Compare commits

...

110 Commits

Author SHA1 Message Date
Andrew Johnson
20d2cff501 Update version number to 3.14.12.8-rc1 2018-07-19 12:31:52 -05:00
Andrew Johnson
860ce156a2 Documentation updates for 3.14.12.8 2018-07-19 12:20:41 -05:00
Andrew Johnson
31fc35fbe8 dbCa: Fix for lp: #541221
I'd looked at this a few times since it was reported, but never
actually fixed the bug I described in the comments. Apparently
the only thing left to do was to store the eventId and use it to
clear the subscription when we saw a type-change to a PV.
2018-07-13 13:05:54 -05:00
Ralph Lange
e459e8bdd4 cas: don't spin on zero-length search requests
(fix lp:1743321)
2018-06-07 11:32:16 +02:00
Ralph Lange
b558bd9b16 Cherry-picking e794639e from 3.15
(lp:1730982 lp:1762543)
2018-06-07 11:21:04 +02:00
Michael Davidsaver
3c16c3c0da Cherry-picking d2b0e920 from 3.15
(closes lp:1773373)
2018-06-07 11:07:29 +02:00
Andrew Johnson
67844bacc3 Perl s/use vars/our/ 2018-05-28 16:13:14 -05:00
Ralph Lange
7e7d230d8c templates: fix warnings for xxxRecord.c in exampleApp
(fixes #1772833)
2018-05-23 09:24:56 +02:00
Andrew Johnson
c1ece40f41 Updated Release Notes for Base-3.14.12.8 2018-05-19 22:42:23 -05:00
Andrew Johnson
a732539eee epicsMath.h defines 'finite()' not 'isfinite()' 2018-05-19 21:14:36 -05:00
Ralph Lange
3bc0805a89 rec: fix missing includes in longin/longout 2018-05-18 09:54:42 +02:00
Ralph Lange
c72e35c769 Merge Ralph's fix-1770292 branch into 3.14 2018-05-17 17:16:07 +02:00
Ralph Lange
2d9c5e99a1 db: correctly convert NaN alarm levels to integers
(fixes lp #1771298)
2018-05-15 11:18:11 +02:00
Ralph Lange
ca22d50831 rec: consistent get_alarm_double() for longin/longout
(fixes lp #1770292)
2018-05-15 11:18:10 +02:00
Andrew Johnson
5cb91d9f6d Merge Ben Franksen's deadlock_warning branch into 3.14 2018-05-12 20:20:30 -05:00
Andrew Johnson
116c90c2ea Reformatting, no code changes 2018-05-03 14:40:12 -05:00
Andrew Johnson
3f3696fb91 dbStatic: Prevent modifying a NAME field using a DB file
Fixes LP: #1597809
2018-05-03 14:28:44 -05:00
Benjamin Franksen
91ce807e8b Fix for lp: #1751380
Add warnings about possible deadlock to the docs for ca_clear_channel,
ca_clear_subscription, and ca_context_destroy.
2018-04-11 12:58:28 +02:00
Andrew Johnson
b9443f8813 Tell MSVC to use absolute filenames in diagnostics (-FC flag) 2018-03-23 11:39:53 -05:00
Andrew Johnson
b7d4609e57 Merge Bruce Hill's camonitor-server-relative-ts-bug-3.14 branch 2018-03-15 17:33:32 -05:00
Andrew Johnson
c8a7e1597d VxWorks Timezone updates
Remove 2017; fix hour in MET settings
2018-03-15 10:57:55 -05:00
Andrew Johnson
ceaff61c09 Pull in the podToHtml.pl script and rules from 3.15
This lets src/cap5 build with Perl installations that lack Perl's
podchecker and pod2html scripts (e.g. Fedora 27).
2018-03-14 14:12:12 -05:00
Bruce Hill
6cc623a7b4 Fixed camonitor server side relative timestamps bug
tsFirst needs to get initialized from the first server side
timestamp instead of the client side tsNow.
2018-03-08 01:40:11 -08:00
Andrew Johnson
ac4d5c95ac Clean up some compiler warnings from clang 2018-02-09 10:56:52 -06:00
Andrew Johnson
de442e9584 Fix for LP: #1743076
Never zero the CA client context private ID.
2018-02-05 12:02:13 -06:00
Andrew Johnson
713c2d5080 Fix for lp: #1747091
generalTimeGetEvent()
2018-02-02 17:47:35 -06:00
Michael Davidsaver
734d16291f rsrv: buffer for IP too small
An IPv4 address and port number
has 21 characters max.
2018-02-01 09:42:51 -08:00
Andrew Johnson
1454f42a27 Config fix for parallel builds with MSVC 2015 and later
From Mark Rivers and Freddie Akeroyd.
2018-02-01 11:19:08 -06:00
Andrew Johnson
c830a3a4ee Updated links to new EPICS website at Argonne
Only done for documents that are still present in EPICS 7.
2018-01-18 23:35:09 -06:00
Ralph Lange
8a1477ecab appveyor-ci: update APS download URL 2018-01-04 09:00:18 +01:00
Ralph Lange
006ce1a240 appveyor-ci: remove VS 2008, add VS 2017 2017-12-19 09:39:57 +01:00
Ralph Lange
276dee2c3e appveyor-ci: use curl for download of make.zip 2017-12-19 09:39:10 +01:00
Andrew Johnson
98a2871727 Reset SNAPSHOT to -DEV after tagging 3.14.12.7 2017-12-15 16:09:21 -06:00
Andrew Johnson
5ca1bb3bd5 Set SNAPSHOT for 3.14.12.7 final release 2017-12-15 16:06:08 -06:00
Andrew Johnson
f6be3c7f70 Set snapshot to -rc1-DEV 2017-12-08 16:40:08 -06:00
Andrew Johnson
00924dcba0 About to tag 3.14.12.7-rc1 2017-12-08 16:37:03 -06:00
Andrew Johnson
5278799575 aSubRecord: Copy the right amount of data
Initialize OVLx from VALx with NEVx elements, size from FTVx
2017-11-15 20:59:06 -06:00
Michael Davidsaver
2af98c33c9 std/rec: aSub handle INAM changing outputs
Allow EFLG="On Change" to work with INAM.
2017-11-08 14:29:30 -06:00
Andrew Johnson
22debb3532 Fix for LP: #1702298 2017-09-25 15:41:31 -05:00
Andrew Johnson
c441cdd5a4 Adjust comments about EPICS_TIMEZONE 2017-09-25 12:14:48 -05:00
Andrew Johnson
13fa1e2722 Travis: Use 'make test-results' for more compact output 2017-09-07 17:39:42 -05:00
Andrew Johnson
fad89189da Fix typo in CAref.html 2017-09-07 17:38:58 -05:00
Andrew Johnson
4ab56518a0 Add readline support to linux-xscale_be rules
Also moves cross-build config to the right host-arch's
2017-08-18 15:14:42 -05:00
Andrew Johnson
80dbc7aeef Clean up the cross-build rules slightly 2017-08-18 15:10:13 -05:00
Andrew Johnson
238f6772bd Dirk's simpler VxWorks version rules 2017-08-18 15:06:38 -05:00
Andrew Johnson
dc9859cee9 Fix RPATH and readline for linux-arm cross-builds 2017-08-18 11:59:17 -05:00
Andrew Johnson
5d5f27a486 Don't set RPATH if STATIC_BUILD=YES 2017-08-18 11:57:50 -05:00
Andrew Johnson
ad6a16d7c4 Update EPICS_TIMEZONE settings, extend to 2022 2017-08-18 11:33:17 -05:00
Michael Davidsaver
5c8e5c52ef rsrv: fix recv() error handling on WIN32
For WIN32 osiSockIoctl_t is unsigned, so

> osiSockIoctl_t nchars = recv(...

is casting signed -> unsigned which treats
errors as success.
2017-08-01 17:02:41 +02:00
Michael Davidsaver
546df1c1f0 rsrv: export CASDEBUG to iocsh 2017-08-01 17:02:41 +02:00
Michael Davidsaver
603331e7a5 rsrv: flush any queued messages before forced disconnect
Avoid loss of various ERROR messages which camessage()
has queued.
2017-08-01 16:44:48 +02:00
Michael Davidsaver
4b272cc0cf rsrv: locking in cas_send_bs_msg()
Must lock around "pclient->send.stk = 0u;"
2017-08-01 16:44:48 +02:00
Michael Davidsaver
619a99bf99 rsrv: missing send lock around send_err() 2017-08-01 16:44:48 +02:00
Michael Davidsaver
1f8cb740f1 rsrv: drop un-commited VERSION message
This is a no-op as cas_commit_msg() isn't called.
A VERSION message is already queued during create_tcp_client().
2017-08-01 16:44:29 +02:00
Michael Davidsaver
322f7a97de rsrv: add some comments 2017-08-01 16:44:29 +02:00
Michael Davidsaver
0fc770166c rsrv: avoid possible overflow in vsend_err()
Accounting of message size doesn't take into account
space used by header of failed message (16 or 24 bytes).
This would allow a theoretical really long error message
to overflow the send buffer by 16 or 24 bytes.
2017-08-01 16:44:08 +02:00
Andrew Johnson
1a70855e25 Use static strings for epicsInterruptContextMessage()
The callbackRequest() routine was passing a stack-allocated
string to epicsInterruptContextMessage() but on RTEMS the
pointer is queued without copying the string. This fix uses
static strings for the 3 messages instead.

Fixes LP: #1705219
2017-07-24 11:19:20 -05:00
Andrew Johnson
6b5e7da4fd catools: dbr_long_t is only 32 bits wide
Don't print it as a native long.
Fixes LP: #1699332
2017-06-20 15:49:41 -05:00
Andrew Johnson
a1dc16848c configure: Fix include CONFIG_APP_INCLUDE
which needs to happen *after* CONFIG_SITE overrides.
2017-06-14 10:03:43 -05:00
Andrew Johnson
2819d7ea3d Posix epicsEventWaitWithTimeout() max delay
Limit timeouts on Posix to max-out at 10 years.
Adds a test that will fail when that time-out hits Y2038 on
systems where time_t is still a 32-bit integer.
2017-06-14 10:01:23 -05:00
Andrew Johnson
6ef995525a Restore the use of DBL_MAX in timerQueue.cpp 2017-06-09 13:44:30 -05:00
Andrew Johnson
18dee384ec Fix tv_sec casts to use time_t, not long 2017-06-09 12:20:16 -05:00
Andrew Johnson
b369aa67f1 Use 1000 years as 'forever' in timers
DBL_MAX causes problems...
2017-06-08 21:55:12 -05:00
Andrew Johnson
c853234e01 Remove artificial 60-minute timeout limit (Posix) 2017-06-08 09:53:07 -04:00
Andrew Johnson
9c859ffdca Protect casStatsFetch() if called before rsrv_init()
Also ensures clientQ is initialized before creating clientQlock.

Fixes LP: #1694966
2017-06-01 15:37:34 -05:00
Andrew Johnson
0dc850f4ec A gitignore pattern for vi on MacOS 2017-05-30 17:13:56 -05:00
Andrew Johnson
672fd16ec8 Add make targets test-results and clean-tests
These are mainly intended for CI builds.
2017-05-19 15:44:15 -05:00
Ralph Lange
dcadeac903 ci: add appveyor configuration 2017-05-19 13:38:39 +09:00
Andrew Johnson
b7b3dd2b37 Support for 'make junitfiles' target.
The Perl XML::Generator module must be installed to use this.
2017-05-18 16:31:43 -05:00
Xiaoqiang Wang
82396ee3ef fix data size of gdd container type
getDataSizeElement of gdd container returns the number of sub fields.
It has to be called on the "value" field. This fix has already been done
in monitorReponse.
2017-05-10 10:22:13 -05:00
Michael Davidsaver
e430d097b7 ioc/rsrv: bounds check DBR
avoid array overrun when evaluating dbr_size_n() macro.
2017-05-03 16:49:28 -04:00
Michael Davidsaver
38be82a154 missing include 2017-05-02 18:22:57 -04:00
Michael Davidsaver
27cd9fd051 ioc/dbStatic: dbFreeBase() don't double free alias'd records
dbFreeBase() has been broken since alias() was introduced.

Traversal of recList in the function assumed that dbDeleteRecord()
remove only the current dbRecordNode.  However, dbDeleteRecord()
called dbDeleteAliases() which removes alias dbRecordNode s.
If this happens (as it often does) to be the node immediately
after the real node, dbFreeBase() will then iterate using
a ellDelete()d node.
2017-05-02 18:04:06 -04:00
Michael Davidsaver
1ffce72a38 ioc/dbStatic: plug leak in dbFreeBase() 2017-05-02 18:02:05 -04:00
Michael Davidsaver
dcac64d50f ioc/dbStatic: whitespace 2017-05-02 18:01:39 -04:00
Andrew Johnson
0bf789db4c Fix indentation warning from GCC 2017-04-28 14:56:18 -05:00
Michael Davidsaver
57cbe61709 libCom/test: errlog test more verbose 2017-04-27 16:53:40 -04:00
Michael Davidsaver
a2ab17a782 libCom: STATIC_ASSERT use c++11 static_assert when possible 2017-04-27 16:52:33 -04:00
Andrew Johnson
d825f87359 Check for empty PV names in Perl catools 2017-04-27 12:10:27 -05:00
Michael Davidsaver
3184371e8d travisci 2017-04-27 12:53:35 -04:00
Andrew Johnson
f2e54be965 catools: Fix SEGFAULT from bad PV names 2017-04-27 10:52:07 -05:00
Jeong Han Lee
c22670cbb0 typo 2017-04-24 21:06:30 -04:00
Andrew Johnson
c5decfbd12 Fix for dbCa warning seg-fault
Don't queue an errlog message containing a pointer to a string
that will disappear soon.

Thanks to Matt Pearson for the bug analysis.
2017-04-24 18:03:53 -05:00
Andrew Johnson
e25a2964bc Fix postfix.h macro arg, document 2017-04-21 16:09:36 -05:00
Michael Davidsaver
8382367495 libCom/test: epicsCalcTest use exact postifx buffers
exposes INFIX_TO_POSTFIX_SIZE() bug
2017-04-21 16:13:18 -04:00
Andrew Johnson
64c16c0f6e Cleanup in asLib
Improve error messages.
Remove unnecessary pointer casts.
2017-04-20 16:27:20 -05:00
Andrew Johnson
9f01c47542 Allow whitespace before comments in AS config files
Fixes lp: #1677302
Makes the lexer patterns more like dbStatic.
Handle non-printable invalid characters in input properly.
2017-04-20 16:23:36 -05:00
Andrew Johnson
aca7b44a05 Supress MS warning C4251 2017-04-20 11:42:52 -05:00
Andrew Johnson
4f8fd545fa Merge branch 'fix-async-dns/master' into 3.14 2017-04-17 15:52:10 -05:00
Andrew Johnson
d4552af39b Fix and test for macLib losing error status
Problem found & diagnosed by Mark Rivers.
2017-04-17 11:47:21 -05:00
Michael Davidsaver
0c02c5cb30 update notes 2017-04-15 19:38:56 -04:00
Michael Davidsaver
1f90e98491 libCom/test: ipAddrToAsciiTest skip cleanup unless valgrind is possible 2017-04-15 19:34:04 -04:00
Michael Davidsaver
352fd32c45 libCom/test: add ipAddrToAsciiTest to testHarness 2017-04-12 20:30:23 -04:00
Andrew Johnson
e0af3e2af5 Adjusted .gitignore patterns 2017-03-31 12:08:03 -05:00
Ralph Lange
5726ca6964 libCom/test: add network libraries for Windows builds 2017-03-31 15:01:51 +02:00
Ralph Lange
f164b14ba1 Moved .bzrignore to .gitignore 2017-03-30 15:43:15 -05:00
Andrew Johnson
214e9534cc Allow 'make -q' to work with CHECK_RELEASE=NO 2017-03-03 18:18:57 -06:00
Michael Davidsaver
2a0cd00958 libca: lock when removing from msgMultiPVList 2017-02-27 14:48:30 -05:00
Michael Davidsaver
d744b06a28 libca: findOrCreateVirtCircuit() can return w/ piiu==NULL 2017-02-27 11:07:17 -05:00
Michael Davidsaver
048b75304d libCom/test: add ipAddrToAsciiTest 2017-02-25 19:08:46 -05:00
Ben Franksen
aaafb1a5de db: call rset::get_precision with wrong type 2017-02-25 16:42:29 -05:00
Michael Davidsaver
5783823e25 libCom: revise ipAddrToAscii
create multiple light-weight engines to
track transactions by engine and cancel
all transactions when an engine is released.

prior to fix for lp:1527636 this was ensured
for the last/only owner for the engine singleton.
2017-02-23 20:08:46 -05:00
Andrew Johnson
faf691a5be VS2015 starting to dislike '/' for compiler flags 2017-01-30 12:11:29 -06:00
Andrew Johnson
3a0e52fc3f Fix Windows dllPath.bat properly 2017-01-24 14:17:37 -06:00
Andrew Johnson
a105c6f538 Always quote Windows PATH arg's 2017-01-24 11:48:36 -06:00
Andrew Johnson
3e58c59377 Fix CA server bind issue from Freddie Akeroyd 2017-01-19 12:33:54 -06:00
Andrew Johnson
b9ae6c3308 Allow ARCH with trailing spaces 2017-01-18 10:59:36 -06:00
Andrew Johnson
7310d78057 Prepend to PATH, not append 2017-01-16 10:46:56 -06:00
Andrew Johnson
49e0e23f76 Better protection against bad periodic scan rates 2017-01-06 15:38:03 -06:00
Andrew Johnson
20dda339cc Make *_INC files order-only prerequisites 2017-01-04 16:32:13 -06:00
112 changed files with 2832 additions and 1060 deletions

View File

@@ -1,9 +0,0 @@
./bin
./lib
./db
./dbd
./html
./include
./templates
**/O.*
./QtC-*

13
.gitignore vendored Normal file
View File

@@ -0,0 +1,13 @@
/cfg/
/bin/
/lib/
/db/
/dbd/
/html/
/include/
/templates/
O.*/
/QtC-*
*.orig
*.log
.*.swp

31
.travis.yml Normal file
View File

@@ -0,0 +1,31 @@
sudo: false
dist: trusty
language: c
compiler:
- gcc
env:
- CMPLR=gcc
- CMPLR=gcc EXTRA=CMD_CXXFLAGS=-std=c++11
- CMPLR=gcc STATIC=YES
- CMPLR=clang
- CMPLR=clang STATIC=YES
- WINE=32 TEST=NO STATIC=YES
- RTEMS=4.10 TEST=NO
- RTEMS=4.9 TEST=NO
addons:
apt:
packages:
- libreadline6-dev
- libncurses5-dev
- perl
- clang
- g++-mingw-w64-i686
- bison
- flex
- texinfo
- install-info
cache:
directories:
- $HOME/.cache
install: sh ci/travis-prepare.sh </dev/null
script: sh ci/travis-build.sh </dev/null

2
README
View File

@@ -20,5 +20,5 @@ Additional information about EPICS including mailing list
archives and subscription instructions, documentation and
training materials, additional components, links to other
websites etc. is available on the EPICS home page at
http://www.aps.anl.gov/epics/
https://epics.anl.gov/

85
appveyor.yml Normal file
View File

@@ -0,0 +1,85 @@
# AppVeyor configuration for EPICS Base
# Ralph Lange <ralph.lange@gmx.de>
# Copyright (c) 2016-2017 ITER Organization
# Version format
version: base-{branch}-{build}
#---------------------------------#
# repository cloning #
#---------------------------------#
# Called at very beginning, before repo cloning
init:
# Set autocrlf to make batch files work
- git config --global core.autocrlf true
# Set clone depth (do not fetch complete history)
clone_depth: 2
# Skipping commits affecting only specific files
skip_commits:
files:
- 'documentation/*'
- 'templates/*'
- '**/*.html'
- '**/*.md'
#---------------------------------#
# build matrix configuration #
#---------------------------------#
# Build Configurations: dll/static, regular/debug
configuration:
- dynamic
- static
- dynamic-debug
- static-debug
# Environment variables: compiler toolchain
environment:
matrix:
- TOOLCHAIN: 10.0
- TOOLCHAIN: 11.0
- TOOLCHAIN: 12.0
- TOOLCHAIN: 14.0
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
TOOLCHAIN: 2017
- TOOLCHAIN: cygwin
- TOOLCHAIN: mingw
# Platform: architecture
platform:
- x86
- x64
# Matrix configuration: allow specific failing jobs
matrix:
exclude:
# VS Express installs don't have the 64 bit compiler
- platform: x64
TOOLCHAIN: 10.0
#---------------------------------#
# building & testing #
#---------------------------------#
install:
- cmd: ci/appveyor-prepare.bat
build_script:
- cmd: ci/appveyor-make.bat
test_script:
- cmd: ci/appveyor-make.bat runtests
#---------------------------------#
# notifications #
#---------------------------------#
notifications:
- provider: Slack
incoming_webhook:
secure: RYOm3FIUYeZGjWKaeTVKwq+C3fzK54AKwbmAoECED45mex3lN+8HmrC845a6mg9xPUJ/ND51RopWVaKDD9/UzaM0SO195RQLKqUTIUafiuM=

137
ci/appveyor-make.bat Normal file
View File

@@ -0,0 +1,137 @@
:: Universal build script for AppVeyor (https://ci.appveyor.com/)
:: Environment:
:: TOOLCHAIN - toolchain version [10.0/11.0/12.0/14.0/2017/cygwin/mingw]
:: CONFIGURATION - determines EPICS build [dynamic/static]
:: PLATFORM - architecture [x86/x64]
::
:: All command line args are passed to make
Setlocal EnableDelayedExpansion
set "ST="
if /i "%CONFIGURATION%"=="static" set ST=-static
set OS=64BIT
if "%PLATFORM%"=="x86" set OS=32BIT
echo [INFO] Platform: %OS%
:: Use parallel make, except for 3.14
set "MAKEARGS=-j2 -Otarget"
if "%APPVEYOR_REPO_BRANCH%"=="3.14" set MAKEARGS=
if "%TOOLCHAIN%"=="cygwin" (
set "MAKE=make"
if "%OS%"=="64BIT" (
set "EPICS_HOST_ARCH=cygwin-x86_64"
set "INCLUDE=C:\cygwin64\include;%INCLUDE%"
set "PATH=C:\cygwin64\bin;%PATH%"
echo [INFO] Cygwin Toolchain 64bit
) else (
set "EPICS_HOST_ARCH=cygwin-x86"
set "INCLUDE=C:\cygwin\include;%INCLUDE%"
set "PATH=C:\cygwin\bin;%PATH%"
echo [INFO] Cygwin Toolchain 32bit
)
echo [INFO] Compiler Version
gcc -v
goto Finish
)
if "%TOOLCHAIN%"=="mingw" (
set "MAKE=mingw32-make"
if "%OS%"=="64BIT" (
set "EPICS_HOST_ARCH=windows-x64-mingw"
set "INCLUDE=C:\tools\mingw64\include;%INCLUDE%"
set "PATH=C:\tools\mingw64\bin;%PATH%"
echo [INFO] MinGW Toolchain 64bit
) else (
set "EPICS_HOST_ARCH=win32-x86-mingw"
set "INCLUDE=C:\tools\mingw32\include;%INCLUDE%"
set "PATH=C:\tools\mingw32\bin;%PATH%"
echo [INFO] MinGW Toolchain 32bit
)
echo [INFO] Compiler Version
gcc -v
goto Finish
)
set "VSINSTALL=C:\Program Files (x86)\Microsoft Visual Studio %TOOLCHAIN%"
if not exist "%VSINSTALL%\" set "VSINSTALL=C:\Program Files (x86)\Microsoft Visual Studio\%TOOLCHAIN%\Community"
if not exist "%VSINSTALL%\" goto MSMissing
set "MAKE=C:\tools\make"
echo [INFO] APPVEYOR_BUILD_WORKER_IMAGE=%APPVEYOR_BUILD_WORKER_IMAGE%
if "%OS%"=="64BIT" (
set EPICS_HOST_ARCH=windows-x64%ST%
:: VS 2017
if exist "%VSINSTALL%\VC\Auxiliary\Build\vcvars64.bat" (
call "%VSINSTALL%\VC\Auxiliary\Build\vcvars64.bat"
where cl
if !ERRORLEVEL! NEQ 0 goto MSMissing
goto MSFound
)
if exist "%VSINSTALL%\VC\vcvarsall.bat" (
call "%VSINSTALL%\VC\vcvarsall.bat" amd64
where cl
if !ERRORLEVEL! NEQ 0 (
call "%VSINSTALL%\VC\vcvarsall.bat" x86_amd64
where cl
if !ERRORLEVEL! NEQ 0 goto MSMissing
)
goto MSFound
)
if exist "%VSINSTALL%\VC\bin\amd64\vcvars64.bat" (
call "%VSINSTALL%\VC\bin\amd64\vcvars64.bat"
where cl
if !ERRORLEVEL! NEQ 0 goto MSMissing
goto MSFound
)
) else (
set EPICS_HOST_ARCH=win32-x86%ST%
:: VS 2017
if exist "%VSINSTALL%\VC\Auxiliary\Build\vcvars32.bat" (
call "%VSINSTALL%\VC\Auxiliary\Build\vcvars32.bat"
where cl
if !ERRORLEVEL! NEQ 0 goto MSMissing
goto MSFound
)
if exist "%VSINSTALL%\VC\vcvarsall.bat" (
call "%VSINSTALL%\VC\vcvarsall.bat" x86
where cl
if !ERRORLEVEL! NEQ 0 goto MSMissing
goto MSFound
)
if exist "%VSINSTALL%\VC\bin\vcvars32.bat" (
call "%VSINSTALL%\VC\bin\vcvars32.bat"
where cl
if !ERRORLEVEL! NEQ 0 goto MSMissing
goto MSFound
)
if exist "%VSINSTALL%\Common7\Tools\vsvars32.bat" (
call "%VSINSTALL%\Common7\Tools\vsvars32.bat"
where cl
if !ERRORLEVEL! NEQ 0 goto MSMissing
goto MSFound
)
)
:MSMissing
echo [INFO] Installation for MSVC Toolchain %TOOLCHAIN% / %OS% seems to be missing
exit 1
:MSFound
echo [INFO] Microsoft Visual Studio Toolchain %TOOLCHAIN%
echo [INFO] Compiler Version
cl
:Finish
echo [INFO] EPICS_HOST_ARCH: %EPICS_HOST_ARCH%
echo [INFO] Make version
%MAKE% --version
echo [INFO] Perl version
perl --version
%MAKE% %MAKEARGS% %*

70
ci/appveyor-prepare.bat Normal file
View File

@@ -0,0 +1,70 @@
:: Build script for AppVeyor (https://ci.appveyor.com/)
:: Environment:
:: TOOLCHAIN - Toolchain Version [9.0/10.0/11.0/12.0/14.0/cygwin/mingw]
:: CONFIGURATION - determines EPICS build [dynamic/static, -debug]
:: PLATFORM - "x86" -> use 32bit architecture
::
:: Prepares an Appveyor build by excuting the following steps
:: - Set up configure\CONFIG_SITE for static vs. dynamic build
:: - Install Cygwin / Mingw (TOOLCHAIN setting) in the in the appropriate flavor
:: - Download and install Make-4.1 from EPICS download page
Setlocal EnableDelayedExpansion
set OS=64BIT
if "%PLATFORM%"=="x86" set OS=32BIT
echo [INFO] Platform: %OS%
if "%TOOLCHAIN%"=="cygwin" (
echo.%CONFIGURATION% | findstr /C:"static">nul && (
echo SHARED_LIBRARIES=NO>> configure\CONFIG_SITE
echo STATIC_BUILD=YES>> configure\CONFIG_SITE
echo [INFO] EPICS set up for static build
) || (
echo [INFO] EPICS set up for dynamic build
)
echo.%CONFIGURATION% | findstr /C:"debug">nul && (
echo HOST_OPT=NO>> configure\CONFIG_SITE
echo [INFO] EPICS set up for debug build
) || (
echo [INFO] EPICS set up for optimized build
)
if "%OS%"=="64BIT" (
echo [INFO] Installing Cygwin 64bit and dependencies
@powershell -Command "(new-object net.webclient).DownloadFile('http://www.cygwin.com/setup-x86_64.exe', 'C:\cygwin64\setup-x86_64.exe')"
C:\cygwin64\setup-x86_64.exe -q -P "libreadline-devel,libncursesw-devel"
) else (
echo [INFO] Installing Cygwin 32bit and dependencies
@powershell -Command "(new-object net.webclient).DownloadFile('http://www.cygwin.com/setup-x86.exe', 'C:\cygwin\setup-x86.exe')"
C:\cygwin\setup-x86.exe -q -P "libreadline-devel,libncursesw-devel"
)
)
if "%TOOLCHAIN%"=="mingw" (
echo.%CONFIGURATION% | findstr /C:"static">nul && (
echo SHARED_LIBRARIES=NO>> configure\CONFIG_SITE
echo STATIC_BUILD=YES>> configure\CONFIG_SITE
echo [INFO] EPICS set up for static build
) || (
echo [INFO] EPICS set up for dynamic build
)
echo.%CONFIGURATION% | findstr /C:"debug">nul && (
echo HOST_OPT=NO>> configure\CONFIG_SITE
echo [INFO] EPICS set up for debug build
) || (
echo [INFO] EPICS set up for optimized build
)
if "%OS%"=="64BIT" (
echo [INFO] Installing MinGW 64bit
cinst mingw || cinst mingw
) else (
echo [INFO] Installing MinGW 32bit
cinst mingw --x86 || cinst mingw --x86
)
)
echo [INFO] Installing Make 4.1
curl -fsS --retry 3 -o C:\tools\make-4.1.zip https://epics.anl.gov/download/tools/make-4.1-win64.zip
cd \tools
"C:\Program Files\7-Zip\7z" e make-4.1.zip

90
ci/travis-build.sh Normal file
View File

@@ -0,0 +1,90 @@
#!/bin/sh
set -e -x
die() {
echo "$1" >&2
exit 1
}
ticker() {
while true
do
sleep 60
date -R
[ -r "$1" ] && tail -n10 "$1"
done
}
CACHEKEY=1
EPICS_HOST_ARCH=`sh startup/EpicsHostArch`
[ -e configure/os/CONFIG_SITE.Common.linux-x86 ] || die "Wrong location: $PWD"
case "$CMPLR" in
clang)
echo "Host compiler is clang"
cat << EOF >> configure/os/CONFIG_SITE.Common.$EPICS_HOST_ARCH
GNU = NO
CMPLR_CLASS = clang
CC = clang
CCC = clang++
EOF
;;
*) echo "Host compiler is default";;
esac
if [ "$STATIC" = "YES" ]
then
echo "Build static libraries/executables"
cat << EOF >> configure/CONFIG_SITE
SHARED_LIBRARIES=NO
STATIC_BUILD=YES
EOF
fi
# requires wine and g++-mingw-w64-i686
if [ "$WINE" = "32" ]
then
echo "Cross mingw32"
sed -i -e '/CMPLR_PREFIX/d' configure/os/CONFIG_SITE.linux-x86.win32-x86-mingw
cat << EOF >> configure/os/CONFIG_SITE.linux-x86.win32-x86-mingw
CMPLR_PREFIX=i686-w64-mingw32-
EOF
cat << EOF >> configure/CONFIG_SITE
CROSS_COMPILER_TARGET_ARCHS+=win32-x86-mingw
EOF
fi
# set RTEMS to eg. "4.9" or "4.10"
# requires qemu, bison, flex, texinfo, install-info
if [ -n "$RTEMS" ]
then
echo "Cross RTEMS${RTEMS} for pc386"
install -d /home/travis/.cache
curl -L "https://github.com/mdavidsaver/rsb/releases/download/travis-20160306-2/rtems${RTEMS}-i386-trusty-20190306-2.tar.gz" \
| tar -C /home/travis/.cache -xj
sed -i -e '/^RTEMS_VERSION/d' -e '/^RTEMS_BASE/d' configure/os/CONFIG_SITE.Common.RTEMS
cat << EOF >> configure/os/CONFIG_SITE.Common.RTEMS
RTEMS_VERSION=$RTEMS
RTEMS_BASE=/home/travis/.cache/rtems${RTEMS}-i386
EOF
cat << EOF >> configure/CONFIG_SITE
CROSS_COMPILER_TARGET_ARCHS+=RTEMS-pc386
EOF
# find local qemu-system-i386
export PATH="$HOME/.cache/qemu/usr/bin:$PATH"
echo -n "Using QEMU: "
type qemu-system-i386 || echo "Missing qemu"
EXTRA=RTEMS_QEMU_FIXUPS=YES
fi
make -j2 $EXTRA
if [ "$TEST" != "NO" ]
then
make tapfiles
make -s test-results
fi

40
ci/travis-prepare.sh Normal file
View File

@@ -0,0 +1,40 @@
#!/bin/sh
set -e -x
die() {
echo "$1" >&2
exit 1
}
CURDIR="$PWD"
QDIR="$HOME/.cache/qemu"
if [ -n "$RTEMS" -a "$TEST" = "YES" ]
then
git clone --quiet --branch vme --depth 10 https://github.com/mdavidsaver/qemu.git "$HOME/.build/qemu"
cd "$HOME/.build/qemu"
HEAD=`git log -n1 --pretty=format:%H`
echo "HEAD revision $HEAD"
[ -e "$HOME/.cache/qemu/built" ] && BUILT=`cat "$HOME/.cache/qemu/built"`
echo "Cached revision $BUILT"
if [ "$HEAD" != "$BUILT" ]
then
echo "Building QEMU"
git submodule --quiet update --init
install -d "$HOME/.build/qemu/build"
cd "$HOME/.build/qemu/build"
"$HOME/.build/qemu/configure" --prefix="$HOME/.cache/qemu/usr" --target-list=i386-softmmu --disable-werror
make -j2
make install
echo "$HEAD" > "$HOME/.cache/qemu/built"
fi
fi
cd "$CURDIR"

View File

@@ -75,17 +75,17 @@ ifdef T_A
#
-include $(CONFIG)/os/CONFIG.$(EPICS_HOST_ARCH).$(T_A)
# Site specific target and host-target definitions and overrides
#
-include $(CONFIG)/os/CONFIG_SITE.Common.$(T_A)
-include $(CONFIG)/os/CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A)
# RELEASE file specific definitions
#
ifneq ($(CONFIG),$(TOP)/configure)
-include $(CONFIG)/CONFIG_APP_INCLUDE
endif
# Site specific target and host-target definitions
#
-include $(CONFIG)/os/CONFIG_SITE.Common.$(T_A)
-include $(CONFIG)/os/CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A)
endif # ifdef T_A

View File

@@ -17,14 +17,14 @@ BUILD_CLASS = CROSS
# ifdef CROSS looks better than ifeq ($(BUILD_CLASS),CROSS)
CROSS = YES
GNU_TARGET_INCLUDE_DIR = $(GNU_TARGET:%= $(GNU_DIR)/%/include)
GNU_TARGET_LIB_DIR = $(GNU_TARGET:%= $(GNU_DIR)/%/lib)
GNU_TARGET_INCLUDE_DIR = $(wildcard $(GNU_TARGET:%=$(GNU_DIR)/%/include))
GNU_TARGET_LIB_DIR = $(wildcard $(GNU_TARGET:%=$(GNU_DIR)/%/lib))
CROSS_INCLUDES = $(addprefix -I,$(GNU_TARGET_INCLUDE_DIR))
CROSS_LDFLAGS = $(addprefix -L,$(GNU_TARGET_LIB_DIR))
CROSS_INCLUDES = $(GNU_TARGET_INCLUDE_DIR:%=-I%)
CROSS_LDFLAGS = $(GNU_TARGET_LIB_DIR:%=-L%)
CMPLR_PREFIX_CROSS=$(addsuffix -,$(GNU_TARGET))
CMPLR_PREFIX=$(CMPLR_PREFIX_$(BUILD_CLASS))
CMPLR_PREFIX_CROSS = $(addsuffix -,$(GNU_TARGET))
CMPLR_PREFIX = $(CMPLR_PREFIX_$(BUILD_CLASS))
# Cross builds usually use the gnu compiler
include $(CONFIG)/CONFIG.gnuCommon

View File

@@ -66,6 +66,7 @@ DBTOMENUH = $(call PATH_FILTER, $(TOOLS)/dbToMenuH$(HOSTEXE))
REGISTERRECORDDEVICEDRIVER = $(PERL) $(TOOLS)/registerRecordDeviceDriver.pl
CONVERTRELEASE = $(PERL) $(call FIND_TOOL,convertRelease.pl)
FULLPATHNAME = $(PERL) $(TOOLS)/fullPathName.pl
TAPTOJUNIT = $(PERL) $(TOOLS)/tap-to-junit-xml.pl
#-------------------------------------------------------
# tools for installing libraries and products

View File

@@ -28,15 +28,10 @@ EPICS_MODIFICATION = 12
# EPICS_PATCH_LEVEL must be a number (win32 resource file requirement)
# Not included if zero
EPICS_PATCH_LEVEL = 6
EPICS_PATCH_LEVEL = 8
# This will end in -DEV between official releases
EPICS_DEV_SNAPSHOT=-DEV
#EPICS_DEV_SNAPSHOT=-pre1
#EPICS_DEV_SNAPSHOT=-pre1-DEV
#EPICS_DEV_SNAPSHOT=-pre2
#EPICS_DEV_SNAPSHOT=-pre2-DEV
#EPICS_DEV_SNAPSHOT=-rc1
EPICS_DEV_SNAPSHOT=-rc1
#EPICS_DEV_SNAPSHOT=-rc1-DEV
#EPICS_DEV_SNAPSHOT=-rc2
#EPICS_DEV_SNAPSHOT=-rc2-DEV

View File

@@ -121,11 +121,10 @@ CROSS_COMPILER_TARGET_ARCHS=
#
CROSS_COMPILER_HOST_ARCHS=
# The 'make runtests' and 'make tapfiles' build targets normally only run
# The 'runtests', 'tapfiles' and 'junitfiles' make targets normally only run
# self-tests for the EPICS_HOST_ARCH architecture. If the host can execute
# the self-test programs for any other cross-built architectures such as
# a -debug architecture, those architectures can be named here.
#
# a -debug architecture, those architectures must be named in this variable:
CROSS_COMPILER_RUNTEST_ARCHS=
# Build shared libraries?

View File

@@ -13,7 +13,7 @@
#
# CONFIG_SITE_ENV - EPICS Environment Parameter Site configuration file
#
# This file is read by the script base/src/libCom/env/bldEnvdata.pl
# This file is read by the script base/src/libCom/env/bldEnvData.pl
# Variable definitions must take the form
# VAR = VALUE
# or
@@ -26,31 +26,42 @@
# Time service:
# EPICS_TIMEZONE
# local timezone info for vxWorks and RTEMS IOCs. The format is
# <name>::<minutesWest>:<start daylight>:<end daylight>
# where the start and end are mmddhh - that is month,day,hour
# e.g. for ANL in 2016: EPICS_TIMEZONE=CUS::360:031302:110602
# Local timezone info for vxWorks and RTEMS. The format is
# <name>::<minutesWest>:<startDST>:<endDST>
# where <name> is only used by strftime() for %Z conversions,
# and <startDST> and <endDST> are mmddhh - that is month,day,hour
# e.g. for ANL in 2018: EPICS_TIMEZONE=CUS::360:031102:110402
# The future dates below assume the rules don't get changed;
# see http://www.timeanddate.com/time/dst/2018.html to check.
#
# DST for 2016 US: Mar 13 - Nov 06
# EU: Mar 27 - Oct 30
# DST for 2017 US: Mar 12 - Nov 05
# EU: Mar 26 - Oct 29
# DST for 2018 US: Mar 11 - Nov 04
# EU: Mar 25 - Oct 28
EPICS_TIMEZONE = CUS::360:031102:110402
#EPICS_TIMEZONE = MET::-60:032502:102803
#
# DST for 2019 US: Mar 10 - Nov 03
# EU: Mar 31 - Oct 27
#EPICS_TIMEZONE = CUS::360:031002:110302
#EPICS_TIMEZONE = MET::-60:033102:102703
#
# DST for 2020 US: Mar 08 - Nov 01
# EU: Mar 29 - Oct 25
#EPICS_TIMEZONE = CUS::360:030802:110102
#EPICS_TIMEZONE = MET::-60:032902:102503
#
# DST for 2021 US: Mar 14 - Nov 07
# EU: Mar 28 - Oct 31
# (see: http://www.timeanddate.com/time/dst/2016.html etc. )
#EPICS_TIMEZONE = CUS::360:031402:110702
#EPICS_TIMEZONE = MET::-60:032802:103103
#
# These values are for 2016:
EPICS_TIMEZONE=CUS::360:031302:110602
#EPICS_TIMEZONE=MET::-60:032702:103002
# DST for 2022 US: Mar 13 - Nov 06
# EU: Mar 27 - Oct 30
#EPICS_TIMEZONE = CUS::360:031302:110602
#EPICS_TIMEZONE = MET::-60:032702:103003
# EPICS_TS_NTP_INET
# NTP time server ip address. Uses boot host if not set.
# NTP time server ip address for VxWorks and RTEMS.
# IOC will use its boot host if this is not set.
EPICS_TS_NTP_INET=
# IOC Shell:

View File

@@ -134,7 +134,7 @@ ACTIONS += build
ACTIONS += install
ACTIONS += buildInstall
ACTIONS += browse
ACTIONS += runtests tapfiles
ACTIONS += runtests tapfiles clean-tests test-results junitfiles
actionArchTargets = $(foreach x, $(ACTIONS),\ $(foreach arch,$(BUILD_ARCHS), $(x)$(DIVIDER)$(arch)))
@@ -150,6 +150,7 @@ buildInstall : build
rebuild: clean install
.PHONY: all inc build install clean rebuild buildInstall
.PHONY: runtests tapfiles clean-tests test-results junitfiles
$(actionArchTargets) $(BUILD_ARCHS):install
$(cleanArchTargets):clean
@@ -300,6 +301,20 @@ $(foreach file, $(DBD_INSTALLS), $(eval $(call DBD_INSTALLS_template, $(file))))
.PRECIOUS: $(COMMON_DBDS) $(COMMON_DIR)/%Include.dbd
##################################################### HTML files
$(COMMON_DIR)/%.html: %.pm $(TOOLS)/podToHtml.pl
@$(RM) $(notdir $@)
$(PERL) $(TOOLS)/podToHtml.pl -o $(notdir $@) $<
@$(MV) $(notdir $@) $@
$(COMMON_DIR)/%.html: ../%.pm $(TOOLS)/podToHtml.pl
@$(RM) $(notdir $@)
$(PERL) $(TOOLS)/podToHtml.pl -o $(notdir $@) $<
@$(MV) $(notdir $@) $@
.PRECIOUS: $(COMMON_DIR)/%.html %.html
##################################################### DB files
$(COMMON_DIR)/%.db$(RAW): $(COMMON_DIR)/%.edf

View File

@@ -14,7 +14,7 @@ build$(DIVIDER)$(ARCH) build: buildInstall
install$(DIVIDER)$(ARCH) install: buildInstall
$(ARCH): buildInstall
ifeq ($(filter $(ARCH),$(BUILD_ARCHS)),$(ARCH))
ifeq ($(filter $(ARCH),$(BUILD_ARCHS)),$(strip $(ARCH)))
buildInstall$(DIVIDER)$(ARCH) buildInstall: $(TARGETS)
clean$(DIVIDER)$(ARCH) clean:
@@ -31,4 +31,3 @@ cdCommands envPaths dllPath.bat relPaths.sh: \
realclean:
$(RM) cdCommands envPaths dllPath.bat relPaths.sh

View File

@@ -14,7 +14,7 @@ ACTIONS += build
ACTIONS += install
ACTIONS += buildInstall
ACTIONS += browse
ACTIONS += runtests tapfiles
ACTIONS += runtests tapfiles clean-tests test-results junitfiles
#ACTIONS += rebuild
actionArchTargets = $(foreach action, $(ACTIONS), \

View File

@@ -4,7 +4,7 @@
# Copyright (c) 2002 The Regents of the University of California, as
# Operator of Los Alamos National Laboratory.
# EPICS BASE is distributed subject to a Software License Agreement found
# in the file LICENSE that is included with this distribution.
# in the file LICENSE that is included with this distribution.
#*************************************************************************
#
# Rules for making things specified in Makefile
@@ -101,10 +101,11 @@ endif
ifneq (,$(findstring $(T_A),$(EPICS_HOST_ARCH) $(CROSS_COMPILER_RUNTEST_ARCHS)))
RUNTESTS_ENABLED = YES
TAPFILES += $(TESTSCRIPTS:.t=.tap)
JUNITFILES += $(TAPFILES:.tap=.xml)
endif
#---------------------------------------------------------------
# Libraries
# Libraries
#
LIBTARGETS += $(LIBNAME) $(INSTALL_LIBS) \
@@ -117,16 +118,16 @@ $(INSTALL_LIBS): $(INSTALL_SHRLIBS) $(INSTALL_DLL_LINK_LIBS) $(INSTALL_LOADABL
# Main targets
install: buildInstall
install: buildInstall
buildInstall : build
buildInstall: build
# Allows rebuild to work with parallel builds option, -j.
install: $(patsubst rebuild,clean,$(filter rebuild,$(MAKECMDGOALS)))
rebuild: clean install
build : inc
build: inc
build: $(OBJSNAME) $(LIBTARGETS) $(PRODTARGETS) $(TESTPRODNAME) \
$(TARGETS) $(TESTSCRIPTS) $(INSTALL_LIB_INSTALLS)
@@ -148,7 +149,7 @@ clean::
$(INC) $(TARGETS) $(DLL_LINK_LIBNAME) $(TDS) \
*.out MakefileInclude $(LOADABLE_SHRLIBNAME) *.manifest *.exp \
$(COMMON_INC) $(HDEPENDS_FILES) $(PRODTARGETS) \
$(TESTSCRIPTS) $(TAPFILES)
$(TESTSCRIPTS) $(TAPFILES) $(JUNITFILES)
ifdef RES
@$(RM) *$(RES)
endif
@@ -176,7 +177,7 @@ warnRelease:
-$(CONVERTRELEASE) checkRelease
noCheckRelease:
ifeq ($(EPICS_HOST_ARCH),$(T_A))
@echo "Warning: RELEASE file consistency checks have been disabled"
$(info Warning: RELEASE file consistency checks have been disabled)
endif
#---------------------------------------------------------------
@@ -207,17 +208,18 @@ $(OBJLIBNAME):%$(OBJ):
%.o : %.cc
%.o : %.cpp
%$(OBJ): %.c $(COMMON_INC) $(INSTALL_INC)
# Include files are order-only prerequisites for compilation:
%$(OBJ): %.c | $(COMMON_INC) $(INSTALL_INC)
@$(HDEPENDS_CMD)
@$(RM) $@
$(COMPILE.c) $(call PATH_FILTER,$<) $(COMPILE_FILTER.c)
%$(OBJ): %.cc $(COMMON_INC) $(INSTALL_INC)
%$(OBJ): %.cc | $(COMMON_INC) $(INSTALL_INC)
@$(HDEPENDS_CMD)
@$(RM) $@
$(COMPILE.cpp) $(call PATH_FILTER,$<) $(COMPILE_FILTER.cpp)
%$(OBJ): %.cpp $(COMMON_INC) $(INSTALL_INC)
%$(OBJ): %.cpp | $(COMMON_INC) $(INSTALL_INC)
@$(HDEPENDS_CMD)
@$(RM) $@
$(COMPILE.cpp) $(call PATH_FILTER,$<) $(COMPILE_FILTER.cpp)
@@ -288,7 +290,7 @@ endif
$(LIBNAME): $(LIBRARY_OBJS)
$(DLL_LINK_LIBNAME): $(LIBRARY_OBJS) $(LIBRARY_RESS) $(SHRLIB_DEPLIBS)
$(DLL_LINK_LIBNAME): $(LIBRARY_OBJS) $(LIBRARY_RESS) $(SHRLIB_DEPLIBS)
$(LIBNAME) $(DLL_LINK_LIBNAME): $(LIB_PREFIX)%$(LIB_SUFFIX):
@$(RM) $@
@@ -352,7 +354,23 @@ testspec: $(TESTSCRIPTS)
$(if $^, @echo Tests: $^ >> $@)
$(if $(TESTSPEC_$(OS_CLASS)), @echo "Harness: $(TESTSPEC_$(OS_CLASS))" >> $@)
test-results: tapfiles
ifneq ($(TAPFILES),)
ifdef RUNTESTS_ENABLED
prove --failures --ext .tap --exec cat --color $(TAPFILES)
endif
endif
clean-tests:
ifneq ($(TAPFILES),)
$(RM) $(TAPFILES)
endif
ifneq ($(JUNITFILES),)
$(RM) $(JUNITFILES)
endif
tapfiles: $(TESTSCRIPTS) $(TAPFILES)
junitfiles: $(JUNITFILES)
# A .tap file is the output from running the associated test script
%.tap: %.t
@@ -360,6 +378,9 @@ ifdef RUNTESTS_ENABLED
-$(PERL) $< -tap > $@
endif
%.xml: %.tap
$(TAPTOJUNIT) --puretap --output $@ --input $< $*
# If there's a perl test script (.plt) available, use it
%.t: ../%.plt
@$(RM) $@
@@ -479,6 +500,10 @@ $(INSTALL_HTML)/$(HTMLS_DIR)/%: ../%
$(ECHO) "Installing html $@"
@$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D)
$(INSTALL_HTML)/$(HTMLS_DIR)/%: $(COMMON_DIR)/%
$(ECHO) "Installing generated html $@"
@$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D)
$(INSTALL_TEMPLATES_SUBDIR)/%: ../%
$(ECHO) "Installing $@"
@$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D)
@@ -493,7 +518,8 @@ $(INSTALL_TEMPLATES_SUBDIR)/%: %
.PRECIOUS: $(COMMON_INC)
.PHONY: all inc build install clean rebuild buildInstall
.PHONY: runtests checkRelease warnRelease noCheckRelease
.PHONY: runtests tapfiles clean-tests test-results junitfiles
.PHONY: checkRelease warnRelease noCheckRelease
endif # BASE_RULES_BUILD
# EOF RULES_BUILD

View File

@@ -9,7 +9,7 @@
ARCHS += $(BUILD_ARCHS)
ACTIONS += inc build install buildInstall clean realclean archclean
ACTIONS += runtests tapfiles
ACTIONS += runtests tapfiles clean-tests test-results junitfiles
dirActionArchTargets = $(foreach dir, $(DIRS), \
$(foreach action, $(ACTIONS), \

View File

@@ -58,6 +58,7 @@ help:
@echo " Cannot be used within an O.<arch> dir"
@echo " rebuild - Same as clean install"
@echo " archclean - Removes O.<arch> dirs but not O.Common dir"
@echo " runtests - Run self-tests, summarize results"
@echo "\"Partial\" build targets supported by Makefiles:"
@echo " inc$(DIVIDER)<arch> - Installs <arch> only header files."
@echo " build$(DIVIDER)<arch> - Builds and installs <arch> only."

View File

@@ -15,5 +15,14 @@ ARCH_CLASS = xscale
ifeq ($(BUILD_CLASS),CROSS)
VALID_BUILDS = Ioc
GNU_TARGET = xscale_be
CMPLR_PREFIX = $(addsuffix -,$(GNU_TARGET))
CMPLR_PREFIX = $(GNU_TARGET:%=%-)
# Configure for readline if requested
OP_SYS_INCLUDES += $(READLINE_DIR:%=-I%/include)
READLINE_LDFLAGS = $(READLINE_DIR:%=-L%/lib)
RUNTIME_LDFLAGS_READLINE_YES_NO = $(READLINE_DIR:%=-Wl,-rpath,%/lib)
RUNTIME_LDFLAGS += \
$(RUNTIME_LDFLAGS_READLINE_$(LINKER_USE_RPATH)_$(STATIC_BUILD))
SHRLIBDIR_LDFLAGS += $(READLINE_LDFLAGS)
PRODDIR_LDFLAGS += $(READLINE_LDFLAGS)
endif

View File

@@ -21,13 +21,15 @@ STATIC_LDFLAGS_YES= -Wl,-Bstatic
STATIC_LDFLAGS_NO=
STATIC_LDLIBS_YES= -Wl,-Bdynamic
# Set runtime path for shared libraries
SHRLIBDIR_RPATH_LDFLAGS_YES += $(SHRLIB_DEPLIB_DIRS:%=-Wl,-rpath,%)
SHRLIBDIR_LDFLAGS += $(SHRLIBDIR_RPATH_LDFLAGS_$(LINKER_USE_RPATH))
# Set runtime path for shared libraries if USE_RPATH=YES and STATIC_BUILD=NO
SHRLIBDIR_RPATH_LDFLAGS_YES_NO = $(SHRLIB_DEPLIB_DIRS:%=-Wl,-rpath,%)
SHRLIBDIR_LDFLAGS += \
$(SHRLIBDIR_RPATH_LDFLAGS_$(LINKER_USE_RPATH)_$(STATIC_BUILD))
# Set runtime path for products
PRODDIR_RPATH_LDFLAGS_YES += $(PROD_DEPLIB_DIRS:%=-Wl,-rpath,%)
PRODDIR_LDFLAGS += $(PRODDIR_RPATH_LDFLAGS_$(LINKER_USE_RPATH))
# Set runtime path for products if USE_RPATH=YES and STATIC_BUILD=NO
PRODDIR_RPATH_LDFLAGS_YES_NO = $(PROD_DEPLIB_DIRS:%=-Wl,-rpath,%)
PRODDIR_LDFLAGS += \
$(PRODDIR_RPATH_LDFLAGS_$(LINKER_USE_RPATH)_$(STATIC_BUILD))
# Link libraries controlled by COMMANDLINE_LIBRARY
# The newest Linux versions only need readline, older ones need both

View File

@@ -122,20 +122,10 @@ GNU_DIR_6 = $(WIND_BASE)/gnu/$(VX_GNU_VERSION)-vxworks-$(VXWORKS_VERSION)/$(WIND
GNU_DIR = $(GNU_DIR_$(VXWORKS_MAJOR_VERSION))
#--------------------------------------------------
# Wind River moved nm out of GNU_BIN in some versions
# This finds nm on any supported VxWorks version
WORKBENCH_BIN = $(WIND_BASE)/workbench-$(WORKBENCH_VERSION)/$(WIND_HOST_TYPE)/bin
UTILITIES_BIN = $(WIND_BASE)/utilities-$(UTILITIES_VERSION)/$(WIND_HOST_TYPE)/bin
NM_DIR_6.4 = $(WORKBENCH_BIN)
NM_DIR_6.5 = $(WORKBENCH_BIN)
NM_DIR_6.6 = $(WORKBENCH_BIN)
NM_DIR_6.7 = $(GNU_BIN)
NM_DIR_6.8 = $(UTILITIES_BIN)
NM_DIR_6.9 = $(UTILITIES_BIN)
NM_DIR = $(firstword $(NM_DIR_$(VXWORKS_VERSION)) $(GNU_BIN))
NM = $(NM_DIR)/$(CMPLR_PREFIX)nm$(CMPLR_SUFFIX)$(HOSTEXE)
NMPROG = $(CMPLR_PREFIX)nm$(CMPLR_SUFFIX)$(HOSTEXE)
NM = $(firstword $(wildcard $(WIND_BASE)/*/$(WIND_HOST_TYPE)/bin/$(NMPROG)))
#--------------------------------------------------
# A linker script is essential for munching from vxWorks 6.6 onwards
@@ -146,14 +136,10 @@ MUNCH_LDFLAGS_6 = -T $(VX_DIR)/target/h/tool/gnu/ldscripts/link.OUT
MUNCH_LDFLAGS = $(MUNCH_LDFLAGS_$(VXWORKS_MAJOR_VERSION))
#--------------------------------------------------
# The follow 2 exports prevent gnu cross-compiler
# from finding wrong assembler (as).
# These are required by some of the Wind River tools
export WIND_BASE
export WIND_HOME = $(WIND_BASE)
export WIND_HOST_TYPE
#--------------------------------------------------
# Tornado2.2
# The follow export allows vxWorks.h to include gnu header files
export TOOL_FAMILY = GNU
#--------------------------------------------------
@@ -196,6 +182,8 @@ OSITHREAD_USE_DEFAULT_STACK = NO
#--------------------------------------------------
# Link definitions
CROSS_LDFLAGS =
#
LINK.cpp = $(LD) -o $@ $(STATIC_LDFLAGS) $(PRODDIR_LDFLAGS) $(LDFLAGS)
LINK.cpp += $(PROD_LDFLAGS) $(PROD_LD_OBJS) $(PROD_LD_RESS) $(PROD_LDLIBS)

View File

@@ -11,19 +11,14 @@ GNU_TARGET = arm-linux
CMPLR_SUFFIX =
CMPLR_PREFIX = $(addsuffix -,$(GNU_TARGET))
# Provide a link-time path for shared libraries
SHRLIBDIR_RPATH_LDFLAGS_YES += $(SHRLIB_DEPLIB_DIRS:%=-Wl,-rpath-link,%)
SHRLIBDIR_LDFLAGS += $(SHRLIBDIR_RPATH_LDFLAGS_$(LINKER_USE_RPATH))
# Provide a link-time path for products
PRODDIR_RPATH_LDFLAGS_YES += $(PROD_DEPLIB_DIRS:%=-Wl,-rpath-link,%)
PRODDIR_LDFLAGS += $(PRODDIR_RPATH_LDFLAGS_$(LINKER_USE_RPATH))
# Provide a link-time path for readline
RUNTIME_LDFLAGS_READLINE_YES = -Wl,-rpath-link,$(GNU_DIR)/lib
RUNTIME_LDFLAGS_READLINE = $(RUNTIME_LDFLAGS_READLINE_$(LINKER_USE_RPATH))
RUNTIME_LDFLAGS_READLINE_CURSES = $(RUNTIME_LDFLAGS_READLINE_$(LINKER_USE_RPATH))
RUNTIME_LDFLAGS_READLINE_NCURSES = $(RUNTIME_LDFLAGS_READLINE_$(LINKER_USE_RPATH))
# Provide a link-time path for readline if needed
OP_SYS_INCLUDES += $(READLINE_DIR:%=-I%/include)
READLINE_LDFLAGS = $(READLINE_DIR:%=-L%/lib)
RUNTIME_LDFLAGS_READLINE_YES_NO = $(READLINE_DIR:%=-Wl,-rpath,%/lib)
RUNTIME_LDFLAGS += \
$(RUNTIME_LDFLAGS_READLINE_$(LINKER_USE_RPATH)_$(STATIC_BUILD))
SHRLIBDIR_LDFLAGS += $(READLINE_LDFLAGS)
PRODDIR_LDFLAGS += $(READLINE_LDFLAGS)
# Library flags
STATIC_LDFLAGS_YES= -Wl,-Bstatic

View File

@@ -22,7 +22,7 @@ WINLINK = link
RCCMD = rc -l 0x409 $(INCLUDES) -fo $@ $<
ARCMD = lib /nologo /verbose /out:$@ $(LIB_OPT_LDFLAGS) $(LIBRARY_LD_OBJS)
ARCMD = lib -nologo -verbose -out:$@ $(LIB_OPT_LDFLAGS) $(LIBRARY_LD_OBJS)
BAFCMD = bscmake /nologo /o $@
@@ -67,45 +67,50 @@ OBJ_CFLAG = -Fo
# vis c++ compiles the code (and includes
# the header files)
#
# /MT static multithreaded C RTL
# /MTd static multithreaded C RTL (debug version)
# /MD multithreaded C RTL in DLL
# /MDd multithreaded C RTL in DLL (debug version)
# -MT static multithreaded C RTL
# -MTd static multithreaded C RTL (debug version)
# -MD multithreaded C RTL in DLL
# -MDd multithreaded C RTL in DLL (debug version)
VISC_DLL_NO = -DEPICS_DLL_NO
VISC_DLL_YES =
VISC_DLL = $(VISC_DLL_$(SHARED_LIBRARIES))
VISC_STATIC_CFLAGS_DEBUG_NO = d
VISC_STATIC_CFLAGS_DEBUG_YES =
VISC_STATIC_CFLAGS_DEBUG = $(VISC_STATIC_CFLAGS_DEBUG_$(HOST_OPT))
STATIC_CFLAGS_YES= /MT$(VISC_STATIC_CFLAGS_DEBUG) $(VISC_DLL)
STATIC_CFLAGS_NO= /MD$(VISC_STATIC_CFLAGS_DEBUG) $(VISC_DLL)
STATIC_CFLAGS_YES= -MT$(VISC_STATIC_CFLAGS_DEBUG) $(VISC_DLL)
STATIC_CFLAGS_NO= -MD$(VISC_STATIC_CFLAGS_DEBUG) $(VISC_DLL)
# OS vendor c preprocessor
CPP = cl /nologo /C /E
CPP = cl -nologo -C -E
# Configure OS vendor C++ compiler
#
# __STDC__=0 gives us both:
# 1) define STDC for code (pretend ANSI conformance)
# 2) set it to 0 to use MS C "extensions" (open for _open etc.)
# because MS uses: if __STDC__ ... disable many nice things
#
# -EHsc - generate code for exceptions
# -GR - generate code for run time type identification
#
CCC = cl -EHsc -GR
CODE_CPPFLAGS += -nologo -D__STDC__=0
# Other compiler flags, used for CPP, C and C++
#
# -FC - Show absolute path of source file in diagnostics
# -D__STDC__=0 gives us both:
# 1) define STDC for code (pretend ANSI conformance)
# 2) set it to 0 to use MS C "extensions" (open for _open etc.)
# because MS uses: if __STDC__ ... disable many nice things
#
CODE_CPPFLAGS += -nologo -FC -D__STDC__=0
CODE_CPPFLAGS += -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE
# Compiler flags for C++ files
#
# -W<N> use warning level N
# (maximum lint level warnings at level 4)
# -w44355 set "'this' used in the base initializer list" to be level 4
# -W<n> disable warnings from levels > n
# -w<n><m> set warning m to level n
# -w44355 "'this' used in the base initializer list"
# -w44344 "behavior change: use of explicit template arguments results in ..."
WARN_CXXFLAGS_YES = -W3 -w44355 -w44344
# -w44251 "class needs to have dll-interface to be used by clients of ..."
WARN_CXXFLAGS_YES = -W3 -w44355 -w44344 -w44251
WARN_CXXFLAGS_NO = -W1
#
@@ -129,18 +134,29 @@ OBJ_CXXFLAG = -Fo
# vis c++ compiles the code (and includes
# the header files)
#
# /MT static multithreaded C RTL
# /MTd static multithreaded C RTL (debug version)
# /MD multithreaded C RTL in DLL
# /MDd multithreaded C RTL in DLL (debug version)
STATIC_CXXFLAGS_YES= /MT$(VISC_STATIC_CFLAGS_DEBUG) $(VISC_DLL)
STATIC_CXXFLAGS_NO= /MD$(VISC_STATIC_CFLAGS_DEBUG) $(VISC_DLL)
# -MT static multithreaded C RTL
# -MTd static multithreaded C RTL (debug version)
# -MD multithreaded C RTL in DLL
# -MDd multithreaded C RTL in DLL (debug version)
STATIC_CXXFLAGS_YES= -MT$(VISC_STATIC_CFLAGS_DEBUG) $(VISC_DLL)
STATIC_CXXFLAGS_NO= -MD$(VISC_STATIC_CFLAGS_DEBUG) $(VISC_DLL)
STATIC_LDLIBS_YES=ws2_32.lib advapi32.lib user32.lib kernel32.lib winmm.lib
STATIC_LDLIBS_NO=
STATIC_LDFLAGS=
RANLIB=
#
# option needed for parallel builds with Visual Studio 2015 onward
#
# -FS Force Synchronous PDB Writes
ifneq ($(VisualStudioVersion),)
OPT_CXXFLAGS_NO += -FS
OPT_CFLAGS_NO += -FS
endif
#
# add -profile here to run the ms profiler
# -LTCG whole program optimization
# -incremental:no full linking
@@ -173,10 +189,10 @@ BAF=.bsc
BOF=.sbr
# Problem: MS Visual C++ does not recognize *.cc as C++ source,
# so we do C++ compiles using the global flag -TP
COMPILER_CXXFLAGS = /TP
# so we do C++ compiles using the global flag -TP
COMPILER_CXXFLAGS = -TP
# Operating system flags
# Operating system flags
OP_SYS_CFLAGS =
OP_SYS_CXXFLAGS = $(COMPILER_CXXFLAGS)
@@ -192,13 +208,13 @@ OP_SYS_CXXFLAGS = $(COMPILER_CXXFLAGS)
# '-entry:_DllMainCRTStartup$(DLLENTRY)'
DLLENTRY = @12
WIN32_DLLFLAGS = /subsystem:windows /dll $(OPT_LDFLAGS) \
WIN32_DLLFLAGS = -subsystem:windows -dll $(OPT_LDFLAGS) \
$(USR_LDFLAGS) $(CMD_LDFLAGS) $(TARGET_LDFLAGS) $(LIB_LDFLAGS)
#
# specify dll .def file only if it exists
#
DLL_DEF_FLAG = $(addprefix /def:,$(wildcard ../$(addsuffix .def,$*)))
DLL_DEF_FLAG = $(addprefix -def:,$(wildcard ../$(addsuffix .def,$*)))
#
# A WIN32 dll has three parts:
@@ -206,9 +222,9 @@ DLL_DEF_FLAG = $(addprefix /def:,$(wildcard ../$(addsuffix .def,$*)))
# x.lib: what you link to progs that use the dll (DLL_LINK_LIBNAME)
# x.exp: what you need to build the dll (in no variable)
#
LINK.shrlib = $(WINLINK) /nologo $(WIN32_DLLFLAGS) /implib:$*.lib /out:$*.dll $(DLL_DEF_FLAG)
LINK.shrlib = $(WINLINK) -nologo $(WIN32_DLLFLAGS) -implib:$*.lib -out:$*.dll $(DLL_DEF_FLAG)
LINK.shrlib += $(call PATH_FILTER, $(LIBRARY_LD_OBJS) $(LIBRARY_LD_RESS) $(SHRLIB_LDLIBS))
MUNCH_CMD = $(CCC) /Fo $@ $^
MUNCH_CMD = $(CCC) -Fo $@ $^
# adjust names of libraries to build
@@ -222,7 +238,7 @@ SHRLIBNAME_YES = $(BUILD_LIBRARY:%=%$(SHRLIB_SUFFIX))
LOADABLE_SHRLIBNAME = $(LOADABLE_BUILD_LIBRARY:%=%$(SHRLIB_SUFFIX))
#
# When SHARED_LIBRARIES is YES we are building a DLL link library
# When SHARED_LIBRARIES is YES we are building a DLL link library
# and when SHARED_LIBRARIES is NO we are building an object library
#
DLL_LINK_LIBNAME_YES = $(BUILD_LIBRARY:%=%.lib)
@@ -289,7 +305,7 @@ LINK.cpp = $(WINLINK) -nologo $(STATIC_LDFLAGS) $(LDFLAGS) $(PROD_LDFLAGS) \
#--------------------------------------------------
# UseManifestTool.pl checks MS Visual c++ compiler version number to
# decide whether or not to use the Manifest Tool command to embed the
# linker created .manifest file into a library or product target.
# linker created .manifest file into a library or product target.
# useManifestTool.pl returns 0(don't use) or 1(use).
#
MT.exe = mt.exe -nologo -manifest $@.manifest
@@ -299,4 +315,3 @@ MT_EXE_COMMAND_NO = $(MT.exe) "-outputresource:$@;\#1"
MT_EXE_COMMAND1 = $(MT_EXE_COMMAND_$(STATIC_BUILD))
MT_DLL_COMMAND = $(MT_DLL_COMMAND$(shell $(PERL) $(TOOLS)/useManifestTool.pl))
MT_EXE_COMMAND = $(MT_EXE_COMMAND$(shell $(PERL) $(TOOLS)/useManifestTool.pl))

View File

@@ -9,14 +9,13 @@ include $(CONFIG)/os/CONFIG.win32-x86.win32-x86
-include $(CONFIG)/os/CONFIG_SITE.win32-x86.win32-x86
# Modify CONFIG.win32-x86.win32-x86 settings:
ARCH_DEP_CPPFLAGS += /favor:blend
# /favor:blend both AMD64 and INTEL64
# /favor:AMD64
# /favor:INTEL64 (new value)
# /favor:EN64T (old value)
OPT_LDFLAGS += /MACHINE:X64
# /MACHINE:X64
# /MACHINE:IA64 (Itanium)
# /MACHINE:X86
ARCH_DEP_CPPFLAGS += -favor:blend
# -favor:blend both AMD64 and INTEL64
# -favor:AMD64
# -favor:INTEL64 (new value)
# -favor:EN64T (old value)
OPT_LDFLAGS += -MACHINE:X64
# -MACHINE:X64
# -MACHINE:IA64 (Itanium)
# -MACHINE:X86

View File

@@ -1,10 +1,4 @@
# CONFIG_SITE.Common.linux-xscale_be
#
# Site specific definitions for linux-xscale_be target builds.
# Site specific definitions for all linux-xscale_be target builds.
#-------------------------------------------------------
# Set GNU_DIR to point to directory containing the tool-chain
# APS:
GNU_DIR = /usr/local/vw/xscale_be

View File

@@ -10,7 +10,7 @@
# Note: vxWorks 5.3 (Tornado 1.x) is not supported
#VXWORKS_VERSION = 5.4
VXWORKS_VERSION = 5.5
#VXWORKS_VERSION = 5.5
#VXWORKS_VERSION = 6.0
#VXWORKS_VERSION = 6.1
#VXWORKS_VERSION = 6.2
@@ -20,7 +20,7 @@ VXWORKS_VERSION = 5.5
#VXWORKS_VERSION = 6.6
#VXWORKS_VERSION = 6.7
#VXWORKS_VERSION = 6.8
#VXWORKS_VERSION = 6.9
VXWORKS_VERSION = 6.9
# Sites may override the following path for a particular host
@@ -31,19 +31,6 @@ VXWORKS_VERSION = 5.5
# Under vxWorks 6.x this is *not* the same as the old VX_DIR setting
#WIND_BASE = /usr/local/vw/tornado202p1
WIND_BASE = /usr/local/vw/tornado22-$(ARCH_CLASS)
#WIND_BASE = /usr/local/vw/vxWorks-$(VXWORKS_VERSION)
#WIND_BASE = /usr/local/vw/tornado22-$(ARCH_CLASS)
WIND_BASE = /usr/local/vw/vxWorks-$(VXWORKS_VERSION)
#WIND_BASE = /ade/vxWorks/$(VXWORKS_VERSION)
# WorkBench Version number, required for vxWorks 6.x
#WORKBENCH_VERSION = 2.6
#WORKBENCH_VERSION = 3.0
#WORKBENCH_VERSION = 3.2
#WORKBENCH_VERSION = 3.3
# Utilities Version number, required from vxWorks 6.8 and later
#UTILITIES_VERSION = 1.0

View File

@@ -7,8 +7,25 @@
GNU_TARGET = arm-xilinx-linux-gnueabi
# Set GNU tools install path
# This is the install path at APS:
# Examples are installations at the APS:
GNU_DIR = /usr/local/vw/zynq-2011.09
#GNU_DIR = /usr/local/Xilinx/SDK/2016.3/gnu/arm/lin
#GNU_DIR = /APSshare/XilinxSDK/2015.4/gnu/arm/lin
# If cross-building shared libraries and the paths on the target machine are
# different than on the build host, you should uncomment the lines below to
# disable putting runtime library paths in products and shared libraries.
# You will also need to provide another way for programs to find their shared
# libraries at runtime, such as by setting LD_LIBRARY_PATH or by using
# mechanisms related to /etc/ld.so.conf
#SHRLIBDIR_RPATH_LDFLAGS_YES_NO =
#PRODDIR_RPATH_LDFLAGS_YES_NO =
# Note: It may be simpler to just set STATIC_BUILD=YES here and not
# try to use shared libraries at all in these circumstances.
# To use libreadline, point this to its install prefix
#READLINE_DIR = $(GNU_DIR)
#READLINE_DIR = /tools/cross/linux-x86.linux-arm/readline
# See CONFIG_SITE.Common.linux-arm for other COMMANDLINE_LIBRARY values
#COMMANDLINE_LIBRARY = READLINE
# With a Xilinx SDK, it'll be something like
#GNU_DIR = /usr/local/zynq/Xilinx/SDK/2015.4/gnu/arm/lin

View File

@@ -0,0 +1,11 @@
# CONFIG_SITE.linux-x86.linux-xscale_be
#
# Site specific definitions for linux-x86 host - linux-xscale_be targets
#-------------------------------------------------------
# Set GNU_DIR to point to directory containing the tool-chain
GNU_DIR = /usr/local/vw/xscale_be
# If readline is available, configure it
READLINE_DIR = $(GNU_DIR)/target/usr
COMMANDLINE_LIBRARY = READLINE

View File

@@ -0,0 +1,7 @@
# CONFIG_SITE.linux-x86_64.linux-xscale_be
#
# Site specific settings for linux-x86_64 host - linux-xscale_be target
#-------------------------------------------------------
# Inherit setting from linux-x86
include $(CONFIG)/os/CONFIG_SITE.linux-x86.linux-xscale_be

View File

@@ -4,27 +4,16 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Known Problems in R3.14.12.1</title>
<title>Known Problems in R3.14.12.8</title>
</head>
<body>
<h1 style="text-align: center">EPICS Base R3.14.12.1: Known Problems</h1>
<h1 style="text-align: center">EPICS Base R3.14.12.8: Known Problems</h1>
<p>Any patch files linked below should be applied at the root of the
base-3.14.12.1 tree. Download them, then use the GNU Patch program as
follows:</p>
<blockquote><pre>% <b>cd <i>/path/to/</i>base-3.14.12.1</b>
% <b>patch -p0 &lt; <i>/path/to/</i>file.patch</b></pre></blockquote>
<p>The following significant problems have been reported with this
version of EPICS Base:</p>
<ul>
<li>None yet.</li>
</ul>
<p>This was the last release in the Base-3.14 series, so we are no longer
tracking bugs in this branch. Please upgrade to one of the newer releases which
have incorporated many bug fixes and new features since they branched off the
Base-3.14 release series.</p>
</body>
</html>

View File

@@ -436,6 +436,6 @@
References
1. http://www.aps.anl.gov/epics/base/tornado.php
2. http://www.aps.anl.gov/epics/base/vxWorks6.php
3. http://www.aps.anl.gov/epics/
1. https://epics.anl.gov/base/tornado.php
2. https://epics.anl.gov/base/vxWorks6.php
3. https://epics.anl.gov/

View File

@@ -96,8 +96,8 @@
needed to build for these target systems. The absolute path to and version
number of the vxWorks installation is normally specified in the
base/configure/os/CONFIG_SITE.Common.vxWorksCommon file. Consult the EPICS web
pages about <a href="http://www.aps.anl.gov/epics/base/tornado.php">vxWorks
5.x</a> and <a href="http://www.aps.anl.gov/epics/base/vxWorks6.php">vxWorks
pages about <a href="https://epics.anl.gov/base/tornado.php">vxWorks
5.x</a> and <a href="https://epics.anl.gov/base/vxWorks6.php">vxWorks
6.x</a> and the vxWorks documentation for information about configuring your
vxWorks operating system for use with EPICS.</P>
@@ -126,7 +126,7 @@
<H3><A NAME="0_0_8"> Documentation</A></H3>
<BLOCKQUOTE>EPICS documentation is available through the
<a href="http://www.aps.anl.gov/epics/">EPICS website</a> at Argonne.
<a href="https://epics.anl.gov/">EPICS website</a> at Argonne.
<P>Release specific documentation can also be found in the base/documentation
directory of the distribution.</BLOCKQUOTE>

View File

@@ -3,16 +3,138 @@
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
<title>EPICS Base R3.14.12.6 Release Notes</title>
<title>EPICS Base R3.14.12.8 Release Notes</title>
</head>
<body lang="en">
<h1 align="center">EPICS Base Release 3.14.12.6</h1>
<h1 align="center">EPICS Base Release 3.14.12.8</h1>
<h2 align="center">Changes between 3.14.12.5 and 3.14.12.6</h2>
<p>This is the final release in the Base-3.14 series, please upgrade to the
Base-3.15 series or to EPICS 7.</p>
<h2 align="center">Changes between 3.14.12.7 and 3.14.12.8</h2>
<!-- Insert new items immediately below here ... -->
<h3>Fixes for Launchpad bugs</h3>
<p>The following launchpad bugs have fixes included:</p>
<ul>
<li><a href="https://bugs.launchpad.net/epics-base/+bug/541221">
lp: #541221</a>, 'assert (pca->pgetNative)' failed in ../dbCa.c</li>
<li><a href="https://bugs.launchpad.net/epics-base/+bug/1747091">
lp: #1747091</a>, epicsTimeGetEvent() / generalTime bug</li>
<li><a href="https://bugs.launchpad.net/epics-base/+bug/1743076">
lp: #1743076</a>, Segfault in ca_attach_context() during exits</li>
<li><a href="https://bugs.launchpad.net/epics-base/+bug/1751380">
lp: #1751380</a>, Deadlock in ca_clear_subscription()</li>
<li><a href="https://bugs.launchpad.net/epics-base/+bug/1597809">
lp: #1597809</a>, Setting NAME field in DB file may break IOC</li>
<li><a href="https://bugs.launchpad.net/epics-base/+bug/1770292">
lp: #1770292</a>, get_alarm_double() inconsistent across record types</li>
<li><a href="https://bugs.launchpad.net/epics-base/+bug/1771298">
lp: #1771298</a>, Conversion of NaN to integer relies on undefined
behavior</li>
</ul>
<h3>Updated VxWorks Timezone settings</h3>
<p>Removed the settings for 2017; fixed the hour of the change for MET.</p>
<h3>Back-port podToHtml.pl and Rules from Base-3.15</h3>
<p>This script permits Base to be built with Perl installations that do not
provide the podchecker and pod2html scripts (e.g. Fedora 27).</p>
<h3>Fixed camonitor server side relative timestamps bug</h3>
<p>Initialize the first time-stamp from the first monitor, not the client-side
current time in this configuration.</p>
<h3>Build changes for MSVC</h3>
<p>Windows builds using Visual Studio 2015 and later now use the <tt>-FS</tt>
compiler option to allow parallel builds to work properly.</p>
<p>We now give the <tt>-FC</tt> option to tell the compiler to print absolute
paths for source files in diagnostic messages.</p>
<h2 align="center">Changes between 3.14.12.6 and 3.14.12.7</h2>
<h3>Extend maximum Posix epicsEventWaitWithTimeout() delay</h3>
<p>The Posix implementation of epicsEventWaitWithTimeout() was limiting the
timeout delay to at most 60 minutes (3600.0 seconds). This has been changed to
10 years; significantly longer maximum delays cause problems on systems where
<tt>time_t</tt> is still a signed 32-bit integer so cannot represent absolute
time-stamps after 2038-01-19. Our assumption is that such 32-bit systems will
have been retired before the year 2028, but some additional tests have been
added to the epicsTimeTest program to detect and fail if this assumption is
violated.</p>
<h3>New test-related make targets</h3>
<p>This release adds several new make targets intended for use by developers
and Continuous Integration systems which simplify the task of running the
built-in self-test programs and viewing the results. Since these targets are
intended for limited use they can have requirements for the build host which
go beyond the standard minimum set needed to build and run Base.</p>
<blockquote>
<h4><tt>test-results</tt> &mdash; Summarize test results</h4>
<p>The new make target <tt>test-results</tt> will run the self-tests if
necessary to generate a TAP file for each test, then summarizes the TAP output
files in each test directory in turn, displaying the details of any failures.
This step uses the program <q>prove</q> which comes with Perl, but also needs
<q>cat</q> to be provided in the default search path so will not work on most
Windows systems.</p>
<h4><tt>junitfiles</tt> &mdash; Convert test results to JUnit XML Format</h4>
<p>The new make target <tt>junitfiles</tt> will run the self-tests if necessary
and then convert the TAP output files into the more commonly-supported JUnit
XML format. The program that performs this conversion needs the Perl module
<q><tt>XML::Generator</tt></q> to have been installed.</p>
<h4><tt>clean-tests</tt> &mdash; Delete test result files</h4>
<p>The new make target <tt>clean-tests</tt> removes any test result files from
previous test runs. It cleans both TAP and JUnit XML files.</p>
</blockquote>
<h3>Fix DNS related crash on exit</h3>
<p>The attempt to fix DNS related delays for short lived CLI programs (eg. caget)
in lp:1527636 introduced a bug which cased these short lived clients to crash on exit.
This bug should now be fixed.</p>
<h3>Server bind issue on Windows</h3>
<p>When a National Instruments network variables CA server is already running on
a Windows system and an IOC or PCAS server is started, the IOC's attempt to
bind a TCP socket to the CA server port number fails, but Windows returns a
different error status value than the IOC is expecting in that circumstance
(because the National Instruments code requests exclusive use of that port,
unlike the EPICS code) so the IOC fails to start properly. The relevent EPICS
bind() checks have now been updated so the IOC will request that a dynamic port
number be allocated for this TCP socket instead when this happens.</p>
<h3>Checking Periodic Scan Rates</h3>
<p>Code has been added to the IOC startup to better protect it against bad
periodic scan rates, including against locales where <q><tt>.</tt></q> is not
accepted as a decimal separator character. If the scan period in a menuScan
choice string cannot be parsed, the associated periodic scan thread will no
longer be started by the IOC and a warning message will be displayed at iocInit
time. The <tt>scanppl</tt> command will also flag the faulty menuScan value.</p>
<h2 align="center">Changes between 3.14.12.5 and 3.14.12.6</h2>
<h3>Launchpad Bug-fixes</h3>
<p>In addition to the more detailed change descriptions below, the following
@@ -277,8 +399,6 @@ it up. This release patches the readline support code to clean up automatically
by registering an epicsAtExit() routine.</p>
<h1 align="center">EPICS Base Release 3.14.12.5</h1>
<h2 align="center">Changes between 3.14.12.4 and 3.14.12.5</h2>
<h3>aoRecord raw conversion overflows</h3>
@@ -776,7 +896,7 @@ access monitor on the DLYA field; this happens twice during record processing if
the ODLY field is larger than 0.</p>
<p>Timestamps from all seq record monitor events have been wrong since 1995 or
earlier, the time being provided was from the last time the record processed.
earlier, the time being provided was from the last time the record processed.
Now the record timestamp will be updated between reading each DOL1..DOLA link
and posting the monitor on the associated DO1..DOA field. The VAL field is
never given a value by the record processing code, but is used for posting
@@ -1008,7 +1128,7 @@ fixed in this release:</p>
<li>717252
<a href="https://launchpad.net/bugs/771252">
local caput causes ioc crash on win32</a></li>
<li>750549
<li>750549
<a href="https://launchpad.net/bugs/750549 ">
epicsTime has non-portable c++ static initialization</a></li>
<li>753137
@@ -1362,7 +1482,7 @@ more extensive modifications.</p>
<h4>RTEMS 4.10 support</h4>
<p>Added support for the latest release of RTEMS. There is no longer a
<p>Added support for the latest release of RTEMS. There is no longer a
distinction between executive and malloc memory pools. The new mount() API
is used.</p>
@@ -1455,7 +1575,7 @@ doing a put</p>
<p> These changes impact the Gateway (Proxy server) and other servers but not
the IOC.</h4>
<p>Mantis 360 fix - server is unresponsive for one of its clients, when
<p>Mantis 360 fix - server is unresponsive for one of its clients, when
async io postponed and in flow control mode</p>
<p>Mantis 358 fix - PCAS service snap-in has no way to determine if its a put,
@@ -1468,7 +1588,7 @@ controling motor through gw.</p>
<p>Mantis 340 fix - leak when performing a read and conversion fails.</p>
<p>Mantis 348 fix - A call to 'assert (item.pList == this)'
<p>Mantis 348 fix - A call to 'assert (item.pList == this)'
failed in ../../../../src/cas/generic/st/ioBlocked.cc line 112</p>
<p>Mantis 345 fix - Compilation warning: complaint about missing
@@ -1484,7 +1604,7 @@ R3.13 client</p>
<p>Mantis 329 fix - GW hang, pthread_mutex_lock failed: error Invalid
argument message</p>
<p>Mantis 352 fix - gateway hangs temporarily under heavy load on 8-core
<p>Mantis 352 fix - gateway hangs temporarily under heavy load on 8-core
64bit RHEL5</p>
<ul>
@@ -2005,7 +2125,7 @@ tools to allow specifying the CA priority.</p>
<h4>GCC_EXEC_PREFIX references removed from configuration files</h4>
<p>Definition of GCC_EXEC_PREFIX removed from CONFIG.CrossCommon and
<p>Definition of GCC_EXEC_PREFIX removed from CONFIG.CrossCommon and
unexport of GCC_EXEC_PREFIX removed from vxWorks and RTEMS builds.</p>
<h4>RTEMS Release</h4>
@@ -3222,7 +3342,7 @@ was returned as -1.17549435E-38. This is now fixed.</p>
in a &lt;name&gt;_DBD macro definition. An include line will be placed in the
&lt;name&gt;Include.dbd for each file specified in the &lt;name&gt;_DBD
definition. If a Makefile contains</p>
<pre> DBD=xxx.dbd
<pre> DBD=xxx.dbd
xxx_DBD = f1.dbd f2.dbd f3.dbd </pre>
<p>an xxxInclude.dbd file will be created containing the lines</p>

View File

@@ -3,9 +3,8 @@
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
%{
static int yyerror(char *);
@@ -29,9 +28,7 @@ static ASGRULE *yyAsgRule=NULL;
%union
{
int Int;
char Char;
char *Str;
double Real;
}
%%
@@ -208,11 +205,12 @@ rule_hag_list_name: tokenSTRING
static int yyerror(char *str)
{
if (strlen(str)) epicsPrintf("%s\n", str);
epicsPrintf("Access Security file error at line %d\n",
line_num);
if (strlen(str))
errlogPrintf("%s at line %d\n", str, line_num);
else
errlogPrintf("Error at line %d\n", line_num);
yyFailed = TRUE;
return(0);
return 0;
}
static int myParse(ASINPUTFUNCPTR inputfunction)
{

View File

@@ -1,12 +1,10 @@
/* share/src/as/asLibRoutines.c */
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* Author: Marty Kraimer Date: 10-15-93 */
@@ -21,7 +19,7 @@
#include "epicsThread.h"
#include "cantProceed.h"
#include "epicsMutex.h"
#include "epicsPrint.h"
#include "errlog.h"
#include "gpHash.h"
#include "freeList.h"
#include "macLib.h"
@@ -111,7 +109,7 @@ long epicsShareAPI asInitialize(ASINPUTFUNCPTR inputfunction)
pasg = (ASG *)ellFirst(&pasbasenew->asgList);
while(pasg) {
pasg->pavalue = asCalloc(CALCPERFORM_NARGS, sizeof(double));
pasg = (ASG *)ellNext((ELLNODE *)pasg);
pasg = (ASG *)ellNext(&pasg->node);
}
gphInitPvt(&pasbasenew->phash, 256);
/*Hash each uagname and each hagname*/
@@ -121,12 +119,12 @@ long epicsShareAPI asInitialize(ASINPUTFUNCPTR inputfunction)
while(puagname) {
pgphentry = gphAdd(pasbasenew->phash,puagname->user,puag);
if(!pgphentry) {
epicsPrintf("Duplicated user '%s' in UAG '%s'\n",
errlogPrintf("Duplicated user '%s' in UAG '%s'\n",
puagname->user, puag->name);
}
puagname = (UAGNAME *)ellNext((ELLNODE *)puagname);
puagname = (UAGNAME *)ellNext(&puagname->node);
}
puag = (UAG *)ellNext((ELLNODE *)puag);
puag = (UAG *)ellNext(&puag->node);
}
phag = (HAG *)ellFirst(&pasbasenew->hagList);
while(phag) {
@@ -134,12 +132,12 @@ long epicsShareAPI asInitialize(ASINPUTFUNCPTR inputfunction)
while(phagname) {
pgphentry = gphAdd(pasbasenew->phash,phagname->host,phag);
if(!pgphentry) {
epicsPrintf("Duplicated host '%s' in HAG '%s'\n",
errlogPrintf("Duplicated host '%s' in HAG '%s'\n",
phagname->host, phag->name);
}
phagname = (HAGNAME *)ellNext((ELLNODE *)phagname);
phagname = (HAGNAME *)ellNext(&phagname->node);
}
phag = (HAG *)ellNext((ELLNODE *)phag);
phag = (HAG *)ellNext(&phag->node);
}
pasbaseold = (ASBASE *)pasbase;
pasbase = (ASBASE volatile *)pasbasenew;
@@ -152,12 +150,12 @@ long epicsShareAPI asInitialize(ASINPUTFUNCPTR inputfunction)
while(poldasg) {
poldmem = (ASGMEMBER *)ellFirst(&poldasg->memberList);
while(poldmem) {
pnextoldmem = (ASGMEMBER *)ellNext((ELLNODE *)poldmem);
ellDelete(&poldasg->memberList,(ELLNODE *)poldmem);
pnextoldmem = (ASGMEMBER *)ellNext(&poldmem->node);
ellDelete(&poldasg->memberList,&poldmem->node);
status = asAddMemberPvt(&poldmem,poldmem->asgName);
poldmem = pnextoldmem;
}
poldasg = (ASG *)ellNext((ELLNODE *)poldasg);
poldasg = (ASG *)ellNext(&poldasg->node);
}
asFreeAll(pasbaseold);
}
@@ -203,7 +201,7 @@ static int myInputFunction(char *buf, int max_size)
n = macExpandString(macHandle,mac_input_buffer,
my_buffer,BUF_SIZE);
if(n<0) {
epicsPrintf("access security: macExpandString failed\n"
errlogPrintf("access security: macExpandString failed\n"
"input line: %s\n",mac_input_buffer);
return(0);
}
@@ -243,7 +241,7 @@ long epicsShareAPI asInitFP(FILE *fp,const char *substitutions)
macHandle = NULL;
} else {
macInstallMacros(macHandle,macPairs);
free((void *)macPairs);
free(macPairs);
mac_input_buffer = mac_buffer;
}
}
@@ -279,13 +277,13 @@ long epicsShareAPI asRemoveMember(ASMEMBERPVT *asMemberPvt)
return(S_asLib_clientsExist);
}
if(pasgmember->pasg) {
ellDelete(&pasgmember->pasg->memberList,(ELLNODE *)pasgmember);
ellDelete(&pasgmember->pasg->memberList,&pasgmember->node);
} else {
errMessage(-1,"Logic error in asRemoveMember");
UNLOCK;
return(-1);
}
free((void *)pasgmember);
free(pasgmember);
*asMemberPvt = NULL;
UNLOCK;
return(0);
@@ -301,7 +299,7 @@ long epicsShareAPI asChangeGroup(ASMEMBERPVT *asMemberPvt,const char *newAsgName
if(!pasgmember) return(S_asLib_badMember);
LOCK;
if(pasgmember->pasg) {
ellDelete(&pasgmember->pasg->memberList,(ELLNODE *)pasgmember);
ellDelete(&pasgmember->pasg->memberList,&pasgmember->node);
} else {
errMessage(-1,"Logic error in asChangeGroup");
UNLOCK;
@@ -353,7 +351,7 @@ long epicsShareAPI asAddClient(ASCLIENTPVT *pasClientPvt,ASMEMBERPVT asMemberPvt
pasgclient->user = user;
pasgclient->host = host;
LOCK;
ellAdd(&pasgmember->clientList,(ELLNODE *)pasgclient);
ellAdd(&pasgmember->clientList,&pasgclient->node);
status = asComputePvt(pasgclient);
UNLOCK;
return(status);
@@ -395,7 +393,7 @@ long epicsShareAPI asRemoveClient(ASCLIENTPVT *asClientPvt)
UNLOCK;
return(-1);
}
ellDelete(&pasgMember->clientList,(ELLNODE *)pasgclient);
ellDelete(&pasgMember->clientList,&pasgclient->node);
UNLOCK;
freeListFree(freeListPvt,pasgclient);
*asClientPvt = NULL;
@@ -508,10 +506,10 @@ int epicsShareAPI asDumpFP(
if(puagname) fprintf(fp," {"); else fprintf(fp,"\n");
while(puagname) {
fprintf(fp,"%s",puagname->user);
puagname = (UAGNAME *)ellNext((ELLNODE *)puagname);
puagname = (UAGNAME *)ellNext(&puagname->node);
if(puagname) fprintf(fp,","); else fprintf(fp,"}\n");
}
puag = (UAG *)ellNext((ELLNODE *)puag);
puag = (UAG *)ellNext(&puag->node);
}
phag = (HAG *)ellFirst(&pasbase->hagList);
if(!phag) fprintf(fp,"No HAGs\n");
@@ -521,10 +519,10 @@ int epicsShareAPI asDumpFP(
if(phagname) fprintf(fp," {"); else fprintf(fp,"\n");
while(phagname) {
fprintf(fp,"%s",phagname->host);
phagname = (HAGNAME *)ellNext((ELLNODE *)phagname);
phagname = (HAGNAME *)ellNext(&phagname->node);
if(phagname) fprintf(fp,","); else fprintf(fp,"}\n");
}
phag = (HAG *)ellNext((ELLNODE *)phag);
phag = (HAG *)ellNext(&phag->node);
}
pasg = (ASG *)ellFirst(&pasbase->asgList);
if(!pasg) fprintf(fp,"No ASGs\n");
@@ -552,7 +550,7 @@ int epicsShareAPI asDumpFP(
fprintf(fp," value=%f",pasg->pavalue[pasginp->inpIndex]);
}
fprintf(fp,"\n");
pasginp = (ASGINP *)ellNext((ELLNODE *)pasginp);
pasginp = (ASGINP *)ellNext(&pasginp->node);
}
while(pasgrule) {
int print_end_brace;
@@ -572,14 +570,14 @@ int epicsShareAPI asDumpFP(
if(pasguag) fprintf(fp,"\t\tUAG(");
while(pasguag) {
fprintf(fp,"%s",pasguag->puag->name);
pasguag = (ASGUAG *)ellNext((ELLNODE *)pasguag);
pasguag = (ASGUAG *)ellNext(&pasguag->node);
if(pasguag) fprintf(fp,","); else fprintf(fp,")\n");
}
pasghag = (ASGHAG *)ellFirst(&pasgrule->hagList);
if(pasghag) fprintf(fp,"\t\tHAG(");
while(pasghag) {
fprintf(fp,"%s",pasghag->phag->name);
pasghag = (ASGHAG *)ellNext((ELLNODE *)pasghag);
pasghag = (ASGHAG *)ellNext(&pasghag->node);
if(pasghag) fprintf(fp,","); else fprintf(fp,")\n");
}
if(pasgrule->calc) {
@@ -589,7 +587,7 @@ int epicsShareAPI asDumpFP(
fprintf(fp,"\n");
}
if(print_end_brace) fprintf(fp,"\t}\n");
pasgrule = (ASGRULE *)ellNext((ELLNODE *)pasgrule);
pasgrule = (ASGRULE *)ellNext(&pasgrule->node);
}
pasgmember = (ASGMEMBER *)ellFirst(&pasg->memberList);
if(!verbose) pasgmember = NULL;
@@ -616,12 +614,12 @@ int epicsShareAPI asDumpFP(
fprintf(fp," Illegal Access %d",pasgclient->access);
if(clientcallback) clientcallback(pasgclient,fp);
fprintf(fp,"\n");
pasgclient = (ASGCLIENT *)ellNext((ELLNODE *)pasgclient);
pasgclient = (ASGCLIENT *)ellNext(&pasgclient->node);
}
pasgmember = (ASGMEMBER *)ellNext((ELLNODE *)pasgmember);
pasgmember = (ASGMEMBER *)ellNext(&pasgmember->node);
}
if(print_end_brace) fprintf(fp,"}\n");
pasg = (ASG *)ellNext((ELLNODE *)pasg);
pasg = (ASG *)ellNext(&pasg->node);
}
return(0);
}
@@ -641,7 +639,7 @@ int epicsShareAPI asDumpUagFP(FILE *fp,const char *uagname)
if(!puag) fprintf(fp,"No UAGs\n");
while(puag) {
if(uagname && strcmp(uagname,puag->name)!=0) {
puag = (UAG *)ellNext((ELLNODE *)puag);
puag = (UAG *)ellNext(&puag->node);
continue;
}
fprintf(fp,"UAG(%s)",puag->name);
@@ -649,10 +647,10 @@ int epicsShareAPI asDumpUagFP(FILE *fp,const char *uagname)
if(puagname) fprintf(fp," {"); else fprintf(fp,"\n");
while(puagname) {
fprintf(fp,"%s",puagname->user);
puagname = (UAGNAME *)ellNext((ELLNODE *)puagname);
puagname = (UAGNAME *)ellNext(&puagname->node);
if(puagname) fprintf(fp,","); else fprintf(fp,"}\n");
}
puag = (UAG *)ellNext((ELLNODE *)puag);
puag = (UAG *)ellNext(&puag->node);
}
return(0);
}
@@ -672,7 +670,7 @@ int epicsShareAPI asDumpHagFP(FILE *fp,const char *hagname)
if(!phag) fprintf(fp,"No HAGs\n");
while(phag) {
if(hagname && strcmp(hagname,phag->name)!=0) {
phag = (HAG *)ellNext((ELLNODE *)phag);
phag = (HAG *)ellNext(&phag->node);
continue;
}
fprintf(fp,"HAG(%s)",phag->name);
@@ -680,10 +678,10 @@ int epicsShareAPI asDumpHagFP(FILE *fp,const char *hagname)
if(phagname) fprintf(fp," {"); else fprintf(fp,"\n");
while(phagname) {
fprintf(fp,"%s",phagname->host);
phagname = (HAGNAME *)ellNext((ELLNODE *)phagname);
phagname = (HAGNAME *)ellNext(&phagname->node);
if(phagname) fprintf(fp,","); else fprintf(fp,"}\n");
}
phag = (HAG *)ellNext((ELLNODE *)phag);
phag = (HAG *)ellNext(&phag->node);
}
return(0);
}
@@ -708,7 +706,7 @@ int epicsShareAPI asDumpRulesFP(FILE *fp,const char *asgname)
int print_end_brace;
if(asgname && strcmp(asgname,pasg->name)!=0) {
pasg = (ASG *)ellNext((ELLNODE *)pasg);
pasg = (ASG *)ellNext(&pasg->node);
continue;
}
fprintf(fp,"ASG(%s)",pasg->name);
@@ -728,7 +726,7 @@ int epicsShareAPI asDumpRulesFP(FILE *fp,const char *asgname)
fprintf(fp," INVALID");
fprintf(fp," value=%f",pasg->pavalue[pasginp->inpIndex]);
fprintf(fp,"\n");
pasginp = (ASGINP *)ellNext((ELLNODE *)pasginp);
pasginp = (ASGINP *)ellNext(&pasginp->node);
}
while(pasgrule) {
int print_end_brace;
@@ -748,14 +746,14 @@ int epicsShareAPI asDumpRulesFP(FILE *fp,const char *asgname)
if(pasguag) fprintf(fp,"\t\tUAG(");
while(pasguag) {
fprintf(fp,"%s",pasguag->puag->name);
pasguag = (ASGUAG *)ellNext((ELLNODE *)pasguag);
pasguag = (ASGUAG *)ellNext(&pasguag->node);
if(pasguag) fprintf(fp,","); else fprintf(fp,")\n");
}
pasghag = (ASGHAG *)ellFirst(&pasgrule->hagList);
if(pasghag) fprintf(fp,"\t\tHAG(");
while(pasghag) {
fprintf(fp,"%s",pasghag->phag->name);
pasghag = (ASGHAG *)ellNext((ELLNODE *)pasghag);
pasghag = (ASGHAG *)ellNext(&pasghag->node);
if(pasghag) fprintf(fp,","); else fprintf(fp,")\n");
}
if(pasgrule->calc) {
@@ -764,10 +762,10 @@ int epicsShareAPI asDumpRulesFP(FILE *fp,const char *asgname)
fprintf(fp,"\n");
}
if(print_end_brace) fprintf(fp,"\t}\n");
pasgrule = (ASGRULE *)ellNext((ELLNODE *)pasgrule);
pasgrule = (ASGRULE *)ellNext(&pasgrule->node);
}
if(print_end_brace) fprintf(fp,"}\n");
pasg = (ASG *)ellNext((ELLNODE *)pasg);
pasg = (ASG *)ellNext(&pasg->node);
}
return(0);
}
@@ -791,7 +789,7 @@ int epicsShareAPI asDumpMemFP(FILE *fp,const char *asgname,
while(pasg) {
if(asgname && strcmp(asgname,pasg->name)!=0) {
pasg = (ASG *)ellNext((ELLNODE *)pasg);
pasg = (ASG *)ellNext(&pasg->node);
continue;
}
fprintf(fp,"ASG(%s)\n",pasg->name);
@@ -820,11 +818,11 @@ int epicsShareAPI asDumpMemFP(FILE *fp,const char *asgname,
else
fprintf(fp," Illegal Access %d",pasgclient->access);
fprintf(fp,"\n");
pasgclient = (ASGCLIENT *)ellNext((ELLNODE *)pasgclient);
pasgclient = (ASGCLIENT *)ellNext(&pasgclient->node);
}
pasgmember = (ASGMEMBER *)ellNext((ELLNODE *)pasgmember);
pasgmember = (ASGMEMBER *)ellNext(&pasgmember->node);
}
pasg = (ASG *)ellNext((ELLNODE *)pasg);
pasg = (ASG *)ellNext(&pasg->node);
}
return(0);
}
@@ -875,23 +873,23 @@ static long asAddMemberPvt(ASMEMBERPVT *pasMemberPvt,const char *asgName)
pgroup = (ASG *)ellFirst(&pasbase->asgList);
while(pgroup) {
if(strcmp(pgroup->name,pasgmember->asgName)==0) goto got_it;
pgroup = (ASG *)ellNext((ELLNODE *)pgroup);
pgroup = (ASG *)ellNext(&pgroup->node);
}
/* Put it in DEFAULT*/
pgroup = (ASG *)ellFirst(&pasbase->asgList);
while(pgroup) {
if(strcmp(pgroup->name,DEFAULT)==0) goto got_it;
pgroup = (ASG *)ellNext((ELLNODE *)pgroup);
pgroup = (ASG *)ellNext(&pgroup->node);
}
errMessage(-1,"Logic Error in asAddMember");
return(-1);
got_it:
pasgmember->pasg = pgroup;
ellAdd(&pgroup->memberList,(ELLNODE *)pasgmember);
ellAdd(&pgroup->memberList,&pasgmember->node);
pasgclient = (ASGCLIENT *)ellFirst(&pasgmember->clientList);
while(pasgclient) {
asComputePvt((ASCLIENTPVT)pasgclient);
pasgclient = (ASGCLIENT *)ellNext((ELLNODE *)pasgclient);
pasgclient = (ASGCLIENT *)ellNext(&pasgclient->node);
}
return(0);
}
@@ -904,7 +902,7 @@ static long asComputeAllAsgPvt(void)
pasg = (ASG *)ellFirst(&pasbase->asgList);
while(pasg) {
asComputeAsgPvt(pasg);
pasg = (ASG *)ellNext((ELLNODE *)pasg);
pasg = (ASG *)ellNext(&pasg->node);
}
return(0);
}
@@ -930,7 +928,7 @@ static long asComputeAsgPvt(ASG *pasg)
pasgrule->result = ((result>.99) && (result<1.01)) ? 1 : 0;
}
}
pasgrule = (ASGRULE *)ellNext((ELLNODE *)pasgrule);
pasgrule = (ASGRULE *)ellNext(&pasgrule->node);
}
pasg->inpChanged = FALSE;
pasgmember = (ASGMEMBER *)ellFirst(&pasg->memberList);
@@ -938,9 +936,9 @@ static long asComputeAsgPvt(ASG *pasg)
pasgclient = (ASGCLIENT *)ellFirst(&pasgmember->clientList);
while(pasgclient) {
asComputePvt((ASCLIENTPVT)pasgclient);
pasgclient = (ASGCLIENT *)ellNext((ELLNODE *)pasgclient);
pasgclient = (ASGCLIENT *)ellNext(&pasgclient->node);
}
pasgmember = (ASGMEMBER *)ellNext((ELLNODE *)pasgmember);
pasgmember = (ASGMEMBER *)ellNext(&pasgmember->node);
}
return(0);
}
@@ -979,7 +977,7 @@ static long asComputePvt(ASCLIENTPVT asClientPvt)
pgphentry = gphFind(pasbase->phash,pasgclient->user,puag);
if(pgphentry) goto check_hag;
}
pasguag = (ASGUAG *)ellNext((ELLNODE *)pasguag);
pasguag = (ASGUAG *)ellNext(&pasguag->node);
}
goto next_rule;
}
@@ -995,7 +993,7 @@ check_hag:
pgphentry=gphFind(pasbase->phash,pasgclient->host,phag);
if(pgphentry) goto check_calc;
}
pasghag = (ASGHAG *)ellNext((ELLNODE *)pasghag);
pasghag = (ASGHAG *)ellNext(&pasghag->node);
}
goto next_rule;
}
@@ -1006,7 +1004,7 @@ check_calc:
trapMask = pasgrule->trapMask;
}
next_rule:
pasgrule = (ASGRULE *)ellNext((ELLNODE *)pasgrule);
pasgrule = (ASGRULE *)ellNext(&pasgrule->node);
}
pasgclient->access = access;
pasgclient->trapMask = trapMask;
@@ -1033,70 +1031,70 @@ static void asFreeAll(ASBASE *pasbase)
while(puag) {
puagname = (UAGNAME *)ellFirst(&puag->list);
while(puagname) {
pnext = ellNext((ELLNODE *)puagname);
ellDelete(&puag->list,(ELLNODE *)puagname);
free((void *)puagname);
pnext = ellNext(&puagname->node);
ellDelete(&puag->list,&puagname->node);
free(puagname);
puagname = pnext;
}
pnext = ellNext((ELLNODE *)puag);
ellDelete(&pasbase->uagList,(ELLNODE *)puag);
free((void *)puag);
pnext = ellNext(&puag->node);
ellDelete(&pasbase->uagList,&puag->node);
free(puag);
puag = pnext;
}
phag = (HAG *)ellFirst(&pasbase->hagList);
while(phag) {
phagname = (HAGNAME *)ellFirst(&phag->list);
while(phagname) {
pnext = ellNext((ELLNODE *)phagname);
ellDelete(&phag->list,(ELLNODE *)phagname);
free((void *)phagname);
pnext = ellNext(&phagname->node);
ellDelete(&phag->list,&phagname->node);
free(phagname);
phagname = pnext;
}
pnext = ellNext((ELLNODE *)phag);
ellDelete(&pasbase->hagList,(ELLNODE *)phag);
free((void *)phag);
pnext = ellNext(&phag->node);
ellDelete(&pasbase->hagList,&phag->node);
free(phag);
phag = pnext;
}
pasg = (ASG *)ellFirst(&pasbase->asgList);
while(pasg) {
free((void *)pasg->pavalue);
free(pasg->pavalue);
pasginp = (ASGINP *)ellFirst(&pasg->inpList);
while(pasginp) {
pnext = ellNext((ELLNODE *)pasginp);
ellDelete(&pasg->inpList,(ELLNODE *)pasginp);
free((void *)pasginp);
pnext = ellNext(&pasginp->node);
ellDelete(&pasg->inpList,&pasginp->node);
free(pasginp);
pasginp = pnext;
}
pasgrule = (ASGRULE *)ellFirst(&pasg->ruleList);
while(pasgrule) {
free((void *)pasgrule->calc);
free((void *)pasgrule->rpcl);
free(pasgrule->calc);
free(pasgrule->rpcl);
pasguag = (ASGUAG *)ellFirst(&pasgrule->uagList);
while(pasguag) {
pnext = ellNext((ELLNODE *)pasguag);
ellDelete(&pasgrule->uagList,(ELLNODE *)pasguag);
free((void *)pasguag);
pnext = ellNext(&pasguag->node);
ellDelete(&pasgrule->uagList,&pasguag->node);
free(pasguag);
pasguag = pnext;
}
pasghag = (ASGHAG *)ellFirst(&pasgrule->hagList);
while(pasghag) {
pnext = ellNext((ELLNODE *)pasghag);
ellDelete(&pasgrule->hagList,(ELLNODE *)pasghag);
free((void *)pasghag);
pnext = ellNext(&pasghag->node);
ellDelete(&pasgrule->hagList,&pasghag->node);
free(pasghag);
pasghag = pnext;
}
pnext = ellNext((ELLNODE *)pasgrule);
ellDelete(&pasg->ruleList,(ELLNODE *)pasgrule);
free((void *)pasgrule);
pnext = ellNext(&pasgrule->node);
ellDelete(&pasg->ruleList,&pasgrule->node);
free(pasgrule);
pasgrule = pnext;
}
pnext = ellNext((ELLNODE *)pasg);
ellDelete(&pasbase->asgList,(ELLNODE *)pasg);
free((void *)pasg);
pnext = ellNext(&pasg->node);
ellDelete(&pasbase->asgList,&pasg->node);
free(pasg);
pasg = pnext;
}
gphFreeMem(pasbase->phash);
free((void *)pasbase);
free(pasbase);
}
/*Beginning of routines called by lex code*/
@@ -1117,17 +1115,17 @@ static UAG *asUagAdd(const char *uagName)
errlogPrintf("Duplicate User Access Group named '%s'\n", uagName);
return(NULL);
}
pnext = (UAG *)ellNext((ELLNODE *)pnext);
pnext = (UAG *)ellNext(&pnext->node);
}
puag = asCalloc(1,sizeof(UAG)+strlen(uagName)+1);
ellInit(&puag->list);
puag->name = (char *)(puag+1);
strcpy(puag->name,uagName);
if(pnext==NULL) { /*Add to end of list*/
ellAdd(&pasbase->uagList,(ELLNODE *)puag);
ellAdd(&pasbase->uagList,&puag->node);
} else {
pprev = (UAG *)ellPrevious((ELLNODE *)pnext);
ellInsert(&pasbase->uagList,(ELLNODE *)pprev,(ELLNODE *)puag);
pprev = (UAG *)ellPrevious(&pnext->node);
ellInsert(&pasbase->uagList,&pprev->node,&puag->node);
}
return(puag);
}
@@ -1140,7 +1138,7 @@ static long asUagAddUser(UAG *puag,const char *user)
puagname = asCalloc(1,sizeof(UAGNAME)+strlen(user)+1);
puagname->user = (char *)(puagname+1);
strcpy(puagname->user,user);
ellAdd(&puag->list,(ELLNODE *)puagname);
ellAdd(&puag->list,&puagname->node);
return(0);
}
@@ -1161,17 +1159,17 @@ static HAG *asHagAdd(const char *hagName)
errlogPrintf("Duplicate Host Access Group named '%s'\n", hagName);
return(NULL);
}
pnext = (HAG *)ellNext((ELLNODE *)pnext);
pnext = (HAG *)ellNext(&pnext->node);
}
phag = asCalloc(1,sizeof(HAG)+strlen(hagName)+1);
ellInit(&phag->list);
phag->name = (char *)(phag+1);
strcpy(phag->name,hagName);
if(pnext==NULL) { /*Add to end of list*/
ellAdd(&pasbase->hagList,(ELLNODE *)phag);
ellAdd(&pasbase->hagList,&phag->node);
} else {
pprev = (HAG *)ellPrevious((ELLNODE *)pnext);
ellInsert(&pasbase->hagList,(ELLNODE *)pprev,(ELLNODE *)phag);
pprev = (HAG *)ellPrevious(&pnext->node);
ellInsert(&pasbase->hagList,&pprev->node,&phag->node);
}
return(phag);
}
@@ -1188,7 +1186,7 @@ static long asHagAddHost(HAG *phag,const char *host)
for (i = 0; i < len; i++) {
phagname->host[i] = (char)tolower((int)host[i]);
}
ellAdd(&phag->list, (ELLNODE *)phagname);
ellAdd(&phag->list, &phagname->node);
return 0;
}
@@ -1214,7 +1212,7 @@ static ASG *asAsgAdd(const char *asgName)
errlogPrintf("Duplicate Access Security Group named '%s'\n", asgName);
return(NULL);
}
pnext = (ASG *)ellNext((ELLNODE *)pnext);
pnext = (ASG *)ellNext(&pnext->node);
}
pasg = asCalloc(1,sizeof(ASG)+strlen(asgName)+1);
ellInit(&pasg->inpList);
@@ -1223,10 +1221,10 @@ static ASG *asAsgAdd(const char *asgName)
pasg->name = (char *)(pasg+1);
strcpy(pasg->name,asgName);
if(pnext==NULL) { /*Add to end of list*/
ellAdd(&pasbase->asgList,(ELLNODE *)pasg);
ellAdd(&pasbase->asgList,&pasg->node);
} else {
pprev = (ASG *)ellPrevious((ELLNODE *)pnext);
ellInsert(&pasbase->asgList,(ELLNODE *)pprev,(ELLNODE *)pasg);
pprev = (ASG *)ellPrevious(&pnext->node);
ellInsert(&pasbase->asgList,&pprev->node,&pasg->node);
}
return(pasg);
}
@@ -1241,7 +1239,7 @@ static long asAsgAddInp(ASG *pasg,const char *inp,int inpIndex)
strcpy(pasginp->inp,inp);
pasginp->pasg = pasg;
pasginp->inpIndex = inpIndex;
ellAdd(&pasg->inpList,(ELLNODE *)pasginp);
ellAdd(&pasg->inpList,&pasginp->node);
return(0);
}
@@ -1256,7 +1254,7 @@ static ASGRULE *asAsgAddRule(ASG *pasg,asAccessRights access,int level)
pasgrule->level = level;
ellInit(&pasgrule->uagList);
ellInit(&pasgrule->hagList);
ellAdd(&pasg->ruleList,(ELLNODE *)pasgrule);
ellAdd(&pasg->ruleList,&pasgrule->node);
return(pasgrule);
}
@@ -1267,52 +1265,56 @@ static long asAsgAddRuleOptions(ASGRULE *pasgrule,int trapMask)
return(0);
}
static long asAsgRuleUagAdd(ASGRULE *pasgrule,const char *name)
static long asAsgRuleUagAdd(ASGRULE *pasgrule, const char *name)
{
ASGUAG *pasguag;
UAG *puag;
ASBASE *pasbase = (ASBASE *)pasbasenew;
long status;
if(!pasgrule) return(0);
if (!pasgrule)
return 0;
puag = (UAG *)ellFirst(&pasbase->uagList);
while(puag) {
if(strcmp(puag->name,name)==0) break;
puag = (UAG *)ellNext((ELLNODE *)puag);
while (puag) {
if (strcmp(puag->name, name)==0)
break;
puag = (UAG *)ellNext(&puag->node);
}
if(!puag){
status = S_asLib_noUag;
errlogPrintf("No User Access Group named '%s' defined\n", name);
return(S_asLib_noUag);
if (!puag){
errlogPrintf("No User Access Group named '%s' defined\n", name);
return S_asLib_noUag;
}
pasguag = asCalloc(1,sizeof(ASGUAG));
pasguag = asCalloc(1, sizeof(ASGUAG));
pasguag->puag = puag;
ellAdd(&pasgrule->uagList,(ELLNODE *)pasguag);
return(0);
ellAdd(&pasgrule->uagList, &pasguag->node);
return 0;
}
static long asAsgRuleHagAdd(ASGRULE *pasgrule,const char *name)
static long asAsgRuleHagAdd(ASGRULE *pasgrule, const char *name)
{
ASGHAG *pasghag;
HAG *phag;
ASBASE *pasbase = (ASBASE *)pasbasenew;
long status;
if(!pasgrule) return(0);
if (!pasgrule)
return 0;
phag = (HAG *)ellFirst(&pasbase->hagList);
while(phag) {
if(strcmp(phag->name,name)==0) break;
phag = (HAG *)ellNext((ELLNODE *)phag);
while (phag) {
if (strcmp(phag->name, name)==0)
break;
phag = (HAG *)ellNext(&phag->node);
}
if(!phag){
status = S_asLib_noHag;
errlogPrintf("No Host Access Group named '%s' defined\n", name);
return(S_asLib_noHag);
if (!phag){
errlogPrintf("No Host Access Group named '%s' defined\n", name);
return S_asLib_noHag;
}
pasghag = asCalloc(1,sizeof(ASGHAG));
pasghag = asCalloc(1, sizeof(ASGHAG));
pasghag->phag = phag;
ellAdd(&pasgrule->hagList,(ELLNODE *)pasghag);
return(0);
ellAdd(&pasgrule->hagList, &pasghag->node);
return 0;
}
static long asAsgRuleCalc(ASGRULE *pasgrule,const char *calc)
@@ -1329,8 +1331,8 @@ static long asAsgRuleCalc(ASGRULE *pasgrule,const char *calc)
pasgrule->rpcl = asCalloc(1, INFIX_TO_POSTFIX_SIZE(insize));
status = postfix(pasgrule->calc, pasgrule->rpcl, &err);
if(status) {
free((void *)pasgrule->calc);
free((void *)pasgrule->rpcl);
free(pasgrule->calc);
free(pasgrule->rpcl);
pasgrule->calc = NULL;
pasgrule->rpcl = NULL;
status = S_asLib_badCalc;
@@ -1340,8 +1342,8 @@ static long asAsgRuleCalc(ASGRULE *pasgrule,const char *calc)
calcArgUsage(pasgrule->rpcl, &pasgrule->inpUsed, &stores);
/* Until someone proves stores are not dangerous, don't allow them */
if (stores) {
free((void *)pasgrule->calc);
free((void *)pasgrule->rpcl);
free(pasgrule->calc);
free(pasgrule->rpcl);
pasgrule->calc = NULL;
pasgrule->rpcl = NULL;
status = S_asLib_badCalc;

View File

@@ -3,18 +3,21 @@
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
digit [0-9]
name [a-zA-Z0-9_\-:\.\[\]<>;]
notquote [^\"]
escapequote \\\"
string {notquote}|{escapequote}
newline "\n"
backslash "\\"
doublequote "\""
comment "#"
whitespace [ \t\r]
escape {backslash}.
stringchar [^"\n\\]
name [a-zA-Z0-9_\-+:.\[\]<>;]
digit [0-9]
punctuation [(){},]
link [A-L]
link [A-L]
%{
static ASINPUTFUNCPTR *my_yyinput;
@@ -37,46 +40,55 @@ HAG { return(tokenHAG); }
ASG { return(tokenASG); }
RULE { return(tokenRULE); }
CALC { return(tokenCALC); }
INP{link} {
yylval.Int = (unsigned char)yytext[3];
yylval.Int -= 'A';
return(tokenINP);
}
}
{digit}+ { /*integer*/
yylval.Int = atoi((char *)yytext);
return(tokenINTEGER);
}
}
{name}+ { /*unquoted string*/
yylval.Str=asStrdup(yytext);
return(tokenSTRING);
}
}
\"{string}*\" { /*quoted string*/
/* making sure that neither double quote gets passed back */
{doublequote}({stringchar}|{escape})*{doublequote} { /* quoted string */
yylval.Str=asStrdup(yytext+1);
yylval.Str[strlen(yylval.Str)-1] = '\0';
return(tokenSTRING);
}
}
{doublequote}({stringchar}|{escape})*{newline} { /* bad string */
yyerror("Newline in quoted string, closing quote missing");
}
{punctuation} { return(yytext[0]); }
^#.*
{whitespace} ;
{newline} { line_num++; }
\n { line_num ++;}
{comment}.* ;
{whitespace} ;
. {
char message[40];
YY_BUFFER_STATE *dummy=0;
sprintf(message,"invalid character '%c'",yytext[0]);
if (isprint((int) yytext[0])) {
sprintf(message, "Invalid character '%c'", yytext[0]);
}
else {
sprintf(message, "Invalid character 0x%2.2x", yytext[0]);
}
yyerror(message);
/*The following suppress compiler warning messages*/
if (0) yyunput('c',(unsigned char *) message);
if (0) yy_switch_to_buffer(*dummy);
}
}
%%

View File

@@ -1009,7 +1009,7 @@ d:/user/R3.14.clean/epics/base/lib/WIN32-x86/</code></p>
<h2><a name="CommandUtils">Command Line Utilities</a></h2>
<h3><a name="acctst">acctst</a></h3>
<pre>acctst &lt;PV name&gt; [progress logging level] [channel duplication count]
<pre>acctst &lt;PV name&gt; [progress logging level] [channel duplication count]
[test repetition count] [enable preemptive callback]</pre>
<h4>Description</h4>
@@ -2079,7 +2079,7 @@ example, be beneficial when tuning an archiver installation.</p>
<p>Significant performance gains can be realized when the CA client library
doesn't wait for a response to return from the server after each request. All
requests which require interaction with a CA server are accumulated (buffered)
and not forwarded to the IOC until one of <code>ca_flush_io()</code>,
and not forwarded to the IOC until one of <code>ca_flush_io()</code>,
<code>ca_pend_io()</code>, <code>ca_pend_event()</code>, or
<code>ca_sg_block()</code> are called allowing several operations to be
efficiently sent over the network together. Any process variable values written
@@ -2103,16 +2103,16 @@ shouldn't test the success of a CA function call by checking to see if the
returned value is zero as is the UNIX convention. Below are several methods to
test CA function returns. See <a href="#ca_signal"><code>ca_signal()</code> and
<code>SEVCHK()</code></a> for more information on this topic.</p>
<pre>status = ca_XXXX();
SEVCHK( status, "ca_XXXX() returned failure status");
<pre>status = ca_XXXX();
SEVCHK( status, "ca_XXXX() returned failure status");
if ( status &amp; CA_M_SUCCESS ) {
printf ( "The requested ca_XXXX() operation didn't complete successfully");
}
if ( status &amp; CA_M_SUCCESS ) {
printf ( "The requested ca_XXXX() operation didn't complete successfully");
}
if ( status != ECA_NORMAL ) {
if ( status != ECA_NORMAL ) {
printf("The requested ca_XXXX() operation didn't complete successfully because \"%s\"\n",
ca_message ( status ) );
ca_message ( status ) );
}</pre>
<h3><a name="Channel">Channel Access Data Types</a></h3>
@@ -2285,7 +2285,7 @@ int main ( int argc, char ** argv )
unsigned nBytes;
unsigned elementCount;
char timeString[32];
unsigned i;
unsigned i;
chid chan;
double sum;
int status;
@@ -2328,7 +2328,7 @@ int main ( int argc, char ** argv )
epicsTimeToStrftime ( timeString, sizeof ( timeString ),
"%a %b %d %Y %H:%M:%S.%f", &amp; pTD-&gt;stamp );
printf ( "The sum of elements in %s at %s was %f\n",
printf ( "The sum of elements in %s at %s was %f\n",
argv[1], timeString, sum );
ca_clear_channel ( chan );
@@ -2359,7 +2359,7 @@ executing within the user's callback function.</p>
<pre>typedef struct event_handler_args {
void *usr; /* user argument supplied with request */
chanId chid; /* channel id */
long type; /* the type of the item returned */
long type; /* the type of the item returned */
long count; /* the element count of the item returned */
const void *dbr; /* a pointer to the item returned */
int status; /* ECA_XXX status of the requested op from the server */
@@ -2382,7 +2382,7 @@ attached to the request, an exception handler is executed in the client. The
default exception handler prints a message on the console and exits if the
exception condition is severe. Certain internal exceptions within the CA client
library, and failures detected by the SEVCHK macro may also cause the exception
handler to be invoked. To modify this behavior see
handler to be invoked. To modify this behavior see
<code><a href="#ca_add_exception_event">ca_add_exception_event</a>()</code>.</p>
<h3><a name="Server">Server and Client Share the Same Address Space on The Same
@@ -2674,6 +2674,14 @@ automatically released by the system when the process exits and
vxWorks or RTEMS no cleanup occurs unless the application calls
<code>ca_context_destroy()</code>.</p>
<p>Note: This operation blocks until any user callbacks for any channel
created in the current context have run to completion. If callbacks take a
lock (mutex) then it is the user's responsibility to ensure that this lock
is not held when <code>ca_clear_context()</code> is called, otherwise a
deadlock may ensue. (See also
<code><a href="#ca_clear_channel">ca_clear_channel</a>()</code> and
<code><a href="#ca_clear_event">ca_clear_subscription</a>()</code>.)</p>
<h4>Returns</h4>
<p>ECA_NORMAL - Normal successful completion</p>
@@ -2746,7 +2754,7 @@ time.</p>
</dl>
<dl>
<dt><code>USERFUNC</code></dt>
<dd>Optional address of the user's callback function to be run when the
<dd>Optional pointer to the user's callback function to be run when the
connection state changes. Casual users of channel access may decide to
set this field to null or 0 if they do not need to have a callback
function run in response to each connection state change event.
@@ -2819,6 +2827,12 @@ efficiently sent over the network in one message.</p>
clearing a channel does shutdown and reclaim any channel state change event
subscriptions (monitors) registered with the channel.</p>
<p>Note: This operation blocks until any user callbacks for this channel
have run to completion. If callbacks take a lock (mutex) then it is the
user's responsibility to ensure that this lock is not held when
<code>ca_clear_channel()</code> is called, otherwise a deadlock may ensue.
(See also <code><a href="#ca_clear_event">ca_clear_subscription</a>()</code>.)</p>
<h4>Arguments</h4>
<dl>
<dt><code>CHID</code></dt>
@@ -2833,16 +2847,16 @@ subscriptions (monitors) registered with the channel.</p>
<h3><code><a name="ca_put">ca_put()</a></code></h3>
<pre>#include &lt;cadef.h&gt;
int ca_put ( chtype TYPE,
chid CHID, void *PVALUE );
int ca_array_put ( chtype TYPE, unsigned long COUNT,
int ca_put ( chtype TYPE,
chid CHID, void *PVALUE );
int ca_array_put ( chtype TYPE, unsigned long COUNT,
chid CHID, const void *PVALUE);
typedef void ( caEventCallBackFunc ) (struct event_handler_args);
int ca_put_callback ( chtype TYPE,
chid CHID, const void *PVALUE,
caEventCallBackFunc PFUNC, void *USERARG );
int ca_array_put_callback ( chtype TYPE, unsigned long COUNT,
chid CHID, const void *PVALUE,
int ca_put_callback ( chtype TYPE,
chid CHID, const void *PVALUE,
caEventCallBackFunc PFUNC, void *USERARG );
int ca_array_put_callback ( chtype TYPE, unsigned long COUNT,
chid CHID, const void *PVALUE,
caEventCallBackFunc PFUNC, void *USERARG );</pre>
<h4>Description</h4>
@@ -2921,7 +2935,7 @@ but they do not cause the record to be processed.</p>
</dl>
<dl>
<dt><code>PFUNC</code></dt>
<dd>address of <a href="#User">user supplied callback function</a> to be
<dd>Pointer to a <a href="#User">user supplied callback function</a> to be
run when the requested operation completes</dd>
</dl>
<dl>
@@ -3029,7 +3043,7 @@ when a CA get request is initiated.</p>
</dl>
<dl>
<dt><code>USERFUNC</code></dt>
<dd>Address of <a href="#User">user supplied callback function</a> to be
<dd>Pointer to a <a href="#User">user supplied callback function</a> to be
run when the requested operation completes.</dd>
</dl>
<dl>
@@ -3069,7 +3083,7 @@ when a CA get request is initiated.</p>
typedef void ( caEventCallBackFunc ) (struct event_handler_args);
int ca_create_subscription ( chtype TYPE, unsigned long COUNT,
chid CHID, unsigned long MASK,
caEventCallBackFunc USERFUNC, void *USERARG,
caEventCallBackFunc USERFUNC, void *USERARG,
evid *PEVID );</pre>
<h4>Description</h4>
@@ -3130,8 +3144,8 @@ indicating the current state of the channel.</p>
<dd>channel identifier</dd>
</dl>
<dl>
<dt><code>USRERFUNC</code></dt>
<dd>The address of <a href="#User">user supplied callback function</a> to
<dt><code>USERFUNC</code></dt>
<dd>Pointer to a <a href="#User">user supplied callback function</a> to
be invoked with each subscription update.</dd>
</dl>
<dl>
@@ -3153,7 +3167,7 @@ indicating the current state of the channel.</p>
<dt><code>MASK</code></dt>
<dd>A mask with bits set for each of the event trigger types requested. The
event trigger mask must be a <em>bitwise or</em> of one or more of the
following constants.
following constants.
<ul>
<li>DBE_VALUE - Trigger events when the channel value exceeds the
monitor dead band</li>
@@ -3200,6 +3214,13 @@ and not forwarded to the server until one of <code>ca_flush_io()</code>, <code>c
<code>ca_pend_event()</code>, or <code>ca_sg_block()</code> are called. This allows several requests to be
efficiently sent together in one message.</p>
<p>Note: This operation blocks until any user callbacks for this channel
have run to completion. If callbacks take a lock (mutex) then it is the
user's responsibility to ensure that this lock is not held when
<code>ca_clear_subscription()</code> is called, otherwise a deadlock may
ensue. (See also <code><a
href="#ca_clear_channel">ca_clear_channel</a>()</code>.)</p>
<h4>Arguments</h4>
<dl>
<dt>EVID</dt>
@@ -3364,7 +3385,7 @@ becomes full.</p>
<h3><code><a name="ca_signal">ca_signal()</a></code></h3>
<pre>#include &lt;cadef.h&gt;
int ca_signal ( long CA_STATUS, const char * CONTEXT_STRING );
int ca_signal ( long CA_STATUS, const char * CONTEXT_STRING );
void SEVCHK( CA_STATUS, CONTEXT_STRING );</pre>
<h4>Description</h4>
@@ -3381,7 +3402,7 @@ recommended error handler for simple applications which do not wish to write
code testing the status returned from each channel access call.</p>
<h4>Examples</h4>
<pre>status = ca_context_create (...);
<pre>status = ca_context_create (...);
SEVCHK ( status, "Unable to create a CA client context" );</pre>
<p>If the application only wishes to print the message associated with an error
@@ -3405,7 +3426,7 @@ this purpose.</p>
<h3><code><a
name="ca_add_exception_event">ca_add_exception_event()</a></code></h3>
<pre>#include &lt;cadef.h&gt;
<pre>#include &lt;cadef.h&gt;
typedef void (*pCallback) ( struct exception_handler_args HANDLERARGS );
int ca_add_exception_event ( pCallback USERFUNC, void *USERARG );</pre>
@@ -3429,7 +3450,7 @@ field should not be used.</p>
<h4>Arguments</h4>
<dl>
<dt><code>USERFUNC</code></dt>
<dd>Address of user callback function to be executed when an exceptions
<dd>Pointer to a user callback function to be executed when exceptions
occur. Passing a null value causes the default exception handler to be
reinstalled. The following structure is passed by value to the user's
callback function. Currently, the <code>op</code> field can be one of
@@ -3564,7 +3585,7 @@ default handler uses fprintf to send messages to 'stderr'.</p>
<h4>Arguments</h4>
<dl>
<dt><code>PFUNC</code></dt>
<dd>The address of a user supplied callback handler to be invoked when CA
<dd>A pointer to a user supplied callback handler to be invoked when CA
prints diagnostic messages. Installing a null pointer will cause the
default callback handler to be reinstalled.</dd>
</dl>
@@ -3612,9 +3633,9 @@ specified channel.</p>
</dl>
<dl>
<dt><code>PFUNC</code></dt>
<dd>Address of user supplied callback function. A null pointer uninstalls
<dd>Pointer to a user supplied callback function. A null pointer uninstalls
the current handler. The following arguments are passed <em>by value</em>
to the supplied callback handler.
to the supplied callback handler.
<pre>typedef struct ca_access_rights {
unsigned read_access:1;
unsigned write_access:1;
@@ -3954,8 +3975,8 @@ type.</p>
prints diagnostics to standard out.</p>
<h4>Examples</h4>
<pre>void ca_test_event ();
status = ca_create_subscription ( type, chid, ca_test_event, NULL, NULL );
<pre>void ca_test_event ();
status = ca_create_subscription ( type, chid, ca_test_event, NULL, NULL );
SEVCHK ( status, .... );</pre>
<h4>See Also</h4>
@@ -3989,8 +4010,8 @@ outstanding within them at any given time.</p>
</dl>
<h4>Examples</h4>
<pre>CA_SYNC_GID gid;
status = ca_sg_create ( &amp;gid );
<pre>CA_SYNC_GID gid;
status = ca_sg_create ( &amp;gid );
SEVCHK ( status, Sync group create failed );</pre>
<h4>Returns</h4>
@@ -4028,8 +4049,8 @@ int ca_sg_delete ( CA_SYNC_GID GID );</pre>
</dl>
<h4>Examples</h4>
<pre>CA_SYNC_GID gid;
status = ca_sg_delete ( gid );
<pre>CA_SYNC_GID gid;
status = ca_sg_delete ( gid );
SEVCHK ( status, Sync group delete failed );</pre>
<h4>Returns</h4>
@@ -4140,7 +4161,7 @@ will not block unless additional subsequent requests are made.</p>
</dl>
<h4>Examples</h4>
<pre>CA_SYNC_GID gid;
<pre>CA_SYNC_GID gid;
status = ca_sg_reset(gid);</pre>
<h4>Returns</h4>
@@ -4153,7 +4174,7 @@ status = ca_sg_reset(gid);</pre>
<pre>#include &lt;cadef.h&gt;
int ca_sg_put ( CA_SYNC_GID GID, chtype TYPE,
chid CHID, void *PVALUE );
int ca_sg_array_put ( CA_SYNC_GID GID, chtype TYPE,
int ca_sg_array_put ( CA_SYNC_GID GID, chtype TYPE,
unsigned long COUNT, chid CHID, void *PVALUE );</pre>
<p>Write a value, or array of values, to a channel and increment the outstanding
@@ -4294,7 +4315,7 @@ reissued.</p>
<h3><code><a name="ca_client_status">ca_client_status()</a></code></h3>
<pre>int ca_client_status ( unsigned level );
int ca_context_status ( struct ca_client_context *CONTEXT,
int ca_context_status ( struct ca_client_context *CONTEXT,
unsigned LEVEL );</pre>
<h4>Description</h4>

View File

@@ -127,21 +127,10 @@ const char * ca_message_text []
static epicsThreadOnceId caClientContextIdOnce = EPICS_THREAD_ONCE_INIT;
extern "C" void ca_client_exit_handler (void *)
{
if ( caClientContextId ) {
epicsThreadPrivateDelete ( caClientContextId );
caClientContextId = 0;
}
}
// runs once only for each process
extern "C" void ca_init_client_context ( void * )
{
caClientContextId = epicsThreadPrivateCreate ();
if ( caClientContextId ) {
epicsAtExit ( ca_client_exit_handler,0 );
}
}
/*

View File

@@ -635,11 +635,13 @@ void cac::transferChanToVirtCircuit (
// must occur before moving to new iiu
pChan->getPIIU(guard)->uninstallChanDueToSuccessfulSearchResponse (
guard, *pChan, currentTime );
piiu->installChannel (
guard, *pChan, sid, typeCode, count );
if ( piiu ) {
piiu->installChannel (
guard, *pChan, sid, typeCode, count );
if ( newIIU ) {
piiu->start ( guard );
if ( newIIU ) {
piiu->start ( guard );
}
}
}
@@ -1304,9 +1306,11 @@ void cac::pvMultiplyDefinedNotify ( msgForMultiplyDefinedPV & mfmdpv,
callbackManager mgr ( this->notify, this->cbMutex );
epicsGuard < epicsMutex > guard ( this->mutex );
this->exception ( mgr.cbGuard, guard, ECA_DBLCHNL, buf, __FILE__, __LINE__ );
// remove from the list under lock
this->msgMultiPVList.remove ( mfmdpv );
}
// remove from the list and delete msg object
this->msgMultiPVList.remove ( mfmdpv );
// delete msg object
mfmdpv.~msgForMultiplyDefinedPV ();
this->mdpvFreeList.release ( & mfmdpv );
}

View File

@@ -24,7 +24,7 @@
DBE_ARCHIVE (DBE_LOG)
Trigger an event when an archive significant change in the channel's
valuue occurs. Relies on the archiver monitor deadband field under DCT.
value occurs. Relies on the archiver monitor deadband field under DCT.
DBE_ALARM
Trigger an event when the alarm state changes

View File

@@ -639,7 +639,7 @@ not follow this pattern, but are still printable strings.
=item [1] R3.14 Channel Access Reference Manual by Jeffrey O. Hill
L<http://www.aps.anl.gov/epics/base/R3-14/12-docs/CAref.html>
L<https://epics.anl.gov/base/R3-14/12-docs/CAref.html>
=back

View File

@@ -66,10 +66,6 @@ ifdef T_A
$(RM) $@ $@_new
$(PERL) $(XSUBPP) -typemap $(EXTUTILS)/typemap $< > $@_new && $(MV) $@_new $@
%.html: ../%.pm
$(RM) $@
podchecker $< && pod2html --infile=$< --outfile=$@
$(INSTALL_PERL_MODULES)/$(PERL_ARCHPATH)/%: %
$(ECHO) "Installing loadable shared library $@"
@$(INSTALL_LIBRARY) -d -m $(LIB_PERMISSIONS) $< $(INSTALL_PERL_MODULES)/$(PERL_ARCHPATH)

View File

@@ -20,13 +20,16 @@ $Getopt::Std::OUTPUT_HELP_VERSION = 1;
HELP_MESSAGE() unless getopts('0:ac:d:e:f:F:g:hnsStw:');
HELP_MESSAGE() if $opt_h;
die "caget: -c option takes a positive number\n"
die "caget.pl: -c option takes a positive number\n"
unless looks_like_number($opt_c) && $opt_c >= 0;
die "No pv name specified. ('caget -h' gives help.)\n"
die "No pv name specified. ('caget.pl -h' gives help.)\n"
unless @ARGV;
my @chans = map { CA->new($_); } @ARGV;
my @chans = map { CA->new($_); } grep { $_ ne '' } @ARGV;
die "caget.pl: Please provide at least one non-empty pv name\n"
unless @chans;
eval { CA->pend_io($opt_w); };
if ($@) {

View File

@@ -16,10 +16,13 @@ $Getopt::Std::OUTPUT_HELP_VERSION = 1;
HELP_MESSAGE() unless getopts('hw:');
HELP_MESSAGE() if $opt_h;
die "No pv name specified. ('cainfo -h' gives help.)\n"
die "No pv name specified. ('cainfo.pl -h' gives help.)\n"
unless @ARGV;
my @chans = map { CA->new($_); } @ARGV;
my @chans = map { CA->new($_); } grep { $_ ne '' } @ARGV;
die "cainfo.pl: Please provide at least one non-empty pv name\n"
unless @chans;
eval {
CA->pend_io($opt_w);

View File

@@ -20,14 +20,17 @@ $Getopt::Std::OUTPUT_HELP_VERSION = 1;
HELP_MESSAGE() unless getopts('0:c:e:f:F:g:hm:nsSw:');
HELP_MESSAGE() if $opt_h;
die "caget: -c option takes a positive number\n"
die "camonitor.pl: -c option takes a positive number\n"
unless looks_like_number($opt_c) && $opt_c >= 0;
die "No pv name specified. ('camonitor -h' gives help.)\n"
die "No pv name specified. ('camonitor.pl -h' gives help.)\n"
unless @ARGV;
my %monitors;
my @chans = map { CA->new($_, \&conn_callback); } @ARGV;
my @chans = map { CA->new($_, \&conn_callback); } grep { $_ ne '' } @ARGV;
die "camonitor.pl: Please provide at least one non-empty pv name\n"
unless @chans;
my $fmt = ($opt_F eq ' ') ? "%-30s %s\n" : "%s$opt_F%s\n";

View File

@@ -17,11 +17,13 @@ $Getopt::Std::OUTPUT_HELP_VERSION = 1;
HELP_MESSAGE() unless getopts('achlnsStw:');
HELP_MESSAGE() if $opt_h;
die "No pv name specified. ('caput -h' gives help.)\n"
die "No pv name specified. ('caput.pl -h' gives help.)\n"
unless @ARGV;
my $pv = shift;
die "caput.pl: Empty pv name given.\n"
unless $pv ne '';
die "No value specified. ('caput -h' gives help.)\n"
die "No value specified. ('caput.pl -h' gives help.)\n"
unless @ARGV;
my $chan = CA->new($pv);

View File

@@ -74,10 +74,9 @@ LIBSRCS += casStreamIO.cc
LIBSRCS += ipIgnoreEntry.cc
# There is a bug in some vxWorks compilers that these work around:
ifeq ($(VX_GNU_VERSION), 4.1.2)
casStreamOS_CXXFLAGS_vxWorks-ppc604_altivec = -O0
casStreamOS_CXXFLAGS_vxWorks-ppc604_long = -O0
casStreamOS_CXXFLAGS_vxWorks-ppc604 = -O0
ifeq ($(VXWORKS_VERSION)$(filter -mcpu=604,$(ARCH_DEP_CFLAGS)), 6.6-mcpu=604)
casDGIntfOS_CXXFLAGS = -fno-inline
casStreamOS_CXXFLAGS = -fno-inline
endif
LIBSRCS_vxWorks += templateInstances.cpp

View File

@@ -646,6 +646,11 @@ caStatus casDGClient::processDG ()
if ( status != S_cas_success ) {
break;
}
if ( this->in.bytesPresent () > 0 && dgInBytesConsumed == 0 && status == S_cas_success ) {
this->in.removeMsg ( this->in.bytesPresent() );
}
}
return status;
}

View File

@@ -530,8 +530,20 @@ caStatus casStrmClient::readResponse ( epicsGuard < casClientMutex > & guard,
pChan->getCID(), status, ECA_GETFAIL );
}
aitUint32 elementCount = 0;
if (desc.isContainer()) {
aitUint32 index;
int gdds = gddApplicationTypeTable::app_table.mapAppToIndex
( desc.applicationType(), gddAppType_value, index );
if ( gdds ) {
return S_cas_badType;
}
elementCount = desc.getDD(index)->getDataSizeElements();
} else {
elementCount = desc.getDataSizeElements();
}
ca_uint32_t count = (msg.m_count == 0) ?
(ca_uint32_t)desc.getDataSizeElements() :
(ca_uint32_t)elementCount :
msg.m_count;
void * pPayload;
@@ -659,8 +671,20 @@ caStatus casStrmClient::readNotifyResponse ( epicsGuard < casClientMutex > & gua
return ecaStatus;
}
aitUint32 elementCount = 0;
if (desc.isContainer()) {
aitUint32 index;
int gdds = gddApplicationTypeTable::app_table.mapAppToIndex
( desc.applicationType(), gddAppType_value, index );
if ( gdds ) {
return S_cas_badType;
}
elementCount = desc.getDD(index)->getDataSizeElements();
} else {
elementCount = desc.getDataSizeElements();
}
ca_uint32_t count = (msg.m_count == 0) ?
(ca_uint32_t)desc.getDataSizeElements() :
(ca_uint32_t)elementCount :
msg.m_count;
void *pPayload;

View File

@@ -4,7 +4,7 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
//
@@ -32,7 +32,7 @@ const unsigned caServerConnectPendQueueSize = 5u;
//
// casIntfIO::casIntfIO()
//
casIntfIO::casIntfIO ( const caNetAddr & addrIn ) :
casIntfIO::casIntfIO ( const caNetAddr & addrIn ) :
sock ( INVALID_SOCKET ),
addr ( addrIn.getSockIP() )
{
@@ -40,80 +40,79 @@ casIntfIO::casIntfIO ( const caNetAddr & addrIn ) :
osiSocklen_t addrSize;
bool portChange;
if ( ! osiSockAttach () ) {
throw S_cas_internal;
}
if ( ! osiSockAttach () ) {
throw S_cas_internal;
}
/*
* Setup the server socket
*/
this->sock = epicsSocketCreate ( AF_INET, SOCK_STREAM, IPPROTO_TCP );
if (this->sock==INVALID_SOCKET) {
/*
* Setup the server socket
*/
this->sock = epicsSocketCreate ( AF_INET, SOCK_STREAM, IPPROTO_TCP );
if (this->sock == INVALID_SOCKET) {
char sockErrBuf[64];
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
printf ( "No socket error was %s\n", sockErrBuf );
throw S_cas_noFD;
}
printf ( "No socket error was %s\n", sockErrBuf );
throw S_cas_noFD;
}
epicsSocketEnableAddressReuseDuringTimeWaitState ( this->sock );
status = bind ( this->sock,
reinterpret_cast <sockaddr *> (&this->addr),
sizeof(this->addr) );
if (status<0) {
if (SOCKERRNO == SOCK_EADDRINUSE) {
//
// enable assignment of a default port
// (so the getsockname() call below will
// work correctly)
//
this->addr.sin_port = ntohs (0);
status = bind(
status = bind ( this->sock,
reinterpret_cast <sockaddr *> (&this->addr),
sizeof(this->addr) );
if (status < 0) {
if (SOCKERRNO == SOCK_EADDRINUSE ||
SOCKERRNO == SOCK_EACCES) {
//
// enable assignment of a default port
// (so the getsockname() call below will
// work correctly)
//
this->addr.sin_port = ntohs (0);
status = bind(
this->sock,
reinterpret_cast <sockaddr *> (&this->addr),
sizeof(this->addr) );
}
if (status<0) {
}
if (status < 0) {
char sockErrBuf[64];
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
char buf[64];
ipAddrToA (&this->addr, buf, sizeof(buf));
errPrintf ( S_cas_bindFail,
__FILE__, __LINE__,
"- bind TCP IP addr=%s failed because %s",
buf, sockErrBuf );
char buf[64];
ipAddrToA (&this->addr, buf, sizeof(buf));
errlogPrintf ( "CAS: Socket bind TCP to %s failed with %s",
buf, sockErrBuf );
epicsSocketDestroy (this->sock);
throw S_cas_bindFail;
}
throw S_cas_bindFail;
}
portChange = true;
}
}
else {
portChange = false;
}
addrSize = ( osiSocklen_t ) sizeof (this->addr);
status = getsockname (
this->sock,
reinterpret_cast <sockaddr *> ( &this->addr ),
addrSize = ( osiSocklen_t ) sizeof (this->addr);
status = getsockname (
this->sock,
reinterpret_cast <sockaddr *> ( &this->addr ),
&addrSize );
if (status) {
if (status) {
char sockErrBuf[64];
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
errlogPrintf ( "CAS: getsockname() error %s\n",
sockErrBuf );
errlogPrintf ( "CAS: getsockname() error %s\n",
sockErrBuf );
epicsSocketDestroy (this->sock);
throw S_cas_internal;
}
throw S_cas_internal;
}
//
// be sure of this now so that we can fetch the IP
// address and port number later
//
//
// be sure of this now so that we can fetch the IP
// address and port number later
//
assert (this->addr.sin_family == AF_INET);
if ( portChange ) {
errlogPrintf ( "cas warning: Configured TCP port was unavailable.\n");
errlogPrintf ( "cas warning: Using dynamically assigned TCP port %hu,\n",
errlogPrintf ( "cas warning: Using dynamically assigned TCP port %hu,\n",
ntohs (this->addr.sin_port) );
errlogPrintf ( "cas warning: but now two or more servers share the same UDP port.\n");
errlogPrintf ( "cas warning: Depending on your IP kernel this server may not be\n" );
@@ -121,12 +120,12 @@ casIntfIO::casIntfIO ( const caNetAddr & addrIn ) :
}
status = listen(this->sock, caServerConnectPendQueueSize);
if(status < 0) {
if (status < 0) {
char sockErrBuf[64];
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
errlogPrintf ( "CAS: listen() error %s\n", sockErrBuf );
errlogPrintf ( "CAS: listen() error %s\n", sockErrBuf );
epicsSocketDestroy (this->sock);
throw S_cas_internal;
throw S_cas_internal;
}
}
@@ -135,17 +134,17 @@ casIntfIO::casIntfIO ( const caNetAddr & addrIn ) :
//
casIntfIO::~casIntfIO()
{
if (this->sock != INVALID_SOCKET) {
epicsSocketDestroy (this->sock);
}
if (this->sock != INVALID_SOCKET) {
epicsSocketDestroy (this->sock);
}
osiSockRelease ();
osiSockRelease ();
}
//
// newStreamIO::newStreamClient()
//
casStreamOS *casIntfIO::newStreamClient ( caServerI & cas,
casStreamOS *casIntfIO::newStreamClient ( caServerI & cas,
clientBufMemoryManager & bufMgr ) const
{
static bool oneMsgFlag = false;
@@ -175,14 +174,14 @@ casStreamOS *casIntfIO::newStreamClient ( caServerI & cas,
args.sock = newSock;
casStreamOS * pOS = new casStreamOS ( cas, bufMgr, args );
if ( ! pOS ) {
errMessage ( S_cas_noMemory,
errMessage ( S_cas_noMemory,
"unable to create data structures for a new client" );
epicsSocketDestroy ( newSock );
}
else {
if ( cas.getDebugLevel() > 0u ) {
char pName[64u];
pOS->hostName ( pName, sizeof ( pName ) );
errlogPrintf ( "CAS: allocated client object for \"%s\"\n", pName );
}
@@ -197,7 +196,7 @@ void casIntfIO::setNonBlocking()
{
int status;
osiSockIoctl_t yes = true;
status = socket_ioctl(this->sock, FIONBIO, &yes); // X aCC 392
if ( status < 0 ) {
char sockErrBuf[64];

View File

@@ -541,11 +541,11 @@ int main (int argc, char *argv[])
for (n = 0; optind < argc; n++, optind++)
pvs[n].name = argv[optind] ; /* Copy PV names from command line */
connect_pvs(pvs, nPvs);
result = connect_pvs(pvs, nPvs);
/* Read and print data */
result = caget(pvs, nPvs, request, format, type, count);
if (!result)
result = caget(pvs, nPvs, request, format, type, count);
/* Shut down Channel Access */
ca_context_destroy();

View File

@@ -211,10 +211,11 @@ int main (int argc, char *argv[])
for (n = 0; optind < argc; n++, optind++)
pvs[n].name = argv[optind] ; /* Copy PV names from command line */
connect_pvs(pvs, nPvs);
result = connect_pvs(pvs, nPvs);
/* Print data */
result = cainfo(pvs, nPvs);
if (!result)
result = cainfo(pvs, nPvs);
/* Shut down Channel Access */
ca_context_destroy();

View File

@@ -81,14 +81,14 @@ static void sprint_long (char *ret, dbr_long_t val, IntFormatT outType)
}
else {
const char *fmt[4] = { /* Order must match the enum IntFormatT */
"%ld" /* dec */,
"0" /* bin, val is 0 */,
"0o%lo" /* oct */,
"0x%lX" /* hex */
"%d" /* dec */,
"0" /* bin and val is 0 */,
"0o%o" /* oct */,
"0x%X" /* hex */
};
/* Formats have long modifier, pass value as a long */
sprintf(ret, fmt[outType], (long) val);
/* dbr_long_t is actually an int on all supported platforms */
sprintf(ret, fmt[outType], (int) val);
}
}
@@ -416,6 +416,12 @@ char *dbr2str (const void *value, unsigned type)
ptsNewS = &((struct TYPE *)value)->stamp; \
ptsNewC = &tsNow; \
\
if (!tsInitS) \
{ \
tsFirst = *ptsNewS; \
tsInitS = 1; \
} \
\
switch (tsType) { \
case relative: \
ptsRefC = &tsStart; \
@@ -508,12 +514,6 @@ void print_time_val_sts (pv* pv, unsigned long reqElems)
epicsTimeGetCurrent(&tsNow);
epicsTimeToStrftime(timeText, TIMETEXTLEN, timeFormatStr, &tsNow);
if (!tsInitS)
{
tsFirst = tsNow;
tsInitS = 1;
}
if (pv->nElems <= 1 && fieldSeparator == ' ') printf("%-30s", pv->name);
else printf("%s", pv->name);
printf("%c", fieldSeparator);

View File

@@ -60,6 +60,10 @@ static void *exitCallback;
static char *threadName[NUM_CALLBACK_PRIORITIES] = {
"cbLow", "cbMedium", "cbHigh"
};
#define FULL_MSG(name) "callbackRequest: " name " ring buffer full\n"
static char *fullMessage[NUM_CALLBACK_PRIORITIES] = {
FULL_MSG("cbLow"), FULL_MSG("cbMedium"), FULL_MSG("cbHigh")
};
static unsigned int threadPriority[NUM_CALLBACK_PRIORITIES] = {
epicsThreadPriorityScanLow - 1,
epicsThreadPriorityScanLow + 4,
@@ -168,11 +172,7 @@ void callbackRequest(CALLBACK *pcallback)
epicsInterruptUnlock(lockKey);
if (!pushOK) {
char msg[48] = "callbackRequest: ";
strcat(msg, threadName[priority]);
strcat(msg, " ring buffer full\n");
epicsInterruptContextMessage(msg);
epicsInterruptContextMessage(fullMessage[priority]);
ringOverflow[priority] = TRUE;
}
epicsEventSignal(callbackSem[priority]);

View File

@@ -297,10 +297,10 @@ static void get_alarm(DBADDR *paddr, char **ppbuffer,
if (*options & DBR_AL_LONG) {
struct dbr_alLong *pal = (struct dbr_alLong*) pbuffer;
pal->upper_alarm_limit = (epicsInt32) ald.upper_alarm_limit;
pal->upper_warning_limit = (epicsInt32) ald.upper_warning_limit;
pal->lower_warning_limit = (epicsInt32) ald.lower_warning_limit;
pal->lower_alarm_limit = (epicsInt32) ald.lower_alarm_limit;
pal->upper_alarm_limit = finite(ald.upper_alarm_limit) ? (epicsInt32) ald.upper_alarm_limit : 0;
pal->upper_warning_limit = finite(ald.upper_warning_limit) ? (epicsInt32) ald.upper_warning_limit : 0;
pal->lower_warning_limit = finite(ald.lower_warning_limit) ? (epicsInt32) ald.lower_warning_limit : 0;
pal->lower_alarm_limit = finite(ald.lower_alarm_limit) ? (epicsInt32) ald.lower_alarm_limit : 0;
if (no_data)
*options ^= DBR_AL_LONG; /*Turn off option*/

View File

@@ -409,7 +409,7 @@ long epicsShareAPI dbd(const char *record_name)
precord = addr.precord;
if (! precord->bkpt & BKPT_ON_MASK) {
if (!(precord->bkpt & BKPT_ON_MASK)) {
printf(" BKPT> No breakpoint set in this record\n");
return(S_db_bkptNotSet);
}

View File

@@ -142,7 +142,6 @@ static void addAction(caLink *pca, short link_action)
if (++removesOutstanding >= removesOutstandingWarning) {
errlogPrintf("dbCa::addAction pausing, %d channels to clear\n",
removesOutstanding);
printLinks(pca);
}
while (removesOutstanding >= removesOutstandingWarning) {
epicsMutexUnlock(workListLock);
@@ -592,11 +591,16 @@ static void connectionCallback(struct connection_handler_args arg)
if (pca->gotFirstConnection) {
if (pca->nelements != ca_element_count(arg.chid) ||
pca->dbrType != ca_field_type(arg.chid)) {
/* BUG: We have no way to clear any old subscription with the
* originally chosen data type/size. That will continue
* to send us data and will result in an assert() fail.
*/
/* Let next dbCaGetLink and/or dbCaPutLink determine options */
/* Size or type changed, clear everything and let the next call
to dbCaGetLink() and/or dbCaPutLink() reset everything */
if (pca->evidNative) {
ca_clear_event(pca->evidNative);
pca->evidNative = 0;
}
if (pca->evidString) {
ca_clear_event(pca->evidString);
pca->evidString = 0;
}
plink->value.pv_link.pvlMask &=
~(pvlOptInpNative | pvlOptInpString |
pvlOptOutNative | pvlOptOutString);
@@ -970,7 +974,8 @@ static void dbCaTask(void *arg)
status = ca_add_array_event(
ca_field_type(pca->chid)+DBR_TIME_STRING,
ca_element_count(pca->chid),
pca->chid, eventCallback, pca, 0.0, 0.0, 0.0, 0);
pca->chid, eventCallback, pca, 0.0, 0.0, 0.0,
&pca->evidNative);
if (status != ECA_NORMAL) {
errlogPrintf("dbCaTask ca_add_array_event %s\n",
ca_message(status));
@@ -982,7 +987,8 @@ static void dbCaTask(void *arg)
pca->pgetString = dbCalloc(1, MAX_STRING_SIZE);
epicsMutexUnlock(pca->lock);
status = ca_add_array_event(DBR_TIME_STRING, 1,
pca->chid, eventCallback, pca, 0.0, 0.0, 0.0, 0);
pca->chid, eventCallback, pca, 0.0, 0.0, 0.0,
&pca->evidString);
if (status != ECA_NORMAL) {
errlogPrintf("dbCaTask ca_add_array_event %s\n",
ca_message(status));

View File

@@ -73,6 +73,8 @@ typedef struct caLink
char *pgetString;
void *pputNative;
char *pputString;
evid evidNative;
evid evidString;
char gotInNative;
char gotInString;
char gotOutNative;

View File

@@ -1628,7 +1628,7 @@ static long getFloatString(
char *pbuffer = (char *)pto;
float *psrc=(float *)(paddr->pfield);
long status = 0;
int precision = 6;
long precision = 6;
struct rset *prset = 0;
if(paddr) prset = dbGetRset(paddr);
@@ -1838,7 +1838,7 @@ static long getDoubleString(
char *pbuffer = (char *)pto;
double *psrc=(double *)(paddr->pfield);
long status = 0;
int precision = 6;
long precision = 6;
struct rset *prset = 0;
if(paddr) prset = dbGetRset(paddr);
@@ -3940,7 +3940,7 @@ static long putFloatString(
const float *pbuffer = (const float *)pfrom;
char *pdest=(char *)(paddr->pfield);
long status = 0;
int precision = 6;
long precision = 6;
struct rset *prset = dbGetRset(paddr);
short size=paddr->field_size;
@@ -4150,7 +4150,7 @@ static long putDoubleString(
const double *pbuffer = (const double *)pfrom;
char *pdest=(char *)(paddr->pfield);
long status = 0;
int precision = 6;
long precision = 6;
struct rset *prset = dbGetRset(paddr);
short size=paddr->field_size;

View File

@@ -90,7 +90,8 @@ struct event_user {
epicsMutexId lock;
epicsEventId ppendsem; /* Wait while empty */
epicsEventId pflush_sem; /* wait for flush */
epicsEventId pexitsem; /* wait for event task to join */
EXTRALABORFUNC *extralabor_sub;/* off load to event task */
void *extralabor_arg;/* parameter to above */
@@ -134,7 +135,9 @@ static char *EVENT_PEND_NAME = "eventTask";
static struct evSubscrip canceledEvent;
static unsigned short ringSpace ( const struct event_que *pevq )
static epicsMutexId stopSync;
static unsigned short ringSpace ( const struct event_que *pevq )
{
if ( pevq->evque[pevq->putix] == EVENTQEMPTY ) {
if ( pevq->getix > pevq->putix ) {
@@ -274,7 +277,11 @@ int epicsShareAPI dbel ( const char *pname, unsigned level )
dbEventCtx epicsShareAPI db_init_events (void)
{
struct event_user * evUser;
if (!stopSync) {
stopSync = epicsMutexMustCreate();
}
if (!dbevEventUserFreeList) {
freeListInitPvt(&dbevEventUserFreeList,
sizeof(struct event_user),8);
@@ -293,38 +300,49 @@ dbEventCtx epicsShareAPI db_init_events (void)
if (!evUser) {
return NULL;
}
/* Flag will be cleared when event task starts */
evUser->pendexit = TRUE;
evUser->firstque.evUser = evUser;
evUser->firstque.writelock = epicsMutexCreate();
if (!evUser->firstque.writelock) {
return NULL;
}
if (!evUser->firstque.writelock)
goto fail;
evUser->ppendsem = epicsEventCreate(epicsEventEmpty);
if (!evUser->ppendsem) {
epicsMutexDestroy (evUser->firstque.writelock);
return NULL;
}
if (!evUser->ppendsem)
goto fail;
evUser->pflush_sem = epicsEventCreate(epicsEventEmpty);
if (!evUser->pflush_sem) {
epicsMutexDestroy (evUser->firstque.writelock);
epicsEventDestroy (evUser->ppendsem);
return NULL;
}
if (!evUser->pflush_sem)
goto fail;
evUser->lock = epicsMutexCreate();
if (!evUser->lock) {
epicsMutexDestroy (evUser->firstque.writelock);
epicsEventDestroy (evUser->pflush_sem);
epicsEventDestroy (evUser->ppendsem);
return NULL;
}
if (!evUser->lock)
goto fail;
evUser->pexitsem = epicsEventCreate(epicsEventEmpty);
if (!evUser->pexitsem)
goto fail;
evUser->flowCtrlMode = FALSE;
evUser->extraLaborBusy = FALSE;
evUser->pSuicideEvent = NULL;
return (dbEventCtx) evUser;
fail:
if(evUser->lock)
epicsMutexDestroy (evUser->lock);
if(evUser->firstque.writelock)
epicsMutexDestroy (evUser->firstque.writelock);
if(evUser->ppendsem)
epicsEventDestroy (evUser->ppendsem);
if(evUser->pflush_sem)
epicsEventDestroy (evUser->pflush_sem);
if(evUser->pexitsem)
epicsEventDestroy (evUser->pexitsem);
freeListFree(dbevEventUserFreeList,evUser);
return NULL;
}
/* intentionally leak stopSync to avoid possible shutdown races */
/*
* DB_CLOSE_EVENTS()
*
@@ -346,10 +364,30 @@ void epicsShareAPI db_close_events (dbEventCtx ctx)
* hazardous to the system's health.
*/
epicsMutexMustLock ( evUser->lock );
evUser->pendexit = TRUE;
if(!evUser->pendexit) { /* event task running */
evUser->pendexit = TRUE;
epicsMutexUnlock ( evUser->lock );
/* notify the waiting task */
epicsEventSignal(evUser->ppendsem);
/* wait for task to exit */
epicsEventMustWait(evUser->pexitsem);
epicsMutexMustLock ( evUser->lock );
}
epicsMutexUnlock ( evUser->lock );
/* notify the waiting task */
epicsEventSignal(evUser->ppendsem);
epicsMutexMustLock (stopSync);
epicsEventDestroy(evUser->pexitsem);
epicsEventDestroy(evUser->ppendsem);
epicsEventDestroy(evUser->pflush_sem);
epicsMutexDestroy(evUser->lock);
epicsMutexUnlock (stopSync);
freeListFree(dbevEventUserFreeList, evUser);
}
/*
@@ -977,14 +1015,17 @@ static void event_task (void *pParm)
}
}
epicsEventDestroy(evUser->ppendsem);
epicsEventDestroy(evUser->pflush_sem);
epicsMutexDestroy(evUser->lock);
freeListFree(dbevEventUserFreeList, evUser);
taskwdRemove(epicsThreadGetIdSelf());
/* use stopSync to ensure pexitsem is not destroy'd
* until epicsEventSignal() has returned.
*/
epicsMutexMustLock (stopSync);
epicsEventSignal(evUser->pexitsem);
epicsMutexUnlock(stopSync);
return;
}
@@ -1008,7 +1049,6 @@ int epicsShareAPI db_start_events (
return DB_EVENT_OK;
}
evUser->pendexit = FALSE;
evUser->init_func = init_func;
evUser->init_func_arg = init_func_arg;
if (!taskname) {
@@ -1022,6 +1062,7 @@ int epicsShareAPI db_start_events (
epicsMutexUnlock ( evUser->lock );
return DB_EVENT_ERROR;
}
evUser->pendexit = FALSE;
epicsMutexUnlock ( evUser->lock );
return DB_EVENT_OK;
}

View File

@@ -525,10 +525,10 @@ long epicsShareAPI dblsr(char *recordname,int level)
printf(" Not Locked\n");
} else {
printf(" thread %p",plockSet->thread_id);
if(! plockSet->precord || !plockSet->precord->name)
printf(" NULL record or record name\n");
if(! plockSet->precord)
printf(" NULL record\n");
else
printf(" record %s\n",plockSet->precord->name);
printf(" record %s\n",plockSet->precord->name);
}
if(level==0) { if(recordname) break; continue; }
for(plockRecord = (lockRecord *)ellFirst(&plockSet->lockRecordList);

View File

@@ -148,8 +148,11 @@ static void scanShutdown(void *arg)
interruptAccept = FALSE;
for (i = 0; i < nPeriodic; i++) {
papPeriodic[i]->scanCtl = ctlExit;
epicsEventSignal(papPeriodic[i]->loopEvent);
periodic_scan_list *ppsl = papPeriodic[i];
if (!ppsl) continue;
ppsl->scanCtl = ctlExit;
epicsEventSignal(ppsl->loopEvent);
epicsEventWait(startStopEvent);
}
@@ -182,16 +185,24 @@ void scanRun(void)
interruptAccept = TRUE;
scanCtl = ctlRun;
for (i = 0; i < nPeriodic; i++)
papPeriodic[i]->scanCtl = ctlRun;
for (i = 0; i < nPeriodic; i++) {
periodic_scan_list *ppsl = papPeriodic[i];
if (!ppsl) continue;
ppsl->scanCtl = ctlRun;
}
}
void scanPause(void)
{
int i;
for (i = nPeriodic - 1; i >= 0; --i)
papPeriodic[i]->scanCtl = ctlPause;
for (i = nPeriodic - 1; i >= 0; --i) {
periodic_scan_list *ppsl = papPeriodic[i];
if (!ppsl) continue;
ppsl->scanCtl = ctlPause;
}
scanCtl = ctlPause;
interruptAccept = FALSE;
@@ -275,9 +286,11 @@ void scanAdd(struct dbCommon *precord)
piosl += prio; /* get piosl for correct priority*/
addToList(precord, &piosl->scan_list);
} else if (scan >= SCAN_1ST_PERIODIC) {
addToList(precord, &papPeriodic[scan - SCAN_1ST_PERIODIC]->scan_list);
periodic_scan_list *ppsl = papPeriodic[scan - SCAN_1ST_PERIODIC];
if (ppsl)
addToList(precord, &ppsl->scan_list);
}
return;
}
void scanDelete(struct dbCommon *precord)
@@ -348,28 +361,48 @@ void scanDelete(struct dbCommon *precord)
piosl += prio; /*get piosl for correct priority*/
deleteFromList(precord, &piosl->scan_list);
} else if (scan >= SCAN_1ST_PERIODIC) {
deleteFromList(precord, &papPeriodic[scan - SCAN_1ST_PERIODIC]->scan_list);
periodic_scan_list *ppsl = papPeriodic[scan - SCAN_1ST_PERIODIC];
if (ppsl)
deleteFromList(precord, &ppsl->scan_list);
}
return;
}
double scanPeriod(int scan) {
periodic_scan_list *ppsl;
scan -= SCAN_1ST_PERIODIC;
if (scan < 0 || scan >= nPeriodic)
return 0.0;
return papPeriodic[scan]->period;
ppsl = papPeriodic[scan];
return ppsl ? ppsl->period : 0.0;
}
int scanppl(double period) /* print periodic list */
int scanppl(double period) /* print periodic scan list(s) */
{
periodic_scan_list *ppsl;
dbMenu *pmenu = dbFindMenu(pdbbase, "menuScan");
char message[80];
int i;
if (!pmenu || !papPeriodic) {
printf("scanppl: dbScan subsystem not initialized\n");
return -1;
}
for (i = 0; i < nPeriodic; i++) {
ppsl = papPeriodic[i];
if (ppsl == NULL) continue;
if (period > 0.0 && (fabs(period - ppsl->period) >.05)) continue;
periodic_scan_list *ppsl = papPeriodic[i];
if (!ppsl) {
const char *choice = pmenu->papChoiceValue[i + SCAN_1ST_PERIODIC];
printf("Periodic scan list for SCAN = '%s' not initialized\n",
choice);
continue;
}
if (period > 0.0 &&
(fabs(period - ppsl->period) > 0.05))
continue;
sprintf(message, "Records with SCAN = '%s' (%lu over-runs):",
ppsl->name, ppsl->overruns);
printList(&ppsl->scan_list, message);
@@ -588,7 +621,7 @@ static void periodicTask(void *arg)
if (++overruns >= 10 &&
epicsTimeDiffInSeconds(&now, &reported) > report_delay) {
errlogPrintf("\ndbScan warning from '%s' scan thread:\n"
"\tScan processing averages %.2f seconds (%.2f .. %.2f).\n"
"\tScan processing averages %.3f seconds (%.3f .. %.3f).\n"
"\tOver-runs have now happened %u times in a row.\n"
"\tTo fix this, move some records to a slower scan rate.\n",
ppsl->name, ppsl->period + overtime / overruns,
@@ -617,25 +650,30 @@ static void periodicTask(void *arg)
static void initPeriodic(void)
{
dbMenu *pmenu;
periodic_scan_list *ppsl;
dbMenu *pmenu = dbFindMenu(pdbbase, "menuScan");
int i;
pmenu = dbFindMenu(pdbbase, "menuScan");
if (!pmenu) {
epicsPrintf("initPeriodic: menuScan not present\n");
errlogPrintf("initPeriodic: menuScan not present\n");
return;
}
nPeriodic = pmenu->nChoice - SCAN_1ST_PERIODIC;
papPeriodic = dbCalloc(nPeriodic, sizeof(periodic_scan_list*));
periodicTaskId = dbCalloc(nPeriodic, sizeof(void *));
for (i = 0; i < nPeriodic; i++) {
ppsl = dbCalloc(1, sizeof(periodic_scan_list));
periodic_scan_list *ppsl = dbCalloc(1, sizeof(periodic_scan_list));
const char *choice = pmenu->papChoiceValue[i + SCAN_1ST_PERIODIC];
if (!epicsScanDouble(choice, &ppsl->period) ||
ppsl->period <= 0) {
errlogPrintf("initPeriodic: Bad menuScan choice '%s'\n", choice);
free(ppsl);
continue;
}
ppsl->scan_list.lock = epicsMutexMustCreate();
ellInit(&ppsl->scan_list.list);
ppsl->name = pmenu->papChoiceValue[i + SCAN_1ST_PERIODIC];
epicsScanDouble(ppsl->name, &ppsl->period);
ppsl->name = choice;
ppsl->scanCtl = ctlPause;
ppsl->loopEvent = epicsEventMustCreate(epicsEventEmpty);
@@ -645,10 +683,11 @@ static void initPeriodic(void)
static void spawnPeriodic(int ind)
{
periodic_scan_list *ppsl;
periodic_scan_list *ppsl = papPeriodic[ind];
char taskName[20];
ppsl = papPeriodic[ind];
if (!ppsl) return;
sprintf(taskName, "scan%g", ppsl->period);
periodicTaskId[ind] = epicsThreadCreate(
taskName, epicsThreadPriorityScanLow + ind,

View File

@@ -960,23 +960,29 @@ static void dbRecordHead(char *recordType, char *name, int visible)
static void dbRecordField(char *name,char *value)
{
DBENTRY *pdbentry;
tempListNode *ptempListNode;
long status;
DBENTRY *pdbentry;
tempListNode *ptempListNode;
long status;
if(duplicate) return;
if (duplicate) return;
ptempListNode = (tempListNode *)ellFirst(&tempList);
pdbentry = ptempListNode->item;
status = dbFindField(pdbentry,name);
if(status) {
epicsPrintf("Record \"%s\" does not have a field \"%s\"\n",
dbGetRecordName(pdbentry), name);
yyerror(NULL);
return;
if (status) {
epicsPrintf("Record \"%s\" does not have a field \"%s\"\n",
dbGetRecordName(pdbentry), name);
yyerror(NULL);
return;
}
if (pdbentry->indfield == 0) {
epicsPrintf("Can't set \"NAME\" field of record \"%s\"\n",
dbGetRecordName(pdbentry));
yyerror(NULL);
return;
}
dbTranslateEscape(value, value); /* yuck: in-place, but safe */
status = dbPutString(pdbentry,value);
if(status) {
if (status) {
epicsPrintf("Can't set \"%s.%s\" to \"%s\"\n",
dbGetRecordName(pdbentry), name, value);
yyerror(NULL);
@@ -986,33 +992,33 @@ static void dbRecordField(char *name,char *value)
static void dbRecordInfo(char *name, char *value)
{
DBENTRY *pdbentry;
tempListNode *ptempListNode;
long status;
DBENTRY *pdbentry;
tempListNode *ptempListNode;
long status;
if(duplicate) return;
if (duplicate) return;
ptempListNode = (tempListNode *)ellFirst(&tempList);
pdbentry = ptempListNode->item;
status = dbPutInfo(pdbentry,name,value);
if(status) {
epicsPrintf("Can't set \"%s\" info \"%s\" to \"%s\"\n",
if (status) {
epicsPrintf("Can't set \"%s\" info \"%s\" to \"%s\"\n",
dbGetRecordName(pdbentry), name, value);
yyerror(NULL);
return;
yyerror(NULL);
return;
}
}
static void dbRecordAlias(char *name)
{
DBENTRY *pdbentry;
tempListNode *ptempListNode;
long status;
DBENTRY *pdbentry;
tempListNode *ptempListNode;
long status;
if(duplicate) return;
if (duplicate) return;
ptempListNode = (tempListNode *)ellFirst(&tempList);
pdbentry = ptempListNode->item;
status = dbCreateAlias(pdbentry, name);
if(status) {
if (status) {
epicsPrintf("Can't create alias \"%s\" for \"%s\"\n",
name, dbGetRecordName(pdbentry));
yyerror(NULL);
@@ -1022,15 +1028,16 @@ static void dbRecordAlias(char *name)
static void dbAlias(char *name, char *alias)
{
DBENTRY dbEntry;
DBENTRY *pdbEntry = &dbEntry;
DBENTRY dbEntry;
DBENTRY *pdbEntry = &dbEntry;
dbInitEntry(pdbbase, pdbEntry);
if (dbFindRecord(pdbEntry, name)) {
epicsPrintf("Alias \"%s\" refers to unknown record \"%s\"\n",
alias, name);
yyerror(NULL);
} else if (dbCreateAlias(pdbEntry, alias)) {
}
else if (dbCreateAlias(pdbEntry, alias)) {
epicsPrintf("Can't create alias \"%s\" referring to \"%s\"\n",
alias, name);
yyerror(NULL);
@@ -1040,14 +1047,14 @@ static void dbAlias(char *name, char *alias)
static void dbRecordBody(void)
{
DBENTRY *pdbentry;
DBENTRY *pdbentry;
if(duplicate) {
duplicate = FALSE;
return;
if (duplicate) {
duplicate = FALSE;
return;
}
pdbentry = (DBENTRY *)popFirstTemp();
if(ellCount(&tempList))
yyerrorAbort("dbRecordBody: tempList not empty");
if (ellCount(&tempList))
yyerrorAbort("dbRecordBody: tempList not empty");
dbFreeEntry(pdbentry);
}

View File

@@ -18,6 +18,7 @@
#define DBFLDTYPES_GBLSOURCE
#define GUIGROUPS_GBLSOURCE
#define SPECIAL_GBLSOURCE
#include "epicsAssert.h"
#include "dbDefs.h"
#include "epicsPrint.h"
#include "errlog.h"
@@ -578,8 +579,6 @@ void epicsShareAPI dbFreeBase(dbBase *pdbbase)
dbRecordType *pdbRecordType;
dbRecordType *pdbRecordTypeNext;
dbFldDes * pdbFldDes;
dbRecordNode *pdbRecordNode;
dbRecordNode *pdbRecordNodeNext;
dbRecordAttribute *pAttribute;
dbRecordAttribute *pAttributeNext;
devSup *pdevSup;
@@ -594,133 +593,136 @@ void epicsShareAPI dbFreeBase(dbBase *pdbbase)
brkTable *pbrkTableNext;
int i;
DBENTRY dbentry;
long status;
dbInitEntry(pdbbase,&dbentry);
pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList);
while(pdbRecordType) {
pdbRecordNode = (dbRecordNode *)ellFirst(&pdbRecordType->recList);
while(pdbRecordNode) {
pdbRecordNodeNext = (dbRecordNode *)ellNext(&pdbRecordNode->node);
if(!dbFindRecord(&dbentry,pdbRecordNode->recordname))
dbDeleteRecord(&dbentry);
pdbRecordNode = pdbRecordNodeNext;
}
pdbRecordType = (dbRecordType *)ellNext(&pdbRecordType->node);
status = dbFirstRecordType(&dbentry);
while(!status) {
/* dbDeleteRecord() will remove alias or real record node.
* For real record nodes, also removes the nodes of all aliases.
* This complicates safe traversal, so we re-start iteration
* from the first record after each call.
*/
while((status = dbFirstRecord(&dbentry))==0) {
dbDeleteRecord(&dbentry);
}
assert(status==S_dbLib_recNotFound);
status = dbNextRecordType(&dbentry);
}
dbFinishEntry(&dbentry);
pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList);
while(pdbRecordType) {
for(i=0; i<pdbRecordType->no_fields; i++) {
pdbFldDes = pdbRecordType->papFldDes[i];
free((void *)pdbFldDes->prompt);
free((void *)pdbFldDes->name);
free((void *)pdbFldDes->extra);
free((void *)pdbFldDes->initial);
if(pdbFldDes->field_type==DBF_DEVICE && pdbFldDes->ftPvt) {
dbDeviceMenu *pdbDeviceMenu;
for(i=0; i<pdbRecordType->no_fields; i++) {
pdbFldDes = pdbRecordType->papFldDes[i];
free((void *)pdbFldDes->prompt);
free((void *)pdbFldDes->name);
free((void *)pdbFldDes->extra);
free((void *)pdbFldDes->initial);
if(pdbFldDes->field_type==DBF_DEVICE && pdbFldDes->ftPvt) {
dbDeviceMenu *pdbDeviceMenu;
pdbDeviceMenu = (dbDeviceMenu *)pdbFldDes->ftPvt;
free((void *)pdbDeviceMenu->papChoice);
free((void *)pdbDeviceMenu);
pdbFldDes->ftPvt=0;
}
free((void *)pdbFldDes);
}
pdevSup = (devSup *)ellFirst(&pdbRecordType->devList);
while(pdevSup) {
pdevSupNext = (devSup *)ellNext(&pdevSup->node);
ellDelete(&pdbRecordType->devList,&pdevSup->node);
free((void *)pdevSup->name);
free((void *)pdevSup->choice);
free((void *)pdevSup);
pdevSup = pdevSupNext;
}
ptext = (dbText *)ellFirst(&pdbRecordType->cdefList);
while(ptext) {
ptextNext = (dbText *)ellNext(&ptext->node);
ellDelete(&pdbRecordType->cdefList,&ptext->node);
free((void *)ptext->text);
free((void *)ptext);
ptext = ptextNext;
}
pAttribute =
(dbRecordAttribute *)ellFirst(&pdbRecordType->attributeList);
while(pAttribute) {
pAttributeNext = (dbRecordAttribute *)ellNext(&pAttribute->node);
ellDelete(&pdbRecordType->attributeList,&pAttribute->node);
free((void *)pAttribute->name);
free((void *)pAttribute->pdbFldDes);
pAttribute = pAttributeNext;
}
pdbRecordTypeNext = (dbRecordType *)ellNext(&pdbRecordType->node);
gphDelete(pdbbase->pgpHash,pdbRecordType->name,&pdbbase->recordTypeList);
ellDelete(&pdbbase->recordTypeList,&pdbRecordType->node);
free((void *)pdbRecordType->name);
free((void *)pdbRecordType->link_ind);
free((void *)pdbRecordType->papsortFldName);
free((void *)pdbRecordType->sortFldInd);
free((void *)pdbRecordType->papFldDes);
free((void *)pdbRecordType);
pdbRecordType = pdbRecordTypeNext;
pdbDeviceMenu = (dbDeviceMenu *)pdbFldDes->ftPvt;
free((void *)pdbDeviceMenu->papChoice);
free((void *)pdbDeviceMenu);
pdbFldDes->ftPvt=0;
}
free((void *)pdbFldDes);
}
pdevSup = (devSup *)ellFirst(&pdbRecordType->devList);
while(pdevSup) {
pdevSupNext = (devSup *)ellNext(&pdevSup->node);
ellDelete(&pdbRecordType->devList,&pdevSup->node);
free((void *)pdevSup->name);
free((void *)pdevSup->choice);
free((void *)pdevSup);
pdevSup = pdevSupNext;
}
ptext = (dbText *)ellFirst(&pdbRecordType->cdefList);
while(ptext) {
ptextNext = (dbText *)ellNext(&ptext->node);
ellDelete(&pdbRecordType->cdefList,&ptext->node);
free((void *)ptext->text);
free((void *)ptext);
ptext = ptextNext;
}
pAttribute =
(dbRecordAttribute *)ellFirst(&pdbRecordType->attributeList);
while(pAttribute) {
pAttributeNext = (dbRecordAttribute *)ellNext(&pAttribute->node);
ellDelete(&pdbRecordType->attributeList,&pAttribute->node);
free((void *)pAttribute->name);
free((void *)pAttribute->pdbFldDes);
free(pAttribute);
pAttribute = pAttributeNext;
}
pdbRecordTypeNext = (dbRecordType *)ellNext(&pdbRecordType->node);
gphDelete(pdbbase->pgpHash,pdbRecordType->name,&pdbbase->recordTypeList);
ellDelete(&pdbbase->recordTypeList,&pdbRecordType->node);
free((void *)pdbRecordType->name);
free((void *)pdbRecordType->link_ind);
free((void *)pdbRecordType->papsortFldName);
free((void *)pdbRecordType->sortFldInd);
free((void *)pdbRecordType->papFldDes);
free((void *)pdbRecordType);
pdbRecordType = pdbRecordTypeNext;
}
pdbMenu = (dbMenu *)ellFirst(&pdbbase->menuList);
while(pdbMenu) {
pdbMenuNext = (dbMenu *)ellNext(&pdbMenu->node);
gphDelete(pdbbase->pgpHash,pdbMenu->name,&pdbbase->menuList);
ellDelete(&pdbbase->menuList,&pdbMenu->node);
for(i=0; i< pdbMenu->nChoice; i++) {
free((void *)pdbMenu->papChoiceName[i]);
free((void *)pdbMenu->papChoiceValue[i]);
}
free((void *)pdbMenu->papChoiceName);
free((void *)pdbMenu->papChoiceValue);
free((void *)pdbMenu ->name);
free((void *)pdbMenu);
pdbMenu = pdbMenuNext;
pdbMenuNext = (dbMenu *)ellNext(&pdbMenu->node);
gphDelete(pdbbase->pgpHash,pdbMenu->name,&pdbbase->menuList);
ellDelete(&pdbbase->menuList,&pdbMenu->node);
for(i=0; i< pdbMenu->nChoice; i++) {
free((void *)pdbMenu->papChoiceName[i]);
free((void *)pdbMenu->papChoiceValue[i]);
}
free((void *)pdbMenu->papChoiceName);
free((void *)pdbMenu->papChoiceValue);
free((void *)pdbMenu ->name);
free((void *)pdbMenu);
pdbMenu = pdbMenuNext;
}
pdrvSup = (drvSup *)ellFirst(&pdbbase->drvList);
while(pdrvSup) {
pdrvSupNext = (drvSup *)ellNext(&pdrvSup->node);
ellDelete(&pdbbase->drvList,&pdrvSup->node);
free((void *)pdrvSup->name);
free((void *)pdrvSup);
pdrvSup = pdrvSupNext;
pdrvSupNext = (drvSup *)ellNext(&pdrvSup->node);
ellDelete(&pdbbase->drvList,&pdrvSup->node);
free((void *)pdrvSup->name);
free((void *)pdrvSup);
pdrvSup = pdrvSupNext;
}
ptext = (dbText *)ellFirst(&pdbbase->registrarList);
while(ptext) {
ptextNext = (dbText *)ellNext(&ptext->node);
ellDelete(&pdbbase->registrarList,&ptext->node);
free((void *)ptext->text);
free((void *)ptext);
ptext = ptextNext;
ptextNext = (dbText *)ellNext(&ptext->node);
ellDelete(&pdbbase->registrarList,&ptext->node);
free((void *)ptext->text);
free((void *)ptext);
ptext = ptextNext;
}
ptext = (dbText *)ellFirst(&pdbbase->functionList);
while(ptext) {
ptextNext = (dbText *)ellNext(&ptext->node);
ellDelete(&pdbbase->functionList,&ptext->node);
free((void *)ptext->text);
free((void *)ptext);
ptext = ptextNext;
ptextNext = (dbText *)ellNext(&ptext->node);
ellDelete(&pdbbase->functionList,&ptext->node);
free((void *)ptext->text);
free((void *)ptext);
ptext = ptextNext;
}
pvar = (dbVariableDef *)ellFirst(&pdbbase->variableList);
while(pvar) {
pvarNext = (dbVariableDef *)ellNext(&pvar->node);
ellDelete(&pdbbase->variableList,&pvar->node);
free((void *)pvar->name);
pvarNext = (dbVariableDef *)ellNext(&pvar->node);
ellDelete(&pdbbase->variableList,&pvar->node);
free((void *)pvar->name);
free((void *)pvar->type);
free((void *)pvar);
pvar = pvarNext;
free((void *)pvar);
pvar = pvarNext;
}
pbrkTable = (brkTable *)ellFirst(&pdbbase->bptList);
while(pbrkTable) {
pbrkTableNext = (brkTable *)ellNext(&pbrkTable->node);
gphDelete(pdbbase->pgpHash,pbrkTable->name,&pdbbase->bptList);
ellDelete(&pdbbase->bptList,&pbrkTable->node);
free(pbrkTable->name);
free((void *)pbrkTable->paBrkInt);
free((void *)pbrkTable);
pbrkTable = pbrkTableNext;
pbrkTableNext = (brkTable *)ellNext(&pbrkTable->node);
gphDelete(pdbbase->pgpHash,pbrkTable->name,&pdbbase->bptList);
ellDelete(&pdbbase->bptList,&pbrkTable->node);
free(pbrkTable->name);
free((void *)pbrkTable->paBrkInt);
free((void *)pbrkTable);
pbrkTable = pbrkTableNext;
}
gphFreeMem(pdbbase->pgpHash);
dbPvdFreeMem(pdbbase);

View File

@@ -19,9 +19,10 @@
#define CALCPERFORM_NARGS 12
#define CALCPERFORM_STACK 80
#define INFIX_TO_POSTFIX_SIZE(n) (n*21/6)
#define INFIX_TO_POSTFIX_SIZE(n) ((n)*21/6)
/* The above expression is an estimate of the maximum postfix buffer
* size needed for a given infix expression buffer. The actual size
* size needed for a given infix expression buffer (the argument must count
* the trailing nil byte in the input expression string). The actual size
* needed is never larger than this value, although it is actually a
* few bytes smaller for some sizes.
*

View File

@@ -116,7 +116,7 @@ epicsShareFunc void fdManager::process (double delay)
if ( ioPending ) {
struct timeval tv;
tv.tv_sec = static_cast<long> ( minDelay );
tv.tv_sec = static_cast<time_t> ( minDelay );
tv.tv_usec = static_cast<long> ( (minDelay-tv.tv_sec) * uSecPerSec );
fd_set * pReadSet = & this->fdSetsPtr[fdrRead];

View File

@@ -857,9 +857,9 @@ static void refer ( MAC_HANDLE *handle, MAC_ENTRY *entry, int level,
if ( !refentry->visited ) {
/* reference is good, use it */
if ( !handle->dirty ) {
/* copy the already-expanded value, and its error status! */
/* copy the already-expanded value, merge any error status */
cpy2val( refentry->value, &v, valend );
entry->error = refentry->error;
entry->error = entry->error || refentry->error;
} else {
/* translate raw value */
const char *rv = refentry->rawval;

View File

@@ -18,6 +18,9 @@
#include <stdexcept>
#include <stdio.h>
//#define EPICS_FREELIST_DEBUG
#define EPICS_PRIVATE_API
#define epicsExportSharedSymbols
#include "ipAddrToAsciiAsynchronous.h"
#include "epicsThread.h"
@@ -45,7 +48,6 @@ public:
< ipAddrToAsciiTransactionPrivate, 0x80 > & );
epicsPlacementDeleteOperator (( void *, tsFreeList
< ipAddrToAsciiTransactionPrivate, 0x80 > & ))
private:
osiSockAddr addr;
ipAddrToAsciiEnginePrivate & engine;
ipAddrToAsciiCallBack * pCB;
@@ -54,7 +56,7 @@ private:
void release ();
void * operator new ( size_t );
void operator delete ( void * );
friend class ipAddrToAsciiEnginePrivate;
private:
ipAddrToAsciiTransactionPrivate & operator = ( const ipAddrToAsciiTransactionPrivate & );
ipAddrToAsciiTransactionPrivate ( const ipAddrToAsciiTransactionPrivate & );
};
@@ -75,41 +77,54 @@ extern "C" {
static void ipAddrToAsciiEngineGlobalMutexConstruct ( void * );
}
// - this class executes the synchronous DNS query
// - it creates one thread
class ipAddrToAsciiEnginePrivate :
public ipAddrToAsciiEngine,
public epicsThreadRunable {
public:
ipAddrToAsciiEnginePrivate ();
virtual ~ipAddrToAsciiEnginePrivate ();
void show ( unsigned level ) const;
private:
namespace {
struct ipAddrToAsciiGlobal : public epicsThreadRunable {
ipAddrToAsciiGlobal();
virtual ~ipAddrToAsciiGlobal() {}
virtual void run ();
char nameTmp [1024];
tsFreeList
< ipAddrToAsciiTransactionPrivate, 0x80 >
tsFreeList
< ipAddrToAsciiTransactionPrivate, 0x80 >
transactionFreeList;
tsDLList < ipAddrToAsciiTransactionPrivate > labor;
mutable epicsMutex mutex;
epicsEvent laborEvent;
epicsEvent destructorBlockEvent;
epicsThread thread;
// pCurrent may be changed by any thread (worker or other)
ipAddrToAsciiTransactionPrivate * pCurrent;
// pActive may only be changed by the worker
ipAddrToAsciiTransactionPrivate * pActive;
unsigned cancelPendingCount;
bool exitFlag;
bool callbackInProgress;
static ipAddrToAsciiEnginePrivate * pEngine;
};
}
// - this class executes the synchronous DNS query
// - it creates one thread
class ipAddrToAsciiEnginePrivate :
public ipAddrToAsciiEngine {
public:
ipAddrToAsciiEnginePrivate() :refcount(1u), released(false) {}
virtual ~ipAddrToAsciiEnginePrivate () {}
void show ( unsigned level ) const;
unsigned refcount;
bool released;
static ipAddrToAsciiGlobal * pEngine;
ipAddrToAsciiTransaction & createTransaction ();
void release ();
void run ();
ipAddrToAsciiEnginePrivate ( const ipAddrToAsciiEngine & );
void release ();
private:
ipAddrToAsciiEnginePrivate ( const ipAddrToAsciiEngine & );
ipAddrToAsciiEnginePrivate & operator = ( const ipAddrToAsciiEngine & );
friend class ipAddrToAsciiEngine;
friend class ipAddrToAsciiTransactionPrivate;
friend void ipAddrToAsciiEngineGlobalMutexConstruct ( void * );
};
ipAddrToAsciiEnginePrivate * ipAddrToAsciiEnginePrivate :: pEngine = 0;
ipAddrToAsciiGlobal * ipAddrToAsciiEnginePrivate :: pEngine = 0;
static epicsThreadOnceId ipAddrToAsciiEngineGlobalMutexOnceFlag = EPICS_THREAD_ONCE_INIT;
// the users are not required to supply a show routine
@@ -124,12 +139,24 @@ ipAddrToAsciiEngine::~ipAddrToAsciiEngine () {}
static void ipAddrToAsciiEngineGlobalMutexConstruct ( void * )
{
try{
ipAddrToAsciiEnginePrivate::pEngine = new ipAddrToAsciiEnginePrivate ();
ipAddrToAsciiEnginePrivate::pEngine = new ipAddrToAsciiGlobal ();
}catch(std::exception& e){
errlogPrintf("ipAddrToAsciiEnginePrivate ctor fails with: %s\n", e.what());
}
}
void ipAddrToAsciiEngine::cleanup()
{
{
epicsGuard<epicsMutex> G(ipAddrToAsciiEnginePrivate::pEngine->mutex);
ipAddrToAsciiEnginePrivate::pEngine->exitFlag = true;
}
ipAddrToAsciiEnginePrivate::pEngine->laborEvent.signal();
ipAddrToAsciiEnginePrivate::pEngine->thread.exitWait();
delete ipAddrToAsciiEnginePrivate::pEngine;
ipAddrToAsciiEnginePrivate::pEngine = 0;
}
// for now its probably sufficent to allocate one
// DNS transaction thread for all codes sharing
// the same process that need DNS services but we
@@ -141,41 +168,78 @@ ipAddrToAsciiEngine & ipAddrToAsciiEngine::allocate ()
ipAddrToAsciiEngineGlobalMutexConstruct, 0 );
if(!ipAddrToAsciiEnginePrivate::pEngine)
throw std::runtime_error("ipAddrToAsciiEngine::allocate fails");
return * ipAddrToAsciiEnginePrivate::pEngine;
return * new ipAddrToAsciiEnginePrivate();
}
ipAddrToAsciiEnginePrivate::ipAddrToAsciiEnginePrivate () :
ipAddrToAsciiGlobal::ipAddrToAsciiGlobal () :
thread ( *this, "ipToAsciiProxy",
epicsThreadGetStackSize(epicsThreadStackBig),
epicsThreadPriorityLow ),
pCurrent ( 0 ), cancelPendingCount ( 0u ), exitFlag ( false ),
pCurrent ( 0 ), pActive ( 0 ), cancelPendingCount ( 0u ), exitFlag ( false ),
callbackInProgress ( false )
{
this->thread.start (); // start the thread
}
ipAddrToAsciiEnginePrivate::~ipAddrToAsciiEnginePrivate ()
{
{
epicsGuard < epicsMutex > guard ( this->mutex );
this->exitFlag = true;
}
this->laborEvent.signal ();
this->thread.exitWait ();
}
void ipAddrToAsciiEnginePrivate::release ()
{
bool last;
{
epicsGuard < epicsMutex > guard ( this->pEngine->mutex );
if(released)
throw std::logic_error("Engine release() called again!");
// released==true prevents new transactions
released = true;
{
// cancel any pending transactions
tsDLIter < ipAddrToAsciiTransactionPrivate > it(pEngine->labor.firstIter());
while(it.valid()) {
ipAddrToAsciiTransactionPrivate *trn = it.pointer();
++it;
if(this==&trn->engine) {
trn->pending = false;
pEngine->labor.remove(*trn);
}
}
// cancel transaction in lookup or callback
if (pEngine->pCurrent && this==&pEngine->pCurrent->engine) {
pEngine->pCurrent->pending = false;
pEngine->pCurrent = 0;
}
// wait for completion of in-progress callback
pEngine->cancelPendingCount++;
while(pEngine->pActive && this==&pEngine->pActive->engine
&& ! pEngine->thread.isCurrentThread()) {
epicsGuardRelease < epicsMutex > unguard ( guard );
pEngine->destructorBlockEvent.wait();
}
pEngine->cancelPendingCount--;
if(pEngine->cancelPendingCount)
pEngine->destructorBlockEvent.signal();
}
assert(refcount>0);
last = 0==--refcount;
}
if(last) {
delete this;
}
}
void ipAddrToAsciiEnginePrivate::show ( unsigned level ) const
{
epicsGuard < epicsMutex > guard ( this->mutex );
epicsGuard < epicsMutex > guard ( this->pEngine->mutex );
printf ( "ipAddrToAsciiEngine at %p with %u requests pending\n",
static_cast <const void *> (this), this->labor.count () );
static_cast <const void *> (this), this->pEngine->labor.count () );
if ( level > 0u ) {
tsDLIterConst < ipAddrToAsciiTransactionPrivate >
pItem = this->labor.firstIter ();
tsDLIter < ipAddrToAsciiTransactionPrivate >
pItem = this->pEngine->labor.firstIter ();
while ( pItem.valid () ) {
pItem->show ( level - 1u );
pItem++;
@@ -183,10 +247,10 @@ void ipAddrToAsciiEnginePrivate::show ( unsigned level ) const
}
if ( level > 1u ) {
printf ( "mutex:\n" );
this->mutex.show ( level - 2u );
this->pEngine->mutex.show ( level - 2u );
printf ( "laborEvent:\n" );
this->laborEvent.show ( level - 2u );
printf ( "exitFlag boolean = %u\n", this->exitFlag );
this->pEngine->laborEvent.show ( level - 2u );
printf ( "exitFlag boolean = %u\n", this->pEngine->exitFlag );
printf ( "exit event:\n" );
}
}
@@ -226,10 +290,20 @@ void ipAddrToAsciiTransactionPrivate::operator delete ( void * )
ipAddrToAsciiTransaction & ipAddrToAsciiEnginePrivate::createTransaction ()
{
return * new ( this->transactionFreeList ) ipAddrToAsciiTransactionPrivate ( *this );
epicsGuard <epicsMutex> G(this->pEngine->mutex);
if(this->released)
throw std::logic_error("createTransaction() on release()'d ipAddrToAsciiEngine");
assert(this->refcount>0);
ipAddrToAsciiTransactionPrivate *ret = new ( this->pEngine->transactionFreeList ) ipAddrToAsciiTransactionPrivate ( *this );
this->refcount++;
return * ret;
}
void ipAddrToAsciiEnginePrivate::run ()
void ipAddrToAsciiGlobal::run ()
{
epicsGuard < epicsMutex > guard ( this->mutex );
while ( ! this->exitFlag ) {
@@ -267,7 +341,7 @@ void ipAddrToAsciiEnginePrivate::run ()
// fix for lp:1580623
// a destructing cac sets pCurrent to NULL, so
// make local copy to avoid race when releasing the guard
ipAddrToAsciiTransactionPrivate *pCur = this->pCurrent;
ipAddrToAsciiTransactionPrivate *pCur = pActive = pCurrent;
this->callbackInProgress = true;
{
@@ -277,6 +351,7 @@ void ipAddrToAsciiEnginePrivate::run ()
}
this->callbackInProgress = false;
pActive = 0;
if ( this->pCurrent ) {
this->pCurrent->pending = false;
@@ -300,44 +375,53 @@ ipAddrToAsciiTransactionPrivate::ipAddrToAsciiTransactionPrivate
void ipAddrToAsciiTransactionPrivate::release ()
{
this->~ipAddrToAsciiTransactionPrivate ();
this->engine.transactionFreeList.release ( this );
this->engine.pEngine->transactionFreeList.release ( this );
}
ipAddrToAsciiTransactionPrivate::~ipAddrToAsciiTransactionPrivate ()
{
epicsGuard < epicsMutex > guard ( this->engine.mutex );
while ( this->pending ) {
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++;
{
epicsGuardRelease < epicsMutex > unguard ( guard );
this->engine.destructorBlockEvent.wait ();
}
assert ( this->engine.cancelPendingCount > 0u );
this->engine.cancelPendingCount--;
if ( ! this->pending ) {
if ( this->engine.cancelPendingCount ) {
this->engine.destructorBlockEvent.signal ();
ipAddrToAsciiGlobal *pGlobal = this->engine.pEngine;
bool last;
{
epicsGuard < epicsMutex > guard ( pGlobal->mutex );
while ( this->pending ) {
if ( pGlobal->pCurrent == this &&
pGlobal->callbackInProgress &&
! pGlobal->thread.isCurrentThread() ) {
// cancel from another thread while callback in progress
// waits for callback to complete
assert ( pGlobal->cancelPendingCount < UINT_MAX );
pGlobal->cancelPendingCount++;
{
epicsGuardRelease < epicsMutex > unguard ( guard );
pGlobal->destructorBlockEvent.wait ();
}
assert ( pGlobal->cancelPendingCount > 0u );
pGlobal->cancelPendingCount--;
if ( ! this->pending ) {
if ( pGlobal->cancelPendingCount ) {
pGlobal->destructorBlockEvent.signal ();
}
break;
}
break;
}
}
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 );
if ( pGlobal->pCurrent == this ) {
// cancel from callback, or while lookup in progress
pGlobal->pCurrent = 0;
}
else {
// cancel before lookup starts
pGlobal->labor.remove ( *this );
}
this->pending = false;
}
this->pending = false;
}
assert(this->engine.refcount>0);
last = 0==--this->engine.refcount;
}
if(last) {
delete &this->engine;
}
}
@@ -345,15 +429,21 @@ void ipAddrToAsciiTransactionPrivate::ipAddrToAscii (
const osiSockAddr & addrIn, ipAddrToAsciiCallBack & cbIn )
{
bool success;
ipAddrToAsciiGlobal *pGlobal = this->engine.pEngine;
{
epicsGuard < epicsMutex > guard ( this->engine.mutex );
// put some reasonable limit on queue expansion
if ( !this->pending && engine.labor.count () < 16u ) {
epicsGuard < epicsMutex > guard ( pGlobal->mutex );
if (this->engine.released) {
errlogPrintf("Warning: ipAddrToAscii on transaction with release()'d ipAddrToAsciiEngine");
success = false;
} else if ( !this->pending && pGlobal->labor.count () < 16u ) {
// put some reasonable limit on queue expansion
this->addr = addrIn;
this->pCB = & cbIn;
this->pending = true;
this->engine.labor.add ( *this );
pGlobal->labor.add ( *this );
success = true;
}
else {
@@ -362,7 +452,7 @@ void ipAddrToAsciiTransactionPrivate::ipAddrToAscii (
}
if ( success ) {
this->engine.laborEvent.signal ();
pGlobal->laborEvent.signal ();
}
else {
char autoNameTmp[256];
@@ -379,7 +469,7 @@ osiSockAddr ipAddrToAsciiTransactionPrivate::address () const
void ipAddrToAsciiTransactionPrivate::show ( unsigned level ) const
{
epicsGuard < epicsMutex > guard ( this->engine.mutex );
epicsGuard < epicsMutex > guard ( this->engine.pEngine->mutex );
char ipAddr [64];
sockAddrToDottedIP ( &this->addr.sa, ipAddr, sizeof ( ipAddr ) );
printf ( "ipAddrToAsciiTransactionPrivate for address %s\n", ipAddr );

View File

@@ -44,6 +44,10 @@ public:
static ipAddrToAsciiEngine & allocate ();
protected:
virtual ~ipAddrToAsciiEngine () = 0;
public:
#ifdef EPICS_PRIVATE_API
static void cleanup();
#endif
};
#endif // ifdef ipAddrToAsciiAsynchronous_h

View File

@@ -43,12 +43,15 @@ epicsShareFunc void epicsAssert (const char *pFile, const unsigned line,
/* Compile-time checks */
#if __cplusplus>=201103L
#define STATIC_ASSERT(expr) static_assert(expr, #expr)
#else
#define STATIC_JOIN(x, y) STATIC_JOIN2(x, y)
#define STATIC_JOIN2(x, y) x ## y
#define STATIC_ASSERT(expr) \
typedef int STATIC_JOIN(static_assert_failed_at_line_, __LINE__) \
[ (expr) ? 1 : -1 ]
#endif
#ifdef __cplusplus
}

View File

@@ -269,7 +269,7 @@ static int generalTimeGetEventPriority(epicsTimeStamp *pDest, int eventNumber,
}
}
} else {
if (epicsTimeGreaterThanEqual(pDest,
if (epicsTimeGreaterThanEqual(&ts,
&gtPvt.eventTime[eventNumber])) {
*pDest = ts;
gtPvt.eventTime[eventNumber] = ts;
@@ -279,7 +279,6 @@ static int generalTimeGetEventPriority(epicsTimeStamp *pDest, int eventNumber,
key = epicsInterruptLock();
gtPvt.ErrorCounts++;
epicsInterruptUnlock(key);
}
IFDEBUG(10) {
char last[40], buff[40];
@@ -291,6 +290,7 @@ static int generalTimeGetEventPriority(epicsTimeStamp *pDest, int eventNumber,
" %s, using %s instead\n",
ptp->name, buff, last);
}
}
}
break;
}

View File

@@ -1,7 +1,7 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Saskatchewan
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Author: Eric Norum
@@ -38,6 +38,7 @@ typedef socklen_t osiSocklen_t;
#define SOCK_ENOBUFS ENOBUFS
#define SOCK_ECONNRESET ECONNRESET
#define SOCK_ETIMEDOUT ETIMEDOUT
#define SOCK_EACCES EACCES
#define SOCK_EADDRINUSE EADDRINUSE
#define SOCK_ECONNREFUSED ECONNREFUSED
#define SOCK_ECONNABORTED ECONNABORTED

View File

@@ -67,14 +67,14 @@ convertDoubleToWakeTime(double timeout, struct timespec *wakeTime)
mach_timespec_t now;
struct timespec wait;
if (timeout < 0.0)
timeout = 0.0;
else if (timeout > 60 * 60 * 24 * 3652.5)
timeout = 60 * 60 * 24 * 3652.5; /* 10 years */
clock_get_time(host_clock, &now);
if (timeout<0.0)
timeout = 0.0;
else if(timeout>3600.0)
timeout = 3600.0;
wait.tv_sec = static_cast< long >(timeout);
wait.tv_sec = static_cast< time_t >(timeout);
wait.tv_nsec = static_cast< long >((timeout - (double)wait.tv_sec) * 1e9);
wakeTime->tv_sec = now.tv_sec + wait.tv_sec;

View File

@@ -4,7 +4,7 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
@@ -13,12 +13,12 @@
* Under Linux if we dont define _POSIX_C_SOURCE or _XOPEN_SOURCE
* then none of the POSIX stuff (such as signals) can be used
* with cc -v. However if one of _POSIX_C_SOURCE or _XOPEN_SOURCE
* are defined then we cant use the socket library. Therefore I
* have been adding the following in order to use POSIX signals
* are defined then we cant use the socket library. Therefore I
* have been adding the following in order to use POSIX signals
* and also sockets on Linux with cc -v. What a pain....
*
* #ifdef linux
* #define __EXTENSIONS__
* #define __EXTENSIONS__
* #endif
*/
@@ -53,6 +53,7 @@ typedef socklen_t osiSocklen_t;
#define SOCK_ENOBUFS ENOBUFS
#define SOCK_ECONNRESET ECONNRESET
#define SOCK_ETIMEDOUT ETIMEDOUT
#define SOCK_EACCES EACCES
#define SOCK_EADDRINUSE EADDRINUSE
#define SOCK_ECONNREFUSED ECONNREFUSED
#define SOCK_ECONNABORTED ECONNABORTED
@@ -82,4 +83,3 @@ typedef socklen_t osiSocklen_t;
#define ifreq_size(pifreq) (sizeof(pifreq->ifr_name))
#endif /*osdSockH*/

View File

@@ -1,7 +1,7 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Saskatchewan
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* RTEMS osdSock.h
@@ -35,7 +35,7 @@ int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, str
#ifdef __cplusplus
}
#endif
typedef int SOCKET;
#define INVALID_SOCKET (-1)
#define SOCKERRNO errno
@@ -49,6 +49,7 @@ typedef socklen_t osiSocklen_t;
#define SOCK_ENOBUFS ENOBUFS
#define SOCK_ECONNRESET ECONNRESET
#define SOCK_ETIMEDOUT ETIMEDOUT
#define SOCK_EACCES EACCES
#define SOCK_EADDRINUSE EADDRINUSE
#define SOCK_ECONNREFUSED ECONNREFUSED
#define SOCK_ECONNABORTED ECONNABORTED
@@ -74,7 +75,7 @@ typedef socklen_t osiSocklen_t;
#ifndef INADDR_NONE
# define INADDR_NONE (0xffffffff)
#endif
#endif
/*
* For shutdown()

View File

@@ -4,7 +4,7 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
#ifndef osdSockH
@@ -14,7 +14,7 @@
#include <errno.h>
/*
* winsock2.h changes the structure alignment to 4 if
* winsock2.h changes the structure alignment to 4 if
* WIN32 isnt set which can be a source of confusion
*/
#ifndef WIN32
@@ -48,6 +48,7 @@ typedef int osiSocklen_t;
#define SOCK_ENOBUFS WSAENOBUFS
#define SOCK_ECONNRESET WSAECONNRESET
#define SOCK_ETIMEDOUT WSAETIMEDOUT
#define SOCK_EACCES WSAEACCES
#define SOCK_EADDRINUSE WSAEADDRINUSE
#define SOCK_ECONNREFUSED WSAECONNREFUSED
#define SOCK_ECONNABORTED WSAECONNABORTED

View File

@@ -4,7 +4,7 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* cygwin32 specific include
@@ -49,6 +49,7 @@ typedef int osiSocklen_t;
#define SOCK_ENOBUFS ENOBUFS
#define SOCK_ECONNRESET ECONNRESET
#define SOCK_ETIMEDOUT ETIMEDOUT
#define SOCK_EACCES EACCES
#define SOCK_EADDRINUSE EADDRINUSE
#define SOCK_ECONNREFUSED ECONNREFUSED
#define SOCK_ECONNABORTED ECONNABORTED
@@ -66,4 +67,3 @@ typedef int osiSocklen_t;
#define ifreq_size(pifreq) (sizeof(pifreq->ifr_name))
#endif /*osdSockH*/

View File

@@ -4,7 +4,7 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
#ifndef osdSockH
@@ -29,7 +29,7 @@
#define IPPORT_USERRESERVED 5000
#endif
typedef int SOCKET;
#define INVALID_SOCKET (-1)
#define SOCKERRNO errno
@@ -43,6 +43,7 @@ typedef socklen_t osiSocklen_t;
#define SOCK_ENOBUFS ENOBUFS
#define SOCK_ECONNRESET ECONNRESET
#define SOCK_ETIMEDOUT ETIMEDOUT
#define SOCK_EACCES EACCES
#define SOCK_EADDRINUSE EADDRINUSE
#define SOCK_ECONNREFUSED ECONNREFUSED
#define SOCK_ECONNABORTED ECONNABORTED
@@ -76,4 +77,3 @@ typedef socklen_t osiSocklen_t;
#endif
#endif /*osdSockH*/

View File

@@ -39,6 +39,7 @@ typedef socklen_t osiSocklen_t;
#define SOCK_ENOBUFS ENOBUFS
#define SOCK_ECONNRESET ECONNRESET
#define SOCK_ETIMEDOUT ETIMEDOUT
#define SOCK_EACCES EACCES
#define SOCK_EADDRINUSE EADDRINUSE
#define SOCK_ECONNREFUSED ECONNREFUSED
#define SOCK_ECONNABORTED ECONNABORTED

View File

@@ -87,30 +87,35 @@ int epicsTime_localtime ( const time_t *clock, // X aCC 361
extern "C" epicsShareFunc void
convertDoubleToWakeTime(double timeout,struct timespec *wakeTime)
{
struct timespec wait;
struct timespec now, wait;
int status;
if(timeout<0.0) timeout = 0.0;
else if(timeout>3600.0) timeout = 3600.0;
if (timeout < 0.0)
timeout = 0.0;
else if (timeout > 60 * 60 * 24 * 3652.5)
timeout = 60 * 60 * 24 * 3652.5; /* 10 years */
#ifdef CLOCK_REALTIME
status = clock_gettime(CLOCK_REALTIME, wakeTime);
status = clock_gettime(CLOCK_REALTIME, &now);
#else
{
struct timeval tv;
struct timezone tz;
status = gettimeofday(&tv, &tz);
wakeTime->tv_sec = tv.tv_sec;
wakeTime->tv_nsec = tv.tv_usec * 1000;
now.tv_sec = tv.tv_sec;
now.tv_nsec = tv.tv_usec * 1000;
}
#endif
if (status) {
perror("convertDoubleToWakeTime");
cantProceed("convertDoubleToWakeTime");
}
wait.tv_sec = static_cast< long >(timeout);
wait.tv_sec = static_cast< time_t >(timeout);
wait.tv_nsec = static_cast< long >((timeout - (double)wait.tv_sec) * 1e9);
wakeTime->tv_sec += wait.tv_sec;
wakeTime->tv_nsec += wait.tv_nsec;
wakeTime->tv_sec = now.tv_sec + wait.tv_sec;
wakeTime->tv_nsec = now.tv_nsec + wait.tv_nsec;
if (wakeTime->tv_nsec >= 1000000000L) {
wakeTime->tv_nsec -= 1000000000L;
++wakeTime->tv_sec;

View File

@@ -4,7 +4,7 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
@@ -39,7 +39,7 @@ typedef int osiSockIoctl_t;
#if SOLARIS > 6 || defined ( _SOCKLEN_T )
typedef uint32_t osiSocklen_t;
#else
#else
typedef int osiSocklen_t;
#endif
@@ -51,6 +51,7 @@ typedef int osiSockIoctl_t;
#define SOCK_ENOBUFS ENOBUFS
#define SOCK_ECONNRESET ECONNRESET
#define SOCK_ETIMEDOUT ETIMEDOUT
#define SOCK_EACCES EACCES
#define SOCK_EADDRINUSE EADDRINUSE
#define SOCK_ECONNREFUSED ECONNREFUSED
#define SOCK_ECONNABORTED ECONNABORTED
@@ -79,9 +80,8 @@ typedef int osiSockIoctl_t;
#ifndef INADDR_NONE
# define INADDR_NONE (0xffffffff)
#endif
#endif
#define ifreq_size(pifreq) (sizeof(pifreq->ifr_name))
#endif /*osdSockH*/

View File

@@ -4,7 +4,7 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* vxWorks specific socket include
@@ -44,7 +44,7 @@ int sysClkRateGet(void);
#ifdef __cplusplus
}
#endif
typedef int SOCKET;
#define INVALID_SOCKET (-1)
#define SOCKERRNO errno
@@ -72,6 +72,7 @@ typedef int osiSocklen_t;
#define SOCK_ENOBUFS ENOBUFS
#define SOCK_ECONNRESET ECONNRESET
#define SOCK_ETIMEDOUT ETIMEDOUT
#define SOCK_EACCES EACCES
#define SOCK_EADDRINUSE EADDRINUSE
#define SOCK_ECONNREFUSED ECONNREFUSED
#define SOCK_ECONNABORTED ECONNABORTED
@@ -92,7 +93,7 @@ typedef int osiSocklen_t;
#ifndef INADDR_NONE
# define INADDR_NONE (0xffffffff)
#endif
#endif
#if defined(_SIZEOF_ADDR_IFREQ)
# define ifreq_size(pifreq) _SIZEOF_ADDR_IFREQ(*pifreq)
@@ -103,5 +104,3 @@ typedef int osiSocklen_t;
#endif
#endif /*osdSockH*/

View File

@@ -11,6 +11,7 @@ TOP=../../..
include $(TOP)/configure/CONFIG
PROD_LIBS += Com
PROD_SYS_LIBS_WIN32 += ws2_32 advapi32 user32
TESTPROD_HOST += epicsUnitTestTest
epicsUnitTestTest_SRCS += epicsUnitTestTest.c
@@ -151,6 +152,10 @@ epicsMessageQueueTest_SRCS += epicsMessageQueueTest.cpp
testHarness_SRCS += epicsMessageQueueTest.cpp
TESTS += epicsMessageQueueTest
TESTPROD_HOST += ipAddrToAsciiTest
ipAddrToAsciiTest_SRCS += ipAddrToAsciiTest.cpp
testHarness_SRCS += ipAddrToAsciiTest.cpp
TESTS += ipAddrToAsciiTest
# The testHarness runs all the test programs in a known working order.
testHarness_SRCS += epicsRunLibComTests.c

View File

@@ -6,6 +6,9 @@
\*************************************************************************/
// Author: Andrew Johnson
#include <stdlib.h>
#include <string.h>
#include "epicsUnitTest.h"
#include "epicsTypes.h"
#include "epicsMath.h"
@@ -20,17 +23,23 @@ double doCalc(const char *expr) {
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];
char *rpn = (char*)malloc(INFIX_TO_POSTFIX_SIZE(strlen(expr)+1));
short err;
double result = 0.0;
result /= result; /* Start as NaN */
if(!rpn) {
testAbort("postfix: %s no memory", expr);
return epicsNAN;
}
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);
}
free(rpn);
return result;
}
@@ -40,11 +49,16 @@ void testCalc(const char *expr, double expected) {
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];
char *rpn = (char*)malloc(INFIX_TO_POSTFIX_SIZE(strlen(expr)+1));
short err;
double result = 0.0;
result /= result; /* Start as NaN */
if(!rpn) {
testFail("postfix: %s no memory", expr);
return;
}
if (postfix(expr, rpn, &err)) {
testDiag("postfix: %s in expression '%s'", calcErrorStr(err), expr);
} else
@@ -63,6 +77,7 @@ void testCalc(const char *expr, double expected) {
testDiag("Expected result is %g, actually got %g", expected, result);
calcExprDump(rpn);
}
free(rpn);
}
void testUInt32Calc(const char *expr, epicsUInt32 expected) {
@@ -71,12 +86,17 @@ void testUInt32Calc(const char *expr, epicsUInt32 expected) {
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];
char *rpn = (char*)malloc(INFIX_TO_POSTFIX_SIZE(strlen(expr)+1));
short err;
epicsUInt32 uresult;
double result = 0.0;
result /= result; /* Start as NaN */
if(!rpn) {
testFail("postfix: %s no memory", expr);
return;
}
if (postfix(expr, rpn, &err)) {
testDiag("postfix: %s in expression '%s'", calcErrorStr(err), expr);
} else
@@ -91,38 +111,50 @@ void testUInt32Calc(const char *expr, epicsUInt32 expected) {
expected, expected, uresult, uresult);
calcExprDump(rpn);
}
free(rpn);
}
void testArgs(const char *expr, unsigned long einp, unsigned long eout) {
char rpn[MAX_POSTFIX_SIZE];
char *rpn = (char*)malloc(INFIX_TO_POSTFIX_SIZE(strlen(expr)+1));
short err = 0;
unsigned long vinp, vout;
if(!rpn) {
testFail("postfix: %s no memory", expr);
return;
}
if (postfix(expr, rpn, &err)) {
testFail("postfix: %s in expression '%s'", calcErrorStr(err), expr);
return;
testFail("postfix: %s in expression '%s'", calcErrorStr(err), expr);
return;
}
if (calcArgUsage(rpn, &vinp, &vout)) {
testFail("calcArgUsage returned error for '%s'", expr);
return;
testFail("calcArgUsage returned error for '%s'", expr);
return;
}
if (!testOk(vinp == einp && vout == eout, "Args for '%s'", expr)) {
testDiag("Expected (%lx, %lx) got (%lx, %lx)", einp, eout, vinp, vout);
testDiag("Expected (%lx, %lx) got (%lx, %lx)", einp, eout, vinp, vout);
}
free(rpn);
}
void testBadExpr(const char *expr, short expected_err) {
/* Parse an invalid expression, test against expected error code */
char rpn[MAX_POSTFIX_SIZE];
char *rpn = (char*)malloc(INFIX_TO_POSTFIX_SIZE(strlen(expr)+1));
short err = 0;
if(!rpn) {
testFail("postfix: %s no memory", expr);
return;
}
postfix(expr, rpn, &err);
if (!testOk(err == expected_err, "Bad expression '%s'", expr)) {
testDiag("Expected '%s', actually got '%s'",
calcErrorStr(expected_err), calcErrorStr(err));
calcExprDump(rpn);
testDiag("Expected '%s', actually got '%s'",
calcErrorStr(expected_err), calcErrorStr(err));
calcExprDump(rpn);
}
return;
free(rpn);
}
/* Test an expression that is also valid C code */

View File

@@ -75,6 +75,12 @@ typedef struct {
int jam;
} clientPvt;
static
void testEqInt_(int lhs, int rhs, const char *LHS, const char *RHS)
{
testOk(lhs==rhs, "%s (%d) == %s (%d)", LHS, lhs, RHS, rhs);
}
#define testEqInt(L, R) testEqInt_(L, R, #L, #R);
static
void logClient(void* raw, const char* msg)
{
@@ -146,7 +152,7 @@ MAIN(epicsErrlogTest)
errlogPrintfNoConsole("%s", pvt.expect);
errlogFlush();
testOk1(pvt.count == 1);
testEqInt(pvt.count, 1);
errlogAddListener(&logClient, &pvt2);
@@ -156,8 +162,8 @@ MAIN(epicsErrlogTest)
errlogPrintfNoConsole("%s", pvt.expect);
errlogFlush();
testOk1(pvt.count == 2);
testOk1(pvt2.count == 1);
testEqInt(pvt.count, 2);
testEqInt(pvt2.count, 1);
/* Removes the first listener, but the second remains */
errlogRemoveListener(&logClient);
@@ -168,8 +174,8 @@ MAIN(epicsErrlogTest)
errlogPrintfNoConsole("%s", pvt2.expect);
errlogFlush();
testOk1(pvt.count == 2);
testOk1(pvt2.count == 2);
testEqInt(pvt.count, 2);
testEqInt(pvt2.count, 2);
/* Remove the second listener */
errlogRemoveListener(&logClient);
@@ -177,8 +183,8 @@ MAIN(epicsErrlogTest)
errlogPrintfNoConsole("Something different");
errlogFlush();
testOk1(pvt.count == 2);
testOk1(pvt2.count == 2);
testEqInt(pvt.count, 2);
testEqInt(pvt2.count, 2);
/* Re-add one listener */
errlogAddListener(&logClient, &pvt);
@@ -191,7 +197,7 @@ MAIN(epicsErrlogTest)
errlogPrintfNoConsole("%s", longmsg);
errlogFlush();
testOk1(pvt.count == 3);
testEqInt(pvt.count, 3);
pvt.expect = NULL;
@@ -204,12 +210,12 @@ MAIN(epicsErrlogTest)
errlogPrintfNoConsole("%s", longmsg);
epicsThreadSleep(0.1);
testOk1(pvt.count == 3);
testEqInt(pvt.count, 3);
epicsEventSignal(pvt.jammer);
errlogFlush();
testOk1(pvt.count == 4);
testEqInt(pvt.count, 4);
testDiag("Find buffer capacity (%u theoretical)",LOGBUFSIZE);
@@ -262,7 +268,7 @@ MAIN(epicsErrlogTest)
}
epicsThreadSleep(0.1); /* should really be a second Event */
testOk1(pvt.count == 0);
testEqInt(pvt.count, 0);
/* Extract the first 2 messages, 2*(sizeof(msgNode) + 128) bytes */
pvt.jam = -2;
@@ -270,7 +276,7 @@ MAIN(epicsErrlogTest)
epicsThreadSleep(0.1);
testDiag("Drained %u messages", pvt.count);
testOk1(pvt.count == 2);
testEqInt(pvt.count, 2);
/* The buffer has space for 1 more message: sizeof(msgNode) + 256 bytes */
errlogPrintfNoConsole("%s", msg); /* Use up that space */
@@ -278,13 +284,13 @@ MAIN(epicsErrlogTest)
testDiag("Overflow the buffer");
errlogPrintfNoConsole("%s", msg);
testOk1(pvt.count == 2);
testEqInt(pvt.count, 2);
epicsEventSignal(pvt.jammer); /* Empty */
errlogFlush();
testDiag("Logged %u messages", pvt.count);
testOk1(pvt.count == N+1);
testEqInt(pvt.count, N+1);
/* Clean up */
errlogRemoveListener(&logClient);

View File

@@ -41,6 +41,7 @@ int macEnvExpandTest(void);
int ringPointerTest(void);
int ringBytesTest(void);
int blockingSockTest(void);
int ipAddrToAsciiTest(void);
int epicsSockResolveTest(void);
int taskwdTest(void);
int epicsExitTest(void);
@@ -102,6 +103,8 @@ void epicsRunLibComTests(void)
runTest(ringBytesTest);
runTest(blockingSockTest);
runTest(ipAddrToAsciiTest);
runTest(epicsSockResolveTest);

View File

@@ -48,7 +48,7 @@ MAIN(epicsTimeTest)
const int wasteTime = 100000;
const int nTimes = 10;
testPlan(15 + nTimes * 19);
testPlan(17 + nTimes * 19);
try {
const epicsTimeStamp epochTS = {0, 0};
@@ -216,5 +216,35 @@ MAIN(epicsTimeTest)
testOk1(beginTS + diff == now);
}
epicsTime ten_years_hence;
try {
now = epicsTime::getCurrent();
ten_years_hence = now + 60 * 60 * 24 * 3652.5;
testPass("epicsTime can represent 10 years hence");
}
catch ( ... ) {
testFail("epicsTime exception for value 10 years hence");
}
try {
/* This test exists because in libCom/osi/os/posix/osdTime.cpp
* the convertDoubleToWakeTime() routine limits the timeout delay
* to 10 years. libCom/timer/timerQueue.cpp returns DBL_MAX for
* queues with no timers present, and convertDoubleToWakeTime()
* has to return an absolute Posix timestamp. On 2028-01-19 any
* systems that still implement time_t as a signed 32-bit integer
* will be unable to represent that timestamp, so this will fail.
*/
time_t_wrapper os_time_t = ten_years_hence;
epicsTime then = os_time_t; // No fractional seconds
double delta = ten_years_hence - then;
testOk(delta >= 0 && delta < 1.0,
"OS time_t can represent 10 years hence");
}
catch ( ... ) {
testFail("OS time_t conversion exception for value 10 years hence");
}
return testDone();
}

View File

@@ -74,13 +74,13 @@ void testTimer (fdctx *pfdm, double delay)
epicsTimeGetCurrent (&begin);
cbs.done = 0;
tmo.tv_sec = (unsigned long) delay;
tmo.tv_sec = (time_t) delay;
tmo.tv_usec = (unsigned long) ((delay - tmo.tv_sec) * uSecPerSec);
aid = fdmgr_add_timeout (pfdm, &tmo, alarmCB, &cbs);
verify (aid!=fdmgrNoAlarm);
while (!cbs.done) {
tmo.tv_sec = (unsigned long) delay;
tmo.tv_sec = (time_t) delay;
tmo.tv_usec = (unsigned long) ((delay - tmo.tv_sec) * uSecPerSec);
status = fdmgr_pend_event (pfdm, &tmo);
verify (status==0);

View File

@@ -0,0 +1,165 @@
/*************************************************************************\
* Copyright (c) 2017 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 <stdlib.h>
#define EPICS_PRIVATE_API
#include "epicsMutex.h"
#include "epicsGuard.h"
#include "epicsThread.h"
#include "epicsEvent.h"
#include "ipAddrToAsciiAsynchronous.h"
#include "epicsUnitTest.h"
#include "testMain.h"
namespace {
typedef epicsGuard<epicsMutex> Guard;
typedef epicsGuardRelease<epicsMutex> UnGuard;
struct CB : public ipAddrToAsciiCallBack
{
const char *name;
epicsMutex mutex;
epicsEvent starter, blocker, complete;
bool started, cont, done;
CB(const char *name) : name(name), started(false), cont(false), done(false) {}
virtual ~CB() {}
virtual void transactionComplete ( const char * pHostName )
{
Guard G(mutex);
started = true;
starter.signal();
testDiag("In transactionComplete(%s) for %s", pHostName, name);
while(!cont) {
UnGuard U(G);
if(!blocker.wait(2.0))
break;
}
done = true;
complete.signal();
}
void waitStart()
{
Guard G(mutex);
while(!started) {
UnGuard U(G);
if(!starter.wait(2.0))
break;
}
}
void poke()
{
testDiag("Poke");
Guard G(mutex);
cont = true;
blocker.signal();
}
void finish()
{
testDiag("Finish");
Guard G(mutex);
while(!done) {
UnGuard U(G);
if(!complete.wait(2.0))
break;
}
testDiag("Finished");
}
};
// ensure that lookup of 127.0.0.1 works
void doLookup(ipAddrToAsciiEngine& engine)
{
testDiag("In doLookup");
ipAddrToAsciiTransaction& trn(engine.createTransaction());
CB cb("cb");
osiSockAddr addr;
addr.ia.sin_family = AF_INET;
addr.ia.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
addr.ia.sin_port = htons(42);
testDiag("Start lookup");
trn.ipAddrToAscii(addr, cb);
cb.poke();
cb.finish();
testOk1(cb.cont);
testOk1(cb.done);
trn.release();
}
// Test cancel of pending transaction
void doCancel()
{
testDiag("In doCancel");
ipAddrToAsciiEngine& engine1(ipAddrToAsciiEngine::allocate());
ipAddrToAsciiEngine& engine2(ipAddrToAsciiEngine::allocate());
ipAddrToAsciiTransaction& trn1(engine1.createTransaction()),
& trn2(engine2.createTransaction());
testOk1(&trn1!=&trn2);
CB cb1("cb1"), cb2("cb2");
osiSockAddr addr;
addr.ia.sin_family = AF_INET;
addr.ia.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
addr.ia.sin_port = htons(42);
// ensure that the worker thread is blocked with a transaction from engine1
testDiag("Start lookup1");
trn1.ipAddrToAscii(addr, cb1);
testDiag("Wait start1");
cb1.waitStart();
testDiag("Start lookup2");
trn2.ipAddrToAscii(addr, cb2);
testDiag("release engine2, implicitly cancels lookup2");
engine2.release();
cb2.poke();
testDiag("Wait for lookup2 timeout");
cb2.finish();
testOk1(!cb2.done);
testDiag("Complete lookup1");
cb1.poke();
cb1.finish();
testOk1(cb1.done);
engine1.release();
trn1.release();
trn2.release();
}
} // namespace
MAIN(ipAddrToAsciiTest)
{
testPlan(5);
{
ipAddrToAsciiEngine& engine(ipAddrToAsciiEngine::allocate());
doLookup(engine);
engine.release();
}
doCancel();
// TODO: somehow test cancel of in-progress callback
// allow time for any un-canceled transcations to crash us...
epicsThreadSleep(1.0);
#ifdef __linux__
ipAddrToAsciiEngine::cleanup();
#endif
return testDone();
}

View File

@@ -65,7 +65,7 @@ static void ovcheck(void)
MAIN(macLibTest)
{
testPlan(89);
testPlan(91);
if (macCreateHandle(&h, NULL))
testAbort("macCreateHandle() failed");
@@ -203,6 +203,9 @@ MAIN(macLibTest)
/* STR2 = "VAL2" */
check("${FOO}", " VAL2");
check("$(FOO)$(FOO1)", "!VAL2$(FOO1,undefined)");
check("$(FOO1)$(FOO)", "!$(FOO1,undefined)VAL2");
macPutValue(h, "BAR","${FOO}");
/* FOO = "${BAR}" */
/* BAR = "${FOO}" */

View File

@@ -107,7 +107,7 @@ private:
epicsTime exceptMsgTimeStamp;
bool cancelPending;
static const double exceptMsgMinPeriod;
void printExceptMsg ( const char * pName,
void printExceptMsg ( const char * pName,
const type_info & type );
timerQueue ( const timerQueue & );
timerQueue & operator = ( const timerQueue & );

View File

@@ -198,8 +198,8 @@ static long get_alarm_double(DBADDR *paddr,struct dbr_alDouble *pad)
static void checkAlarms(xxxRecord *prec)
{
double val;
float hyst, lalm, hihi, high, low, lolo;
double val, hyst, lalm;
float hihi, high, low, lolo;
unsigned short hhsv, llsv, hsv, lsv;
if(prec->udf == TRUE ){

View File

@@ -43,6 +43,9 @@ include "devSoft.dbd"
registrar(asSub)
variable(asCaDebug,int)
# CA server debug flag (very verbose) range[0,5]
variable(CASDEBUG,int)
# dbStaticLib settings
variable(dbRecordsOnceOnly,int)
variable(dbBptNotMonotonic,int)

View File

@@ -16,8 +16,6 @@
#define epicsExportSharedSymbols
#include "epicsRelease.h"
static const char id[] = "@(#) " EPICS_VERSION_STRING ", Misc. Utilities Library" __DATE__;
epicsShareFunc int epicsShareAPI coreRelease(void)
{
printf ( "############################################################################\n" );

View File

@@ -207,6 +207,14 @@ static long init_record(aSubRecord *prec, int pass)
}
strcpy(prec->onam, prec->snam);
prec->oval = prec->val;
for (i = 0; i < NUM_ARGS; i++) {
epicsUInt32 nev = (&prec->neva)[i];
(&prec->onva)[i] = nev;
if (nev)
memcpy((&prec->ovla)[i], (&prec->vala)[i],
dbValueSize((&prec->ftva)[i]) * nev);
}
return 0;
}

View File

@@ -21,6 +21,7 @@
#include "dbDefs.h"
#include "epicsPrint.h"
#include "epicsMath.h"
#include "alarm.h"
#include "dbAccess.h"
#include "dbEvent.h"
@@ -201,10 +202,10 @@ static long get_alarm_double(DBADDR *paddr, struct dbr_alDouble *pad)
longinRecord *prec=(longinRecord *)paddr->precord;
if(paddr->pfield==(void *)&prec->val){
pad->upper_alarm_limit = prec->hihi;
pad->upper_warning_limit = prec->high;
pad->lower_warning_limit = prec->low;
pad->lower_alarm_limit = prec->lolo;
pad->upper_alarm_limit = prec->hhsv ? prec->hihi : epicsNAN;
pad->upper_warning_limit = prec->hsv ? prec->high : epicsNAN;
pad->lower_warning_limit = prec->lsv ? prec->low : epicsNAN;
pad->lower_alarm_limit = prec->llsv ? prec->lolo : epicsNAN;
} else recGblGetAlarmDouble(paddr,pad);
return(0);
}

View File

@@ -19,6 +19,7 @@
#include "dbDefs.h"
#include "epicsPrint.h"
#include "epicsMath.h"
#include "alarm.h"
#include "dbAccess.h"
#include "dbEvent.h"
@@ -242,10 +243,10 @@ static long get_alarm_double(DBADDR *paddr,struct dbr_alDouble *pad)
int fieldIndex = dbGetFieldIndex(paddr);
if(fieldIndex == longoutRecordVAL) {
pad->upper_alarm_limit = prec->hihi;
pad->upper_warning_limit = prec->high;
pad->lower_warning_limit = prec->low;
pad->lower_alarm_limit = prec->lolo;
pad->upper_alarm_limit = prec->hhsv ? prec->hihi : epicsNAN;
pad->upper_warning_limit = prec->hsv ? prec->high : epicsNAN;
pad->lower_warning_limit = prec->lsv ? prec->low : epicsNAN;
pad->lower_alarm_limit = prec->llsv ? prec->lolo : epicsNAN;
} else recGblGetAlarmDouble(paddr,pad);
return(0);
}

Some files were not shown because too many files have changed in this diff Show More