Compare commits
164 Commits
R3.15.5-pr
...
current-3.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7dd1ea4cab | ||
|
|
922ed30136 | ||
|
|
9f9f119e7e | ||
|
|
d8214a4531 | ||
|
|
120b100e7e | ||
|
|
949e9d788a | ||
|
|
27c6e6a385 | ||
|
|
4b59476170 | ||
|
|
526b565c6b | ||
|
|
1b7b2bcceb | ||
|
|
49c925d064 | ||
|
|
d3bcf5737f | ||
|
|
6c5505ad3e | ||
|
|
4247d98b08 | ||
|
|
13735a8088 | ||
|
|
58d4242b68 | ||
|
|
8e42f516b0 | ||
|
|
9051cdbb34 | ||
|
|
2548a37267 | ||
|
|
1dc1b25aaa | ||
|
|
fb31dd784b | ||
| 89870e2817 | |||
| 4e9cf72d71 | |||
| 80869a0868 | |||
| 998fa984ba | |||
| 31844af88e | |||
| 8f161f9463 | |||
| e0399478ad | |||
|
|
2a2a1e54ac | ||
|
|
20d2cff501 | ||
|
|
860ce156a2 | ||
|
|
31fc35fbe8 | ||
| ab493264b2 | |||
| 68779943eb | |||
| 7a5ff26984 | |||
| eae59183cc | |||
|
|
b32629c3bf | ||
|
|
220e404203 | ||
|
|
8f55a1307d | ||
|
|
e459e8bdd4 | ||
|
|
b558bd9b16 | ||
|
|
3c16c3c0da | ||
|
|
67844bacc3 | ||
|
|
7e7d230d8c | ||
|
|
c1ece40f41 | ||
|
|
a732539eee | ||
|
|
3bc0805a89 | ||
|
|
c72e35c769 | ||
|
|
2d9c5e99a1 | ||
|
|
ca22d50831 | ||
|
|
5cb91d9f6d | ||
|
|
116c90c2ea | ||
|
|
3f3696fb91 | ||
|
|
91ce807e8b | ||
|
|
b9443f8813 | ||
|
|
b7d4609e57 | ||
|
|
c8a7e1597d | ||
|
|
ceaff61c09 | ||
|
|
6cc623a7b4 | ||
|
|
ac4d5c95ac | ||
|
|
de442e9584 | ||
|
|
713c2d5080 | ||
|
|
734d16291f | ||
|
|
1454f42a27 | ||
|
|
c830a3a4ee | ||
|
|
8a1477ecab | ||
|
|
006ce1a240 | ||
|
|
276dee2c3e | ||
|
|
98a2871727 | ||
|
|
5ca1bb3bd5 | ||
|
|
f6be3c7f70 | ||
|
|
00924dcba0 | ||
|
|
5278799575 | ||
|
|
2af98c33c9 | ||
|
|
22debb3532 | ||
|
|
c441cdd5a4 | ||
|
|
13fa1e2722 | ||
|
|
fad89189da | ||
|
|
4ab56518a0 | ||
|
|
80dbc7aeef | ||
|
|
238f6772bd | ||
|
|
dc9859cee9 | ||
|
|
5d5f27a486 | ||
|
|
ad6a16d7c4 | ||
|
|
5c8e5c52ef | ||
|
|
546df1c1f0 | ||
|
|
603331e7a5 | ||
|
|
4b272cc0cf | ||
|
|
619a99bf99 | ||
|
|
1f8cb740f1 | ||
|
|
322f7a97de | ||
|
|
0fc770166c | ||
|
|
1a70855e25 | ||
|
|
6b5e7da4fd | ||
|
|
a1dc16848c | ||
|
|
2819d7ea3d | ||
|
|
6ef995525a | ||
|
|
18dee384ec | ||
|
|
b369aa67f1 | ||
|
|
c853234e01 | ||
|
|
9c859ffdca | ||
|
|
0dc850f4ec | ||
|
|
672fd16ec8 | ||
|
|
dcadeac903 | ||
|
|
b7b3dd2b37 | ||
|
|
82396ee3ef | ||
|
|
e430d097b7 | ||
|
|
38be82a154 | ||
|
|
27cd9fd051 | ||
|
|
1ffce72a38 | ||
|
|
dcac64d50f | ||
|
|
0bf789db4c | ||
|
|
57cbe61709 | ||
|
|
a2ab17a782 | ||
|
|
d825f87359 | ||
|
|
3184371e8d | ||
|
|
f2e54be965 | ||
|
|
c22670cbb0 | ||
|
|
c5decfbd12 | ||
|
|
e25a2964bc | ||
|
|
8382367495 | ||
|
|
64c16c0f6e | ||
|
|
9f01c47542 | ||
|
|
aca7b44a05 | ||
|
|
4f8fd545fa | ||
|
|
d4552af39b | ||
|
|
0c02c5cb30 | ||
|
|
1f90e98491 | ||
|
|
352fd32c45 | ||
|
|
e0af3e2af5 | ||
|
|
5726ca6964 | ||
|
|
f164b14ba1 | ||
|
|
214e9534cc | ||
|
|
2a0cd00958 | ||
|
|
d744b06a28 | ||
|
|
048b75304d | ||
|
|
aaafb1a5de | ||
|
|
5783823e25 | ||
|
|
faf691a5be | ||
|
|
3a0e52fc3f | ||
|
|
a105c6f538 | ||
|
|
3e58c59377 | ||
|
|
b9ae6c3308 | ||
|
|
7310d78057 | ||
|
|
49e0e23f76 | ||
|
|
20dda339cc | ||
|
|
260bc64b59 | ||
|
|
5097ac3230 | ||
|
|
8d7bf52e51 | ||
|
|
1cb75ebb6e | ||
|
|
94397b52fc | ||
|
|
7fe152ce1b | ||
|
|
d3568605ce | ||
|
|
666721c7ad | ||
| 0f7f4710c6 | |||
|
|
f1439f8b1c | ||
|
|
aa6e976f92 | ||
|
|
67daaaa9b7 | ||
|
|
a36443557b | ||
|
|
435ac7b086 | ||
|
|
178a8a835a | ||
|
|
3e3b691518 | ||
|
|
428268a71e | ||
|
|
746c739769 |
@@ -1,9 +0,0 @@
|
||||
./bin
|
||||
./lib
|
||||
./db
|
||||
./dbd
|
||||
./html
|
||||
./include
|
||||
./templates
|
||||
**/O.*
|
||||
./QtC-*
|
||||
13
.gitignore
vendored
Normal file
13
.gitignore
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
/cfg/
|
||||
/bin/
|
||||
/lib/
|
||||
/db/
|
||||
/dbd/
|
||||
/html/
|
||||
/include/
|
||||
/templates/
|
||||
O.*/
|
||||
/QtC-*
|
||||
*.orig
|
||||
*.log
|
||||
.*.swp
|
||||
31
.travis.yml
Normal file
31
.travis.yml
Normal file
@@ -0,0 +1,31 @@
|
||||
sudo: false
|
||||
dist: trusty
|
||||
language: c
|
||||
compiler:
|
||||
- gcc
|
||||
env:
|
||||
- CMPLR=gcc
|
||||
- CMPLR=gcc EXTRA=CMD_CXXFLAGS=-std=c++11
|
||||
- CMPLR=gcc STATIC=YES
|
||||
- CMPLR=clang
|
||||
- CMPLR=clang STATIC=YES
|
||||
- WINE=32 TEST=NO STATIC=YES
|
||||
- RTEMS=4.10 TEST=NO
|
||||
- RTEMS=4.9 TEST=NO
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libreadline6-dev
|
||||
- libncurses5-dev
|
||||
- perl
|
||||
- clang
|
||||
- g++-mingw-w64-i686
|
||||
- bison
|
||||
- flex
|
||||
- texinfo
|
||||
- install-info
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.cache
|
||||
install: sh ci/travis-prepare.sh </dev/null
|
||||
script: sh ci/travis-build.sh </dev/null
|
||||
2
README
2
README
@@ -20,5 +20,5 @@ Additional information about EPICS including mailing list
|
||||
archives and subscription instructions, documentation and
|
||||
training materials, additional components, links to other
|
||||
websites etc. is available on the EPICS home page at
|
||||
http://www.aps.anl.gov/epics/
|
||||
https://epics.anl.gov/
|
||||
|
||||
|
||||
85
appveyor.yml
Normal file
85
appveyor.yml
Normal file
@@ -0,0 +1,85 @@
|
||||
# AppVeyor configuration for EPICS Base
|
||||
|
||||
# Ralph Lange <ralph.lange@gmx.de>
|
||||
# Copyright (c) 2016-2017 ITER Organization
|
||||
|
||||
# Version format
|
||||
version: base-{branch}-{build}
|
||||
|
||||
#---------------------------------#
|
||||
# repository cloning #
|
||||
#---------------------------------#
|
||||
|
||||
# Called at very beginning, before repo cloning
|
||||
init:
|
||||
# Set autocrlf to make batch files work
|
||||
- git config --global core.autocrlf true
|
||||
|
||||
# Set clone depth (do not fetch complete history)
|
||||
clone_depth: 2
|
||||
|
||||
# Skipping commits affecting only specific files
|
||||
skip_commits:
|
||||
files:
|
||||
- 'documentation/*'
|
||||
- 'templates/*'
|
||||
- '**/*.html'
|
||||
- '**/*.md'
|
||||
|
||||
#---------------------------------#
|
||||
# build matrix configuration #
|
||||
#---------------------------------#
|
||||
|
||||
# Build Configurations: dll/static, regular/debug
|
||||
configuration:
|
||||
- dynamic
|
||||
- static
|
||||
- dynamic-debug
|
||||
- static-debug
|
||||
|
||||
# Environment variables: compiler toolchain
|
||||
environment:
|
||||
matrix:
|
||||
- TOOLCHAIN: 10.0
|
||||
- TOOLCHAIN: 11.0
|
||||
- TOOLCHAIN: 12.0
|
||||
- TOOLCHAIN: 14.0
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
TOOLCHAIN: 2017
|
||||
- TOOLCHAIN: cygwin
|
||||
- TOOLCHAIN: mingw
|
||||
|
||||
# Platform: architecture
|
||||
platform:
|
||||
- x86
|
||||
- x64
|
||||
|
||||
# Matrix configuration: allow specific failing jobs
|
||||
matrix:
|
||||
exclude:
|
||||
# VS Express installs don't have the 64 bit compiler
|
||||
- platform: x64
|
||||
TOOLCHAIN: 10.0
|
||||
|
||||
#---------------------------------#
|
||||
# building & testing #
|
||||
#---------------------------------#
|
||||
|
||||
install:
|
||||
- cmd: ci/appveyor-prepare.bat
|
||||
|
||||
build_script:
|
||||
- cmd: ci/appveyor-make.bat
|
||||
|
||||
test_script:
|
||||
- cmd: ci/appveyor-make.bat runtests
|
||||
|
||||
#---------------------------------#
|
||||
# notifications #
|
||||
#---------------------------------#
|
||||
|
||||
notifications:
|
||||
|
||||
- provider: Slack
|
||||
incoming_webhook:
|
||||
secure: RYOm3FIUYeZGjWKaeTVKwq+C3fzK54AKwbmAoECED45mex3lN+8HmrC845a6mg9xPUJ/ND51RopWVaKDD9/UzaM0SO195RQLKqUTIUafiuM=
|
||||
137
ci/appveyor-make.bat
Normal file
137
ci/appveyor-make.bat
Normal file
@@ -0,0 +1,137 @@
|
||||
:: Universal build script for AppVeyor (https://ci.appveyor.com/)
|
||||
:: Environment:
|
||||
:: TOOLCHAIN - toolchain version [10.0/11.0/12.0/14.0/2017/cygwin/mingw]
|
||||
:: CONFIGURATION - determines EPICS build [dynamic/static]
|
||||
:: PLATFORM - architecture [x86/x64]
|
||||
::
|
||||
:: All command line args are passed to make
|
||||
|
||||
Setlocal EnableDelayedExpansion
|
||||
|
||||
set "ST="
|
||||
if /i "%CONFIGURATION%"=="static" set ST=-static
|
||||
|
||||
set OS=64BIT
|
||||
if "%PLATFORM%"=="x86" set OS=32BIT
|
||||
|
||||
echo [INFO] Platform: %OS%
|
||||
|
||||
:: Use parallel make, except for 3.14
|
||||
set "MAKEARGS=-j2 -Otarget"
|
||||
if "%APPVEYOR_REPO_BRANCH%"=="3.14" set MAKEARGS=
|
||||
|
||||
if "%TOOLCHAIN%"=="cygwin" (
|
||||
set "MAKE=make"
|
||||
if "%OS%"=="64BIT" (
|
||||
set "EPICS_HOST_ARCH=cygwin-x86_64"
|
||||
set "INCLUDE=C:\cygwin64\include;%INCLUDE%"
|
||||
set "PATH=C:\cygwin64\bin;%PATH%"
|
||||
echo [INFO] Cygwin Toolchain 64bit
|
||||
) else (
|
||||
set "EPICS_HOST_ARCH=cygwin-x86"
|
||||
set "INCLUDE=C:\cygwin\include;%INCLUDE%"
|
||||
set "PATH=C:\cygwin\bin;%PATH%"
|
||||
echo [INFO] Cygwin Toolchain 32bit
|
||||
)
|
||||
echo [INFO] Compiler Version
|
||||
gcc -v
|
||||
goto Finish
|
||||
)
|
||||
|
||||
if "%TOOLCHAIN%"=="mingw" (
|
||||
set "MAKE=mingw32-make"
|
||||
if "%OS%"=="64BIT" (
|
||||
set "EPICS_HOST_ARCH=windows-x64-mingw"
|
||||
set "INCLUDE=C:\tools\mingw64\include;%INCLUDE%"
|
||||
set "PATH=C:\tools\mingw64\bin;%PATH%"
|
||||
echo [INFO] MinGW Toolchain 64bit
|
||||
) else (
|
||||
set "EPICS_HOST_ARCH=win32-x86-mingw"
|
||||
set "INCLUDE=C:\tools\mingw32\include;%INCLUDE%"
|
||||
set "PATH=C:\tools\mingw32\bin;%PATH%"
|
||||
echo [INFO] MinGW Toolchain 32bit
|
||||
)
|
||||
echo [INFO] Compiler Version
|
||||
gcc -v
|
||||
goto Finish
|
||||
)
|
||||
|
||||
set "VSINSTALL=C:\Program Files (x86)\Microsoft Visual Studio %TOOLCHAIN%"
|
||||
if not exist "%VSINSTALL%\" set "VSINSTALL=C:\Program Files (x86)\Microsoft Visual Studio\%TOOLCHAIN%\Community"
|
||||
if not exist "%VSINSTALL%\" goto MSMissing
|
||||
|
||||
set "MAKE=C:\tools\make"
|
||||
|
||||
echo [INFO] APPVEYOR_BUILD_WORKER_IMAGE=%APPVEYOR_BUILD_WORKER_IMAGE%
|
||||
|
||||
if "%OS%"=="64BIT" (
|
||||
set EPICS_HOST_ARCH=windows-x64%ST%
|
||||
:: VS 2017
|
||||
if exist "%VSINSTALL%\VC\Auxiliary\Build\vcvars64.bat" (
|
||||
call "%VSINSTALL%\VC\Auxiliary\Build\vcvars64.bat"
|
||||
where cl
|
||||
if !ERRORLEVEL! NEQ 0 goto MSMissing
|
||||
goto MSFound
|
||||
)
|
||||
if exist "%VSINSTALL%\VC\vcvarsall.bat" (
|
||||
call "%VSINSTALL%\VC\vcvarsall.bat" amd64
|
||||
where cl
|
||||
if !ERRORLEVEL! NEQ 0 (
|
||||
call "%VSINSTALL%\VC\vcvarsall.bat" x86_amd64
|
||||
where cl
|
||||
if !ERRORLEVEL! NEQ 0 goto MSMissing
|
||||
)
|
||||
goto MSFound
|
||||
)
|
||||
if exist "%VSINSTALL%\VC\bin\amd64\vcvars64.bat" (
|
||||
call "%VSINSTALL%\VC\bin\amd64\vcvars64.bat"
|
||||
where cl
|
||||
if !ERRORLEVEL! NEQ 0 goto MSMissing
|
||||
goto MSFound
|
||||
)
|
||||
) else (
|
||||
set EPICS_HOST_ARCH=win32-x86%ST%
|
||||
:: VS 2017
|
||||
if exist "%VSINSTALL%\VC\Auxiliary\Build\vcvars32.bat" (
|
||||
call "%VSINSTALL%\VC\Auxiliary\Build\vcvars32.bat"
|
||||
where cl
|
||||
if !ERRORLEVEL! NEQ 0 goto MSMissing
|
||||
goto MSFound
|
||||
)
|
||||
if exist "%VSINSTALL%\VC\vcvarsall.bat" (
|
||||
call "%VSINSTALL%\VC\vcvarsall.bat" x86
|
||||
where cl
|
||||
if !ERRORLEVEL! NEQ 0 goto MSMissing
|
||||
goto MSFound
|
||||
)
|
||||
if exist "%VSINSTALL%\VC\bin\vcvars32.bat" (
|
||||
call "%VSINSTALL%\VC\bin\vcvars32.bat"
|
||||
where cl
|
||||
if !ERRORLEVEL! NEQ 0 goto MSMissing
|
||||
goto MSFound
|
||||
)
|
||||
if exist "%VSINSTALL%\Common7\Tools\vsvars32.bat" (
|
||||
call "%VSINSTALL%\Common7\Tools\vsvars32.bat"
|
||||
where cl
|
||||
if !ERRORLEVEL! NEQ 0 goto MSMissing
|
||||
goto MSFound
|
||||
)
|
||||
)
|
||||
|
||||
:MSMissing
|
||||
echo [INFO] Installation for MSVC Toolchain %TOOLCHAIN% / %OS% seems to be missing
|
||||
exit 1
|
||||
|
||||
:MSFound
|
||||
echo [INFO] Microsoft Visual Studio Toolchain %TOOLCHAIN%
|
||||
echo [INFO] Compiler Version
|
||||
cl
|
||||
|
||||
:Finish
|
||||
echo [INFO] EPICS_HOST_ARCH: %EPICS_HOST_ARCH%
|
||||
echo [INFO] Make version
|
||||
%MAKE% --version
|
||||
echo [INFO] Perl version
|
||||
perl --version
|
||||
|
||||
%MAKE% %MAKEARGS% %*
|
||||
70
ci/appveyor-prepare.bat
Normal file
70
ci/appveyor-prepare.bat
Normal file
@@ -0,0 +1,70 @@
|
||||
:: Build script for AppVeyor (https://ci.appveyor.com/)
|
||||
:: Environment:
|
||||
:: TOOLCHAIN - Toolchain Version [9.0/10.0/11.0/12.0/14.0/cygwin/mingw]
|
||||
:: CONFIGURATION - determines EPICS build [dynamic/static, -debug]
|
||||
:: PLATFORM - "x86" -> use 32bit architecture
|
||||
::
|
||||
:: Prepares an Appveyor build by excuting the following steps
|
||||
:: - Set up configure\CONFIG_SITE for static vs. dynamic build
|
||||
:: - Install Cygwin / Mingw (TOOLCHAIN setting) in the in the appropriate flavor
|
||||
:: - Download and install Make-4.1 from EPICS download page
|
||||
|
||||
Setlocal EnableDelayedExpansion
|
||||
|
||||
set OS=64BIT
|
||||
if "%PLATFORM%"=="x86" set OS=32BIT
|
||||
|
||||
echo [INFO] Platform: %OS%
|
||||
|
||||
if "%TOOLCHAIN%"=="cygwin" (
|
||||
echo.%CONFIGURATION% | findstr /C:"static">nul && (
|
||||
echo SHARED_LIBRARIES=NO>> configure\CONFIG_SITE
|
||||
echo STATIC_BUILD=YES>> configure\CONFIG_SITE
|
||||
echo [INFO] EPICS set up for static build
|
||||
) || (
|
||||
echo [INFO] EPICS set up for dynamic build
|
||||
)
|
||||
echo.%CONFIGURATION% | findstr /C:"debug">nul && (
|
||||
echo HOST_OPT=NO>> configure\CONFIG_SITE
|
||||
echo [INFO] EPICS set up for debug build
|
||||
) || (
|
||||
echo [INFO] EPICS set up for optimized build
|
||||
)
|
||||
if "%OS%"=="64BIT" (
|
||||
echo [INFO] Installing Cygwin 64bit and dependencies
|
||||
@powershell -Command "(new-object net.webclient).DownloadFile('http://www.cygwin.com/setup-x86_64.exe', 'C:\cygwin64\setup-x86_64.exe')"
|
||||
C:\cygwin64\setup-x86_64.exe -q -P "libreadline-devel,libncursesw-devel"
|
||||
) else (
|
||||
echo [INFO] Installing Cygwin 32bit and dependencies
|
||||
@powershell -Command "(new-object net.webclient).DownloadFile('http://www.cygwin.com/setup-x86.exe', 'C:\cygwin\setup-x86.exe')"
|
||||
C:\cygwin\setup-x86.exe -q -P "libreadline-devel,libncursesw-devel"
|
||||
)
|
||||
)
|
||||
|
||||
if "%TOOLCHAIN%"=="mingw" (
|
||||
echo.%CONFIGURATION% | findstr /C:"static">nul && (
|
||||
echo SHARED_LIBRARIES=NO>> configure\CONFIG_SITE
|
||||
echo STATIC_BUILD=YES>> configure\CONFIG_SITE
|
||||
echo [INFO] EPICS set up for static build
|
||||
) || (
|
||||
echo [INFO] EPICS set up for dynamic build
|
||||
)
|
||||
echo.%CONFIGURATION% | findstr /C:"debug">nul && (
|
||||
echo HOST_OPT=NO>> configure\CONFIG_SITE
|
||||
echo [INFO] EPICS set up for debug build
|
||||
) || (
|
||||
echo [INFO] EPICS set up for optimized build
|
||||
)
|
||||
if "%OS%"=="64BIT" (
|
||||
echo [INFO] Installing MinGW 64bit
|
||||
cinst mingw || cinst mingw
|
||||
) else (
|
||||
echo [INFO] Installing MinGW 32bit
|
||||
cinst mingw --x86 || cinst mingw --x86
|
||||
)
|
||||
)
|
||||
|
||||
echo [INFO] Installing Make 4.1
|
||||
curl -fsS --retry 3 -o C:\tools\make-4.1.zip https://epics.anl.gov/download/tools/make-4.1-win64.zip
|
||||
cd \tools
|
||||
"C:\Program Files\7-Zip\7z" e make-4.1.zip
|
||||
90
ci/travis-build.sh
Normal file
90
ci/travis-build.sh
Normal 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=`perl src/tools/EpicsHostArch.pl`
|
||||
|
||||
[ -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
40
ci/travis-prepare.sh
Normal 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"
|
||||
@@ -20,11 +20,15 @@ else
|
||||
endif
|
||||
|
||||
# Provide a default if the user hasn't set EPICS_HOST_ARCH
|
||||
ifeq ($(origin EPICS_HOST_ARCH), undefined)
|
||||
# NB: We use a simply expanded variable here for performance:
|
||||
EPICS_HOST_ARCH := $(shell $(CONFIG)/../startup/EpicsHostArch.pl)
|
||||
endif
|
||||
#
|
||||
ifeq ($(origin EPICS_HOST_ARCH), undefined)
|
||||
# Bootstrapping ...
|
||||
EHA := $(firstword $(wildcard $(EPICS_BASE)/lib/perl/EpicsHostArch.pl \
|
||||
$(TOP)/src/tools/EpicsHostArch.pl))
|
||||
# NB: We use a simply expanded variable here for performance:
|
||||
export EPICS_HOST_ARCH := $(shell perl $(EHA))
|
||||
EHA :=
|
||||
endif
|
||||
|
||||
-include $(CONFIG)/os/CONFIG_COMPAT
|
||||
|
||||
@@ -75,17 +79,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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
#*************************************************************************
|
||||
#
|
||||
# EPICS Version information
|
||||
@@ -26,21 +26,12 @@ EPICS_REVISION = 14
|
||||
# EPICS_MODIFICATION must be a number >=0 and <256
|
||||
EPICS_MODIFICATION = 12
|
||||
|
||||
# EPICS_PATCH_LEVEL must be a number (win32 resource file requirement)
|
||||
# EPICS_PATCH_LEVEL must be a number (win32 resource file requirement)
|
||||
# Not included if zero
|
||||
EPICS_PATCH_LEVEL = 5
|
||||
EPICS_PATCH_LEVEL = 8
|
||||
|
||||
# This will end in -DEV between official releases
|
||||
EPICS_DEV_SNAPSHOT=-DEV
|
||||
#EPICS_DEV_SNAPSHOT=-pre1
|
||||
#EPICS_DEV_SNAPSHOT=-pre1-DEV
|
||||
#EPICS_DEV_SNAPSHOT=-pre2
|
||||
#EPICS_DEV_SNAPSHOT=-pre2-DEV
|
||||
#EPICS_DEV_SNAPSHOT=-rc1
|
||||
#EPICS_DEV_SNAPSHOT=-rc1-DEV
|
||||
#EPICS_DEV_SNAPSHOT=-rc2
|
||||
#EPICS_DEV_SNAPSHOT=-rc2-DEV
|
||||
#EPICS_DEV_SNAPSHOT=
|
||||
EPICS_DEV_SNAPSHOT=
|
||||
|
||||
# No changes should be needed below here
|
||||
|
||||
|
||||
@@ -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?
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#
|
||||
# CONFIG_SITE_ENV - EPICS Environment Parameter Site configuration file
|
||||
#
|
||||
# This file is read by the script base/src/libCom/env/bldEnvdata.pl
|
||||
# This file is read by the script base/src/libCom/env/bldEnvData.pl
|
||||
# Variable definitions must take the form
|
||||
# VAR = VALUE
|
||||
# or
|
||||
@@ -26,31 +26,42 @@
|
||||
|
||||
# Time service:
|
||||
# EPICS_TIMEZONE
|
||||
# local timezone info for vxWorks and RTEMS IOCs. The format is
|
||||
# <name>::<minutesWest>:<start daylight>:<end daylight>
|
||||
# where the start and end are mmddhh - that is month,day,hour
|
||||
# e.g. for ANL in 2016: EPICS_TIMEZONE=CUS::360:031302:110602
|
||||
# Local timezone info for vxWorks and RTEMS. The format is
|
||||
# <name>::<minutesWest>:<startDST>:<endDST>
|
||||
# where <name> is only used by strftime() for %Z conversions,
|
||||
# and <startDST> and <endDST> are mmddhh - that is month,day,hour
|
||||
# e.g. for ANL in 2018: EPICS_TIMEZONE=CUS::360:031102:110402
|
||||
# The future dates below assume the rules don't get changed;
|
||||
# see http://www.timeanddate.com/time/dst/2018.html to check.
|
||||
#
|
||||
# DST for 2016 US: Mar 13 - Nov 06
|
||||
# EU: Mar 27 - Oct 30
|
||||
# DST for 2017 US: Mar 12 - Nov 05
|
||||
# EU: Mar 26 - Oct 29
|
||||
# DST for 2018 US: Mar 11 - Nov 04
|
||||
# EU: Mar 25 - Oct 28
|
||||
EPICS_TIMEZONE = CUS::360:031102:110402
|
||||
#EPICS_TIMEZONE = MET::-60:032502:102803
|
||||
#
|
||||
# DST for 2019 US: Mar 10 - Nov 03
|
||||
# EU: Mar 31 - Oct 27
|
||||
#EPICS_TIMEZONE = CUS::360:031002:110302
|
||||
#EPICS_TIMEZONE = MET::-60:033102:102703
|
||||
#
|
||||
# DST for 2020 US: Mar 08 - Nov 01
|
||||
# EU: Mar 29 - Oct 25
|
||||
#EPICS_TIMEZONE = CUS::360:030802:110102
|
||||
#EPICS_TIMEZONE = MET::-60:032902:102503
|
||||
#
|
||||
# DST for 2021 US: Mar 14 - Nov 07
|
||||
# EU: Mar 28 - Oct 31
|
||||
# (see: http://www.timeanddate.com/time/dst/2016.html etc. )
|
||||
#EPICS_TIMEZONE = CUS::360:031402:110702
|
||||
#EPICS_TIMEZONE = MET::-60:032802:103103
|
||||
#
|
||||
# These values are for 2016:
|
||||
EPICS_TIMEZONE=CUS::360:031302:110602
|
||||
#EPICS_TIMEZONE=MET::-60:032702:103002
|
||||
# DST for 2022 US: Mar 13 - Nov 06
|
||||
# EU: Mar 27 - Oct 30
|
||||
#EPICS_TIMEZONE = CUS::360:031302:110602
|
||||
#EPICS_TIMEZONE = MET::-60:032702:103003
|
||||
|
||||
# EPICS_TS_NTP_INET
|
||||
# NTP time server ip address. Uses boot host if not set.
|
||||
# NTP time server ip address for VxWorks and RTEMS.
|
||||
# IOC will use its boot host if this is not set.
|
||||
EPICS_TS_NTP_INET=
|
||||
|
||||
# IOC Shell:
|
||||
|
||||
@@ -134,7 +134,7 @@ ACTIONS += build
|
||||
ACTIONS += install
|
||||
ACTIONS += buildInstall
|
||||
ACTIONS += browse
|
||||
ACTIONS += runtests tapfiles
|
||||
ACTIONS += runtests tapfiles clean-tests test-results junitfiles
|
||||
|
||||
actionArchTargets = $(foreach x, $(ACTIONS),\ $(foreach arch,$(BUILD_ARCHS), $(x)$(DIVIDER)$(arch)))
|
||||
|
||||
@@ -150,6 +150,7 @@ buildInstall : build
|
||||
rebuild: clean install
|
||||
|
||||
.PHONY: all inc build install clean rebuild buildInstall
|
||||
.PHONY: runtests tapfiles clean-tests test-results junitfiles
|
||||
|
||||
$(actionArchTargets) $(BUILD_ARCHS):install
|
||||
$(cleanArchTargets):clean
|
||||
@@ -300,6 +301,20 @@ $(foreach file, $(DBD_INSTALLS), $(eval $(call DBD_INSTALLS_template, $(file))))
|
||||
|
||||
.PRECIOUS: $(COMMON_DBDS) $(COMMON_DIR)/%Include.dbd
|
||||
|
||||
##################################################### HTML files
|
||||
|
||||
$(COMMON_DIR)/%.html: %.pm $(TOOLS)/podToHtml.pl
|
||||
@$(RM) $(notdir $@)
|
||||
$(PERL) $(TOOLS)/podToHtml.pl -o $(notdir $@) $<
|
||||
@$(MV) $(notdir $@) $@
|
||||
|
||||
$(COMMON_DIR)/%.html: ../%.pm $(TOOLS)/podToHtml.pl
|
||||
@$(RM) $(notdir $@)
|
||||
$(PERL) $(TOOLS)/podToHtml.pl -o $(notdir $@) $<
|
||||
@$(MV) $(notdir $@) $@
|
||||
|
||||
.PRECIOUS: $(COMMON_DIR)/%.html %.html
|
||||
|
||||
##################################################### DB files
|
||||
|
||||
$(COMMON_DIR)/%.db$(RAW): $(COMMON_DIR)/%.edf
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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), \
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# Copyright (c) 2002 The Regents of the University of California, as
|
||||
# Operator of Los Alamos National Laboratory.
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in the file LICENSE that is included with this distribution.
|
||||
# in the file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
#
|
||||
# Rules for making things specified in Makefile
|
||||
@@ -101,10 +101,11 @@ endif
|
||||
ifneq (,$(findstring $(T_A),$(EPICS_HOST_ARCH) $(CROSS_COMPILER_RUNTEST_ARCHS)))
|
||||
RUNTESTS_ENABLED = YES
|
||||
TAPFILES += $(TESTSCRIPTS:.t=.tap)
|
||||
JUNITFILES += $(TAPFILES:.tap=.xml)
|
||||
endif
|
||||
|
||||
#---------------------------------------------------------------
|
||||
# Libraries
|
||||
# Libraries
|
||||
#
|
||||
|
||||
LIBTARGETS += $(LIBNAME) $(INSTALL_LIBS) \
|
||||
@@ -117,16 +118,16 @@ $(INSTALL_LIBS): $(INSTALL_SHRLIBS) $(INSTALL_DLL_LINK_LIBS) $(INSTALL_LOADABL
|
||||
|
||||
# Main targets
|
||||
|
||||
install: buildInstall
|
||||
install: buildInstall
|
||||
|
||||
buildInstall : build
|
||||
buildInstall: build
|
||||
|
||||
# Allows rebuild to work with parallel builds option, -j.
|
||||
install: $(patsubst rebuild,clean,$(filter rebuild,$(MAKECMDGOALS)))
|
||||
|
||||
rebuild: clean install
|
||||
|
||||
build : inc
|
||||
build: inc
|
||||
|
||||
build: $(OBJSNAME) $(LIBTARGETS) $(PRODTARGETS) $(TESTPRODNAME) \
|
||||
$(TARGETS) $(TESTSCRIPTS) $(INSTALL_LIB_INSTALLS)
|
||||
@@ -148,7 +149,7 @@ clean::
|
||||
$(INC) $(TARGETS) $(DLL_LINK_LIBNAME) $(TDS) \
|
||||
*.out MakefileInclude $(LOADABLE_SHRLIBNAME) *.manifest *.exp \
|
||||
$(COMMON_INC) $(HDEPENDS_FILES) $(PRODTARGETS) \
|
||||
$(TESTSCRIPTS) $(TAPFILES)
|
||||
$(TESTSCRIPTS) $(TAPFILES) $(JUNITFILES)
|
||||
ifdef RES
|
||||
@$(RM) *$(RES)
|
||||
endif
|
||||
@@ -176,7 +177,7 @@ warnRelease:
|
||||
-$(CONVERTRELEASE) checkRelease
|
||||
noCheckRelease:
|
||||
ifeq ($(EPICS_HOST_ARCH),$(T_A))
|
||||
@echo "Warning: RELEASE file consistency checks have been disabled"
|
||||
$(info Warning: RELEASE file consistency checks have been disabled)
|
||||
endif
|
||||
|
||||
#---------------------------------------------------------------
|
||||
@@ -207,17 +208,18 @@ $(OBJLIBNAME):%$(OBJ):
|
||||
%.o : %.cc
|
||||
%.o : %.cpp
|
||||
|
||||
%$(OBJ): %.c $(COMMON_INC) $(INSTALL_INC)
|
||||
# Include files are order-only prerequisites for compilation:
|
||||
%$(OBJ): %.c | $(COMMON_INC) $(INSTALL_INC)
|
||||
@$(HDEPENDS_CMD)
|
||||
@$(RM) $@
|
||||
$(COMPILE.c) $(call PATH_FILTER,$<) $(COMPILE_FILTER.c)
|
||||
|
||||
%$(OBJ): %.cc $(COMMON_INC) $(INSTALL_INC)
|
||||
%$(OBJ): %.cc | $(COMMON_INC) $(INSTALL_INC)
|
||||
@$(HDEPENDS_CMD)
|
||||
@$(RM) $@
|
||||
$(COMPILE.cpp) $(call PATH_FILTER,$<) $(COMPILE_FILTER.cpp)
|
||||
|
||||
%$(OBJ): %.cpp $(COMMON_INC) $(INSTALL_INC)
|
||||
%$(OBJ): %.cpp | $(COMMON_INC) $(INSTALL_INC)
|
||||
@$(HDEPENDS_CMD)
|
||||
@$(RM) $@
|
||||
$(COMPILE.cpp) $(call PATH_FILTER,$<) $(COMPILE_FILTER.cpp)
|
||||
@@ -288,7 +290,7 @@ endif
|
||||
|
||||
$(LIBNAME): $(LIBRARY_OBJS)
|
||||
|
||||
$(DLL_LINK_LIBNAME): $(LIBRARY_OBJS) $(LIBRARY_RESS) $(SHRLIB_DEPLIBS)
|
||||
$(DLL_LINK_LIBNAME): $(LIBRARY_OBJS) $(LIBRARY_RESS) $(SHRLIB_DEPLIBS)
|
||||
|
||||
$(LIBNAME) $(DLL_LINK_LIBNAME): $(LIB_PREFIX)%$(LIB_SUFFIX):
|
||||
@$(RM) $@
|
||||
@@ -352,7 +354,23 @@ testspec: $(TESTSCRIPTS)
|
||||
$(if $^, @echo Tests: $^ >> $@)
|
||||
$(if $(TESTSPEC_$(OS_CLASS)), @echo "Harness: $(TESTSPEC_$(OS_CLASS))" >> $@)
|
||||
|
||||
test-results: tapfiles
|
||||
ifneq ($(TAPFILES),)
|
||||
ifdef RUNTESTS_ENABLED
|
||||
prove --failures --ext .tap --exec cat --color $(TAPFILES)
|
||||
endif
|
||||
endif
|
||||
|
||||
clean-tests:
|
||||
ifneq ($(TAPFILES),)
|
||||
$(RM) $(TAPFILES)
|
||||
endif
|
||||
ifneq ($(JUNITFILES),)
|
||||
$(RM) $(JUNITFILES)
|
||||
endif
|
||||
|
||||
tapfiles: $(TESTSCRIPTS) $(TAPFILES)
|
||||
junitfiles: $(JUNITFILES)
|
||||
|
||||
# A .tap file is the output from running the associated test script
|
||||
%.tap: %.t
|
||||
@@ -360,6 +378,9 @@ ifdef RUNTESTS_ENABLED
|
||||
-$(PERL) $< -tap > $@
|
||||
endif
|
||||
|
||||
%.xml: %.tap
|
||||
$(TAPTOJUNIT) --puretap --output $@ --input $< $*
|
||||
|
||||
# If there's a perl test script (.plt) available, use it
|
||||
%.t: ../%.plt
|
||||
@$(RM) $@
|
||||
@@ -479,6 +500,10 @@ $(INSTALL_HTML)/$(HTMLS_DIR)/%: ../%
|
||||
$(ECHO) "Installing html $@"
|
||||
@$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D)
|
||||
|
||||
$(INSTALL_HTML)/$(HTMLS_DIR)/%: $(COMMON_DIR)/%
|
||||
$(ECHO) "Installing generated html $@"
|
||||
@$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D)
|
||||
|
||||
$(INSTALL_TEMPLATES_SUBDIR)/%: ../%
|
||||
$(ECHO) "Installing $@"
|
||||
@$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D)
|
||||
@@ -493,7 +518,8 @@ $(INSTALL_TEMPLATES_SUBDIR)/%: %
|
||||
.PRECIOUS: $(COMMON_INC)
|
||||
|
||||
.PHONY: all inc build install clean rebuild buildInstall
|
||||
.PHONY: runtests checkRelease warnRelease noCheckRelease
|
||||
.PHONY: runtests tapfiles clean-tests test-results junitfiles
|
||||
.PHONY: checkRelease warnRelease noCheckRelease
|
||||
|
||||
endif # BASE_RULES_BUILD
|
||||
# EOF RULES_BUILD
|
||||
|
||||
@@ -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), \
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -22,7 +22,7 @@ WINLINK = link
|
||||
|
||||
RCCMD = rc -l 0x409 $(INCLUDES) -fo $@ $<
|
||||
|
||||
ARCMD = lib /nologo /verbose /out:$@ $(LIB_OPT_LDFLAGS) $(LIBRARY_LD_OBJS)
|
||||
ARCMD = lib -nologo -verbose -out:$@ $(LIB_OPT_LDFLAGS) $(LIBRARY_LD_OBJS)
|
||||
|
||||
BAFCMD = bscmake /nologo /o $@
|
||||
|
||||
@@ -67,45 +67,50 @@ OBJ_CFLAG = -Fo
|
||||
# vis c++ compiles the code (and includes
|
||||
# the header files)
|
||||
#
|
||||
# /MT static multithreaded C RTL
|
||||
# /MTd static multithreaded C RTL (debug version)
|
||||
# /MD multithreaded C RTL in DLL
|
||||
# /MDd multithreaded C RTL in DLL (debug version)
|
||||
# -MT static multithreaded C RTL
|
||||
# -MTd static multithreaded C RTL (debug version)
|
||||
# -MD multithreaded C RTL in DLL
|
||||
# -MDd multithreaded C RTL in DLL (debug version)
|
||||
VISC_DLL_NO = -DEPICS_DLL_NO
|
||||
VISC_DLL_YES =
|
||||
VISC_DLL = $(VISC_DLL_$(SHARED_LIBRARIES))
|
||||
VISC_STATIC_CFLAGS_DEBUG_NO = d
|
||||
VISC_STATIC_CFLAGS_DEBUG_YES =
|
||||
VISC_STATIC_CFLAGS_DEBUG = $(VISC_STATIC_CFLAGS_DEBUG_$(HOST_OPT))
|
||||
STATIC_CFLAGS_YES= /MT$(VISC_STATIC_CFLAGS_DEBUG) $(VISC_DLL)
|
||||
STATIC_CFLAGS_NO= /MD$(VISC_STATIC_CFLAGS_DEBUG) $(VISC_DLL)
|
||||
STATIC_CFLAGS_YES= -MT$(VISC_STATIC_CFLAGS_DEBUG) $(VISC_DLL)
|
||||
STATIC_CFLAGS_NO= -MD$(VISC_STATIC_CFLAGS_DEBUG) $(VISC_DLL)
|
||||
|
||||
# OS vendor c preprocessor
|
||||
CPP = cl /nologo /C /E
|
||||
CPP = cl -nologo -C -E
|
||||
|
||||
# Configure OS vendor C++ compiler
|
||||
#
|
||||
# __STDC__=0 gives us both:
|
||||
# 1) define STDC for code (pretend ANSI conformance)
|
||||
# 2) set it to 0 to use MS C "extensions" (open for _open etc.)
|
||||
# because MS uses: if __STDC__ ... disable many nice things
|
||||
#
|
||||
# -EHsc - generate code for exceptions
|
||||
# -GR - generate code for run time type identification
|
||||
#
|
||||
CCC = cl -EHsc -GR
|
||||
CODE_CPPFLAGS += -nologo -D__STDC__=0
|
||||
|
||||
# Other compiler flags, used for CPP, C and C++
|
||||
#
|
||||
# -FC - Show absolute path of source file in diagnostics
|
||||
# -D__STDC__=0 gives us both:
|
||||
# 1) define STDC for code (pretend ANSI conformance)
|
||||
# 2) set it to 0 to use MS C "extensions" (open for _open etc.)
|
||||
# because MS uses: if __STDC__ ... disable many nice things
|
||||
#
|
||||
CODE_CPPFLAGS += -nologo -FC -D__STDC__=0
|
||||
CODE_CPPFLAGS += -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE
|
||||
|
||||
|
||||
# Compiler flags for C++ files
|
||||
|
||||
#
|
||||
# -W<N> use warning level N
|
||||
# (maximum lint level warnings at level 4)
|
||||
# -w44355 set "'this' used in the base initializer list" to be level 4
|
||||
# -W<n> disable warnings from levels > n
|
||||
# -w<n><m> set warning m to level n
|
||||
# -w44355 "'this' used in the base initializer list"
|
||||
# -w44344 "behavior change: use of explicit template arguments results in ..."
|
||||
WARN_CXXFLAGS_YES = -W3 -w44355 -w44344
|
||||
# -w44251 "class needs to have dll-interface to be used by clients of ..."
|
||||
WARN_CXXFLAGS_YES = -W3 -w44355 -w44344 -w44251
|
||||
WARN_CXXFLAGS_NO = -W1
|
||||
|
||||
#
|
||||
@@ -129,18 +134,29 @@ OBJ_CXXFLAG = -Fo
|
||||
# vis c++ compiles the code (and includes
|
||||
# the header files)
|
||||
#
|
||||
# /MT static multithreaded C RTL
|
||||
# /MTd static multithreaded C RTL (debug version)
|
||||
# /MD multithreaded C RTL in DLL
|
||||
# /MDd multithreaded C RTL in DLL (debug version)
|
||||
STATIC_CXXFLAGS_YES= /MT$(VISC_STATIC_CFLAGS_DEBUG) $(VISC_DLL)
|
||||
STATIC_CXXFLAGS_NO= /MD$(VISC_STATIC_CFLAGS_DEBUG) $(VISC_DLL)
|
||||
# -MT static multithreaded C RTL
|
||||
# -MTd static multithreaded C RTL (debug version)
|
||||
# -MD multithreaded C RTL in DLL
|
||||
# -MDd multithreaded C RTL in DLL (debug version)
|
||||
STATIC_CXXFLAGS_YES= -MT$(VISC_STATIC_CFLAGS_DEBUG) $(VISC_DLL)
|
||||
STATIC_CXXFLAGS_NO= -MD$(VISC_STATIC_CFLAGS_DEBUG) $(VISC_DLL)
|
||||
|
||||
STATIC_LDLIBS_YES=ws2_32.lib advapi32.lib user32.lib kernel32.lib winmm.lib
|
||||
STATIC_LDLIBS_NO=
|
||||
STATIC_LDFLAGS=
|
||||
RANLIB=
|
||||
|
||||
#
|
||||
# option needed for parallel builds with Visual Studio 2015 onward
|
||||
#
|
||||
# -FS Force Synchronous PDB Writes
|
||||
ifneq ($(VisualStudioVersion),)
|
||||
OPT_CXXFLAGS_NO += -FS
|
||||
OPT_CFLAGS_NO += -FS
|
||||
endif
|
||||
|
||||
|
||||
#
|
||||
# add -profile here to run the ms profiler
|
||||
# -LTCG whole program optimization
|
||||
# -incremental:no full linking
|
||||
@@ -173,10 +189,10 @@ BAF=.bsc
|
||||
BOF=.sbr
|
||||
|
||||
# Problem: MS Visual C++ does not recognize *.cc as C++ source,
|
||||
# so we do C++ compiles using the global flag -TP
|
||||
COMPILER_CXXFLAGS = /TP
|
||||
# so we do C++ compiles using the global flag -TP
|
||||
COMPILER_CXXFLAGS = -TP
|
||||
|
||||
# Operating system flags
|
||||
# Operating system flags
|
||||
OP_SYS_CFLAGS =
|
||||
OP_SYS_CXXFLAGS = $(COMPILER_CXXFLAGS)
|
||||
|
||||
@@ -192,13 +208,13 @@ OP_SYS_CXXFLAGS = $(COMPILER_CXXFLAGS)
|
||||
# '-entry:_DllMainCRTStartup$(DLLENTRY)'
|
||||
DLLENTRY = @12
|
||||
|
||||
WIN32_DLLFLAGS = /subsystem:windows /dll $(OPT_LDFLAGS) \
|
||||
WIN32_DLLFLAGS = -subsystem:windows -dll $(OPT_LDFLAGS) \
|
||||
$(USR_LDFLAGS) $(CMD_LDFLAGS) $(TARGET_LDFLAGS) $(LIB_LDFLAGS)
|
||||
|
||||
#
|
||||
# specify dll .def file only if it exists
|
||||
#
|
||||
DLL_DEF_FLAG = $(addprefix /def:,$(wildcard ../$(addsuffix .def,$*)))
|
||||
DLL_DEF_FLAG = $(addprefix -def:,$(wildcard ../$(addsuffix .def,$*)))
|
||||
|
||||
#
|
||||
# A WIN32 dll has three parts:
|
||||
@@ -206,9 +222,9 @@ DLL_DEF_FLAG = $(addprefix /def:,$(wildcard ../$(addsuffix .def,$*)))
|
||||
# x.lib: what you link to progs that use the dll (DLL_LINK_LIBNAME)
|
||||
# x.exp: what you need to build the dll (in no variable)
|
||||
#
|
||||
LINK.shrlib = $(WINLINK) /nologo $(WIN32_DLLFLAGS) /implib:$*.lib /out:$*.dll $(DLL_DEF_FLAG)
|
||||
LINK.shrlib = $(WINLINK) -nologo $(WIN32_DLLFLAGS) -implib:$*.lib -out:$*.dll $(DLL_DEF_FLAG)
|
||||
LINK.shrlib += $(call PATH_FILTER, $(LIBRARY_LD_OBJS) $(LIBRARY_LD_RESS) $(SHRLIB_LDLIBS))
|
||||
MUNCH_CMD = $(CCC) /Fo $@ $^
|
||||
MUNCH_CMD = $(CCC) -Fo $@ $^
|
||||
|
||||
|
||||
# adjust names of libraries to build
|
||||
@@ -222,7 +238,7 @@ SHRLIBNAME_YES = $(BUILD_LIBRARY:%=%$(SHRLIB_SUFFIX))
|
||||
LOADABLE_SHRLIBNAME = $(LOADABLE_BUILD_LIBRARY:%=%$(SHRLIB_SUFFIX))
|
||||
|
||||
#
|
||||
# When SHARED_LIBRARIES is YES we are building a DLL link library
|
||||
# When SHARED_LIBRARIES is YES we are building a DLL link library
|
||||
# and when SHARED_LIBRARIES is NO we are building an object library
|
||||
#
|
||||
DLL_LINK_LIBNAME_YES = $(BUILD_LIBRARY:%=%.lib)
|
||||
@@ -289,7 +305,7 @@ LINK.cpp = $(WINLINK) -nologo $(STATIC_LDFLAGS) $(LDFLAGS) $(PROD_LDFLAGS) \
|
||||
#--------------------------------------------------
|
||||
# UseManifestTool.pl checks MS Visual c++ compiler version number to
|
||||
# decide whether or not to use the Manifest Tool command to embed the
|
||||
# linker created .manifest file into a library or product target.
|
||||
# linker created .manifest file into a library or product target.
|
||||
# useManifestTool.pl returns 0(don't use) or 1(use).
|
||||
#
|
||||
MT.exe = mt.exe -nologo -manifest $@.manifest
|
||||
@@ -299,4 +315,3 @@ MT_EXE_COMMAND_NO = $(MT.exe) "-outputresource:$@;\#1"
|
||||
MT_EXE_COMMAND1 = $(MT_EXE_COMMAND_$(STATIC_BUILD))
|
||||
MT_DLL_COMMAND = $(MT_DLL_COMMAND$(shell $(PERL) $(TOOLS)/useManifestTool.pl))
|
||||
MT_EXE_COMMAND = $(MT_EXE_COMMAND$(shell $(PERL) $(TOOLS)/useManifestTool.pl))
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
11
configure/os/CONFIG_SITE.linux-x86.linux-xscale_be
Normal file
11
configure/os/CONFIG_SITE.linux-x86.linux-xscale_be
Normal 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
|
||||
7
configure/os/CONFIG_SITE.linux-x86_64.linux-xscale_be
Normal file
7
configure/os/CONFIG_SITE.linux-x86_64.linux-xscale_be
Normal 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
|
||||
@@ -4,27 +4,16 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
||||
<title>Known Problems in R3.14.12.1</title>
|
||||
<title>Known Problems in R3.14.12.8</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1 style="text-align: center">EPICS Base R3.14.12.1: Known Problems</h1>
|
||||
<h1 style="text-align: center">EPICS Base R3.14.12.8: Known Problems</h1>
|
||||
|
||||
<p>Any patch files linked below should be applied at the root of the
|
||||
base-3.14.12.1 tree. Download them, then use the GNU Patch program as
|
||||
follows:</p>
|
||||
|
||||
<blockquote><pre>% <b>cd <i>/path/to/</i>base-3.14.12.1</b>
|
||||
% <b>patch -p0 < <i>/path/to/</i>file.patch</b></pre></blockquote>
|
||||
|
||||
<p>The following significant problems have been reported with this
|
||||
version of EPICS Base:</p>
|
||||
|
||||
<ul>
|
||||
|
||||
<li>None yet.</li>
|
||||
|
||||
</ul>
|
||||
<p>This was the last release in the Base-3.14 series, so we are no longer
|
||||
tracking bugs in this branch. Please upgrade to one of the newer releases which
|
||||
have incorporated many bug fixes and new features since they branched off the
|
||||
Base-3.14 release series.</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -221,14 +221,11 @@
|
||||
|
||||
base/startup directory - contains scripts to set environment and path
|
||||
|
||||
EpicsHostArch C shell script to set EPICS_HOST_ARCH env variable
|
||||
EpicsHostArch.pl Perl script to set EPICS_HOST_ARCH env variable
|
||||
Site.profile bourne shell script to set path and env variables
|
||||
Site.cshrc c shell script to set path and env variables
|
||||
borland.bat WIN32 bat file to set borland path and env variables
|
||||
cygwin.bat WIN32 bat file to set cygwin path and env variables
|
||||
win32.bat WIN32 bat file to set path and env variables
|
||||
win32-debug.bat WIN32 debug bat file to set debug path and env variables
|
||||
EpicsHostArch Shell script to set EPICS_HOST_ARCH env variable
|
||||
unix.csh C shell script to set path and env variables
|
||||
unix.sh Bourne shell script to set path and env variables
|
||||
win32.bat Bat file example to configure win32-x86 target
|
||||
windows.bat Bat file example to configure windows-x64 target
|
||||
|
||||
base/configure directory - contains build definitions and rules
|
||||
|
||||
@@ -436,6 +433,6 @@
|
||||
|
||||
References
|
||||
|
||||
1. http://www.aps.anl.gov/epics/base/tornado.php
|
||||
2. http://www.aps.anl.gov/epics/base/vxWorks6.php
|
||||
3. http://www.aps.anl.gov/epics/
|
||||
1. https://epics.anl.gov/base/tornado.php
|
||||
2. https://epics.anl.gov/base/vxWorks6.php
|
||||
3. https://epics.anl.gov/
|
||||
|
||||
@@ -21,7 +21,7 @@ of my Bash login script (~/.bash_login):
|
||||
#
|
||||
EPICS_BASE="${HOME}/src/EPICS/base"
|
||||
EPICS_EXTENSIONS="${HOME}/src/EPICS/extensions"
|
||||
<strong>.</strong> "${EPICS_BASE}"/startup/Site.profile
|
||||
<strong>.</strong> "${EPICS_BASE}"/startup/unix.sh
|
||||
</pre>
|
||||
</li>
|
||||
<li>
|
||||
|
||||
@@ -96,8 +96,8 @@
|
||||
needed to build for these target systems. The absolute path to and version
|
||||
number of the vxWorks installation is normally specified in the
|
||||
base/configure/os/CONFIG_SITE.Common.vxWorksCommon file. Consult the EPICS web
|
||||
pages about <a href="http://www.aps.anl.gov/epics/base/tornado.php">vxWorks
|
||||
5.x</a> and <a href="http://www.aps.anl.gov/epics/base/vxWorks6.php">vxWorks
|
||||
pages about <a href="https://epics.anl.gov/base/tornado.php">vxWorks
|
||||
5.x</a> and <a href="https://epics.anl.gov/base/vxWorks6.php">vxWorks
|
||||
6.x</a> and the vxWorks documentation for information about configuring your
|
||||
vxWorks operating system for use with EPICS.</P>
|
||||
|
||||
@@ -126,7 +126,7 @@
|
||||
|
||||
<H3><A NAME="0_0_8"> Documentation</A></H3>
|
||||
<BLOCKQUOTE>EPICS documentation is available through the
|
||||
<a href="http://www.aps.anl.gov/epics/">EPICS website</a> at Argonne.
|
||||
<a href="https://epics.anl.gov/">EPICS website</a> at Argonne.
|
||||
<P>Release specific documentation can also be found in the base/documentation
|
||||
directory of the distribution.</BLOCKQUOTE>
|
||||
|
||||
@@ -230,14 +230,11 @@
|
||||
|
||||
<H4>base/startup directory - contains scripts to set environment and path</H4>
|
||||
<PRE>
|
||||
EpicsHostArch C shell script to set EPICS_HOST_ARCH env variable
|
||||
EpicsHostArch.pl Perl script to set EPICS_HOST_ARCH env variable
|
||||
Site.profile bourne shell script to set path and env variables
|
||||
Site.cshrc c shell script to set path and env variables
|
||||
borland.bat WIN32 bat file to set borland path and env variables
|
||||
cygwin.bat WIN32 bat file to set cygwin path and env variables
|
||||
win32.bat WIN32 bat file to set path and env variables
|
||||
win32-debug.bat WIN32 debug bat file to set debug path and env variables
|
||||
EpicsHostArch Shell script to set EPICS_HOST_ARCH env variable
|
||||
unix.csh C shell script to set path and env variables
|
||||
unix.sh Bourne shell script to set path and env variables
|
||||
win32.bat Bat file example to configure win32-x86 target
|
||||
windows.bat Bat file example to configure windows-x64 target
|
||||
</PRE>
|
||||
|
||||
<H4>base/configure directory - contains build definitions and rules</H4>
|
||||
|
||||
@@ -3,15 +3,239 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
|
||||
<title>EPICS Base R3.14.12.6 Release Notes</title>
|
||||
<title>EPICS Base R3.14.12.8 Release Notes</title>
|
||||
</head>
|
||||
|
||||
<body lang="en">
|
||||
<h1 align="center">EPICS Base Release 3.14.12.6</h1>
|
||||
<h1 align="center">EPICS Base Release 3.14.12.8</h1>
|
||||
|
||||
<p>This is the final release in the Base-3.14 series, please upgrade to the
|
||||
Base-3.15 series or to EPICS 7.</p>
|
||||
|
||||
<h2 align="center">Changes between 3.14.12.7 and 3.14.12.8</h2>
|
||||
|
||||
<!-- Insert new items immediately below here ... -->
|
||||
|
||||
<h3>Fix broken <tt>EPICS_IOC_LOG_FILE_LIMIT=0</tt> setting</h3>
|
||||
|
||||
<p>The Application Developers' Guide says this is allowed and disables the
|
||||
limit on the log-file, but it hasn't actually worked for some time (if ever).
|
||||
Note that the iocLogServer will be removed from newer Base release sometime
|
||||
soon as its functionality can be implemented by other dedicated log servers
|
||||
such as logstash or syslog-ng.</p>
|
||||
|
||||
<p>Fixes <a href="https://bugs.launchpad.net/bugs/1786858">lp:1786858</a>
|
||||
and part of <a href="https://bugs.launchpad.net/bugs/1786966">lp:1786966</a>.
|
||||
</p>
|
||||
|
||||
<h3>Cleanup of startup directory</h3>
|
||||
|
||||
<p>The files in the startup directory have not been maintained in recent years
|
||||
and have grown crufty (technical term). This release includes the following
|
||||
updates to these files:</p>
|
||||
|
||||
<ul>
|
||||
|
||||
<li>The Perl <tt>EpicsHostArch.pl</tt> script has been rewritten, and support
|
||||
for a few previously missing host architectures has been added to it.</li>
|
||||
|
||||
<li>The <tt>EpicsHostArch.pl</tt> script has also been moved into the standard
|
||||
<tt>src/tools</tt> directory, from where it will be installed into
|
||||
<tt>lib/perl</tt>. In this new location it is no longer executable, so it must
|
||||
be run by the <tt>perl</tt> executable.</li>
|
||||
|
||||
<li>The build system has been adjusted to look for <tt>EpicsHostArch.pl</tt> in
|
||||
both places if the <tt>EPICS_HOST_ARCH</tt> environment variable has not been
|
||||
set at build-time.</li>
|
||||
|
||||
<li>Sites that used the original Perl script to set <tt>EPICS_HOST_ARCH</tt> as
|
||||
part of their standard environment will need to adjust their scripts when they
|
||||
upgrade to this release.</li>
|
||||
|
||||
<li>The <tt>EpicsHostArch</tt> shell script has been replaced with a wrapper
|
||||
routine that calls the Perl <tt>EpicsHostArch.pl</tt> script. Sites that rely on
|
||||
this script to set <tt>EPICS_HOST_ARCH</tt> should consider switching to the
|
||||
Perl script instead.</li>
|
||||
|
||||
<li>The <tt>Site.cshrc</tt> and <tt>Site.profile</tt> files have been renamed to
|
||||
<tt>unix.csh</tt> and <tt>unix.sh</tt>, respectively.</li>
|
||||
|
||||
<li>The existing <tt>win32.bat</tt> file has been cleaned up and a new
|
||||
<tt>windows.bat</tt> file added for 64-bit targets. The contents of these files
|
||||
should be seen as examples, don't uncomment or install parts for software that
|
||||
you don't explicitly know that you need.</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<h3>Recent Apple XCode Build Issues</h3>
|
||||
|
||||
<p>The latest version of XCode will not compile calls to <tt>system()</tt> or
|
||||
<tt>clock_settime()</tt> for iOS targets. There were several places in Base
|
||||
where these were being compiled, although there were probably never called. The
|
||||
code has now been modified to permit iOS builds to complete again.</p>
|
||||
|
||||
<h3>Prevent illegal alarm severities</h3>
|
||||
|
||||
<p>A check has been added to <tt>recGblResetAlarms()</tt> that prevents records
|
||||
from getting an alarm severity higher than INVALID_ALARM. It is still possible
|
||||
for a field like HSV to get set to a value that is not a legal alarm severity,
|
||||
but the core IOC code should never copy such a value into a record's SEVR or
|
||||
ACKS fields. With this fix the record's alarm severity will be limited to
|
||||
INVALID_ALARM.</p>
|
||||
|
||||
<h3>Fixes for Launchpad bugs</h3>
|
||||
|
||||
<p>The following launchpad bugs have fixes included:</p>
|
||||
|
||||
<ul>
|
||||
<li><a href="https://bugs.launchpad.net/epics-base/+bug/1786320">
|
||||
lp: #1786320</a>, dbCa subscribes twice to ENUM</li>
|
||||
<li><a href="https://bugs.launchpad.net/epics-base/+bug/541221">
|
||||
lp: #541221</a>, 'assert (pca->pgetNative)' failed in ../dbCa.c</li>
|
||||
<li><a href="https://bugs.launchpad.net/epics-base/+bug/1747091">
|
||||
lp: #1747091</a>, epicsTimeGetEvent() / generalTime bug</li>
|
||||
<li><a href="https://bugs.launchpad.net/epics-base/+bug/1743076">
|
||||
lp: #1743076</a>, Segfault in ca_attach_context() during exits</li>
|
||||
<li><a href="https://bugs.launchpad.net/epics-base/+bug/1751380">
|
||||
lp: #1751380</a>, Deadlock in ca_clear_subscription()</li>
|
||||
<li><a href="https://bugs.launchpad.net/epics-base/+bug/1597809">
|
||||
lp: #1597809</a>, Setting NAME field in DB file may break IOC</li>
|
||||
<li><a href="https://bugs.launchpad.net/epics-base/+bug/1770292">
|
||||
lp: #1770292</a>, get_alarm_double() inconsistent across record types</li>
|
||||
<li><a href="https://bugs.launchpad.net/epics-base/+bug/1771298">
|
||||
lp: #1771298</a>, Conversion of NaN to integer relies on undefined
|
||||
behavior</li>
|
||||
</ul>
|
||||
|
||||
<h3>Updated VxWorks Timezone settings</h3>
|
||||
|
||||
<p>Removed the settings for 2017; fixed the hour of the change for MET.</p>
|
||||
|
||||
<h3>Back-port podToHtml.pl and Rules from Base-3.15</h3>
|
||||
|
||||
<p>This script permits Base to be built with Perl installations that do not
|
||||
provide the podchecker and pod2html scripts (e.g. Fedora 27).</p>
|
||||
|
||||
<h3>Fixed camonitor server side relative timestamps bug</h3>
|
||||
|
||||
<p>Initialize the first time-stamp from the first monitor, not the client-side
|
||||
current time in this configuration.</p>
|
||||
|
||||
<h3>Build changes for MSVC</h3>
|
||||
|
||||
<p>Windows builds using Visual Studio 2015 and later now use the <tt>-FS</tt>
|
||||
compiler option to allow parallel builds to work properly.</p>
|
||||
|
||||
<p>We now give the <tt>-FC</tt> option to tell the compiler to print absolute
|
||||
paths for source files in diagnostic messages.</p>
|
||||
|
||||
<h2 align="center">Changes between 3.14.12.6 and 3.14.12.7</h2>
|
||||
|
||||
<h3>Extend maximum Posix epicsEventWaitWithTimeout() delay</h3>
|
||||
|
||||
<p>The Posix implementation of epicsEventWaitWithTimeout() was limiting the
|
||||
timeout delay to at most 60 minutes (3600.0 seconds). This has been changed to
|
||||
10 years; significantly longer maximum delays cause problems on systems where
|
||||
<tt>time_t</tt> is still a signed 32-bit integer so cannot represent absolute
|
||||
time-stamps after 2038-01-19. Our assumption is that such 32-bit systems will
|
||||
have been retired before the year 2028, but some additional tests have been
|
||||
added to the epicsTimeTest program to detect and fail if this assumption is
|
||||
violated.</p>
|
||||
|
||||
<h3>New test-related make targets</h3>
|
||||
|
||||
<p>This release adds several new make targets intended for use by developers
|
||||
and Continuous Integration systems which simplify the task of running the
|
||||
built-in self-test programs and viewing the results. Since these targets are
|
||||
intended for limited use they can have requirements for the build host which
|
||||
go beyond the standard minimum set needed to build and run Base.</p>
|
||||
|
||||
<blockquote>
|
||||
|
||||
<h4><tt>test-results</tt> — 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> — 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> — 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>
|
||||
|
||||
<!-- Insert new items immediately below here ... -->
|
||||
<h3>Launchpad Bug-fixes</h3>
|
||||
|
||||
<p>In addition to the more detailed change descriptions below, the following
|
||||
Launchpad bugs have also been fixed in this release:</p>
|
||||
|
||||
<ul>
|
||||
<li><a href="https://bugs.launchpad.net/epics-base/+bug/1440186">
|
||||
#1440186</a> Crash due to a too small buffer being provided in
|
||||
dbContextReadNotifyCache</li>
|
||||
<li><a href="https://bugs.launchpad.net/epics-base/+bug/1479316">
|
||||
#1479316</a> Some data races found using Helgrind</li>
|
||||
<li><a href="https://bugs.launchpad.net/epics-base/+bug/1495833">
|
||||
#1495833</a> biRecord prompt groups are nonsensical</li>
|
||||
<li><a href="https://bugs.launchpad.net/epics-base/+bug/1606848">
|
||||
#1606848</a> WSAIoctl SIO_GET_INTERFACE_LIST failed in Windows</li>
|
||||
</ul>
|
||||
|
||||
<h3>Whole-Program Optimization for MS Visual Studio Targets</h3>
|
||||
|
||||
<p>When using the Microsoft compilers a new build system variable is provided
|
||||
that controls whether whole program optimization is used or not. For static
|
||||
builds using Visual Studio 2010 this optimization must be disabled. This is
|
||||
controlled in the files configure/os/CONFIG_SITE.Common.windows-x64-static and
|
||||
configure/os/CONFIG_SITE.Common.win32-x86-static by setting the variable
|
||||
<tt>OPT_WHOLE_PROGRAM = NO</tt> to override the default value
|
||||
<tt>YES</tt> that would otherwise be used.</p>
|
||||
|
||||
<p>Note that enabling this optimization slows down the build process. It is not
|
||||
possible to selectively disable this optimization, when building a particular
|
||||
module say; Microsoft's linker will restart itself automatically with the
|
||||
<tt>-LTCG</tt> flag set and display a warning if it is asked to link any object
|
||||
files that were compiled with the <tt>-GL</tt> flag.</p>
|
||||
|
||||
<h3>Add dynamic (variable length) array support to PCAS</h3>
|
||||
|
||||
@@ -244,8 +468,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>
|
||||
@@ -743,7 +965,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
|
||||
@@ -975,7 +1197,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
|
||||
@@ -1329,7 +1551,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>
|
||||
|
||||
@@ -1422,7 +1644,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,
|
||||
@@ -1435,7 +1657,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
|
||||
@@ -1451,7 +1673,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>
|
||||
@@ -1972,7 +2194,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>
|
||||
@@ -3189,7 +3411,7 @@ was returned as -1.17549435E-38. This is now fixed.</p>
|
||||
in a <name>_DBD macro definition. An include line will be placed in the
|
||||
<name>Include.dbd for each file specified in the <name>_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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
%%
|
||||
|
||||
@@ -1009,7 +1009,7 @@ d:/user/R3.14.clean/epics/base/lib/WIN32-x86/</code></p>
|
||||
<h2><a name="CommandUtils">Command Line Utilities</a></h2>
|
||||
|
||||
<h3><a name="acctst">acctst</a></h3>
|
||||
<pre>acctst <PV name> [progress logging level] [channel duplication count]
|
||||
<pre>acctst <PV name> [progress logging level] [channel duplication count]
|
||||
[test repetition count] [enable preemptive callback]</pre>
|
||||
|
||||
<h4>Description</h4>
|
||||
@@ -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 <type></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 <nr></td>
|
||||
<td>Use %e format, with <nr> digits after the decimal point</td>
|
||||
<td>Use %e format, with a precision of <nr> digits</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>-f <nr></td>
|
||||
<td>Use %f format, with <nr> digits after the decimal point</td>
|
||||
<td>Use %f format, with a precision of <nr> digits</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>-g <nr></td>
|
||||
<td>Use %g format, with <nr> digits after the decimal point</td>
|
||||
<td>Use %g format, with a precision of <nr> 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 <ofs></td>
|
||||
<td>Use <ofs> 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 <mask></td>
|
||||
<td>Specify CA event mask to use, with <mask> being any combination
|
||||
of 'v' (value), 'a' (alarm), 'l' (log), 'p' (property). Default: va</td>
|
||||
<td>-m <msk></td>
|
||||
<td>Specify CA event mask to use. <msk> 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 <prio></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>-# <count></td>
|
||||
<td>Print first <count> elements of an array</td>
|
||||
<td>-# <num></td>
|
||||
<td>Request and print up to <num> 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 <nr></td>
|
||||
<td>Use %e format, with <nr> digits after the decimal point</td>
|
||||
<td>-e <num></td>
|
||||
<td>Use %e format, with a precision of <num> digits</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>-f <nr></td>
|
||||
<td>Use %f format, with <nr> digits after the decimal point</td>
|
||||
<td>-f <num></td>
|
||||
<td>Use %f format, with a precision of <num> digits</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>-g <nr></td>
|
||||
<td>Use %g format, with <nr> digits after the decimal point</td>
|
||||
<td>-g <num></td>
|
||||
<td>Use %g format, with a precision of <num> 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] <PV name> <value>
|
||||
<pre>caput [options] <PV name> <value> ...
|
||||
caput -a [options] <PV name> <no of elements> <value> ...</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>
|
||||
@@ -2052,7 +2079,7 @@ example, be beneficial when tuning an archiver installation.</p>
|
||||
<p>Significant performance gains can be realized when the CA client library
|
||||
doesn't wait for a response to return from the server after each request. All
|
||||
requests which require interaction with a CA server are accumulated (buffered)
|
||||
and not forwarded to the IOC until one of <code>ca_flush_io()</code>,
|
||||
and not forwarded to the IOC until one of <code>ca_flush_io()</code>,
|
||||
<code>ca_pend_io()</code>, <code>ca_pend_event()</code>, or
|
||||
<code>ca_sg_block()</code> are called allowing several operations to be
|
||||
efficiently sent over the network together. Any process variable values written
|
||||
@@ -2076,16 +2103,16 @@ shouldn't test the success of a CA function call by checking to see if the
|
||||
returned value is zero as is the UNIX convention. Below are several methods to
|
||||
test CA function returns. See <a href="#ca_signal"><code>ca_signal()</code> and
|
||||
<code>SEVCHK()</code></a> for more information on this topic.</p>
|
||||
<pre>status = ca_XXXX();
|
||||
SEVCHK( status, "ca_XXXX() returned failure status");
|
||||
<pre>status = ca_XXXX();
|
||||
SEVCHK( status, "ca_XXXX() returned failure status");
|
||||
|
||||
if ( status & CA_M_SUCCESS ) {
|
||||
printf ( "The requested ca_XXXX() operation didn't complete successfully");
|
||||
}
|
||||
if ( status & CA_M_SUCCESS ) {
|
||||
printf ( "The requested ca_XXXX() operation didn't complete successfully");
|
||||
}
|
||||
|
||||
if ( status != ECA_NORMAL ) {
|
||||
if ( status != ECA_NORMAL ) {
|
||||
printf("The requested ca_XXXX() operation didn't complete successfully because \"%s\"\n",
|
||||
ca_message ( status ) );
|
||||
ca_message ( status ) );
|
||||
}</pre>
|
||||
|
||||
<h3><a name="Channel">Channel Access Data Types</a></h3>
|
||||
@@ -2258,7 +2285,7 @@ int main ( int argc, char ** argv )
|
||||
unsigned nBytes;
|
||||
unsigned elementCount;
|
||||
char timeString[32];
|
||||
unsigned i;
|
||||
unsigned i;
|
||||
chid chan;
|
||||
double sum;
|
||||
int status;
|
||||
@@ -2301,7 +2328,7 @@ int main ( int argc, char ** argv )
|
||||
epicsTimeToStrftime ( timeString, sizeof ( timeString ),
|
||||
"%a %b %d %Y %H:%M:%S.%f", & pTD->stamp );
|
||||
|
||||
printf ( "The sum of elements in %s at %s was %f\n",
|
||||
printf ( "The sum of elements in %s at %s was %f\n",
|
||||
argv[1], timeString, sum );
|
||||
|
||||
ca_clear_channel ( chan );
|
||||
@@ -2332,7 +2359,7 @@ executing within the user's callback function.</p>
|
||||
<pre>typedef struct event_handler_args {
|
||||
void *usr; /* user argument supplied with request */
|
||||
chanId chid; /* channel id */
|
||||
long type; /* the type of the item returned */
|
||||
long type; /* the type of the item returned */
|
||||
long count; /* the element count of the item returned */
|
||||
const void *dbr; /* a pointer to the item returned */
|
||||
int status; /* ECA_XXX status of the requested op from the server */
|
||||
@@ -2355,7 +2382,7 @@ attached to the request, an exception handler is executed in the client. The
|
||||
default exception handler prints a message on the console and exits if the
|
||||
exception condition is severe. Certain internal exceptions within the CA client
|
||||
library, and failures detected by the SEVCHK macro may also cause the exception
|
||||
handler to be invoked. To modify this behavior see
|
||||
handler to be invoked. To modify this behavior see
|
||||
<code><a href="#ca_add_exception_event">ca_add_exception_event</a>()</code>.</p>
|
||||
|
||||
<h3><a name="Server">Server and Client Share the Same Address Space on The Same
|
||||
@@ -2647,6 +2674,14 @@ automatically released by the system when the process exits and
|
||||
vxWorks or RTEMS no cleanup occurs unless the application calls
|
||||
<code>ca_context_destroy()</code>.</p>
|
||||
|
||||
<p>Note: This operation blocks until any user callbacks for any channel
|
||||
created in the current context have run to completion. If callbacks take a
|
||||
lock (mutex) then it is the user's responsibility to ensure that this lock
|
||||
is not held when <code>ca_clear_context()</code> is called, otherwise a
|
||||
deadlock may ensue. (See also
|
||||
<code><a href="#ca_clear_channel">ca_clear_channel</a>()</code> and
|
||||
<code><a href="#ca_clear_event">ca_clear_subscription</a>()</code>.)</p>
|
||||
|
||||
<h4>Returns</h4>
|
||||
|
||||
<p>ECA_NORMAL - Normal successful completion</p>
|
||||
@@ -2719,7 +2754,7 @@ time.</p>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt><code>USERFUNC</code></dt>
|
||||
<dd>Optional address of the user's callback function to be run when the
|
||||
<dd>Optional pointer to the user's callback function to be run when the
|
||||
connection state changes. Casual users of channel access may decide to
|
||||
set this field to null or 0 if they do not need to have a callback
|
||||
function run in response to each connection state change event.
|
||||
@@ -2792,6 +2827,12 @@ efficiently sent over the network in one message.</p>
|
||||
clearing a channel does shutdown and reclaim any channel state change event
|
||||
subscriptions (monitors) registered with the channel.</p>
|
||||
|
||||
<p>Note: This operation blocks until any user callbacks for this channel
|
||||
have run to completion. If callbacks take a lock (mutex) then it is the
|
||||
user's responsibility to ensure that this lock is not held when
|
||||
<code>ca_clear_channel()</code> is called, otherwise a deadlock may ensue.
|
||||
(See also <code><a href="#ca_clear_event">ca_clear_subscription</a>()</code>.)</p>
|
||||
|
||||
<h4>Arguments</h4>
|
||||
<dl>
|
||||
<dt><code>CHID</code></dt>
|
||||
@@ -2806,16 +2847,16 @@ subscriptions (monitors) registered with the channel.</p>
|
||||
|
||||
<h3><code><a name="ca_put">ca_put()</a></code></h3>
|
||||
<pre>#include <cadef.h>
|
||||
int ca_put ( chtype TYPE,
|
||||
chid CHID, void *PVALUE );
|
||||
int ca_array_put ( chtype TYPE, unsigned long COUNT,
|
||||
int ca_put ( chtype TYPE,
|
||||
chid CHID, void *PVALUE );
|
||||
int ca_array_put ( chtype TYPE, unsigned long COUNT,
|
||||
chid CHID, const void *PVALUE);
|
||||
typedef void ( caEventCallBackFunc ) (struct event_handler_args);
|
||||
int ca_put_callback ( chtype TYPE,
|
||||
chid CHID, const void *PVALUE,
|
||||
caEventCallBackFunc PFUNC, void *USERARG );
|
||||
int ca_array_put_callback ( chtype TYPE, unsigned long COUNT,
|
||||
chid CHID, const void *PVALUE,
|
||||
int ca_put_callback ( chtype TYPE,
|
||||
chid CHID, const void *PVALUE,
|
||||
caEventCallBackFunc PFUNC, void *USERARG );
|
||||
int ca_array_put_callback ( chtype TYPE, unsigned long COUNT,
|
||||
chid CHID, const void *PVALUE,
|
||||
caEventCallBackFunc PFUNC, void *USERARG );</pre>
|
||||
|
||||
<h4>Description</h4>
|
||||
@@ -2894,7 +2935,7 @@ but they do not cause the record to be processed.</p>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt><code>PFUNC</code></dt>
|
||||
<dd>address of <a href="#User">user supplied callback function</a> to be
|
||||
<dd>Pointer to a <a href="#User">user supplied callback function</a> to be
|
||||
run when the requested operation completes</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
@@ -3002,7 +3043,7 @@ when a CA get request is initiated.</p>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt><code>USERFUNC</code></dt>
|
||||
<dd>Address of <a href="#User">user supplied callback function</a> to be
|
||||
<dd>Pointer to a <a href="#User">user supplied callback function</a> to be
|
||||
run when the requested operation completes.</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
@@ -3042,7 +3083,7 @@ when a CA get request is initiated.</p>
|
||||
typedef void ( caEventCallBackFunc ) (struct event_handler_args);
|
||||
int ca_create_subscription ( chtype TYPE, unsigned long COUNT,
|
||||
chid CHID, unsigned long MASK,
|
||||
caEventCallBackFunc USERFUNC, void *USERARG,
|
||||
caEventCallBackFunc USERFUNC, void *USERARG,
|
||||
evid *PEVID );</pre>
|
||||
|
||||
<h4>Description</h4>
|
||||
@@ -3103,8 +3144,8 @@ indicating the current state of the channel.</p>
|
||||
<dd>channel identifier</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt><code>USRERFUNC</code></dt>
|
||||
<dd>The address of <a href="#User">user supplied callback function</a> to
|
||||
<dt><code>USERFUNC</code></dt>
|
||||
<dd>Pointer to a <a href="#User">user supplied callback function</a> to
|
||||
be invoked with each subscription update.</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
@@ -3126,7 +3167,7 @@ indicating the current state of the channel.</p>
|
||||
<dt><code>MASK</code></dt>
|
||||
<dd>A mask with bits set for each of the event trigger types requested. The
|
||||
event trigger mask must be a <em>bitwise or</em> of one or more of the
|
||||
following constants.
|
||||
following constants.
|
||||
<ul>
|
||||
<li>DBE_VALUE - Trigger events when the channel value exceeds the
|
||||
monitor dead band</li>
|
||||
@@ -3173,6 +3214,13 @@ and not forwarded to the server until one of <code>ca_flush_io()</code>, <code>c
|
||||
<code>ca_pend_event()</code>, or <code>ca_sg_block()</code> are called. This allows several requests to be
|
||||
efficiently sent together in one message.</p>
|
||||
|
||||
<p>Note: This operation blocks until any user callbacks for this channel
|
||||
have run to completion. If callbacks take a lock (mutex) then it is the
|
||||
user's responsibility to ensure that this lock is not held when
|
||||
<code>ca_clear_subscription()</code> is called, otherwise a deadlock may
|
||||
ensue. (See also <code><a
|
||||
href="#ca_clear_channel">ca_clear_channel</a>()</code>.)</p>
|
||||
|
||||
<h4>Arguments</h4>
|
||||
<dl>
|
||||
<dt>EVID</dt>
|
||||
@@ -3337,7 +3385,7 @@ becomes full.</p>
|
||||
|
||||
<h3><code><a name="ca_signal">ca_signal()</a></code></h3>
|
||||
<pre>#include <cadef.h>
|
||||
int ca_signal ( long CA_STATUS, const char * CONTEXT_STRING );
|
||||
int ca_signal ( long CA_STATUS, const char * CONTEXT_STRING );
|
||||
void SEVCHK( CA_STATUS, CONTEXT_STRING );</pre>
|
||||
|
||||
<h4>Description</h4>
|
||||
@@ -3354,7 +3402,7 @@ recommended error handler for simple applications which do not wish to write
|
||||
code testing the status returned from each channel access call.</p>
|
||||
|
||||
<h4>Examples</h4>
|
||||
<pre>status = ca_context_create (...);
|
||||
<pre>status = ca_context_create (...);
|
||||
SEVCHK ( status, "Unable to create a CA client context" );</pre>
|
||||
|
||||
<p>If the application only wishes to print the message associated with an error
|
||||
@@ -3378,7 +3426,7 @@ this purpose.</p>
|
||||
|
||||
<h3><code><a
|
||||
name="ca_add_exception_event">ca_add_exception_event()</a></code></h3>
|
||||
<pre>#include <cadef.h>
|
||||
<pre>#include <cadef.h>
|
||||
typedef void (*pCallback) ( struct exception_handler_args HANDLERARGS );
|
||||
int ca_add_exception_event ( pCallback USERFUNC, void *USERARG );</pre>
|
||||
|
||||
@@ -3402,7 +3450,7 @@ field should not be used.</p>
|
||||
<h4>Arguments</h4>
|
||||
<dl>
|
||||
<dt><code>USERFUNC</code></dt>
|
||||
<dd>Address of user callback function to be executed when an exceptions
|
||||
<dd>Pointer to a user callback function to be executed when exceptions
|
||||
occur. Passing a null value causes the default exception handler to be
|
||||
reinstalled. The following structure is passed by value to the user's
|
||||
callback function. Currently, the <code>op</code> field can be one of
|
||||
@@ -3537,7 +3585,7 @@ default handler uses fprintf to send messages to 'stderr'.</p>
|
||||
<h4>Arguments</h4>
|
||||
<dl>
|
||||
<dt><code>PFUNC</code></dt>
|
||||
<dd>The address of a user supplied callback handler to be invoked when CA
|
||||
<dd>A pointer to a user supplied callback handler to be invoked when CA
|
||||
prints diagnostic messages. Installing a null pointer will cause the
|
||||
default callback handler to be reinstalled.</dd>
|
||||
</dl>
|
||||
@@ -3585,9 +3633,9 @@ specified channel.</p>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt><code>PFUNC</code></dt>
|
||||
<dd>Address of user supplied callback function. A null pointer uninstalls
|
||||
<dd>Pointer to a user supplied callback function. A null pointer uninstalls
|
||||
the current handler. The following arguments are passed <em>by value</em>
|
||||
to the supplied callback handler.
|
||||
to the supplied callback handler.
|
||||
<pre>typedef struct ca_access_rights {
|
||||
unsigned read_access:1;
|
||||
unsigned write_access:1;
|
||||
@@ -3927,8 +3975,8 @@ type.</p>
|
||||
prints diagnostics to standard out.</p>
|
||||
|
||||
<h4>Examples</h4>
|
||||
<pre>void ca_test_event ();
|
||||
status = ca_create_subscription ( type, chid, ca_test_event, NULL, NULL );
|
||||
<pre>void ca_test_event ();
|
||||
status = ca_create_subscription ( type, chid, ca_test_event, NULL, NULL );
|
||||
SEVCHK ( status, .... );</pre>
|
||||
|
||||
<h4>See Also</h4>
|
||||
@@ -3962,8 +4010,8 @@ outstanding within them at any given time.</p>
|
||||
</dl>
|
||||
|
||||
<h4>Examples</h4>
|
||||
<pre>CA_SYNC_GID gid;
|
||||
status = ca_sg_create ( &gid );
|
||||
<pre>CA_SYNC_GID gid;
|
||||
status = ca_sg_create ( &gid );
|
||||
SEVCHK ( status, Sync group create failed );</pre>
|
||||
|
||||
<h4>Returns</h4>
|
||||
@@ -4001,8 +4049,8 @@ int ca_sg_delete ( CA_SYNC_GID GID );</pre>
|
||||
</dl>
|
||||
|
||||
<h4>Examples</h4>
|
||||
<pre>CA_SYNC_GID gid;
|
||||
status = ca_sg_delete ( gid );
|
||||
<pre>CA_SYNC_GID gid;
|
||||
status = ca_sg_delete ( gid );
|
||||
SEVCHK ( status, Sync group delete failed );</pre>
|
||||
|
||||
<h4>Returns</h4>
|
||||
@@ -4113,7 +4161,7 @@ will not block unless additional subsequent requests are made.</p>
|
||||
</dl>
|
||||
|
||||
<h4>Examples</h4>
|
||||
<pre>CA_SYNC_GID gid;
|
||||
<pre>CA_SYNC_GID gid;
|
||||
status = ca_sg_reset(gid);</pre>
|
||||
|
||||
<h4>Returns</h4>
|
||||
@@ -4126,7 +4174,7 @@ status = ca_sg_reset(gid);</pre>
|
||||
<pre>#include <cadef.h>
|
||||
int ca_sg_put ( CA_SYNC_GID GID, chtype TYPE,
|
||||
chid CHID, void *PVALUE );
|
||||
int ca_sg_array_put ( CA_SYNC_GID GID, chtype TYPE,
|
||||
int ca_sg_array_put ( CA_SYNC_GID GID, chtype TYPE,
|
||||
unsigned long COUNT, chid CHID, void *PVALUE );</pre>
|
||||
|
||||
<p>Write a value, or array of values, to a channel and increment the outstanding
|
||||
@@ -4267,7 +4315,7 @@ reissued.</p>
|
||||
|
||||
<h3><code><a name="ca_client_status">ca_client_status()</a></code></h3>
|
||||
<pre>int ca_client_status ( unsigned level );
|
||||
int ca_context_status ( struct ca_client_context *CONTEXT,
|
||||
int ca_context_status ( struct ca_client_context *CONTEXT,
|
||||
unsigned LEVEL );</pre>
|
||||
|
||||
<h4>Description</h4>
|
||||
|
||||
@@ -127,21 +127,10 @@ const char * ca_message_text []
|
||||
|
||||
static epicsThreadOnceId caClientContextIdOnce = EPICS_THREAD_ONCE_INIT;
|
||||
|
||||
extern "C" void ca_client_exit_handler (void *)
|
||||
{
|
||||
if ( caClientContextId ) {
|
||||
epicsThreadPrivateDelete ( caClientContextId );
|
||||
caClientContextId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// runs once only for each process
|
||||
extern "C" void ca_init_client_context ( void * )
|
||||
{
|
||||
caClientContextId = epicsThreadPrivateCreate ();
|
||||
if ( caClientContextId ) {
|
||||
epicsAtExit ( ca_client_exit_handler,0 );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -639,7 +639,7 @@ not follow this pattern, but are still printable strings.
|
||||
|
||||
=item [1] R3.14 Channel Access Reference Manual by Jeffrey O. Hill
|
||||
|
||||
L<http://www.aps.anl.gov/epics/base/R3-14/12-docs/CAref.html>
|
||||
L<https://epics.anl.gov/base/R3-14/12-docs/CAref.html>
|
||||
|
||||
=back
|
||||
|
||||
|
||||
@@ -66,10 +66,6 @@ ifdef T_A
|
||||
$(RM) $@ $@_new
|
||||
$(PERL) $(XSUBPP) -typemap $(EXTUTILS)/typemap $< > $@_new && $(MV) $@_new $@
|
||||
|
||||
%.html: ../%.pm
|
||||
$(RM) $@
|
||||
podchecker $< && pod2html --infile=$< --outfile=$@
|
||||
|
||||
$(INSTALL_PERL_MODULES)/$(PERL_ARCHPATH)/%: %
|
||||
$(ECHO) "Installing loadable shared library $@"
|
||||
@$(INSTALL_LIBRARY) -d -m $(LIB_PERMISSIONS) $< $(INSTALL_PERL_MODULES)/$(PERL_ARCHPATH)
|
||||
|
||||
@@ -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 ($@) {
|
||||
@@ -137,6 +140,10 @@ sub display {
|
||||
printf " Lo ctrl limit: %g\n", $data->{lower_ctrl_limit};
|
||||
printf " Hi ctrl limit: %g\n", $data->{upper_ctrl_limit};
|
||||
}
|
||||
if (exists $data->{ackt}) {
|
||||
printf " Ack transients: %s\n", $data->{ackt} ? 'YES' : 'NO';
|
||||
printf " Ack severity: %s\n", $data->{acks};
|
||||
}
|
||||
} else {
|
||||
my $value = format_number($data, $type);
|
||||
if ($opt_t) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 )
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
//
|
||||
@@ -646,6 +646,11 @@ caStatus casDGClient::processDG ()
|
||||
if ( status != S_cas_success ) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ( this->in.bytesPresent () > 0 && dgInBytesConsumed == 0 && status == S_cas_success ) {
|
||||
this->in.removeMsg ( this->in.bytesPresent() );
|
||||
}
|
||||
|
||||
}
|
||||
return status;
|
||||
}
|
||||
@@ -655,7 +660,7 @@ caStatus casDGClient::processDG ()
|
||||
//
|
||||
unsigned casDGClient::getDebugLevel() const
|
||||
{
|
||||
return this->getCAS().getDebugLevel();
|
||||
return this->getCAS().getDebugLevel();
|
||||
}
|
||||
|
||||
//
|
||||
@@ -663,7 +668,7 @@ unsigned casDGClient::getDebugLevel() const
|
||||
//
|
||||
caNetAddr casDGClient::fetchLastRecvAddr () const
|
||||
{
|
||||
return this->lastRecvAddr;
|
||||
return this->lastRecvAddr;
|
||||
}
|
||||
|
||||
//
|
||||
@@ -671,7 +676,7 @@ caNetAddr casDGClient::fetchLastRecvAddr () const
|
||||
//
|
||||
ca_uint32_t casDGClient::datagramSequenceNumber () const
|
||||
{
|
||||
return this->seqNoOfReq;
|
||||
return this->seqNoOfReq;
|
||||
}
|
||||
|
||||
//
|
||||
@@ -731,27 +736,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 +805,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 +851,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 +866,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 +935,7 @@ caStatus casDGClient::sendErr ( const caHdrLargeArray *curp,
|
||||
this->out.commitMsg ();
|
||||
}
|
||||
|
||||
return S_cas_success;
|
||||
return S_cas_success;
|
||||
}
|
||||
|
||||
|
||||
@@ -938,8 +944,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 +956,5 @@ caStatus casDGClient::echoAction ()
|
||||
memcpy ( pPayloadOut, dp, mp->m_postsize );
|
||||
this->out.commitMsg ();
|
||||
}
|
||||
return S_cas_success;
|
||||
return S_cas_success;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -81,14 +81,14 @@ static void sprint_long (char *ret, dbr_long_t val, IntFormatT outType)
|
||||
}
|
||||
else {
|
||||
const char *fmt[4] = { /* Order must match the enum IntFormatT */
|
||||
"%ld" /* dec */,
|
||||
"0" /* bin, val is 0 */,
|
||||
"0o%lo" /* oct */,
|
||||
"0x%lX" /* hex */
|
||||
"%d" /* dec */,
|
||||
"0" /* bin and val is 0 */,
|
||||
"0o%o" /* oct */,
|
||||
"0x%X" /* hex */
|
||||
};
|
||||
|
||||
/* Formats have long modifier, pass value as a long */
|
||||
sprintf(ret, fmt[outType], (long) val);
|
||||
/* dbr_long_t is actually an int on all supported platforms */
|
||||
sprintf(ret, fmt[outType], (int) val);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -416,6 +416,12 @@ char *dbr2str (const void *value, unsigned type)
|
||||
ptsNewS = &((struct TYPE *)value)->stamp; \
|
||||
ptsNewC = &tsNow; \
|
||||
\
|
||||
if (!tsInitS) \
|
||||
{ \
|
||||
tsFirst = *ptsNewS; \
|
||||
tsInitS = 1; \
|
||||
} \
|
||||
\
|
||||
switch (tsType) { \
|
||||
case relative: \
|
||||
ptsRefC = &tsStart; \
|
||||
@@ -508,12 +514,6 @@ void print_time_val_sts (pv* pv, unsigned long reqElems)
|
||||
epicsTimeGetCurrent(&tsNow);
|
||||
epicsTimeToStrftime(timeText, TIMETEXTLEN, timeFormatStr, &tsNow);
|
||||
|
||||
if (!tsInitS)
|
||||
{
|
||||
tsFirst = tsNow;
|
||||
tsInitS = 1;
|
||||
}
|
||||
|
||||
if (pv->nElems <= 1 && fieldSeparator == ' ') printf("%-30s", pv->name);
|
||||
else printf("%s", pv->name);
|
||||
printf("%c", fieldSeparator);
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -297,10 +297,10 @@ static void get_alarm(DBADDR *paddr, char **ppbuffer,
|
||||
if (*options & DBR_AL_LONG) {
|
||||
struct dbr_alLong *pal = (struct dbr_alLong*) pbuffer;
|
||||
|
||||
pal->upper_alarm_limit = (epicsInt32) ald.upper_alarm_limit;
|
||||
pal->upper_warning_limit = (epicsInt32) ald.upper_warning_limit;
|
||||
pal->lower_warning_limit = (epicsInt32) ald.lower_warning_limit;
|
||||
pal->lower_alarm_limit = (epicsInt32) ald.lower_alarm_limit;
|
||||
pal->upper_alarm_limit = finite(ald.upper_alarm_limit) ? (epicsInt32) ald.upper_alarm_limit : 0;
|
||||
pal->upper_warning_limit = finite(ald.upper_warning_limit) ? (epicsInt32) ald.upper_warning_limit : 0;
|
||||
pal->lower_warning_limit = finite(ald.lower_warning_limit) ? (epicsInt32) ald.lower_warning_limit : 0;
|
||||
pal->lower_alarm_limit = finite(ald.lower_alarm_limit) ? (epicsInt32) ald.lower_alarm_limit : 0;
|
||||
|
||||
if (no_data)
|
||||
*options ^= DBR_AL_LONG; /*Turn off option*/
|
||||
|
||||
@@ -409,7 +409,7 @@ long epicsShareAPI dbd(const char *record_name)
|
||||
|
||||
precord = addr.precord;
|
||||
|
||||
if (! precord->bkpt & BKPT_ON_MASK) {
|
||||
if (!(precord->bkpt & BKPT_ON_MASK)) {
|
||||
printf(" BKPT> No breakpoint set in this record\n");
|
||||
return(S_db_bkptNotSet);
|
||||
}
|
||||
|
||||
@@ -142,7 +142,6 @@ static void addAction(caLink *pca, short link_action)
|
||||
if (++removesOutstanding >= removesOutstandingWarning) {
|
||||
errlogPrintf("dbCa::addAction pausing, %d channels to clear\n",
|
||||
removesOutstanding);
|
||||
printLinks(pca);
|
||||
}
|
||||
while (removesOutstanding >= removesOutstandingWarning) {
|
||||
epicsMutexUnlock(workListLock);
|
||||
@@ -592,11 +591,16 @@ static void connectionCallback(struct connection_handler_args arg)
|
||||
if (pca->gotFirstConnection) {
|
||||
if (pca->nelements != ca_element_count(arg.chid) ||
|
||||
pca->dbrType != ca_field_type(arg.chid)) {
|
||||
/* BUG: We have no way to clear any old subscription with the
|
||||
* originally chosen data type/size. That will continue
|
||||
* to send us data and will result in an assert() fail.
|
||||
*/
|
||||
/* Let next dbCaGetLink and/or dbCaPutLink determine options */
|
||||
/* Size or type changed, clear everything and let the next call
|
||||
to dbCaGetLink() and/or dbCaPutLink() reset everything */
|
||||
if (pca->evidNative) {
|
||||
ca_clear_event(pca->evidNative);
|
||||
pca->evidNative = 0;
|
||||
}
|
||||
if (pca->evidString) {
|
||||
ca_clear_event(pca->evidString);
|
||||
pca->evidString = 0;
|
||||
}
|
||||
plink->value.pv_link.pvlMask &=
|
||||
~(pvlOptInpNative | pvlOptInpString |
|
||||
pvlOptOutNative | pvlOptOutString);
|
||||
@@ -644,6 +648,7 @@ static void eventCallback(struct event_handler_args arg)
|
||||
struct dbr_time_double *pdbr_time_double;
|
||||
dbCaCallback monitor = 0;
|
||||
void *userPvt = 0;
|
||||
int doScan = 1;
|
||||
|
||||
assert(pca);
|
||||
epicsMutexMustLock(pca->lock);
|
||||
@@ -672,10 +677,13 @@ static void eventCallback(struct event_handler_args arg)
|
||||
memcpy(pca->pgetString, dbr_value_ptr(arg.dbr, arg.type), size);
|
||||
pca->gotInString = TRUE;
|
||||
} else switch (arg.type){
|
||||
case DBR_TIME_ENUM:
|
||||
/* Disable the record scan if we also have a string monitor */
|
||||
doScan = !(plink->value.pv_link.pvlMask & pvlOptInpString);
|
||||
/* fall through */
|
||||
case DBR_TIME_STRING:
|
||||
case DBR_TIME_SHORT:
|
||||
case DBR_TIME_FLOAT:
|
||||
case DBR_TIME_ENUM:
|
||||
case DBR_TIME_CHAR:
|
||||
case DBR_TIME_LONG:
|
||||
case DBR_TIME_DOUBLE:
|
||||
@@ -691,7 +699,7 @@ static void eventCallback(struct event_handler_args arg)
|
||||
pca->sevr = pdbr_time_double->severity;
|
||||
pca->stat = pdbr_time_double->status;
|
||||
memcpy(&pca->timeStamp, &pdbr_time_double->stamp, sizeof(epicsTimeStamp));
|
||||
if (precord) {
|
||||
if (doScan && precord) {
|
||||
struct pv_link *ppv_link = &plink->value.pv_link;
|
||||
|
||||
if ((ppv_link->pvlMask & pvlOptCP) ||
|
||||
@@ -970,7 +978,8 @@ static void dbCaTask(void *arg)
|
||||
status = ca_add_array_event(
|
||||
ca_field_type(pca->chid)+DBR_TIME_STRING,
|
||||
ca_element_count(pca->chid),
|
||||
pca->chid, eventCallback, pca, 0.0, 0.0, 0.0, 0);
|
||||
pca->chid, eventCallback, pca, 0.0, 0.0, 0.0,
|
||||
&pca->evidNative);
|
||||
if (status != ECA_NORMAL) {
|
||||
errlogPrintf("dbCaTask ca_add_array_event %s\n",
|
||||
ca_message(status));
|
||||
@@ -982,7 +991,8 @@ static void dbCaTask(void *arg)
|
||||
pca->pgetString = dbCalloc(1, MAX_STRING_SIZE);
|
||||
epicsMutexUnlock(pca->lock);
|
||||
status = ca_add_array_event(DBR_TIME_STRING, 1,
|
||||
pca->chid, eventCallback, pca, 0.0, 0.0, 0.0, 0);
|
||||
pca->chid, eventCallback, pca, 0.0, 0.0, 0.0,
|
||||
&pca->evidString);
|
||||
if (status != ECA_NORMAL) {
|
||||
errlogPrintf("dbCaTask ca_add_array_event %s\n",
|
||||
ca_message(status));
|
||||
|
||||
@@ -73,6 +73,8 @@ typedef struct caLink
|
||||
char *pgetString;
|
||||
void *pputNative;
|
||||
char *pputString;
|
||||
evid evidNative;
|
||||
evid evidString;
|
||||
char gotInNative;
|
||||
char gotInString;
|
||||
char gotOutNative;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
105
src/db/dbEvent.c
105
src/db/dbEvent.c
@@ -90,7 +90,8 @@ struct event_user {
|
||||
epicsMutexId lock;
|
||||
epicsEventId ppendsem; /* Wait while empty */
|
||||
epicsEventId pflush_sem; /* wait for flush */
|
||||
|
||||
epicsEventId pexitsem; /* wait for event task to join */
|
||||
|
||||
EXTRALABORFUNC *extralabor_sub;/* off load to event task */
|
||||
void *extralabor_arg;/* parameter to above */
|
||||
|
||||
@@ -134,7 +135,9 @@ static char *EVENT_PEND_NAME = "eventTask";
|
||||
|
||||
static struct evSubscrip canceledEvent;
|
||||
|
||||
static unsigned short ringSpace ( const struct event_que *pevq )
|
||||
static epicsMutexId stopSync;
|
||||
|
||||
static unsigned short ringSpace ( const struct event_que *pevq )
|
||||
{
|
||||
if ( pevq->evque[pevq->putix] == EVENTQEMPTY ) {
|
||||
if ( pevq->getix > pevq->putix ) {
|
||||
@@ -274,7 +277,11 @@ int epicsShareAPI dbel ( const char *pname, unsigned level )
|
||||
dbEventCtx epicsShareAPI db_init_events (void)
|
||||
{
|
||||
struct event_user * evUser;
|
||||
|
||||
|
||||
if (!stopSync) {
|
||||
stopSync = epicsMutexMustCreate();
|
||||
}
|
||||
|
||||
if (!dbevEventUserFreeList) {
|
||||
freeListInitPvt(&dbevEventUserFreeList,
|
||||
sizeof(struct event_user),8);
|
||||
@@ -293,38 +300,49 @@ dbEventCtx epicsShareAPI db_init_events (void)
|
||||
if (!evUser) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Flag will be cleared when event task starts */
|
||||
evUser->pendexit = TRUE;
|
||||
|
||||
evUser->firstque.evUser = evUser;
|
||||
evUser->firstque.writelock = epicsMutexCreate();
|
||||
if (!evUser->firstque.writelock) {
|
||||
return NULL;
|
||||
}
|
||||
if (!evUser->firstque.writelock)
|
||||
goto fail;
|
||||
|
||||
evUser->ppendsem = epicsEventCreate(epicsEventEmpty);
|
||||
if (!evUser->ppendsem) {
|
||||
epicsMutexDestroy (evUser->firstque.writelock);
|
||||
return NULL;
|
||||
}
|
||||
if (!evUser->ppendsem)
|
||||
goto fail;
|
||||
evUser->pflush_sem = epicsEventCreate(epicsEventEmpty);
|
||||
if (!evUser->pflush_sem) {
|
||||
epicsMutexDestroy (evUser->firstque.writelock);
|
||||
epicsEventDestroy (evUser->ppendsem);
|
||||
return NULL;
|
||||
}
|
||||
if (!evUser->pflush_sem)
|
||||
goto fail;
|
||||
evUser->lock = epicsMutexCreate();
|
||||
if (!evUser->lock) {
|
||||
epicsMutexDestroy (evUser->firstque.writelock);
|
||||
epicsEventDestroy (evUser->pflush_sem);
|
||||
epicsEventDestroy (evUser->ppendsem);
|
||||
return NULL;
|
||||
}
|
||||
if (!evUser->lock)
|
||||
goto fail;
|
||||
evUser->pexitsem = epicsEventCreate(epicsEventEmpty);
|
||||
if (!evUser->pexitsem)
|
||||
goto fail;
|
||||
|
||||
evUser->flowCtrlMode = FALSE;
|
||||
evUser->extraLaborBusy = FALSE;
|
||||
evUser->pSuicideEvent = NULL;
|
||||
return (dbEventCtx) evUser;
|
||||
fail:
|
||||
if(evUser->lock)
|
||||
epicsMutexDestroy (evUser->lock);
|
||||
if(evUser->firstque.writelock)
|
||||
epicsMutexDestroy (evUser->firstque.writelock);
|
||||
if(evUser->ppendsem)
|
||||
epicsEventDestroy (evUser->ppendsem);
|
||||
if(evUser->pflush_sem)
|
||||
epicsEventDestroy (evUser->pflush_sem);
|
||||
if(evUser->pexitsem)
|
||||
epicsEventDestroy (evUser->pexitsem);
|
||||
freeListFree(dbevEventUserFreeList,evUser);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* intentionally leak stopSync to avoid possible shutdown races */
|
||||
/*
|
||||
* DB_CLOSE_EVENTS()
|
||||
*
|
||||
@@ -346,10 +364,30 @@ void epicsShareAPI db_close_events (dbEventCtx ctx)
|
||||
* hazardous to the system's health.
|
||||
*/
|
||||
epicsMutexMustLock ( evUser->lock );
|
||||
evUser->pendexit = TRUE;
|
||||
if(!evUser->pendexit) { /* event task running */
|
||||
evUser->pendexit = TRUE;
|
||||
epicsMutexUnlock ( evUser->lock );
|
||||
|
||||
/* notify the waiting task */
|
||||
epicsEventSignal(evUser->ppendsem);
|
||||
/* wait for task to exit */
|
||||
epicsEventMustWait(evUser->pexitsem);
|
||||
|
||||
epicsMutexMustLock ( evUser->lock );
|
||||
}
|
||||
|
||||
epicsMutexUnlock ( evUser->lock );
|
||||
/* notify the waiting task */
|
||||
epicsEventSignal(evUser->ppendsem);
|
||||
|
||||
epicsMutexMustLock (stopSync);
|
||||
|
||||
epicsEventDestroy(evUser->pexitsem);
|
||||
epicsEventDestroy(evUser->ppendsem);
|
||||
epicsEventDestroy(evUser->pflush_sem);
|
||||
epicsMutexDestroy(evUser->lock);
|
||||
|
||||
epicsMutexUnlock (stopSync);
|
||||
|
||||
freeListFree(dbevEventUserFreeList, evUser);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -977,14 +1015,17 @@ static void event_task (void *pParm)
|
||||
}
|
||||
}
|
||||
|
||||
epicsEventDestroy(evUser->ppendsem);
|
||||
epicsEventDestroy(evUser->pflush_sem);
|
||||
epicsMutexDestroy(evUser->lock);
|
||||
|
||||
freeListFree(dbevEventUserFreeList, evUser);
|
||||
|
||||
taskwdRemove(epicsThreadGetIdSelf());
|
||||
|
||||
/* use stopSync to ensure pexitsem is not destroy'd
|
||||
* until epicsEventSignal() has returned.
|
||||
*/
|
||||
epicsMutexMustLock (stopSync);
|
||||
|
||||
epicsEventSignal(evUser->pexitsem);
|
||||
|
||||
epicsMutexUnlock(stopSync);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1008,7 +1049,6 @@ int epicsShareAPI db_start_events (
|
||||
return DB_EVENT_OK;
|
||||
}
|
||||
|
||||
evUser->pendexit = FALSE;
|
||||
evUser->init_func = init_func;
|
||||
evUser->init_func_arg = init_func_arg;
|
||||
if (!taskname) {
|
||||
@@ -1022,6 +1062,7 @@ int epicsShareAPI db_start_events (
|
||||
epicsMutexUnlock ( evUser->lock );
|
||||
return DB_EVENT_ERROR;
|
||||
}
|
||||
evUser->pendexit = FALSE;
|
||||
epicsMutexUnlock ( evUser->lock );
|
||||
return DB_EVENT_OK;
|
||||
}
|
||||
|
||||
@@ -525,10 +525,10 @@ long epicsShareAPI dblsr(char *recordname,int level)
|
||||
printf(" Not Locked\n");
|
||||
} else {
|
||||
printf(" thread %p",plockSet->thread_id);
|
||||
if(! plockSet->precord || !plockSet->precord->name)
|
||||
printf(" NULL record or record name\n");
|
||||
if(! plockSet->precord)
|
||||
printf(" NULL record\n");
|
||||
else
|
||||
printf(" record %s\n",plockSet->precord->name);
|
||||
printf(" record %s\n",plockSet->precord->name);
|
||||
}
|
||||
if(level==0) { if(recordname) break; continue; }
|
||||
for(plockRecord = (lockRecord *)ellFirst(&plockSet->lockRecordList);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <limits.h>
|
||||
|
||||
#include "dbDefs.h"
|
||||
#include "alarm.h"
|
||||
#include "epicsMath.h"
|
||||
#include "epicsTime.h"
|
||||
#include "epicsPrint.h"
|
||||
@@ -222,6 +223,9 @@ unsigned short epicsShareAPI recGblResetAlarms(void *precord)
|
||||
epicsEnum16 val_mask = 0;
|
||||
epicsEnum16 stat_mask = 0;
|
||||
|
||||
if (new_sevr > INVALID_ALARM)
|
||||
new_sevr = INVALID_ALARM;
|
||||
|
||||
pdbc->stat = new_stat;
|
||||
pdbc->sevr = new_sevr;
|
||||
pdbc->nsta = 0;
|
||||
|
||||
@@ -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;
|
||||
@@ -959,23 +960,29 @@ static void dbRecordHead(char *recordType, char *name, int visible)
|
||||
|
||||
static void dbRecordField(char *name,char *value)
|
||||
{
|
||||
DBENTRY *pdbentry;
|
||||
tempListNode *ptempListNode;
|
||||
long status;
|
||||
DBENTRY *pdbentry;
|
||||
tempListNode *ptempListNode;
|
||||
long status;
|
||||
|
||||
if(duplicate) return;
|
||||
if (duplicate) return;
|
||||
ptempListNode = (tempListNode *)ellFirst(&tempList);
|
||||
pdbentry = ptempListNode->item;
|
||||
status = dbFindField(pdbentry,name);
|
||||
if(status) {
|
||||
epicsPrintf("Record \"%s\" does not have a field \"%s\"\n",
|
||||
dbGetRecordName(pdbentry), name);
|
||||
yyerror(NULL);
|
||||
return;
|
||||
if (status) {
|
||||
epicsPrintf("Record \"%s\" does not have a field \"%s\"\n",
|
||||
dbGetRecordName(pdbentry), name);
|
||||
yyerror(NULL);
|
||||
return;
|
||||
}
|
||||
if (pdbentry->indfield == 0) {
|
||||
epicsPrintf("Can't set \"NAME\" field of record \"%s\"\n",
|
||||
dbGetRecordName(pdbentry));
|
||||
yyerror(NULL);
|
||||
return;
|
||||
}
|
||||
dbTranslateEscape(value, value); /* yuck: in-place, but safe */
|
||||
status = dbPutString(pdbentry,value);
|
||||
if(status) {
|
||||
if (status) {
|
||||
epicsPrintf("Can't set \"%s.%s\" to \"%s\"\n",
|
||||
dbGetRecordName(pdbentry), name, value);
|
||||
yyerror(NULL);
|
||||
@@ -985,33 +992,33 @@ static void dbRecordField(char *name,char *value)
|
||||
|
||||
static void dbRecordInfo(char *name, char *value)
|
||||
{
|
||||
DBENTRY *pdbentry;
|
||||
tempListNode *ptempListNode;
|
||||
long status;
|
||||
DBENTRY *pdbentry;
|
||||
tempListNode *ptempListNode;
|
||||
long status;
|
||||
|
||||
if(duplicate) return;
|
||||
if (duplicate) return;
|
||||
ptempListNode = (tempListNode *)ellFirst(&tempList);
|
||||
pdbentry = ptempListNode->item;
|
||||
status = dbPutInfo(pdbentry,name,value);
|
||||
if(status) {
|
||||
epicsPrintf("Can't set \"%s\" info \"%s\" to \"%s\"\n",
|
||||
if (status) {
|
||||
epicsPrintf("Can't set \"%s\" info \"%s\" to \"%s\"\n",
|
||||
dbGetRecordName(pdbentry), name, value);
|
||||
yyerror(NULL);
|
||||
return;
|
||||
yyerror(NULL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void dbRecordAlias(char *name)
|
||||
{
|
||||
DBENTRY *pdbentry;
|
||||
tempListNode *ptempListNode;
|
||||
long status;
|
||||
DBENTRY *pdbentry;
|
||||
tempListNode *ptempListNode;
|
||||
long status;
|
||||
|
||||
if(duplicate) return;
|
||||
if (duplicate) return;
|
||||
ptempListNode = (tempListNode *)ellFirst(&tempList);
|
||||
pdbentry = ptempListNode->item;
|
||||
status = dbCreateAlias(pdbentry, name);
|
||||
if(status) {
|
||||
if (status) {
|
||||
epicsPrintf("Can't create alias \"%s\" for \"%s\"\n",
|
||||
name, dbGetRecordName(pdbentry));
|
||||
yyerror(NULL);
|
||||
@@ -1021,15 +1028,16 @@ static void dbRecordAlias(char *name)
|
||||
|
||||
static void dbAlias(char *name, char *alias)
|
||||
{
|
||||
DBENTRY dbEntry;
|
||||
DBENTRY *pdbEntry = &dbEntry;
|
||||
DBENTRY dbEntry;
|
||||
DBENTRY *pdbEntry = &dbEntry;
|
||||
|
||||
dbInitEntry(pdbbase, pdbEntry);
|
||||
if (dbFindRecord(pdbEntry, name)) {
|
||||
epicsPrintf("Alias \"%s\" refers to unknown record \"%s\"\n",
|
||||
alias, name);
|
||||
yyerror(NULL);
|
||||
} else if (dbCreateAlias(pdbEntry, alias)) {
|
||||
}
|
||||
else if (dbCreateAlias(pdbEntry, alias)) {
|
||||
epicsPrintf("Can't create alias \"%s\" referring to \"%s\"\n",
|
||||
alias, name);
|
||||
yyerror(NULL);
|
||||
@@ -1039,14 +1047,14 @@ static void dbAlias(char *name, char *alias)
|
||||
|
||||
static void dbRecordBody(void)
|
||||
{
|
||||
DBENTRY *pdbentry;
|
||||
DBENTRY *pdbentry;
|
||||
|
||||
if(duplicate) {
|
||||
duplicate = FALSE;
|
||||
return;
|
||||
if (duplicate) {
|
||||
duplicate = FALSE;
|
||||
return;
|
||||
}
|
||||
pdbentry = (DBENTRY *)popFirstTemp();
|
||||
if(ellCount(&tempList))
|
||||
yyerrorAbort("dbRecordBody: tempList not empty");
|
||||
if (ellCount(&tempList))
|
||||
yyerrorAbort("dbRecordBody: tempList not empty");
|
||||
dbFreeEntry(pdbentry);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -269,7 +269,7 @@ static int generalTimeGetEventPriority(epicsTimeStamp *pDest, int eventNumber,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (epicsTimeGreaterThanEqual(pDest,
|
||||
if (epicsTimeGreaterThanEqual(&ts,
|
||||
>Pvt.eventTime[eventNumber])) {
|
||||
*pDest = ts;
|
||||
gtPvt.eventTime[eventNumber] = ts;
|
||||
@@ -279,7 +279,6 @@ static int generalTimeGetEventPriority(epicsTimeStamp *pDest, int eventNumber,
|
||||
key = epicsInterruptLock();
|
||||
gtPvt.ErrorCounts++;
|
||||
epicsInterruptUnlock(key);
|
||||
}
|
||||
|
||||
IFDEBUG(10) {
|
||||
char last[40], buff[40];
|
||||
@@ -291,6 +290,7 @@ static int generalTimeGetEventPriority(epicsTimeStamp *pDest, int eventNumber,
|
||||
" %s, using %s instead\n",
|
||||
ptp->name, buff, last);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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*/
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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*/
|
||||
|
||||
|
||||
@@ -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*/
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user