Compare commits
262 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b3f785964e | ||
|
|
bb4b23f658 | ||
|
|
8b31fba8cb | ||
|
|
8481ae3787 | ||
|
|
46535bde64 | ||
|
|
6ee928109c | ||
|
|
cff13b9aa7 | ||
|
|
58aa30ab0a | ||
|
|
5f46d6dcee | ||
|
|
d41355e0fc | ||
|
|
a5aa5459e3 | ||
|
|
6201d37756 | ||
|
|
67599e54e4 | ||
|
|
7bc0d6922b | ||
|
|
02d7304b3f | ||
|
|
7c90e6ed0b | ||
|
|
c5fd621337 | ||
|
|
ea409e79be | ||
|
|
6d5f57daf1 | ||
|
|
c59a18600a | ||
|
|
d8d14b11db | ||
|
|
68f6f361e1 | ||
|
|
84b7612036 | ||
|
|
f3cf1df503 | ||
|
|
9b385480d0 | ||
|
|
ec036cb26d | ||
|
|
64d9d1a4c9 | ||
|
|
e53244df1f | ||
|
|
fe3d68b5f7 | ||
|
|
49f5527cd7 | ||
|
|
ee90dffd40 | ||
|
|
6664ccfc64 | ||
|
|
444cac337c | ||
|
|
313afc4a4c | ||
|
|
0fae0fcc17 | ||
|
|
aab5693b45 | ||
|
|
6f919c3991 | ||
|
|
87761ebf29 | ||
|
|
10d951e2d7 | ||
|
|
d436561cb2 | ||
|
|
a43b805b65 | ||
|
|
0649a2f13f | ||
|
|
5e10b98a99 | ||
|
|
fc90d347d1 | ||
|
|
64a4c556b4 | ||
|
|
34115f83ba | ||
|
|
a38c1d07f5 | ||
|
|
9e999d2bef | ||
|
|
79690940b7 | ||
|
|
040f9013f4 | ||
|
|
0f16977caf | ||
|
|
694f045332 | ||
|
|
daad9b1ba1 | ||
|
|
937878e0a9 | ||
|
|
6e536e1ee0 | ||
|
|
383b6b1c36 | ||
|
|
bb19bd519e | ||
|
|
d70bfed75b | ||
|
|
3c2fe264cd | ||
|
|
716f102dd6 | ||
|
|
cae597d21c | ||
|
|
c23012d081 | ||
|
|
6ea6c6ff66 | ||
|
|
168d430921 | ||
|
|
9a8860b771 | ||
|
|
693c1020f2 | ||
|
|
63ddb2d4fc | ||
|
|
3d8e2d933d | ||
|
|
30268e3577 | ||
|
|
ebe7cf046e | ||
|
|
5f3f87a365 | ||
|
|
00d937cc02 | ||
|
|
072dbd53e7 | ||
|
|
560f43b561 | ||
|
|
301ded2dc1 | ||
|
|
d3927dea91 | ||
|
|
b80ce4883d | ||
|
|
924c1a21f9 | ||
|
|
6fb98c07b0 | ||
|
|
43322335df | ||
|
|
fcb5675040 | ||
|
|
3d88c8495b | ||
|
|
215c5d954b | ||
|
|
7bd55cb233 | ||
|
|
5f0b8eb064 | ||
|
|
f6391ee702 | ||
|
|
d129af29c2 | ||
|
|
36c2f78355 | ||
|
|
464e8a4f14 | ||
|
|
f0bbae1767 | ||
|
|
fbbd2369e9 | ||
|
|
78537fbb80 | ||
|
|
78b6312f49 | ||
|
|
59ec8d897d | ||
|
|
818e6c236d | ||
|
|
23d9176772 | ||
|
|
2efe56c6d1 | ||
|
|
94ebd0fe48 | ||
|
|
8a7442e878 | ||
|
|
31870b4c41 | ||
|
|
ae38fb2c1c | ||
|
|
a3ace1f260 | ||
|
|
728bb556cf | ||
|
|
b7afb287d5 | ||
|
|
275d36b09d | ||
|
|
a81c3503d2 | ||
|
|
03b8257d71 | ||
|
|
46370302f6 | ||
|
|
ab59c97f4b | ||
|
|
77bdea22f8 | ||
|
|
00ee7bf7d3 | ||
|
|
3c607d9034 | ||
|
|
06f522b253 | ||
|
|
c6476fbbdc | ||
|
|
b336545853 | ||
|
|
63994839d0 | ||
|
|
1564f87bd6 | ||
|
|
6eb88b16a0 | ||
|
|
27ee078bc8 | ||
|
|
a62c357e99 | ||
|
|
ea0556e471 | ||
|
|
c08b1ef5d1 | ||
|
|
5f68d62f40 | ||
|
|
891caa5933 | ||
|
|
b18478077a | ||
|
|
dd78ab0888 | ||
|
|
f1e55ef240 | ||
|
|
2c07e5fbb9 | ||
|
|
11ba48232c | ||
|
|
531ab6fc36 | ||
|
|
e7e9e66651 | ||
|
|
453ad41c48 | ||
|
|
eed208afaa | ||
|
|
ae63854dff | ||
|
|
ce7943fb44 | ||
|
|
4e865a03d8 | ||
|
|
9a4febd3bc | ||
|
|
dc5d373b57 | ||
|
|
47c361f135 | ||
|
|
6f29a00ead | ||
|
|
9943796f7f | ||
| 3cb72ec209 | |||
| 701ef5b936 | |||
| c3995a9d63 | |||
| ce3eadde34 | |||
|
|
62929fcbd1 | ||
|
|
456a68eb96 | ||
|
|
b319b4722f | ||
|
|
b4cc5fdf4b | ||
|
|
d35835659c | ||
| 65714033ea | |||
| 7151fbe498 | |||
|
|
cbb13bf6b1 | ||
|
|
150d764d28 | ||
|
|
7dd1ea4cab | ||
|
|
922ed30136 | ||
|
|
9f9f119e7e | ||
|
|
d8214a4531 | ||
|
|
120b100e7e | ||
|
|
949e9d788a | ||
|
|
27c6e6a385 | ||
|
|
4b59476170 | ||
|
|
526b565c6b | ||
|
|
1b7b2bcceb | ||
|
|
49c925d064 | ||
|
|
46b5d6006e | ||
|
|
6a2ed4b333 | ||
|
|
73b81ad139 | ||
|
|
7c00cc8045 | ||
|
|
b2bb14c654 | ||
|
|
ae5122759d | ||
|
|
d3bcf5737f | ||
|
|
6c5505ad3e | ||
|
|
4247d98b08 | ||
|
|
13735a8088 | ||
|
|
58d4242b68 | ||
|
|
8e42f516b0 | ||
|
|
9051cdbb34 | ||
|
|
8ffea9de27 | ||
|
|
2548a37267 | ||
|
|
592a83385d | ||
|
|
6e85a407da | ||
|
|
76a4a20698 | ||
|
|
7626856a20 | ||
|
|
1dc1b25aaa | ||
|
|
fb31dd784b | ||
|
|
fe7260e263 | ||
|
|
67e2b74758 | ||
|
|
c09b6e2f1b | ||
|
|
45be2306bd | ||
|
|
6027f906c3 | ||
|
|
ec351c5e2f | ||
| 89870e2817 | |||
| 4e9cf72d71 | |||
| 80869a0868 | |||
| 998fa984ba | |||
| 31844af88e | |||
| 8f161f9463 | |||
| e0399478ad | |||
|
|
2a2a1e54ac | ||
|
|
20d2cff501 | ||
|
|
860ce156a2 | ||
|
|
dc310a4238 | ||
| ab493264b2 | |||
| 68779943eb | |||
| 7a5ff26984 | |||
| eae59183cc | |||
|
|
b32629c3bf | ||
|
|
220e404203 | ||
|
|
83b17d5061 | ||
|
|
65dec97f9e | ||
|
|
dcb494b494 | ||
|
|
8f55a1307d | ||
|
|
c0a7ab976c | ||
|
|
b029448059 | ||
|
|
3b77d9be8c | ||
|
|
6e3aa77c42 | ||
|
|
2fb46fc541 | ||
|
|
36f23f3aec | ||
|
|
ffe6fceffa | ||
|
|
bcfdc8d368 | ||
|
|
c6c25ab43d | ||
|
|
5796f717ef | ||
|
|
89b9e240b0 | ||
|
|
8cdcaf5a87 | ||
|
|
f2ceb3bbbf | ||
|
|
fd30989f63 | ||
|
|
3b89515664 | ||
|
|
1893cb4f54 | ||
|
|
2b1d5ae4e3 | ||
|
|
1ca8535266 | ||
|
|
c0cbbd8bee | ||
|
|
fef15d6c91 | ||
|
|
805e62b29c | ||
|
|
d94c8d1e37 | ||
|
|
a4fcd2296a | ||
|
|
877d38e79a | ||
|
|
7cef334b64 | ||
|
|
b84ee89d87 | ||
|
|
c2c32e5876 | ||
|
|
ca2003bb63 | ||
|
|
97ea68d40c | ||
|
|
8f64af96fd | ||
|
|
54c47f02de | ||
|
|
d87ac0319b | ||
|
|
20404003bf | ||
|
|
1fa5d9d3b6 | ||
|
|
5e394e4928 | ||
|
|
c0d4835e66 | ||
|
|
8ae34ba01d | ||
|
|
98f656fc96 | ||
|
|
e8b4f448ea | ||
|
|
d5f74fe006 | ||
|
|
6923ca9fda | ||
|
|
aace975de1 | ||
|
|
c8b60e0f1b | ||
|
|
1255cdc9ee | ||
|
|
12da38a7ca | ||
|
|
f78e1f39d7 | ||
|
|
684fe10d8c | ||
|
|
15b97f65cb | ||
|
|
c1b0c1bac1 |
@@ -6,18 +6,9 @@ die() {
|
||||
exit 1
|
||||
}
|
||||
|
||||
ticker() {
|
||||
while true
|
||||
do
|
||||
sleep 60
|
||||
date -R
|
||||
[ -r "$1" ] && tail -n10 "$1"
|
||||
done
|
||||
}
|
||||
|
||||
CACHEKEY=1
|
||||
|
||||
EPICS_HOST_ARCH=`sh startup/EpicsHostArch`
|
||||
export EPICS_HOST_ARCH=`perl src/tools/EpicsHostArch.pl`
|
||||
|
||||
[ -e configure/os/CONFIG_SITE.Common.linux-x86 ] || die "Wrong location: $PWD"
|
||||
|
||||
@@ -57,28 +48,24 @@ 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
|
||||
curl -L "https://github.com/mdavidsaver/rsb/releases/download/20171203-${RTEMS}/i386-rtems${RTEMS}-trusty-20171203-${RTEMS}.tar.bz2" \
|
||||
| tar -C / -xmj
|
||||
|
||||
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
|
||||
RTEMS_BASE=$HOME/.rtems
|
||||
EOF
|
||||
cat << EOF >> configure/CONFIG_SITE
|
||||
CROSS_COMPILER_TARGET_ARCHS+=RTEMS-pc386
|
||||
CROSS_COMPILER_TARGET_ARCHS += RTEMS-pc386-qemu
|
||||
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
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
#!/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"
|
||||
|
||||
cat <<EOF >> configure/CONFIG_SITE
|
||||
USR_CPPFLAGS += $USR_CPPFLAGS
|
||||
USR_CFLAGS += $USR_CFLAGS
|
||||
USR_CXXFLAGS += $USR_CXXFLAGS
|
||||
EOF
|
||||
30
.travis.yml
30
.travis.yml
@@ -11,23 +11,17 @@ addons:
|
||||
- perl
|
||||
- clang
|
||||
- g++-mingw-w64-i686
|
||||
- bison
|
||||
- flex
|
||||
- texinfo
|
||||
- install-info
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.cache
|
||||
install:
|
||||
- ./.ci/travis-prepare.sh
|
||||
- qemu-system-x86
|
||||
script:
|
||||
- ./.ci/travis-build.sh
|
||||
- .ci/travis-build.sh
|
||||
env:
|
||||
- BRCORE=master BRLIBCOM=master BRCA=master
|
||||
- CMPLR=clang
|
||||
- USR_CXXFLAGS=-std=c++11
|
||||
- CMPLR=clang USR_CXXFLAGS=-std=c++11
|
||||
- WINE=32 TEST=NO STATIC=YES
|
||||
- WINE=32 TEST=NO STATIC=NO
|
||||
- RTEMS=4.10 TEST=NO
|
||||
- RTEMS=4.9 TEST=NO
|
||||
- CMPLR=gcc
|
||||
- CMPLR=clang
|
||||
- CMPLR=gcc STATIC=YES
|
||||
- CMPLR=clang STATIC=YES
|
||||
- CMPLR=gcc EXTRA=CMD_CXXFLAGS=-std=c++11
|
||||
- CMPLR=clang EXTRA=CMD_CXXFLAGS=-std=c++11
|
||||
- WINE=32 TEST=NO STATIC=YES
|
||||
- WINE=32 TEST=NO STATIC=NO
|
||||
- RTEMS=4.10 TEST=YES
|
||||
- RTEMS=4.9 TEST=YES
|
||||
|
||||
@@ -20,11 +20,14 @@ else
|
||||
endif
|
||||
|
||||
# Provide a default if the user hasn't set EPICS_HOST_ARCH
|
||||
ifeq ($(strip $(EPICS_HOST_ARCH)),)
|
||||
# NB: We must set the environment variable for submodules to include
|
||||
# the correct modules/RELEASE.<host>.local file to set EPICS_BASE,
|
||||
# they can't do this for themselves since CONFIG is relative to it:
|
||||
export EPICS_HOST_ARCH := $(shell $(CONFIG)/../startup/EpicsHostArch.pl)
|
||||
#
|
||||
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)/RELEASE
|
||||
|
||||
@@ -24,9 +24,14 @@ LD = $(GNU_BIN)/$(CMPLR_PREFIX)ld$(CMPLR_SUFFIX) -r
|
||||
CPP = $(CC) -x c -E
|
||||
RANLIB = $(GNU_BIN)/$(CMPLR_PREFIX)ranlib$(CMPLR_SUFFIX)
|
||||
|
||||
# Requires at least GCC 4.8 or LLVM (clang) 3.1
|
||||
ASAN_FLAGS_YES = -fsanitize=address
|
||||
ASAN_LDFLAGS_YES = $(ASAN_FLAGS_YES)
|
||||
|
||||
PROF_CFLAGS_YES = -p
|
||||
GPROF_CFLAGS_YES = -pg
|
||||
CODE_CFLAGS = $(PROF_CFLAGS_$(PROFILE)) $(GPROF_CFLAGS_$(GPROF))
|
||||
CODE_CFLAGS += $(ASAN_FLAGS_$(ENABLE_ASAN))
|
||||
WARN_CFLAGS_YES = -Wall
|
||||
WARN_CFLAGS_NO = -w
|
||||
OPT_CFLAGS_YES = -O3
|
||||
@@ -35,12 +40,14 @@ OPT_CFLAGS_NO = -g
|
||||
PROF_CXXFLAGS_YES = -p
|
||||
GPROF_CXXFLAGS_YES = -pg
|
||||
CODE_CXXFLAGS = $(PROF_CXXFLAGS_$(PROFILE)) $(GPROF_CXXFLAGS_$(GPROF))
|
||||
CODE_CXXFLAGS += $(ASAN_FLAGS_$(ENABLE_ASAN))
|
||||
WARN_CXXFLAGS_YES = -Wall
|
||||
WARN_CXXFLAGS_NO = -w
|
||||
OPT_CXXFLAGS_YES = -O3
|
||||
OPT_CXXFLAGS_NO = -g
|
||||
|
||||
CODE_LDFLAGS = $(PROF_CXXFLAGS_$(PROFILE)) $(GPROF_CXXFLAGS_$(GPROF))
|
||||
CODE_LDFLAGS += $(ASAN_LDFLAGS_$(ENABLE_ASAN))
|
||||
|
||||
PIPE_CFLAGS_YES_YES = -pipe
|
||||
PIPE_CFLAGS = $(PIPE_CFLAGS_$(GCC_PIPE)_$(GNU))
|
||||
|
||||
@@ -42,7 +42,7 @@ PODTOHTML = $(PERL) $(TOOLS)/podToHtml.pl
|
||||
CONVERTRELEASE = $(PERL) $(call FIND_TOOL,convertRelease.pl)
|
||||
FULLPATHNAME = $(PERL) $(TOOLS)/fullPathName.pl
|
||||
TAPTOJUNIT = $(PERL) $(TOOLS)/tap-to-junit-xml.pl
|
||||
GENVERSIONHEADER = $(PERL) $(TOOLS)/genVersionHeader.pl $(QUIET_FLAG)
|
||||
GENVERSIONHEADER = $(PERL) $(TOOLS)/genVersionHeader.pl $(QUIET_FLAG) $(QUESTION_FLAG)
|
||||
|
||||
#---------------------------------------------------------------
|
||||
# tools for installing libraries and products
|
||||
|
||||
@@ -15,17 +15,26 @@
|
||||
# EPICS_SITE_VERSION is defined in CONFIG_SITE for sites that want a local
|
||||
# version number to be included in the reported version string.
|
||||
|
||||
# We define BASE_3_14 and BASE_3_15 as NO and BASE_3_16 as YES, so
|
||||
# We define convenience macros for our release series to be NO or YES, so
|
||||
# Makefiles can detect 'Series X or later', or 'Series X only' like this:
|
||||
#
|
||||
# ifdef BASE_3_14
|
||||
# true for 3.14 or later
|
||||
# ifdef BASE_3_15
|
||||
# true for 3.15 or later
|
||||
# ifdef BASE_3_16
|
||||
# true for 3.16 or later
|
||||
# ifdef BASE_7_0
|
||||
# true for 7.0 or later
|
||||
#
|
||||
# ifeq ($(BASE_3_14),YES)
|
||||
# true for 3.14.x only
|
||||
# ifeq ($(BASE_3_15),YES)
|
||||
# true for 3.15 only
|
||||
# true for 3.15.x only
|
||||
# ifeq ($(BASE_3_16),YES)
|
||||
# true for 3.16 only.
|
||||
# true for 3.16.x only.
|
||||
# ifeq ($(BASE_7_0),YES)
|
||||
# true for 7.0.x only.
|
||||
|
||||
BASE_3_14 = NO
|
||||
BASE_3_15 = NO
|
||||
@@ -39,14 +48,14 @@ EPICS_VERSION = 7
|
||||
EPICS_REVISION = 0
|
||||
|
||||
# EPICS_MODIFICATION must be a number >=0 and <256
|
||||
EPICS_MODIFICATION = 1
|
||||
EPICS_MODIFICATION = 2
|
||||
|
||||
# EPICS_PATCH_LEVEL must be a number (win32 resource file requirement)
|
||||
# Not included if zero
|
||||
EPICS_PATCH_LEVEL = 2
|
||||
EPICS_PATCH_LEVEL = 0
|
||||
|
||||
# This will end in -DEV between official releases
|
||||
EPICS_DEV_SNAPSHOT=-DEV
|
||||
#EPICS_DEV_SNAPSHOT=-DEV
|
||||
#EPICS_DEV_SNAPSHOT=-pre1
|
||||
#EPICS_DEV_SNAPSHOT=-pre1-DEV
|
||||
#EPICS_DEV_SNAPSHOT=-pre2
|
||||
@@ -55,7 +64,7 @@ EPICS_DEV_SNAPSHOT=-DEV
|
||||
#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
|
||||
|
||||
|
||||
@@ -76,10 +76,14 @@ COMMON_DIR = ../O.Common
|
||||
IOCS_APPL_TOP = $(shell $(FULLPATHNAME) $(INSTALL_LOCATION))
|
||||
|
||||
#-------------------------------------------------------
|
||||
# Make echo output - suppress echoing if make's '-s' flag is set
|
||||
# Silencing the build - suppress messages during 'make -s'
|
||||
NOP = :
|
||||
ECHO = @$(if $(findstring s,$(patsubst T_A=%,,$(MAKEFLAGS))),$(NOP),echo)
|
||||
QUIET_FLAG := $(if $(findstring s,$(MAKEFLAGS)),-q,)
|
||||
ECHO = @$(if $(findstring s,$(MFLAGS)),$(NOP),echo)
|
||||
QUIET_FLAG := $(if $(findstring s,$(MFLAGS)),-q,)
|
||||
|
||||
#-------------------------------------------------------
|
||||
# Convert 'make -q' flag into '-i' for genVersionHeader.pl
|
||||
QUESTION_FLAG := $(if $(findstring q,$(MFLAGS)),-i,)
|
||||
|
||||
#-------------------------------------------------------
|
||||
ifdef T_A
|
||||
@@ -89,7 +93,7 @@ INSTALL_SHRLIB = $(INSTALL_LOCATION_LIB)/$(T_A)
|
||||
INSTALL_TCLLIB = $(INSTALL_LOCATION_LIB)/$(T_A)
|
||||
INSTALL_BIN = $(INSTALL_LOCATION_BIN)/$(T_A)
|
||||
|
||||
#Directories for libraries
|
||||
# Directories for libraries
|
||||
SHRLIB_SEARCH_DIRS = $(INSTALL_LIB)
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
# Copyright (c) 2006 UChicago Argonne LLC, 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 the file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
|
||||
ifndef T_A
|
||||
|
||||
@@ -4,9 +4,10 @@
|
||||
# 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 the file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
#RULES.Db
|
||||
|
||||
# RULES.Db
|
||||
|
||||
# Set db substitutions and template file suffixes
|
||||
SUBST_SUFFIX ?= .substitutions
|
||||
|
||||
@@ -4,9 +4,10 @@
|
||||
# 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 the file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
#RULES.ioc
|
||||
|
||||
# RULES.ioc
|
||||
|
||||
include $(CONFIG)/RULES_DIRS
|
||||
|
||||
|
||||
@@ -90,6 +90,4 @@ realclean:
|
||||
.PHONY : $(BUILD_ARCHS) rebuild archsCommonClean
|
||||
.PHONY : $(ACTIONS) clean realclean archclean host all
|
||||
|
||||
# User specific rules
|
||||
#
|
||||
-include $(HOME)/configure/RULES_USER
|
||||
include $(CONFIG)/RULES_COMMON
|
||||
|
||||
@@ -6,11 +6,12 @@
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in the file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
|
||||
# RULES_BUILD
|
||||
|
||||
# Rules for making things specified in a Makefile
|
||||
#
|
||||
# Rules for making things specified in Makefile
|
||||
#
|
||||
# we are in O.$(T_A), but most sources are elsewhere
|
||||
#
|
||||
# CWD is O.$(T_A), but most sources are elsewhere
|
||||
|
||||
ifndef BASE_RULES_BUILD
|
||||
BASE_RULES_BUILD=1
|
||||
@@ -42,6 +43,7 @@ LOADABLE_LIBRARY += $(LOADABLE_LIBRARY_HOST)
|
||||
OBJS += $(OBJS_HOST)
|
||||
PROD += $(PROD_HOST)
|
||||
SCRIPTS += $(SCRIPTS_HOST)
|
||||
TARGETS += $(TARGETS_HOST)
|
||||
TESTLIBRARY += $(TESTLIBRARY_HOST)
|
||||
TESTSCRIPTS += $(TESTSCRIPTS_HOST)
|
||||
TESTPROD += $(TESTPROD_HOST)
|
||||
@@ -53,6 +55,7 @@ LOADABLE_LIBRARY += $(LOADABLE_LIBRARY_IOC)
|
||||
OBJS += $(OBJS_IOC)
|
||||
PROD += $(PROD_IOC)
|
||||
SCRIPTS += $(SCRIPTS_IOC)
|
||||
TARGETS += $(TARGETS_IOC)
|
||||
TESTLIBRARY += $(TESTLIBRARY_IOC)
|
||||
TESTSCRIPTS += $(TESTSCRIPTS_IOC)
|
||||
TESTPROD += $(TESTPROD_IOC)
|
||||
@@ -79,9 +82,9 @@ else
|
||||
host:
|
||||
endif
|
||||
|
||||
-include $(CONFIG)/RULES_FILE_TYPE
|
||||
include $(CONFIG)/RULES_FILE_TYPE
|
||||
|
||||
-include $(CONFIG)/RULES.Db
|
||||
include $(CONFIG)/RULES.Db
|
||||
|
||||
#---------------------------------------------------------------
|
||||
# Include defines and rules for prod, library and test* targets
|
||||
@@ -185,7 +188,7 @@ endif
|
||||
|
||||
# RELEASE file consistency checking
|
||||
checkRelease:
|
||||
$(CONVERTRELEASE) checkRelease
|
||||
+$(CONVERTRELEASE) checkRelease
|
||||
warnRelease:
|
||||
-$(CONVERTRELEASE) checkRelease
|
||||
noCheckRelease:
|
||||
@@ -256,15 +259,13 @@ YACCOPT ?= $($*_YACCOPT)
|
||||
$(MV) $*.tab.c $*.c
|
||||
$(if $(findstring -d, $(YACCOPT)),$(MV) $*.tab.h $*.h,)
|
||||
|
||||
# must be a seperate rule since when not using '-d' the
|
||||
# must be a separate rule since when not using '-d' the
|
||||
# prefix for .h will be different then .c
|
||||
%.h : %.c %.y
|
||||
|
||||
%.c: %.l
|
||||
@$(RM) $*.yy.c
|
||||
$(LEX) $(LEXOPT) -t $< > $*.yy.c
|
||||
@$(RM) $@
|
||||
$(MV) $*.yy.c $@
|
||||
$(LEX) $(LEXOPT) -o$@ $<
|
||||
|
||||
#---------------------------------------------------------------
|
||||
# Libraries, shared/DLL and stubs
|
||||
@@ -361,14 +362,17 @@ ifneq ($(TAPFILES),)
|
||||
ifdef RUNTESTS_ENABLED
|
||||
prove --failures --ext .tap --exec "$(CAT)" --color $(TAPFILES)
|
||||
endif
|
||||
|
||||
CURRENT_TAPFILES := $(wildcard $(TAPFILES))
|
||||
CURRENT_JUNITFILES := $(wildcard $(JUNITFILES))
|
||||
endif
|
||||
|
||||
clean-tests:
|
||||
ifneq ($(TAPFILES),)
|
||||
$(RM) $(TAPFILES)
|
||||
ifneq ($(CURRENT_TAPFILES),)
|
||||
$(RM) $(CURRENT_TAPFILES)
|
||||
endif
|
||||
ifneq ($(JUNITFILES),)
|
||||
$(RM) $(JUNITFILES)
|
||||
ifneq ($(CURRENT_JUNITFILES),)
|
||||
$(RM) $(CURRENT_JUNITFILES)
|
||||
endif
|
||||
|
||||
tapfiles: $(TESTSCRIPTS) $(TAPFILES)
|
||||
@@ -392,7 +396,7 @@ endif
|
||||
# Generate a perl program to exec the real test binary.
|
||||
%.t: %$(EXE) $(TOOLS)/makeTestfile.pl
|
||||
@$(RM) $@
|
||||
$(PERL) $(TOOLS)/makeTestfile.pl $@ $<
|
||||
$(PERL) $(TOOLS)/makeTestfile.pl $(T_A) $(EPICS_HOST_ARCH) $@ $<
|
||||
|
||||
#---------------------------------------------------------------
|
||||
# Generate header with version number from VCS
|
||||
@@ -531,7 +535,7 @@ $(INSTALL_TEMPLATES_SUBDIR)/%: %
|
||||
$(ECHO) "Installing $@"
|
||||
@$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D)
|
||||
|
||||
-include $(CONFIG)/RULES_EXPAND
|
||||
include $(CONFIG)/RULES_EXPAND
|
||||
|
||||
.PRECIOUS: %.i %.o %.c %.nm %.cpp %.cc
|
||||
.PRECIOUS: $(COMMON_INC)
|
||||
@@ -540,5 +544,9 @@ $(INSTALL_TEMPLATES_SUBDIR)/%: %
|
||||
.PHONY: runtests tapfiles clean-tests test-results junitfiles
|
||||
.PHONY: checkRelease warnRelease noCheckRelease FORCE
|
||||
|
||||
include $(CONFIG)/RULES_COMMON
|
||||
|
||||
else
|
||||
$(warning RULES_BUILD included more than once. \
|
||||
Use 'make show-makefiles' to work out why.)
|
||||
endif # BASE_RULES_BUILD
|
||||
# EOF RULES_BUILD
|
||||
|
||||
35
configure/RULES_COMMON
Normal file
35
configure/RULES_COMMON
Normal file
@@ -0,0 +1,35 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2018 UChicago Argonne LLC, as Operator of Argonne
|
||||
# National Laboratory.
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in the file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
|
||||
# These rules show the set of Makefiles, config files and
|
||||
# rules files loaded by GNUmake.
|
||||
|
||||
# Protect against filenames containing colons (Windows)
|
||||
SAFE_MAKEFILES = $(subst :,__colon__,$(MAKEFILE_LIST))
|
||||
SHOW_MAKEFILES = $(SAFE_MAKEFILES:%=show-makefile.%)
|
||||
show-makefiles: $(SHOW_MAKEFILES)
|
||||
|
||||
# The sort prevents warnings about duplicate targets:
|
||||
$(sort $(SHOW_MAKEFILES)): show-makefile.%:
|
||||
@echo " $(subst __colon__,:,$(@:show-makefile.%=%))"
|
||||
|
||||
.PHONY: show-makefiles show-makefile.%
|
||||
|
||||
# These rules support printing a Makefile variable values.
|
||||
# Many variables are only set inside an O.<arch> build directory.
|
||||
# make PRINT.T_A
|
||||
|
||||
PRINT_Var = $(@:PRINT.%=%)
|
||||
PRINT.%:
|
||||
@echo $(PRINT_Var) = '$($(PRINT_Var))'
|
||||
|
||||
.PHONY: PRINT PRINT.%
|
||||
|
||||
|
||||
# User specific rules
|
||||
#
|
||||
-include $(HOME)/configure/RULES_USER
|
||||
@@ -92,7 +92,4 @@ $(ARCHS) $(ACTIONS) $(actionArchTargets) :%: \
|
||||
.PHONY : $(dirActionArchTargets)
|
||||
.PHONY : $(actionArchTargets)
|
||||
|
||||
|
||||
# User specific rules
|
||||
#
|
||||
-include $(HOME)/configure/RULES_USER
|
||||
include $(CONFIG)/RULES_COMMON
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
# <top>/configure/RULES_EXPAND
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2011 UChicago Argonne LLC, 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 is distributed subject to a Software License Agreement found
|
||||
# in the file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
|
||||
# RULES_EXPAND
|
||||
|
||||
vpath %@ $(USR_VPATH) $(ALL_SRC_DIRS)
|
||||
|
||||
|
||||
@@ -7,9 +7,11 @@
|
||||
# in the file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
|
||||
# Include <top>/configure/RULES_BUILD from tops defined in RELEASE* files
|
||||
# Include <top>/configure/RULES_BUILD from tops defined in RELEASE* files,
|
||||
# excluding EPICS_BASE
|
||||
#
|
||||
RELEASE_RULES_BUILDS = $(foreach top, $(RELEASE_TOPS), \
|
||||
RELEASE_RULES_BUILDS = $(foreach top, \
|
||||
$(filter-out EPICS_BASE, $(RELEASE_TOPS)), \
|
||||
$(wildcard $($(top))/configure/RULES_BUILD))
|
||||
ifneq ($(RELEASE_RULES_BUILDS),)
|
||||
include $(RELEASE_RULES_BUILDS)
|
||||
@@ -23,7 +25,7 @@ ifneq ($(RELEASE_CFG_RULES),)
|
||||
include $(RELEASE_CFG_RULES)
|
||||
endif
|
||||
|
||||
# If this is not BASE then include <TOP>/configure/RULES_BUILD
|
||||
# If this is not BASE then include <top>/configure/RULES_BUILD
|
||||
#
|
||||
ifeq ($(wildcard $(TOP)/configure/CONFIG_BASE_VERSION),)
|
||||
TOP_RULES_BUILDS = $(wildcard $(TOP)/configure/RULES_BUILD)
|
||||
@@ -67,7 +69,3 @@ file_type_clean:
|
||||
@$(RM) $(foreach type, $(FILE_TYPE), $($(type)))
|
||||
|
||||
.PHONY : file_type_clean
|
||||
|
||||
# User specific rules
|
||||
#
|
||||
-include $(HOME)/configure/RULES_USER
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
# Copyright (c) 2006 UChicago Argonne LLC, 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 the file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
|
||||
# Octave definitions and rules
|
||||
|
||||
@@ -1,18 +1,13 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
# Copyright (c) 2011 UChicago Argonne LLC, 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 the file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
#
|
||||
# RULES_TARGET
|
||||
#
|
||||
# This file is to be maintained by the community.
|
||||
#
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
# RULES_TARGET
|
||||
|
||||
define TARGET_template
|
||||
$(1)_$(2) += $$(if $$(strip $$($(1)_$(2)_$$(OS_CLASS))), \
|
||||
|
||||
@@ -15,6 +15,10 @@ CVSCLEAN = $(call FIND_TOOL,cvsclean.pl)
|
||||
cvsclean:
|
||||
$(PERL) $(CVSCLEAN)
|
||||
|
||||
DEPCLEAN = $(call FIND_TOOL,depclean.pl)
|
||||
depclean:
|
||||
$(PERL) $(DEPCLEAN)
|
||||
|
||||
realuninstall: uninstallDirs
|
||||
$(RMDIR) $(INSTALL_LOCATION_BIN)
|
||||
$(RMDIR) $(INSTALL_LOCATION_LIB)
|
||||
@@ -73,12 +77,14 @@ help:
|
||||
@echo " uninstall - Remove install directories created by this hostarch."
|
||||
@echo " realuninstall - Removes ALL install dirs"
|
||||
@echo " distclean - Same as realclean cvsclean realuninstall."
|
||||
@echo " depclean - Removes all .d files from O.<arch> directories."
|
||||
@echo " cvsclean - Removes cvs .#* files in all dirs of directory tree"
|
||||
@echo " help - Prints this list of valid make targets "
|
||||
@echo "Indiv. object targets are supported by O.<arch> level Makefile .e.g"
|
||||
@echo " xxxRecord.o"
|
||||
|
||||
.PHONY: cleandirs distclean cvsclean realuninstall archuninstall uninstallDirs
|
||||
.PHONY: cleandirs distclean cvsclean depclean
|
||||
.PHONY: realuninstall archuninstall uninstallDirs
|
||||
.PHONY: uninstall help
|
||||
|
||||
# Include <top>/cfg/TOP_RULES* files from tops defined in RELEASE* files
|
||||
|
||||
@@ -27,9 +27,13 @@ ifneq ($(CONFIG),$(TOP)/configure)
|
||||
-include $(TOP)/configure/CONFIG_SITE.Common.RTEMS
|
||||
endif
|
||||
|
||||
#--------------------------------------------------
|
||||
# Set RTEMS_BSP from T_A if not already done
|
||||
RTEMS_BSP ?= $(subst RTEMS-,,$(T_A))
|
||||
|
||||
#-------------------------------------------------------
|
||||
# Pick up the RTEMS tool/path definitions from the RTEMS BSP directory.
|
||||
include $(RTEMS_BASE)/$(RTEMS_TARGET_CPU)-rtems$(RTEMS_VERSION)/$(subst RTEMS-,,$(T_A))/Makefile.inc
|
||||
include $(RTEMS_BASE)/$(RTEMS_TARGET_CPU)-rtems$(RTEMS_VERSION)/$(RTEMS_BSP)/Makefile.inc
|
||||
include $(RTEMS_CUSTOM)
|
||||
include $(CONFIG.CC)
|
||||
|
||||
@@ -72,7 +76,7 @@ CPPFLAGS += $($(BUILD_CLASS)_CPPFLAGS) $(POSIX_CPPFLAGS) $(OPT_CPPFLAGS)\
|
||||
$(USR_CPPFLAGS) $(CMD_CPPFLAGS) $(ARCH_DEP_CPPFLAGS) $(OP_SYS_CPPFLAGS)\
|
||||
$(OP_SYS_INCLUDE_CPPFLAGS) $(CODE_CPPFLAGS)
|
||||
|
||||
ECHO = @$(if $(findstring s,$(patsubst T_A=%,,$(MAKEFLAGS))),$(NOP),echo)
|
||||
ECHO = @$(if $(findstring s,$(MFLAGS)),$(NOP),echo)
|
||||
|
||||
#--------------------------------------------------
|
||||
# Although RTEMS uses gcc, it wants to use gcc its own way
|
||||
|
||||
@@ -9,5 +9,6 @@
|
||||
#
|
||||
# All RTEMS targets use the same Makefile fragment
|
||||
#
|
||||
RTEMS_TARGET_CPU=arm
|
||||
RTEMS_BSP = at91rm9200ek
|
||||
RTEMS_TARGET_CPU = arm
|
||||
include $(CONFIG)/os/CONFIG.Common.RTEMS
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
# All RTEMS targets use the same Makefile fragment
|
||||
#
|
||||
EXE = .elf
|
||||
RTEMS_BSP = beatnik
|
||||
RTEMS_TARGET_CPU = powerpc
|
||||
GNU_TARGET = powerpc-rtems
|
||||
ARCH_DEP_CFLAGS += -DMY_DO_BOOTP=NULL
|
||||
|
||||
@@ -5,5 +5,6 @@
|
||||
#
|
||||
# All RTEMS targets use the same Makefile fragment
|
||||
#
|
||||
RTEMS_TARGET_CPU=m68k
|
||||
RTEMS_BSP = gen68360
|
||||
RTEMS_TARGET_CPU = m68k
|
||||
include $(CONFIG)/os/CONFIG.Common.RTEMS
|
||||
|
||||
@@ -5,5 +5,6 @@
|
||||
#
|
||||
# All RTEMS targets use the same Makefile fragment
|
||||
#
|
||||
RTEMS_TARGET_CPU=ppc
|
||||
RTEMS_BSP = mcp750
|
||||
RTEMS_TARGET_CPU = ppc
|
||||
include $(CONFIG)/os/CONFIG.Common.RTEMS
|
||||
|
||||
@@ -5,5 +5,6 @@
|
||||
#
|
||||
# All RTEMS targets use the same Makefile fragment
|
||||
#
|
||||
RTEMS_TARGET_CPU=m68k
|
||||
RTEMS_BSP = mvme167
|
||||
RTEMS_TARGET_CPU = m68k
|
||||
include $(CONFIG)/os/CONFIG.Common.RTEMS
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
# All RTEMS targets use the same Makefile fragment
|
||||
#
|
||||
EXE = .elf
|
||||
RTEMS_BSP = mvme2100
|
||||
RTEMS_TARGET_CPU = powerpc
|
||||
GNU_TARGET = powerpc-rtems
|
||||
ARCH_DEP_CFLAGS += -DMY_DO_BOOTP=NULL
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#
|
||||
# Author: Matt Rippa
|
||||
#
|
||||
RTEMS_BSP = mvme2700
|
||||
RTEMS_TARGET_CPU = powerpc
|
||||
ARCH_DEP_CFLAGS += -DMY_DO_BOOTP=NULL
|
||||
ARCH_DEP_CFLAGS += -DHAVE_PPCBUG
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
# All RTEMS targets use the same Makefile fragment
|
||||
#
|
||||
EXE = .elf
|
||||
RTEMS_BSP = mvme3100
|
||||
RTEMS_TARGET_CPU = powerpc
|
||||
GNU_TARGET = powerpc-rtems
|
||||
ARCH_DEP_CFLAGS += -DMY_DO_BOOTP=NULL
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
# All RTEMS targets use the same Makefile fragment
|
||||
#
|
||||
EXE = .elf
|
||||
RTEMS_BSP = mvme5500
|
||||
RTEMS_TARGET_CPU = powerpc
|
||||
GNU_TARGET = powerpc-rtems
|
||||
ARCH_DEP_CFLAGS += -DMY_DO_BOOTP=NULL
|
||||
|
||||
@@ -5,14 +5,15 @@
|
||||
#
|
||||
# All RTEMS targets use the same Makefile fragment
|
||||
#
|
||||
RTEMS_TARGET_CPU=i386
|
||||
RTEMS_BSP = pc386
|
||||
RTEMS_TARGET_CPU = i386
|
||||
|
||||
MUNCH_SUFFIX = .boot
|
||||
define MUNCH_CMD
|
||||
$(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary -R .comment -S $< temp.bin
|
||||
$(RM) $*.bin
|
||||
$(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary -R .comment -S $< $*.bin
|
||||
$(BIN2BOOT) $@ 0x00097E00 \
|
||||
$(PROJECT_RELEASE)/lib/start16.bin 0x00097C00 0 temp.bin 0x00100000 0
|
||||
rm -f temp.bin
|
||||
$(PROJECT_RELEASE)/lib/start16.bin 0x00097C00 0 $*.bin 0x00100000 0
|
||||
endef
|
||||
|
||||
include $(CONFIG)/os/CONFIG.Common.RTEMS
|
||||
|
||||
11
configure/os/CONFIG.Common.RTEMS-pc386-qemu
Normal file
11
configure/os/CONFIG.Common.RTEMS-pc386-qemu
Normal file
@@ -0,0 +1,11 @@
|
||||
# CONFIG.Common.RTEMS-pc386-qemu
|
||||
#
|
||||
# Definitions for the RTEMS-pc386-qemu target
|
||||
# Site-specific overrides go in CONFIG_SITE.Common.RTEMS-pc386-qemu
|
||||
#
|
||||
#-------------------------------------------------------
|
||||
|
||||
# Include definitions from RTEMS-pc386
|
||||
include $(CONFIG)/os/CONFIG.Common.RTEMS-pc386
|
||||
|
||||
RTEMS_QEMU_FIXUPS = YES
|
||||
@@ -5,5 +5,6 @@
|
||||
#
|
||||
# All RTEMS targets use the same Makefile fragment
|
||||
#
|
||||
RTEMS_TARGET_CPU=ppc
|
||||
RTEMS_BSP = psim
|
||||
RTEMS_TARGET_CPU = ppc
|
||||
include $(CONFIG)/os/CONFIG.Common.RTEMS
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#
|
||||
# All RTEMS targets use the same Makefile fragment
|
||||
#
|
||||
RTEMS_BSP = uC5282
|
||||
RTEMS_TARGET_CPU = m68k
|
||||
ARCH_DEP_CFLAGS += -DMY_DO_BOOTP=NULL
|
||||
|
||||
|
||||
@@ -146,8 +146,10 @@ SHRLIB_CFLAGS =
|
||||
SHRLIB_LDFLAGS =
|
||||
|
||||
#--------------------------------------------------
|
||||
# Earlier versions of gcc don't understand -MF
|
||||
HDEPENDS_COMPFLAGS = -MM > $@
|
||||
# Don't use gcc 2.x for dependency generation
|
||||
|
||||
HDEPENDS_METHOD_2 = MKMF
|
||||
HDEPENDS_METHOD = $(firstword $(HDEPENDS_METHOD_$(VX_GNU_MAJOR_VERSION)) COMP)
|
||||
|
||||
#--------------------------------------------------
|
||||
# osithead use default stack, YES or NO override
|
||||
|
||||
@@ -65,14 +65,14 @@ GNU = NO
|
||||
#
|
||||
# Darwin shared libraries
|
||||
#
|
||||
SHRLIB_LDFLAGS = -dynamiclib -flat_namespace -undefined suppress \
|
||||
SHRLIB_LDFLAGS = -dynamiclib -undefined dynamic_lookup \
|
||||
-install_name $(shell $(FULLPATHNAME) $(INSTALL_LIB))/$@ \
|
||||
$(addprefix -compatibility_version , $(SHRLIB_VERSION)) \
|
||||
$(addprefix -current_version , $(SHRLIB_VERSION))
|
||||
SHRLIB_SUFFIX_BASE = .dylib
|
||||
SHRLIB_SUFFIX = $(addprefix ., $(SHRLIB_VERSION))$(SHRLIB_SUFFIX_BASE)
|
||||
|
||||
LOADABLE_SHRLIB_LDFLAGS = -bundle -flat_namespace -undefined suppress
|
||||
LOADABLE_SHRLIB_LDFLAGS = -bundle -undefined dynamic_lookup
|
||||
|
||||
#
|
||||
# Position-independent code is the default on Darwin.
|
||||
|
||||
@@ -26,3 +26,5 @@ endif
|
||||
# Needed to find dlls for base installed build tools (antelope,eflex,...)
|
||||
PATH := $(EPICS_BASE_BIN):$(PATH)
|
||||
|
||||
# Silence the tr1 namespace deprecation warnings
|
||||
USR_CXXFLAGS_WIN32 += -D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
#
|
||||
# Site-specific overrides for RTEMS-pc386 target
|
||||
#
|
||||
9
configure/os/CONFIG_SITE.Common.RTEMS-pc386-qemu
Normal file
9
configure/os/CONFIG_SITE.Common.RTEMS-pc386-qemu
Normal file
@@ -0,0 +1,9 @@
|
||||
# CONFIG_SITE.Common.RTEMS-pc386-qemu
|
||||
#
|
||||
# Site-specific overrides for the RTEMS-pc386-qemu target
|
||||
#
|
||||
|
||||
# If you're building this architecture you _probably_ want to
|
||||
# run the tests for it under QEMU, but if not you can turn
|
||||
# them off here by commenting out this line:
|
||||
CROSS_COMPILER_RUNTEST_ARCHS += RTEMS-pc386-qemu
|
||||
@@ -54,3 +54,7 @@ OPT_CXXFLAGS_YES += -g
|
||||
# Tune GNU compiler output for a specific 32-bit cpu-type
|
||||
# (e.g. generic, native, i386, i686, pentium2/3/4, prescott, k6, athlon etc.)
|
||||
GNU_TUNE_CFLAGS = -mtune=generic
|
||||
|
||||
|
||||
# Developers using a suitable compiler may enable its address sanitizer:
|
||||
#ENABLE_ASAN = YES
|
||||
|
||||
@@ -50,3 +50,7 @@ OPT_CXXFLAGS_YES += -g
|
||||
# Tune GNU compiler output for a specific 64-bit cpu-type
|
||||
# (e.g. generic, native, core2, nocona, k8, opteron, athlon64, barcelona etc.)
|
||||
GNU_TUNE_CFLAGS = -mtune=generic
|
||||
|
||||
|
||||
# Developers using a suitable compiler may enable its address sanitizer:
|
||||
#ENABLE_ASAN = YES
|
||||
|
||||
@@ -4,17 +4,17 @@
|
||||
<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 EPICS 7.0.1</title>
|
||||
<title>Known Problems in EPICS 7.0.2</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1 style="text-align: center">EPICS 7.0.1: Known Problems</h1>
|
||||
<h1 style="text-align: center">EPICS 7.0.2: Known Problems</h1>
|
||||
|
||||
<p>Any patch files linked below should be applied at the root of the
|
||||
base-7.0.1 tree. Download them, then use the GNU Patch program as
|
||||
base-7.0.2 tree. Download them, then use the GNU Patch program as
|
||||
follows:</p>
|
||||
|
||||
<blockquote><pre>% <b>cd <i>/path/to/</i>base-7.0.1</b>
|
||||
<blockquote><pre>% <b>cd <i>/path/to/</i>base-7.0.2</b>
|
||||
% <b>patch -p1 < <i>/path/to/</i>file.patch</b></pre></blockquote>
|
||||
|
||||
<p>The following problems were known by the developers at the time of this
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Installation Instructions
|
||||
|
||||
EPICS Base Release 7.0.1.1
|
||||
EPICS Base Release 7.0.2
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
@@ -164,12 +164,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
|
||||
cygwin.bat WIN32 bat file to set cygwin path and env variables
|
||||
win32.bat WIN32 bat file to set 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
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<BODY>
|
||||
<CENTER>
|
||||
<H1>Installation Instructions</H1>
|
||||
<H2>EPICS Base Release 7.0.1.1</H2><BR>
|
||||
<H2>EPICS Base Release 7.0.2</H2><BR>
|
||||
</CENTER>
|
||||
<HR>
|
||||
<H3> Table of Contents</H3>
|
||||
@@ -176,12 +176,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
|
||||
cygwin.bat WIN32 bat file to set cygwin path and env variables
|
||||
win32.bat WIN32 bat file to set 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>
|
||||
|
||||
@@ -8,7 +8,20 @@
|
||||
|
||||
<body lang="en">
|
||||
|
||||
<h1 align="center">EPICS Release 7.0.2.x</h1>
|
||||
<p>These release notes describe changes that have been made since the previous
|
||||
release of this series of EPICS Base. <b>Note that changes which were merged up
|
||||
from commits to new releases in an older Base series are not described at the
|
||||
top of this file but have entries that appear lower down, under the series to
|
||||
which they were originally committed.</b> Thus it is important to read more than
|
||||
just the first section to understand everything that has changed in each
|
||||
release.</p>
|
||||
|
||||
<p>The external PVA submodules each have their own separate set of release notes
|
||||
which should also be read to understand what has changed since an earlier
|
||||
release.</p>
|
||||
|
||||
|
||||
<h1 align="center">EPICS Release 7.0.2</h1>
|
||||
|
||||
<!-- Insert new items immediately below this template ...
|
||||
|
||||
@@ -18,6 +31,13 @@
|
||||
|
||||
-->
|
||||
|
||||
<h3>Launchpad Bugs</h3>
|
||||
|
||||
<p>The list of tracked bugs fixed in this release can be found on the
|
||||
<a href="https://launchpad.net/epics-base/+milestone/7.0.2">Launchpad Milestone
|
||||
page for EPICS Base 7.0.2</a>.</p>
|
||||
|
||||
|
||||
<h3>Git Branches Recombined</h3>
|
||||
|
||||
<p>The four separate Git branches <tt>core/master</tt>, <tt>libcom/master</tt>,
|
||||
@@ -93,9 +113,139 @@ code than documentation. Send questions to the tech-talk mailing list and we'll
|
||||
be happy to try and answer them!</p>
|
||||
|
||||
|
||||
<h2 align="center">Changes from the 3.16 branch since 3.16.1</h2>
|
||||
<h2 align="center">Changes between 3.16.1 and 3.16.2</h2>
|
||||
|
||||
<!-- Insert inherited items immediately below here ... -->
|
||||
<p>The list of tracked bugs fixed in this release can be found on the
|
||||
<a href="https://launchpad.net/epics-base/+milestone/3.16.2">Launchpad Milestone
|
||||
page for EPICS Base 3.16.2</a>.</p>
|
||||
|
||||
<h3>Status reporting for the callback and scanOnce task queues</h3>
|
||||
|
||||
<p>Two new iocsh commands and some associated underlying APIs have been added to
|
||||
show the state of the queues that feed the three callback tasks and the scanOnce
|
||||
task, including a high-water mark which can optionally be reset. The new iocsh
|
||||
commands are <tt>callbackQueueShow</tt> and <tt>scanOnceQueueShow</tt>; both
|
||||
take an optional integer argument which must be non-zero to reset the
|
||||
high-water mark.</p>
|
||||
|
||||
<h3>Support for event codes greater than or equal to NUM_TIME_EVENTS</h3>
|
||||
|
||||
<p>Event numbers greater than or equal to NUM_TIME_EVENTS are now allowed if
|
||||
supported by the registered event time provider, which must provide its own
|
||||
advancing timestamp validation for such events.</p>
|
||||
|
||||
<p>Time events numbered 0 through (NUM_TIME_EVENTS-1) are still validated by
|
||||
code in epicsGeneralTime.c that checks for advancing timestamps and enforces
|
||||
that restriction.</p>
|
||||
|
||||
<h3>Type-safe Device and Driver Support Tables</h3>
|
||||
|
||||
<p>Type-safe versions of the device and driver support structures <tt>dset</tt>
|
||||
and <tt>drvet</tt> have been added to the devSup.h and drvSup.h headers
|
||||
respectively. The original structure definitions have not been changed so
|
||||
existing support modules will still build normally, but older modules can be
|
||||
modified and new code written to be compatible with both.</p>
|
||||
|
||||
<p>The old structure definitions will be replaced by the new ones if the macros
|
||||
<tt>USE_TYPED_DSET</tt> and/or <tt>USE_TYPED_DRVET</tt> are defined when the
|
||||
appropriate header is included. The best place to define these is in the
|
||||
Makefile, as with the <tt>USE_TYPED_RSET</tt> macro that was introduced in
|
||||
Base-3.16.1 and described below. See the comments in devSup.h for a brief usage
|
||||
example, or look at <a href="https://github.com/epics-modules/ipac/commit/a7e0ff4089b9aa39108bc8569e95ba7fcf07cee9">
|
||||
this commit</a> to the ipac module to see a module conversion.</p>
|
||||
|
||||
<p>A helper function <tt>DBLINK* dbGetDevLink(dbCommon *prec)</tt> has also been
|
||||
added to devSup.h which fetches a pointer to the INP or OUT field of the
|
||||
record.</p>
|
||||
|
||||
<h3>RTEMS build configuration update, running tests under QEMU</h3>
|
||||
|
||||
<p>This release includes the ability to run the EPICS unit tests built for a
|
||||
special version of the RTEMS-pc386 target architecture on systems that have an
|
||||
appropriate QEMU emulator installed (<tt>qemu-system-i386</tt>). It is also now
|
||||
possible to create sub-architectures of RTEMS targets, whereas previously the
|
||||
EPICS target architecture name had to be <tt>RTEMS-$(RTEMS_BSP)</tt>.</p>
|
||||
|
||||
<p>The new target <tt>RTEMS-pc386-qemu</tt> builds binaries that can be run in
|
||||
the <tt>qemu-system-i386</tt> PC System emulator. This target is a derivative of
|
||||
the original <tt>RTEMS-pc386</tt> target but with additional software to build
|
||||
an in-memory file-system, and some minor modifications to allow the unit tests
|
||||
to work properly under QEMU. When this target is enabled, building any of the
|
||||
make targets that cause the built-in self-tests to be run (such as
|
||||
<tt>make runtests</tt>) will also run the tests for RTEMS using QEMU.</p>
|
||||
|
||||
<p>To allow the new 3-component RTEMS target name, the EPICS build system for
|
||||
RTEMS was modified to allow a <tt>configure/os/CONFIG.Common.<arch></tt>
|
||||
file to set the <tt>RTEMS_BSP</tt> variable to inform the build what RTEMS BSP
|
||||
to use. Previously this was inferred from the value of the <tt>T_A</tt> make
|
||||
variable, but that prevents having multiple EPICS targets that build against the
|
||||
same BSP. All the included RTEMS target configuration files have been updated;
|
||||
build configuration files for out-of-tree RTEMS targets will continue to work as
|
||||
the original rules are used to set <tt>RTEMS_BSP</tt> if it hasn't been set when
|
||||
needed.</p>
|
||||
|
||||
<h3>Link type enhancements</h3>
|
||||
|
||||
<p>This release adds three new link types: "state", "debug" and "trace". The
|
||||
"state" link type gets and puts boolean values from/to the dbState library that
|
||||
was added in the 3.15.1 release. The "debug" link type sets the
|
||||
<code>jlink::debug</code> flag in its child link, while the "trace" link type
|
||||
also causes the arguments and return values for all calls to the child link's
|
||||
jlif and lset routines to be printed on stdout. The debug flag can no longer be
|
||||
set using an info tag. The addition of the "trace" link type has allowed over
|
||||
200 lines of conditional diagnostic printf() calls to be removed from the other
|
||||
link types.</p>
|
||||
|
||||
<p>The "calc" link type can now be used for output links as well as input links.
|
||||
This allows modification of the output value and even combining it with values
|
||||
from other input links. See the separate JSON Link types document for
|
||||
details.</p>
|
||||
|
||||
<p>A new <code>start_child()</code> method was added to the end of the jlif
|
||||
interface table.</p>
|
||||
|
||||
<p>The <code>lset</code> methods have now been properly documented in the
|
||||
dbLink.h header file using Doxygen annotations, although we do not run Doxygen
|
||||
on the source tree yet to generate API documentation.</p>
|
||||
|
||||
<p>Link types that utilize child links must now indicate whether the child will
|
||||
be used for input, output or forward linking by the return value from its
|
||||
<code>parse_start_map()</code> method. The <code>jlif_key_result</code> enum now
|
||||
contains 3 values <code>jlif_key_child_inlink</code>,
|
||||
<code>jlif_key_child_outlink</code> and <code>jlif_key_child_fwdlink</code>
|
||||
instead of the single <code>jlif_key_child_link</code> that was previously used
|
||||
for this.</p>
|
||||
|
||||
<h3>GNUmake targets for debugging</h3>
|
||||
|
||||
<p>Some additional build rules have been added to help debug configuration
|
||||
problems with the build system. Run <tt>make show-makefiles</tt> to get a sorted
|
||||
list of all the files that the build system includes when building in the
|
||||
current directory.</p>
|
||||
|
||||
<p>A new pattern rule for <tt>PRINT.%</tt> can be used to show the value of any
|
||||
GNUmake variable for the current build directory (make sure you are in the right
|
||||
directory though, many variables are only set when inside the
|
||||
<tt>O.<i>arch</i></tt> build directory). For example <tt>make PRINT.T_A</tt>
|
||||
will display the build target architecture name from inside a
|
||||
<tt>O.<i>arch</i></tt> directory but the variable will be empty from an
|
||||
application top or src directory. <tt>make PRINT.EPICS_BASE</tt> will show the
|
||||
path to Base from any EPICS application directory though.</p>
|
||||
|
||||
<h3>Propagate PUTF across Asynchronous record processing</h3>
|
||||
|
||||
<p>The IOC contains a mechanism involving the PUTF and RPRO fields of each
|
||||
record to ensure that if a record is busy when it receives a put to one of its
|
||||
fields, the record will be processed again to ensure that the new field value
|
||||
has been correctly acted on. Until now that mechanism only worked if the put was
|
||||
to the asynchronous record itself, so puts that were chained from some other
|
||||
record via a DB link did not cause reprocessing.</p>
|
||||
|
||||
<p>In this release the mechanism has been extended to propagate the PUTF state
|
||||
across DB links until all downstream records have been reprocessed. Some
|
||||
additional information about the record state can be shown by setting the TPRO
|
||||
field of an upstream record, and even more trace data is displayed if the
|
||||
debugging variable <tt>dbAccessDebugPUTF</tt> is set in addition to TPRO.</p>
|
||||
|
||||
<h3>Finding info fields</h3>
|
||||
|
||||
@@ -113,15 +263,18 @@ release also includes additional protection against buffer overflows while
|
||||
printing long links in <tt>dbpr</tt>, and corrects the output of long strings
|
||||
from the <tt>dbgf</tt> command.</p>
|
||||
|
||||
<h3>Record types mbbiDirect and mbboDirect extended to 32 bit</h3>
|
||||
<h3>Record types mbbiDirect and mbboDirect upgraded to 32 bit</h3>
|
||||
|
||||
<p>The VAL fields of mbbiDirect and mbboDirect records have
|
||||
been extended from <tt>DBF_USHORT</tt> (16 bit) to <tt>DBF_LONG</tt> (32 bit).
|
||||
New bit fields <tt>B10</tt>...<tt>B1F</tt> have been added.</p>
|
||||
<p>The VAL fields and related fields of these records are now <tt>DBF_LONG</tt>.
|
||||
(Not <tt>DBF_ULONG</tt> in order to prevent Channel Access from promoting them
|
||||
to <tt>DBF_DOUBLE</tt>.) Additional bit fields <tt>B10</tt>...<tt>B1F</tt> have
|
||||
been added.</p>
|
||||
|
||||
<p>Device support which accesses the bit fields can test if the macro
|
||||
<tt>mbbiDirectRecord1BF</tt> or <tt>mbboDirectRecord1BF</tt> is
|
||||
defined. Device support which only accesses RVAL needs no modification.</p>
|
||||
<p>Device support that accesses <tt>VAL</tt> or the bit fields directly (most
|
||||
don't) and aims for compatibility with old and new versions of these records
|
||||
should use at least 32 bit integer types to avoid bit loss. The number of bit
|
||||
fields can be calculated using <code>8 * sizeof(prec->val)</code>
|
||||
which is correct in both versions.</p>
|
||||
|
||||
<h3>Restore use of ledlib for VxWorks command editing</h3>
|
||||
|
||||
@@ -763,11 +916,76 @@ the stdout stream, making it hard to parse.</p>
|
||||
callback.h header and removed the need for dbScan.c to reach into the internals
|
||||
of its CALLBACK objects.</p>
|
||||
|
||||
|
||||
<h2 align="center">Changes from the 3.15 branch since 3.15.5</h2>
|
||||
<h2 align="center">Changes from the 3.15 branch since 3.15.6</h2>
|
||||
|
||||
<!-- Insert inherited items immediately below here ... -->
|
||||
|
||||
<h3>Routine <tt>epicsTempName()</tt> removed from libCom</h3>
|
||||
|
||||
<p>This routine was a simple wrapper around the C89 function <tt>tmpnam()</tt>
|
||||
which is now seen as unsafe and causes warning messages to be generated by
|
||||
most modern compilers. The two internal uses of this function have been
|
||||
modified to call <tt>epicsTempFile()</tt> instead. We were unable to find any
|
||||
published code that used this function, so it was removed immediately instead
|
||||
of being deprecated.</p>
|
||||
|
||||
<h3>DBD Parsing of Record Types</h3>
|
||||
|
||||
<p>The Perl DBD file parser has been made slightly more liberal; the order in
|
||||
which DBD files must be parsed is now more flexible, so that a record type
|
||||
definition can now be parsed after a device support that referred to that
|
||||
record type. A warning message will be displayed when the device support is
|
||||
seen, but the subsequent loading of the record type will be accepted without
|
||||
triggering an error. See
|
||||
<a href="https://bugs.launchpad.net/epics-base/+bug/1801145">Launchpad bug
|
||||
#1801145</a>.</p>
|
||||
|
||||
<h3>menuScan and several record types documented with POD</h3>
|
||||
|
||||
<p>The EPICS Wiki pages describing a number of standard record types has been
|
||||
converted into the Perl POD documentation format and added to the DBD files,
|
||||
so at build-time an HTML version of these documents is generated and installed
|
||||
into the htmls directory. Thanks to Tony Pietryla.</p>
|
||||
|
||||
<h3>CA client tools learned <tt>-V</tt> option</h3>
|
||||
|
||||
<p>This displays the version numbers of EPICS Base and the CA protocol.</p>
|
||||
|
||||
|
||||
<h2 align="center">Changes made between 3.15.5 and 3.15.6</h2>
|
||||
|
||||
<h3>Unsetting environment variables</h3>
|
||||
|
||||
<p>The new command <code>epicsEnvUnset <i>varname</i></code> can be used to
|
||||
unset an environment variable.</p>
|
||||
|
||||
<h3>Warning indicators in msi (and macLib) output</h3>
|
||||
|
||||
<p>The libCom macro expansion library has been modified so that when the
|
||||
SUPPRESS_WARNINGS flag is set it will no longer include any <tt>,undefined</tt>
|
||||
or <tt>,recursive</tt> indicators in its output when undefined or recursive
|
||||
macros are encountered. These indicators were harmless when the output was fed
|
||||
into an IOC along with a definition for the macro, but when the <tt>msi</tt>
|
||||
tool was used to generate other kinds of files they caused problems. If the
|
||||
<tt>msi -V</tt> flag is used the markers will still be present in the output
|
||||
whenever the appropriate condition is seen.</p>
|
||||
|
||||
<h3>Improvements to msi</h3>
|
||||
|
||||
<p>In addition to fixing its response to discovering parsing errors in its
|
||||
substitution input file (reported as Launchpad
|
||||
<a href="https://bugs.launchpad.net/epics-base/+bug/1503661">bug #1503661</a>)
|
||||
so it now deletes the incomplete output file, the msi program has been cleaned
|
||||
up a little bit internally.</p>
|
||||
|
||||
<h3>All array records now post monitors on their array-length fields</h3>
|
||||
|
||||
<p>The waveform record has been posting monitors on its NORD field since Base
|
||||
3.15.0.1; we finally got around to doing the equivalent in all the other
|
||||
built-in record types, which even required modifying device support in some
|
||||
cases. This fixes <a href="https://bugs.launchpad.net/epics-base/+bug/1730727">
|
||||
Launchpad bug #1730727</a>.</p>
|
||||
|
||||
<h3>HOWTO: Converting Wiki Record Reference to POD</h3>
|
||||
|
||||
<p>Some documentation has been added to the <tt>dbdToHtml.pl</tt> script
|
||||
@@ -799,15 +1017,84 @@ of having go modify or replace the original. A new .gitignore pattern
|
||||
tells git to ignore all configure/*.local files.</p>
|
||||
|
||||
|
||||
<h2 align="center">Changes from the 3.14 branch since 3.15.5</h2>
|
||||
<h2 align="center">Changes from the 3.14 branch between 3.15.5 and 3.15.6</h2>
|
||||
|
||||
<!-- Insert inherited 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">
|
||||
|
||||
@@ -133,20 +133,20 @@ made.</p>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td>Release Manager</td>
|
||||
<td>Tag the module in Git using these tag conventions:
|
||||
<td>Tag the module in Git, using these tag conventions:
|
||||
<ul>
|
||||
<li>
|
||||
<tt>R7.1.1-pre<i>n</i></tt>
|
||||
<tt>R7.0.2-pre<i>n</i></tt>
|
||||
— pre-release tag
|
||||
</li>
|
||||
<li>
|
||||
<tt>R7.1.1-rc<i>n</i></tt>
|
||||
<tt>R7.0.2-rc<i>n</i></tt>
|
||||
— release candidate tag
|
||||
</li>
|
||||
</ul>
|
||||
</ul>
|
||||
<blockquote><tt>
|
||||
cd base-7.1<br />
|
||||
git tag -m 'ANJ: Tagged for 7.1.1-rc1' R7.1.1-rc1
|
||||
cd base-7.0<br />
|
||||
git tag -m 'ANJ: Tagged for 7.0.2-rc1' R7.0.2-rc1
|
||||
</tt></blockquote>
|
||||
Note that submodules must <em>not</em> be tagged with the version used
|
||||
for the top-level, they each have their own separate version numbers
|
||||
@@ -159,12 +159,12 @@ made.</p>
|
||||
script generates a gzipped tarfile directly from the tag, excluding the
|
||||
files and directories that are only used for continuous integration:
|
||||
<blockquote><tt>
|
||||
cd base-7.1<br />
|
||||
.ci/make-tar.sh R7.1.1-rc1 base-7.1.1-rc1.tar.gz base-7.1.1-rc1/
|
||||
cd base-7.0<br />
|
||||
./.tools/make-tar.sh R7.0.2-rc1 base-7.0.2-rc1.tar.gz base-7.0.2-rc1/
|
||||
</tt></blockquote>
|
||||
Create a GPG signature file of the tarfile as follows:
|
||||
<blockquote><tt>
|
||||
gpg --armor --sign --detach-sig base-7.1.1-rc1.tar.gz
|
||||
gpg --armor --sign --detach-sig base-7.0.2-rc1.tar.gz
|
||||
</tt></blockquote>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -247,6 +247,7 @@ made.</p>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th colspan="3">Release Approval</th>
|
||||
</tr>
|
||||
@@ -263,18 +264,36 @@ made.</p>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td>Release Manager</td>
|
||||
<td>Edit and commit changes to the EPICS version number file
|
||||
configure/CONFIG_BASE_VERSION.</td>
|
||||
<td>
|
||||
<p>For each external submodule, check if the module's release version
|
||||
number (and SHRLIB_VERSION setting) has been updated if appropriate,
|
||||
and that its Release Notes have been updated to cover any changes.
|
||||
Commit any fixes and tag the module if that hasn't already been
|
||||
done.</p>
|
||||
<p>Update all external submodules on the Base-7.0 branch and
|
||||
commit.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td>Release Manager</td>
|
||||
<td>Tag the module in Git:
|
||||
<td>Edit and commit changes to the EPICS Base version number file and
|
||||
the embedded module version files:
|
||||
<ul>
|
||||
<li>configure/CONFIG_BASE_VERSION </li>
|
||||
<li>modules/libcom/configure/CONFIG_LIBCOM_VERSION</li>
|
||||
<li>modules/ca/configure/CONFIG_CA_VERSION</li>
|
||||
<li>modules/database/configure/CONFIG_DATABASE_VERSION</li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td>Release Manager</td>
|
||||
<td>Tag the epics-base module in Git:
|
||||
<blockquote><tt>
|
||||
cd base-7.1<br />
|
||||
git tag -m 'ANJ: Tagged for 7.1.1' R7.1.1</i>
|
||||
cd base-7.0<br />
|
||||
git tag -m 'ANJ: Tagged for 7.0.2' R7.0.2</i>
|
||||
</tt></blockquote>
|
||||
</td>
|
||||
Don't push the new tag to the Launchpad repository yet.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
@@ -283,12 +302,12 @@ made.</p>
|
||||
script generates a gzipped tarfile directly from the tag, excluding the
|
||||
files and directories that are only used for continuous integration:
|
||||
<blockquote><tt>
|
||||
cd base-7.1<br />
|
||||
.ci/make-tar.sh R7.1.1 base-7.1.1.tar.gz base-7.1.1/
|
||||
cd base-7.0<br />
|
||||
./.tools/make-tar.sh R7.0.2 base-7.0.2.tar.gz base-7.0.2/
|
||||
</tt></blockquote>
|
||||
Create a GPG signature file of the tarfile as follows:
|
||||
<blockquote><tt>
|
||||
gpg --armor --sign --detach-sig base-7.1.1.tar.gz
|
||||
gpg --armor --sign --detach-sig base-7.0.2.tar.gz
|
||||
</tt></blockquote>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -296,7 +315,12 @@ made.</p>
|
||||
<td> </td>
|
||||
<td>Release Manager</td>
|
||||
<td>Test the tar file by extracting its contents and building it on at
|
||||
least one supported platform</td>
|
||||
least one supported platform. When this succeeds the new git tag can be
|
||||
pushed to the Launchpad repository:
|
||||
<blockquote><tt>
|
||||
git push --follow-tags upstream 7.0
|
||||
</tt></blockquote>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
@@ -316,8 +340,8 @@ made.</p>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td>Website Manager</td>
|
||||
<td>Copy the tar file and its <tt>.asc</tt> signature file to the Base
|
||||
download area of the website.</td>
|
||||
<td>Upload the tar file and its <tt>.asc</tt> signature file to the
|
||||
Launchpad milestone for this release version.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
EPICS_CA_MAJOR_VERSION = 4
|
||||
EPICS_CA_MINOR_VERSION = 13
|
||||
EPICS_CA_MAINTENANCE_VERSION = 2
|
||||
EPICS_CA_DEVELOPMENT_FLAG = 1
|
||||
EPICS_CA_MAINTENANCE_VERSION = 3
|
||||
EPICS_CA_DEVELOPMENT_FLAG = 0
|
||||
|
||||
@@ -125,7 +125,7 @@ EXPANDVARS += EPICS_CA_DEVELOPMENT_FLAG
|
||||
EXPANDFLAGS += $(foreach var,$(EXPANDVARS),-D$(var)="$(strip $($(var)))")
|
||||
|
||||
# shared library ABI version.
|
||||
SHRLIB_VERSION = 4.13.1
|
||||
SHRLIB_VERSION = $(EPICS_CA_MAJOR_VERSION).$(EPICS_CA_MINOR_VERSION).$(EPICS_CA_MAINTENANCE_VERSION)
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
|
||||
|
||||
@@ -193,7 +193,7 @@ udpiiu::udpiiu (
|
||||
|
||||
#ifdef IP_MULTICAST_TTL
|
||||
{
|
||||
int ttl;
|
||||
osiSockOptMcastTTL_t ttl;
|
||||
long val;
|
||||
if(envGetLongConfigParam(&EPICS_CA_MCAST_TTL, &val))
|
||||
val =1;
|
||||
@@ -961,7 +961,7 @@ bool udpiiu::pushDatagramMsg ( epicsGuard < epicsMutex > & guard,
|
||||
|
||||
udpiiu :: SearchDestUDP :: SearchDestUDP (
|
||||
const osiSockAddr & destAddr, udpiiu & udpiiuIn ) :
|
||||
_destAddr ( destAddr ), _udpiiu ( udpiiuIn )
|
||||
_lastError (0u), _destAddr ( destAddr ), _udpiiu ( udpiiuIn )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -976,6 +976,13 @@ void udpiiu :: SearchDestUDP :: searchRequest (
|
||||
int status = sendto ( _udpiiu.sock, const_cast<char *>(pBuf), bufSizeAsInt, 0,
|
||||
& _destAddr.sa, sizeof ( _destAddr.sa ) );
|
||||
if ( status == bufSizeAsInt ) {
|
||||
if ( _lastError ) {
|
||||
char buf[64];
|
||||
sockAddrToDottedIP ( &_destAddr.sa, buf, sizeof ( buf ) );
|
||||
errlogPrintf (
|
||||
"CAC: ok sending UDP msg to %s\n", buf);
|
||||
}
|
||||
_lastError = 0;
|
||||
break;
|
||||
}
|
||||
if ( status >= 0 ) {
|
||||
@@ -1002,7 +1009,9 @@ void udpiiu :: SearchDestUDP :: searchRequest (
|
||||
else if ( localErrno == SOCK_EBADF ) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
else if ( localErrno == _lastError) {
|
||||
break;
|
||||
} else {
|
||||
char sockErrBuf[64];
|
||||
epicsSocketConvertErrnoToString (
|
||||
sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
@@ -1011,6 +1020,8 @@ void udpiiu :: SearchDestUDP :: searchRequest (
|
||||
errlogPrintf (
|
||||
"CAC: error = \"%s\" sending UDP msg to %s\n",
|
||||
sockErrBuf, buf);
|
||||
|
||||
_lastError = localErrno;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,6 +123,7 @@ private:
|
||||
void show (
|
||||
epicsGuard < epicsMutex > &, unsigned level ) const;
|
||||
private:
|
||||
int _lastError;
|
||||
osiSockAddr _destAddr;
|
||||
udpiiu & _udpiiu;
|
||||
};
|
||||
|
||||
@@ -143,6 +143,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) {
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <alarm.h>
|
||||
#include <cadef.h>
|
||||
#include <epicsGetopt.h>
|
||||
#include "epicsVersion.h"
|
||||
|
||||
#include "tool_lib.h"
|
||||
|
||||
@@ -55,6 +56,7 @@ static void usage (void)
|
||||
{
|
||||
fprintf (stderr, "\nUsage: caget [options] <PV name> ...\n\n"
|
||||
" -h: Help: Print this message\n"
|
||||
" -V: Version: Show EPICS and CA versions\n"
|
||||
"Channel Access options:\n"
|
||||
" -w <sec>: Wait time, specifies CA timeout, default is %f second(s)\n"
|
||||
" -c: Asynchronous get (use ca_get_callback and wait for completion)\n"
|
||||
@@ -389,11 +391,14 @@ int main (int argc, char *argv[])
|
||||
|
||||
LINE_BUFFER(stdout); /* Configure stdout buffering */
|
||||
|
||||
while ((opt = getopt(argc, argv, ":taicnhsSe:f:g:l:#:d:0:w:p:F:")) != -1) {
|
||||
while ((opt = getopt(argc, argv, ":taicnhsSVe:f:g:l:#:d:0:w:p:F:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'h': /* Print usage */
|
||||
usage();
|
||||
return 0;
|
||||
case 'V':
|
||||
printf( "\nEPICS Version %s, CA Protocol version %s\n", EPICS_VERSION_STRING, ca_version() );
|
||||
return 0;
|
||||
case 't': /* Terse output mode */
|
||||
complainIfNotPlainAndSet(&format, terse);
|
||||
break;
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <epicsStdlib.h>
|
||||
#include "epicsVersion.h"
|
||||
|
||||
#include <cadef.h>
|
||||
#include <epicsGetopt.h>
|
||||
@@ -36,12 +37,14 @@ void usage (void)
|
||||
{
|
||||
fprintf (stderr, "\nUsage: cainfo [options] <PV name> ...\n\n"
|
||||
" -h: Help: Print this message\n"
|
||||
" -V: Version: Show EPICS and CA versions\n"
|
||||
"Channel Access options:\n"
|
||||
" -w <sec>: Wait time, specifies CA timeout, default is %f second(s)\n"
|
||||
" -s <level>: Call ca_client_status with the specified interest level\n"
|
||||
" -p <prio>: CA priority (0-%u, default 0=lowest)\n"
|
||||
"\nExample: cainfo my_channel another_channel\n\n"
|
||||
, DEFAULT_TIMEOUT, CA_PRIORITY_MAX);
|
||||
fprintf (stderr, "\nEPICS Version %s, CA Protocol version %s\n", EPICS_VERSION_STRING, ca_version() );
|
||||
}
|
||||
|
||||
|
||||
@@ -137,11 +140,14 @@ int main (int argc, char *argv[])
|
||||
|
||||
LINE_BUFFER(stdout); /* Configure stdout buffering */
|
||||
|
||||
while ((opt = getopt(argc, argv, ":nhw:s:p:")) != -1) {
|
||||
while ((opt = getopt(argc, argv, ":nhVw:s:p:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'h': /* Print usage */
|
||||
usage();
|
||||
return 0;
|
||||
case 'V':
|
||||
printf( "\nEPICS Version %s, CA Protocol version %s\n", EPICS_VERSION_STRING, ca_version() );
|
||||
return 0;
|
||||
case 'w': /* Set CA timeout value */
|
||||
if(epicsScanDouble(optarg, &caTimeout) != 1)
|
||||
{
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <stdio.h>
|
||||
#include <epicsStdlib.h>
|
||||
#include <string.h>
|
||||
#include "epicsVersion.h"
|
||||
|
||||
#include <cadef.h>
|
||||
#include <epicsGetopt.h>
|
||||
@@ -44,7 +45,8 @@ void usage (void)
|
||||
{
|
||||
fprintf (stderr, "\nUsage: camonitor [options] <PV name> ...\n"
|
||||
"\n"
|
||||
" -h: Help; Print this message\n"
|
||||
" -h: Help: Print this message\n"
|
||||
" -V: Version: Show EPICS and CA versions\n"
|
||||
"Channel Access options:\n"
|
||||
" -w <sec>: Wait time, specifies CA timeout, default is %f second(s)\n"
|
||||
" -m <msk>: Specify CA event mask to use. <msk> is any combination of\n"
|
||||
@@ -209,11 +211,14 @@ int main (int argc, char *argv[])
|
||||
|
||||
LINE_BUFFER(stdout); /* Configure stdout buffering */
|
||||
|
||||
while ((opt = getopt(argc, argv, ":nhm:sSe:f:g:l:#:0:w:t:p:F:")) != -1) {
|
||||
while ((opt = getopt(argc, argv, ":nhVm:sSe:f:g:l:#:0:w:t:p:F:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'h': /* Print usage */
|
||||
usage();
|
||||
return 0;
|
||||
case 'V':
|
||||
printf( "\nEPICS Version %s, CA Protocol version %s\n", EPICS_VERSION_STRING, ca_version() );
|
||||
return 0;
|
||||
case 'n': /* Print ENUM as index numbers */
|
||||
enumAsNr=1;
|
||||
break;
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <epicsGetopt.h>
|
||||
#include <epicsEvent.h>
|
||||
#include <epicsString.h>
|
||||
#include "epicsVersion.h"
|
||||
|
||||
#include "tool_lib.h"
|
||||
|
||||
@@ -59,6 +60,7 @@ void usage (void)
|
||||
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"
|
||||
" -V: Version: Show EPICS and CA versions\n"
|
||||
"Channel Access options:\n"
|
||||
" -w <sec>: Wait time, specifies CA timeout, default is %f second(s)\n"
|
||||
" -c: Asynchronous put (use ca_put_callback and wait for completion)\n"
|
||||
@@ -281,11 +283,14 @@ int main (int argc, char *argv[])
|
||||
LINE_BUFFER(stdout); /* Configure stdout buffering */
|
||||
putenv("POSIXLY_CORRECT="); /* Behave correct on GNU getopt systems */
|
||||
|
||||
while ((opt = getopt(argc, argv, ":cnlhatsS#:w:p:F:")) != -1) {
|
||||
while ((opt = getopt(argc, argv, ":cnlhatsVS#:w:p:F:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'h': /* Print usage */
|
||||
usage();
|
||||
return 0;
|
||||
case 'V':
|
||||
printf( "\nEPICS Version %s, CA Protocol version %s\n", EPICS_VERSION_STRING, ca_version() );
|
||||
return 0;
|
||||
case 'n': /* Force interpret ENUM as index number */
|
||||
enumAsNr = 1;
|
||||
enumAsString = 0;
|
||||
|
||||
@@ -25,7 +25,7 @@ INSTALL_LOCATION = $(TOP)
|
||||
BASE_CPPFLAGS += -DUSE_TYPED_RSET
|
||||
|
||||
# Shared library ABI version.
|
||||
SHRLIB_VERSION = 3.17.0
|
||||
SHRLIB_VERSION = $(EPICS_DATABASE_MAJOR_VERSION).$(EPICS_DATABASE_MINOR_VERSION).$(EPICS_DATABASE_MAINTENANCE_VERSION)
|
||||
|
||||
# CONFIG_SITE files contain other build configuration settings
|
||||
include $(TOP)/configure/CONFIG_SITE
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
EPICS_DATABASE_MAJOR_VERSION = 3
|
||||
EPICS_DATABASE_MINOR_VERSION = 17
|
||||
EPICS_DATABASE_MAINTENANCE_VERSION = 1
|
||||
EPICS_DATABASE_DEVELOPMENT_FLAG = 1
|
||||
EPICS_DATABASE_MAINTENANCE_VERSION = 2
|
||||
EPICS_DATABASE_DEVELOPMENT_FLAG = 0
|
||||
|
||||
@@ -25,11 +25,6 @@ INC += databaseVersionNum.h
|
||||
|
||||
PROD_LIBS = Com
|
||||
|
||||
EPICS_DATABASE_MAJOR_VERSION = 3
|
||||
EPICS_DATABASE_MINOR_VERSION = 17
|
||||
EPICS_DATABASE_MAINTENANCE_VERSION = 0
|
||||
EPICS_DATABASE_DEVELOPMENT_FLAG = 1
|
||||
|
||||
include $(IOCDIR)/as/Makefile
|
||||
include $(IOCDIR)/bpt/Makefile
|
||||
include $(IOCDIR)/db/Makefile
|
||||
|
||||
@@ -35,7 +35,6 @@ INC += dbTest.h
|
||||
INC += dbCaTest.h
|
||||
INC += db_test.h
|
||||
INC += db_field_log.h
|
||||
INC += initHooks.h
|
||||
INC += recGbl.h
|
||||
INC += dbIocRegister.h
|
||||
INC += chfPlugin.h
|
||||
@@ -62,7 +61,7 @@ DBDINC += menuScan
|
||||
DBDINC += dbCommon
|
||||
|
||||
dbMenusPod = $(notdir $(wildcard ../db/menu*.dbd.pod))
|
||||
HTMLS += $(patsubst %.dbd.pod,%.html,$(menusPod))
|
||||
HTMLS += $(patsubst %.dbd.pod,%.html,$(dbMenusPod))
|
||||
|
||||
dbCore_SRCS += dbLock.c
|
||||
dbCore_SRCS += dbAccess.c
|
||||
@@ -86,7 +85,6 @@ dbCore_SRCS += recGbl.c
|
||||
dbCore_SRCS += callback.c
|
||||
dbCore_SRCS += dbCa.c
|
||||
dbCore_SRCS += dbCaTest.c
|
||||
dbCore_SRCS += initHooks.c
|
||||
dbCore_SRCS += cvtBpt.c
|
||||
dbCore_SRCS += dbContext.cpp
|
||||
dbCore_SRCS += dbChannelIO.cpp
|
||||
|
||||
@@ -54,6 +54,7 @@ typedef struct cbQueueSet {
|
||||
epicsEventId semWakeUp;
|
||||
epicsRingPointerId queue;
|
||||
int queueOverflow;
|
||||
int queueOverflows;
|
||||
int shutdown;
|
||||
int threadsConfigured;
|
||||
int threadsRunning;
|
||||
@@ -103,6 +104,51 @@ int callbackSetQueueSize(int size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int callbackQueueStatus(const int reset, callbackQueueStats *result)
|
||||
{
|
||||
int ret;
|
||||
if (!callbackIsInit) return -1;
|
||||
if (result) {
|
||||
int prio;
|
||||
result->size = callbackQueueSize;
|
||||
for(prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) {
|
||||
epicsRingPointerId qId = callbackQueue[prio].queue;
|
||||
result->numUsed[prio] = epicsRingPointerGetUsed(qId);
|
||||
result->maxUsed[prio] = epicsRingPointerGetHighWaterMark(qId);
|
||||
result->numOverflow[prio] = epicsAtomicGetIntT(&callbackQueue[prio].queueOverflows);
|
||||
}
|
||||
ret = 0;
|
||||
} else {
|
||||
ret = -2;
|
||||
}
|
||||
if (reset) {
|
||||
int prio;
|
||||
for(prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) {
|
||||
epicsRingPointerResetHighWaterMark(callbackQueue[prio].queue);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void callbackQueueShow(const int reset)
|
||||
{
|
||||
callbackQueueStats stats;
|
||||
if (callbackQueueStatus(reset, &stats) == -1) {
|
||||
fprintf(stderr, "Callback system not initialized, yet. Please run "
|
||||
"iocInit before using this command.\n");
|
||||
} else {
|
||||
int prio;
|
||||
printf("PRIORITY HIGH-WATER MARK ITEMS IN Q Q SIZE %% USED Q OVERFLOWS\n");
|
||||
for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) {
|
||||
double qusage = 100.0 * stats.numUsed[prio] / stats.size;
|
||||
printf("%8s %15d %10d %6d %6.1f %11d\n",
|
||||
threadNamePrefix[prio], stats.maxUsed[prio],
|
||||
stats.numUsed[prio], stats.size, qusage,
|
||||
stats.numOverflow[prio]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int callbackParallelThreads(int count, const char *prio)
|
||||
{
|
||||
if (callbackIsInit) {
|
||||
@@ -290,6 +336,7 @@ int callbackRequest(CALLBACK *pcallback)
|
||||
if (!pushOK) {
|
||||
epicsInterruptContextMessage(fullMessage[priority]);
|
||||
mySet->queueOverflow = TRUE;
|
||||
epicsAtomicIncrIntT(&mySet->queueOverflows);
|
||||
return S_db_bufFull;
|
||||
}
|
||||
epicsEventSignal(mySet->semWakeUp);
|
||||
|
||||
@@ -48,6 +48,13 @@ typedef epicsCallback CALLBACK;
|
||||
|
||||
typedef void (*CALLBACKFUNC)(struct callbackPvt*);
|
||||
|
||||
typedef struct callbackQueueStats {
|
||||
int size;
|
||||
int numUsed[NUM_CALLBACK_PRIORITIES];
|
||||
int maxUsed[NUM_CALLBACK_PRIORITIES];
|
||||
int numOverflow[NUM_CALLBACK_PRIORITIES];
|
||||
} callbackQueueStats;
|
||||
|
||||
#define callbackSetCallback(PFUN, PCALLBACK) \
|
||||
( (PCALLBACK)->callback = (PFUN) )
|
||||
#define callbackSetPriority(PRIORITY, PCALLBACK) \
|
||||
@@ -73,6 +80,8 @@ epicsShareFunc void callbackCancelDelayed(CALLBACK *pcallback);
|
||||
epicsShareFunc void callbackRequestProcessCallbackDelayed(
|
||||
CALLBACK *pCallback, int Priority, void *pRec, double seconds);
|
||||
epicsShareFunc int callbackSetQueueSize(int size);
|
||||
epicsShareFunc int callbackQueueStatus(const int reset, callbackQueueStats *result);
|
||||
epicsShareFunc void callbackQueueShow(const int reset);
|
||||
epicsShareFunc int callbackParallelThreads(int count, const char *prio);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
#include "errlog.h"
|
||||
#include "errMdef.h"
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "epicsExport.h" /* #define epicsExportSharedSymbols */
|
||||
#include "caeventmask.h"
|
||||
#include "callback.h"
|
||||
#include "dbAccessDefs.h"
|
||||
@@ -65,6 +65,9 @@
|
||||
epicsShareDef struct dbBase *pdbbase = 0;
|
||||
epicsShareDef volatile int interruptAccept=FALSE;
|
||||
|
||||
epicsShareDef int dbAccessDebugPUTF = 0;
|
||||
epicsExportAddress(int, dbAccessDebugPUTF);
|
||||
|
||||
/* Hook Routines */
|
||||
|
||||
epicsShareDef DB_LOAD_RECORDS_HOOK_ROUTINE dbLoadRecordsHook = NULL;
|
||||
@@ -446,22 +449,6 @@ int dbGetFieldIndex(const struct dbAddr *paddr)
|
||||
return paddr->pfldDes->indRecordType;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process a record if its scan field is passive.
|
||||
* Will notify if processing is complete by callback.
|
||||
* (only if you are interested in completion)
|
||||
*/
|
||||
long dbScanPassive(dbCommon *pfrom, dbCommon *pto)
|
||||
{
|
||||
/* if not passive just return success */
|
||||
if (pto->scan != 0)
|
||||
return 0;
|
||||
|
||||
if (pfrom && pfrom->ppn)
|
||||
dbNotifyAdd(pfrom,pto);
|
||||
return dbProcess(pto);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process the record.
|
||||
* 1. Check for breakpoints.
|
||||
@@ -527,7 +514,8 @@ long dbProcess(dbCommon *precord)
|
||||
unsigned short monitor_mask;
|
||||
|
||||
if (*ptrace)
|
||||
printf("%s: Active %s\n", context, precord->name);
|
||||
printf("%s: dbProcess of Active '%s' with RPRO=%d\n",
|
||||
context, precord->name, precord->rpro);
|
||||
|
||||
/* raise scan alarm after MAX_LOCK times */
|
||||
if ((precord->stat == SCAN_ALARM) ||
|
||||
@@ -556,7 +544,8 @@ long dbProcess(dbCommon *precord)
|
||||
/* if disabled check disable alarm severity and return success */
|
||||
if (precord->disa == precord->disv) {
|
||||
if (*ptrace)
|
||||
printf("%s: Disabled %s\n", context, precord->name);
|
||||
printf("%s: dbProcess of Disabled '%s'\n",
|
||||
context, precord->name);
|
||||
|
||||
/*take care of caching and notifyCompletion*/
|
||||
precord->rpro = FALSE;
|
||||
@@ -593,7 +582,7 @@ long dbProcess(dbCommon *precord)
|
||||
}
|
||||
|
||||
if (*ptrace)
|
||||
printf("%s: Process %s\n", context, precord->name);
|
||||
printf("%s: dbProcess of '%s'\n", context, precord->name);
|
||||
|
||||
/* process record */
|
||||
status = prset->process(precord);
|
||||
@@ -713,6 +702,18 @@ void dbInitEntryFromRecord(struct dbCommon *prec, DBENTRY *pdbentry)
|
||||
pdbentry->precnode = ppvt->recnode;
|
||||
}
|
||||
|
||||
struct link* dbGetDevLink(struct dbCommon* prec)
|
||||
{
|
||||
DBLINK *plink = 0;
|
||||
DBENTRY entry;
|
||||
dbInitEntryFromRecord(prec, &entry);
|
||||
if(dbFindField(&entry, "INP")==0 || dbFindField(&entry, "OUT")==0) {
|
||||
plink = (DBLINK*)entry.pfield;
|
||||
}
|
||||
dbFinishEntry(&entry);
|
||||
return plink;
|
||||
}
|
||||
|
||||
long dbValueSize(short dbr_type)
|
||||
{
|
||||
/* sizes for value associated with each DBR request type */
|
||||
@@ -1049,7 +1050,7 @@ static long dbPutFieldLink(DBADDR *paddr,
|
||||
return S_db_badDbrtype;
|
||||
}
|
||||
|
||||
status = dbParseLink(pstring, pfldDes->field_type, &link_info, 0);
|
||||
status = dbParseLink(pstring, pfldDes->field_type, &link_info);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
@@ -1222,8 +1223,8 @@ long dbPutField(DBADDR *paddr, short dbrType,
|
||||
precord->scan == 0 &&
|
||||
dbrType < DBR_PUT_ACKT)) {
|
||||
if (precord->pact) {
|
||||
if (precord->tpro)
|
||||
printf("%s: Active %s\n",
|
||||
if (dbAccessDebugPUTF && precord->tpro)
|
||||
printf("%s: dbPutField to Active '%s', setting RPRO=1\n",
|
||||
epicsThreadGetNameSelf(), precord->name);
|
||||
precord->rpro = TRUE;
|
||||
} else {
|
||||
@@ -1356,4 +1357,3 @@ done:
|
||||
paddr->pfield = pfieldsave;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ extern "C" {
|
||||
|
||||
epicsShareExtern struct dbBase *pdbbase;
|
||||
epicsShareExtern volatile int interruptAccept;
|
||||
epicsShareExtern int dbAccessDebugPUTF;
|
||||
|
||||
/* The database field and request types are defined in dbFldTypes.h*/
|
||||
/* Data Base Request Options */
|
||||
|
||||
@@ -703,7 +703,12 @@ static long doLocked(struct link *plink, dbLinkUserCallback rtn, void *priv)
|
||||
caLink *pca;
|
||||
long status;
|
||||
|
||||
pcaGetCheck
|
||||
assert(plink);
|
||||
if (plink->type != CA_LINK) return -1;
|
||||
pca = (caLink *)plink->value.pv_link.pvt;
|
||||
assert(pca);
|
||||
epicsMutexMustLock(pca->lock);
|
||||
assert(pca->plink);
|
||||
status = rtn(plink, priv);
|
||||
epicsMutexUnlock(pca->lock);
|
||||
return status;
|
||||
@@ -842,6 +847,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);
|
||||
@@ -872,10 +878,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:
|
||||
@@ -893,7 +902,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) ||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "cantProceed.h"
|
||||
#include "epicsAssert.h"
|
||||
#include "epicsString.h"
|
||||
#include "epicsStdio.h"
|
||||
#include "errlog.h"
|
||||
#include "freeList.h"
|
||||
#include "gpHash.h"
|
||||
|
||||
@@ -12,6 +12,29 @@
|
||||
* Current Author: Andrew Johnson
|
||||
*/
|
||||
|
||||
/* The PUTF and RPRO fields in dbCommon are flags that indicate when a record
|
||||
* is being processed as a result of an external put (i.e. some server process
|
||||
* calling dbPutField()), ensuring that the record and its successors will
|
||||
* eventually get processed even if they happen to be busy at the time of the
|
||||
* put. From Base-3.16.2 and 7.0.2 the code ensures that all records downstream
|
||||
* from the original are processed even if a busy asynchronous device appears
|
||||
* in the processing chain (this breaks the chain in older versions).
|
||||
*
|
||||
* PUTF - This field is set in dbPutField() prior to it calling dbProcess().
|
||||
* It is normally cleared at the end of processing in recGblFwdLink().
|
||||
* It may also be cleared in dbProcess() if DISA==DISV (scan disabled),
|
||||
* or by the processTarget() function below.
|
||||
*
|
||||
* If PUTF is TRUE before a call to dbProcess(prec), then after it returns
|
||||
* either PACT is TRUE, or PUTF will be FALSE.
|
||||
*
|
||||
* RPRO - This field is set by dbPutField() or by the processTarget() function
|
||||
* below when a record to be processed is found to be busy (PACT==1).
|
||||
* It is normally cleared in recGblFwdLink() when the record is queued
|
||||
* for re-processing, or in dbProcess() if DISA==DISV (scan disabled).
|
||||
*/
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
@@ -43,17 +66,22 @@
|
||||
#include "dbNotify.h"
|
||||
#include "dbScan.h"
|
||||
#include "dbStaticLib.h"
|
||||
#include "dbServer.h"
|
||||
#include "devSup.h"
|
||||
#include "link.h"
|
||||
#include "recGbl.h"
|
||||
#include "recSup.h"
|
||||
#include "special.h"
|
||||
#include "dbDbLink.h"
|
||||
|
||||
|
||||
/***************************** Database Links *****************************/
|
||||
|
||||
/* Forward definition */
|
||||
/* Forward definitions */
|
||||
static lset dbDb_lset;
|
||||
|
||||
static long processTarget(dbCommon *psrc, dbCommon *pdst);
|
||||
|
||||
long dbDbInitLink(struct link *plink, short dbfType)
|
||||
{
|
||||
DBADDR dbaddr;
|
||||
@@ -138,11 +166,7 @@ static long dbDbGetValue(struct link *plink, short dbrType, void *pbuffer,
|
||||
|
||||
/* scan passive records if link is process passive */
|
||||
if (ppv_link->pvlMask & pvlOptPP) {
|
||||
unsigned char pact = precord->pact;
|
||||
|
||||
precord->pact = TRUE;
|
||||
status = dbScanPassive(precord, paddr->precord);
|
||||
precord->pact = pact;
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
@@ -311,22 +335,10 @@ static long dbDbPutValue(struct link *plink, short dbrType,
|
||||
return status;
|
||||
|
||||
if (paddr->pfield == (void *) &pdest->proc ||
|
||||
(ppv_link->pvlMask & pvlOptPP && pdest->scan == 0)) {
|
||||
/* if dbPutField caused asyn record to process */
|
||||
/* ask for reprocessing*/
|
||||
if (pdest->putf) {
|
||||
pdest->rpro = TRUE;
|
||||
} else { /* process dest record with source's PACT true */
|
||||
unsigned char pact;
|
||||
|
||||
if (psrce && psrce->ppn)
|
||||
dbNotifyAdd(psrce, pdest);
|
||||
pact = psrce->pact;
|
||||
psrce->pact = TRUE;
|
||||
status = dbProcess(pdest);
|
||||
psrce->pact = pact;
|
||||
}
|
||||
(ppv_link->pvlMask & pvlOptPP && pdest->scan == 0)) {
|
||||
status = processTarget(psrce, pdest);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -356,3 +368,75 @@ static lset dbDb_lset = {
|
||||
dbDbPutValue, NULL,
|
||||
dbDbScanFwdLink, doLocked
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Process a record if its scan field is passive.
|
||||
*/
|
||||
long dbScanPassive(dbCommon *pfrom, dbCommon *pto)
|
||||
{
|
||||
/* if not passive we're done */
|
||||
if (pto->scan != 0)
|
||||
return 0;
|
||||
|
||||
return processTarget(pfrom, pto);
|
||||
}
|
||||
|
||||
static long processTarget(dbCommon *psrc, dbCommon *pdst)
|
||||
{
|
||||
char context[40] = "";
|
||||
int trace = dbAccessDebugPUTF && *dbLockSetAddrTrace(psrc);
|
||||
long status;
|
||||
epicsUInt8 pact = psrc->pact;
|
||||
|
||||
psrc->pact = TRUE;
|
||||
|
||||
if (psrc && psrc->ppn)
|
||||
dbNotifyAdd(psrc, pdst);
|
||||
|
||||
if (trace && dbServerClient(context, sizeof(context))) {
|
||||
/* No client, use thread name */
|
||||
strncpy(context, epicsThreadGetNameSelf(), sizeof(context));
|
||||
context[sizeof(context) - 1] = 0;
|
||||
}
|
||||
|
||||
if (!pdst->pact) {
|
||||
/* Normal propagation of PUTF from src to dst */
|
||||
if (trace)
|
||||
printf("%s: '%s' -> '%s' with PUTF=%u\n",
|
||||
context, psrc->name, pdst->name, psrc->putf);
|
||||
|
||||
if (pdst->putf)
|
||||
errlogPrintf("Warning: '%s.PUTF' found true with PACT false\n",
|
||||
pdst->name);
|
||||
|
||||
pdst->putf = psrc->putf;
|
||||
}
|
||||
else if (psrc->putf) {
|
||||
/* The dst record is busy (awaiting async reprocessing) and
|
||||
* we were originally triggered by a call to dbPutField(),
|
||||
* so we mark the dst record for reprocessing once the async
|
||||
* completion is over.
|
||||
*/
|
||||
if (trace)
|
||||
printf("%s: '%s' -> Active '%s', setting RPRO=1\n",
|
||||
context, psrc->name, pdst->name);
|
||||
|
||||
pdst->putf = FALSE;
|
||||
pdst->rpro = TRUE;
|
||||
}
|
||||
else {
|
||||
/* The dst record is busy, but we weren't triggered by a call
|
||||
* to dbPutField(). Do nothing.
|
||||
*/
|
||||
if (trace)
|
||||
printf("%s: '%s' -> Active '%s', done\n",
|
||||
context, psrc->name, pdst->name);
|
||||
}
|
||||
|
||||
status = dbProcess(pdst);
|
||||
|
||||
psrc->pact = pact;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -296,6 +296,17 @@ static void scanOnceSetQueueSizeCallFunc(const iocshArgBuf *args)
|
||||
scanOnceSetQueueSize(args[0].ival);
|
||||
}
|
||||
|
||||
/* scanOnceQueueShow */
|
||||
static const iocshArg scanOnceQueueShowArg0 = { "reset",iocshArgInt};
|
||||
static const iocshArg * const scanOnceQueueShowArgs[1] =
|
||||
{&scanOnceQueueShowArg0};
|
||||
static const iocshFuncDef scanOnceQueueShowFuncDef =
|
||||
{"scanOnceQueueShow",1,scanOnceQueueShowArgs};
|
||||
static void scanOnceQueueShowCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
scanOnceQueueShow(args[0].ival);
|
||||
}
|
||||
|
||||
/* scanppl */
|
||||
static const iocshArg scanpplArg0 = { "rate",iocshArgDouble};
|
||||
static const iocshArg * const scanpplArgs[1] = {&scanpplArg0};
|
||||
@@ -335,6 +346,17 @@ static void callbackSetQueueSizeCallFunc(const iocshArgBuf *args)
|
||||
callbackSetQueueSize(args[0].ival);
|
||||
}
|
||||
|
||||
/* callbackQueueShow */
|
||||
static const iocshArg callbackQueueShowArg0 = { "reset", iocshArgInt};
|
||||
static const iocshArg * const callbackQueueShowArgs[1] =
|
||||
{&callbackQueueShowArg0};
|
||||
static const iocshFuncDef callbackQueueShowFuncDef =
|
||||
{"callbackQueueShow",1,callbackQueueShowArgs};
|
||||
static void callbackQueueShowCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
callbackQueueShow(args[0].ival);
|
||||
}
|
||||
|
||||
/* callbackParallelThreads */
|
||||
static const iocshArg callbackParallelThreadsArg0 = { "no of threads", iocshArgInt};
|
||||
static const iocshArg callbackParallelThreadsArg1 = { "priority", iocshArgString};
|
||||
@@ -441,12 +463,14 @@ void dbIocRegister(void)
|
||||
iocshRegister(&dbLockShowLockedFuncDef,dbLockShowLockedCallFunc);
|
||||
|
||||
iocshRegister(&scanOnceSetQueueSizeFuncDef,scanOnceSetQueueSizeCallFunc);
|
||||
iocshRegister(&scanOnceQueueShowFuncDef,scanOnceQueueShowCallFunc);
|
||||
iocshRegister(&scanpplFuncDef,scanpplCallFunc);
|
||||
iocshRegister(&scanpelFuncDef,scanpelCallFunc);
|
||||
iocshRegister(&postEventFuncDef,postEventCallFunc);
|
||||
iocshRegister(&scanpiolFuncDef,scanpiolCallFunc);
|
||||
|
||||
iocshRegister(&callbackSetQueueSizeFuncDef,callbackSetQueueSizeCallFunc);
|
||||
iocshRegister(&callbackQueueShowFuncDef,callbackQueueShowCallFunc);
|
||||
iocshRegister(&callbackParallelThreadsFuncDef,callbackParallelThreadsCallFunc);
|
||||
|
||||
/* Needed before callback system is initialized */
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (c) 2016 UChicago Argonne LLC, as Operator of Argonne
|
||||
* 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.
|
||||
\*************************************************************************/
|
||||
/* dbJLink.c */
|
||||
|
||||
@@ -25,19 +25,33 @@
|
||||
#include "dbLock.h"
|
||||
#include "dbStaticLib.h"
|
||||
#include "link.h"
|
||||
#include "epicsExport.h"
|
||||
|
||||
#define IFDEBUG(n) if(parser->parse_debug)
|
||||
epicsShareDef int dbJLinkDebug = 0;
|
||||
epicsExportAddress(int, dbJLinkDebug);
|
||||
|
||||
#define IFDEBUG(n) if (dbJLinkDebug >= (n))
|
||||
|
||||
typedef struct parseContext {
|
||||
jlink *pjlink;
|
||||
jlink *product;
|
||||
short dbfType;
|
||||
short jsonDepth;
|
||||
unsigned key_is_link:1;
|
||||
unsigned parse_debug:1;
|
||||
unsigned lset_debug:1;
|
||||
} parseContext;
|
||||
|
||||
epicsShareDef const char *jlif_result_name[2] = {
|
||||
"jlif_stop",
|
||||
"jlif_continue",
|
||||
};
|
||||
|
||||
epicsShareDef const char *jlif_key_result_name[5] = {
|
||||
"jlif_key_stop",
|
||||
"jlif_key_continue",
|
||||
"jlif_key_child_inlink",
|
||||
"jlif_key_child_outlink",
|
||||
"jlif_key_child_fwdlink"
|
||||
};
|
||||
|
||||
#define CALL_OR_STOP(routine) !(routine) ? jlif_stop : (routine)
|
||||
|
||||
static int dbjl_return(parseContext *parser, jlif_result result) {
|
||||
@@ -45,8 +59,8 @@ static int dbjl_return(parseContext *parser, jlif_result result) {
|
||||
|
||||
IFDEBUG(10) {
|
||||
printf("dbjl_return(%s@%p, %d)\t", pjlink ? pjlink->pif->name : "", pjlink, result);
|
||||
printf(" jsonDepth=%d, parseDepth=%d, key_is_link=%d\n",
|
||||
parser->jsonDepth, pjlink ? pjlink->parseDepth : 0, parser->key_is_link);
|
||||
printf(" jsonDepth=%d, parseDepth=%d, dbfType=%d\n",
|
||||
parser->jsonDepth, pjlink ? pjlink->parseDepth : 0, parser->dbfType);
|
||||
}
|
||||
|
||||
if (result == jlif_stop && pjlink) {
|
||||
@@ -59,6 +73,9 @@ static int dbjl_return(parseContext *parser, jlif_result result) {
|
||||
pjlink->pif->free_jlink(pjlink);
|
||||
}
|
||||
|
||||
IFDEBUG(10)
|
||||
printf(" returning %d %s\n", result,
|
||||
result == jlif_stop ? "*** STOP ***" : "Continue");
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -68,8 +85,8 @@ static int dbjl_value(parseContext *parser, jlif_result result) {
|
||||
|
||||
IFDEBUG(10) {
|
||||
printf("dbjl_value(%s@%p, %d)\t", pjlink ? pjlink->pif->name : "", pjlink, result);
|
||||
printf(" jsonDepth=%d, parseDepth=%d, key_is_link=%d\n",
|
||||
parser->jsonDepth, pjlink ? pjlink->parseDepth : 0, parser->key_is_link);
|
||||
printf(" jsonDepth=%d, parseDepth=%d, dbfType=%d\n",
|
||||
parser->jsonDepth, pjlink ? pjlink->parseDepth : 0, parser->dbfType);
|
||||
}
|
||||
|
||||
if (result == jlif_stop || pjlink->parseDepth > 0)
|
||||
@@ -81,7 +98,6 @@ static int dbjl_value(parseContext *parser, jlif_result result) {
|
||||
} else if (parent->pif->end_child) {
|
||||
parent->pif->end_child(parent, pjlink);
|
||||
}
|
||||
pjlink->debug = 0;
|
||||
|
||||
parser->pjlink = parent;
|
||||
|
||||
@@ -159,29 +175,46 @@ static int dbjl_start_map(void *ctx) {
|
||||
if (!pjlink) {
|
||||
IFDEBUG(10) {
|
||||
printf("dbjl_start_map(NULL)\t");
|
||||
printf(" jsonDepth=%d, parseDepth=00, key_is_link=%d\n",
|
||||
parser->jsonDepth, parser->key_is_link);
|
||||
printf(" jsonDepth=%d, parseDepth=00, dbfType=%d\n",
|
||||
parser->jsonDepth, parser->dbfType);
|
||||
}
|
||||
|
||||
assert(parser->jsonDepth == 0);
|
||||
parser->jsonDepth++;
|
||||
parser->key_is_link = 1;
|
||||
return jlif_continue; /* Opening '{' */
|
||||
}
|
||||
|
||||
IFDEBUG(10) {
|
||||
printf("dbjl_start_map(%s@%p)\t", pjlink ? pjlink->pif->name : "", pjlink);
|
||||
printf(" jsonDepth=%d, parseDepth=%d, key_is_link=%d\n",
|
||||
parser->jsonDepth, pjlink ? pjlink->parseDepth : 0, parser->key_is_link);
|
||||
printf(" jsonDepth=%d, parseDepth=%d, dbfType=%d\n",
|
||||
parser->jsonDepth, pjlink ? pjlink->parseDepth : 0, parser->dbfType);
|
||||
}
|
||||
|
||||
pjlink->parseDepth++;
|
||||
parser->jsonDepth++;
|
||||
|
||||
result = CALL_OR_STOP(pjlink->pif->parse_start_map)(pjlink);
|
||||
if (result == jlif_key_child_link) {
|
||||
parser->key_is_link = 1;
|
||||
switch (result) {
|
||||
case jlif_key_child_inlink:
|
||||
parser->dbfType = DBF_INLINK;
|
||||
result = jlif_continue;
|
||||
break;
|
||||
case jlif_key_child_outlink:
|
||||
parser->dbfType = DBF_OUTLINK;
|
||||
result = jlif_continue;
|
||||
break;
|
||||
case jlif_key_child_fwdlink:
|
||||
parser->dbfType = DBF_FWDLINK;
|
||||
result = jlif_continue;
|
||||
break;
|
||||
case jlif_key_stop:
|
||||
case jlif_key_continue:
|
||||
break;
|
||||
default:
|
||||
errlogPrintf("dbJLinkInit: Bad return %d from '%s'::parse_start_map()\n",
|
||||
result, pjlink->pif->name);
|
||||
result = jlif_stop;
|
||||
break;
|
||||
}
|
||||
|
||||
IFDEBUG(10)
|
||||
@@ -196,8 +229,9 @@ static int dbjl_map_key(void *ctx, const unsigned char *key, size_t len) {
|
||||
char *link_name;
|
||||
linkSup *linkSup;
|
||||
jlif *pjlif;
|
||||
jlink *child;
|
||||
|
||||
if (!parser->key_is_link) {
|
||||
if (parser->dbfType == 0) {
|
||||
if (!pjlink) {
|
||||
errlogPrintf("dbJLinkInit: Illegal second link key '%.*s'\n",
|
||||
(int) len, key);
|
||||
@@ -207,8 +241,8 @@ static int dbjl_map_key(void *ctx, const unsigned char *key, size_t len) {
|
||||
IFDEBUG(10) {
|
||||
printf("dbjl_map_key(%s@%p, \"%.*s\")\t",
|
||||
pjlink->pif->name, pjlink, (int) len, key);
|
||||
printf(" jsonDepth=%d, parseDepth=%d, key_is_link=%d\n",
|
||||
parser->jsonDepth, pjlink ? pjlink->parseDepth : 0, parser->key_is_link);
|
||||
printf(" jsonDepth=%d, parseDepth=%d, dbfType=%d\n",
|
||||
parser->jsonDepth, pjlink ? pjlink->parseDepth : 0, parser->dbfType);
|
||||
}
|
||||
|
||||
assert(pjlink->parseDepth > 0);
|
||||
@@ -219,8 +253,8 @@ static int dbjl_map_key(void *ctx, const unsigned char *key, size_t len) {
|
||||
|
||||
IFDEBUG(10) {
|
||||
printf("dbjl_map_key(NULL, \"%.*s\")\t", (int) len, key);
|
||||
printf(" jsonDepth=%d, parseDepth=00, key_is_link=%d\n",
|
||||
parser->jsonDepth, parser->key_is_link);
|
||||
printf(" jsonDepth=%d, parseDepth=00, dbfType=%d\n",
|
||||
parser->jsonDepth, parser->dbfType);
|
||||
}
|
||||
|
||||
link_name = dbmfStrndup((const char *) key, len);
|
||||
@@ -241,27 +275,35 @@ static int dbjl_map_key(void *ctx, const unsigned char *key, size_t len) {
|
||||
return dbjl_return(parser, jlif_stop);
|
||||
}
|
||||
|
||||
dbmfFree(link_name);
|
||||
|
||||
pjlink = pjlif->alloc_jlink(parser->dbfType);
|
||||
if (!pjlink) {
|
||||
errlogPrintf("dbJLinkInit: Out of memory\n");
|
||||
child = pjlif->alloc_jlink(parser->dbfType);
|
||||
if (!child) {
|
||||
errlogPrintf("dbJLinkInit: Link type '%s' allocation failed. \n",
|
||||
link_name);
|
||||
dbmfFree(link_name);
|
||||
return dbjl_return(parser, jlif_stop);
|
||||
}
|
||||
pjlink->pif = pjlif;
|
||||
pjlink->parent = NULL;
|
||||
pjlink->parseDepth = 0;
|
||||
pjlink->debug = !!parser->lset_debug;
|
||||
|
||||
child->pif = pjlif;
|
||||
child->parseDepth = 0;
|
||||
child->debug = 0;
|
||||
|
||||
if (parser->pjlink) {
|
||||
/* We're starting a child link, save its parent */
|
||||
pjlink->parent = parser->pjlink;
|
||||
child->parent = pjlink;
|
||||
|
||||
if (pjlink->pif->start_child)
|
||||
pjlink->pif->start_child(pjlink, child);
|
||||
}
|
||||
parser->pjlink = pjlink;
|
||||
parser->key_is_link = 0;
|
||||
else
|
||||
child->parent = NULL;
|
||||
|
||||
parser->pjlink = child;
|
||||
parser->dbfType = 0;
|
||||
|
||||
dbmfFree(link_name);
|
||||
|
||||
IFDEBUG(8)
|
||||
printf("dbjl_map_key: New %s@%p\n", pjlink ? pjlink->pif->name : "", pjlink);
|
||||
printf("dbjl_map_key: New %s@%p\n", child ? child->pif->name : "", child);
|
||||
|
||||
return jlif_continue;
|
||||
}
|
||||
@@ -274,9 +316,9 @@ static int dbjl_end_map(void *ctx) {
|
||||
IFDEBUG(10) {
|
||||
printf("dbjl_end_map(%s@%p)\t",
|
||||
pjlink ? pjlink->pif->name : "NULL", pjlink);
|
||||
printf(" jsonDepth=%d, parseDepth=%d, key_is_link=%d\n",
|
||||
printf(" jsonDepth=%d, parseDepth=%d, dbfType=%d\n",
|
||||
parser->jsonDepth, pjlink ? pjlink->parseDepth : 0,
|
||||
parser->key_is_link);
|
||||
parser->dbfType);
|
||||
}
|
||||
|
||||
parser->jsonDepth--;
|
||||
@@ -298,8 +340,8 @@ static int dbjl_start_array(void *ctx) {
|
||||
|
||||
IFDEBUG(10) {
|
||||
printf("dbjl_start_array(%s@%p)\t", pjlink ? pjlink->pif->name : "", pjlink);
|
||||
printf(" jsonDepth=%d, parseDepth=%d, key_is_link=%d\n",
|
||||
parser->jsonDepth, pjlink ? pjlink->parseDepth : 0, parser->key_is_link);
|
||||
printf(" jsonDepth=%d, parseDepth=%d, dbfType=%d\n",
|
||||
parser->jsonDepth, pjlink ? pjlink->parseDepth : 0, parser->dbfType);
|
||||
}
|
||||
|
||||
assert(pjlink);
|
||||
@@ -316,8 +358,8 @@ static int dbjl_end_array(void *ctx) {
|
||||
|
||||
IFDEBUG(10) {
|
||||
printf("dbjl_end_array(%s@%p)\t", pjlink ? pjlink->pif->name : "", pjlink);
|
||||
printf(" jsonDepth=%d, parseDepth=%d, key_is_link=%d\n",
|
||||
parser->jsonDepth, pjlink ? pjlink->parseDepth : 0, parser->key_is_link);
|
||||
printf(" jsonDepth=%d, parseDepth=%d, dbfType=%d\n",
|
||||
parser->jsonDepth, pjlink ? pjlink->parseDepth : 0, parser->dbfType);
|
||||
}
|
||||
|
||||
assert(pjlink);
|
||||
@@ -335,7 +377,7 @@ static yajl_callbacks dbjl_callbacks = {
|
||||
};
|
||||
|
||||
long dbJLinkParse(const char *json, size_t jlen, short dbfType,
|
||||
jlink **ppjlink, unsigned opts)
|
||||
jlink **ppjlink)
|
||||
{
|
||||
parseContext context, *parser = &context;
|
||||
yajl_alloc_funcs dbjl_allocs;
|
||||
@@ -347,17 +389,14 @@ long dbJLinkParse(const char *json, size_t jlen, short dbfType,
|
||||
parser->product = NULL;
|
||||
parser->dbfType = dbfType;
|
||||
parser->jsonDepth = 0;
|
||||
parser->key_is_link = 0;
|
||||
parser->parse_debug = !!(opts&LINK_DEBUG_JPARSE);
|
||||
parser->lset_debug = !!(opts&LINK_DEBUG_LSET);
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("dbJLinkInit(\"%.*s\", %d, %p)\n",
|
||||
(int) jlen, json, dbfType, ppjlink);
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("dbJLinkInit: jsonDepth=%d, key_is_link=%d\n",
|
||||
parser->jsonDepth, parser->key_is_link);
|
||||
printf("dbJLinkInit: jsonDepth=%d, dbfType=%d\n",
|
||||
parser->jsonDepth, parser->dbfType);
|
||||
|
||||
yajl_set_default_alloc_funcs(&dbjl_allocs);
|
||||
yh = yajl_alloc(&dbjl_callbacks, &dbjl_allocs, parser);
|
||||
@@ -365,8 +404,14 @@ long dbJLinkParse(const char *json, size_t jlen, short dbfType,
|
||||
return S_db_noMemory;
|
||||
|
||||
ys = yajl_parse(yh, (const unsigned char *) json, jlen);
|
||||
if (ys == yajl_status_ok)
|
||||
IFDEBUG(10)
|
||||
printf("dbJLinkInit: yajl_parse() returned %d\n", ys);
|
||||
|
||||
if (ys == yajl_status_ok) {
|
||||
ys = yajl_complete_parse(yh);
|
||||
IFDEBUG(10)
|
||||
printf("dbJLinkInit: yajl_complete_parse() returned %d\n", ys);
|
||||
}
|
||||
|
||||
switch (ys) {
|
||||
unsigned char *err;
|
||||
@@ -378,6 +423,9 @@ long dbJLinkParse(const char *json, size_t jlen, short dbfType,
|
||||
break;
|
||||
|
||||
case yajl_status_error:
|
||||
IFDEBUG(10)
|
||||
printf(" jsonDepth=%d, product=%p, pjlink=%p\n",
|
||||
parser->jsonDepth, parser->product, parser->pjlink);
|
||||
err = yajl_get_error(yh, 1, (const unsigned char *) json, jlen);
|
||||
errlogPrintf("dbJLinkInit: %s\n", err);
|
||||
yajl_free_error(yh, err);
|
||||
@@ -389,18 +437,24 @@ long dbJLinkParse(const char *json, size_t jlen, short dbfType,
|
||||
}
|
||||
|
||||
yajl_free(yh);
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("dbJLinkInit: returning status=0x%lx\n\n",
|
||||
status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
long dbJLinkInit(struct link *plink)
|
||||
{
|
||||
jlink *pjlink;
|
||||
|
||||
assert(plink);
|
||||
pjlink = plink->value.json.jlink;
|
||||
|
||||
if (pjlink)
|
||||
plink->lset = pjlink->pif->get_lset(pjlink);
|
||||
if (plink->type == JSON_LINK) {
|
||||
jlink *pjlink = plink->value.json.jlink;
|
||||
|
||||
if (pjlink)
|
||||
plink->lset = pjlink->pif->get_lset(pjlink);
|
||||
}
|
||||
|
||||
dbLinkOpen(plink);
|
||||
return 0;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (c) 2016 UChicago Argonne LLC, as Operator of Argonne
|
||||
* 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.
|
||||
\*************************************************************************/
|
||||
/* dbJLink.h */
|
||||
|
||||
@@ -21,12 +21,16 @@ typedef enum {
|
||||
jlif_continue = 1
|
||||
} jlif_result;
|
||||
|
||||
epicsShareExtern const char *jlif_result_name[2];
|
||||
|
||||
typedef enum {
|
||||
jlif_key_stop = jlif_stop,
|
||||
jlif_key_continue = jlif_continue,
|
||||
jlif_key_child_link
|
||||
jlif_key_child_inlink, jlif_key_child_outlink, jlif_key_child_fwdlink
|
||||
} jlif_key_result;
|
||||
|
||||
epicsShareExtern const char *jlif_key_result_name[5];
|
||||
|
||||
struct link;
|
||||
struct lset;
|
||||
struct jlif;
|
||||
@@ -35,7 +39,7 @@ typedef struct jlink {
|
||||
struct jlif *pif; /* Link methods */
|
||||
struct jlink *parent; /* NULL for top-level links */
|
||||
int parseDepth; /* Used by parser, unused afterwards */
|
||||
unsigned debug:1; /* set by caller of jlif operations to request debug output to console */
|
||||
unsigned debug:1; /* Set to request debug output to console */
|
||||
/* Link types extend or embed this structure for private storage */
|
||||
} jlink;
|
||||
|
||||
@@ -72,8 +76,9 @@ typedef struct jlif {
|
||||
/* Optional, parser saw a string value */
|
||||
|
||||
jlif_key_result (*parse_start_map)(jlink *);
|
||||
/* Optional, parser saw an open-brace '{'. Return jlif_key_child_link
|
||||
* to expect a child link next (extra key/value pairs may follow).
|
||||
/* Optional, parser saw an open-brace '{'. Return jlif_key_child_inlink,
|
||||
* jlif_key_child_outlink, or jlif_key_child_fwdlink to expect a child
|
||||
* link next (extra key/value pairs may follow)
|
||||
*/
|
||||
|
||||
jlif_result (*parse_map_key)(jlink *, const char *key, size_t len);
|
||||
@@ -90,7 +95,8 @@ typedef struct jlif {
|
||||
|
||||
void (*end_child)(jlink *parent, jlink *child);
|
||||
/* Optional, called with pointer to the new child link after
|
||||
* parse_start_map() returned jlif_key_child_link */
|
||||
* the child link has finished parsing successfully
|
||||
*/
|
||||
|
||||
struct lset* (*get_lset)(const jlink *);
|
||||
/* Required, return lset for this link instance */
|
||||
@@ -98,7 +104,7 @@ typedef struct jlif {
|
||||
void (*report)(const jlink *, int level, int indent);
|
||||
/* Optional, print status information about this link instance, then
|
||||
* if (level > 0) print a link identifier (at indent+2) and call
|
||||
* dbJLinkReport(child, level-1, indent+4)
|
||||
* dbJLinkReport(child, level-1, indent+4)
|
||||
* for each child.
|
||||
*/
|
||||
|
||||
@@ -107,13 +113,19 @@ typedef struct jlif {
|
||||
* Stop immediately and return status if non-zero.
|
||||
*/
|
||||
|
||||
void (*start_child)(jlink *parent, jlink *child);
|
||||
/* Optional, called with pointer to the new child link after
|
||||
* parse_start_map() returned a jlif_key_child_link value and
|
||||
* the child link has been allocated (but not parsed yet)
|
||||
*/
|
||||
|
||||
/* Link types must NOT extend this table with their own routines,
|
||||
* this space is reserved for extensions to the jlink interface.
|
||||
*/
|
||||
} jlif;
|
||||
|
||||
epicsShareFunc long dbJLinkParse(const char *json, size_t len, short dbfType,
|
||||
jlink **ppjlink, unsigned opts);
|
||||
jlink **ppjlink);
|
||||
epicsShareFunc long dbJLinkInit(struct link *plink);
|
||||
|
||||
epicsShareFunc void dbJLinkFree(jlink *);
|
||||
@@ -130,4 +142,3 @@ epicsShareFunc long dbJLinkMapAll(char *recname, jlink_map_fn rtn, void *ctx);
|
||||
#endif
|
||||
|
||||
#endif /* INC_dbJLink_H */
|
||||
|
||||
|
||||
@@ -265,8 +265,19 @@ int dbIsLinkConnected(const struct link *plink)
|
||||
{
|
||||
lset *plset = plink->lset;
|
||||
|
||||
if (!plset || !plset->isConnected)
|
||||
if (!plset)
|
||||
return FALSE;
|
||||
if (!plset->isVolatile)
|
||||
return TRUE;
|
||||
|
||||
if (!plset->isConnected) {
|
||||
struct dbCommon *precord = plink->precord;
|
||||
|
||||
errlogPrintf("dbLink: Link type for '%s.%s' is volatile but has no"
|
||||
" lset::isConnected() method\n",
|
||||
precord->name, dbLinkFieldName(plink));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return plset->isConnected(plink);
|
||||
}
|
||||
|
||||
@@ -27,54 +27,337 @@ extern "C" {
|
||||
|
||||
struct dbLocker;
|
||||
|
||||
/** @file dbLink.h
|
||||
* @brief Link Support API
|
||||
*
|
||||
* Link support run-time API, all link types provide an lset which is used by
|
||||
* the IOC database to control and operate the link. This file also declares the
|
||||
* dbLink routines that IOC, record and device code can call to perform link
|
||||
* operations.
|
||||
*/
|
||||
|
||||
/** @brief callback routine for locked link operations
|
||||
*
|
||||
* Called by the lset::doLocked method to permit multiple link operations
|
||||
* while the link instance is locked.
|
||||
*
|
||||
* @param plink the link
|
||||
* @param priv context for the callback routine
|
||||
*/
|
||||
typedef long (*dbLinkUserCallback)(struct link *plink, void *priv);
|
||||
|
||||
/** @brief Link Support Entry Table
|
||||
*
|
||||
* This structure provides information about and methods for an individual link
|
||||
* type. A pointer to this structure is included in every link's lset field, and
|
||||
* is used to perform operations on the link. For JSON links the pointer is
|
||||
* obtained by calling pjlink->pif->get_lset() at link initialization time,
|
||||
* immediately before calling dbLinkOpen() to activate the link.
|
||||
*/
|
||||
typedef struct lset {
|
||||
/* Characteristics of the link type */
|
||||
|
||||
/** @brief link constancy
|
||||
*
|
||||
* 1 means this is a constant link type whose value doesn't change.
|
||||
* The link's value will be obtained using one of the methods loadScalar,
|
||||
* loadLS or loadArray.
|
||||
*/
|
||||
const unsigned isConstant:1;
|
||||
|
||||
/** @brief link volatility
|
||||
*
|
||||
* 0 means the link is always connected.
|
||||
*/
|
||||
const unsigned isVolatile:1;
|
||||
|
||||
/* Activation */
|
||||
/** @brief activate link
|
||||
*
|
||||
* Optional, called whenever a JSON link is initialized or added at runtime.
|
||||
*
|
||||
* @param plink the link
|
||||
*/
|
||||
void (*openLink)(struct link *plink);
|
||||
|
||||
/* Destructor */
|
||||
/** @brief deactivate link
|
||||
*
|
||||
* Optional, called whenever a link address is changed at runtime, or the
|
||||
* IOC is shutting down.
|
||||
*
|
||||
* @param locker
|
||||
* @param plink the link
|
||||
*/
|
||||
void (*removeLink)(struct dbLocker *locker, struct link *plink);
|
||||
|
||||
/* Const init, data type hinting */
|
||||
/* Constant link initialization and data type hinting */
|
||||
|
||||
/** @brief load constant scalar from link type
|
||||
*
|
||||
* Usually called during IOC initialization, constant link types must copy a
|
||||
* scalar value of the indicated data type to the buffer provided and return
|
||||
* 0. A non-constant link type can use this method call as an early hint
|
||||
* that subsequent calls to dbGetLink() will request scalar data of the
|
||||
* indicated type, although the type might change.
|
||||
*
|
||||
* @param plink the link
|
||||
* @param dbrType data type code
|
||||
* @param pbuffer where to put the value
|
||||
* @returns 0 if a value was loaded, non-zero otherwise
|
||||
*/
|
||||
long (*loadScalar)(struct link *plink, short dbrType, void *pbuffer);
|
||||
|
||||
/** @brief load constant long string from link type
|
||||
*
|
||||
* Usually called during IOC initialization, constant link types must copy a
|
||||
* nil-terminated string up to size characters long to the buffer provided,
|
||||
* and write the length of that string to the plen location. A non-constant
|
||||
* link type can use this as an early hint that subsequent calls to
|
||||
* dbGetLink() will request long string data, although this might change.
|
||||
*
|
||||
* @param plink the link
|
||||
* @param pbuffer where to put the string
|
||||
* @param size length of pbuffer in chars
|
||||
* @param plen set to number of chars written
|
||||
* @returns status value
|
||||
*/
|
||||
long (*loadLS)(struct link *plink, char *pbuffer, epicsUInt32 size,
|
||||
epicsUInt32 *plen);
|
||||
|
||||
/** @brief load constant array from link type
|
||||
*
|
||||
* Usually called during IOC initialization, constant link types must copy
|
||||
* an array value of the indicated data type to the buffer provided, update
|
||||
* the pnRequest location to indicate how many elements were loaded, and
|
||||
* return 0. A non-constant link type can use this method call as an early
|
||||
* hint that subsequent calls to dbGetLink() will request array data of the
|
||||
* indicated type and max size, although the request might change.
|
||||
*
|
||||
* @param plink the link
|
||||
* @param dbrType data type code
|
||||
* @param pbuffer where to put the value
|
||||
* @param pnRequest Max elements on entry, actual on exit
|
||||
* @returns 0 if elements were loaded, non-zero otherwise
|
||||
*/
|
||||
long (*loadArray)(struct link *plink, short dbrType, void *pbuffer,
|
||||
long *pnRequest);
|
||||
|
||||
/* Metadata */
|
||||
|
||||
/** @brief return link connection status
|
||||
*
|
||||
* Return an indication whether this link is connected or not. This routine
|
||||
* is polled by the calcout and some external record types. Not required for
|
||||
* non-volatile link types, which are by definition always connected.
|
||||
*
|
||||
* @param plink the link
|
||||
* @returns 1 if connected, 0 if disconnected
|
||||
*/
|
||||
int (*isConnected)(const struct link *plink);
|
||||
|
||||
/** @brief get data type of link destination
|
||||
*
|
||||
* Called on both input and output links by long string support code to
|
||||
* decide whether to use DBR_CHAR/DBR_UCHAR or DBR_STRING for a subsequent
|
||||
* dbPutLink() or dbGetLink() call. Optional, but if not provided long
|
||||
* strings cannot be transported over this link type, and no warning or
|
||||
* error will appear to explain why. Not required for constant link types.
|
||||
*
|
||||
* @param plink the link
|
||||
* @returns DBF_* type code, or -1 on error/disconnected link
|
||||
*/
|
||||
int (*getDBFtype)(const struct link *plink);
|
||||
long (*getElements)(const struct link *plink, long *nelements);
|
||||
|
||||
/* Get data */
|
||||
|
||||
/** @brief get array size of an input link
|
||||
*
|
||||
* Called on input links by the compress record type for memory allocation
|
||||
* purposes, before using the dbGetLink() routine to fetch the actual
|
||||
* array data.
|
||||
*
|
||||
* @param plink the link
|
||||
* @param pnElements where to put the answer
|
||||
* @returns status value
|
||||
*/
|
||||
long (*getElements)(const struct link *plink, long *pnElements);
|
||||
|
||||
/** @brief get value from an input link
|
||||
*
|
||||
* Called to fetch data from the link, which must be converted into the
|
||||
* given data type and placed in the buffer indicated. The actual number of
|
||||
* elements retrieved should be updated in the pnRequest location. If this
|
||||
* method returns an error status value, the link's record will be placed
|
||||
* into an Invalid severity / Link Alarm state by the dbGetLink() routine
|
||||
* that calls this method.
|
||||
*
|
||||
* @param plink the link
|
||||
* @param dbrType data type code
|
||||
* @param pbuffer where to put the value
|
||||
* @param pnRequest max elements on entry, actual on exit
|
||||
* @returns status value
|
||||
*/
|
||||
long (*getValue)(struct link *plink, short dbrType, void *pbuffer,
|
||||
long *pnRequest);
|
||||
|
||||
/** @brief get the control range for an output link
|
||||
*
|
||||
* Called to fetch the control range for the link target, as a pair of
|
||||
* double values for the lowest and highest values that the target will
|
||||
* accept. This method is not used at all by the IOC or built-in record
|
||||
* types, although external record types may require it.
|
||||
*
|
||||
* @param plink the link
|
||||
* @param lo lowest accepted value
|
||||
* @param hi highest accepted value
|
||||
* @returns status value
|
||||
*/
|
||||
long (*getControlLimits)(const struct link *plink, double *lo, double *hi);
|
||||
|
||||
/** @brief get the display range from an input link
|
||||
*
|
||||
* Called to fetch the display range for an input link target, as a pair of
|
||||
* double values for the lowest and highest values that the PV expects to
|
||||
* return. This method is used by several built-in record types to obtain
|
||||
* the display range for their generic input links.
|
||||
*
|
||||
* @param plink the link
|
||||
* @param lo lowest accepted value
|
||||
* @param hi highest accepted value
|
||||
* @returns status value
|
||||
*/
|
||||
long (*getGraphicLimits)(const struct link *plink, double *lo, double *hi);
|
||||
|
||||
/** @brief get the alarm limits from an input link
|
||||
*
|
||||
* Called to fetch the alarm limits for an input link target, as four
|
||||
* double values for the warning and alarm levels that the PV checks its
|
||||
* value against. This method is used by several built-in record types to
|
||||
* obtain the alarm limits for their generic input links.
|
||||
*
|
||||
* @param plink the link
|
||||
* @param lolo low alarm value
|
||||
* @param lo low warning value
|
||||
* @param hi high warning value
|
||||
* @param hihi high alarm value
|
||||
* @returns status value
|
||||
*/
|
||||
long (*getAlarmLimits)(const struct link *plink, double *lolo, double *lo,
|
||||
double *hi, double *hihi);
|
||||
|
||||
/** @brief get the precision from an input link
|
||||
*
|
||||
* Called to fetch the precision for an input link target. This method is
|
||||
* used by several built-in record types to obtain the precision for their
|
||||
* generic input links.
|
||||
*
|
||||
* @param plink the link
|
||||
* @param precision where to put the answer
|
||||
* @returns status value
|
||||
*/
|
||||
long (*getPrecision)(const struct link *plink, short *precision);
|
||||
|
||||
/** @brief get the units string from an input link
|
||||
*
|
||||
* Called to fetch the units string for an input link target. This method is
|
||||
* used by several built-in record types to obtain the units string for
|
||||
* their generic input links.
|
||||
*
|
||||
* @param plink the link
|
||||
* @param units where to put the answer
|
||||
* @param unitsSize buffer size for the answer
|
||||
* @returns status value
|
||||
*/
|
||||
long (*getUnits)(const struct link *plink, char *units, int unitsSize);
|
||||
|
||||
/** @brief get the alarm condition from an input link
|
||||
*
|
||||
* Called to fetch the alarm status and severity for an input link target.
|
||||
* Either status or severity pointers may be NULL when that value is not
|
||||
* needed by the calling code. This method is used by several built-in
|
||||
* record types to obtain the alarm condition for their generic input links.
|
||||
*
|
||||
* @param plink the link
|
||||
* @param status where to put the alarm status (or NULL)
|
||||
* @param severity where to put the severity (or NULL)
|
||||
* @returns status value
|
||||
*/
|
||||
long (*getAlarm)(const struct link *plink, epicsEnum16 *status,
|
||||
epicsEnum16 *severity);
|
||||
|
||||
/** @brief get the time-stamp from an input link
|
||||
*
|
||||
* Called to fetch the time-stamp for an input link target. This method is
|
||||
* used by many built-in device supports to obtain the precision for their
|
||||
* generic input links.
|
||||
*
|
||||
* @param plink the link
|
||||
* @param pstamp where to put the answer
|
||||
* @returns status value
|
||||
*/
|
||||
long (*getTimeStamp)(const struct link *plink, epicsTimeStamp *pstamp);
|
||||
|
||||
/* Put data */
|
||||
|
||||
/** @brief put a value to an output link
|
||||
*
|
||||
* Called to send nRequest elements of type dbrType found at pbuffer to an
|
||||
* output link target.
|
||||
*
|
||||
* @param plink the link
|
||||
* @param dbrType data type code
|
||||
* @param pbuffer where to put the value
|
||||
* @param nRequest number of elements to send
|
||||
* @returns status value
|
||||
*/
|
||||
long (*putValue)(struct link *plink, short dbrType,
|
||||
const void *pbuffer, long nRequest);
|
||||
|
||||
/** @brief put a value to an output link with asynchronous completion
|
||||
*
|
||||
* Called to send nRequest elements of type dbrType found at pbuffer to an
|
||||
* output link target. If the return status is zero, the link type will
|
||||
* later indicate the put has completed by calling dbLinkAsyncComplete()
|
||||
* from a background thread, which will be used to continue the record
|
||||
* process operation from where it left off.
|
||||
*
|
||||
* @param plink the link
|
||||
* @param dbrType data type code
|
||||
* @param pbuffer where to put the value
|
||||
* @param nRequest number of elements to send
|
||||
* @returns status value
|
||||
*/
|
||||
long (*putAsync)(struct link *plink, short dbrType,
|
||||
const void *pbuffer, long nRequest);
|
||||
|
||||
/* Process */
|
||||
|
||||
/** @brief trigger processing of a forward link
|
||||
*
|
||||
* Called to trigger processing of the record pointed to by a forward link.
|
||||
* This routine is optional, but if not provided no warning message will be
|
||||
* shown when called by dbScanFwdLink(). JSON link types that do not support
|
||||
* this operation should return NULL from their jlif::alloc_jlink() method
|
||||
* if it gets called with a dbfType of DBF_FWDLINK.
|
||||
*
|
||||
* @param plink the link
|
||||
*/
|
||||
void (*scanForward)(struct link *plink);
|
||||
|
||||
/* Atomicity */
|
||||
|
||||
/** @brief execute a callback routine with link locked
|
||||
*
|
||||
* Called on an input link when multiple link attributes need to be fetched
|
||||
* in an atomic fashion. The link type must call the callback routine and
|
||||
* prevent any background I/O from updating any cached link data until that
|
||||
* routine returns. This method is used by most input device support to
|
||||
* fetch the timestamp along with the value when the record's TSE field is
|
||||
* set to epicsTimeEventDeviceTime.
|
||||
*
|
||||
* @param plink the link
|
||||
* @param rtn routine to execute
|
||||
* @returns status value
|
||||
*/
|
||||
long (*doLocked)(struct link *plink, dbLinkUserCallback rtn, void *priv);
|
||||
} lset;
|
||||
|
||||
@@ -99,7 +382,7 @@ epicsShareFunc long dbLoadLink(struct link *plink, short dbrType,
|
||||
epicsShareFunc long dbLoadLinkArray(struct link *, short dbrType, void *pbuffer,
|
||||
long *pnRequest);
|
||||
|
||||
epicsShareFunc long dbGetNelements(const struct link *plink, long *nelements);
|
||||
epicsShareFunc long dbGetNelements(const struct link *plink, long *pnElements);
|
||||
epicsShareFunc int dbIsLinkConnected(const struct link *plink); /* 0 or 1 */
|
||||
epicsShareFunc int dbGetLinkDBFtype(const struct link *plink);
|
||||
epicsShareFunc long dbTryGetLink(struct link *, short dbrType, void *pbuffer,
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
#ifndef INCdbLockh
|
||||
#define INCdbLockh
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "ellLib.h"
|
||||
#include "shareLib.h"
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "cantProceed.h"
|
||||
#include "dbDefs.h"
|
||||
#include "ellLib.h"
|
||||
#include "epicsAtomic.h"
|
||||
#include "epicsEvent.h"
|
||||
#include "epicsMutex.h"
|
||||
#include "epicsPrint.h"
|
||||
@@ -63,6 +64,7 @@ static volatile enum ctl scanCtl;
|
||||
static int onceQueueSize = 1000;
|
||||
static epicsEventId onceSem;
|
||||
static epicsRingBytesId onceQ;
|
||||
static int onceQOverruns = 0;
|
||||
static epicsThreadId onceTaskId;
|
||||
static void *exitOnce;
|
||||
|
||||
@@ -676,6 +678,7 @@ int scanOnceCallback(struct dbCommon *precord, once_complete cb, void *usr)
|
||||
if (!pushOK) {
|
||||
if (newOverflow) errlogPrintf("scanOnce: Ring buffer overflow\n");
|
||||
newOverflow = FALSE;
|
||||
epicsAtomicIncrIntT(&onceQOverruns);
|
||||
} else {
|
||||
newOverflow = TRUE;
|
||||
}
|
||||
@@ -722,6 +725,40 @@ int scanOnceSetQueueSize(int size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int scanOnceQueueStatus(const int reset, scanOnceQueueStats *result)
|
||||
{
|
||||
int ret;
|
||||
if (!onceQ) return -1;
|
||||
if (result) {
|
||||
result->size = epicsRingBytesSize(onceQ) / sizeof(onceEntry);
|
||||
result->numUsed = epicsRingBytesUsedBytes(onceQ) / sizeof(onceEntry);
|
||||
result->maxUsed = epicsRingBytesHighWaterMark(onceQ) / sizeof(onceEntry);
|
||||
result->numOverflow = epicsAtomicGetIntT(&onceQOverruns);
|
||||
ret = 0;
|
||||
} else {
|
||||
ret = -2;
|
||||
}
|
||||
if (reset) {
|
||||
epicsRingBytesResetHighWaterMark(onceQ);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void scanOnceQueueShow(const int reset)
|
||||
{
|
||||
scanOnceQueueStats stats;
|
||||
if (scanOnceQueueStatus(reset, &stats) == -1) {
|
||||
fprintf(stderr, "scanOnce system not initialized, yet. Please run "
|
||||
"iocInit before using this command.\n");
|
||||
} else {
|
||||
double qusage = 100.0 * stats.numUsed / stats.size;
|
||||
printf("PRIORITY HIGH-WATER MARK ITEMS IN Q Q SIZE %% USED Q OVERFLOWS\n");
|
||||
printf("%8s %15d %10d %6d %6.1f %11d\n", "scanOnce", stats.maxUsed,
|
||||
stats.numUsed, stats.size, qusage,
|
||||
epicsAtomicGetIntT(&onceQOverruns));
|
||||
}
|
||||
}
|
||||
|
||||
static void initOnce(void)
|
||||
{
|
||||
if ((onceQ = epicsRingBytesLockedCreate(sizeof(onceEntry)*onceQueueSize)) == NULL) {
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "menuScan.h"
|
||||
#include "shareLib.h"
|
||||
#include "compilerDependencies.h"
|
||||
#include "devSup.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -33,9 +34,7 @@ extern "C" {
|
||||
#define MIN_PHASE SHRT_MIN
|
||||
|
||||
/*definitions for I/O Interrupt Scanning */
|
||||
struct ioscan_head;
|
||||
|
||||
typedef struct ioscan_head *IOSCANPVT;
|
||||
/* IOSCANPVT now defined in devSup.h */
|
||||
typedef struct event_list *EVENTPVT;
|
||||
|
||||
struct dbCommon;
|
||||
@@ -43,6 +42,13 @@ struct dbCommon;
|
||||
typedef void (*io_scan_complete)(void *usr, IOSCANPVT, int prio);
|
||||
typedef void (*once_complete)(void *usr, struct dbCommon*);
|
||||
|
||||
typedef struct scanOnceQueueStats {
|
||||
int size;
|
||||
int numUsed;
|
||||
int maxUsed;
|
||||
int numOverflow;
|
||||
} scanOnceQueueStats;
|
||||
|
||||
epicsShareFunc long scanInit(void);
|
||||
epicsShareFunc void scanRun(void);
|
||||
epicsShareFunc void scanPause(void);
|
||||
@@ -58,6 +64,8 @@ epicsShareFunc double scanPeriod(int scan);
|
||||
epicsShareFunc int scanOnce(struct dbCommon *);
|
||||
epicsShareFunc int scanOnceCallback(struct dbCommon *, once_complete cb, void *usr);
|
||||
epicsShareFunc int scanOnceSetQueueSize(int size);
|
||||
epicsShareFunc int scanOnceQueueStatus(const int reset, scanOnceQueueStats *result);
|
||||
epicsShareFunc void scanOnceQueueShow(const int reset);
|
||||
|
||||
/*print periodic lists*/
|
||||
epicsShareFunc int scanppl(double rate);
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dbDefs.h"
|
||||
#include "ellLib.h"
|
||||
#include "envDefs.h"
|
||||
#include "epicsStdio.h"
|
||||
@@ -29,6 +30,7 @@ static char *stateNames[] = {
|
||||
int dbRegisterServer(dbServer *psrv)
|
||||
{
|
||||
const char * ignore = envGetConfigParamPtr(&EPICS_IOC_IGNORE_SERVERS);
|
||||
ELLNODE *node;
|
||||
|
||||
if (!psrv || !psrv->name || state != registering)
|
||||
return -1;
|
||||
@@ -55,10 +57,14 @@ int dbRegisterServer(dbServer *psrv)
|
||||
}
|
||||
}
|
||||
|
||||
if (ellNext(&psrv->node) || ellLast(&serverList) == &psrv->node) {
|
||||
fprintf(stderr, "dbRegisterServer: '%s' registered twice?\n",
|
||||
psrv->name);
|
||||
return -1;
|
||||
for(node=ellFirst(&serverList); node; node = ellNext(node)) {
|
||||
dbServer *cur = CONTAINER(node, dbServer, node);
|
||||
if(cur==psrv) {
|
||||
return 0; /* already registered identically. */
|
||||
} else if(strcmp(cur->name, psrv->name)==0) {
|
||||
fprintf(stderr, "dbRegisterServer: Can't redefine '%s'.\n", cur->name);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
ellAdd(&serverList, &psrv->node);
|
||||
|
||||
@@ -15,6 +15,10 @@
|
||||
|
||||
#include "shareLib.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @file dbState.h
|
||||
* @brief Generic IOC state facility
|
||||
*
|
||||
@@ -89,4 +93,9 @@ epicsShareFunc void dbStateShow(dbStateId id, unsigned int level);
|
||||
*/
|
||||
epicsShareFunc void dbStateShowAll(unsigned int level);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // INCdbStateH
|
||||
|
||||
@@ -1,11 +1,48 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
|
||||
# Copyright (c) 2018 UChicago Argonne LLC, 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 is distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
|
||||
=head1 Menu menuScan
|
||||
|
||||
This menu is used for the C<SCAN> field of all record types.
|
||||
|
||||
The set of periodic scan rates may be modified for an individual IOC by
|
||||
copying the F<menuScan.dbd> file from Base into the IOC's source
|
||||
directory and changing it to contain the desired scan rates.
|
||||
|
||||
The scan periods are extracted from the choice strings at runtime, which
|
||||
must be expressed as a number with any of the following units appended:
|
||||
|
||||
=over 4
|
||||
|
||||
second
|
||||
seconds
|
||||
minute
|
||||
minutes
|
||||
hour
|
||||
hours
|
||||
Hertz
|
||||
Hz
|
||||
|
||||
=back
|
||||
|
||||
At IOC start-up a separate scan thread will be created for each period,
|
||||
with thread priority increasing further down the list, so faster periods
|
||||
should appear after slower ones.
|
||||
|
||||
Scan rates that cannot be achieved will generate a warning message from
|
||||
the C<iocInit> command.
|
||||
|
||||
|
||||
=menu menuScan
|
||||
|
||||
=cut
|
||||
|
||||
menu(menuScan) {
|
||||
choice(menuScanPassive,"Passive")
|
||||
choice(menuScanEvent,"Event")
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include "alarm.h"
|
||||
#include "dbDefs.h"
|
||||
#include "alarm.h"
|
||||
#include "epicsMath.h"
|
||||
#include "epicsPrint.h"
|
||||
#include "epicsStdlib.h"
|
||||
@@ -180,6 +181,9 @@ unsigned short 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;
|
||||
|
||||
@@ -2241,7 +2241,7 @@ long dbInitRecordLinks(dbRecordType *rtyp, struct dbCommon *prec)
|
||||
if(!plink->text)
|
||||
continue;
|
||||
|
||||
if(dbParseLink(plink->text, pflddes->field_type, &link_info, 0)!=0) {
|
||||
if(dbParseLink(plink->text, pflddes->field_type, &link_info)!=0) {
|
||||
/* This was already parsed once when ->text was set.
|
||||
* Any syntax error messages were printed at that time.
|
||||
*/
|
||||
@@ -2270,7 +2270,7 @@ void dbFreeLinkInfo(dbLinkInfo *pinfo)
|
||||
pinfo->target = NULL;
|
||||
}
|
||||
|
||||
long dbParseLink(const char *str, short ftype, dbLinkInfo *pinfo, unsigned opts)
|
||||
long dbParseLink(const char *str, short ftype, dbLinkInfo *pinfo)
|
||||
{
|
||||
char *pstr;
|
||||
size_t len;
|
||||
@@ -2306,7 +2306,7 @@ long dbParseLink(const char *str, short ftype, dbLinkInfo *pinfo, unsigned opts)
|
||||
|
||||
/* Check for braces => JSON */
|
||||
if (*str == '{' && str[len-1] == '}') {
|
||||
if (dbJLinkParse(str, len, ftype, &pinfo->jlink, opts))
|
||||
if (dbJLinkParse(str, len, ftype, &pinfo->jlink))
|
||||
goto fail;
|
||||
|
||||
pinfo->ltype = JSON_LINK;
|
||||
@@ -2353,9 +2353,13 @@ long dbParseLink(const char *str, short ftype, dbLinkInfo *pinfo, unsigned opts)
|
||||
else if (strcmp(pinfo->hwid, "VS")==0) pinfo->ltype = VXI_IO;
|
||||
else goto fail;
|
||||
|
||||
if (parm && pinfo->ltype != RF_IO) {
|
||||
/* move parm string to beginning of buffer */
|
||||
memmove(pinfo->target, parm, len + 1);
|
||||
if (pinfo->ltype != RF_IO) {
|
||||
if (!parm) {
|
||||
pinfo->target[0] = '\0';
|
||||
} else {
|
||||
/* move parm string to beginning of buffer */
|
||||
memmove(pinfo->target, parm, len + 1);
|
||||
}
|
||||
} else if (!parm && pinfo->ltype == RF_IO) {
|
||||
/* RF_IO, the string isn't needed at all */
|
||||
free(pinfo->target);
|
||||
@@ -2641,21 +2645,8 @@ long dbPutString(DBENTRY *pdbentry,const char *pstring)
|
||||
case DBF_FWDLINK: {
|
||||
dbLinkInfo link_info;
|
||||
DBLINK *plink = (DBLINK *)pfield;
|
||||
DBENTRY infoentry;
|
||||
unsigned opts = 0;
|
||||
|
||||
if(pdbentry->precnode && ellCount(&pdbentry->precnode->infoList)) {
|
||||
dbCopyEntryContents(pdbentry, &infoentry);
|
||||
|
||||
if(dbFindInfo(&infoentry, "base:lsetDebug")==0 && epicsStrCaseCmp(dbGetInfoString(&infoentry), "YES")==0)
|
||||
opts |= LINK_DEBUG_LSET;
|
||||
if(dbFindInfo(&infoentry, "base:jlinkDebug")==0 && epicsStrCaseCmp(dbGetInfoString(&infoentry), "YES")==0)
|
||||
opts |= LINK_DEBUG_JPARSE;
|
||||
|
||||
dbFinishEntry(&infoentry);
|
||||
}
|
||||
|
||||
status = dbParseLink(pstring, pflddes->field_type, &link_info, opts);
|
||||
status = dbParseLink(pstring, pflddes->field_type, &link_info);
|
||||
if (status) break;
|
||||
|
||||
if (plink->type==CONSTANT && plink->value.constantStr==NULL) {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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.
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/* dbStaticPvt.h */
|
||||
/*
|
||||
@@ -59,13 +59,10 @@ typedef struct dbLinkInfo {
|
||||
|
||||
long dbInitRecordLinks(dbRecordType *rtyp, struct dbCommon *prec);
|
||||
|
||||
#define LINK_DEBUG_LSET 1
|
||||
#define LINK_DEBUG_JPARSE 2
|
||||
|
||||
/* Parse link string. no record locks needed.
|
||||
* on success caller must free pinfo->target
|
||||
*/
|
||||
epicsShareFunc long dbParseLink(const char *str, short ftype, dbLinkInfo *pinfo, unsigned opts);
|
||||
epicsShareFunc long dbParseLink(const char *str, short ftype, dbLinkInfo *pinfo);
|
||||
/* Check if link type allow the parsed link value pinfo
|
||||
* to be assigned to the given link.
|
||||
* Record containing plink must be locked.
|
||||
|
||||
@@ -6,7 +6,11 @@
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/* devSup.h Device Support */
|
||||
/** @file devSup.h
|
||||
*
|
||||
* @brief Device support routines
|
||||
*/
|
||||
|
||||
/*
|
||||
* Author: Marty Kraimer
|
||||
* Date: 6-1-90
|
||||
@@ -21,6 +25,111 @@
|
||||
/* structures defined elsewhere */
|
||||
struct dbCommon;
|
||||
struct devSup;
|
||||
typedef struct ioscan_head *IOSCANPVT;
|
||||
struct link; /* aka DBLINK */
|
||||
|
||||
/** Type safe version of 'struct dset'
|
||||
*
|
||||
* Recommended usage:
|
||||
*
|
||||
* In Makefile:
|
||||
@code
|
||||
USR_CFLAGS += -DUSE_TYPED_RSET -DUSE_TYPED_DSET
|
||||
@endcode
|
||||
*
|
||||
* In C source file:
|
||||
@code
|
||||
#include <devSup.h>
|
||||
#include <dbScan.h> // For IOCSCANPVT
|
||||
...
|
||||
#include <epicsExport.h> // defines epicsExportSharedSymbols
|
||||
...
|
||||
static long init_record(dbCommon *prec);
|
||||
static long get_iointr_info(int detach, dbCommon *prec, IOCSCANPVT* pscan);
|
||||
static long longin_read(longinRecord *prec);
|
||||
|
||||
const struct {
|
||||
dset common;
|
||||
long (*read)(longinRecord *prec);
|
||||
} devLiDevName = {
|
||||
{
|
||||
5, // 4 from dset + 1 from longinRecord
|
||||
NULL,
|
||||
NULL,
|
||||
&init_record,
|
||||
&get_iointr_info
|
||||
},
|
||||
&longin_read
|
||||
};
|
||||
epicsExportAddress(dset, devLiDevName);
|
||||
@endcode
|
||||
*/
|
||||
typedef struct typed_dset {
|
||||
/** Number of function pointers which follow.
|
||||
* The value depends on the recordtype, but must be >=4 */
|
||||
long number;
|
||||
/** Called from dbior() */
|
||||
long (*report)(int lvl);
|
||||
/** Called twice during iocInit().
|
||||
* First with @a after = 0 before init_record() or array field allocation.
|
||||
* Again with @a after = 1 after init_record() has finished.
|
||||
*/
|
||||
long (*init)(int after);
|
||||
/** Called once per record instance */
|
||||
long (*init_record)(struct dbCommon *prec);
|
||||
/** Called when SCAN="I/O Intr" on startup, or after SCAN is changed.
|
||||
*
|
||||
* Caller must assign the third arguement (IOCSCANPVT*). eg.
|
||||
@code
|
||||
struct mpvt {
|
||||
IOSCANPVT drvlist;
|
||||
};
|
||||
...
|
||||
// init_record() routine calls
|
||||
scanIoInit(&pvt->drvlist);
|
||||
...
|
||||
static long get_ioint_info(int detach, struct dbCommon *prec, IOCSCANPVT* pscan) {
|
||||
if(prec->dpvt)
|
||||
*pscan = &((mypvt*)prec->dpvt)->drvlist;
|
||||
@endcode
|
||||
*
|
||||
* When a particular record instance can/will only used a single scan list,
|
||||
* the @a detach argument can be ignored.
|
||||
*
|
||||
* If this is not the case, then the following should be noted.
|
||||
* + get_ioint_info() is called with @a detach = 0 to fetch the scan list to
|
||||
* which this record will be added.
|
||||
* + get_ioint_info() is called later with @a detach = 1 to fetch the scan
|
||||
* list from which this record should be removed.
|
||||
* + Calls will be balanced, so a call with @a detach = 0 will be followed
|
||||
* by one with @a detach = 1.
|
||||
*
|
||||
* @note get_ioint_info() will be called during IOC shutdown if the
|
||||
* dsxt::del_record() extended callback is defined. (from 3.15.0.1)
|
||||
*/
|
||||
long (*get_ioint_info)(int detach, struct dbCommon *prec, IOSCANPVT* pscan);
|
||||
/* Any further functions are specified by the record type. */
|
||||
} typed_dset;
|
||||
|
||||
/** Device support extension table.
|
||||
*
|
||||
* Optional routines to allow run-time address modifications to be communicated
|
||||
* to device support, which must register a struct dsxt by calling devExtend()
|
||||
* from its init() routine.
|
||||
*/
|
||||
typedef struct dsxt {
|
||||
/** Optional, called to offer device support a new record to control.
|
||||
*
|
||||
* Routine may return a non-zero error code to refuse record.
|
||||
*/
|
||||
long (*add_record)(struct dbCommon *precord);
|
||||
/** Optional, called to remove record from device support control.
|
||||
*
|
||||
* Routine return a non-zero error code to refuse record removal.
|
||||
*/
|
||||
long (*del_record)(struct dbCommon *precord);
|
||||
/* Only future Base releases may extend this table. */
|
||||
} dsxt;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -29,6 +138,8 @@ extern "C" {
|
||||
typedef long (*DEVSUPFUN)(); /* ptr to device support function*/
|
||||
#endif
|
||||
|
||||
#ifndef USE_TYPED_DSET
|
||||
|
||||
typedef struct dset { /* device support entry table */
|
||||
long number; /*number of support routines*/
|
||||
DEVSUPFUN report; /*print report*/
|
||||
@@ -38,11 +149,15 @@ typedef struct dset { /* device support entry table */
|
||||
/*other functions are record dependent*/
|
||||
} dset;
|
||||
|
||||
typedef struct dsxt { /* device support extension table */
|
||||
long (*add_record)(struct dbCommon *precord);
|
||||
long (*del_record)(struct dbCommon *precord);
|
||||
/* Recordtypes are *not* allowed to extend this table */
|
||||
} dsxt;
|
||||
#else
|
||||
typedef typed_dset dset;
|
||||
#endif /* USE_TYPED_DSET */
|
||||
|
||||
/** Fetch INP or OUT link (or NULL if record type has neither).
|
||||
*
|
||||
* Recommended for use in device support init_record()
|
||||
*/
|
||||
epicsShareFunc struct link* dbGetDevLink(struct dbCommon* prec);
|
||||
|
||||
epicsShareExtern dsxt devSoft_DSXT; /* Allow anything table */
|
||||
|
||||
|
||||
@@ -6,7 +6,10 @@
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/* drvSup.h Driver Support */
|
||||
/** @file drvSup.h
|
||||
*
|
||||
* @brief Driver support routines.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Author: Marty Kraimer
|
||||
@@ -18,16 +21,38 @@
|
||||
|
||||
#include "errMdef.h"
|
||||
|
||||
typedef long (*DRVSUPFUN) (); /* ptr to driver support function*/
|
||||
/** Driver entry table */
|
||||
typedef struct typed_drvet {
|
||||
/** Number of function pointers which follow. Must be >=2 */
|
||||
long number;
|
||||
/** Called from dbior() */
|
||||
long (*report)(int lvl);
|
||||
/** Called during iocInit() */
|
||||
long (*init)(void);
|
||||
/* Any further functions are driver-specific */
|
||||
} typed_drvet;
|
||||
|
||||
#ifdef USE_TYPED_DRVET
|
||||
|
||||
typedef typed_drvet drvet;
|
||||
|
||||
#else
|
||||
|
||||
/* These interfaces may eventually get deprecated */
|
||||
|
||||
typedef long (*DRVSUPFUN) (); /* ptr to driver support function */
|
||||
|
||||
typedef struct drvet { /* driver entry table */
|
||||
long number; /* number of support routines */
|
||||
DRVSUPFUN report; /* print report */
|
||||
DRVSUPFUN init; /* init support */
|
||||
/* Any further functions are driver-specific */
|
||||
} drvet;
|
||||
|
||||
typedef struct drvet { /* driver entry table */
|
||||
long number; /*number of support routines*/
|
||||
DRVSUPFUN report; /*print report*/
|
||||
DRVSUPFUN init; /*init support*/
|
||||
/*other functions are device dependent*/
|
||||
}drvet;
|
||||
#define DRVETNUMBER ( (sizeof(struct drvet) -sizeof(long))/sizeof(DRVSUPFUN) )
|
||||
|
||||
#endif /* USE_TYPED_DRVET */
|
||||
|
||||
#define S_drv_noDrvSup (M_drvSup| 1) /*SDR_DRVSUP: Driver support missing*/
|
||||
#define S_drv_noDrvet (M_drvSup| 3) /*Missing driver support entry table*/
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -34,10 +34,10 @@ be written to stdout unless the -o option is given.</p>
|
||||
|
||||
<dl>
|
||||
<dt><tt>-V</tt></dt>
|
||||
<dd>Verbose warnings; if this parameter is specified then any undefined
|
||||
macro discovered in the template file which does not have an associated
|
||||
default value is considered an error. An error message is generated, and
|
||||
when msi terminates it will do so with an exit status of 2.</dd>
|
||||
<dd>Verbose warnings; if this parameter is specified then any undefined or
|
||||
recursive macros discovered in the template will be considered an error and
|
||||
will be marked in the output file. An error message will be shown, and when
|
||||
msi terminates it will do so with an exit status of 2.</dd>
|
||||
|
||||
<dt><tt>-g</tt></dt>
|
||||
<dd>When this flag is given all macros defined in a substitution file will
|
||||
|
||||
@@ -26,3 +26,4 @@ dbCore_SRCS += miscIocRegister.c
|
||||
dbCore_SRCS += dlload.c
|
||||
dbCore_SRCS += iocshRegisterCommon.c
|
||||
|
||||
miscIocRegister_CFLAGS_iOS = -DSYSTEM_UNAVAILABLE
|
||||
|
||||
@@ -12,6 +12,9 @@ variable(asCaDebug,int)
|
||||
# CA server debug flag (very verbose) range[0,5]
|
||||
variable(CASDEBUG,int)
|
||||
|
||||
# Link parsing debug
|
||||
variable(dbJLinkDebug,int)
|
||||
|
||||
# Static database access variables
|
||||
variable(dbRecordsOnceOnly,int)
|
||||
variable(dbRecordsAbcSorted,int)
|
||||
@@ -19,8 +22,12 @@ variable(dbBptNotMonotonic,int)
|
||||
variable(dbQuietMacroWarnings,int)
|
||||
variable(dbConvertStrict,int)
|
||||
|
||||
# PUTF/RPRO tracing; set TPRO on records to trace
|
||||
variable(dbAccessDebugPUTF,int)
|
||||
|
||||
# dbLoadTemplate settings
|
||||
variable(dbTemplateMaxVars,int)
|
||||
|
||||
# Default number of parallel callback threads
|
||||
variable(callbackParallelThreadsDefault,int)
|
||||
|
||||
|
||||
@@ -66,10 +66,12 @@ void miscIocRegister(void)
|
||||
|
||||
/* system -- escape to system command interpreter.
|
||||
*
|
||||
* Disabled by default, for security reasons. To enable this command, add
|
||||
* Disabled by default for security reasons, not available on all OSs.
|
||||
* To enable this command, add
|
||||
* registrar(iocshSystemCommand)
|
||||
* to an application dbd file.
|
||||
* to an application dbd file, or include system.dbd
|
||||
*/
|
||||
#ifndef SYSTEM_UNAVAILABLE
|
||||
static const iocshArg systemArg0 = { "command string",iocshArgString};
|
||||
static const iocshArg * const systemArgs[] = {&systemArg0};
|
||||
static const iocshFuncDef systemFuncDef = {"system",1,systemArgs};
|
||||
@@ -77,12 +79,15 @@ static void systemCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
system(args[0].sval);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void iocshSystemCommand(void)
|
||||
{
|
||||
#ifndef SYSTEM_UNAVAILABLE
|
||||
if (system(NULL))
|
||||
iocshRegister(&systemFuncDef, systemCallFunc);
|
||||
else
|
||||
#endif
|
||||
errlogPrintf ("Can't register 'system' command -- no command interpreter available.\n");
|
||||
}
|
||||
epicsExportRegistrar(iocshSystemCommand);
|
||||
|
||||
@@ -83,20 +83,22 @@ static void req_server (void *pParm)
|
||||
|
||||
while (TRUE) {
|
||||
SOCKET clientSock;
|
||||
struct sockaddr sockAddr;
|
||||
osiSockAddr sockAddr;
|
||||
osiSocklen_t addLen = sizeof(sockAddr);
|
||||
|
||||
while (castcp_ctl == ctlPause) {
|
||||
epicsThreadSleep(0.1);
|
||||
}
|
||||
|
||||
clientSock = epicsSocketAccept ( IOC_sock, &sockAddr, &addLen );
|
||||
if ( clientSock == INVALID_SOCKET ) {
|
||||
clientSock = epicsSocketAccept ( IOC_sock, &sockAddr.sa, &addLen );
|
||||
if ( clientSock == INVALID_SOCKET ||
|
||||
sockAddr.sa.sa_family != AF_INET ||
|
||||
addLen < sizeof(sockAddr.ia) ) {
|
||||
char sockErrBuf[64];
|
||||
epicsSocketConvertErrnoToString (
|
||||
sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
errlogPrintf("CAS: Client accept error: %s\n",
|
||||
sockErrBuf );
|
||||
errlogPrintf("CAS: Client accept error: %s (%d)\n",
|
||||
sockErrBuf, (int)addLen );
|
||||
epicsThreadSleep(15.0);
|
||||
continue;
|
||||
}
|
||||
@@ -105,7 +107,7 @@ static void req_server (void *pParm)
|
||||
struct client *pClient;
|
||||
|
||||
/* socket passed in is closed if unsuccessful here */
|
||||
pClient = create_tcp_client ( clientSock );
|
||||
pClient = create_tcp_client ( clientSock, &sockAddr );
|
||||
if ( ! pClient ) {
|
||||
epicsThreadSleep ( 15.0 );
|
||||
continue;
|
||||
@@ -324,7 +326,7 @@ void rsrv_build_addr_lists(void)
|
||||
|
||||
#ifdef IP_MULTICAST_TTL
|
||||
{
|
||||
int ttl;
|
||||
osiSockOptMcastTTL_t ttl;
|
||||
long val;
|
||||
if(envGetLongConfigParam(&EPICS_CA_MCAST_TTL, &val))
|
||||
val =1;
|
||||
@@ -1405,12 +1407,11 @@ void casExpandRecvBuffer ( struct client *pClient, ca_uint32_t size )
|
||||
/*
|
||||
* create_tcp_client ()
|
||||
*/
|
||||
struct client *create_tcp_client ( SOCKET sock )
|
||||
struct client *create_tcp_client (SOCKET sock , const osiSockAddr *peerAddr)
|
||||
{
|
||||
int status;
|
||||
struct client *client;
|
||||
int intTrue = TRUE;
|
||||
osiSocklen_t addrSize;
|
||||
unsigned priorityOfEvents;
|
||||
|
||||
/* socket passed in is destroyed here if unsuccessful */
|
||||
@@ -1419,6 +1420,8 @@ struct client *create_tcp_client ( SOCKET sock )
|
||||
return NULL;
|
||||
}
|
||||
|
||||
client->addr = peerAddr->ia;
|
||||
|
||||
/*
|
||||
* see TCP(4P) this seems to make unsolicited single events much
|
||||
* faster. I take care of queue up as load increases.
|
||||
@@ -1470,15 +1473,6 @@ struct client *create_tcp_client ( SOCKET sock )
|
||||
}
|
||||
#endif
|
||||
|
||||
addrSize = sizeof ( client->addr );
|
||||
status = getpeername ( sock, (struct sockaddr *)&client->addr,
|
||||
&addrSize );
|
||||
if ( status < 0 ) {
|
||||
epicsPrintf ("CAS: peer address fetch failed\n");
|
||||
destroy_tcp_client (client);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
client->evuser = (struct event_user *) db_init_events ();
|
||||
if ( ! client->evuser ) {
|
||||
errlogPrintf ("CAS: unable to init the event facility\n");
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <cantProceed.h>
|
||||
|
||||
#include "addrList.h"
|
||||
#include "dbDefs.h"
|
||||
@@ -45,6 +46,7 @@ void rsrv_online_notify_task(void *pParm)
|
||||
caHdr msg;
|
||||
int status;
|
||||
ca_uint32_t beaconCounter = 0;
|
||||
int *lastError;
|
||||
|
||||
taskwdInsert (epicsThreadGetIdSelf(),NULL,NULL);
|
||||
|
||||
@@ -70,29 +72,45 @@ void rsrv_online_notify_task(void *pParm)
|
||||
msg.m_count = htons (ca_server_port);
|
||||
msg.m_dataType = htons (CA_MINOR_PROTOCOL_REVISION);
|
||||
|
||||
/* beaconAddrList should not change after rsrv_init(), which then starts this thread */
|
||||
lastError = callocMustSucceed(ellCount(&beaconAddrList), sizeof(*lastError), "rsrv_online_notify_task lastError");
|
||||
|
||||
epicsEventSignal(beacon_startStopEvent);
|
||||
|
||||
while (TRUE) {
|
||||
ELLNODE *cur;
|
||||
unsigned i;
|
||||
|
||||
/* send beacon to each interface */
|
||||
for(cur=ellFirst(&beaconAddrList); cur; cur=ellNext(cur))
|
||||
for(i=0, cur=ellFirst(&beaconAddrList); cur; i++, cur=ellNext(cur))
|
||||
{
|
||||
osiSockAddrNode *pAddr = CONTAINER(cur, osiSockAddrNode, node);
|
||||
status = sendto (beaconSocket, (char *)&msg, sizeof(msg), 0,
|
||||
&pAddr->addr.sa, sizeof(pAddr->addr));
|
||||
if (status < 0) {
|
||||
char sockErrBuf[64];
|
||||
char sockDipBuf[22];
|
||||
int err = SOCKERRNO;
|
||||
if(err != lastError[i]) {
|
||||
char sockErrBuf[64];
|
||||
char sockDipBuf[22];
|
||||
|
||||
epicsSocketConvertErrnoToString(sockErrBuf, sizeof(sockErrBuf));
|
||||
ipAddrToDottedIP(&pAddr->addr.ia, sockDipBuf, sizeof(sockDipBuf));
|
||||
errlogPrintf ( "CAS: CA beacon send to %s error: %s\n",
|
||||
sockDipBuf, sockErrBuf);
|
||||
epicsSocketConvertErrorToString(sockErrBuf, sizeof(sockErrBuf), err);
|
||||
ipAddrToDottedIP(&pAddr->addr.ia, sockDipBuf, sizeof(sockDipBuf));
|
||||
errlogPrintf ( "CAS: CA beacon send to %s error: %s\n",
|
||||
sockDipBuf, sockErrBuf);
|
||||
|
||||
lastError[i] = err;
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert (status == sizeof(msg));
|
||||
if(lastError[i]) {
|
||||
char sockDipBuf[22];
|
||||
|
||||
ipAddrToDottedIP(&pAddr->addr.ia, sockDipBuf, sizeof(sockDipBuf));
|
||||
errlogPrintf ( "CAS: CA beacon send to %s ok\n",
|
||||
sockDipBuf);
|
||||
}
|
||||
lastError[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,6 +129,8 @@ void rsrv_online_notify_task(void *pParm)
|
||||
delay = 0.02; /* Restart beacon timing if paused */
|
||||
}
|
||||
}
|
||||
|
||||
free(lastError);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -230,7 +230,7 @@ void rsrv_online_notify_task (void *);
|
||||
void cast_server (void *);
|
||||
struct client *create_client ( SOCKET sock, int proto );
|
||||
void destroy_client ( struct client * );
|
||||
struct client *create_tcp_client ( SOCKET sock );
|
||||
struct client *create_tcp_client ( SOCKET sock, const osiSockAddr* peerAddr );
|
||||
void destroy_tcp_client ( struct client * );
|
||||
void casAttachThreadToClient ( struct client * );
|
||||
int camessage ( struct client *client );
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "dbDefs.h"
|
||||
#include "dbAccess.h"
|
||||
#include "dbConstLink.h"
|
||||
#include "dbEvent.h"
|
||||
#include "recGbl.h"
|
||||
#include "devSup.h"
|
||||
#include "cantProceed.h"
|
||||
@@ -96,11 +97,15 @@ static long readLocked(struct link *pinp, void *dummy)
|
||||
|
||||
static long read_aai(aaiRecord *prec)
|
||||
{
|
||||
epicsUInt32 nord = prec->nord;
|
||||
struct link *pinp = prec->simm == menuYesNoYES ? &prec->siol : &prec->inp;
|
||||
long status = dbLinkDoLocked(pinp, readLocked, NULL);
|
||||
|
||||
if (status == S_db_noLSET)
|
||||
status = readLocked(pinp, NULL);
|
||||
|
||||
if (!status && nord != prec->nord)
|
||||
db_post_events(prec, &prec->nord, DBE_VALUE | DBE_LOG);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* Copyright (c) 2002 Lawrence Berkeley Laboratory,The Control Systems
|
||||
* Group, Systems Engineering Department
|
||||
* 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.
|
||||
\*************************************************************************/
|
||||
|
||||
/*
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "alarm.h"
|
||||
#include "dbDefs.h"
|
||||
#include "dbAccess.h"
|
||||
#include "dbEvent.h"
|
||||
#include "recGbl.h"
|
||||
#include "devSup.h"
|
||||
#include "subArrayRecord.h"
|
||||
@@ -101,6 +102,7 @@ static long read_sa(subArrayRecord *prec)
|
||||
{
|
||||
long status;
|
||||
struct sart rt;
|
||||
epicsUInt32 nord = prec->nord;
|
||||
|
||||
rt.nRequest = prec->indx + prec->nelm;
|
||||
if (rt.nRequest > prec->malm)
|
||||
@@ -123,8 +125,12 @@ static long read_sa(subArrayRecord *prec)
|
||||
status = readLocked(&prec->inp, &rt);
|
||||
}
|
||||
|
||||
if (!status && rt.nRequest > 0)
|
||||
if (!status && rt.nRequest > 0) {
|
||||
subset(prec, rt.nRequest);
|
||||
|
||||
if (nord != prec->nord)
|
||||
db_post_events(prec, &prec->nord, DBE_VALUE | DBE_LOG);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
\*************************************************************************/
|
||||
|
||||
/*
|
||||
@@ -81,6 +81,7 @@ static long read_wf(waveformRecord *prec)
|
||||
{
|
||||
long status;
|
||||
struct wfrt rt;
|
||||
epicsUInt32 nord = prec->nord;
|
||||
|
||||
rt.nRequest = prec->nelm;
|
||||
rt.ptime = (dbLinkIsConstant(&prec->tsel) &&
|
||||
@@ -93,6 +94,8 @@ static long read_wf(waveformRecord *prec)
|
||||
if (!status && rt.nRequest > 0) {
|
||||
prec->nord = rt.nRequest;
|
||||
prec->udf = FALSE;
|
||||
if (nord != prec->nord)
|
||||
db_post_events(prec, &prec->nord, DBE_VALUE | DBE_LOG);
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Copyright (c) 2016 UChicago Argonne LLC, as Operator of Argonne
|
||||
# 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.
|
||||
#*************************************************************************
|
||||
|
||||
# This is a Makefile fragment, see src/std/Makefile.
|
||||
@@ -13,6 +13,7 @@ DBD += links.dbd
|
||||
|
||||
dbRecStd_SRCS += lnkConst.c
|
||||
dbRecStd_SRCS += lnkCalc.c
|
||||
dbRecStd_SRCS += lnkState.c
|
||||
dbRecStd_SRCS += lnkDebug.c
|
||||
|
||||
HTMLS += links.html
|
||||
|
||||
|
||||
@@ -13,6 +13,12 @@ The following additional link types are available in this release:
|
||||
|
||||
=item * L<Calc|/"Calculation Link calc">
|
||||
|
||||
=item * L<dbState|/"dbState Link state">
|
||||
|
||||
=item * L<Debug|/"Debug Link debug">
|
||||
|
||||
=item * L<Trace|/"Trace Link trace">
|
||||
|
||||
=back
|
||||
|
||||
=head2 Using JSON Links
|
||||
@@ -31,15 +37,16 @@ database file syntax.
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
link(const, lnkConstIf)
|
||||
|
||||
=head3 Constant Link C<"const">
|
||||
|
||||
Constant links provide one or more values at link initalization time, but do not
|
||||
return any data when their C<getValue()> routine is called. Most record types
|
||||
support the use of constant links by calling C<recGblInitConstantLink()> at
|
||||
record initialization, which results in the constant value being loaded into the
|
||||
target field at that time.
|
||||
Constant links are input links that provide literal values at link initalization
|
||||
time, but do not return any data when their C<getValue()> routine is called.
|
||||
Most record types support the use of constant links on their input links by
|
||||
calling C<recGblInitConstantLink()> at record initialization, which results in
|
||||
the constant value being loaded into the target field at that time.
|
||||
|
||||
Note that for most record types (the C<printf> and C<calcout> records are the
|
||||
main exceptions) it is pointless to set an input link to a constant link at
|
||||
@@ -70,14 +77,35 @@ converted to the desired double value at initialization, for example:
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
link(calc, lnkCalcIf)
|
||||
|
||||
=head3 Calculation Link C<"calc">
|
||||
|
||||
Calculation links can perform simple mathematical expressions on scalar
|
||||
(double-precision floating-point) values obtained from other link types and
|
||||
return a single double-precision floating-point result. The expressions are
|
||||
evaluated by the EPICS Calc engine, and up to 12 inputs can be provided.
|
||||
A calculation link is an input link that can evaluate mathematical expressions
|
||||
on scalar (double-precision floating-point) values obtained from up to 12 child
|
||||
input links, and returns a double-precision floating-point result. The
|
||||
expression is evaluated by the EPICS Calc engine, and the result is returned as
|
||||
the value of the link.
|
||||
|
||||
Two additional expressions may also be provided and are evaluated to determine
|
||||
whether the record owning the link should be placed in alarm state. In both
|
||||
cases the result of the main calculation is available to these expressions as
|
||||
C<VAL> (attempts to assign to C<VAL> inside either expression will have no
|
||||
lasting effect). If the C<major> expression evaluates to a non-zero value the
|
||||
record will be placed in C<LINK/MAJOR> alarm. If not and the C<minor> expression
|
||||
evaluates to non-zero the record will be placed in C<LINK/MINOR> alarm state.
|
||||
|
||||
A calculation link can also be an output link, with the scalar output value
|
||||
being converted to a double and provided to the expression as C<VAL>. Up to 12
|
||||
additional input links can also be read and provided to the expression as above.
|
||||
The result of the calculation is forwarded to a child output link specified in
|
||||
the link's C<out> parameter.
|
||||
|
||||
For an output link the main expression is actually optional; if not provided the
|
||||
converted value will be forwarded to the output link unchanged. The two alarm
|
||||
expressions may still be used to put the output link into alarm state as
|
||||
described above.
|
||||
|
||||
=head4 Parameters
|
||||
|
||||
@@ -88,6 +116,7 @@ The link address is a JSON map with the following keys:
|
||||
=item expr
|
||||
|
||||
The primary expression to be evaluated, given as a string.
|
||||
This is optional for output links, required for input links.
|
||||
|
||||
=item major
|
||||
|
||||
@@ -104,6 +133,12 @@ to the inputs C<A>, C<B>, C<C>, ... C<L>. Each input argument may be either a
|
||||
numeric literal or an embedded JSON link inside C<{}> braces. The same input
|
||||
values are provided to the two alarm expressions as to the primary expression.
|
||||
|
||||
=item out
|
||||
|
||||
A JSON link inside C<{}> braces which specifies the destination of C<putValue>
|
||||
operations after any expressions have been evaluated.
|
||||
This key is required for output links, not used by input links.
|
||||
|
||||
=item units
|
||||
|
||||
An optional string specifying the engineering units for the result of the
|
||||
@@ -129,3 +164,72 @@ atomically with the value of the input argument.
|
||||
{calc: {expr:"A*B", args:[{db:"record.VAL"}, 1.5], prec:3}}
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
link(state, lnkStateIf)
|
||||
|
||||
=head3 dbState Link C<"state">
|
||||
|
||||
A dbState link is one that gets or puts a boolean value from/to a named global
|
||||
flag as implemented by the dbState facility in C<dbstate.h>. The link type can
|
||||
invert the sense of the dbState flag during the get or put if desired.
|
||||
|
||||
The value of the named flag is read or written at the time of the link I/O
|
||||
operation. When reading a flag, the value returned by the link will be zero or
|
||||
one converted to the requested data type. When writing to a flag the boolean
|
||||
value of the data written is determined in the originating data type. All
|
||||
strings are regarded as true other than C<""> and C<"0"> which are both false.
|
||||
|
||||
A link can be configured to invert the sense of the flag data by putting an
|
||||
exclamation mark C<!> before the first character of the flag's name in the link
|
||||
address.
|
||||
|
||||
These dbState flags can be accessed from the IOC Shell with various dbState
|
||||
commands, and are also used by the C<"sync"> Channel-Access server-side filter
|
||||
mechanism.
|
||||
|
||||
=head4 Parameters
|
||||
|
||||
The link takes a single parameter which must be a string, providing the name of
|
||||
the dbState object, with an optional leading C<!> character to indicate that the
|
||||
flag's value should be inverted. The dbState object will be created when the
|
||||
link is initialized if it doesn't already exist.
|
||||
|
||||
=head4 Examples
|
||||
|
||||
{state:"redBeam"}
|
||||
{state:"!simEnable"}
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
link(debug, lnkDebugIf)
|
||||
variable(lnkDebug_debug, int)
|
||||
|
||||
=head3 Debug Link C<"debug">
|
||||
|
||||
The debug link type exists to enable debugging of other link types; it provides
|
||||
no functionality itself other than to turn on the debug flag for the child link
|
||||
that is its only parameter and pass all link operations down to that link.
|
||||
|
||||
=head4 Example
|
||||
|
||||
{debug:{state:"redBeam"}}
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
link(trace, lnkTraceIf)
|
||||
|
||||
=head3 Trace Link C<"trace">
|
||||
|
||||
The trace link type is a relative of the debug link type that also traces the
|
||||
operation of its child link. At creation it turns on the debug flag of its child
|
||||
link, then it prints the method arguments and return values of all link
|
||||
operations before / after passing control down to the child link.
|
||||
|
||||
=head4 Example
|
||||
|
||||
{trace:{state:"redBeam"}}
|
||||
|
||||
=cut
|
||||
|
||||
@@ -6,13 +6,9 @@
|
||||
\*************************************************************************/
|
||||
/* lnkCalc.c */
|
||||
|
||||
/* Current usage
|
||||
* {calc:{expr:"A", args:[{...}, ...]}}
|
||||
/* Usage
|
||||
* {calc:{expr:"A*B", args:[{...}, ...], units:"mm"}}
|
||||
* First link in 'args' is 'A', second is 'B', and so forth.
|
||||
*
|
||||
* TODO:
|
||||
* Support setting individual input links instead of the args list.
|
||||
* {calc:{expr:"K", K:{...}}}
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
@@ -26,6 +22,7 @@
|
||||
#include "epicsAssert.h"
|
||||
#include "epicsString.h"
|
||||
#include "epicsTypes.h"
|
||||
#include "epicsTime.h"
|
||||
#include "dbAccessDefs.h"
|
||||
#include "dbCommon.h"
|
||||
#include "dbConvertFast.h"
|
||||
@@ -40,15 +37,14 @@
|
||||
|
||||
typedef long (*FASTCONVERT)();
|
||||
|
||||
#define IFDEBUG(n) if(clink->jlink.debug)
|
||||
|
||||
typedef struct calc_link {
|
||||
jlink jlink; /* embedded object */
|
||||
int nArgs;
|
||||
short dbfType;
|
||||
enum {
|
||||
ps_init,
|
||||
ps_expr, ps_major, ps_minor,
|
||||
ps_args,
|
||||
ps_args, ps_out,
|
||||
ps_prec,
|
||||
ps_units,
|
||||
ps_time,
|
||||
@@ -66,7 +62,9 @@ typedef struct calc_link {
|
||||
char *units;
|
||||
short tinp;
|
||||
struct link inp[CALCPERFORM_NARGS];
|
||||
struct link out;
|
||||
double arg[CALCPERFORM_NARGS];
|
||||
epicsTimeStamp time;
|
||||
double val;
|
||||
} calc_link;
|
||||
|
||||
@@ -77,19 +75,25 @@ static lset lnkCalc_lset;
|
||||
|
||||
static jlink* lnkCalc_alloc(short dbfType)
|
||||
{
|
||||
calc_link *clink = calloc(1, sizeof(struct calc_link));
|
||||
calc_link *clink;
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("lnkCalc_alloc()\n");
|
||||
if (dbfType == DBF_FWDLINK) {
|
||||
errlogPrintf("lnkCalc: No support for forward links\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
clink = calloc(1, sizeof(struct calc_link));
|
||||
if (!clink) {
|
||||
errlogPrintf("lnkCalc: calloc() failed.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
clink->nArgs = 0;
|
||||
clink->dbfType = dbfType;
|
||||
clink->pstate = ps_init;
|
||||
clink->prec = 15; /* standard value for a double */
|
||||
clink->tinp = -1;
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("lnkCalc_alloc -> calc@%p\n", clink);
|
||||
|
||||
return &clink->jlink;
|
||||
}
|
||||
|
||||
@@ -98,12 +102,11 @@ static void lnkCalc_free(jlink *pjlink)
|
||||
calc_link *clink = CONTAINER(pjlink, struct calc_link, jlink);
|
||||
int i;
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("lnkCalc_free(calc@%p)\n", clink);
|
||||
|
||||
for (i = 0; i < clink->nArgs; i++)
|
||||
dbJLinkFree(clink->inp[i].value.json.jlink);
|
||||
|
||||
dbJLinkFree(clink->out.value.json.jlink);
|
||||
|
||||
free(clink->expr);
|
||||
free(clink->major);
|
||||
free(clink->minor);
|
||||
@@ -118,9 +121,6 @@ static jlif_result lnkCalc_integer(jlink *pjlink, long long num)
|
||||
{
|
||||
calc_link *clink = CONTAINER(pjlink, struct calc_link, jlink);
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("lnkCalc_integer(calc@%p, %lld)\n", clink, num);
|
||||
|
||||
if (clink->pstate == ps_prec) {
|
||||
clink->prec = num;
|
||||
return jlif_continue;
|
||||
@@ -146,9 +146,6 @@ static jlif_result lnkCalc_double(jlink *pjlink, double num)
|
||||
{
|
||||
calc_link *clink = CONTAINER(pjlink, struct calc_link, jlink);
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("lnkCalc_double(calc@%p, %g)\n", clink, num);
|
||||
|
||||
if (clink->pstate != ps_args) {
|
||||
return jlif_stop;
|
||||
errlogPrintf("lnkCalc: Unexpected double %g\n", num);
|
||||
@@ -171,9 +168,6 @@ static jlif_result lnkCalc_string(jlink *pjlink, const char *val, size_t len)
|
||||
char *inbuf, *postbuf;
|
||||
short err;
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("lnkCalc_string(calc@%p, \"%.*s\")\n", clink, (int) len, val);
|
||||
|
||||
if (clink->pstate == ps_units) {
|
||||
clink->units = epicsStrnDup(val, len);
|
||||
return jlif_continue;
|
||||
@@ -181,7 +175,8 @@ static jlif_result lnkCalc_string(jlink *pjlink, const char *val, size_t len)
|
||||
|
||||
if (clink->pstate == ps_time) {
|
||||
char tinp;
|
||||
if (len != 1 || (tinp = toupper(val[0])) < 'A' || tinp > 'L') {
|
||||
|
||||
if (len != 1 || (tinp = toupper((int) val[0])) < 'A' || tinp > 'L') {
|
||||
errlogPrintf("lnkCalc: Bad 'time' parameter \"%.*s\"\n", (int) len, val);
|
||||
return jlif_stop;
|
||||
}
|
||||
@@ -234,11 +229,10 @@ static jlif_key_result lnkCalc_start_map(jlink *pjlink)
|
||||
{
|
||||
calc_link *clink = CONTAINER(pjlink, struct calc_link, jlink);
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("lnkCalc_start_map(calc@%p)\n", clink);
|
||||
|
||||
if (clink->pstate == ps_args)
|
||||
return jlif_key_child_link;
|
||||
return jlif_key_child_inlink;
|
||||
if (clink->pstate == ps_out)
|
||||
return jlif_key_child_outlink;
|
||||
|
||||
if (clink->pstate != ps_init) {
|
||||
errlogPrintf("lnkCalc: Unexpected map\n");
|
||||
@@ -252,10 +246,21 @@ static jlif_result lnkCalc_map_key(jlink *pjlink, const char *key, size_t len)
|
||||
{
|
||||
calc_link *clink = CONTAINER(pjlink, struct calc_link, jlink);
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("lnkCalc_map_key(calc@%p, \"%.*s\")\n", pjlink, (int) len, key);
|
||||
/* FIXME: These errors messages are wrong when a key is duplicated.
|
||||
* The key is known, we just don't allow it more than once.
|
||||
*/
|
||||
|
||||
if (len == 4) {
|
||||
if (len == 3) {
|
||||
if (!strncmp(key, "out", len) &&
|
||||
clink->dbfType == DBF_OUTLINK &&
|
||||
clink->out.type == 0)
|
||||
clink->pstate = ps_out;
|
||||
else {
|
||||
errlogPrintf("lnkCalc: Unknown key \"%.3s\"\n", key);
|
||||
return jlif_stop;
|
||||
}
|
||||
}
|
||||
else if (len == 4) {
|
||||
if (!strncmp(key, "expr", len) && !clink->post_expr)
|
||||
clink->pstate = ps_expr;
|
||||
else if (!strncmp(key, "args", len) && !clink->nArgs)
|
||||
@@ -293,13 +298,16 @@ static jlif_result lnkCalc_end_map(jlink *pjlink)
|
||||
{
|
||||
calc_link *clink = CONTAINER(pjlink, struct calc_link, jlink);
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("lnkCalc_end_map(calc@%p)\n", clink);
|
||||
|
||||
if (clink->pstate == ps_error)
|
||||
return jlif_stop;
|
||||
else if (!clink->post_expr) {
|
||||
errlogPrintf("lnkCalc: no expression ('expr' key)\n");
|
||||
else if (clink->dbfType == DBF_INLINK &&
|
||||
!clink->post_expr) {
|
||||
errlogPrintf("lnkCalc: No expression ('expr' key)\n");
|
||||
return jlif_stop;
|
||||
}
|
||||
else if (clink->dbfType == DBF_OUTLINK &&
|
||||
clink->out.type != JSON_LINK) {
|
||||
errlogPrintf("lnkCalc: No output link ('out' key)\n");
|
||||
return jlif_stop;
|
||||
}
|
||||
|
||||
@@ -310,9 +318,6 @@ static jlif_result lnkCalc_start_array(jlink *pjlink)
|
||||
{
|
||||
calc_link *clink = CONTAINER(pjlink, struct calc_link, jlink);
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("lnkCalc_start_array(calc@%p)\n", clink);
|
||||
|
||||
if (clink->pstate != ps_args) {
|
||||
errlogPrintf("lnkCalc: Unexpected array\n");
|
||||
return jlif_stop;
|
||||
@@ -325,9 +330,6 @@ static jlif_result lnkCalc_end_array(jlink *pjlink)
|
||||
{
|
||||
calc_link *clink = CONTAINER(pjlink, struct calc_link, jlink);
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("lnkCalc_end_array(calc@%p)\n", clink);
|
||||
|
||||
if (clink->pstate == ps_error)
|
||||
return jlif_stop;
|
||||
|
||||
@@ -339,15 +341,27 @@ static void lnkCalc_end_child(jlink *parent, jlink *child)
|
||||
calc_link *clink = CONTAINER(parent, struct calc_link, jlink);
|
||||
struct link *plink;
|
||||
|
||||
if (clink->nArgs == CALCPERFORM_NARGS) {
|
||||
dbJLinkFree(child);
|
||||
errlogPrintf("lnkCalc: Too many input args, limit is %d\n",
|
||||
CALCPERFORM_NARGS);
|
||||
if (clink->pstate == ps_args) {
|
||||
if (clink->nArgs == CALCPERFORM_NARGS) {
|
||||
errlogPrintf("lnkCalc: Too many input args, limit is %d\n",
|
||||
CALCPERFORM_NARGS);
|
||||
goto errOut;
|
||||
}
|
||||
|
||||
plink = &clink->inp[clink->nArgs++];
|
||||
}
|
||||
else if (clink->pstate == ps_out) {
|
||||
plink = &clink->out;
|
||||
}
|
||||
else {
|
||||
errlogPrintf("lnkCalc: Unexpected child link, parser state = %d\n",
|
||||
clink->pstate);
|
||||
errOut:
|
||||
clink->pstate = ps_error;
|
||||
dbJLinkFree(child);
|
||||
return;
|
||||
}
|
||||
|
||||
plink = &clink->inp[clink->nArgs++];
|
||||
plink->type = JSON_LINK;
|
||||
plink->value.json.string = NULL;
|
||||
plink->value.json.jlink = child;
|
||||
@@ -355,11 +369,6 @@ static void lnkCalc_end_child(jlink *parent, jlink *child)
|
||||
|
||||
static struct lset* lnkCalc_get_lset(const jlink *pjlink)
|
||||
{
|
||||
calc_link *clink = CONTAINER(pjlink, struct calc_link, jlink);
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("lnkCalc_get_lset(calc@%p)\n", pjlink);
|
||||
|
||||
return &lnkCalc_lset;
|
||||
}
|
||||
|
||||
@@ -368,9 +377,6 @@ static void lnkCalc_report(const jlink *pjlink, int level, int indent)
|
||||
calc_link *clink = CONTAINER(pjlink, struct calc_link, jlink);
|
||||
int i;
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("lnkCalc_report(calc@%p)\n", clink);
|
||||
|
||||
printf("%*s'calc': \"%s\" = %.*g %s\n", indent, "",
|
||||
clink->expr, clink->prec, clink->val,
|
||||
clink->units ? clink->units : "");
|
||||
@@ -388,9 +394,13 @@ static void lnkCalc_report(const jlink *pjlink, int level, int indent)
|
||||
printf("%*s Minor expression: \"%s\"\n", indent, "",
|
||||
clink->minor);
|
||||
|
||||
if (clink->tinp >= 0 && clink->tinp < clink->nArgs)
|
||||
printf("%*s Timestamp input \"%c\"\n", indent, "",
|
||||
clink->tinp + 'A');
|
||||
if (clink->tinp >= 0) {
|
||||
char timeStr[40];
|
||||
epicsTimeToStrftime(timeStr, 40, "%Y-%m-%d %H:%M:%S.%09f",
|
||||
&clink->time);
|
||||
printf("%*s Timestamp input %c: %s\n", indent, "",
|
||||
clink->tinp + 'A', timeStr);
|
||||
}
|
||||
|
||||
for (i = 0; i < clink->nArgs; i++) {
|
||||
struct link *plink = &clink->inp[i];
|
||||
@@ -403,17 +413,20 @@ static void lnkCalc_report(const jlink *pjlink, int level, int indent)
|
||||
if (child)
|
||||
dbJLinkReport(child, level - 1, indent + 4);
|
||||
}
|
||||
|
||||
if (clink->out.type == JSON_LINK) {
|
||||
printf("%*s Output:\n", indent, "");
|
||||
|
||||
dbJLinkReport(clink->out.value.json.jlink, level - 1, indent + 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
long lnkCalc_map_children(jlink *pjlink, jlink_map_fn rtn, void *ctx)
|
||||
static long lnkCalc_map_children(jlink *pjlink, jlink_map_fn rtn, void *ctx)
|
||||
{
|
||||
calc_link *clink = CONTAINER(pjlink, struct calc_link, jlink);
|
||||
int i;
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("lnkCalc_map_children(calc@%p)\n", clink);
|
||||
|
||||
for (i = 0; i < clink->nArgs; i++) {
|
||||
struct link *child = &clink->inp[i];
|
||||
long status = dbJLinkMapChildren(child, rtn, ctx);
|
||||
@@ -421,6 +434,10 @@ long lnkCalc_map_children(jlink *pjlink, jlink_map_fn rtn, void *ctx)
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
if (clink->out.type == JSON_LINK) {
|
||||
return dbJLinkMapChildren(&clink->out, rtn, ctx);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -432,9 +449,6 @@ static void lnkCalc_open(struct link *plink)
|
||||
struct calc_link, jlink);
|
||||
int i;
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("lnkCalc_open(calc@%p)\n", clink);
|
||||
|
||||
for (i = 0; i < clink->nArgs; i++) {
|
||||
struct link *child = &clink->inp[i];
|
||||
|
||||
@@ -442,6 +456,10 @@ static void lnkCalc_open(struct link *plink)
|
||||
dbJLinkInit(child);
|
||||
dbLoadLink(child, DBR_DOUBLE, &clink->arg[i]);
|
||||
}
|
||||
|
||||
if (clink->out.type == JSON_LINK) {
|
||||
dbJLinkInit(&clink->out);
|
||||
}
|
||||
}
|
||||
|
||||
static void lnkCalc_remove(struct dbLocker *locker, struct link *plink)
|
||||
@@ -450,15 +468,16 @@ static void lnkCalc_remove(struct dbLocker *locker, struct link *plink)
|
||||
struct calc_link, jlink);
|
||||
int i;
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("lnkCalc_remove(calc@%p)\n", clink);
|
||||
|
||||
for (i = 0; i < clink->nArgs; i++) {
|
||||
struct link *child = &clink->inp[i];
|
||||
|
||||
dbRemoveLink(locker, child);
|
||||
}
|
||||
|
||||
if (clink->out.type == JSON_LINK) {
|
||||
dbRemoveLink(locker, &clink->out);
|
||||
}
|
||||
|
||||
free(clink->expr);
|
||||
free(clink->major);
|
||||
free(clink->minor);
|
||||
@@ -477,9 +496,6 @@ static int lnkCalc_isConn(const struct link *plink)
|
||||
int connected = 1;
|
||||
int i;
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("lnkCalc_isConn(calc@%p)\n", clink);
|
||||
|
||||
for (i = 0; i < clink->nArgs; i++) {
|
||||
struct link *child = &clink->inp[i];
|
||||
|
||||
@@ -488,37 +504,24 @@ static int lnkCalc_isConn(const struct link *plink)
|
||||
connected = 0;
|
||||
}
|
||||
|
||||
if (clink->out.type == JSON_LINK) {
|
||||
struct link *child = &clink->out;
|
||||
|
||||
if (dbLinkIsVolatile(child) &&
|
||||
!dbIsLinkConnected(child))
|
||||
connected = 0;
|
||||
}
|
||||
|
||||
return connected;
|
||||
}
|
||||
|
||||
static int lnkCalc_getDBFtype(const struct link *plink)
|
||||
{
|
||||
calc_link *clink = CONTAINER(plink->value.json.jlink,
|
||||
struct calc_link, jlink);
|
||||
|
||||
IFDEBUG(10) {
|
||||
calc_link *clink = CONTAINER(plink->value.json.jlink,
|
||||
struct calc_link, jlink);
|
||||
|
||||
printf("lnkCalc_getDBFtype(calc@%p)\n", clink);
|
||||
}
|
||||
|
||||
return DBF_DOUBLE;
|
||||
}
|
||||
|
||||
static long lnkCalc_getElements(const struct link *plink, long *nelements)
|
||||
{
|
||||
calc_link *clink = CONTAINER(plink->value.json.jlink,
|
||||
struct calc_link, jlink);
|
||||
|
||||
IFDEBUG(10) {
|
||||
calc_link *clink = CONTAINER(plink->value.json.jlink,
|
||||
struct calc_link, jlink);
|
||||
|
||||
printf("lnkCalc_getElements(calc@%p, (%ld))\n",
|
||||
clink, *nelements);
|
||||
}
|
||||
|
||||
*nelements = 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -551,23 +554,22 @@ static long lnkCalc_getValue(struct link *plink, short dbrType, void *pbuffer,
|
||||
long status;
|
||||
FASTCONVERT conv = dbFastPutConvertRoutine[DBR_DOUBLE][dbrType];
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("lnkCalc_getValue(calc@%p, %d, ...)\n",
|
||||
clink, dbrType);
|
||||
|
||||
/* Any link errors will trigger a LINK/INVALID alarm in the child link */
|
||||
for (i = 0; i < clink->nArgs; i++) {
|
||||
struct link *child = &clink->inp[i];
|
||||
long nReq = 1;
|
||||
|
||||
if (i == clink->tinp &&
|
||||
dbLinkIsConstant(&prec->tsel) &&
|
||||
prec->tse == epicsTimeEventDeviceTime) {
|
||||
struct lcvt vt = {&clink->arg[i], &prec->time};
|
||||
if (i == clink->tinp) {
|
||||
struct lcvt vt = {&clink->arg[i], &clink->time};
|
||||
|
||||
status = dbLinkDoLocked(child, readLocked, &vt);
|
||||
if (status == S_db_noLSET)
|
||||
status = readLocked(child, &vt);
|
||||
|
||||
if (dbLinkIsConstant(&prec->tsel) &&
|
||||
prec->tse == epicsTimeEventDeviceTime) {
|
||||
prec->time = clink->time;
|
||||
}
|
||||
}
|
||||
else
|
||||
dbGetLink(child, DBR_DOUBLE, &clink->arg[i], NULL, &nReq);
|
||||
@@ -599,7 +601,7 @@ static long lnkCalc_getValue(struct link *plink, short dbrType, void *pbuffer,
|
||||
}
|
||||
}
|
||||
|
||||
if (!status && clink->post_minor) {
|
||||
if (!status && !clink->sevr && clink->post_minor) {
|
||||
double alval = clink->val;
|
||||
|
||||
status = calcPerform(clink->arg, &alval, clink->post_minor);
|
||||
@@ -613,14 +615,79 @@ static long lnkCalc_getValue(struct link *plink, short dbrType, void *pbuffer,
|
||||
return status;
|
||||
}
|
||||
|
||||
static long lnkCalc_putValue(struct link *plink, short dbrType,
|
||||
const void *pbuffer, long nRequest)
|
||||
{
|
||||
calc_link *clink = CONTAINER(plink->value.json.jlink,
|
||||
struct calc_link, jlink);
|
||||
dbCommon *prec = plink->precord;
|
||||
int i;
|
||||
long status;
|
||||
FASTCONVERT conv = dbFastGetConvertRoutine[dbrType][DBR_DOUBLE];
|
||||
|
||||
/* Any link errors will trigger a LINK/INVALID alarm in the child link */
|
||||
for (i = 0; i < clink->nArgs; i++) {
|
||||
struct link *child = &clink->inp[i];
|
||||
long nReq = 1;
|
||||
|
||||
if (i == clink->tinp) {
|
||||
struct lcvt vt = {&clink->arg[i], &clink->time};
|
||||
|
||||
status = dbLinkDoLocked(child, readLocked, &vt);
|
||||
if (status == S_db_noLSET)
|
||||
status = readLocked(child, &vt);
|
||||
|
||||
if (dbLinkIsConstant(&prec->tsel) &&
|
||||
prec->tse == epicsTimeEventDeviceTime) {
|
||||
prec->time = clink->time;
|
||||
}
|
||||
}
|
||||
else
|
||||
dbGetLink(child, DBR_DOUBLE, &clink->arg[i], NULL, &nReq);
|
||||
}
|
||||
clink->stat = 0;
|
||||
clink->sevr = 0;
|
||||
|
||||
/* Get the value being output as VAL */
|
||||
status = conv(pbuffer, &clink->val, NULL);
|
||||
|
||||
if (!status && clink->post_expr)
|
||||
status = calcPerform(clink->arg, &clink->val, clink->post_expr);
|
||||
|
||||
if (!status && clink->post_major) {
|
||||
double alval = clink->val;
|
||||
|
||||
status = calcPerform(clink->arg, &alval, clink->post_major);
|
||||
if (!status && alval) {
|
||||
clink->stat = LINK_ALARM;
|
||||
clink->sevr = MAJOR_ALARM;
|
||||
recGblSetSevr(prec, clink->stat, clink->sevr);
|
||||
}
|
||||
}
|
||||
|
||||
if (!status && !clink->sevr && clink->post_minor) {
|
||||
double alval = clink->val;
|
||||
|
||||
status = calcPerform(clink->arg, &alval, clink->post_minor);
|
||||
if (!status && alval) {
|
||||
clink->stat = LINK_ALARM;
|
||||
clink->sevr = MINOR_ALARM;
|
||||
recGblSetSevr(prec, clink->stat, clink->sevr);
|
||||
}
|
||||
}
|
||||
|
||||
if (!status) {
|
||||
status = dbPutLink(&clink->out, DBR_DOUBLE, &clink->val, 1);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static long lnkCalc_getPrecision(const struct link *plink, short *precision)
|
||||
{
|
||||
calc_link *clink = CONTAINER(plink->value.json.jlink,
|
||||
struct calc_link, jlink);
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("lnkCalc_getPrecision(calc@%p)\n", clink);
|
||||
|
||||
*precision = clink->prec;
|
||||
return 0;
|
||||
}
|
||||
@@ -630,9 +697,6 @@ static long lnkCalc_getUnits(const struct link *plink, char *units, int len)
|
||||
calc_link *clink = CONTAINER(plink->value.json.jlink,
|
||||
struct calc_link, jlink);
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("lnkCalc_getUnits(calc@%p)\n", clink);
|
||||
|
||||
if (clink->units) {
|
||||
strncpy(units, clink->units, --len);
|
||||
units[len] = '\0';
|
||||
@@ -648,9 +712,6 @@ static long lnkCalc_getAlarm(const struct link *plink, epicsEnum16 *status,
|
||||
calc_link *clink = CONTAINER(plink->value.json.jlink,
|
||||
struct calc_link, jlink);
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("lnkCalc_getAlarm(calc@%p)\n", clink);
|
||||
|
||||
if (status)
|
||||
*status = clink->stat;
|
||||
if (severity)
|
||||
@@ -659,6 +720,19 @@ static long lnkCalc_getAlarm(const struct link *plink, epicsEnum16 *status,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long lnkCalc_getTimestamp(const struct link *plink, epicsTimeStamp *pstamp)
|
||||
{
|
||||
calc_link *clink = CONTAINER(plink->value.json.jlink,
|
||||
struct calc_link, jlink);
|
||||
|
||||
if (clink->tinp >= 0) {
|
||||
*pstamp = clink->time;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static long doLocked(struct link *plink, dbLinkUserCallback rtn, void *priv)
|
||||
{
|
||||
return rtn(plink, priv);
|
||||
@@ -675,8 +749,8 @@ static lset lnkCalc_lset = {
|
||||
lnkCalc_getValue,
|
||||
NULL, NULL, NULL,
|
||||
lnkCalc_getPrecision, lnkCalc_getUnits,
|
||||
lnkCalc_getAlarm, NULL,
|
||||
NULL, NULL,
|
||||
lnkCalc_getAlarm, lnkCalc_getTimestamp,
|
||||
lnkCalc_putValue, NULL,
|
||||
NULL, doLocked
|
||||
};
|
||||
|
||||
@@ -686,6 +760,6 @@ static jlif lnkCalcIf = {
|
||||
lnkCalc_start_map, lnkCalc_map_key, lnkCalc_end_map,
|
||||
lnkCalc_start_array, lnkCalc_end_array,
|
||||
lnkCalc_end_child, lnkCalc_get_lset,
|
||||
lnkCalc_report, lnkCalc_map_children
|
||||
lnkCalc_report, lnkCalc_map_children, NULL
|
||||
};
|
||||
epicsExportAddress(jlif, lnkCalcIf);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (c) 2016 UChicago Argonne LLC, as Operator of Argonne
|
||||
* 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.
|
||||
\*************************************************************************/
|
||||
/* lnkConst.c */
|
||||
|
||||
@@ -22,8 +22,6 @@
|
||||
#include "epicsExport.h"
|
||||
|
||||
|
||||
#define IFDEBUG(n) if (clink->jlink.debug)
|
||||
|
||||
typedef long (*FASTCONVERT)();
|
||||
|
||||
typedef struct const_link {
|
||||
@@ -48,18 +46,23 @@ static lset lnkConst_lset;
|
||||
|
||||
static jlink* lnkConst_alloc(short dbfType)
|
||||
{
|
||||
const_link *clink = calloc(1, sizeof(*clink));
|
||||
const_link *clink;
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("lnkConst_alloc()\n");
|
||||
if (dbfType != DBF_INLINK) {
|
||||
errlogPrintf("lnkConst: Only works with input links\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
clink = calloc(1, sizeof(*clink));
|
||||
if (!clink) {
|
||||
errlogPrintf("lnkConst: calloc() failed.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
clink->type = s0;
|
||||
clink->nElems = 0;
|
||||
clink->value.pmem = NULL;
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("lnkConst_alloc -> const@%p\n", clink);
|
||||
|
||||
return &clink->jlink;
|
||||
}
|
||||
|
||||
@@ -67,9 +70,6 @@ static void lnkConst_free(jlink *pjlink)
|
||||
{
|
||||
const_link *clink = CONTAINER(pjlink, const_link, jlink);
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("lnkConst_free(const@%p) type=%d\n", pjlink, clink->type);
|
||||
|
||||
switch (clink->type) {
|
||||
int i;
|
||||
case ac40:
|
||||
@@ -95,16 +95,13 @@ static jlif_result lnkConst_integer(jlink *pjlink, long long num)
|
||||
const_link *clink = CONTAINER(pjlink, const_link, jlink);
|
||||
int newElems = clink->nElems + 1;
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("lnkConst_integer(const@%p, %lld)\n", pjlink, num);
|
||||
|
||||
switch (clink->type) {
|
||||
void *buf;
|
||||
|
||||
case s0:
|
||||
clink->type = si64;
|
||||
clink->value.scalar_integer = num;
|
||||
IFDEBUG(12)
|
||||
if (pjlink->debug)
|
||||
printf(" si64 := %lld\n", num);
|
||||
break;
|
||||
|
||||
@@ -118,7 +115,7 @@ static jlif_result lnkConst_integer(jlink *pjlink, long long num)
|
||||
|
||||
clink->value.pmem = buf;
|
||||
clink->value.pintegers[clink->nElems] = num;
|
||||
IFDEBUG(12)
|
||||
if (pjlink->debug)
|
||||
printf(" ai64 += %lld\n", num);
|
||||
break;
|
||||
|
||||
@@ -129,7 +126,7 @@ static jlif_result lnkConst_integer(jlink *pjlink, long long num)
|
||||
|
||||
clink->value.pmem = buf;
|
||||
clink->value.pdoubles[clink->nElems] = num;
|
||||
IFDEBUG(12)
|
||||
if (pjlink->debug)
|
||||
printf(" af64 += %lld\n", num);
|
||||
break;
|
||||
|
||||
@@ -146,10 +143,6 @@ static jlif_result lnkConst_integer(jlink *pjlink, long long num)
|
||||
|
||||
static jlif_result lnkConst_boolean(jlink *pjlink, int val)
|
||||
{
|
||||
const_link *clink = CONTAINER(pjlink, const_link, jlink);
|
||||
IFDEBUG(10)
|
||||
printf("lnkConst_boolean(const@%p, %d)\n", pjlink, val);
|
||||
|
||||
return lnkConst_integer(pjlink, val);
|
||||
}
|
||||
|
||||
@@ -158,9 +151,6 @@ static jlif_result lnkConst_double(jlink *pjlink, double num)
|
||||
const_link *clink = CONTAINER(pjlink, const_link, jlink);
|
||||
int newElems = clink->nElems + 1;
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("lnkConst_double(const@%p, %g)\n", pjlink, num);
|
||||
|
||||
switch (clink->type) {
|
||||
epicsFloat64 *f64buf;
|
||||
int i;
|
||||
@@ -212,9 +202,6 @@ static jlif_result lnkConst_string(jlink *pjlink, const char *val, size_t len)
|
||||
const_link *clink = CONTAINER(pjlink, const_link, jlink);
|
||||
int newElems = clink->nElems + 1;
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("lnkConst_string(const@%p, \"%.*s\")\n", clink, (int) len, val);
|
||||
|
||||
switch (clink->type) {
|
||||
char **vec, *str;
|
||||
|
||||
@@ -262,9 +249,6 @@ static jlif_result lnkConst_start_array(jlink *pjlink)
|
||||
{
|
||||
const_link *clink = CONTAINER(pjlink, const_link, jlink);
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("lnkConst_start_array(const@%p)\n", pjlink);
|
||||
|
||||
if (clink->type != s0) {
|
||||
errlogPrintf("lnkConst: Embedded array value\n");
|
||||
return jlif_stop;
|
||||
@@ -276,21 +260,11 @@ static jlif_result lnkConst_start_array(jlink *pjlink)
|
||||
|
||||
static jlif_result lnkConst_end_array(jlink *pjlink)
|
||||
{
|
||||
const_link *clink = CONTAINER(pjlink, const_link, jlink);
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("lnkConst_end_array(const@%p)\n", pjlink);
|
||||
|
||||
return jlif_continue;
|
||||
}
|
||||
|
||||
static struct lset* lnkConst_get_lset(const jlink *pjlink)
|
||||
{
|
||||
const_link *clink = CONTAINER(pjlink, const_link, jlink);
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("lnkConst_get_lset(const@%p)\n", pjlink);
|
||||
|
||||
return &lnkConst_lset;
|
||||
}
|
||||
|
||||
@@ -318,9 +292,6 @@ static void lnkConst_report(const jlink *pjlink, int level, int indent)
|
||||
};
|
||||
const char * const dtype = type_names[clink->type & 3];
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("lnkConst_report(const@%p)\n", clink);
|
||||
|
||||
if (clink->type > a0) {
|
||||
const char * const plural = clink->nElems > 1 ? "s" : "";
|
||||
|
||||
@@ -382,11 +353,6 @@ static void lnkConst_report(const jlink *pjlink, int level, int indent)
|
||||
|
||||
static void lnkConst_remove(struct dbLocker *locker, struct link *plink)
|
||||
{
|
||||
const_link *clink = CONTAINER(plink->value.json.jlink, const_link, jlink);
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("lnkConst_remove(const@%p)\n", clink);
|
||||
|
||||
lnkConst_free(plink->value.json.jlink);
|
||||
}
|
||||
|
||||
@@ -395,55 +361,51 @@ static long lnkConst_loadScalar(struct link *plink, short dbrType, void *pbuffer
|
||||
const_link *clink = CONTAINER(plink->value.json.jlink, const_link, jlink);
|
||||
long status;
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("lnkConst_loadScalar(const@%p, %d, %p)\n",
|
||||
clink, dbrType, pbuffer);
|
||||
|
||||
switch (clink->type) {
|
||||
case si64:
|
||||
IFDEBUG(12)
|
||||
if (clink->jlink.debug)
|
||||
printf(" si64 %lld\n", clink->value.scalar_integer);
|
||||
status = dbFastPutConvertRoutine[DBF_INT64][dbrType]
|
||||
(&clink->value.scalar_integer, pbuffer, NULL);
|
||||
break;
|
||||
|
||||
case sf64:
|
||||
IFDEBUG(12)
|
||||
if (clink->jlink.debug)
|
||||
printf(" sf64 %g\n", clink->value.scalar_double);
|
||||
status = dbFastPutConvertRoutine[DBF_DOUBLE][dbrType]
|
||||
(&clink->value.scalar_double, pbuffer, NULL);
|
||||
break;
|
||||
|
||||
case sc40:
|
||||
IFDEBUG(12)
|
||||
if (clink->jlink.debug)
|
||||
printf(" sc40 '%s'\n", clink->value.scalar_string);
|
||||
status = dbFastPutConvertRoutine[DBF_STRING][dbrType]
|
||||
(clink->value.scalar_string, pbuffer, NULL);
|
||||
break;
|
||||
|
||||
case ai64:
|
||||
IFDEBUG(12)
|
||||
if (clink->jlink.debug)
|
||||
printf(" ai64 [%lld, ...]\n", clink->value.pintegers[0]);
|
||||
status = dbFastPutConvertRoutine[DBF_INT64][dbrType]
|
||||
(clink->value.pintegers, pbuffer, NULL);
|
||||
break;
|
||||
|
||||
case af64:
|
||||
IFDEBUG(12)
|
||||
if (clink->jlink.debug)
|
||||
printf(" af64 [%g, ...]\n", clink->value.pdoubles[0]);
|
||||
status = dbFastPutConvertRoutine[DBF_DOUBLE][dbrType]
|
||||
(clink->value.pdoubles, pbuffer, NULL);
|
||||
break;
|
||||
|
||||
case ac40:
|
||||
IFDEBUG(12)
|
||||
if (clink->jlink.debug)
|
||||
printf(" ac40 ['%s', ...]\n", clink->value.pstrings[0]);
|
||||
status = dbFastPutConvertRoutine[DBF_STRING][dbrType]
|
||||
(clink->value.pstrings[0], pbuffer, NULL);
|
||||
break;
|
||||
|
||||
default:
|
||||
IFDEBUG(12)
|
||||
if (clink->jlink.debug)
|
||||
printf(" Bad type %d\n", clink->type);
|
||||
status = S_db_badField;
|
||||
break;
|
||||
@@ -458,27 +420,23 @@ static long lnkConst_loadLS(struct link *plink, char *pbuffer, epicsUInt32 size,
|
||||
const_link *clink = CONTAINER(plink->value.json.jlink, const_link, jlink);
|
||||
const char *pstr;
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("lnkConst_loadLS(const@%p, %p, %d, %d)\n",
|
||||
clink, pbuffer, size, *plen);
|
||||
|
||||
if(!size) return 0;
|
||||
|
||||
switch (clink->type) {
|
||||
case sc40:
|
||||
IFDEBUG(12)
|
||||
if (clink->jlink.debug)
|
||||
printf(" sc40 '%s'\n", clink->value.scalar_string);
|
||||
pstr = clink->value.scalar_string;
|
||||
break;
|
||||
|
||||
case ac40:
|
||||
IFDEBUG(12)
|
||||
if (clink->jlink.debug)
|
||||
printf(" ac40 ['%s', ...]\n", clink->value.pstrings[0]);
|
||||
pstr = clink->value.pstrings[0];
|
||||
break;
|
||||
|
||||
default:
|
||||
IFDEBUG(12)
|
||||
if (clink->jlink.debug)
|
||||
printf(" Bad type %d\n", clink->type);
|
||||
return S_db_badField;
|
||||
}
|
||||
@@ -499,10 +457,6 @@ static long lnkConst_loadArray(struct link *plink, short dbrType, void *pbuffer,
|
||||
FASTCONVERT conv;
|
||||
long status;
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("lnkConst_loadArray(const@%p, %d, %p, (%ld))\n",
|
||||
clink, dbrType, pbuffer, *pnReq);
|
||||
|
||||
if (nElems > *pnReq)
|
||||
nElems = *pnReq;
|
||||
|
||||
@@ -510,28 +464,28 @@ static long lnkConst_loadArray(struct link *plink, short dbrType, void *pbuffer,
|
||||
int i;
|
||||
|
||||
case si64:
|
||||
IFDEBUG(12)
|
||||
if (clink->jlink.debug)
|
||||
printf(" si64 %lld\n", clink->value.scalar_integer);
|
||||
status = dbFastPutConvertRoutine[DBF_INT64][dbrType]
|
||||
(&clink->value.scalar_integer, pdest, NULL);
|
||||
break;
|
||||
|
||||
case sf64:
|
||||
IFDEBUG(12)
|
||||
if (clink->jlink.debug)
|
||||
printf(" sf64 %g\n", clink->value.scalar_double);
|
||||
status = dbFastPutConvertRoutine[DBF_DOUBLE][dbrType]
|
||||
(&clink->value.scalar_double, pdest, NULL);
|
||||
break;
|
||||
|
||||
case sc40:
|
||||
IFDEBUG(12)
|
||||
if (clink->jlink.debug)
|
||||
printf(" sc40 '%s'\n", clink->value.scalar_string);
|
||||
status = dbFastPutConvertRoutine[DBF_STRING][dbrType]
|
||||
(clink->value.scalar_string, pbuffer, NULL);
|
||||
break;
|
||||
|
||||
case ai64:
|
||||
IFDEBUG(12)
|
||||
if (clink->jlink.debug)
|
||||
printf(" ai64 [%lld, ...]\n", clink->value.pintegers[0]);
|
||||
conv = dbFastPutConvertRoutine[DBF_INT64][dbrType];
|
||||
for (i = 0; i < nElems; i++) {
|
||||
@@ -542,7 +496,7 @@ static long lnkConst_loadArray(struct link *plink, short dbrType, void *pbuffer,
|
||||
break;
|
||||
|
||||
case af64:
|
||||
IFDEBUG(12)
|
||||
if (clink->jlink.debug)
|
||||
printf(" af64 [%g, ...]\n", clink->value.pdoubles[0]);
|
||||
conv = dbFastPutConvertRoutine[DBF_DOUBLE][dbrType];
|
||||
for (i = 0; i < nElems; i++) {
|
||||
@@ -553,7 +507,7 @@ static long lnkConst_loadArray(struct link *plink, short dbrType, void *pbuffer,
|
||||
break;
|
||||
|
||||
case ac40:
|
||||
IFDEBUG(12)
|
||||
if (clink->jlink.debug)
|
||||
printf(" ac40 ['%s', ...]\n", clink->value.pstrings[0]);
|
||||
conv = dbFastPutConvertRoutine[DBF_STRING][dbrType];
|
||||
for (i = 0; i < nElems; i++) {
|
||||
@@ -564,7 +518,7 @@ static long lnkConst_loadArray(struct link *plink, short dbrType, void *pbuffer,
|
||||
break;
|
||||
|
||||
default:
|
||||
IFDEBUG(12)
|
||||
if (clink->jlink.debug)
|
||||
printf(" Bad type %d\n", clink->type);
|
||||
status = S_db_badField;
|
||||
}
|
||||
@@ -574,12 +528,6 @@ static long lnkConst_loadArray(struct link *plink, short dbrType, void *pbuffer,
|
||||
|
||||
static long lnkConst_getNelements(const struct link *plink, long *nelements)
|
||||
{
|
||||
const_link *clink = CONTAINER(plink->value.json.jlink, const_link, jlink);
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("lnkConst_getNelements(const@%p, (%ld))\n",
|
||||
plink->value.json.jlink, *nelements);
|
||||
|
||||
*nelements = 0;
|
||||
return 0;
|
||||
}
|
||||
@@ -587,13 +535,6 @@ static long lnkConst_getNelements(const struct link *plink, long *nelements)
|
||||
static long lnkConst_getValue(struct link *plink, short dbrType, void *pbuffer,
|
||||
long *pnRequest)
|
||||
{
|
||||
const_link *clink = CONTAINER(plink->value.json.jlink, const_link, jlink);
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("lnkConst_getValue(const@%p, %d, %p, ... (%ld))\n",
|
||||
plink->value.json.jlink, dbrType, pbuffer,
|
||||
pnRequest ? *pnRequest : 0);
|
||||
|
||||
if (pnRequest)
|
||||
*pnRequest = 0;
|
||||
return 0;
|
||||
@@ -626,7 +567,6 @@ static jlif lnkConstIf = {
|
||||
NULL, NULL, NULL,
|
||||
lnkConst_start_array, lnkConst_end_array,
|
||||
NULL, lnkConst_get_lset,
|
||||
lnkConst_report, NULL
|
||||
lnkConst_report, NULL, NULL
|
||||
};
|
||||
epicsExportAddress(jlif, lnkConstIf);
|
||||
|
||||
|
||||
1045
modules/database/src/std/link/lnkDebug.c
Normal file
1045
modules/database/src/std/link/lnkDebug.c
Normal file
File diff suppressed because it is too large
Load Diff
230
modules/database/src/std/link/lnkState.c
Normal file
230
modules/database/src/std/link/lnkState.c
Normal file
@@ -0,0 +1,230 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2017 UChicago Argonne LLC, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/* lnkState.c */
|
||||
|
||||
/* Usage:
|
||||
* {state:green}
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "alarm.h"
|
||||
#include "dbDefs.h"
|
||||
#include "errlog.h"
|
||||
#include "epicsAssert.h"
|
||||
#include "epicsString.h"
|
||||
#include "epicsTypes.h"
|
||||
#include "dbAccessDefs.h"
|
||||
#include "dbCommon.h"
|
||||
#include "dbConvertFast.h"
|
||||
#include "dbLink.h"
|
||||
#include "dbJLink.h"
|
||||
#include "dbStaticLib.h"
|
||||
#include "dbStaticPvt.h"
|
||||
#include "dbState.h"
|
||||
#include "recGbl.h"
|
||||
#include "epicsExport.h"
|
||||
|
||||
|
||||
typedef long (*FASTCONVERT)();
|
||||
|
||||
typedef struct state_link {
|
||||
jlink jlink; /* embedded object */
|
||||
char *name;
|
||||
short val;
|
||||
short invert;
|
||||
dbStateId state;
|
||||
} state_link;
|
||||
|
||||
static lset lnkState_lset;
|
||||
|
||||
|
||||
/*************************** jlif Routines **************************/
|
||||
|
||||
static jlink* lnkState_alloc(short dbfType)
|
||||
{
|
||||
state_link *slink;
|
||||
|
||||
if (dbfType == DBF_FWDLINK) {
|
||||
errlogPrintf("lnkState: DBF_FWDLINK not supported\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
slink = calloc(1, sizeof(struct state_link));
|
||||
if (!slink) {
|
||||
errlogPrintf("lnkState: calloc() failed.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
slink->name = NULL;
|
||||
slink->state = NULL;
|
||||
slink->invert = 0;
|
||||
slink->val = 0;
|
||||
|
||||
return &slink->jlink;
|
||||
}
|
||||
|
||||
static void lnkState_free(jlink *pjlink)
|
||||
{
|
||||
state_link *slink = CONTAINER(pjlink, struct state_link, jlink);
|
||||
|
||||
free(slink->name);
|
||||
free(slink);
|
||||
}
|
||||
|
||||
static jlif_result lnkState_string(jlink *pjlink, const char *val, size_t len)
|
||||
{
|
||||
state_link *slink = CONTAINER(pjlink, struct state_link, jlink);
|
||||
|
||||
if (len > 1 && val[0] == '!') {
|
||||
slink->invert = 1;
|
||||
val++; len--;
|
||||
}
|
||||
|
||||
slink->name = epicsStrnDup(val, len);
|
||||
return jlif_continue;
|
||||
}
|
||||
|
||||
static struct lset* lnkState_get_lset(const jlink *pjlink)
|
||||
{
|
||||
return &lnkState_lset;
|
||||
}
|
||||
|
||||
static void lnkState_report(const jlink *pjlink, int level, int indent)
|
||||
{
|
||||
state_link *slink = CONTAINER(pjlink, struct state_link, jlink);
|
||||
|
||||
printf("%*s'state': \"%s\" = %s%s\n", indent, "",
|
||||
slink->name, slink->invert ? "! " : "", slink->val ? "TRUE" : "FALSE");
|
||||
}
|
||||
|
||||
/*************************** lset Routines **************************/
|
||||
|
||||
static void lnkState_open(struct link *plink)
|
||||
{
|
||||
state_link *slink = CONTAINER(plink->value.json.jlink,
|
||||
struct state_link, jlink);
|
||||
|
||||
slink->state = dbStateCreate(slink->name);
|
||||
}
|
||||
|
||||
static void lnkState_remove(struct dbLocker *locker, struct link *plink)
|
||||
{
|
||||
state_link *slink = CONTAINER(plink->value.json.jlink,
|
||||
struct state_link, jlink);
|
||||
|
||||
free(slink->name);
|
||||
free(slink);
|
||||
|
||||
plink->value.json.jlink = NULL;
|
||||
}
|
||||
|
||||
static int lnkState_getDBFtype(const struct link *plink)
|
||||
{
|
||||
return DBF_SHORT;
|
||||
}
|
||||
|
||||
static long lnkState_getElements(const struct link *plink, long *nelements)
|
||||
{
|
||||
*nelements = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long lnkState_getValue(struct link *plink, short dbrType, void *pbuffer,
|
||||
long *pnRequest)
|
||||
{
|
||||
state_link *slink = CONTAINER(plink->value.json.jlink,
|
||||
struct state_link, jlink);
|
||||
FASTCONVERT conv = dbFastPutConvertRoutine[DBR_SHORT][dbrType];
|
||||
|
||||
slink->val = slink->invert ^ dbStateGet(slink->state);
|
||||
return conv(&slink->val, pbuffer, NULL);
|
||||
}
|
||||
|
||||
static long lnkState_putValue(struct link *plink, short dbrType,
|
||||
const void *pbuffer, long nRequest)
|
||||
{
|
||||
state_link *slink = CONTAINER(plink->value.json.jlink,
|
||||
struct state_link, jlink);
|
||||
short val;
|
||||
const char *pstr;
|
||||
|
||||
if (nRequest == 0)
|
||||
return 0;
|
||||
|
||||
switch(dbrType) {
|
||||
case DBR_CHAR:
|
||||
case DBR_UCHAR:
|
||||
val = !! *(const epicsInt8 *) pbuffer;
|
||||
break;
|
||||
|
||||
case DBR_SHORT:
|
||||
case DBR_USHORT:
|
||||
val = !! *(const epicsInt16 *) pbuffer;
|
||||
break;
|
||||
|
||||
case DBR_LONG:
|
||||
case DBR_ULONG:
|
||||
val = !! *(const epicsInt32 *) pbuffer;
|
||||
break;
|
||||
|
||||
case DBR_INT64:
|
||||
case DBR_UINT64:
|
||||
val = !! *(const epicsInt64 *) pbuffer;
|
||||
break;
|
||||
|
||||
case DBR_FLOAT:
|
||||
val = !! *(const epicsFloat32 *) pbuffer;
|
||||
break;
|
||||
|
||||
case DBR_DOUBLE:
|
||||
val = !! *(const epicsFloat64 *) pbuffer;
|
||||
break;
|
||||
|
||||
case DBR_STRING: /* Only "" and "0" are FALSE */
|
||||
pstr = (const char *) pbuffer;
|
||||
val = (pstr[0] != 0) && ((pstr[0] != '0') || (pstr[1] != 0));
|
||||
break;
|
||||
|
||||
default:
|
||||
return S_db_badDbrtype;
|
||||
}
|
||||
slink->val = val;
|
||||
|
||||
val ^= slink->invert;
|
||||
(val ? dbStateSet : dbStateClear)(slink->state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/************************* Interface Tables *************************/
|
||||
|
||||
static lset lnkState_lset = {
|
||||
0, 0, /* not constant, always connected */
|
||||
lnkState_open, lnkState_remove,
|
||||
NULL, NULL, NULL,
|
||||
NULL, lnkState_getDBFtype, lnkState_getElements,
|
||||
lnkState_getValue,
|
||||
NULL, NULL, NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL,
|
||||
lnkState_putValue, NULL,
|
||||
NULL, NULL
|
||||
};
|
||||
|
||||
static jlif lnkStateIf = {
|
||||
"state", lnkState_alloc, lnkState_free,
|
||||
NULL, NULL, NULL, NULL, lnkState_string,
|
||||
NULL, NULL, NULL,
|
||||
NULL, NULL,
|
||||
NULL, lnkState_get_lset,
|
||||
lnkState_report, NULL, NULL
|
||||
};
|
||||
epicsExportAddress(jlif, lnkStateIf);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user