Compare commits

...

91 Commits

Author SHA1 Message Date
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
Andrew Johnson
260bc64b59 Set SNAPSHOT back to -DEV 2016-12-09 13:50:17 -06:00
Andrew Johnson
5097ac3230 Set SNAPSHOT for 3.14.12.6 2016-12-09 13:48:55 -06:00
Andrew Johnson
8d7bf52e51 One more cppcheck issue fixed 2016-12-09 11:17:43 -06:00
Andrew Johnson
1cb75ebb6e asLib message buffer too small (Freddie Akeroyd) 2016-12-08 13:57:23 -06:00
Andrew Johnson
94397b52fc Resolve some cppcheck errors & warnings 2016-12-07 13:53:26 -06:00
Andrew Johnson
7fe152ce1b Merge Bruce Hill's pcas-deadlock-fix-3.14 branch 2016-12-07 10:43:06 -06:00
Bruce Hill
d3568605ce Fetch nativeCount() in casChannelI constructor to avoid deadlock
if we fetch it from eventSysProcess()
2016-12-06 13:43:59 -08:00
Andrew Johnson
666721c7ad Document caput scalar arg's, update usage docs 2016-12-06 12:16:35 -06:00
0f7f4710c6 PCAS dynamic array support for GDD container types 2016-11-30 11:58:24 -06:00
Andrew Johnson
f1439f8b1c Fix epicsStdioTest for MS 2015 compiler 2016-11-15 09:56:42 -06:00
Andrew Johnson
aa6e976f92 Add .local includes to makeBaseApp templates 2016-11-04 17:18:14 -05:00
Andrew Johnson
67daaaa9b7 Set snapshot to -rc1-DEV 2016-10-31 17:06:19 -05:00
Michael Davidsaver
428268a71e rsrv: avoid strlen() on possible unterminated strings
Detect these w/o risk of SIGSEGV
2014-01-11 10:59:57 -05:00
Michael Davidsaver
746c739769 add epicsStrnLen()
Base currently requires only POSIX 2001 while
strnlen() is part of POSIX 2008.
2014-01-11 10:58:39 -05:00
116 changed files with 2942 additions and 1276 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

86
appveyor.yml Normal file
View File

@@ -0,0 +1,86 @@
# 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: 9.0
- TOOLCHAIN: 10.0
- TOOLCHAIN: 11.0
- TOOLCHAIN: 12.0
- TOOLCHAIN: 14.0
- 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: 9.0
- 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=

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

@@ -0,0 +1,118 @@
:: Universal 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]
:: 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%"
set "MAKE=C:\tools\make"
if "%OS%"=="64BIT" (
set EPICS_HOST_ARCH=windows-x64%ST%
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%
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
@powershell -Command "(new-object net.webclient).DownloadFile('https://www.aps.anl.gov/epics/download/tools/make-4.1-win64.zip', 'C:\tools\make-4.1.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,7 +28,7 @@ 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 = 7
# This will end in -DEV between official releases
#EPICS_DEV_SNAPSHOT=-DEV
@@ -36,11 +36,11 @@ EPICS_PATCH_LEVEL = 6
#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
#EPICS_DEV_SNAPSHOT=
EPICS_DEV_SNAPSHOT=
# No changes should be needed below here

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,47 @@
# 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
EPICS_TIMEZONE = CUS::360:031202:110502
#EPICS_TIMEZONE = MET::-60:032602:102902
#
# DST for 2018 US: Mar 11 - Nov 04
# EU: Mar 25 - Oct 28
#EPICS_TIMEZONE = CUS::360:031102:110402
#EPICS_TIMEZONE = MET::-60:032502:102802
#
# DST for 2019 US: Mar 10 - Nov 03
# EU: Mar 31 - Oct 27
#EPICS_TIMEZONE = CUS::360:031002:110302
#EPICS_TIMEZONE = MET::-60:033102:102702
#
# DST for 2020 US: Mar 08 - Nov 01
# EU: Mar 29 - Oct 25
#EPICS_TIMEZONE = CUS::360:030802:110102
#EPICS_TIMEZONE = MET::-60:032902:102502
#
# 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:103102
#
# 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:103002
# 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

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) $@
@@ -493,7 +514,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,21 +67,21 @@ 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
#
@@ -101,11 +101,12 @@ 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,12 +130,12 @@ 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=
@@ -173,10 +174,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 +193,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 +207,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 +223,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 +290,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 +300,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

@@ -3,16 +3,89 @@
<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.7 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.7</h1>
<h2 align="center">Changes between 3.14.12.5 and 3.14.12.6</h2>
<h2 align="center">Changes between 3.14.12.6 and 3.14.12.7</h2>
<!-- Insert new items immediately below here ... -->
<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 +350,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 +847,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 +1079,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 +1433,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 +1526,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 +1539,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 +1555,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 +2076,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 +3293,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

@@ -489,7 +489,7 @@ exitHandler(void)
rtems_task
Init (rtems_task_argument ignored)
{
int i;
int result;
char *argv[3] = { NULL, NULL, NULL };
char *cp;
rtems_task_priority newpri;
@@ -612,8 +612,8 @@ Init (rtems_task_argument ignored)
set_directory (argv[1]);
epicsEnvSet ("IOC_STARTUP_SCRIPT", argv[1]);
atexit(exitHandler);
i = main ((sizeof argv / sizeof argv[0]) - 1, argv);
result = main ((sizeof argv / sizeof argv[0]) - 1, argv);
printf ("***** IOC application terminating *****\n");
epicsThreadSleep(1.0);
epicsExit(0);
epicsExit(result);
}

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]); }
^#.*
{newline} { line_num++; }
{comment}.* ;
{whitespace} ;
\n { line_num ++;}
. {
char message[20];
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

@@ -1146,16 +1146,10 @@ the output.</p>
<td>Wide mode "name timestamp value stat sevr" (read PVs as
DBR_TIME_xxx)</td>
</tr>
<tr>
<td>-n</td>
<td>Print DBF_ENUM values as number (default are enum strings)</td>
</tr>
<tr>
<td>-d &lt;type&gt;</td>
<td>Request specific dbr type; use string (DBR_ prefix may be omitted)
<p>or number of one of the following types:</p>
<td>Request specific dbr type; use string (DBR_ prefix may be omitted)<br>
or number of one of the following types:<br>
<table border="1">
<tbody>
<tr>
@@ -1272,6 +1266,14 @@ the output.</p>
</table>
</td>
</tr>
<tr>
<td></td>
<td><strong>Enum format:</strong></td>
</tr>
<tr>
<td>-n</td>
<td>Print DBF_ENUM value as number (default is enum string)</td>
</tr>
<tr>
<td></td>
<td><strong>Arrays:</strong></td>
@@ -1303,15 +1305,15 @@ the output.</p>
</tr>
<tr>
<td>-e &lt;nr&gt;</td>
<td>Use %e format, with &lt;nr&gt; digits after the decimal point</td>
<td>Use %e format, with a precision of &lt;nr&gt; digits</td>
</tr>
<tr>
<td>-f &lt;nr&gt;</td>
<td>Use %f format, with &lt;nr&gt; digits after the decimal point</td>
<td>Use %f format, with a precision of &lt;nr&gt; digits</td>
</tr>
<tr>
<td>-g &lt;nr&gt;</td>
<td>Use %g format, with &lt;nr&gt; digits after the decimal point</td>
<td>Use %g format, with a precision of &lt;nr&gt; digits</td>
</tr>
<tr>
<td>-s</td>
@@ -1349,6 +1351,14 @@ the output.</p>
<td>-0b</td>
<td>Print as binary number</td>
</tr>
<tr>
<td></td>
<td><strong>Alternate output field separator:</strong></td>
</tr>
<tr>
<td>-F &lt;ofs&gt;</td>
<td>Use &lt;ofs&gt; as an alternate output field separator</td>
</tr>
</tbody>
</table>
@@ -1381,9 +1391,10 @@ the output.</p>
<td>Wait time, specifies longer CA timeout, default is 1.0 second</td>
</tr>
<tr>
<td>-m &lt;mask&gt;</td>
<td>Specify CA event mask to use, with &lt;mask&gt; being any combination
of 'v' (value), 'a' (alarm), 'l' (log), 'p' (property). Default: va</td>
<td>-m &lt;msk&gt;</td>
<td>Specify CA event mask to use. &lt;msk&gt; is any combination of<br>
'v' (value), 'a' (alarm), 'l' (log/archive), 'p' (property).<br>
Default event mask is 'va'</td>
</tr>
<tr>
<td>-p &lt;prio&gt;</td>
@@ -1405,8 +1416,8 @@ the output.</p>
'n' = no timestamps<br>
'r' = relative timestamps (time elapsed since start of program)<br>
'i' = incremental timestamps (time elapsed since last update)<br>
'I' = incremental timestamps (time elapsed since last update, by
channel)</td>
'I' = incremental timestamps (time since last update, by channel)<br>
'r', 'i' or 'I' require 's' or 'c' to select the time source</td>
</tr>
<tr>
<td></td>
@@ -1414,7 +1425,7 @@ the output.</p>
</tr>
<tr>
<td>-n</td>
<td>Print DBF_ENUM values as number (default are enum strings)</td>
<td>Print DBF_ENUM values as number (default is enum string)</td>
</tr>
<tr>
<td></td>
@@ -1422,16 +1433,15 @@ the output.</p>
</tr>
<tr>
<td></td>
<td>Value format: Print number of requested values, then list of
values</td>
<td>Array values: Print number of elements, then list of values</td>
</tr>
<tr>
<td>Default:</td>
<td>Print all values</td>
<td>Default: Request and print all elements (dynamic arrays supported)</td>
</tr>
<tr>
<td>-# &lt;count&gt;</td>
<td>Print first &lt;count&gt; elements of an array</td>
<td>-# &lt;num&gt;</td>
<td>Request and print up to &lt;num&gt; elements</td>
</tr>
<tr>
<td>-S</td>
@@ -1439,23 +1449,23 @@ the output.</p>
</tr>
<tr>
<td></td>
<td><strong>Floating point type format:</strong></td>
<td><strong>Floating point format:</strong></td>
</tr>
<tr>
<td>Default:</td>
<td>Use %g format</td>
</tr>
<tr>
<td>-e &lt;nr&gt;</td>
<td>Use %e format, with &lt;nr&gt; digits after the decimal point</td>
<td>-e &lt;num&gt;</td>
<td>Use %e format, with a precision of &lt;num&gt; digits</td>
</tr>
<tr>
<td>-f &lt;nr&gt;</td>
<td>Use %f format, with &lt;nr&gt; digits after the decimal point</td>
<td>-f &lt;num&gt;</td>
<td>Use %f format, with a precision of &lt;num&gt; digits</td>
</tr>
<tr>
<td>-g &lt;nr&gt;</td>
<td>Use %g format, with &lt;nr&gt; digits after the decimal point</td>
<td>-g &lt;num&gt;</td>
<td>Use %g format, with a precision of &lt;num&gt; digits</td>
</tr>
<tr>
<td>-s</td>
@@ -1497,21 +1507,27 @@ the output.</p>
</table>
<h3><a name="caput">caput</a></h3>
<pre>caput [options] &lt;PV name&gt; &lt;value&gt;
<pre>caput [options] &lt;PV name&gt; &lt;value&gt; ...
caput -a [options] &lt;PV name&gt; &lt;no of elements&gt; &lt;value&gt; ...</pre>
<h4>Description</h4>
<p>Put value to a PV.</p>
<p>The specified value is written to the PV (as a string). The PV value is read
before and after the write operation and printed as "Old" and "new" values on
stdout.</p>
<p>The specified value is written to the PV (as a string). The PV's value is
read before and after the write operation and printed as "Old" and "New" values
on stdout.</p>
<p>The array variant writes an array to the specified PV. The first numeric
argument specifying the number of array elements is kept for compatibility with
the array data format of caget - the actual number of values specified on the
command line is used.</p>
<p>There are two variants to the arguments for this command. For the scalar
variant without the <code>-a</code> flag, all the value arguments provided after
the PV name are concatenated with a single space character between them, and the
resulting string (up to 40 characters long unless the <code>-S</code> flag is
given) is written to the specified PV.</p>
<p>The array variant with the <code>-a</code> flag writes an array of string
values to the specified PV. The numeric argument giving the number of array
elements is actually ignored, the array length to be written is actually
controlled by the number of values provided on the command line.</p>
<table border="1">
<caption></caption>
@@ -1550,12 +1566,16 @@ command line is used.</p>
<td>-t</td>
<td>Terse mode - print only successfully written value, without name</td>
</tr>
<tr>
<td>-l</td>
<td>Long mode "name timestamp value stat sevr" (read PVs as DBR_TIME_xxx)</td>
</tr>
<tr>
<td></td>
<td><strong>Enum Format:</strong></td>
</tr>
<tr>
<td></td>
<td>Default:</td>
<td>Auto - try value as ENUM string, then as index number</td>
</tr>
<tr>
@@ -1571,17 +1591,24 @@ command line is used.</p>
<td><strong>Arrays:</strong></td>
</tr>
<tr>
<td>-a</td>
<td>Put array data</td>
<td>Default:</td>
<td>Put scalar</td>
</tr>
<tr>
<td></td>
<td>Value format: Print number of requested values, then list of
values</td>
<td>Value format: all value arguments concatenated with spaces</td>
</tr>
<tr>
<td>-S</td>
<td>Put string as an array of char (long string)</td>
<td>Put string as an array of chars (long string)</td>
</tr>
<tr>
<td>-a</td>
<td>Put array</td>
</tr>
<tr>
<td></td>
<td>Value format: number of values, then list of values</td>
</tr>
</tbody>
</table>
@@ -2719,7 +2746,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.
@@ -2894,7 +2921,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>
@@ -3002,7 +3029,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>
@@ -3103,8 +3130,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>
@@ -3402,7 +3429,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
@@ -3537,7 +3564,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>
@@ -3585,7 +3612,7 @@ 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.
<pre>typedef struct ca_access_rights {

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

@@ -504,6 +504,7 @@ void ca_repeater ()
if ( sockerrno == SOCK_EADDRINUSE ) {
osiSockRelease ();
debugPrintf ( ( "CA Repeater: exiting because a repeater is already running\n" ) );
delete [] pBuf;
return;
}
char sockErrBuf[64];

View File

@@ -902,10 +902,12 @@ bool udpiiu::pushDatagramMsg ( epicsGuard < epicsMutex > & guard,
caHdr * pbufmsg = ( caHdr * ) &this->xmitBuf[this->nBytesInXmitBuf];
*pbufmsg = msg;
memcpy ( pbufmsg + 1, pExt, extsize );
if ( extsize != alignedExtSize ) {
char *pDest = (char *) ( pbufmsg + 1 );
memset ( pDest + extsize, '\0', alignedExtSize - extsize );
if ( extsize ) {
memcpy ( pbufmsg + 1, pExt, extsize );
if ( extsize != alignedExtSize ) {
char *pDest = (char *) ( pbufmsg + 1 );
memset ( pDest + extsize, '\0', alignedExtSize - extsize );
}
}
AlignedWireRef < epicsUInt16 > ( pbufmsg->m_postsize ) = alignedExtSize;
this->nBytesInXmitBuf += msgsize;

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

@@ -170,7 +170,7 @@ static int parseDirectoryFP (FILE *pf, const char *pFileName)
status = aToIPAddr (hostNameStr, 0u, &ipa);
if (status) {
fprintf (pf, "Unknown host name=\"%s\" (or bad dotted ip addr) in \"%s\" with PV=\"%s\"?\n",
fprintf (stderr, "Unknown host name=\"%s\" (or bad dotted ip addr) in \"%s\" with PV=\"%s\"?\n",
hostNameStr, pFileName, pvNameStr);
return -1;
}

View File

@@ -21,6 +21,7 @@ casChannelI::casChannelI ( casCoreClient & clientIn,
casChannel & chanIn, casPVI & pvIn, ca_uint32_t cidIn ) :
privateForPV ( clientIn, *this ),
pv ( pvIn ),
maxElem( pvIn.nativeCount() ),
chan ( chanIn ),
cid ( cidIn ),
serverDeletePending ( false ),
@@ -29,7 +30,7 @@ casChannelI::casChannelI ( casCoreClient & clientIn,
}
casChannelI::~casChannelI ()
{
{
this->privateForPV.client().removeFromEventQueue (
*this, this->accessRightsEvPending );
@@ -48,7 +49,7 @@ void casChannelI::uninstallFromPV ( casEventSys & eventSys )
this->privateForPV.removeSelfFromPV ( this->pv, dest );
while ( casMonitor * pMon = dest.get () ) {
eventSys.prepareMonitorForDestroy ( *pMon );
}
}
}
void casChannelI::show ( unsigned level ) const
@@ -68,13 +69,13 @@ caStatus casChannelI::cbFunc (
{
caStatus stat = S_cas_success;
{
stat = this->privateForPV.client().accessRightsResponse (
stat = this->privateForPV.client().accessRightsResponse (
clientGuard, this );
}
if ( stat == S_cas_success ) {
this->accessRightsEvPending = false;
}
return stat;
if ( stat == S_cas_success ) {
this->accessRightsEvPending = false;
}
return stat;
}
caStatus casChannelI::read ( const casCtx & ctx, gdd & prototype )

View File

@@ -1,4 +1,3 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
@@ -31,55 +30,62 @@ class casChannelI : public tsDLNode < casChannelI >,
public:
casChannelI ( casCoreClient & clientIn, casChannel & chanIn,
casPVI & pvIn, ca_uint32_t cidIn );
~casChannelI ();
~casChannelI ();
void casChannelDestroyFromInterfaceNotify ();
const caResId getCID ();
const caResId getSID ();
const caResId getCID ();
const caResId getSID ();
void uninstallFromPV ( casEventSys & eventSys );
void installIntoPV ();
void installIO ( casAsyncIOI & );
void uninstallIO ( casAsyncIOI & );
void installMonitor ( casMonitor & mon );
casMonitor * removeMonitor ( ca_uint32_t clientIdIn );
casPVI & getPVI () const;
void clearOutstandingReads ();
void postAccessRightsEvent ();
casPVI & getPVI () const;
void clearOutstandingReads ();
void postAccessRightsEvent ();
const gddEnumStringTable & enumStringTable () const;
void setOwner ( const char * const pUserName,
const char * const pHostName );
bool readAccess () const;
ca_uint32_t getMaxElem () const;
void setOwner ( const char * const pUserName,
const char * const pHostName );
bool readAccess () const;
bool writeAccess () const;
bool confirmationRequested () const;
bool confirmationRequested () const;
caStatus read ( const casCtx & ctx, gdd & prototype );
caStatus write ( const casCtx & ctx, const gdd & value );
caStatus writeNotify ( const casCtx & ctx, const gdd & value );
void show ( unsigned level ) const;
void show ( unsigned level ) const;
private:
chanIntfForPV privateForPV;
tsDLList < casAsyncIOI > ioList;
casPVI & pv;
tsDLList < casAsyncIOI > ioList;
casPVI & pv;
ca_uint32_t maxElem;
casChannel & chan;
caResId cid; // client id
caResId cid; // client id
bool serverDeletePending;
bool accessRightsEvPending;
//epicsShareFunc virtual void destroy ();
caStatus cbFunc (
bool accessRightsEvPending;
//epicsShareFunc virtual void destroy ();
caStatus cbFunc (
casCoreClient &,
epicsGuard < casClientMutex > &,
epicsGuard < evSysMutex > & );
void postDestroyEvent ();
casChannelI ( const casChannelI & );
casChannelI & operator = ( const casChannelI & );
casChannelI ( const casChannelI & );
casChannelI & operator = ( const casChannelI & );
};
inline casPVI & casChannelI::getPVI () const
{
return this->pv;
return this->pv;
}
inline ca_uint32_t casChannelI::getMaxElem () const
{
return this->maxElem;
}
inline const caResId casChannelI::getCID ()
{
return this->cid;
return this->cid;
}
inline const caResId casChannelI::getSID ()
@@ -89,7 +95,7 @@ inline const caResId casChannelI::getSID ()
inline void casChannelI::postAccessRightsEvent ()
{
this->privateForPV.client().addToEventQueue ( *this, this->accessRightsEvPending );
this->privateForPV.client().addToEventQueue ( *this, this->accessRightsEvPending );
}
inline const gddEnumStringTable & casChannelI::enumStringTable () const
@@ -108,7 +114,7 @@ inline void casChannelI::clearOutstandingReads ()
}
inline void casChannelI::setOwner ( const char * const pUserName,
const char * const pHostName )
const char * const pHostName )
{
this->chan.setOwner ( pUserName, pHostName );
}

View File

@@ -24,39 +24,39 @@
casDGClient::pCASMsgHandler const casDGClient::msgHandlers[] =
{
& casDGClient::versionAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::versionAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::searchAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::echoAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::echoAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction
};
//
@@ -84,7 +84,7 @@ casDGClient::~casDGClient()
//
void casDGClient::destroy()
{
printf("Attempt to destroy the DG client was ignored\n");
printf("Attempt to destroy the DG client was ignored\n");
}
//
@@ -92,16 +92,16 @@ void casDGClient::destroy()
//
void casDGClient::show (unsigned level) const
{
printf ( "casDGClient at %p\n",
printf ( "casDGClient at %p\n",
static_cast <const void *> ( this ) );
if (level>=1u) {
char buf[64];
this->hostName (buf, sizeof(buf));
printf ("Client Host=%s\n", buf);
if (level>=1u) {
char buf[64];
this->hostName (buf, sizeof(buf));
printf ("Client Host=%s\n", buf);
this->casCoreClient::show ( level - 1u );
this->in.show ( level - 1u );
this->out.show ( level - 1u );
}
}
}
//
@@ -109,7 +109,7 @@ void casDGClient::show (unsigned level) const
//
caStatus casDGClient::uknownMessageAction ()
{
const caHdrLargeArray * mp = this->ctx.getMsg();
const caHdrLargeArray * mp = this->ctx.getMsg();
char pHostName[64u];
this->lastRecvAddr.stringConvert ( pHostName, sizeof ( pHostName ) );
@@ -117,7 +117,7 @@ caStatus casDGClient::uknownMessageAction ()
caServerI::dumpMsg ( pHostName, "?", mp, this->ctx.getData(),
"bad request code=%u in DG\n", mp->m_cmmd );
return S_cas_badProtocol;
return S_cas_badProtocol;
}
//
@@ -125,9 +125,9 @@ caStatus casDGClient::uknownMessageAction ()
//
caStatus casDGClient::searchAction()
{
const caHdrLargeArray *mp = this->ctx.getMsg();
const caHdrLargeArray *mp = this->ctx.getMsg();
const char *pChanName = static_cast <char * > ( this->ctx.getData() );
caStatus status;
caStatus status;
//
// check the sanity of the message
@@ -135,7 +135,7 @@ caStatus casDGClient::searchAction()
if ( mp->m_postsize <= 1 ) {
char pHostName[64u];
this->lastRecvAddr.stringConvert ( pHostName, sizeof ( pHostName ) );
caServerI::dumpMsg ( pHostName, "?", mp, this->ctx.getData(),
caServerI::dumpMsg ( pHostName, "?", mp, this->ctx.getData(),
"empty PV name extension in UDP search request?\n" );
return S_cas_success;
}
@@ -143,7 +143,7 @@ caStatus casDGClient::searchAction()
if ( pChanName[0] == '\0' ) {
char pHostName[64u];
this->lastRecvAddr.stringConvert ( pHostName, sizeof ( pHostName ) );
caServerI::dumpMsg ( pHostName, "?", mp, this->ctx.getData(),
caServerI::dumpMsg ( pHostName, "?", mp, this->ctx.getData(),
"zero length PV name in UDP search request?\n" );
return S_cas_success;
}
@@ -155,56 +155,56 @@ caStatus casDGClient::searchAction()
if ( i <= 1 ) {
char pHostName[64u];
this->lastRecvAddr.stringConvert ( pHostName, sizeof ( pHostName ) );
caServerI::dumpMsg ( pHostName, "?", mp, this->ctx.getData(),
caServerI::dumpMsg ( pHostName, "?", mp, this->ctx.getData(),
"unterminated PV name in UDP search request?\n" );
return S_cas_success;
}
}
if ( this->getCAS().getDebugLevel() > 6u ) {
char pHostName[64u];
this->hostName ( pHostName, sizeof ( pHostName ) );
printf ( "\"%s\" is searching for \"%s\"\n",
if ( this->getCAS().getDebugLevel() > 6u ) {
char pHostName[64u];
this->hostName ( pHostName, sizeof ( pHostName ) );
printf ( "\"%s\" is searching for \"%s\"\n",
pHostName, pChanName );
}
}
//
// verify that we have sufficent memory for a PV and a
// monitor prior to calling PV exist test so that when
// the server runs out of memory we dont reply to
// search requests, and therefore dont thrash through
// caServer::pvExistTest() and casCreatePV::pvAttach()
//
//
// verify that we have sufficent memory for a PV and a
// monitor prior to calling PV exist test so that when
// the server runs out of memory we dont reply to
// search requests, and therefore dont thrash through
// caServer::pvExistTest() and casCreatePV::pvAttach()
//
if ( ! osiSufficentSpaceInPool ( 0 ) ) {
return S_cas_success;
}
//
// ask the server tool if this PV exists
//
this->userStartedAsyncIO = false;
pvExistReturn pver =
this->getCAS()->pvExistTest ( this->ctx, this->lastRecvAddr, pChanName );
//
// ask the server tool if this PV exists
//
this->userStartedAsyncIO = false;
pvExistReturn pver =
this->getCAS()->pvExistTest ( this->ctx, this->lastRecvAddr, pChanName );
//
// prevent problems when they initiate
// async IO but dont return status
// indicating so (and vise versa)
//
if ( this->userStartedAsyncIO ) {
//
// prevent problems when they initiate
// async IO but dont return status
// indicating so (and vise versa)
//
if ( this->userStartedAsyncIO ) {
if ( pver.getStatus() != pverAsyncCompletion ) {
errMessage (S_cas_badParameter,
"- assuming asynch IO status from caServer::pvExistTest()");
errMessage (S_cas_badParameter,
"- assuming asynch IO status from caServer::pvExistTest()");
}
status = S_cas_success;
}
else {
//
// otherwise we assume sync IO operation was initiated
//
}
else {
//
// otherwise we assume sync IO operation was initiated
//
switch ( pver.getStatus() ) {
case pverExistsHere:
status = this->searchResponse (*mp, pver);
status = this->searchResponse (*mp, pver);
break;
case pverDoesNotExistHere:
@@ -212,18 +212,18 @@ caStatus casDGClient::searchAction()
break;
case pverAsyncCompletion:
errMessage (S_cas_badParameter,
"- unexpected asynch IO status from caServer::pvExistTest() ignored");
errMessage (S_cas_badParameter,
"- unexpected asynch IO status from caServer::pvExistTest() ignored");
status = S_cas_success;
break;
default:
errMessage (S_cas_badParameter,
"- invalid return from caServer::pvExistTest() ignored");
errMessage (S_cas_badParameter,
"- invalid return from caServer::pvExistTest() ignored");
status = S_cas_success;
break;
}
}
}
}
return status;
}
@@ -340,21 +340,21 @@ caStatus casDGClient::searchResponse ( const caHdrLargeArray & msg,
}
//
// casDGClient::searchFailResponse()
// (only when requested by the client
// - when it isnt a reply to a broadcast)
// casDGClient::searchFailResponse()
// (only when requested by the client
// - when it isnt a reply to a broadcast)
//
caStatus casDGClient::searchFailResponse ( const caHdrLargeArray * mp )
{
int status;
int status;
epicsGuard < epicsMutex > guard ( this->mutex );
status = this->out.copyInHeader ( CA_PROTO_NOT_FOUND, 0,
mp->m_dataType, mp->m_count, mp->m_cid, mp->m_available, 0 );
this->out.commitMsg ();
this->out.commitMsg ();
return S_cas_success;
return S_cas_success;
}
/*
@@ -362,7 +362,7 @@ caStatus casDGClient::searchFailResponse ( const caHdrLargeArray * mp )
*/
caStatus casDGClient::versionAction ()
{
const caHdrLargeArray * mp = this->ctx.getMsg();
const caHdrLargeArray * mp = this->ctx.getMsg();
if ( mp->m_count != 0 ) {
this->minor_version_number = static_cast <ca_uint16_t> ( mp->m_count );
@@ -373,7 +373,7 @@ caStatus casDGClient::versionAction ()
this->seqNoOfReq = 0;
}
}
return S_cas_success;
return S_cas_success;
}
//
@@ -382,25 +382,25 @@ caStatus casDGClient::versionAction ()
//
void casDGClient::sendBeacon ( ca_uint32_t beaconNumber )
{
union {
caHdr msg;
char buf;
};
union {
caHdr msg;
char buf;
};
//
// create the message
//
memset ( & buf, 0, sizeof ( msg ) );
//
// create the message
//
memset ( & buf, 0, sizeof ( msg ) );
AlignedWireRef < epicsUInt16 > ( msg.m_cmmd ) = CA_PROTO_RSRV_IS_UP;
AlignedWireRef < epicsUInt16 > ( msg.m_dataType ) = CA_MINOR_PROTOCOL_REVISION;
AlignedWireRef < epicsUInt32 > ( msg.m_cid ) = beaconNumber;
//
// send it to all addresses on the beacon list,
//
// send it to all addresses on the beacon list,
// but let the IO specific code set the address
// field and the port field
//
this->sendBeaconIO ( buf, sizeof (msg), msg.m_count, msg.m_available );
//
this->sendBeaconIO ( buf, sizeof (msg), msg.m_count, msg.m_available );
}
//
@@ -421,8 +421,8 @@ outBufClient::flushCondition casDGClient::xSend ( char *pBufIn,
if ( pHdr->cadg_addr.isValid() ) {
outBufClient::flushCondition stat =
this->osdSend ( pDG, sizeDG, pHdr->cadg_addr );
if ( stat != outBufClient::flushProgress ) {
this->osdSend ( pDG, sizeDG, pHdr->cadg_addr );
if ( stat != outBufClient::flushProgress ) {
break;
}
}
@@ -431,10 +431,10 @@ outBufClient::flushCondition casDGClient::xSend ( char *pBufIn,
}
if ( totalBytes ) {
//
// !! this time fetch may be slowing things down !!
//
//this->lastSendTS = epicsTime::getCurrent();
//
// !! this time fetch may be slowing things down !!
//
//this->lastSendTS = epicsTime::getCurrent();
nBytesSent = totalBytes;
return outBufClient::flushProgress;
}
@@ -457,16 +457,16 @@ inBufClient::fillCondition casDGClient::xRecv (char *pBufIn, bufSizeT nBytesToRe
while (pAfter-pCurBuf >= static_cast<int>(MAX_UDP_RECV+sizeof(cadg))) {
pHdr = reinterpret_cast < cadg * > ( pCurBuf );
stat = this->osdRecv ( reinterpret_cast < char * > ( pHdr + 1 ),
stat = this->osdRecv ( reinterpret_cast < char * > ( pHdr + 1 ),
MAX_UDP_RECV, parm, nDGBytesRecv, pHdr->cadg_addr);
if (stat==casFillProgress) {
if (stat==casFillProgress) {
pHdr->cadg_nBytes = nDGBytesRecv + sizeof(*pHdr);
pCurBuf += pHdr->cadg_nBytes;
//
// !! this time fetch may be slowing things down !!
//
//this->lastRecvTS = epicsTime::getCurrent();
}
//
// !! this time fetch may be slowing things down !!
//
//this->lastRecvTS = epicsTime::getCurrent();
}
else {
break;
}
@@ -517,7 +517,7 @@ caStatus casDGClient::asyncSearchResponse (
pMsg->m_dataType = htons ( sequenceNoIsValid );
}
caStatus stat = this->searchResponse ( msg, retVal );
caStatus stat = this->searchResponse ( msg, retVal );
pRespHdr->cadg_nBytes = this->out.popCtx (outctx) + sizeof ( *pRespHdr );
if ( pRespHdr->cadg_nBytes > sizeof ( *pRespHdr ) + sizeof (caHdr) ) {
@@ -525,7 +525,7 @@ caStatus casDGClient::asyncSearchResponse (
this->out.commitRawMsg ( pRespHdr->cadg_nBytes );
}
return stat;
return stat;
}
//
@@ -655,7 +655,7 @@ caStatus casDGClient::processDG ()
//
unsigned casDGClient::getDebugLevel() const
{
return this->getCAS().getDebugLevel();
return this->getCAS().getDebugLevel();
}
//
@@ -663,7 +663,7 @@ unsigned casDGClient::getDebugLevel() const
//
caNetAddr casDGClient::fetchLastRecvAddr () const
{
return this->lastRecvAddr;
return this->lastRecvAddr;
}
//
@@ -671,7 +671,7 @@ caNetAddr casDGClient::fetchLastRecvAddr () const
//
ca_uint32_t casDGClient::datagramSequenceNumber () const
{
return this->seqNoOfReq;
return this->seqNoOfReq;
}
//
@@ -731,27 +731,27 @@ outBufClient::flushCondition casDGClient::flush ()
//
caStatus casDGClient::processMsg ()
{
int status = S_cas_success;
int status = S_cas_success;
try {
unsigned bytesLeft;
while ( ( bytesLeft = this->in.bytesPresent() ) ) {
unsigned bytesLeft;
while ( ( bytesLeft = this->in.bytesPresent() ) ) {
caHdrLargeArray msgTmp;
unsigned msgSize;
ca_uint32_t hdrSize;
char * rawMP;
{
//
// copy as raw bytes in order to avoid
// alignment problems
//
//
// copy as raw bytes in order to avoid
// alignment problems
//
caHdr smallHdr;
if ( bytesLeft < sizeof ( smallHdr ) ) {
break;
}
rawMP = this->in.msgPtr ();
memcpy ( & smallHdr, rawMP, sizeof ( smallHdr ) );
memcpy ( & smallHdr, rawMP, sizeof ( smallHdr ) );
ca_uint32_t payloadSize = AlignedWireRef < epicsUInt16 > ( smallHdr.m_postsize );
ca_uint32_t nElem = AlignedWireRef < epicsUInt16 > ( smallHdr.m_count );
@@ -800,45 +800,45 @@ caStatus casDGClient::processMsg ()
this->ctx.setMsg ( msgTmp, rawMP + hdrSize );
if ( this->getCAS().getDebugLevel() > 5u ) {
if ( this->getCAS().getDebugLevel() > 5u ) {
char pHostName[64u];
this->lastRecvAddr.stringConvert ( pHostName, sizeof ( pHostName ) );
caServerI::dumpMsg ( pHostName, "?",
caServerI::dumpMsg ( pHostName, "?",
& msgTmp, rawMP + hdrSize, 0 );
}
}
}
//
// Reset the context to the default
// (guarantees that previous message does not get mixed
// up with the current message)
//
this->ctx.setChannel ( NULL );
this->ctx.setPV ( NULL );
//
// Reset the context to the default
// (guarantees that previous message does not get mixed
// up with the current message)
//
this->ctx.setChannel ( NULL );
this->ctx.setPV ( NULL );
//
// Call protocol stub
//
//
// Call protocol stub
//
casDGClient::pCASMsgHandler pHandler;
if ( msgTmp.m_cmmd < NELEMENTS ( casDGClient::msgHandlers ) ) {
if ( msgTmp.m_cmmd < NELEMENTS ( casDGClient::msgHandlers ) ) {
pHandler = this->casDGClient::msgHandlers[msgTmp.m_cmmd];
}
}
else {
pHandler = & casDGClient::uknownMessageAction;
}
status = ( this->*pHandler ) ();
if ( status ) {
status = ( this->*pHandler ) ();
if ( status ) {
this->in.removeMsg ( this->in.bytesPresent() );
break;
}
break;
}
this->in.removeMsg ( msgSize );
}
}
}
catch ( std::exception & except ) {
this->in.removeMsg ( this->in.bytesPresent() );
status = this->sendErr (
this->sendErr (
this->ctx.getMsg(), invalidResID, ECA_INTERNAL,
"C++ exception \"%s\" in CA circuit server",
except.what () );
@@ -846,13 +846,13 @@ caStatus casDGClient::processMsg ()
}
catch (...) {
this->in.removeMsg ( this->in.bytesPresent() );
status = this->sendErr (
this->sendErr (
this->ctx.getMsg(), invalidResID, ECA_INTERNAL,
"unexpected C++ exception in CA datagram server" );
status = S_cas_internal;
}
return status;
return status;
}
//
@@ -861,24 +861,25 @@ caStatus casDGClient::processMsg ()
caStatus casDGClient::sendErr ( const caHdrLargeArray *curp,
ca_uint32_t cid, const int reportedStatus, const char *pformat, ... )
{
unsigned stringSize;
char msgBuf[1024]; /* allocate plenty of space for the message string */
if ( pformat ) {
va_list args;
va_start ( args, pformat );
int status = vsprintf ( msgBuf, pformat, args );
if ( status < 0 ) {
errPrintf (S_cas_internal, __FILE__, __LINE__,
"bad sendErr(%s)", pformat);
stringSize = 0u;
}
else {
stringSize = 1u + (unsigned) status;
}
}
else {
stringSize = 0u;
}
unsigned stringSize;
char msgBuf[1024]; /* allocate plenty of space for the message string */
if ( pformat ) {
va_list args;
va_start ( args, pformat );
int status = vsprintf ( msgBuf, pformat, args );
if ( status < 0 ) {
errPrintf (S_cas_internal, __FILE__, __LINE__,
"bad sendErr(%s)", pformat);
stringSize = 0u;
}
else {
stringSize = 1u + (unsigned) status;
}
va_end ( args );
}
else {
stringSize = 0u;
}
unsigned hdrSize = sizeof ( caHdr );
if ( ( curp->m_postsize >= 0xffff || curp->m_count >= 0xffff ) &&
@@ -929,7 +930,7 @@ caStatus casDGClient::sendErr ( const caHdrLargeArray *curp,
this->out.commitMsg ();
}
return S_cas_success;
return S_cas_success;
}
@@ -938,8 +939,8 @@ caStatus casDGClient::sendErr ( const caHdrLargeArray *curp,
//
caStatus casDGClient::echoAction ()
{
const caHdrLargeArray * mp = this->ctx.getMsg();
const void * dp = this->ctx.getData();
const caHdrLargeArray * mp = this->ctx.getMsg();
const void * dp = this->ctx.getData();
void * pPayloadOut;
epicsGuard < epicsMutex > guard ( this->mutex );
@@ -950,5 +951,5 @@ caStatus casDGClient::echoAction ()
memcpy ( pPayloadOut, dp, mp->m_postsize );
this->out.commitMsg ();
}
return S_cas_success;
return S_cas_success;
}

View File

@@ -409,7 +409,7 @@ caStatus casStrmClient::verifyRequest (casChannelI * & pChan , bool allowdyn)
//
// element count out of range ?
//
if ( ctx.msg.m_count > pChan->getPVI().nativeCount() ||
if ( ctx.msg.m_count > pChan->getMaxElem() ||
( !allowdyn && ctx.msg.m_count == 0u ) ) {
return ECA_BADCOUNT;
}
@@ -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;
@@ -856,8 +880,20 @@ caStatus casStrmClient::monitorResponse (
casChannelI & chan, const caHdrLargeArray & msg,
const gdd & desc, const caStatus completionStatus )
{
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 = 0;
@@ -883,7 +919,7 @@ caStatus casStrmClient::monitorResponse (
gdd * pDBRDD = 0;
if ( completionStatus == S_cas_success ) {
caStatus status = createDBRDD ( msg.m_dataType, count,
chan.getPVI().nativeCount(), pDBRDD );
chan.getMaxElem(), pDBRDD );
if ( status != S_cas_success ) {
caStatus ecaStatus;
if ( status == S_cas_badType ) {
@@ -1854,7 +1890,7 @@ caStatus casStrmClient::privateCreateChanResponse (
// the protocol buffer.
//
assert ( nativeTypeDBR <= 0xffff );
aitIndex nativeCount = chan.getPVI().nativeCount();
aitIndex nativeCount = chan.getMaxElem();
assert ( nativeCount <= 0xffffffff );
assert ( hdr.m_cid == chan.getCID() );
status = this->out.copyInHeader ( CA_PROTO_CREATE_CHAN, 0,
@@ -2614,7 +2650,7 @@ caStatus casStrmClient::read ()
{
gdd * pDD = 0;
caStatus status = createDBRDD ( pHdr->m_dataType, pHdr->m_count,
this->ctx.getChannel()->getPVI().nativeCount(), pDD );
this->ctx.getChannel()->getMaxElem(), pDD );
if ( status != S_cas_success ) {
return status;
}
@@ -2761,6 +2797,7 @@ caStatus casStrmClient::sendErr ( epicsGuard <casClientMutex> &,
else {
stringSize = 1u + (unsigned) status;
}
va_end ( args );
}
else {
stringSize = 0u;

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

@@ -56,7 +56,7 @@ static epicsEventId epId;
void usage (void)
{
fprintf (stderr, "\nUsage: caput [options] <PV name> <PV value>\n"
fprintf (stderr, "\nUsage: caput [options] <PV name> <PV value> ...\n"
" caput -a [options] <PV name> <no of values> <PV value> ...\n\n"
" -h: Help: Print this message\n"
"Channel Access options:\n"
@@ -71,9 +71,11 @@ void usage (void)
" -n: Force interpretation of values as numbers\n"
" -s: Force interpretation of values as strings\n"
"Arrays:\n"
" Default: Put scalar\n"
" Value format: all value arguments concatenated with spaces\n"
" -S: Put string as an array of chars (long string)\n"
" -a: Put array\n"
" Value format: number of requested values, then list of values\n"
" -S: Put string as an array of char (long string)\n"
" Value format: number of values, then list of values\n"
"\nExample: caput my_channel 1.2\n"
" (puts 1.2 to my_channel)\n\n"
, DEFAULT_TIMEOUT, CA_PRIORITY_MAX);

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);
}
}

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

@@ -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);

View File

@@ -126,8 +126,8 @@ long dbcar(char *precordname, int level)
precord->name,
pdbFldDes->name,
plink->value.pv_link.pvname,
pca->nDisconnect,
pca->nNoWrite);
pca ? pca->nDisconnect : 0,
pca ? pca->nNoWrite : 0);
}
}
}

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,11 +3940,10 @@ static long putFloatString(
const float *pbuffer = (const float *)pfrom;
char *pdest=(char *)(paddr->pfield);
long status = 0;
int precision = 6;
struct rset *prset = 0;
long precision = 6;
struct rset *prset = dbGetRset(paddr);
short size=paddr->field_size;
if(paddr) prset = dbGetRset(paddr);
if(prset && (prset->get_precision))
status = (*prset->get_precision)(paddr,&precision);
if(nRequest==1 && offset==0) {
@@ -4151,11 +4150,10 @@ static long putDoubleString(
const double *pbuffer = (const double *)pfrom;
char *pdest=(char *)(paddr->pfield);
long status = 0;
int precision = 6;
struct rset *prset = 0;
long precision = 6;
struct rset *prset = dbGetRset(paddr);
short size=paddr->field_size;
if(paddr) prset = dbGetRset(paddr);
if(prset && (prset->get_precision))
status = (*prset->get_precision)(paddr,&precision);
if(nRequest==1 && offset==0) {

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

@@ -699,8 +699,9 @@ int epicsShareAPI tpn(char *pname,char *pvalue)
return(-1);
}
ppn = calloc(1,sizeof(putNotify));
if(!pdbaddr) {
if(!ppn) {
printf("calloc failed\n");
free((void *)pdbaddr);
return(-1);
}
ppn->paddr = pdbaddr;
@@ -708,13 +709,14 @@ int epicsShareAPI tpn(char *pname,char *pvalue)
ppn->nRequest = 1;
if(dbPutNotifyMapType(ppn,DBR_STRING)) {
printf("dbPutNotifyMapType failed\n");
printf("calloc failed\n");
free((void *)pdbaddr);
return(-1);
}
ppn->userCallback = tpnCallback;
ptpnInfo = calloc(1,sizeof(tpnInfo));
if(!ptpnInfo) {
printf("calloc failed\n");
free((void *)pdbaddr);
return(-1);
}
ptpnInfo->ppn = ppn;

View File

@@ -229,24 +229,25 @@ static long dbReadCOM(DBBASE **ppdbbase,const char *filename, FILE *fp,
}
}
pinputFile = dbCalloc(1,sizeof(inputFile));
if(filename) {
pinputFile->filename = macEnvExpand(filename);
if (filename) {
pinputFile->filename = macEnvExpand(filename);
}
if(!fp) {
FILE *fp1;
if (!fp) {
FILE *fp1 = 0;
if(pinputFile->filename) pinputFile->path = dbOpenFile(pdbbase,pinputFile->filename,&fp1);
if(!pinputFile->filename || !fp1) {
errPrintf(0,__FILE__, __LINE__,
"dbRead opening file %s",pinputFile->filename);
free((void *)pinputFile->filename);
free((void *)pinputFile);
if (pinputFile->filename)
pinputFile->path = dbOpenFile(pdbbase, pinputFile->filename, &fp1);
if (!pinputFile->filename || !fp1) {
errPrintf(0, __FILE__, __LINE__,
"dbRead opening file %s",pinputFile->filename);
free(pinputFile->filename);
free(pinputFile);
status = -1;
goto cleanup;
}
pinputFile->fp = fp1;
}
pinputFile->fp = fp1;
} else {
pinputFile->fp = fp;
pinputFile->fp = fp;
}
pinputFile->line_num = 0;
pinputFileNow = pinputFile;

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

@@ -308,7 +308,7 @@ void gdd::test()
pdd->convertOffsetsToAddress();
pdd->dump();
pdd->unreference();
delete buf;
delete [] buf;
}
#endif
@@ -510,7 +510,7 @@ void gddContainer::test(void)
fprintf(stderr,"=====RE-DUMP OF ORIGINAL CONTAINER:\n");
dump();
cdd1->unreference();
delete buf;
delete [] buf;
// test copy(), Dup(), copyInfo()
fprintf(stderr,"=======CREATING TEST CONTAINER FOR *COPY* TEST:\n");

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

@@ -239,6 +239,18 @@ int epicsStrPrintEscaped(FILE *fp, const char *s, size_t len)
return nout;
}
/* Until Base requires POSIX 2008 we must provide our own implementation */
size_t epicsStrnLen(const char *s, size_t maxlen)
{
size_t i;
for (i=0; i<maxlen; i++) {
if(s[i]=='\0')
return i;
}
return i;
}
int epicsStrGlobMatch(const char *str, const char *pattern)
{
const char *cp = NULL, *mp = NULL;

View File

@@ -33,6 +33,7 @@ epicsShareFunc int epicsStrnCaseCmp(const char *s1, const char *s2, size_t len);
epicsShareFunc char * epicsStrDup(const char *s);
epicsShareFunc int epicsStrPrintEscaped(FILE *fp, const char *s, size_t n);
#define epicsStrSnPrintEscaped epicsStrnEscapedFromRaw
epicsShareFunc size_t epicsStrnLen(const char *s, size_t maxlen);
epicsShareFunc int epicsStrGlobMatch(const char *str, const char *pattern);
epicsShareFunc char * epicsStrtok_r(char *s, const char *delim, char **lasts);
epicsShareFunc unsigned int epicsStrHash(const char *str, unsigned int seed);

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

@@ -378,7 +378,7 @@ static gtProvider * findProvider(ELLLIST *plist, epicsMutexId lock,
for (ptp = (gtProvider *)ellFirst(plist);
ptp; ptp = (gtProvider *)ellNext(&ptp->node)) {
if (ptp->priority == ptp->priority &&
if (ptp->priority == priority &&
!strcmp(ptp->name, name))
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

@@ -167,7 +167,7 @@ static int receiveMessage(
return -1;
}
rsize = receiveMessage(id, id->localBuf, id->maxSize, wait, delay);
if ((rsize < 0) || (rsize > size))
if (rsize > size)
return -1;
memcpy(buffer, id->localBuf, rsize);
}

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

@@ -404,8 +404,6 @@ void epicsThreadGetName (epicsThreadId id, char *name, size_t size)
struct taskVar *v;
int haveName = 0;
if (size <= 0)
return;
taskVarLock ();
for (v=taskVarHead ; v != NULL ; v=v->forw) {
if (v->id == tid) {

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

@@ -517,13 +517,8 @@ static win32ThreadParam * epicsThreadParmCreate ( const char *pName )
pParmWIN32 = calloc ( 1, sizeof ( *pParmWIN32 ) + strlen ( pName ) + 1 );
if ( pParmWIN32 ) {
if ( pName ) {
pParmWIN32->pName = (char *) ( pParmWIN32 + 1 );
strcpy ( pParmWIN32->pName, pName );
}
else {
pParmWIN32->pName = 0;
}
pParmWIN32->pName = (char *) ( pParmWIN32 + 1 );
strcpy ( pParmWIN32->pName, pName );
pParmWIN32->isSuspended = 0;
}
return pParmWIN32;

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

@@ -38,7 +38,14 @@ static void testEpicsSnprintf(void) {
const char *expected = exbuffer;
int size;
int rtn, rlen;
#ifdef _WIN32
#if (defined(_MSC_VER) && _MSC_VER < 1900) || \
(defined(_MINGW) && defined(_TWO_DIGIT_EXPONENT))
_set_output_format(_TWO_DIGIT_EXPONENT);
#endif
#endif
sprintf(exbuffer, format, ivalue, fvalue, svalue);
rlen = strlen(expected)+1;
@@ -122,11 +129,7 @@ void testStdoutRedir (const char *report)
MAIN(epicsStdioTest)
{
#ifdef _WIN32
testPlan(166);
#else
testPlan(163);
#endif
testEpicsSnprintf();
testStdoutRedir("report");
return testDone();

View File

@@ -51,7 +51,7 @@ MAIN(epicsStringTest)
char *s;
int status;
testPlan(299);
testPlan(303);
testChars();
@@ -86,6 +86,11 @@ MAIN(epicsStringTest)
testOk1(epicsStrHash(abcd, 0) == epicsMemHash(abcde, 4, 0));
testOk1(epicsStrHash(abcd, 0) != epicsMemHash("abcd\0", 5, 0));
testOk1(epicsStrnLen("abcd", 5)==4);
testOk1(epicsStrnLen("abcd", 4)==4);
testOk1(epicsStrnLen("abcd", 3)==3);
testOk1(epicsStrnLen("abcd", 0)==0);
memset(result, 'x', sizeof(result));
status = epicsStrnEscapedFromRaw(result, 4, ABCD, 3);
testOk(status == 3, "epicsStrnEscapedFromRaw returned %d (exp. 3)", status);

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

@@ -109,6 +109,7 @@ int main(int argc,char **argv)
pmynode[npv] = callocMustSucceed(1, sizeof(MYNODE), "caMonitor");
npv++;
}
fclose(fp);
SEVCHK(ca_context_create(ca_disable_preemptive_callback),"ca_context_create");
SEVCHK(ca_add_exception_event(exceptionCallback,NULL),
"ca_add_exception_event");

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