Compare commits
80 Commits
PSI-7.0
...
PSI-7.0.9.
| Author | SHA1 | Date | |
|---|---|---|---|
| fba76ea5a5 | |||
| 30144507dd | |||
| 4a435e39a0 | |||
| 1f37f51009 | |||
| 595bb8fb62 | |||
| 58debe99ed | |||
| 0648f31d4a | |||
| 3e5789afa6 | |||
| eec358d70a | |||
| 324ce2471f | |||
| 837c675492 | |||
| eebd0609d7 | |||
| 315c2e1b1d | |||
|
|
ff42c52668 | ||
| 5d9a80da56 | |||
|
|
72f0fd0d42 | ||
|
|
7f3c1630a5 | ||
|
|
dccc79e632 | ||
|
|
04e0a01f10 | ||
|
|
36fcdb18d0 | ||
|
|
0d1ac63179 | ||
|
|
fa8a042481 | ||
|
|
a13dfac124 | ||
|
|
3c7f759d86 | ||
|
|
c1bc9a2b54 | ||
|
|
46d80bf50e | ||
|
|
54c69ad5fa | ||
| 18d61eda06 | |||
|
|
d7286cd956 | ||
| 015cb45289 | |||
| 8d92ac315c | |||
| f6dc2b8723 | |||
| 2d72ba44a9 | |||
| 05d8613e85 | |||
| 4da9e78de1 | |||
| ec00f65236 | |||
| 15c68ff3d3 | |||
| 1918aebf97 | |||
|
|
a2e01c2929 | ||
|
|
280aa0b399 | ||
|
|
9af7ff3b3f | ||
|
|
aba6309604 | ||
|
|
cb0688c850 | ||
| 54ca2cb595 | |||
| f5a5e7c5f7 | |||
| 47c263112f | |||
| a781896e28 | |||
| 3600924f99 | |||
| 232d9bec10 | |||
|
|
271f20faa0 | ||
|
|
d763541341 | ||
|
|
eff502217c | ||
|
|
bd8c35d8e7 | ||
|
|
acd1aef2a0 | ||
|
|
d00ce1bc0a | ||
|
|
4c4f2f075f | ||
|
|
1cea3f1eed | ||
|
|
7444936a22 | ||
|
|
edd99a903b | ||
|
|
e4fbd83c93 | ||
|
|
2e26ec09a6 | ||
|
|
9ce921f4fd | ||
|
|
187801c2e6 | ||
| c3c492d2cd | |||
| bff913e4d1 | |||
| 4c40b9f4bb | |||
| 640ced41c3 | |||
| 5c77c842a4 | |||
| 79624b72e5 | |||
|
|
15ed1643cd | ||
| 007df69726 | |||
|
|
5ae9cc6536 | ||
|
|
ff1fb82ef2 | ||
|
|
f4e1019ebe | ||
|
|
f29137b985 | ||
|
|
38c11d3afe | ||
|
|
dc776b547a | ||
|
|
4dd01aa9b6 | ||
|
|
d724779abf | ||
|
|
26cb0dcbdc |
16
.github/workflows/ci-scripts-build.yml
vendored
16
.github/workflows/ci-scripts-build.yml
vendored
@@ -157,13 +157,25 @@ jobs:
|
||||
cmp: vs2022
|
||||
configuration: debug
|
||||
name: "Win-22 MSC-22"
|
||||
extra: "CMD_CXXFLAGS=-analysis"
|
||||
extra: "CMD_CXXFLAGS=-analyze"
|
||||
|
||||
- os: windows-2022
|
||||
cmp: vs2022
|
||||
configuration: debug
|
||||
name: "Win-22 MSC-22 c++14"
|
||||
extra: "CMD_CXXFLAGS='-analyze -Zc:__cplusplus -std:c++17'"
|
||||
|
||||
- os: windows-2022
|
||||
cmp: vs2022
|
||||
configuration: debug
|
||||
name: "Win-22 MSC-22 c++17"
|
||||
extra: "CMD_CXXFLAGS='-analyze -Zc:__cplusplus -std:c++17'"
|
||||
|
||||
- os: windows-2022
|
||||
cmp: vs2022
|
||||
configuration: static-debug
|
||||
name: "Win-22 MSC-22, static"
|
||||
extra: "CMD_CXXFLAGS=-analysis"
|
||||
extra: "CMD_CXXFLAGS=-analyze"
|
||||
|
||||
- os: windows-2022
|
||||
cmp: vs2022
|
||||
|
||||
13
.gitignore
vendored
13
.gitignore
vendored
@@ -1,3 +1,5 @@
|
||||
# Before adding patterns here, please read the gitignore
|
||||
# documentation at https://git-scm.com/docs/gitignore
|
||||
/cfg/
|
||||
/bin/
|
||||
/lib/
|
||||
@@ -11,14 +13,13 @@
|
||||
/modules/RELEASE.*.local
|
||||
/modules/Makefile.local
|
||||
O.*/
|
||||
/QtC-*
|
||||
/.qtc_*
|
||||
/.vscode/
|
||||
*.orig
|
||||
*.log
|
||||
.*.swp
|
||||
.DS_Store
|
||||
.iocsh_history
|
||||
|
||||
# Common files generated by other tools
|
||||
.DS_Store
|
||||
|
||||
# Files created by rpmbuild
|
||||
RPMS
|
||||
SRPMS
|
||||
BUILDROOT
|
||||
|
||||
10
README
10
README
@@ -13,15 +13,7 @@ this distribution.
|
||||
|
||||
---------------------------------------------------------
|
||||
|
||||
Installation and release information can be found in the
|
||||
various files in the documentation subdirectory.
|
||||
|
||||
Additional information about EPICS including mailing list
|
||||
archives and subscription instructions, documentation and
|
||||
training materials, additional components, links to other
|
||||
websites etc. is available on the EPICS home page at
|
||||
https://epics.anl.gov/
|
||||
For more information, see the README.md file.
|
||||
|
||||
$Format:%cD$
|
||||
$Format:%H$
|
||||
https://code.launchpad.net/epics-base
|
||||
|
||||
64
README.md
Normal file
64
README.md
Normal file
@@ -0,0 +1,64 @@
|
||||
|
||||
# EPICS Base
|
||||
|
||||
EPICS (Experimental Physics and Industrial Control System) is a set of software
|
||||
tools and applications which provide a software infrastructure for use in
|
||||
building distributed control systems to operate devices such as Particle
|
||||
Accelerators, Large Experiments and major Telescopes. EPICS Base is the central
|
||||
core of the control system toolkit. More details can be found at the
|
||||
[About page of the official website](https://epics-controls.org/about-epics/)
|
||||
|
||||
## Links
|
||||
|
||||
- [Official Website](https://epics-controls.org/)
|
||||
- [Original Website](https://epics.anl.gov/)
|
||||
- [Repository](https://github.com/epics-base/epics-base)
|
||||
|
||||
### Documentation
|
||||
|
||||
- [Documentation](https://docs.epics-controls.org/en/latest/)
|
||||
- [Documentation Repository](https://github.com/epics-docs/epics-docs)
|
||||
|
||||
### Community Communication
|
||||
|
||||
- [Tech-Talk Mailing List](https://epics.anl.gov/tech-talk/)
|
||||
- [Matrix Rooms](https://matrix.to/#/#epics:epics-controls.org)
|
||||
- [News](https://epics-controls.org/news-and-events/)
|
||||
|
||||
## Quick Install
|
||||
|
||||
Download a release from the
|
||||
[Downloads page](https://epics-controls.org/resources-and-support/base/downloads)
|
||||
and unpack it. Inside the unpacked folder run:
|
||||
|
||||
```bash
|
||||
make
|
||||
```
|
||||
|
||||
For more information on how to install on your system see the
|
||||
[Installation page](https://docs.epics-controls.org/en/latest/getting-started/installation.html)
|
||||
of the documentation.
|
||||
|
||||
### Quick run a softIOC
|
||||
|
||||
After building, you can run an example soft-IOC (Input/Output Controller)
|
||||
which runs a Channel Access server.
|
||||
|
||||
```bash
|
||||
./bin/*/softIoc -x first
|
||||
```
|
||||
|
||||
Run the `dbl` command to list the records it provides:
|
||||
|
||||
```bash
|
||||
epics> dbl
|
||||
first:BaseVersion
|
||||
first:exit
|
||||
epics>
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
EPICS Base is distributed subject to a Software License
|
||||
Agreement found in the file [LICENSE](./LICENSE) that is included with
|
||||
this distribution.
|
||||
@@ -65,7 +65,7 @@ LOADABLE_SHRLIB_LDFLAGS = -shared -fPIC -Wl,-h$@
|
||||
|
||||
GNU_LDLIBS_YES = -lgcc
|
||||
|
||||
# Use compiler flags to generate header dependancies files
|
||||
# Use compiler flags to generate header dependencies files
|
||||
HDEPENDS_METHOD = COMP
|
||||
HDEPENDS_COMPFLAGS = -MM -MF $@
|
||||
|
||||
|
||||
@@ -17,14 +17,14 @@ ARCMD = $(MSVC_PREFIX)lib$(MSVC_SUFFIX) -nologo -verbose -out:$@ $(LIB_OPT_LDFLA
|
||||
CC = cl
|
||||
|
||||
# OS vendor c preprocessor
|
||||
CPP = $(CC) -nologo -C -E
|
||||
CPP = $(CC) -C -E
|
||||
|
||||
# Configure OS vendor C++ compiler
|
||||
#
|
||||
# -EHsc - generate code for exceptions
|
||||
# -GR - generate code for run time type identification
|
||||
#
|
||||
CCC = $(CC) -EHsc -GR
|
||||
CCC = $(CC) -EHsc -GR -Zc:__cplusplus
|
||||
|
||||
# Override CONFIG.gnuCommon settings for cross builds.
|
||||
GNU = NO
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
# These rules apply to these Makefile-variables:
|
||||
# USR_CFLAGS C flags
|
||||
# USR_CXXFLAGS C++ flags
|
||||
# USR_CPPFLAGS c preprocesser flags
|
||||
# USR_CPPFLAGS c preprocessor flags
|
||||
# SRCS source files for building libraries and prods
|
||||
# USR_SRCS source files for building libraries and prods
|
||||
# PROD_SRCS source files for building prods
|
||||
|
||||
@@ -147,7 +147,7 @@ CMPLR_SRC_DIRS += . $(foreach dir, .. $(SRC_DIRS), \
|
||||
ALL_SRC_DIRS = $(CMPLR_SRC_DIRS) $(OS_SRC_DIRS) $(GENERIC_SRC_DIRS)
|
||||
|
||||
#--------------------------------------------------
|
||||
# Directory for OS independant build created files
|
||||
# Directory for OS independent build created files
|
||||
COMMON_DIR = ../O.Common
|
||||
|
||||
# compile line include directories
|
||||
|
||||
@@ -53,3 +53,5 @@ EPICS_IOC_IGNORE_SERVERS=""
|
||||
# EPICS_IOC_LOG_PORT Log server port number etc.
|
||||
EPICS_IOC_LOG_PORT=7004
|
||||
|
||||
# Posix priority scheduling
|
||||
EPICS_ALLOW_POSIX_THREAD_PRIORITY_SCHEDULING=YES
|
||||
|
||||
@@ -55,7 +55,7 @@ DBD += $(foreach type, $(CROSS_TARGET_OS_TYPES), $(DBD_$(type)))
|
||||
# DBD_solaris += abcSolaris.dbd
|
||||
#
|
||||
# ---------------------------------------------------
|
||||
# DBD concatination files
|
||||
# DBD concatenation files
|
||||
|
||||
COMMON_DBDCATS += $(addprefix $(COMMON_DIR)/,$(DBDCAT))
|
||||
DBDCAT_SOURCES += $(foreach file, $($*_DBD), $(DBDCAT_SOURCE) )
|
||||
@@ -194,7 +194,7 @@ ifneq (,$(strip $(DBDDEPENDS_FILES)))
|
||||
endif
|
||||
|
||||
#---------------------------------------------------------------
|
||||
# build dependancies, clean rule
|
||||
# build dependencies, clean rule
|
||||
|
||||
inc: $(COMMON_INC) $(INSTALL_INC) $(COMMON_DBDS) $(COMMON_DBDCATS) \
|
||||
$(INSTALL_DBDS) $(INSTALL_DBD_INSTALLS) $(COMMON_DOCS)
|
||||
|
||||
@@ -32,7 +32,7 @@ ifneq ($(RELEASE_CFG_DIR_RULES),)
|
||||
include $(RELEASE_CFG_DIR_RULES)
|
||||
endif
|
||||
|
||||
# Create EPICS_HOST_ARCH dependancies for GNU make -j option.
|
||||
# Create EPICS_HOST_ARCH dependencies for GNU make -j option.
|
||||
# Needed in dirs where EPICS_HOST_ARCH build creates a tool used in
|
||||
# cross arch builds
|
||||
|
||||
|
||||
@@ -214,7 +214,7 @@ $(sort $(DIRECTORY_TARGETS)):
|
||||
$(MKDIR) $@
|
||||
|
||||
# Install LIB_INSTALLS libraries before linking executables
|
||||
$(TESTPRODNAME) $(PRODNAME): | $(INSTALL_LIB_INSTALLS)
|
||||
$(TESTPRODNAME) $(PRODNAME): | $(INSTALL_LIB_INSTALLS) $(TESTSHRLIBNAME)
|
||||
|
||||
# Install built libraries too, unless Makefile says to wait
|
||||
ifneq ($(DELAY_INSTALL_LIBS),YES)
|
||||
|
||||
@@ -44,7 +44,7 @@ $(foreach dir, $(DIRS), $(dir)$(DIVIDER)install): \
|
||||
rebuild: $(foreach dir, $(DIRS), $(dir)$(DIVIDER)install)
|
||||
endif
|
||||
|
||||
# Create directory dependancies lines for GNU make -j option
|
||||
# Create directory dependencies lines for GNU make -j option
|
||||
# Only works with GNU make 3.81 or later (uses eval function)
|
||||
define DEP_template1
|
||||
$(1): $$($(1)_DEPEND_DIRS)
|
||||
|
||||
@@ -82,7 +82,7 @@ INC = file.h
|
||||
# Platform specific files can also be put in
|
||||
# separate os/OS_CLASS directories!
|
||||
#
|
||||
# For almost every file the seach order is:
|
||||
# For almost every file the search order is:
|
||||
# ./os/OS_CLASS
|
||||
# ./os/generic
|
||||
# .
|
||||
@@ -136,11 +136,11 @@ PROD_SRCS = ppp.c qqq.c
|
||||
a_file_SRCS = aa.c bb.c
|
||||
|
||||
#
|
||||
# EPICS libs needed to link PROD, TESTPROD and sharable library
|
||||
# EPICS libs needed to link PROD, TESTPROD and shareable library
|
||||
#
|
||||
# note that DLL_LIBS (the libraries needed to link a shareable
|
||||
# library) is created by default from the PROD/SYS libraries specified
|
||||
# below minus the name of the sharable library (LIBRARY)
|
||||
# below minus the name of the shareable library (LIBRARY)
|
||||
#
|
||||
#
|
||||
# ---------- libraries for a specific product pppp
|
||||
@@ -169,7 +169,7 @@ USR_LIBS_DEFAULT = foolib
|
||||
USR_LIBS_WIN32 = -nil-
|
||||
foolib_DIR = $(FOO_LIB)
|
||||
|
||||
# system libs needed to link PROD, TESTPROD and sharable library
|
||||
# system libs needed to link PROD, TESTPROD and shareable library
|
||||
#
|
||||
# ---------- system libraries for all products
|
||||
# for all systems:
|
||||
|
||||
@@ -4,8 +4,9 @@ include $(CONFIG)/os/CONFIG.Common.linux-x86_64
|
||||
BUILD_CLASS = HOST
|
||||
|
||||
TOOLSET_LOCATION = /opt/rh
|
||||
TOOLSET = gcc-toolset-12
|
||||
TOOLSET = gcc-toolset-15
|
||||
STD_CXXFLAGS = -std=c++20
|
||||
STD_CFLAGS = -std=c17
|
||||
|
||||
# Fix bug in gcc-toolset-11 calling the old assembler
|
||||
ifneq ($(filter %-11,$(TOOLSET)),)
|
||||
|
||||
@@ -4,8 +4,9 @@ include $(CONFIG)/os/CONFIG.Common.linux-x86_64
|
||||
BUILD_CLASS = HOST
|
||||
|
||||
TOOLSET_LOCATION = /opt/rh
|
||||
TOOLSET = gcc-toolset-12
|
||||
TOOLSET = gcc-toolset-15
|
||||
STD_CXXFLAGS = -std=c++20
|
||||
STD_CFLAGS = -std=c17
|
||||
|
||||
# Fix bug in gcc-toolset-11 calling the old assembler
|
||||
ifneq ($(filter %-11,$(TOOLSET)),)
|
||||
|
||||
@@ -9,7 +9,7 @@ RTEMS_BSP = beagleboneblack
|
||||
RTEMS_TARGET_CPU = arm
|
||||
GNU_TARGET = arm-rtems
|
||||
|
||||
OP_SYS_LDLIBS += -Wl,--gc-sections
|
||||
OP_SYS_LDFLAGS += -Wl,--gc-sections
|
||||
ARCH_DEP_LDFLAGS = -L$(RTEMS_BASE)/$(GNU_TARGET)$(RTEMS_VERSION)/beagleboneblack/lib/
|
||||
|
||||
include $(CONFIG)/os/CONFIG.Common.RTEMS
|
||||
|
||||
@@ -20,7 +20,6 @@ define MUNCH_CMD
|
||||
$(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary -R .comment -S $< $@
|
||||
endef
|
||||
|
||||
OP_SYS_LDLIBS += -Wl,--gc-sections
|
||||
ARCH_DEP_LDFLAGS = -L$(RTEMS_BASE)/$(GNU_TARGET)$(RTEMS_VERSION)/pc686/lib/
|
||||
|
||||
include $(CONFIG)/os/CONFIG.Common.RTEMS
|
||||
@@ -28,7 +27,7 @@ include $(CONFIG)/os/CONFIG.Common.RTEMS
|
||||
#
|
||||
# Put text segment where it will work with etherboot
|
||||
#
|
||||
OP_SYS_LDFLAGS += -Wl,-Ttext,0x100000
|
||||
OP_SYS_LDFLAGS += -Wl,-Ttext,0x100000 -Wl,--gc-sections
|
||||
|
||||
|
||||
# This check must appear after the above include
|
||||
|
||||
@@ -20,7 +20,7 @@ ARCH_DEP_CFLAGS += -DRTEMS_HAS_ALTIVEC
|
||||
#ARCH_DEP_CFLAGS += -I$(RTEMS_BASE)/powerpc-rtems5/qoriq_e500/lib/include
|
||||
|
||||
#OP_SYS_LDLIBS += -lbspExt #does not use posix stuff ... want to ignore
|
||||
OP_SYS_LDLIBS += -Wl,--gc-sections
|
||||
OP_SYS_LDFLAGS += -Wl,--gc-sections
|
||||
#ARCH_DEP_LDFLAGS = -mcpu=8540 -meabi -msdata=sysv -mstrict-align -mspe -mabi=spe -mfloat-gprs=double
|
||||
ARCH_DEP_LDFLAGS = -L$(RTEMS_BASE)/$(GNU_TARGET)$(RTEMS_VERSION)/$(RTEMS_BSP)/lib
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ GNU_TARGET = arm-rtems
|
||||
#use dhcp/bootp
|
||||
ARCH_DEP_CFLAGS += -DMY_DO_BOOTP=NULL
|
||||
|
||||
OP_SYS_LDLIBS += -Wl,--gc-sections
|
||||
OP_SYS_LDFLAGS += -Wl,--gc-sections
|
||||
ARCH_DEP_LDFLAGS = -L$(RTEMS_BASE)/$(GNU_TARGET)$(RTEMS_VERSION)/xilinx_zynq_a9_qemu/lib/
|
||||
|
||||
|
||||
|
||||
16
configure/os/CONFIG.Common.RTEMS-xilinx_zynq_microzed
Normal file
16
configure/os/CONFIG.Common.RTEMS-xilinx_zynq_microzed
Normal file
@@ -0,0 +1,16 @@
|
||||
#
|
||||
# CONFIG.Common.RTEMS-xilinx_zynq_microzed
|
||||
# Author: Chris Johns <chris@contemporary.software>
|
||||
#
|
||||
# All RTEMS targets use the same Makefile fragment
|
||||
#
|
||||
#EXE = .elf
|
||||
RTEMS_BSP = xilinx_zynq_microzed
|
||||
RTEMS_TARGET_CPU = arm
|
||||
GNU_TARGET = arm-rtems
|
||||
|
||||
OP_SYS_LDLIBS += -Wl,--gc-sections
|
||||
ARCH_DEP_LDFLAGS = -L$(RTEMS_BASE)/$(GNU_TARGET)$(RTEMS_VERSION)/xilinx_zynq_microzed/lib/
|
||||
|
||||
|
||||
include $(CONFIG)/os/CONFIG.Common.RTEMS
|
||||
@@ -9,7 +9,7 @@ RTEMS_BSP = xilinx_zynq_zedboard
|
||||
RTEMS_TARGET_CPU = arm
|
||||
GNU_TARGET = arm-rtems
|
||||
|
||||
OP_SYS_LDLIBS += -Wl,--gc-sections
|
||||
OP_SYS_LDFLAGS += -Wl,--gc-sections
|
||||
ARCH_DEP_LDFLAGS = -L$(RTEMS_BASE)/$(GNU_TARGET)$(RTEMS_VERSION)/xilinx_zynq_zedboard/lib/
|
||||
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ COMMANDLINE_LIBRARY = READLINE
|
||||
|
||||
USR_CXXFLAGS += $(STD_CXXFLAGS)
|
||||
STD_CXXFLAGS = -std=c++11
|
||||
USR_CFLAGS += $(STD_CFLAGS)
|
||||
|
||||
TOOLSET_DIR = $(TOOLSET:%=$(TOOLSET_LOCATION)/%/root)
|
||||
GNU_DIR = $(SYSROOT)$(TOOLSET_DIR)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
# Site specific definitions for linux-x86 host - linux-x86 target builds
|
||||
#-------------------------------------------------------
|
||||
|
||||
# Uncomment the followings lines to build with CLANG instead of GCC.
|
||||
# Uncomment the following lines to build with CLANG instead of GCC.
|
||||
#
|
||||
#GNU = NO
|
||||
#CMPLR_CLASS = clang
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
# Site specific definitions for linux-x86_64 host - linux-x86_64 target builds
|
||||
#-------------------------------------------------------
|
||||
|
||||
# Uncomment the followings lines to build with CLANG instead of GCC.
|
||||
# Uncomment the following lines to build with CLANG instead of GCC.
|
||||
#
|
||||
#GNU = NO
|
||||
#CMPLR_CLASS = clang
|
||||
|
||||
@@ -1105,7 +1105,7 @@ HTML_STYLESHEET =
|
||||
# cascading style sheets that are included after the standard style sheets
|
||||
# created by doxygen. Using this option one can overrule certain style aspects.
|
||||
# This is preferred over using HTML_STYLESHEET since it does not replace the
|
||||
# standard style sheet and is therefor more robust against future updates.
|
||||
# standard style sheet and is therefore more robust against future updates.
|
||||
# Doxygen will copy the style sheet files to the output directory.
|
||||
# Note: The order of the extra stylesheet files is of importance (e.g. the last
|
||||
# stylesheet in the list overrules the setting of the previous ones in the
|
||||
@@ -1648,8 +1648,8 @@ EXTRA_PACKAGES =
|
||||
# Note: Only use a user-defined header if you know what you are doing! The
|
||||
# following commands have a special meaning inside the header: $title,
|
||||
# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
|
||||
# $projectbrief, $projectlogo. Doxygen will replace $title with the empy string,
|
||||
# for the replacement values of the other commands the user is refered to
|
||||
# $projectbrief, $projectlogo. Doxygen will replace $title with the empty string,
|
||||
# for the replacement values of the other commands the user is referred to
|
||||
# HTML_HEADER.
|
||||
# This tag requires that the tag GENERATE_LATEX is set to YES.
|
||||
|
||||
|
||||
@@ -191,7 +191,7 @@ parameter with one called `EPICS_TZ` and a routine for VxWorks that calculates
|
||||
the `TIMEZONE` environment variable from the current `TZ` value. This routine
|
||||
will be run once at start-up, when the EPICS clock has synchronized to its NTP
|
||||
server. The calculations it contains were worked out and donated to EPICS by
|
||||
Larry Hoff in 2009; it is unforunate that it has taken 10 years for them to be
|
||||
Larry Hoff in 2009; it is unfortunate that it has taken 10 years for them to be
|
||||
integrated into Base.
|
||||
|
||||
The default value for the `EPICS_TZ` environment parameter is set in the Base
|
||||
@@ -521,7 +521,7 @@ a Windows system and an IOC or PCAS server is started, the IOC's attempt to
|
||||
bind a TCP socket to the CA server port number fails, but Windows returns a
|
||||
different error status value than the IOC is expecting in that circumstance
|
||||
(because the National Instruments code requests exclusive use of that port,
|
||||
unlike the EPICS code) so the IOC fails to start properly. The relevent EPICS
|
||||
unlike the EPICS code) so the IOC fails to start properly. The relevant EPICS
|
||||
bind() checks have now been updated so the IOC will request that a dynamic port
|
||||
number be allocated for this TCP socket instead when this happens.
|
||||
|
||||
@@ -619,7 +619,7 @@ static versions of the compiler support libraries have now been moved into the
|
||||
The `iocInit` code now performs a sanity check of the current time
|
||||
returned by the generalTime subsystem and will print a warning if the wall-clock
|
||||
time returned has not been initialized yet. This is just a warning message; when
|
||||
a time provider does synchonize the IOC will subsequently pick up and use the
|
||||
a time provider does synchronize the IOC will subsequently pick up and use the
|
||||
correct time. This check code also primes the registered event system provider
|
||||
if there is one so the `epicsTimeGetEventInt()` routine will work on IOCs
|
||||
that ask for event time within an interrupt service routine.
|
||||
@@ -642,7 +642,7 @@ change will not cause the IOC to see time going backwards.
|
||||
### Microsoft Visual Studio builds
|
||||
|
||||
The build configuration files for builds using the Microsoft compilers have been
|
||||
updated, although there should be no noticable difference at most sites. One
|
||||
updated, although there should be no noticeable difference at most sites. One
|
||||
extra compiler warning is now being suppressed for C++ code, `C4344: behavior
|
||||
change: use of explicit template arguments results in ...` which is gratuitous
|
||||
and was appearing frequently in builds of the EPICS V4 modules.
|
||||
|
||||
@@ -661,7 +661,7 @@ the `DB_OPT` build configuration variable.
|
||||
|
||||
The compressRecord has a new field `BALG` which can select between FIFO
|
||||
(append) and LIFO (prepend) ordering for insertion of new elements. FIFO
|
||||
ordering is the default, matching the behviour of previous versions.
|
||||
ordering is the default, matching the behaviour of previous versions.
|
||||
|
||||
### Valgrind Instrumentation
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ been split into 4 separate Git repositories. External modules should build
|
||||
against this new structure with little or no changes needed, except that some
|
||||
allowance may be needed for the merging of the V4 modules.
|
||||
|
||||
There should be rather more description and documantation of these changes
|
||||
There should be rather more description and documentation of these changes
|
||||
than is currently available, but as developers we generally much prefer to
|
||||
write code than documentation. Send questions to the tech-talk mailing list
|
||||
and we'll be happy to try and answer them!
|
||||
|
||||
@@ -56,7 +56,7 @@ A suggested form for IOC shell commands is:
|
||||
|
||||
### Relocatable Builds
|
||||
|
||||
Allows built trees to be copied or moved without invalidating RPATH entires.
|
||||
Allows built trees to be copied or moved without invalidating RPATH entries.
|
||||
|
||||
The `LINKER_USE_RPATH` Makefile variable (see `configure/CONFIG_SITE`) may be
|
||||
set to `YES`, `NO`, and a new third option `ORIGIN`. This is limited to
|
||||
|
||||
@@ -147,7 +147,7 @@ This also fixes [lauchpad bug #1714455](https://bugs.launchpad.net/bugs/1714455)
|
||||
declared in epicsString.h no longer accept octal escaped characters such as
|
||||
`\123` or `\41`.
|
||||
- The routine `epicsStrnEscapedFromRaw()` now generates hex
|
||||
excaped characters for unprintable characters such as `\x1f`.
|
||||
escaped characters for unprintable characters such as `\x1f`.
|
||||
- Hex escape character sequences `\xXX` must now contain exactly 2 hex digits.
|
||||
- An escape sequence `\0` now generates a zero byte in the raw string, but the
|
||||
other digits `1-9` should not appear after a back-slash.
|
||||
|
||||
@@ -117,7 +117,7 @@ with the TCP port number selected.
|
||||
|
||||
DBD files generated by the `dbdExpand.pl` script are now sorted within each
|
||||
item type by the primary name of the item. The result should resolve any
|
||||
issues with reproducable builds. No option is provided to prevent the sorting,
|
||||
issues with reproducible builds. No option is provided to prevent the sorting,
|
||||
previously the order was essentially random and varied each time.
|
||||
|
||||
### `dbExpand.pl` sorts records by name
|
||||
|
||||
@@ -35,7 +35,7 @@ record(bi, "bit1") {
|
||||
|
||||
### ANSI escapes in stderr
|
||||
|
||||
ANSI escape charactor sequences may now be printed to the stderr stream.
|
||||
ANSI escape character sequences may now be printed to the stderr stream.
|
||||
These escapes will appear in logs captured from that stream.
|
||||
Tools which parse and/or render these logs may need to be adjusted to
|
||||
either strip out the escapes, or to translate them into markup.
|
||||
@@ -227,7 +227,7 @@ The pvDatabase module was updated to version 4.7.1:
|
||||
|
||||
`_[distributor=group:<group id>;set:<set_id>;trigger:<field_name>;updates:<n_updates>;mode:<update_mode>]`
|
||||
|
||||
The plugin parameters are optional and are described bellow:
|
||||
The plugin parameters are optional and are described below:
|
||||
|
||||
- group: this parameter indicates a group that client application belongs to (default value: "default"); groups of clients are completely independent of each other
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ although it doesn't currently cover the new processes added to epics-base.
|
||||
Much of the documentation generated from .dbd.pod files at build time is now
|
||||
also being converted into MarkDown (.md) files and installed into the top-level
|
||||
`doc` directory. Some users might find it quicker to look up information about a
|
||||
record type by opening these files in a text editor intead of opening a browser
|
||||
record type by opening these files in a text editor instead of opening a browser
|
||||
and loading the HTML versions or finding and opening the files from the EPICS
|
||||
Documentation site.
|
||||
|
||||
@@ -97,7 +97,7 @@ record("#", "unwanted") {}
|
||||
|
||||
### Only keep readline history for interactive sessions
|
||||
|
||||
Previously, all IOCsh commands were persisited in the libreadline history
|
||||
Previously, all IOCsh commands were persisted in the libreadline history
|
||||
(when readline support is included).
|
||||
Going forward, only interactive commands are saved.
|
||||
|
||||
@@ -111,7 +111,7 @@ already be conditionally casting to/from the appropriate type.
|
||||
|
||||
### Fix issues with `_FORTIFY_SOURCE=3`
|
||||
|
||||
This release fixes the false positives failures whhen building with `_FORTIFY_SOURCE` level 3.
|
||||
This release fixes the false positives failures when building with `_FORTIFY_SOURCE` level 3.
|
||||
The override introduced in 7.0.8.1 has been removed.
|
||||
|
||||
### Other
|
||||
|
||||
@@ -419,7 +419,7 @@ everything that has to be done since it's so easy to miss steps.</p>
|
||||
<tr>
|
||||
<td><input type="checkbox"></td>
|
||||
<td>Website Editor</td>
|
||||
<td>Link to the release webpage from other relevent areas of the
|
||||
<td>Link to the release webpage from other relevant areas of the
|
||||
website - update front page and sidebars.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
||||
@@ -9,7 +9,7 @@ This release incorporates [PR #558](https://github.com/epics-base/epics-base/pul
|
||||
- it replaces the community [`afterInit`](https://github.com/paulscherrerinstitute/iocsh_utilities/blob/master/afterInit.c) and [`doAfterIocInit`](https://github.com/epics-modules/std/blob/master/stdApp/src/delayCmd.cpp) IOC shell commands,
|
||||
- community usage examples:
|
||||
- [`pf4filters.iocsh`](https://github.com/epics-modules/optics/blob/master/opticsApp/iocsh/pf4filters.iocsh) - enable/disable with a single comment ([full description](https://github.com/epics-base/epics-base/pull/558#issuecomment-2430057167))
|
||||
- [ALS-U autosave managment](https://github.com/epics-base/epics-base/pull/558#issuecomment-2430447220)
|
||||
- [ALS-U autosave management](https://github.com/epics-base/epics-base/pull/558#issuecomment-2430447220)
|
||||
|
||||
#### Features
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ prints.
|
||||
- The default IOC Shell prompt is now displayed in green; this color can be
|
||||
modified in the `configure/CONFIG_SITE_ENV` file for all targets, or set for
|
||||
a specific target by adding a `configure/os/CONFIG_SITE_ENV.<arch>` file.
|
||||
The value of the `IOCSH_PS1` environment paremeter in those files can use the
|
||||
The value of the `IOCSH_PS1` environment parameter in those files can use the
|
||||
`ANSI_ENV_*` and `ANSI_*()` color macros found in errlog.h to configure the
|
||||
appearance of the prompt. The C string literal concatenation syntax can be
|
||||
used to construct the prompt string:
|
||||
|
||||
12
documentation/new-notes/PR-651.md
Normal file
12
documentation/new-notes/PR-651.md
Normal file
@@ -0,0 +1,12 @@
|
||||
### Documentation Updates
|
||||
|
||||
The reference documentation for the [event](eventRecord.html) record type
|
||||
has been updated to cover the use of named events which were added in Base
|
||||
3.14.12.3 and 3.15.1.
|
||||
|
||||
Documentation for CALC expression evaluation has been updated for format
|
||||
enhancements and to add some missing operators.
|
||||
The best documentation for these expressions can be found in the
|
||||
[postfix.h](postfix_h.html) header in libCom, but both the
|
||||
[calc](calcRecord.html) and [calcout](calcoutRecord.html) record reference
|
||||
pages also cover the infix expressions supported.
|
||||
@@ -1,7 +1,7 @@
|
||||
### Records calc, calcout and sub extended
|
||||
|
||||
The record types calc, calcout and sub have been extended from
|
||||
12 inputs A-L to 21 inputs A-U.
|
||||
The record types calc, calcout and sub have been extended from 12 inputs
|
||||
A - L to 21 inputs A - U.
|
||||
The macro `CALCPERFORM_NARGS` reflects this change.
|
||||
The new inputs can be used in calc links and access security as well.
|
||||
The size of CALC and OCAL fields have been doubled to 160 chars.
|
||||
The size of CALC and OCAL fields has been doubled to 160 chars.
|
||||
|
||||
@@ -9,5 +9,4 @@ now they switch to octal mode.
|
||||
|
||||
For backward compatibility, this behavior can be switched off, returning
|
||||
to the old decimal only conversions, by setting the environment variable
|
||||
`EPICS_DB_CONVERT_DECIMAL_ONLY` to anything except the empty string or
|
||||
strings starting with `n`, `N`, `f`, `F` or `0` before `iocInit`.
|
||||
`EPICS_DB_CONVERT_DECIMAL_ONLY` to `YES` (case insensitive) before `iocInit`.
|
||||
|
||||
6
documentation/new-notes/PR-688.md
Normal file
6
documentation/new-notes/PR-688.md
Normal file
@@ -0,0 +1,6 @@
|
||||
### `dfanout` improvements
|
||||
|
||||
The dfanout record now has invalid output handling with the usual fields
|
||||
`IVOA` and `IVOV` just like other output records.
|
||||
|
||||
The number of output links has been increased from 8 to 16.
|
||||
5
documentation/new-notes/PR-737.md
Normal file
5
documentation/new-notes/PR-737.md
Normal file
@@ -0,0 +1,5 @@
|
||||
### Add environment variable to opt out of POSIX Real-Time scheduling
|
||||
|
||||
On POSIX systems, processes with real-time capabilities can opt out of using
|
||||
Posix thread priority scheduling and memory locking.
|
||||
Set `EPICS_ALLOW_POSIX_THREAD_PRIORITY_SCHEDULING=NO` to achieve this.
|
||||
@@ -5,7 +5,7 @@
|
||||
Name: epics-base-%{EpicsVersion}
|
||||
Summary: EPICS Base %{EpicsVersion}
|
||||
Version: 1
|
||||
Release: 4%{?dist}
|
||||
Release: 5%{?dist}
|
||||
License: EPICS Open License
|
||||
Group: Development/Languages
|
||||
URL: https://git.psi.ch/epics_base/base-7.0
|
||||
@@ -53,10 +53,10 @@ BuildRequires: wine
|
||||
Summary: Minimal stuff needed to build EPICS host apps
|
||||
Requires: %{name} = %{version}-%{release}
|
||||
|
||||
# This EPICS installation uses the toolset 12 compiler
|
||||
# This EPICS installation uses the toolset 15 compiler
|
||||
%if 0%{?rhel} >= 8
|
||||
Requires: gcc-toolset-12-gcc-c++
|
||||
BuildRequires: gcc-toolset-12-gcc-c++
|
||||
Requires: gcc-toolset-15-gcc-c++
|
||||
BuildRequires: gcc-toolset-15-gcc-c++
|
||||
%endif
|
||||
|
||||
# The perl stuff we need
|
||||
@@ -127,6 +127,9 @@ Summary: EPICS base %{EpicsVersion} for development environments
|
||||
Requires: %{name} = %{version}-%{release}
|
||||
Requires: %{name}-host-devel = %{version}-%{release}
|
||||
Requires: gfa-cross-compiler-links
|
||||
BuildRequires: gfa-cross-compiler-links
|
||||
Requires: mingw64-gcc-c++
|
||||
BuildRequires: mingw64-gcc-c++
|
||||
BuildArch: noarch
|
||||
AutoReqProv: no
|
||||
|
||||
@@ -187,7 +190,8 @@ git submodule update --init --recursive modules
|
||||
%if %{defined epics_host_arch}
|
||||
export EPICS_HOST_ARCH=%{epics_host_arch}
|
||||
%endif
|
||||
%{__make} INSTALL_LOCATION=%{buildroot}%{prog_folder} FINAL_LOCATION=%{prog_folder}
|
||||
%make_build -s INSTALL_LOCATION=%{buildroot}%{prog_folder} FINAL_LOCATION=%{prog_folder} \
|
||||
TESTS= TESTPROD= TESTLIBRARY= TESTFILES= PROD_RTEMS=-nil- PROD_vxWorks=-nil-
|
||||
%{__make} INSTALL_LOCATION=%{buildroot}%{prog_folder} copysrc
|
||||
|
||||
# remove files we do not need
|
||||
@@ -210,7 +214,7 @@ shopt -s extglob
|
||||
# and install will delete our buildroot!
|
||||
|
||||
%clean
|
||||
%{__make} INSTALL_LOCATION=%{buildroot}%{prog_folder} realclean
|
||||
%make_build INSTALL_LOCATION=%{buildroot}%{prog_folder} realclean
|
||||
%{__rm} -f modules/RELEASE.*.local
|
||||
%{__rm} -rf %{buildroot}
|
||||
%{__cp} %{_rpmdir}/*/%{name}*%{version}-%{release}.*.rpm %{_sourcedir}
|
||||
|
||||
@@ -103,7 +103,7 @@ in the file LICENSE that is included with this distribution.</span></p>
|
||||
<ul>
|
||||
<li><a href="#Broadcast">Client and Server Broadcast Addresses Don't
|
||||
Match</a></li>
|
||||
<li><a href="#Client">Client Isnt Configured to Use the Server's
|
||||
<li><a href="#Client">Client Isn't Configured to Use the Server's
|
||||
Port</a></li>
|
||||
<li><a href="#Unicast">Unicast Addresses in the EPICS_CA_ADDR_LIST Does
|
||||
not Reliably Contact Servers Sharing the Same UDP Port on the Same
|
||||
@@ -759,7 +759,7 @@ to respect the EPICS_CA_MAX_ARRAY_BYTES setting as described below instead.</p>
|
||||
<p>Starting with version R3.14 the environment variable
|
||||
EPICS_CA_MAX_ARRAY_BYTES determines the size of the largest array that may pass
|
||||
through CA. Prior to this version only arrays smaller than 16k bytes could be
|
||||
transfered. The CA libraries maintains a free list of 16384 byte network
|
||||
transferred. The CA libraries maintains a free list of 16384 byte network
|
||||
buffers that are used for ordinary communication. If EPICS_CA_MAX_ARRAY_BYTES
|
||||
is larger than 16384 then a second free list of larger data buffers is
|
||||
established and used only after a client send its first large array request.</p>
|
||||
@@ -1085,7 +1085,7 @@ to standard out.</p>
|
||||
|
||||
<p>If a value is specified it is written to the PV. Next, the current value of
|
||||
the PV is converted to each of the many external data type that can be
|
||||
specified at the CA client library interface, and each of these is formated and
|
||||
specified at the CA client library interface, and each of these is formatted and
|
||||
then output to the console.</p>
|
||||
<hr>
|
||||
|
||||
@@ -1631,7 +1631,7 @@ stdout.</p>
|
||||
|
||||
<p>The -s option allows to specify an interest level for calling Channel
|
||||
Access' internal report function <code>ca_client_status()</code>, that prints lots of
|
||||
internal informations on stdout, including environment settings, used CA ports
|
||||
internal information on stdout, including environment settings, used CA ports
|
||||
etc.</p>
|
||||
|
||||
<table border="1">
|
||||
@@ -1969,7 +1969,7 @@ that the request is sent call <code>ca_flush_io()</code> followed by
|
||||
|
||||
<h3><a name="Problems">ENOBUFS Messages</a></h3>
|
||||
|
||||
<p>Many Berkley UNIX derived Internet Protocol (IP) kernels use a memory
|
||||
<p>Many Berkeley UNIX derived Internet Protocol (IP) kernels use a memory
|
||||
management scheme with a fixed sized low level memory allocation quantum called
|
||||
an "mbuf". Messages about "ENOBUFS" are an indication that your IP kernel is
|
||||
running low on mbuf buffers. An IP kernel mbuf starvation situation may lead to
|
||||
|
||||
@@ -65,7 +65,7 @@ const char * ca_message_text []
|
||||
"Sorry, that feature is planned but not supported at this time",
|
||||
"The supplied string is unusually large",
|
||||
"The request was ignored because the specified channel is disconnected",
|
||||
"The data type specifed is invalid",
|
||||
"The data type specified is invalid",
|
||||
|
||||
"Remote Channel not found",
|
||||
"Unable to locate all user specified channels",
|
||||
@@ -94,7 +94,7 @@ const char * ca_message_text []
|
||||
"The supplied string is empty",
|
||||
"Unable to spawn the CA repeater thread- auto reconnect will fail",
|
||||
"No channel id match for search reply- search reply ignored",
|
||||
"Reseting dead connection- will try to reconnect",
|
||||
"Resetting dead connection- will try to reconnect",
|
||||
"Server (IOC) has fallen behind or is not responding- still waiting",
|
||||
|
||||
"No internet interface with broadcast available",
|
||||
@@ -196,7 +196,7 @@ int epicsStdCall ca_context_create (
|
||||
return ECA_ALLOCMEM;
|
||||
}
|
||||
|
||||
epicsThreadPrivateSet ( caClientContextId, (void *) pcac );
|
||||
epicsThreadPrivateSet ( caClientContextId, pcac );
|
||||
}
|
||||
catch ( ... ) {
|
||||
return ECA_ALLOCMEM;
|
||||
@@ -381,11 +381,11 @@ int epicsStdCall ca_clear_channel ( chid pChan )
|
||||
}
|
||||
else {
|
||||
//
|
||||
// we will definately stall out here if all of the
|
||||
// we will definitely stall out here if all of the
|
||||
// following are true
|
||||
//
|
||||
// o user creates non-preemptive mode client library context
|
||||
// o user doesnt periodically call a ca function
|
||||
// o user doesn't periodically call a ca function
|
||||
// o user calls this function from an auxiliary thread
|
||||
//
|
||||
CallbackGuard cbGuard ( cac.cbMutex );
|
||||
|
||||
@@ -844,7 +844,7 @@ void verifyBlockInPendIO ( chid chan, unsigned interestLevel )
|
||||
}
|
||||
}
|
||||
else if ( resp != -100 ) {
|
||||
printf ( "CA didnt block for get to return?\n" );
|
||||
printf ( "CA didn't block for get to return?\n" );
|
||||
}
|
||||
|
||||
req = 1;
|
||||
@@ -1739,7 +1739,7 @@ void arrayEventExceptionNotify ( struct event_handler_args args )
|
||||
if ( args.status == ECA_NORMAL ) {
|
||||
printf (
|
||||
"arrayEventExceptionNotify: expected "
|
||||
"exception but didnt receive one against \"%s\" \n",
|
||||
"exception but didn't receive one against \"%s\" \n",
|
||||
ca_name ( args.chid ) );
|
||||
}
|
||||
else {
|
||||
@@ -3233,7 +3233,7 @@ void verifyDisconnect (
|
||||
|
||||
/*
|
||||
* if its a local channel and will never disconnect
|
||||
* then skip the portions of this test that cant be
|
||||
* then skip the portions of this test that can't be
|
||||
* completed.
|
||||
*/
|
||||
if ( ca_get_ioc_connection_count () == 0 ) {
|
||||
@@ -3307,7 +3307,7 @@ void verifyContextRundownFlush ( const char * pName, unsigned interestLevel )
|
||||
|
||||
status = ca_create_channel ( pName, 0, 0, 0, & chan );
|
||||
/*
|
||||
* currently in-memory channels cant be used with this test
|
||||
* currently in-memory channels can't be used with this test
|
||||
* !!!! FIX ME, FIX ME, FIX ME, FIX ME !!!!
|
||||
*/
|
||||
if ( status != ECA_UNAVAILINSERV ) {
|
||||
@@ -3335,7 +3335,7 @@ void verifyContextRundownFlush ( const char * pName, unsigned interestLevel )
|
||||
status = ca_create_channel ( pName, 0, 0, 0, & chan );
|
||||
SEVCHK ( status, NULL );
|
||||
/*
|
||||
* currently in-memory channels cant be used with this test
|
||||
* currently in-memory channels can't be used with this test
|
||||
* !!!! FIX ME, FIX ME, FIX ME, FIX ME !!!!
|
||||
*/
|
||||
if ( status != ECA_UNAVAILINSERV ) {
|
||||
@@ -3379,7 +3379,7 @@ void verifyContextRundownChanStillExist (
|
||||
for ( i = 0; i < NELEMENTS ( chan ); i++ ) {
|
||||
status = ca_create_channel ( pName, 0, 0, 0, & chan[i] );
|
||||
/*
|
||||
* currently in-memory channels cant be used with this test
|
||||
* currently in-memory channels can't be used with this test
|
||||
* !!!! FIX ME, FIX ME, FIX ME, FIX ME !!!!
|
||||
*/
|
||||
if ( status == ECA_UNAVAILINSERV ) {
|
||||
|
||||
@@ -192,7 +192,7 @@ bool bhe::updatePeriod (
|
||||
this->beaconAnomalyNotify ( guard );
|
||||
|
||||
/*
|
||||
* this is the 2nd beacon seen. We cant tell about
|
||||
* this is the 2nd beacon seen. We can't tell about
|
||||
* the change in period at this point so we just
|
||||
* initialize the average period and return.
|
||||
*/
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
|
||||
/*
|
||||
* These port numbers are only used if the CA repeater and
|
||||
* CA server port numbers cant be obtained from the EPICS
|
||||
* CA server port numbers can't be obtained from the EPICS
|
||||
* environment variables "EPICS_CA_REPEATER_PORT" and
|
||||
* "EPICS_CA_SERVER_PORT"
|
||||
*/
|
||||
|
||||
@@ -117,7 +117,7 @@ ca_client_context::ca_client_context ( bool enablePreemptiveCallback ) :
|
||||
// the local port number below
|
||||
{
|
||||
osiSockAddr addr;
|
||||
memset ( (char *)&addr, 0 , sizeof ( addr ) );
|
||||
memset ( &addr, 0 , sizeof ( addr ) );
|
||||
addr.ia.sin_family = AF_INET;
|
||||
addr.ia.sin_addr.s_addr = htonl ( INADDR_ANY );
|
||||
addr.ia.sin_port = htons ( PORT_ANY );
|
||||
@@ -775,11 +775,11 @@ LIBCA_API int epicsStdCall ca_clear_subscription ( evid pMon )
|
||||
}
|
||||
else {
|
||||
//
|
||||
// we will definately stall out here if all of the
|
||||
// we will definitely stall out here if all of the
|
||||
// following are true
|
||||
//
|
||||
// o user creates non-preemptive mode client library context
|
||||
// o user doesnt periodically call a ca function
|
||||
// o user doesn't periodically call a ca function
|
||||
// o user calls this function from an auxiliary thread
|
||||
//
|
||||
CallbackGuard cbGuard ( cac.cbMutex );
|
||||
|
||||
@@ -7,4 +7,4 @@
|
||||
If a value is specified it is written to the PV. Next, the current value
|
||||
of the PV is converted to each of the many external data type that can
|
||||
be specified at the CA client library interface, and each of these is
|
||||
formated and then output to the console.
|
||||
formatted and then output to the console.
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
#define ECA_STRTOBIG DEFMSG(CA_K_WARNING, 12) /* defunct */
|
||||
/// The request was ignored because the specified channel is disconnected
|
||||
#define ECA_DISCONNCHID DEFMSG(CA_K_ERROR, 13) /* defunct */
|
||||
/// The data type specifed is invalid
|
||||
/// The data type specified is invalid
|
||||
#define ECA_BADTYPE DEFMSG(CA_K_ERROR, 14)
|
||||
/// Remote Channel not found
|
||||
#define ECA_CHIDNOTFND DEFMSG(CA_K_INFO, 15) /* defunct */
|
||||
@@ -146,7 +146,7 @@
|
||||
#define ECA_NEWADDR DEFMSG(CA_K_WARNING, 31) /* defunct */
|
||||
/// New or resumed network connection
|
||||
#define ECA_NEWCONN DEFMSG(CA_K_INFO, 32) /* defunct */
|
||||
/// Specified task isnt a member of a CA context
|
||||
/// Specified task isn't a member of a CA context
|
||||
#define ECA_NOCACTX DEFMSG(CA_K_WARNING, 33) /* defunct */
|
||||
/// Attempt to use defunct CA feature failed
|
||||
#define ECA_DEFUNCT DEFMSG(CA_K_FATAL, 34) /* defunct */
|
||||
@@ -156,7 +156,7 @@
|
||||
#define ECA_NOREPEATER DEFMSG(CA_K_WARNING, 36) /* defunct */
|
||||
/// No channel id match for search reply- search reply ignored
|
||||
#define ECA_NOCHANMSG DEFMSG(CA_K_WARNING, 37) /* defunct */
|
||||
/// Reseting dead connection- will try to reconnect
|
||||
/// Resetting dead connection- will try to reconnect
|
||||
#define ECA_DLCKREST DEFMSG(CA_K_WARNING, 38) /* defunct */
|
||||
/// Server (IOC) has fallen behind or is not responding- still waiting
|
||||
#define ECA_SERVBEHIND DEFMSG(CA_K_WARNING, 39) /* defunct */
|
||||
|
||||
@@ -115,7 +115,7 @@ int main ( int argc, char ** argv )
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset ( (char *) &addr, 0 , sizeof (addr) );
|
||||
memset ( &addr, 0 , sizeof (addr) );
|
||||
addr.ia.sin_family = AF_INET;
|
||||
addr.ia.sin_addr.s_addr = htonl ( INADDR_ANY );
|
||||
addr.ia.sin_port = htons ( 0 ); // any port
|
||||
|
||||
@@ -24,14 +24,14 @@
|
||||
|
||||
//
|
||||
// Requirements:
|
||||
// 1) Allow sufficent headroom so that users will be able to perform
|
||||
// 1) Allow sufficient headroom so that users will be able to perform
|
||||
// a reasonable amount of IO within CA callbacks without experiencing
|
||||
// a push/pull deadlock. If a potential push/pull deadlock situation
|
||||
// occurs then detect and avoid it and provide diagnostic to the user
|
||||
// via special status.
|
||||
// 2) Return status to the user when there is insufficient memory to
|
||||
// queue a complete message.
|
||||
// 3) return status to the user when a message cant be flushed because
|
||||
// 3) return status to the user when a message can't be flushed because
|
||||
// a connection dropped.
|
||||
// 4) Do not allocate too much memory in exception situations (such as
|
||||
// after a circuit disconnect).
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
*
|
||||
* 1) All routines in this file have an encode argument which
|
||||
* determines if we are converting from the standard format to
|
||||
* the local format or vise versa. To date only float and double data
|
||||
* the local format or vice versa. To date only float and double data
|
||||
* types must be converted differently depending on the encode
|
||||
* argument - joh
|
||||
*
|
||||
@@ -517,7 +517,7 @@ arrayElementCount num /* number of values */
|
||||
if (num == 1)
|
||||
pDest->value = pSrc->value;
|
||||
else {
|
||||
memcpy((char *)&pDest->value, (char *)&pSrc->value, num);
|
||||
memcpy(&pDest->value, &pSrc->value, num);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -584,7 +584,7 @@ arrayElementCount num /* number of values */
|
||||
pDest->severity = dbr_ntohs(pSrc->severity);
|
||||
pDest->no_str = dbr_ntohs(pSrc->no_str);
|
||||
if ( s != d ) {
|
||||
memcpy((void *)pDest->strs,(void *)pSrc->strs,sizeof(pSrc->strs));
|
||||
memcpy(pDest->strs, pSrc->strs, sizeof(pSrc->strs));
|
||||
}
|
||||
|
||||
if (num == 1) /* single value */
|
||||
@@ -845,7 +845,7 @@ arrayElementCount num /* number of values */
|
||||
if (num == 1)
|
||||
pDest->value = pSrc->value;
|
||||
else {
|
||||
memcpy((void *)&pDest->value, (void *)&pSrc->value, num);
|
||||
memcpy(&pDest->value, &pSrc->value, num);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1004,7 +1004,7 @@ arrayElementCount num /* number of values */
|
||||
pDest->severity = dbr_ntohs(pSrc->severity);
|
||||
pDest->no_str = dbr_ntohs(pSrc->no_str);
|
||||
if ( s != d ) {
|
||||
memcpy((void *)pDest->strs,(void *)pSrc->strs,sizeof(pSrc->strs));
|
||||
memcpy(pDest->strs, pSrc->strs, sizeof(pSrc->strs));
|
||||
}
|
||||
|
||||
if (num == 1) /* single value */
|
||||
@@ -1049,7 +1049,7 @@ arrayElementCount num /* number of values */
|
||||
pDest->value = pSrc->value;
|
||||
else /* array chan-- multiple pts */
|
||||
{
|
||||
memcpy((void *)&pDest->value, (void *)&pSrc->value, num);
|
||||
memcpy(&pDest->value, &pSrc->value, num);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1268,7 +1268,7 @@ arrayElementCount num /* number of values */
|
||||
pDest->value = pSrc->value;
|
||||
else /* array chan-- multiple pts */
|
||||
{
|
||||
memcpy((void *)&pDest->value, (void *)&pSrc->value, num);
|
||||
memcpy(&pDest->value, &pSrc->value, num);
|
||||
}
|
||||
}
|
||||
/****************************************************************************
|
||||
|
||||
@@ -154,7 +154,7 @@ void nciu::connect ( unsigned nativeType,
|
||||
// the callback lock is also taken when a channel
|
||||
// disconnects to prevent a race condition with the
|
||||
// code below - ie we hold the callback lock here
|
||||
// so a channel cant be destroyed out from under us.
|
||||
// so a channel can't be destroyed out from under us.
|
||||
this->notify().connectNotify ( guard );
|
||||
}
|
||||
|
||||
@@ -618,7 +618,7 @@ unsigned channelNode::getSearchTimerIndex (
|
||||
}
|
||||
else {
|
||||
throw std::runtime_error (
|
||||
"channel was expected to be in a search timer, but wasnt" );;
|
||||
"channel was expected to be in a search timer, but wasn't" );;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
@@ -161,7 +161,7 @@ void netiiu::uninstallChanDueToSuccessfulSearchResponse (
|
||||
epicsGuard < epicsMutex > &, nciu &, const epicsTime & )
|
||||
{
|
||||
throw std::runtime_error (
|
||||
"search response occured when not attached to udpiiu?" );
|
||||
"search response occurred when not attached to udpiiu?" );
|
||||
}
|
||||
|
||||
bool netiiu::searchMsg (
|
||||
|
||||
@@ -595,11 +595,11 @@ void ca_client_context :: whenThereIsAnExceptionDestroySyncGroupIO (
|
||||
epicsGuardRelease < epicsMutex > guardRelease ( guard );
|
||||
{
|
||||
//
|
||||
// we will definately stall out here if all of the
|
||||
// we will definitely stall out here if all of the
|
||||
// following are true
|
||||
//
|
||||
// o user creates non-preemptive mode client library context
|
||||
// o user doesnt periodically call a ca function
|
||||
// o user doesn't periodically call a ca function
|
||||
// o user calls this function from an auxiliary thread
|
||||
//
|
||||
CallbackGuard cbGuard ( this->cbMutex );
|
||||
|
||||
@@ -107,7 +107,7 @@ static int makeSocket ( unsigned short port, bool reuseAddr, SOCKET * pSock )
|
||||
struct sockaddr sa;
|
||||
} bd;
|
||||
|
||||
memset ( (char *) &bd, 0, sizeof (bd) );
|
||||
memset ( &bd, 0, sizeof (bd) );
|
||||
bd.ia.sin_family = AF_INET;
|
||||
bd.ia.sin_addr.s_addr = htonl ( INADDR_ANY );
|
||||
bd.ia.sin_port = htons ( port );
|
||||
@@ -165,7 +165,7 @@ bool repeaterClient::sendConfirm ()
|
||||
int status;
|
||||
|
||||
caHdr confirm;
|
||||
memset ( (char *) &confirm, '\0', sizeof (confirm) );
|
||||
memset ( &confirm, '\0', sizeof (confirm) );
|
||||
AlignedWireRef < epicsUInt16 > ( confirm.m_cmmd ) = REPEATER_CONFIRM;
|
||||
confirm.m_available = this->from.ia.sin_addr.s_addr;
|
||||
status = send ( this->sock, (char *) &confirm,
|
||||
@@ -456,7 +456,7 @@ static void register_new_client ( osiSockAddr & from,
|
||||
* accumulate sockets when there are no beacons
|
||||
*/
|
||||
caHdr noop;
|
||||
memset ( (char *) &noop, '\0', sizeof ( noop ) );
|
||||
memset ( &noop, '\0', sizeof ( noop ) );
|
||||
AlignedWireRef < epicsUInt16 > ( noop.m_cmmd ) = CA_PROTO_VERSION;
|
||||
fanOut ( from, &noop, sizeof ( noop ), freeList );
|
||||
|
||||
|
||||
@@ -353,7 +353,7 @@ void searchTimer::uninstallChanDueToSuccessfulSearchResponse (
|
||||
// when we get 100% success immediately
|
||||
// send another search request
|
||||
//
|
||||
debugPrintf ( ( "All requests succesful, set timer delay to zero\n" ) );
|
||||
debugPrintf ( ( "All requests successful, set timer delay to zero\n" ) );
|
||||
this->timer.start ( *this, currentTime );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,11 +79,11 @@ extern "C" int epicsStdCall ca_sg_delete ( const CA_SYNC_GID gid )
|
||||
}
|
||||
else {
|
||||
//
|
||||
// we will definately stall out here if all of the
|
||||
// we will definitely stall out here if all of the
|
||||
// following are true
|
||||
//
|
||||
// o user creates non-preemptive mode client library context
|
||||
// o user doesnt periodically call a ca function
|
||||
// o user doesn't periodically call a ca function
|
||||
// o user calls this function from an auxiliary thread
|
||||
//
|
||||
CallbackGuard cbGuard ( pcac->cbMutex );
|
||||
@@ -103,11 +103,11 @@ void sync_group_reset ( ca_client_context & client, CASG & sg )
|
||||
}
|
||||
else {
|
||||
//
|
||||
// we will definately stall out here if all of the
|
||||
// we will definitely stall out here if all of the
|
||||
// following are true
|
||||
//
|
||||
// o user creates non-preemptive mode client library context
|
||||
// o user doesnt periodically call a ca function
|
||||
// o user doesn't periodically call a ca function
|
||||
// o user calls this function from an auxiliary thread
|
||||
//
|
||||
CallbackGuard cbGuard ( client.cbMutex );
|
||||
@@ -216,11 +216,11 @@ extern "C" int epicsStdCall ca_sg_test ( const CA_SYNC_GID gid )
|
||||
}
|
||||
else {
|
||||
//
|
||||
// we will definately stall out here if all of the
|
||||
// we will definitely stall out here if all of the
|
||||
// following are true
|
||||
//
|
||||
// o user creates non-preemptive mode client library context
|
||||
// o user doesnt periodically call a ca function
|
||||
// o user doesn't periodically call a ca function
|
||||
// o user calls this function from an auxiliary thread
|
||||
//
|
||||
CallbackGuard cbGuard ( pcac->cbMutex );
|
||||
|
||||
@@ -97,7 +97,7 @@ void tcpRecvWatchdog::beaconArrivalNotify (
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
if ( ! ( this->shuttingDown || this->beaconAnomaly || this->probeResponsePending ) ) {
|
||||
this->timer.start ( *this, this->period );
|
||||
debugPrintf ( ("saw a normal beacon - reseting circuit receive watchdog\n") );
|
||||
debugPrintf ( ("saw a normal beacon - resetting circuit receive watchdog\n") );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ void tcpRecvWatchdog::messageArrivalNotify (
|
||||
if ( ! ( this->shuttingDown || this->probeResponsePending ) ) {
|
||||
this->beaconAnomaly = false;
|
||||
this->timer.start ( *this, this->period );
|
||||
debugPrintf ( ("received a message - reseting circuit recv watchdog\n") );
|
||||
debugPrintf ( ("received a message - resetting circuit recv watchdog\n") );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,7 +182,7 @@ void tcpRecvWatchdog::sendBacklogProgressNotify (
|
||||
// receive at least one message from the server.
|
||||
if ( this->probeResponsePending && ! this->shuttingDown ) {
|
||||
this->timer.start ( *this, CA_ECHO_TIMEOUT );
|
||||
debugPrintf ( ("saw heavy send backlog - reseting circuit recv watchdog\n") );
|
||||
debugPrintf ( ("saw heavy send backlog - resetting circuit recv watchdog\n") );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -812,7 +812,7 @@ tcpiiu::tcpiiu (
|
||||
pSearchDest->setCircuit ( this );
|
||||
}
|
||||
|
||||
memset ( (void *) &this->curMsg, '\0', sizeof ( this->curMsg ) );
|
||||
memset ( &this->curMsg, '\0', sizeof ( this->curMsg ) );
|
||||
}
|
||||
|
||||
// this must always be called by the udp thread when it holds
|
||||
@@ -1817,7 +1817,7 @@ void tcpiiu::disconnectAllChannels (
|
||||
}
|
||||
|
||||
while ( nciu * pChan = this->createRespPend.get () ) {
|
||||
// we don't yet know the server's id so we cant
|
||||
// we don't yet know the server's id so we can't
|
||||
// send a channel delete request and will instead
|
||||
// trust that the server can do the proper cleanup
|
||||
// when the circuit disconnects
|
||||
@@ -1883,7 +1883,7 @@ void tcpiiu::unlinkAllChannels (
|
||||
while ( nciu * pChan = this->createRespPend.get () ) {
|
||||
pChan->channelNode::listMember =
|
||||
channelNode::cs_none;
|
||||
// we don't yet know the server's id so we cant
|
||||
// we don't yet know the server's id so we can't
|
||||
// send a channel delete request and will instead
|
||||
// trust that the server can do the proper cleanup
|
||||
// when the circuit disconnects
|
||||
|
||||
@@ -83,7 +83,7 @@ double getMaxPeriod()
|
||||
}
|
||||
}
|
||||
else {
|
||||
epicsPrintf ( "EPICS \"%s\" wasnt a real number\n",
|
||||
epicsPrintf ( "EPICS \"%s\" wasn't a real number\n",
|
||||
EPICS_CA_MAX_SEARCH_PERIOD.name );
|
||||
epicsPrintf ( "Setting \"%s\" = %f seconds\n",
|
||||
EPICS_CA_MAX_SEARCH_PERIOD.name, maxPeriod );
|
||||
@@ -242,7 +242,7 @@ udpiiu::udpiiu (
|
||||
// the local port number below
|
||||
static const unsigned short PORT_ANY = 0u;
|
||||
osiSockAddr addr;
|
||||
memset ( (char *)&addr, 0 , sizeof (addr) );
|
||||
memset ( &addr, 0 , sizeof (addr) );
|
||||
addr.ia.sin_family = AF_INET;
|
||||
addr.ia.sin_addr.s_addr = htonl ( INADDR_ANY );
|
||||
addr.ia.sin_port = htons ( PORT_ANY );
|
||||
@@ -514,7 +514,7 @@ void epicsStdCall caRepeaterRegistrationMessage (
|
||||
saddr.ia.sin_port = htons ( port );
|
||||
}
|
||||
|
||||
memset ( (char *) &msg, 0, sizeof (msg) );
|
||||
memset ( &msg, 0, sizeof (msg) );
|
||||
AlignedWireRef < epicsUInt16 > ( msg.m_cmmd ) = REPEATER_REGISTER;
|
||||
msg.m_available = saddr.ia.sin_addr.s_addr;
|
||||
|
||||
@@ -597,7 +597,7 @@ void epicsStdCall caStartRepeaterIfNotInstalled ( unsigned repeaterPort )
|
||||
tmpSock = epicsSocketCreate ( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
|
||||
if ( tmpSock != INVALID_SOCKET ) {
|
||||
ca_uint16_t port = static_cast < ca_uint16_t > ( repeaterPort );
|
||||
memset ( (char *) &bd, 0, sizeof ( bd ) );
|
||||
memset ( &bd, 0, sizeof ( bd ) );
|
||||
bd.ia.sin_family = AF_INET;
|
||||
bd.ia.sin_addr.s_addr = htonl ( INADDR_ANY );
|
||||
bd.ia.sin_port = htons ( port );
|
||||
|
||||
@@ -64,7 +64,7 @@ const char * get_error_msg(int status) {
|
||||
"ECA_NOSUPPORT - Sorry, that feature is planned but not supported at this time",
|
||||
"ECA_STRTOBIG - The supplied string is unusually large",
|
||||
"ECA_DISCONNCHID - The request was ignored because the specified channel is disconnected",
|
||||
"ECA_BADTYPE - The data type specifed is invalid",
|
||||
"ECA_BADTYPE - The data type specified is invalid",
|
||||
"ECA_CHIDNOTFND - Remote Channel not found",
|
||||
"ECA_CHIDRETRY - Unable to locate all user specified channels",
|
||||
"ECA_INTERNAL - Channel Access Internal Failure",
|
||||
@@ -83,12 +83,12 @@ const char * get_error_msg(int status) {
|
||||
"ECA_BADMONID - Bad event subscription (monitor) identifier",
|
||||
"ECA_NEWADDR - Remote channel has new network address",
|
||||
"ECA_NEWCONN - New or resumed network connection",
|
||||
"ECA_NOCACTX - Specified task isnt a member of a CA context",
|
||||
"ECA_NOCACTX - Specified task isn't a member of a CA context",
|
||||
"ECA_DEFUNCT - Attempt to use defunct CA feature failed",
|
||||
"ECA_EMPTYSTR - The supplied string is empty",
|
||||
"ECA_NOREPEATER - Unable to spawn the CA repeater thread- auto reconnect will fail",
|
||||
"ECA_NOCHANMSG - No channel id match for search reply- search reply ignored",
|
||||
"ECA_DLCKREST - Reseting dead connection- will try to reconnect",
|
||||
"ECA_DLCKREST - Resetting dead connection- will try to reconnect",
|
||||
"ECA_SERVBEHIND - Server (IOC) has fallen behind or is not responding- still waiting",
|
||||
"ECA_NOCAST - No internet interface with broadcast available",
|
||||
"ECA_BADMASK - Invalid event selection mask",
|
||||
@@ -613,6 +613,7 @@ void CA_put(SV *ca_ref, SV *val, ...) {
|
||||
break;
|
||||
case DBF_STRING:
|
||||
strncpy(data.dbr_string, SvPV_nolen(val), MAX_STRING_SIZE);
|
||||
data.dbr_string[MAX_STRING_SIZE-1] = 0;
|
||||
break;
|
||||
}
|
||||
status = ca_put(type, pch->chan, &data);
|
||||
@@ -705,6 +706,7 @@ void CA_put_callback(SV *ca_ref, SV *sub, SV *val, ...) {
|
||||
break;
|
||||
case DBF_STRING:
|
||||
strncpy(data.dbr_string, SvPV_nolen(val), MAX_STRING_SIZE);
|
||||
data.dbr_string[MAX_STRING_SIZE-1] = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -886,7 +888,7 @@ void CA_get_callback(SV *ca_ref, SV *sub, ...) {
|
||||
while (items > i
|
||||
&& SvOK(ST(i))) {
|
||||
if (SvIOK(ST(i))) {
|
||||
/* Interger => Count arg, zero means current size */
|
||||
/* Integer => Count arg, zero means current size */
|
||||
count = SvIV(ST(i));
|
||||
if (count < 0 || count > ca_element_count(pch->chan)) {
|
||||
croak_msg = "Requested array size is out of range";
|
||||
@@ -962,7 +964,7 @@ SV * CA_create_subscription(SV *ca_ref, const char *mask_str, SV *sub, ...) {
|
||||
while (items > i
|
||||
&& SvOK(ST(i))) {
|
||||
if (SvIOK(ST(i))) {
|
||||
/* Interger => Count arg, zero means current size */
|
||||
/* Integer => Count arg, zero means current size */
|
||||
count = SvIV(ST(i));
|
||||
if (count < 0 || count > ca_element_count(pch->chan)) {
|
||||
croak_msg = "Requested array size is out of range";
|
||||
|
||||
@@ -23,7 +23,7 @@ ifdef T_A
|
||||
# Special settings for Darwin:
|
||||
ifeq ($(OS_CLASS),Darwin)
|
||||
# Use hdepends command (not GNU compiler flags)
|
||||
# to generate header file dependancies for Darwin.
|
||||
# to generate header file dependencies for Darwin.
|
||||
# Darwin has multiple -arch compiler flags.
|
||||
HDEPENDS_METHOD = MKMF
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ int main(int argc,char **argv)
|
||||
SEVCHK(ca_context_create(ca_disable_preemptive_callback),"ca_context_create");
|
||||
SEVCHK(ca_create_channel(argv[1],NULL,NULL,10,&mychid),"ca_create_channel failure");
|
||||
SEVCHK(ca_pend_io(5.0),"ca_pend_io failure");
|
||||
SEVCHK(ca_get(DBR_DOUBLE,mychid,(void *)&data),"ca_get failure");
|
||||
SEVCHK(ca_get(DBR_DOUBLE,mychid,&data),"ca_get failure");
|
||||
SEVCHK(ca_pend_io(5.0),"ca_pend_io failure");
|
||||
printf("%s %f\n",argv[1],data);
|
||||
return(0);
|
||||
|
||||
@@ -167,7 +167,7 @@ sub HELP_MESSAGE {
|
||||
" -w <sec>: Wait time, specifies CA timeout, default is $opt_w second\n",
|
||||
" -c: Use put_callback to wait for completion\n",
|
||||
"Format options:\n",
|
||||
" -t: Terse mode - print only sucessfully written value, without name\n",
|
||||
" -t: Terse mode - print only successfully written value, without name\n",
|
||||
" -l: Long mode \"name timestamp value stat sevr\" (read PVs as DBR_TIME_xxx)\n",
|
||||
" -S: Put string as an array of char (long string)\n",
|
||||
"Enum format:\n",
|
||||
|
||||
@@ -202,7 +202,7 @@ static int caget (pv *pvs, int nPvs, RequestT request, OutputT format,
|
||||
pvs[n].reqElems,
|
||||
pvs[n].chid,
|
||||
event_handler,
|
||||
(void*)&pvs[n]);
|
||||
&pvs[n]);
|
||||
} else {
|
||||
/* We allocate value structure and set nElems */
|
||||
pvs[n].nElems = reqElems && reqElems < nElems ? reqElems : nElems;
|
||||
|
||||
@@ -14,7 +14,7 @@ to stdout.
|
||||
|
||||
The {option}`-s` option allows to specify an interest level for calling Channel
|
||||
Access' internal report function `ca_client_status()`, that prints lots
|
||||
of internal informations on stdout, including environment settings, used
|
||||
of internal information on stdout, including environment settings, used
|
||||
CA ports etc.
|
||||
|
||||
## Options
|
||||
|
||||
@@ -176,7 +176,7 @@ static void connection_handler ( struct connection_handler_args args )
|
||||
ppv->chid,
|
||||
eventMask,
|
||||
event_handler,
|
||||
(void*)ppv,
|
||||
ppv,
|
||||
&ppv->evid);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ void usage (void)
|
||||
" -c: Asynchronous put (use ca_put_callback and wait for completion)\n"
|
||||
" -p <prio>: CA priority (0-%u, default 0=lowest)\n"
|
||||
"Format options:\n"
|
||||
" -t: Terse mode - print only sucessfully written value, without name\n"
|
||||
" -t: Terse mode - print only successfully written value, without name\n"
|
||||
" -l: Long mode \"name timestamp value stat sevr\" (read PVs as DBR_TIME_xxx)\n"
|
||||
"Enum format:\n"
|
||||
" Default: Auto - try value as ENUM string, then as index number\n"
|
||||
@@ -544,7 +544,7 @@ int main (int argc, char *argv[])
|
||||
/* Use callback version of put */
|
||||
pvs[0].status = ECA_NORMAL; /* All ok at the moment */
|
||||
result = ca_array_put_callback (
|
||||
dbrType, count, pvs[0].chid, pbuf, put_event_handler, (void *) pvs);
|
||||
dbrType, count, pvs[0].chid, pbuf, put_event_handler, pvs);
|
||||
} else {
|
||||
/* Use standard put with defined timeout */
|
||||
result = ca_array_put (dbrType, count, pvs[0].chid, pbuf);
|
||||
@@ -571,7 +571,7 @@ int main (int argc, char *argv[])
|
||||
}
|
||||
|
||||
if (result != ECA_NORMAL) {
|
||||
fprintf(stderr, ERL_ERROR " occured writing data: %s\n", ca_message(result));
|
||||
fprintf(stderr, ERL_ERROR " occurred writing data: %s\n", ca_message(result));
|
||||
free(sbuf); free(dbuf); free(ebuf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ int asSetFilename(const char *acf)
|
||||
|
||||
int asSetSubstitutions(const char *substitutions)
|
||||
{
|
||||
if(psubstitutions) free ((void *)psubstitutions);
|
||||
if(psubstitutions) free (psubstitutions);
|
||||
if(substitutions) {
|
||||
psubstitutions = calloc(1,strlen(substitutions)+1);
|
||||
if(!psubstitutions) {
|
||||
@@ -123,7 +123,7 @@ static long asInitCommon(void)
|
||||
static epicsThreadOnceId asInitCommonOnceFlag = EPICS_THREAD_ONCE_INIT;
|
||||
|
||||
|
||||
epicsThreadOnce(&asInitCommonOnceFlag,asInitCommonOnce,(void *)&firstTime);
|
||||
epicsThreadOnce(&asInitCommonOnceFlag, asInitCommonOnce, &firstTime);
|
||||
if(wasFirstTime) {
|
||||
if(!pacf) return(0); /*access security will NEVER be turned on*/
|
||||
} else {
|
||||
@@ -174,7 +174,7 @@ static void asInitTask(ASDBCALLBACK *pcallback)
|
||||
{
|
||||
long status;
|
||||
|
||||
taskwdInsert(epicsThreadGetIdSelf(), wdCallback, (void *)pcallback);
|
||||
taskwdInsert(epicsThreadGetIdSelf(), wdCallback, pcallback);
|
||||
status = asInitCommon();
|
||||
taskwdRemove(epicsThreadGetIdSelf());
|
||||
asInitTheadId = 0;
|
||||
@@ -198,7 +198,7 @@ int asInitAsyn(ASDBCALLBACK *pcallback)
|
||||
asInitTheadId = epicsThreadCreate("asInitTask",
|
||||
(epicsThreadPriorityCAServerHigh + 1),
|
||||
epicsThreadGetStackSize(epicsThreadStackBig),
|
||||
(EPICSTHREADFUNC)asInitTask,(void *)pcallback);
|
||||
(EPICSTHREADFUNC)asInitTask, pcallback);
|
||||
if(asInitTheadId==0) {
|
||||
errMessage(0,"asInit: epicsThreadCreate Error");
|
||||
if(pcallback) {
|
||||
@@ -264,7 +264,7 @@ int astac(const char *pname,const char *user,const char *location)
|
||||
errMessage(status,"asAddClient error");
|
||||
return(1);
|
||||
} else {
|
||||
asPutClientPvt(*pasclientpvt,(void *)precord->name);
|
||||
asPutClientPvt(*pasclientpvt, precord->name);
|
||||
asRegisterClientCallback(*pasclientpvt,astacCallback);
|
||||
}
|
||||
return(0);
|
||||
|
||||
@@ -33,7 +33,7 @@ static const iocshArg asSetSubstitutionsArg0 = { "substitutions",iocshArgString}
|
||||
static const iocshArg * const asSetSubstitutionsArgs[] = {&asSetSubstitutionsArg0};
|
||||
static const iocshFuncDef asSetSubstitutionsFuncDef =
|
||||
{"asSetSubstitutions",1,asSetSubstitutionsArgs,
|
||||
"Set subtitutions used when reading ACF file.\n"
|
||||
"Set substitutions used when reading ACF file.\n"
|
||||
"No immediate effect. Run asInit to (re)load.\n"
|
||||
"Example: asSetSubstitutions var1=5,var2=hello\n"};
|
||||
static void asSetSubstitutionsCallFunc(const iocshArgBuf *args)
|
||||
|
||||
@@ -212,7 +212,7 @@ got_header:
|
||||
pdata[n] = pnext->value;
|
||||
pdataList = pnext;
|
||||
pnext = pnext->next;
|
||||
free((void *)pdataList);
|
||||
free(pdataList);
|
||||
}
|
||||
brkCreateInfo.pTable = pdata;
|
||||
if(create_break(&brkCreateInfo,&brkint[0],MAX_BREAKS,&nBreak))
|
||||
@@ -360,7 +360,7 @@ static int create_break( struct brkCreateInfo *pbci, brkInt *pabrkInt,
|
||||
if (inc < 1)
|
||||
inc = 1;
|
||||
valid = TRUE;
|
||||
/* keep trying intervals until cant do better */
|
||||
/* keep trying intervals until can't do better */
|
||||
expanding = TRUE; /* originally we are trying larger and larger
|
||||
* intervals */
|
||||
while (valid) {
|
||||
|
||||
@@ -65,7 +65,7 @@ typedef struct callbackQueueStats {
|
||||
#define callbackGetPriority(PRIORITY, PCALLBACK) \
|
||||
( (PRIORITY) = (PCALLBACK)->priority )
|
||||
#define callbackSetUser(USER, PCALLBACK) \
|
||||
( (PCALLBACK)->user = (void *) (USER) )
|
||||
( (PCALLBACK)->user = (USER) )
|
||||
#define callbackGetUser(USER, PCALLBACK) \
|
||||
( (USER) = (PCALLBACK)->user )
|
||||
|
||||
|
||||
@@ -339,7 +339,7 @@ static parse_result parse_start(chFilter *filter)
|
||||
}
|
||||
}
|
||||
|
||||
filter->puser = (void*) f;
|
||||
filter->puser = f;
|
||||
|
||||
return parse_continue;
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ long cvtRawToEngBpt(double *pval, short linr, short init,
|
||||
if (!pbrkTable)
|
||||
return S_dbLib_badField;
|
||||
|
||||
*ppbrk = (void *)pbrkTable;
|
||||
*ppbrk = pbrkTable;
|
||||
*plbrk = 0;
|
||||
} else
|
||||
pbrkTable = (brkTable *)*ppbrk;
|
||||
@@ -138,7 +138,7 @@ long cvtEngToRawBpt(double *pval, short linr, short init,
|
||||
if (!pbrkTable)
|
||||
return S_dbLib_badField;
|
||||
|
||||
*ppbrk = (void *)pbrkTable;
|
||||
*ppbrk = pbrkTable;
|
||||
/* start at the beginning */
|
||||
*plbrk = 0;
|
||||
} else
|
||||
|
||||
@@ -183,7 +183,7 @@ static void get_enum_strs(DBADDR *paddr, char **ppbuffer,
|
||||
}
|
||||
|
||||
if(nchoices > NELEMENTS(penum->strs))
|
||||
nchoices = NELEMENTS(penum->strs); /* availible > capacity, truncated list */
|
||||
nchoices = NELEMENTS(penum->strs); /* available > capacity, truncated list */
|
||||
|
||||
penum->no_str = nchoices;
|
||||
|
||||
@@ -365,13 +365,14 @@ static void getOptions(DBADDR *paddr, char **poriginal, long *options,
|
||||
}
|
||||
if( (*options) & DBR_AMSG ) {
|
||||
if (!pfl) {
|
||||
STATIC_ASSERT(sizeof(pcommon->amsg)==sizeof(pfl->amsg));
|
||||
strncpy(pbuffer, pcommon->amsg, sizeof(pcommon->amsg)-1);
|
||||
STATIC_ASSERT(sizeof(pcommon->amsg)==DB_AMSG_SIZE);
|
||||
strncpy(pbuffer, pcommon->amsg, DB_AMSG_SIZE);
|
||||
} else {
|
||||
strncpy(pbuffer, pfl->amsg,sizeof(pfl->amsg)-1);
|
||||
STATIC_ASSERT(sizeof(pfl->amsg)==DB_AMSG_SIZE);
|
||||
strncpy(pbuffer, pfl->amsg, DB_AMSG_SIZE);
|
||||
}
|
||||
pbuffer[sizeof(pcommon->amsg)-1] = '\0';
|
||||
pbuffer += sizeof(pcommon->amsg);
|
||||
pbuffer[DB_AMSG_SIZE-1] = '\0';
|
||||
pbuffer += DB_AMSG_SIZE;
|
||||
}
|
||||
if( (*options) & DBR_UNITS ) {
|
||||
memset(pbuffer,'\0',dbr_units_size);
|
||||
@@ -550,7 +551,7 @@ long dbProcess(dbCommon *precord)
|
||||
monitor_mask |= DBE_VALUE|DBE_LOG;
|
||||
pdbFldDes = pdbRecordType->papFldDes[pdbRecordType->indvalFlddes];
|
||||
db_post_events(precord,
|
||||
(void *)(((char *)precord) + pdbFldDes->offset),
|
||||
((char *)precord) + pdbFldDes->offset,
|
||||
monitor_mask);
|
||||
goto all_done;
|
||||
}
|
||||
@@ -587,7 +588,7 @@ long dbProcess(dbCommon *precord)
|
||||
db_post_events(precord, &precord->sevr, DBE_VALUE);
|
||||
pdbFldDes = pdbRecordType->papFldDes[pdbRecordType->indvalFlddes];
|
||||
db_post_events(precord,
|
||||
(void *)(((char *)precord) + pdbFldDes->offset),
|
||||
((char *)precord) + pdbFldDes->offset,
|
||||
DBE_VALUE|DBE_ALARM);
|
||||
goto all_done;
|
||||
}
|
||||
@@ -597,7 +598,7 @@ long dbProcess(dbCommon *precord)
|
||||
if (!prset || !prset->process) {
|
||||
callNotifyCompletion = TRUE;
|
||||
precord->pact = 1;/*set pact so error is issued only once*/
|
||||
recGblRecordError(S_db_noRSET, (void *)precord, "dbProcess");
|
||||
recGblRecordError(S_db_noRSET, precord, "dbProcess");
|
||||
status = S_db_noRSET;
|
||||
if (*ptrace)
|
||||
printf("%s: No RSET for %s\n", context, precord->name);
|
||||
@@ -709,7 +710,7 @@ void dbInitEntryFromAddr(struct dbAddr *paddr, DBENTRY *pdbentry)
|
||||
struct dbCommon *prec = paddr->precord;
|
||||
dbCommonPvt *ppvt = dbRec2Pvt(prec);
|
||||
|
||||
memset((char *)pdbentry,'\0',sizeof(DBENTRY));
|
||||
memset(pdbentry, '\0', sizeof(DBENTRY));
|
||||
|
||||
pdbentry->pdbbase = pdbbase;
|
||||
pdbentry->precordType = prec->rdes;
|
||||
@@ -723,7 +724,7 @@ void dbInitEntryFromRecord(struct dbCommon *prec, DBENTRY *pdbentry)
|
||||
{
|
||||
dbCommonPvt *ppvt = dbRec2Pvt(prec);
|
||||
|
||||
memset((char *)pdbentry,'\0',sizeof(DBENTRY));
|
||||
memset(pdbentry, '\0', sizeof(DBENTRY));
|
||||
|
||||
pdbentry->pdbbase = pdbbase;
|
||||
pdbentry->precordType = prec->rdes;
|
||||
@@ -805,7 +806,7 @@ int dbLoadRecords(const char* file, const char* subs)
|
||||
if(dbLoadRecordsHook)
|
||||
dbLoadRecordsHook(file, subs);
|
||||
} else {
|
||||
fprintf(stderr, ERL_ERROR " failed to load '%s'\n", file);
|
||||
fprintf(stderr, ERL_ERROR ": Failed to load '%s'\n", file);
|
||||
if(status==-2)
|
||||
fprintf(stderr, " Records cannot be loaded after iocInit!\n");
|
||||
}
|
||||
@@ -851,7 +852,7 @@ static long getLinkValue(DBADDR *paddr, short dbrType,
|
||||
{
|
||||
const char *rtnString = dbGetString(&dbEntry);
|
||||
|
||||
strncpy(pbuf, rtnString, maxlen-1);
|
||||
strncpy(pbuf, rtnString, maxlen);
|
||||
pbuf[maxlen-1] = 0;
|
||||
if(dbrType!=DBR_STRING)
|
||||
nReq = strlen(pbuf)+1;
|
||||
@@ -1070,7 +1071,7 @@ static long dbPutFieldLink(DBADDR *paddr,
|
||||
dbFldDes *pfldDes = paddr->pfldDes;
|
||||
long special = paddr->special;
|
||||
struct link *plink = (struct link *)paddr->pfield;
|
||||
const char *pstring = (const char *)pbuffer;
|
||||
const char *pstring = pbuffer;
|
||||
struct dsxt *old_dsxt = NULL;
|
||||
dset *new_dset = NULL;
|
||||
struct dsxt *new_dsxt = NULL;
|
||||
@@ -1095,7 +1096,7 @@ static long dbPutFieldLink(DBADDR *paddr,
|
||||
return S_db_badDbrtype;
|
||||
}
|
||||
|
||||
status = dbParseLink(pstring, pfldDes->field_type, &link_info);
|
||||
status = dbParseLink(pstring, pfldDes->field_type, &link_info, precord->name, pfldDes->name);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
@@ -1130,7 +1131,7 @@ static long dbPutFieldLink(DBADDR *paddr,
|
||||
}
|
||||
|
||||
if (dbCanSetLink(plink, &link_info, new_devsup)) {
|
||||
/* link type mis-match prevents assignment */
|
||||
/* link type mismatch prevents assignment */
|
||||
status = S_dbLib_badField;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ static int dbca_chan_count;
|
||||
* The libca callbacks take no action if pca->plink==NULL.
|
||||
*
|
||||
* dbCaPutLinkCallback causes an additional complication because
|
||||
* when dbCaRemoveLink is called the callback may not have occured.
|
||||
* when dbCaRemoveLink is called the callback may not have occurred.
|
||||
* If putComplete sees plink==0 it will not call the user's code.
|
||||
* If pca->putCallback is non-zero, dbCaTask will call the
|
||||
* user's callback AFTER it has called ca_clear_channel.
|
||||
@@ -487,7 +487,7 @@ long dbCaGetLink(struct link *plink, short dbrType, void *pdest,
|
||||
ntoget = pca->usedelements;
|
||||
*nelements = ntoget;
|
||||
|
||||
memset((void *)&dbAddr, 0, sizeof(dbAddr));
|
||||
memset(&dbAddr, 0, sizeof(dbAddr));
|
||||
dbAddr.pfield = pca->pgetNative;
|
||||
/*Following will only be used for pca->dbrType == DBR_STRING*/
|
||||
dbAddr.field_size = MAX_STRING_SIZE;
|
||||
@@ -568,7 +568,7 @@ long dbCaPutLinkCallback(struct link *plink,short dbrType,
|
||||
long (*aConvert)(struct dbAddr *paddr, const void *from, long nreq, long nfrom, long off);
|
||||
|
||||
aConvert = dbPutConvertRoutine[dbrType][newType];
|
||||
memset((void *)&dbAddr, 0, sizeof(dbAddr));
|
||||
memset(&dbAddr, 0, sizeof(dbAddr));
|
||||
dbAddr.pfield = pca->pputNative;
|
||||
/*Following only used for DBF_STRING*/
|
||||
dbAddr.field_size = MAX_STRING_SIZE;
|
||||
@@ -1139,7 +1139,7 @@ static void dbCaTask(void *arg)
|
||||
}
|
||||
if (link_action & CA_CONNECT) {
|
||||
status = ca_create_channel(
|
||||
pca->pvname,connectionCallback,(void *)pca,
|
||||
pca->pvname, connectionCallback, pca,
|
||||
CA_PRIORITY_DB_LINKS, &(pca->chid));
|
||||
if (status != ECA_NORMAL) {
|
||||
errlogPrintf("dbCaTask ca_create_channel %s\n",
|
||||
|
||||
@@ -346,7 +346,7 @@ DBCORE_API void dbChannelInit(void);
|
||||
/** \brief Cleanup the dbChannel subsystem. */
|
||||
DBCORE_API void dbChannelExit(void);
|
||||
|
||||
/** \brief Test the given PV name for existance.
|
||||
/** \brief Test the given PV name for existence.
|
||||
*
|
||||
* This routine looks up the given record and field name, but does not check
|
||||
* whether any field modifiers given after the field name are correct.
|
||||
|
||||
@@ -522,7 +522,7 @@ hardware.
|
||||
|
||||
=item *
|
||||
|
||||
Positive values (normally between 1-255) get the time of the last occurance of
|
||||
Positive values (normally between 1-255) get the time of the last occurrence of
|
||||
the numbered generalTime event.
|
||||
|
||||
=back
|
||||
|
||||
@@ -384,7 +384,7 @@ static long dbDbPutValue(struct link *plink, short dbrType,
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (dbChannelField(chan) == (void *) &pdest->proc ||
|
||||
if (dbChannelField(chan) == &pdest->proc ||
|
||||
(ppv_link->pvlMask & pvlOptPP && pdest->scan == 0)) {
|
||||
status = processTarget(psrce, pdest);
|
||||
}
|
||||
|
||||
@@ -200,19 +200,19 @@ int dbel ( const char *pname, unsigned level )
|
||||
const void * taskId;
|
||||
LOCKEVQUE(pevent->ev_que);
|
||||
nEntriesFree = ringSpace ( pevent->ev_que );
|
||||
taskId = ( void * ) pevent->ev_que->evUser->taskid;
|
||||
taskId = pevent->ev_que->evUser->taskid;
|
||||
UNLOCKEVQUE(pevent->ev_que);
|
||||
if ( nEntriesFree == 0u ) {
|
||||
printf ( ", thread=%p, queue full",
|
||||
(void *) taskId );
|
||||
taskId );
|
||||
}
|
||||
else if ( nEntriesFree == EVENTQUESIZE ) {
|
||||
printf ( ", thread=%p, queue empty",
|
||||
(void *) taskId );
|
||||
taskId );
|
||||
}
|
||||
else {
|
||||
printf ( ", thread=%p, unused entries=%u",
|
||||
(void *) taskId, nEntriesFree );
|
||||
taskId, nEntriesFree );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,9 +234,9 @@ int dbel ( const char *pname, unsigned level )
|
||||
|
||||
if ( level > 3 ) {
|
||||
printf ( ", ev %p, ev que %p, ev user %p",
|
||||
( void * ) pevent,
|
||||
( void * ) pevent->ev_que,
|
||||
( void * ) pevent->ev_que->evUser );
|
||||
pevent,
|
||||
pevent->ev_que,
|
||||
pevent->ev_que->evUser );
|
||||
}
|
||||
|
||||
printf( "\n" );
|
||||
@@ -557,6 +557,40 @@ static void event_remove ( struct event_que *ev_que,
|
||||
pevent->npend--;
|
||||
}
|
||||
|
||||
/* synchronize with worker thread.
|
||||
*
|
||||
* On return, any previously pending events or extra labor have been handled.
|
||||
*
|
||||
* caller must lock evUser->lock
|
||||
*/
|
||||
static
|
||||
void db_sync_event (struct event_user * const evUser)
|
||||
{
|
||||
/* grab current cycle counter, then wait for it to change */
|
||||
epicsUInt32 curSeq = evUser->pflush_seq;
|
||||
event_waiter wait;
|
||||
wait.wake = epicsEventCreate(epicsEventEmpty); /* failure allowed */
|
||||
|
||||
ellAdd(&evUser->waiters, &wait.node);
|
||||
do {
|
||||
epicsMutexUnlock( evUser->lock );
|
||||
/* ensure worker will cycle at least once */
|
||||
epicsEventMustTrigger(evUser->ppendsem);
|
||||
|
||||
if(wait.wake) {
|
||||
epicsEventMustWait(wait.wake);
|
||||
} else {
|
||||
epicsThreadSleep(0.01); /* ick. but better than cantProceed() */
|
||||
}
|
||||
|
||||
epicsMutexMustLock ( evUser->lock );
|
||||
} while(curSeq == evUser->pflush_seq);
|
||||
ellDelete(&evUser->waiters, &wait.node);
|
||||
/* destroy under lock to ensure epicsEventMustTrigger() has returned */
|
||||
if(wait.wake)
|
||||
epicsEventDestroy(wait.wake);
|
||||
}
|
||||
|
||||
/*
|
||||
* DB_CANCEL_EVENT()
|
||||
*
|
||||
@@ -594,34 +628,9 @@ void db_cancel_event (dbEventSubscription event)
|
||||
UNLOCKEVQUE (que);
|
||||
|
||||
if(sync) {
|
||||
/* cycle through worker */
|
||||
struct event_user *evUser = que->evUser;
|
||||
epicsUInt32 curSeq;
|
||||
event_waiter wait;
|
||||
wait.wake = epicsEventCreate(epicsEventEmpty); /* may fail */
|
||||
|
||||
epicsMutexMustLock ( evUser->lock );
|
||||
ellAdd(&evUser->waiters, &wait.node);
|
||||
/* grab current cycle counter, then wait for it to change */
|
||||
curSeq = evUser->pflush_seq;
|
||||
do {
|
||||
epicsMutexUnlock( evUser->lock );
|
||||
/* ensure worker will cycle at least once */
|
||||
epicsEventMustTrigger(evUser->ppendsem);
|
||||
|
||||
if(wait.wake) {
|
||||
epicsEventMustWait(wait.wake);
|
||||
} else {
|
||||
epicsThreadSleep(0.01); /* ick. but better than cantProceed() */
|
||||
}
|
||||
|
||||
epicsMutexMustLock ( evUser->lock );
|
||||
} while(curSeq == evUser->pflush_seq);
|
||||
ellDelete(&evUser->waiters, &wait.node);
|
||||
/* destroy under lock to ensure epicsEventMustTrigger() has returned */
|
||||
if(wait.wake)
|
||||
epicsEventDestroy(wait.wake);
|
||||
epicsMutexUnlock( evUser->lock );
|
||||
epicsMutexMustLock ( que->evUser->lock );
|
||||
db_sync_event(que->evUser);
|
||||
epicsMutexUnlock( que->evUser->lock );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -635,10 +644,10 @@ void db_flush_extra_labor_event (dbEventCtx ctx)
|
||||
struct event_user * const evUser = (struct event_user *) ctx;
|
||||
|
||||
epicsMutexMustLock ( evUser->lock );
|
||||
while ( evUser->extraLaborBusy ) {
|
||||
epicsMutexUnlock ( evUser->lock );
|
||||
epicsThreadSleep(0.1);
|
||||
epicsMutexMustLock ( evUser->lock );
|
||||
if ( evUser->extraLaborBusy || (evUser->extra_labor && evUser->extralabor_sub) ) {
|
||||
db_sync_event(evUser);
|
||||
// At this point, original labor completed.
|
||||
// Do not wait for any additional labor queued afterwards.
|
||||
}
|
||||
epicsMutexUnlock ( evUser->lock );
|
||||
}
|
||||
@@ -884,7 +893,7 @@ unsigned int caEventMask
|
||||
* Only send event msg if they are waiting on the field which
|
||||
* changed or pval==NULL, and are waiting on matching event
|
||||
*/
|
||||
if ( (dbChannelField(pevent->chan) == (void *)pField || pField==NULL) &&
|
||||
if ( (dbChannelField(pevent->chan) == pField || pField==NULL) &&
|
||||
(caEventMask & pevent->select)) {
|
||||
db_field_log *pLog = db_create_event_log(pevent);
|
||||
if(pLog)
|
||||
@@ -1027,9 +1036,7 @@ static void event_task (void *pParm)
|
||||
* labor to this task
|
||||
*/
|
||||
epicsMutexMustLock ( evUser->lock );
|
||||
evUser->extraLaborBusy = TRUE;
|
||||
if ( evUser->extra_labor && evUser->extralabor_sub ) {
|
||||
evUser->extra_labor = FALSE;
|
||||
pExtraLaborSub = evUser->extralabor_sub;
|
||||
pExtraLaborArg = evUser->extralabor_arg;
|
||||
}
|
||||
@@ -1037,12 +1044,14 @@ static void event_task (void *pParm)
|
||||
pExtraLaborSub = NULL;
|
||||
pExtraLaborArg = NULL;
|
||||
}
|
||||
evUser->extra_labor = FALSE;
|
||||
if ( pExtraLaborSub ) {
|
||||
evUser->extraLaborBusy = TRUE;
|
||||
epicsMutexUnlock ( evUser->lock );
|
||||
(*pExtraLaborSub)(pExtraLaborArg);
|
||||
epicsMutexMustLock ( evUser->lock );
|
||||
evUser->extraLaborBusy = FALSE;
|
||||
}
|
||||
evUser->extraLaborBusy = FALSE;
|
||||
|
||||
for ( ev_que = &evUser->firstque; ev_que; ev_que = ev_que->nextque ) {
|
||||
/* unlock during iteration is safe as event_que will not be free'd */
|
||||
@@ -1126,7 +1135,7 @@ int db_start_events (
|
||||
taskname = EVENT_PEND_NAME;
|
||||
}
|
||||
evUser->taskid = epicsThreadCreateOpt (
|
||||
taskname, event_task, (void *)evUser, &opts);
|
||||
taskname, event_task, evUser, &opts);
|
||||
if (!evUser->taskid) {
|
||||
epicsMutexUnlock ( evUser->lock );
|
||||
return DB_EVENT_ERROR;
|
||||
|
||||
@@ -199,7 +199,7 @@ static const iocshFuncDef dblFuncDef = {"dbl",2,dblArgs,
|
||||
"Database list.\n"
|
||||
"List record/field names.\n"
|
||||
"With no arguments, lists all record names.\n"
|
||||
"If record type is given, then only the names of records maching the type are printed\n"
|
||||
"If record type is given, then only the names of records matching the type are printed\n"
|
||||
"If a field list is given, then their values are also printed\n\n"
|
||||
"Example: dbl(\"\")\n"
|
||||
" dbl(\"ai\")\n"
|
||||
@@ -440,7 +440,7 @@ static const iocshArg scanOnceQueueShowArg0 = { "reset",iocshArgInt};
|
||||
static const iocshArg * const scanOnceQueueShowArgs[1] =
|
||||
{&scanOnceQueueShowArg0};
|
||||
static const iocshFuncDef scanOnceQueueShowFuncDef = {"scanOnceQueueShow",1,scanOnceQueueShowArgs,
|
||||
"Show details and statitics of scan once queue processing.\n"};
|
||||
"Show details and statistics of scan once queue processing.\n"};
|
||||
static void scanOnceQueueShowCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
scanOnceQueueShow(args[0].ival);
|
||||
|
||||
@@ -233,7 +233,7 @@ static void processNotifyCommon(processNotify *ppn, dbCommon *precord, int first
|
||||
if (ppn->requestType == putProcessRequest ||
|
||||
ppn->requestType == putProcessGetRequest) {
|
||||
/* Check if puts disabled */
|
||||
if (precord->disp && (dbChannelField(ppn->chan) != (void *) &precord->disp)) {
|
||||
if (precord->disp && (dbChannelField(ppn->chan) != &precord->disp)) {
|
||||
ppn->putCallback(ppn, putDisabledType);
|
||||
} else {
|
||||
didPut = ppn->putCallback(ppn, putType);
|
||||
@@ -241,7 +241,7 @@ static void processNotifyCommon(processNotify *ppn, dbCommon *precord, int first
|
||||
}
|
||||
/* Check if dbProcess should be called */
|
||||
if (didPut &&
|
||||
((dbChannelField(ppn->chan) == (void *) &precord->proc) ||
|
||||
((dbChannelField(ppn->chan) == &precord->proc) ||
|
||||
(dbChannelFldDes(ppn->chan)->process_passive && precord->scan == 0)))
|
||||
doProcess = 1;
|
||||
else
|
||||
@@ -338,7 +338,7 @@ void dbProcessNotify(processNotify *ppn)
|
||||
if (ppn->requestType == putProcessRequest ||
|
||||
ppn->requestType == putProcessGetRequest) {
|
||||
/* Check if puts disabled */
|
||||
if (precord->disp && (dbChannelField(ppn->chan) != (void *) &precord->disp)) {
|
||||
if (precord->disp && (dbChannelField(ppn->chan) != &precord->disp)) {
|
||||
ppn->putCallback(ppn, putDisabledType);
|
||||
} else {
|
||||
ppn->putCallback(ppn, putFieldType);
|
||||
@@ -661,7 +661,7 @@ int dbNotifyDump(void)
|
||||
|
||||
pnotifyPvt = (notifyPvt *) ppn->pnotifyPvt;
|
||||
printf("%s state %d ppn %p\n waitList\n",
|
||||
precord->name, pnotifyPvt->state, (void*) ppn);
|
||||
precord->name, pnotifyPvt->state, ppn);
|
||||
ppnr = (processNotifyRecord *) ellFirst(&pnotifyPvt->waitList);
|
||||
while (ppnr) {
|
||||
printf(" %s pact %d\n",
|
||||
|
||||
@@ -245,7 +245,7 @@ void scanAdd(struct dbCommon *precord)
|
||||
scan = precord->scan;
|
||||
if (scan == menuScanPassive) return;
|
||||
if (scan < 0 || scan >= nPeriodic + SCAN_1ST_PERIODIC) {
|
||||
recGblRecordError(-1, (void *)precord,
|
||||
recGblRecordError(-1, precord,
|
||||
"scanAdd detected illegal SCAN value");
|
||||
} else if (scan == menuScanEvent) {
|
||||
char* eventname;
|
||||
@@ -255,7 +255,7 @@ void scanAdd(struct dbCommon *precord)
|
||||
eventname = precord->evnt;
|
||||
prio = precord->prio;
|
||||
if (prio < 0 || prio >= NUM_CALLBACK_PRIORITIES) {
|
||||
recGblRecordError(-1, (void *)precord,
|
||||
recGblRecordError(-1, precord,
|
||||
"scanAdd: illegal prio field");
|
||||
return;
|
||||
}
|
||||
@@ -267,14 +267,14 @@ void scanAdd(struct dbCommon *precord)
|
||||
long (*get_ioint_info)(int, struct dbCommon *, IOSCANPVT*);
|
||||
|
||||
if (precord->dset == NULL){
|
||||
recGblRecordError(-1, (void *)precord,
|
||||
recGblRecordError(-1, precord,
|
||||
"scanAdd: I/O Intr not valid (no DSET) ");
|
||||
precord->scan = menuScanPassive;
|
||||
return;
|
||||
}
|
||||
get_ioint_info = precord->dset->get_ioint_info;
|
||||
if (get_ioint_info == NULL) {
|
||||
recGblRecordError(-1, (void *)precord,
|
||||
recGblRecordError(-1, precord,
|
||||
"scanAdd: I/O Intr not valid (no get_ioint_info)");
|
||||
precord->scan = menuScanPassive;
|
||||
return;
|
||||
@@ -284,14 +284,14 @@ void scanAdd(struct dbCommon *precord)
|
||||
return;
|
||||
}
|
||||
if (piosh == NULL) {
|
||||
recGblRecordError(-1, (void *)precord,
|
||||
recGblRecordError(-1, precord,
|
||||
"scanAdd: I/O Intr not valid");
|
||||
precord->scan = menuScanPassive;
|
||||
return;
|
||||
}
|
||||
prio = precord->prio;
|
||||
if (prio < 0 || prio >= NUM_CALLBACK_PRIORITIES) {
|
||||
recGblRecordError(-1, (void *)precord,
|
||||
recGblRecordError(-1, precord,
|
||||
"scanAdd: illegal prio field");
|
||||
precord->scan = menuScanPassive;
|
||||
return;
|
||||
@@ -313,7 +313,7 @@ void scanDelete(struct dbCommon *precord)
|
||||
scan = precord->scan;
|
||||
if (scan == menuScanPassive) return;
|
||||
if (scan < 0 || scan >= nPeriodic + SCAN_1ST_PERIODIC) {
|
||||
recGblRecordError(-1, (void *)precord,
|
||||
recGblRecordError(-1, precord,
|
||||
"scanDelete detected illegal SCAN value");
|
||||
} else if (scan == menuScanEvent) {
|
||||
int prio;
|
||||
@@ -322,7 +322,7 @@ void scanDelete(struct dbCommon *precord)
|
||||
|
||||
prio = precord->prio;
|
||||
if (prio < 0 || prio >= NUM_CALLBACK_PRIORITIES) {
|
||||
recGblRecordError(-1, (void *)precord,
|
||||
recGblRecordError(-1, precord,
|
||||
"scanDelete detected illegal PRIO field");
|
||||
return;
|
||||
}
|
||||
@@ -335,25 +335,25 @@ void scanDelete(struct dbCommon *precord)
|
||||
long (*get_ioint_info)(int, struct dbCommon *, IOSCANPVT*);
|
||||
|
||||
if (precord->dset==NULL) {
|
||||
recGblRecordError(-1, (void *)precord,
|
||||
recGblRecordError(-1, precord,
|
||||
"scanDelete: I/O Intr not valid (no DSET)");
|
||||
return;
|
||||
}
|
||||
get_ioint_info=precord->dset->get_ioint_info;
|
||||
if (get_ioint_info == NULL) {
|
||||
recGblRecordError(-1, (void *)precord,
|
||||
recGblRecordError(-1, precord,
|
||||
"scanDelete: I/O Intr not valid (no get_ioint_info)");
|
||||
return;
|
||||
}
|
||||
if (get_ioint_info(1, precord, &piosh)) return;
|
||||
if (piosh == NULL) {
|
||||
recGblRecordError(-1, (void *)precord,
|
||||
recGblRecordError(-1, precord,
|
||||
"scanDelete: I/O Intr not valid");
|
||||
return;
|
||||
}
|
||||
prio = precord->prio;
|
||||
if (prio < 0 || prio >= NUM_CALLBACK_PRIORITIES) {
|
||||
recGblRecordError(-1, (void *)precord,
|
||||
recGblRecordError(-1, precord,
|
||||
"scanDelete: get_ioint_info returned illegal priority");
|
||||
return;
|
||||
}
|
||||
@@ -949,7 +949,7 @@ static void spawnPeriodic(int ind)
|
||||
|
||||
sprintf(taskName, "scan-%g", ppsl->period);
|
||||
periodicTaskId[ind] = epicsThreadCreateOpt(
|
||||
taskName, periodicTask, (void *)ppsl, &opts);
|
||||
taskName, periodicTask, ppsl, &opts);
|
||||
|
||||
epicsEventWait(startStopEvent);
|
||||
}
|
||||
@@ -1103,14 +1103,14 @@ static void deleteFromList(struct dbCommon *precord, scan_list *psl)
|
||||
epicsMutexUnlock(psl->lock);
|
||||
errlogPrintf("dbScan: Tried to delete record from wrong scan list!\n"
|
||||
"\t%s.SPVT = NULL, but psl = %p\n",
|
||||
precord->name, (void *)psl);
|
||||
precord->name, psl);
|
||||
return;
|
||||
}
|
||||
if (pse->pscan_list != psl) {
|
||||
epicsMutexUnlock(psl->lock);
|
||||
errlogPrintf("dbScan: Tried to delete record from wrong scan list!\n"
|
||||
"\t%s.SPVT->pscan_list = %p but psl = %p\n",
|
||||
precord->name, (void *)pse, (void *)psl);
|
||||
precord->name, pse, psl);
|
||||
return;
|
||||
}
|
||||
pse->pscan_list = NULL;
|
||||
|
||||
@@ -112,7 +112,7 @@ DBCORE_API void scanIoInit(IOSCANPVT *ppios);
|
||||
* @return
|
||||
*/
|
||||
DBCORE_API unsigned int scanIoRequest(IOSCANPVT pios);
|
||||
/** @brief Process all records on the scan list for the specificed priority.
|
||||
/** @brief Process all records on the scan list for the specified priority.
|
||||
*
|
||||
* Also executes the callback set by scanIoSetComplete()
|
||||
*
|
||||
|
||||
@@ -45,7 +45,7 @@ dbSubscriptionIO::dbSubscriptionIO (
|
||||
{
|
||||
epicsGuardRelease < epicsMutex > unguard ( guard );
|
||||
this->es = db_add_event ( ctx, dbch,
|
||||
dbSubscriptionEventCallback, (void *) this, maskIn );
|
||||
dbSubscriptionEventCallback, this, maskIn );
|
||||
if ( this->es == 0 ) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
@@ -192,8 +192,8 @@ long dbl(const char *precordTypename, const char *fields)
|
||||
status = dbNextRecordType(pdbentry);
|
||||
}
|
||||
if (nfields > 0) {
|
||||
free((void *)papfields);
|
||||
free((void *)fieldnames);
|
||||
free(papfields);
|
||||
free(fieldnames);
|
||||
}
|
||||
dbFinishEntry(pdbentry);
|
||||
return 0;
|
||||
@@ -334,8 +334,8 @@ long dbglob(const char *pmask,const char *fields)
|
||||
status = dbNextRecordType(pdbentry);
|
||||
}
|
||||
if (nfields > 0) {
|
||||
free((void *)papfields);
|
||||
free((void *)fieldnames);
|
||||
free(papfields);
|
||||
free(fieldnames);
|
||||
}
|
||||
dbFinishEntry(pdbentry);
|
||||
return 0;
|
||||
@@ -826,7 +826,7 @@ static void printBuffer(
|
||||
|
||||
if (reqOptions & DBR_STATUS) {
|
||||
if (retOptions & DBR_STATUS) {
|
||||
struct dbr_status *pdbr_status = (void *)pbuffer;
|
||||
struct dbr_status *pdbr_status = pbuffer;
|
||||
|
||||
printf("status = %u, severity = %u\n",
|
||||
pdbr_status->status,
|
||||
@@ -840,7 +840,7 @@ static void printBuffer(
|
||||
|
||||
if (reqOptions & DBR_UNITS) {
|
||||
if (retOptions & DBR_UNITS) {
|
||||
struct dbr_units *pdbr_units = (void *)pbuffer;
|
||||
struct dbr_units *pdbr_units = pbuffer;
|
||||
|
||||
printf("units = \"%s\"\n",
|
||||
pdbr_units->units);
|
||||
@@ -853,7 +853,7 @@ static void printBuffer(
|
||||
|
||||
if (reqOptions & DBR_PRECISION) {
|
||||
if (retOptions & DBR_PRECISION){
|
||||
struct dbr_precision *pdbr_precision = (void *)pbuffer;
|
||||
struct dbr_precision *pdbr_precision = pbuffer;
|
||||
|
||||
printf("precision = %ld\n",
|
||||
pdbr_precision->precision.dp);
|
||||
@@ -866,7 +866,7 @@ static void printBuffer(
|
||||
|
||||
if (reqOptions & DBR_TIME) {
|
||||
if (retOptions & DBR_TIME) {
|
||||
struct dbr_time *pdbr_time = (void *)pbuffer;
|
||||
struct dbr_time *pdbr_time = pbuffer;
|
||||
char time_buf[40];
|
||||
epicsTimeToStrftime(time_buf, 40, "%Y-%m-%d %H:%M:%S.%09f",
|
||||
&pdbr_time->time);
|
||||
@@ -880,7 +880,7 @@ static void printBuffer(
|
||||
|
||||
if (reqOptions & DBR_ENUM_STRS) {
|
||||
if (retOptions & DBR_ENUM_STRS) {
|
||||
struct dbr_enumStrs *pdbr_enumStrs = (void *)pbuffer;
|
||||
struct dbr_enumStrs *pdbr_enumStrs = pbuffer;
|
||||
|
||||
printf("no_strs = %u:\n",
|
||||
pdbr_enumStrs->no_str);
|
||||
@@ -895,7 +895,7 @@ static void printBuffer(
|
||||
|
||||
if (reqOptions & DBR_GR_LONG) {
|
||||
if (retOptions & DBR_GR_LONG) {
|
||||
struct dbr_grLong *pdbr_grLong = (void *)pbuffer;
|
||||
struct dbr_grLong *pdbr_grLong = pbuffer;
|
||||
|
||||
printf("grLong: %d .. %d\n",
|
||||
pdbr_grLong->lower_disp_limit,
|
||||
@@ -909,7 +909,7 @@ static void printBuffer(
|
||||
|
||||
if (reqOptions & DBR_GR_DOUBLE) {
|
||||
if (retOptions & DBR_GR_DOUBLE) {
|
||||
struct dbr_grDouble *pdbr_grDouble = (void *)pbuffer;
|
||||
struct dbr_grDouble *pdbr_grDouble = pbuffer;
|
||||
|
||||
printf("grDouble: %g .. %g\n",
|
||||
pdbr_grDouble->lower_disp_limit,
|
||||
@@ -923,7 +923,7 @@ static void printBuffer(
|
||||
|
||||
if (reqOptions & DBR_CTRL_LONG) {
|
||||
if (retOptions & DBR_CTRL_LONG){
|
||||
struct dbr_ctrlLong *pdbr_ctrlLong = (void *)pbuffer;
|
||||
struct dbr_ctrlLong *pdbr_ctrlLong = pbuffer;
|
||||
|
||||
printf("ctrlLong: %d .. %d\n",
|
||||
pdbr_ctrlLong->lower_ctrl_limit,
|
||||
@@ -937,7 +937,7 @@ static void printBuffer(
|
||||
|
||||
if (reqOptions & DBR_CTRL_DOUBLE) {
|
||||
if (retOptions & DBR_CTRL_DOUBLE) {
|
||||
struct dbr_ctrlDouble *pdbr_ctrlDouble = (void *)pbuffer;
|
||||
struct dbr_ctrlDouble *pdbr_ctrlDouble = pbuffer;
|
||||
|
||||
printf("ctrlDouble: %g .. %g\n",
|
||||
pdbr_ctrlDouble->lower_ctrl_limit,
|
||||
@@ -951,7 +951,7 @@ static void printBuffer(
|
||||
|
||||
if (reqOptions & DBR_AL_LONG) {
|
||||
if (retOptions & DBR_AL_LONG) {
|
||||
struct dbr_alLong *pdbr_alLong = (void *)pbuffer;
|
||||
struct dbr_alLong *pdbr_alLong = pbuffer;
|
||||
|
||||
printf("alLong: %d < %d .. %d < %d\n",
|
||||
pdbr_alLong->lower_alarm_limit,
|
||||
@@ -967,7 +967,7 @@ static void printBuffer(
|
||||
|
||||
if (reqOptions & DBR_AL_DOUBLE) {
|
||||
if (retOptions & DBR_AL_DOUBLE) {
|
||||
struct dbr_alDouble *pdbr_alDouble = (void *)pbuffer;
|
||||
struct dbr_alDouble *pdbr_alDouble = pbuffer;
|
||||
|
||||
printf("alDouble: %g < %g .. %g < %g\n",
|
||||
pdbr_alDouble->lower_alarm_limit,
|
||||
@@ -1224,7 +1224,7 @@ static int dbpr_report(
|
||||
break;
|
||||
|
||||
case DBF_NOACCESS:
|
||||
if (pfield == (void *)&paddr->precord->time) {
|
||||
if (pfield == &paddr->precord->time) {
|
||||
/* Special for the TIME field, make it human-readable */
|
||||
char time_buf[40];
|
||||
epicsTimeToStrftime(time_buf, 40, "%Y-%m-%d %H:%M:%S.%09f",
|
||||
|
||||
@@ -27,7 +27,7 @@ DBCORE_API long dbnr(int verbose);
|
||||
/* list aliases */
|
||||
DBCORE_API long dbla(const char *pmask);
|
||||
/* list infos */
|
||||
DBCORE_API long dbli(const char *patern);
|
||||
DBCORE_API long dbli(const char *pattern);
|
||||
/*list records filtered by glob pattern*/
|
||||
DBCORE_API long dbglob(const char *ppattern,const char *fields);
|
||||
/*list records filtered by glob pattern; alias for dbglob*/
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
#include "errSymTbl.h"
|
||||
#include "iocshRegisterCommon.h"
|
||||
|
||||
#define DBR_NAME(dbrType) (VALID_DB_REQ(dbrType) ? pamapdbfType[dbrType].strvalue+3 : "???")
|
||||
|
||||
static dbEventCtx testEvtCtx;
|
||||
static epicsMutexId testEvtLock;
|
||||
static ELLLIST testEvtList; /* holds testMonitor::node */
|
||||
@@ -153,8 +155,8 @@ long testdbVPutField(const char* pv, short dbrType, va_list ap)
|
||||
OP(DBR_ENUM, int, enum16);
|
||||
#undef OP
|
||||
default:
|
||||
testFail("invalid DBR: dbPutField(\"%s\", %d, ...)",
|
||||
dbChannelName(chan), dbrType);
|
||||
testFail("invalid DBR: dbPutField(\"%s\", DBR%s, ...)",
|
||||
dbChannelName(chan), DBR_NAME(dbrType));
|
||||
ret = S_db_badDbrtype;
|
||||
break;
|
||||
}
|
||||
@@ -174,7 +176,8 @@ void testdbPutFieldOk(const char* pv, int dbrType, ...)
|
||||
ret = testdbVPutField(pv, dbrType, ap);
|
||||
va_end(ap);
|
||||
|
||||
testOk(ret==0, "dbPutField(\"%s\", %d, ...) -> %#lx (%s)", pv, dbrType, ret, errSymMsg(ret));
|
||||
testOk(ret==0, "dbPutField(\"%s\", DBR%s, ...) -> %#lx (%s)",
|
||||
pv, DBR_NAME(dbrType), ret, errSymMsg(ret));
|
||||
}
|
||||
|
||||
void testdbPutFieldFail(long status, const char* pv, int dbrType, ...)
|
||||
@@ -186,8 +189,8 @@ void testdbPutFieldFail(long status, const char* pv, int dbrType, ...)
|
||||
ret = testdbVPutField(pv, dbrType, ap);
|
||||
va_end(ap);
|
||||
|
||||
testOk(ret==status, "dbPutField(\"%s\", %d, ...) -> %#lx (%s) == %#lx (%s)",
|
||||
pv, dbrType, status, errSymMsg(status), ret, errSymMsg(ret));
|
||||
testOk(ret==status, "dbPutField(\"%s\", DBR%s, ...) -> %#lx (%s) == %#lx (%s)",
|
||||
pv, DBR_NAME(dbrType), status, errSymMsg(status), ret, errSymMsg(ret));
|
||||
}
|
||||
|
||||
void testdbGetFieldEqual(const char* pv, int dbrType, ...)
|
||||
@@ -213,10 +216,12 @@ void testdbVGetFieldEqual(const char* pv, short dbrType, va_list ap)
|
||||
|
||||
status = dbChannelGetField(chan, dbrType, pod.bytes, NULL, &nReq, NULL);
|
||||
if (status) {
|
||||
testFail("dbGetField(\"%s\", %d, ...) -> %#lx (%s)", pv, dbrType, status, errSymMsg(status));
|
||||
testFail("dbGetField(\"%s\", DBR%s, ...) -> %#lx (%s)",
|
||||
pv, DBR_NAME(dbrType), status, errSymMsg(status));
|
||||
goto done;
|
||||
} else if(nReq==0) {
|
||||
testFail("dbGetField(\"%s\", %d, ...) -> zero length", pv, dbrType);
|
||||
testFail("dbGetField(\"%s\", DBR%s, ...) -> zero length",
|
||||
pv, DBR_NAME(dbrType));
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -224,13 +229,14 @@ void testdbVGetFieldEqual(const char* pv, short dbrType, va_list ap)
|
||||
case DBR_STRING: {
|
||||
const char *expect = va_arg(ap, char*);
|
||||
testOk(strcmp(expect, pod.valStr)==0,
|
||||
"dbGetField(\"%s\", %d) -> \"%s\" == \"%s\"",
|
||||
pv, dbrType, expect, pod.valStr);
|
||||
"dbGetField(\"%s\", DBR%s) -> \"%s\" == \"%s\"",
|
||||
pv, DBR_NAME(dbrType), expect, pod.valStr);
|
||||
break;
|
||||
}
|
||||
#define OP(DBR,Type,mem,pat) case DBR: {Type expect = va_arg(ap,Type); \
|
||||
testOk(expect==pod.val.mem, "dbGetField(\"%s\", %d) -> " pat " == " pat, \
|
||||
pv, dbrType, expect, (Type)pod.val.mem); break;}
|
||||
testOk(expect==pod.val.mem||((expect!=expect)&&(pod.val.mem!=pod.val.mem)), \
|
||||
"dbGetField(\"%s\", DBR%s) -> " pat " == " pat, \
|
||||
pv, DBR_NAME(dbrType), expect, (Type)pod.val.mem); break;}
|
||||
|
||||
OP(DBR_CHAR, int, int8, "%d");
|
||||
OP(DBR_UCHAR, int, uInt8, "%d");
|
||||
@@ -240,12 +246,12 @@ void testdbVGetFieldEqual(const char* pv, short dbrType, va_list ap)
|
||||
OP(DBR_ULONG, unsigned int, uInt32, "%u");
|
||||
OP(DBR_INT64, long long, int64, "%lld");
|
||||
OP(DBR_UINT64, unsigned long long, uInt64, "%llu");
|
||||
OP(DBR_FLOAT, double, float32, "%e");
|
||||
OP(DBR_DOUBLE, double, float64, "%e");
|
||||
OP(DBR_ENUM, int, enum16, "%d");
|
||||
OP(DBR_FLOAT, double, float32, "%g");
|
||||
OP(DBR_DOUBLE, double, float64, "%g");
|
||||
#undef OP
|
||||
default:
|
||||
testFail("dbGetField(\"%s\", %d) -> unsupported dbf", pv, dbrType);
|
||||
testFail("dbGetField(\"%s\", DBR%s) -> unsupported dbf", pv, DBR_NAME(dbrType));
|
||||
}
|
||||
|
||||
done:
|
||||
@@ -265,7 +271,7 @@ void testdbPutArrFieldOk(const char* pv, short dbrType, unsigned long count, con
|
||||
|
||||
status = dbChannelPutField(chan, dbrType, pbuf, count);
|
||||
|
||||
testOk(status==0, "dbPutField(\"%s\", dbr=%d, count=%lu, ...) -> %ld", pv, dbrType, count, status);
|
||||
testOk(status==0, "dbPutField(\"%s\", DBR%s, count=%lu, ...) -> %ld", pv, DBR_NAME(dbrType), count, status);
|
||||
|
||||
done:
|
||||
if(chan)
|
||||
@@ -294,14 +300,14 @@ void testdbGetArrFieldEqual(const char* pv, short dbfType, long nRequest, unsign
|
||||
|
||||
status = dbChannelGetField(chan, dbfType, gbuf, NULL, &nRequest, NULL);
|
||||
if (status) {
|
||||
testFail("dbGetField(\"%s\", %d, ...) -> %#lx", pv, dbfType, status);
|
||||
testFail("dbGetField(\"%s\", DBR%s, ...) -> %#lx", pv, DBR_NAME(dbfType), status);
|
||||
|
||||
} else {
|
||||
unsigned match = nRequest==cnt;
|
||||
long n, N = nRequest < cnt ? nRequest : cnt;
|
||||
|
||||
if(!match)
|
||||
testDiag("Length mis-match. expected=%lu actual=%lu", cnt, nRequest);
|
||||
testDiag("Length mismatch. expected=%lu actual=%lu", cnt, nRequest);
|
||||
|
||||
for(n=0; n<N; n++, gbuf+=vSize, pbuf+=vSize) {
|
||||
|
||||
@@ -327,14 +333,14 @@ void testdbGetArrFieldEqual(const char* pv, short dbfType, long nRequest, unsign
|
||||
OP(DBR_ULONG, unsigned int, "%u");
|
||||
OP(DBR_INT64, long long, "%lld");
|
||||
OP(DBR_UINT64, unsigned long long, "%llu");
|
||||
OP(DBR_FLOAT, float, "%e");
|
||||
OP(DBR_DOUBLE, double, "%e");
|
||||
OP(DBR_FLOAT, float, "%g");
|
||||
OP(DBR_DOUBLE, double, "%g");
|
||||
OP(DBR_ENUM, int, "%d");
|
||||
#undef OP
|
||||
}
|
||||
}
|
||||
|
||||
testOk(match, "dbGetField(\"%s\", dbrType=%d, nRequest=%ld ...) match", pv, dbfType, nRequest);
|
||||
testOk(match, "dbGetField(\"%s\", DBR%s, nRequest=%ld ...) match", pv, DBR_NAME(dbfType), nRequest);
|
||||
}
|
||||
|
||||
done:
|
||||
@@ -428,6 +434,17 @@ void testMonitorWait(testMonitor *mon)
|
||||
}
|
||||
}
|
||||
|
||||
static void dummylabor(void* unused) {(void)unused;}
|
||||
|
||||
void testMonitorSync(testMonitor *mon)
|
||||
{
|
||||
// db_flush_extra_labor_event() only blocks if there is actual labor pending
|
||||
(void)db_add_extra_labor_event(testEvtCtx, dummylabor, NULL);
|
||||
(void)db_post_extra_labor(testEvtCtx);
|
||||
db_flush_extra_labor_event(testEvtCtx);
|
||||
(void)db_add_extra_labor_event(testEvtCtx, NULL, NULL);
|
||||
}
|
||||
|
||||
unsigned testMonitorCount(testMonitor *mon, unsigned reset)
|
||||
{
|
||||
unsigned count;
|
||||
|
||||
@@ -139,21 +139,45 @@ DBCORE_API dbCommon* testdbRecordPtr(const char* pv);
|
||||
|
||||
typedef struct testMonitor testMonitor;
|
||||
|
||||
/** Setup monitoring the named PV for changes */
|
||||
/** Setup monitoring the named PV for changes
|
||||
*
|
||||
* @param[in] pvname Requested PV name. Must be valid for dbChannelCreate().
|
||||
* @param[in] dbe_mask A bitwise or of DBE_VALUE and friends.
|
||||
* @param[in] opt Currently unused. Set to zero.
|
||||
* @returns Newly allocated testMonitor object, which caller must testMonitorDestroy()
|
||||
*
|
||||
* Calls testAbort() on failure. Will never return NULL.
|
||||
*
|
||||
* @since 3.16.0.1
|
||||
*/
|
||||
DBCORE_API testMonitor* testMonitorCreate(const char* pvname, unsigned dbe_mask, unsigned opt);
|
||||
/** Stop monitoring */
|
||||
/** Stop monitoring
|
||||
*
|
||||
* @since 3.16.0.1
|
||||
*/
|
||||
DBCORE_API void testMonitorDestroy(testMonitor*);
|
||||
/** Return immediately if it has been updated since create, last wait,
|
||||
* or reset (count w/ reset=1).
|
||||
* Otherwise, block until the value of the target PV is updated.
|
||||
*
|
||||
* @since 3.16.0.1
|
||||
*/
|
||||
DBCORE_API void testMonitorWait(testMonitor*);
|
||||
/** Return the number of monitor events which have occured since create,
|
||||
/** Synchronize with dbEvent working for subscription.
|
||||
*
|
||||
* On return, any updates previously posted for this subscriptions have been delivered.
|
||||
*
|
||||
* @since UNRELEASED
|
||||
*/
|
||||
DBCORE_API void testMonitorSync(testMonitor*);
|
||||
/** Return the number of monitor events which have occurred since create,
|
||||
* or a previous reset (called reset=1).
|
||||
* Calling w/ reset=0 only returns the count.
|
||||
* Calling w/ reset=1 resets the count to zero and ensures that the next
|
||||
* wait will block unless subsequent events occur. Returns the previous
|
||||
* count.
|
||||
*
|
||||
* @since 3.16.0.1
|
||||
*/
|
||||
DBCORE_API unsigned testMonitorCount(testMonitor*, unsigned reset);
|
||||
|
||||
|
||||
@@ -126,7 +126,7 @@ typedef struct dbRecordNode {
|
||||
struct dbRecordNode *aliasedRecnode; /* NULL unless flags|DBRN_FLAGS_ISALIAS */
|
||||
}dbRecordNode;
|
||||
|
||||
/*dbRecordAttribute is for "psuedo" fields */
|
||||
/*dbRecordAttribute is for "pseudo" fields */
|
||||
/*pdbFldDes is so that other access routines work correctly*/
|
||||
/*Until base supports char * value MUST be fixed length string*/
|
||||
typedef struct dbRecordAttribute {
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "dbStaticLib.h"
|
||||
#include "dbStaticPvt.h"
|
||||
#include "epicsExport.h"
|
||||
#include "epicsAssert.h"
|
||||
#include "link.h"
|
||||
#include "special.h"
|
||||
#include "iocInit.h"
|
||||
@@ -187,7 +188,7 @@ const char *dbOpenFile(DBBASE *pdbbase,const char *filename,FILE **fp)
|
||||
*fp = fopen(fullfilename, "r");
|
||||
if (*fp && makeDbdDepends)
|
||||
fprintf(stdout, "%s:%s \n", makeDbdDepends, fullfilename);
|
||||
free((void *)fullfilename);
|
||||
free(fullfilename);
|
||||
if (*fp) return pdbPathNode->directory;
|
||||
pdbPathNode = (dbPathNode *)ellNext(&pdbPathNode->node);
|
||||
}
|
||||
@@ -206,7 +207,7 @@ static void freeInputFileList(void)
|
||||
pinputFileNow->filename, strerror(errno));
|
||||
free((void *)pinputFileNow->filename);
|
||||
ellDelete(&inputFileList,(ELLNODE *)pinputFileNow);
|
||||
free((void *)pinputFileNow);
|
||||
free(pinputFileNow);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,6 +238,8 @@ static long dbReadCOM(DBBASE **ppdbbase,const char *filename, FILE *fp,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
errlogInit(0); /* Initialize the errSymTable */
|
||||
|
||||
if(*ppdbbase == 0) *ppdbbase = dbAllocBase();
|
||||
savedPdbbase = *ppdbbase;
|
||||
if(path && strlen(path)>0) {
|
||||
@@ -339,11 +342,11 @@ cleanup:
|
||||
}
|
||||
if(macHandle) macDeleteHandle(macHandle);
|
||||
macHandle = NULL;
|
||||
if(mac_input_buffer) free((void *)mac_input_buffer);
|
||||
if(mac_input_buffer) free(mac_input_buffer);
|
||||
mac_input_buffer = NULL;
|
||||
if(freeListPvt) freeListCleanup(freeListPvt);
|
||||
freeListPvt = NULL;
|
||||
if(my_buffer) free((void *)my_buffer);
|
||||
if(my_buffer) free(my_buffer);
|
||||
my_buffer = NULL;
|
||||
freeInputFileList();
|
||||
if(fp)
|
||||
@@ -351,14 +354,18 @@ cleanup:
|
||||
return(status);
|
||||
}
|
||||
|
||||
long dbReadDatabase(DBBASE **ppdbbase,const char *filename,
|
||||
const char *path,const char *substitutions)
|
||||
{return (dbReadCOM(ppdbbase,filename,0,path,substitutions));}
|
||||
long dbReadDatabase(DBBASE **ppdbbase, const char *filename,
|
||||
const char *path, const char *substitutions)
|
||||
{
|
||||
return dbReadCOM(ppdbbase, filename, 0, path, substitutions);
|
||||
}
|
||||
|
||||
long dbReadDatabaseFP(DBBASE **ppdbbase, FILE *fp,
|
||||
const char *path, const char *substitutions)
|
||||
{
|
||||
return dbReadCOM(ppdbbase, 0, fp, path, substitutions);
|
||||
}
|
||||
|
||||
long dbReadDatabaseFP(DBBASE **ppdbbase,FILE *fp,
|
||||
const char *path,const char *substitutions)
|
||||
{return (dbReadCOM(ppdbbase,0,fp,path,substitutions));}
|
||||
|
||||
static int db_yyinput(char *buf, int max_size)
|
||||
{
|
||||
size_t l,n;
|
||||
@@ -389,7 +396,7 @@ static int db_yyinput(char *buf, int max_size)
|
||||
pinputFileNow->filename, strerror(errno));
|
||||
free((void *)pinputFileNow->filename);
|
||||
ellDelete(&inputFileList,(ELLNODE *)pinputFileNow);
|
||||
free((void *)pinputFileNow);
|
||||
free(pinputFileNow);
|
||||
pinputFileNow = (inputFile *)ellLast(&inputFileList);
|
||||
if(!pinputFileNow) return(0);
|
||||
}
|
||||
@@ -445,7 +452,7 @@ static void dbIncludeNew(char *filename)
|
||||
fprintf(stderr, ERL_ERROR ": Can't open include file '%s'\n", filename);
|
||||
yyerror(NULL);
|
||||
free((void *)pinputFile->filename);
|
||||
free((void *)pinputFile);
|
||||
free(pinputFile);
|
||||
return;
|
||||
}
|
||||
pinputFile->fp = fp;
|
||||
@@ -705,7 +712,7 @@ static void dbRecordtypeEmpty(void)
|
||||
ptempListNode = (tempListNode *)ellFirst(&tempList);
|
||||
pdbRecordType = ptempListNode->item;
|
||||
fprintf(stderr, ERL_ERROR
|
||||
": Declaration of recordtype(%s) preceeded full definition.\n",
|
||||
": Declaration of recordtype(%s) preceded full definition.\n",
|
||||
pdbRecordType->name);
|
||||
yyerrorAbort(NULL);
|
||||
}
|
||||
@@ -1190,6 +1197,37 @@ static void dbRecordHead(char *recordType, char *name, int visible)
|
||||
dbVisibleRecord(pdbentry);
|
||||
}
|
||||
|
||||
/* For better suggestions for wrong field names
|
||||
the following array contains pairs of often
|
||||
confused fields. Thus, the number of elements
|
||||
must be even.
|
||||
For the last character, ranges like A-F are
|
||||
allowed as a shortcut. Pairs must have matching
|
||||
range size.
|
||||
If extending this map, please add only field names
|
||||
found in record types from base.
|
||||
Each array element (i.e. both sides of a pair)
|
||||
is tested against the faulty field name.
|
||||
The first match (considering ranges) where the
|
||||
other side of the pair is an existing field name
|
||||
(after adjusting for ranges) will be suggested
|
||||
as a replacement.
|
||||
If no such match is found, the suggestion falls
|
||||
back to weighted lexical similarity with existing
|
||||
field names.
|
||||
*/
|
||||
|
||||
static const char* const dbFieldConfusionMap [] = {
|
||||
"INP","OUT",
|
||||
"DOL","INP",
|
||||
"ZNAM","ZRST",
|
||||
"ONAM","ONST",
|
||||
"INPA-J","DOL0-9",
|
||||
"INPK-P","DOLA-F",
|
||||
"INP0-9","INPA-J"
|
||||
};
|
||||
STATIC_ASSERT(NELEMENTS(dbFieldConfusionMap)%2==0);
|
||||
|
||||
static void dbRecordField(char *name,char *value)
|
||||
{
|
||||
DBENTRY *pdbentry;
|
||||
@@ -1206,18 +1244,140 @@ static void dbRecordField(char *name,char *value)
|
||||
dbGetRecordTypeName(pdbentry), dbGetRecordName(pdbentry), name);
|
||||
if(dbGetRecordName(pdbentry)) {
|
||||
DBENTRY temp;
|
||||
double bestSim = -1.0;
|
||||
const dbFldDes *bestFld = NULL;
|
||||
int i;
|
||||
dbCopyEntryContents(pdbentry, &temp);
|
||||
for(status = dbFirstField(&temp, 0); !status; status = dbNextField(&temp, 0)) {
|
||||
double sim = epicsStrSimilarity(name, temp.pflddes->name);
|
||||
if(!bestFld || sim > bestSim) {
|
||||
bestSim = sim;
|
||||
for(i = 0; i < NELEMENTS(dbFieldConfusionMap); i++) {
|
||||
const char* fieldname = dbFieldConfusionMap[i];
|
||||
const char* replacement = dbFieldConfusionMap[i^1]; /* swap even with odd indices */
|
||||
const char* guess = NULL;
|
||||
char buf[8]; /* no field name is so long */
|
||||
size_t l = strlen(fieldname);
|
||||
if (l >= 3 && fieldname[l-2] == '-' &&
|
||||
strncmp(name, fieldname, l-3) == 0 &&
|
||||
name[l-3] >= fieldname[l-3] &&
|
||||
name[l-3] <= fieldname[l-1])
|
||||
{
|
||||
/* range map (like XXXA-Z) */
|
||||
size_t l2 = strlen(replacement);
|
||||
strncpy(buf, replacement, sizeof(buf)-1);
|
||||
buf[l2-3] += name[l-3] - fieldname[l-3];
|
||||
buf[l2-2] = 0;
|
||||
guess = buf;
|
||||
} else if (strcmp(name, fieldname) == 0) {
|
||||
/* simple map */
|
||||
guess = replacement;
|
||||
}
|
||||
if (guess && dbFindFieldPart(&temp, &guess) == 0) {
|
||||
/* guessed field exists */
|
||||
bestFld = temp.pflddes;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!bestFld) {
|
||||
/* no map found, use weighted lexical similarity
|
||||
the weights are a bit arbitrary */
|
||||
double bestSim = -1.0;
|
||||
char quote = 0;
|
||||
if (*value == '"' || *value == '\'')
|
||||
quote = *value++;
|
||||
for (status = dbFirstField(&temp, 0); !status; status = dbNextField(&temp, 0)) {
|
||||
if (temp.pflddes->special == SPC_NOMOD ||
|
||||
temp.pflddes->special == SPC_DBADDR) /* cannot be configured */
|
||||
continue;
|
||||
double sim = epicsStrSimilarity(name, temp.pflddes->name);
|
||||
if (!temp.pflddes->promptgroup)
|
||||
sim *= 0.5; /* no prompt: unlikely */
|
||||
if (temp.pflddes->interest)
|
||||
sim *= 1.0 - 0.1 * temp.pflddes->interest; /* 10% less likely per interest level */
|
||||
if (sim == 0)
|
||||
continue;
|
||||
if (*value != quote) {
|
||||
/* value given, check match to field type */
|
||||
long status = 0;
|
||||
char* end = "e;
|
||||
|
||||
switch (temp.pflddes->field_type) {
|
||||
epicsAny dummy;
|
||||
case DBF_CHAR:
|
||||
status = epicsParseInt8(value, &dummy.int8, 0, &end);
|
||||
break;
|
||||
case DBF_UCHAR:
|
||||
status = epicsParseUInt8(value, &dummy.uInt8, 0, &end);
|
||||
break;
|
||||
case DBF_SHORT:
|
||||
status = epicsParseInt16(value, &dummy.int16, 0, &end);
|
||||
break;
|
||||
case DBF_USHORT:
|
||||
case DBF_ENUM:
|
||||
status = epicsParseUInt16(value, &dummy.uInt16, 0, &end);
|
||||
break;
|
||||
case DBF_LONG:
|
||||
status = epicsParseInt32(value, &dummy.int32, 0, &end);
|
||||
break;
|
||||
case DBF_ULONG:
|
||||
status = epicsParseUInt32(value, &dummy.uInt32, 0, &end);
|
||||
break;
|
||||
case DBF_INT64:
|
||||
status = epicsParseInt64(value, &dummy.int64, 0, &end);
|
||||
break;
|
||||
case DBF_UINT64:
|
||||
status = epicsParseUInt64(value, &dummy.uInt64, 0, &end);
|
||||
break;
|
||||
case DBF_FLOAT:
|
||||
status = epicsParseFloat(value, &dummy.float32, &end);
|
||||
break;
|
||||
case DBF_DOUBLE:
|
||||
status = epicsParseDouble(value, &dummy.float64, &end);
|
||||
break;
|
||||
case DBF_MENU:
|
||||
case DBF_DEVICE: {
|
||||
char** choices;
|
||||
int nChoice;
|
||||
int choice;
|
||||
|
||||
if (temp.pflddes->field_type == DBF_MENU) {
|
||||
dbMenu* menu = (dbMenu*)temp.pflddes->ftPvt;
|
||||
choices = menu->papChoiceValue;
|
||||
nChoice = menu->nChoice;
|
||||
} else {
|
||||
dbDeviceMenu* menu = (dbDeviceMenu*)temp.pflddes->ftPvt;
|
||||
choices = menu->papChoice;
|
||||
nChoice = menu->nChoice;
|
||||
}
|
||||
status = epicsParseUInt16(value, &dummy.uInt16, 0, &end);
|
||||
if (!status && *end == quote && dummy.uInt16 < nChoice) {
|
||||
if (temp.pflddes->field_type == DBF_DEVICE)
|
||||
sim *= 0.5; /* numeric device type index is uncommon */
|
||||
break;
|
||||
}
|
||||
for (choice = 0; choice < nChoice; choice++) {
|
||||
size_t len = strlen(choices[choice]);
|
||||
end = value + len;
|
||||
if (strncmp(value, choices[choice], len) == 0 && *end == quote) {
|
||||
sim *= 1.5; /* boost for matching choice string */
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (choice == nChoice)
|
||||
status = S_stdlib_noConversion;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (status || *end != quote)
|
||||
sim *= 0.1; /* value type does not match field type: unlikely */
|
||||
}
|
||||
if (sim > bestSim) {
|
||||
bestSim = sim;
|
||||
bestFld = temp.pflddes;
|
||||
}
|
||||
}
|
||||
}
|
||||
dbFinishEntry(&temp);
|
||||
if(bestSim>0.0) {
|
||||
if (bestFld) {
|
||||
fprintf(stderr, " Did you mean \"%s\"?", bestFld->name);
|
||||
if(bestFld->prompt)
|
||||
fprintf(stderr, " (%s)", bestFld->prompt);
|
||||
|
||||
@@ -50,7 +50,7 @@ static const iocshArg dbDumpMenuArg1 = { "menuName",iocshArgString};
|
||||
static const iocshArg * const dbDumpMenuArgs[] = {
|
||||
&argPdbbase, &dbDumpMenuArg1};
|
||||
static const iocshFuncDef dbDumpMenuFuncDef = {"dbDumpMenu",2,dbDumpMenuArgs,
|
||||
"Dump information about the available menuNames and choices defined withing each menuName.\n"
|
||||
"Dump information about the available menuNames and choices defined within each menuName.\n"
|
||||
"Example: dbDumpMenu pdbbase menuAlarmStat \n"
|
||||
"If last argument(s) are missing, dump all menuNames information in the database.\n"};
|
||||
static void dbDumpMenuCallFunc(const iocshArgBuf *args)
|
||||
|
||||
@@ -109,9 +109,9 @@ void dbFreeLinkContents(struct link *plink)
|
||||
char *parm = NULL;
|
||||
|
||||
switch(plink->type) {
|
||||
case CONSTANT: free((void *)plink->value.constantStr); break;
|
||||
case MACRO_LINK: free((void *)plink->value.macro_link.macroStr); break;
|
||||
case PV_LINK: free((void *)plink->value.pv_link.pvname); break;
|
||||
case CONSTANT: free(plink->value.constantStr); break;
|
||||
case MACRO_LINK: free(plink->value.macro_link.macroStr); break;
|
||||
case PV_LINK: free(plink->value.pv_link.pvname); break;
|
||||
case JSON_LINK:
|
||||
dbJLinkFree(plink->value.json.jlink);
|
||||
parm = plink->value.json.string;
|
||||
@@ -128,7 +128,7 @@ void dbFreeLinkContents(struct link *plink)
|
||||
default:
|
||||
epicsPrintf("dbFreeLink called but link type %d unknown\n", plink->type);
|
||||
}
|
||||
if(parm && (parm != pNullString)) free((void *)parm);
|
||||
if(parm && (parm != pNullString)) free(parm);
|
||||
if(plink->text) free(plink->text);
|
||||
plink->lset = NULL;
|
||||
plink->text = NULL;
|
||||
@@ -145,10 +145,10 @@ void dbFreePath(DBBASE *pdbbase)
|
||||
if(!ppathList) return;
|
||||
while((pdbPathNode = (dbPathNode *)ellFirst(ppathList))) {
|
||||
ellDelete(ppathList,&pdbPathNode->node);
|
||||
free((void *)pdbPathNode->directory);
|
||||
free((void *)pdbPathNode);
|
||||
free(pdbPathNode->directory);
|
||||
free(pdbPathNode);
|
||||
}
|
||||
free((void *)ppathList);
|
||||
free(ppathList);
|
||||
pdbbase->pathPvt = 0;
|
||||
return;
|
||||
}
|
||||
@@ -346,8 +346,8 @@ dbDeviceMenu *dbGetDeviceMenu(DBENTRY *pdbentry)
|
||||
pdbDeviceMenu = (dbDeviceMenu *)pflddes->ftPvt;
|
||||
if(pdbDeviceMenu->nChoice == ellCount(&precordType->devList))
|
||||
return(pdbDeviceMenu);
|
||||
free((void *)pdbDeviceMenu->papChoice);
|
||||
free((void *)pdbDeviceMenu);
|
||||
free(pdbDeviceMenu->papChoice);
|
||||
free(pdbDeviceMenu);
|
||||
pflddes->ftPvt = NULL;
|
||||
}
|
||||
nChoice = ellCount(&precordType->devList);
|
||||
@@ -383,7 +383,7 @@ void dbCatString(char **string,int *stringLength,char *src,char *separator)
|
||||
newString = dbCalloc(size,sizeof(char));
|
||||
if(*string) {
|
||||
strcpy(newString,*string);
|
||||
free((void *)(*string));
|
||||
free(*string);
|
||||
}
|
||||
*string = newString;
|
||||
}
|
||||
@@ -463,35 +463,35 @@ void dbFreeBase(dbBase *pdbbase)
|
||||
while(pdbRecordType) {
|
||||
for(i=0; i<pdbRecordType->no_fields; i++) {
|
||||
pdbFldDes = pdbRecordType->papFldDes[i];
|
||||
free((void *)pdbFldDes->prompt);
|
||||
free((void *)pdbFldDes->name);
|
||||
free((void *)pdbFldDes->extra);
|
||||
free((void *)pdbFldDes->initial);
|
||||
free(pdbFldDes->prompt);
|
||||
free(pdbFldDes->name);
|
||||
free(pdbFldDes->extra);
|
||||
free(pdbFldDes->initial);
|
||||
if(pdbFldDes->field_type==DBF_DEVICE && pdbFldDes->ftPvt) {
|
||||
dbDeviceMenu *pdbDeviceMenu;
|
||||
|
||||
pdbDeviceMenu = (dbDeviceMenu *)pdbFldDes->ftPvt;
|
||||
free((void *)pdbDeviceMenu->papChoice);
|
||||
free((void *)pdbDeviceMenu);
|
||||
free(pdbDeviceMenu->papChoice);
|
||||
free(pdbDeviceMenu);
|
||||
pdbFldDes->ftPvt=0;
|
||||
}
|
||||
free((void *)pdbFldDes);
|
||||
free(pdbFldDes);
|
||||
}
|
||||
pdevSup = (devSup *)ellFirst(&pdbRecordType->devList);
|
||||
while(pdevSup) {
|
||||
pdevSupNext = (devSup *)ellNext(&pdevSup->node);
|
||||
ellDelete(&pdbRecordType->devList,&pdevSup->node);
|
||||
free((void *)pdevSup->name);
|
||||
free((void *)pdevSup->choice);
|
||||
free((void *)pdevSup);
|
||||
free(pdevSup->name);
|
||||
free(pdevSup->choice);
|
||||
free(pdevSup);
|
||||
pdevSup = pdevSupNext;
|
||||
}
|
||||
ptext = (dbText *)ellFirst(&pdbRecordType->cdefList);
|
||||
while(ptext) {
|
||||
ptextNext = (dbText *)ellNext(&ptext->node);
|
||||
ellDelete(&pdbRecordType->cdefList,&ptext->node);
|
||||
free((void *)ptext->text);
|
||||
free((void *)ptext);
|
||||
free(ptext->text);
|
||||
free(ptext);
|
||||
ptext = ptextNext;
|
||||
}
|
||||
pAttribute =
|
||||
@@ -499,20 +499,20 @@ void dbFreeBase(dbBase *pdbbase)
|
||||
while(pAttribute) {
|
||||
pAttributeNext = (dbRecordAttribute *)ellNext(&pAttribute->node);
|
||||
ellDelete(&pdbRecordType->attributeList,&pAttribute->node);
|
||||
free((void *)pAttribute->name);
|
||||
free((void *)pAttribute->pdbFldDes);
|
||||
free(pAttribute->name);
|
||||
free(pAttribute->pdbFldDes);
|
||||
free(pAttribute);
|
||||
pAttribute = pAttributeNext;
|
||||
}
|
||||
pdbRecordTypeNext = (dbRecordType *)ellNext(&pdbRecordType->node);
|
||||
gphDelete(pdbbase->pgpHash,pdbRecordType->name,&pdbbase->recordTypeList);
|
||||
ellDelete(&pdbbase->recordTypeList,&pdbRecordType->node);
|
||||
free((void *)pdbRecordType->name);
|
||||
free((void *)pdbRecordType->link_ind);
|
||||
free((void *)pdbRecordType->papsortFldName);
|
||||
free((void *)pdbRecordType->sortFldInd);
|
||||
free((void *)pdbRecordType->papFldDes);
|
||||
free((void *)pdbRecordType);
|
||||
free(pdbRecordType->name);
|
||||
free(pdbRecordType->link_ind);
|
||||
free(pdbRecordType->papsortFldName);
|
||||
free(pdbRecordType->sortFldInd);
|
||||
free(pdbRecordType->papFldDes);
|
||||
free(pdbRecordType);
|
||||
pdbRecordType = pdbRecordTypeNext;
|
||||
}
|
||||
pdbMenu = (dbMenu *)ellFirst(&pdbbase->menuList);
|
||||
@@ -521,21 +521,21 @@ void dbFreeBase(dbBase *pdbbase)
|
||||
gphDelete(pdbbase->pgpHash,pdbMenu->name,&pdbbase->menuList);
|
||||
ellDelete(&pdbbase->menuList,&pdbMenu->node);
|
||||
for(i=0; i< pdbMenu->nChoice; i++) {
|
||||
free((void *)pdbMenu->papChoiceName[i]);
|
||||
free((void *)pdbMenu->papChoiceValue[i]);
|
||||
free(pdbMenu->papChoiceName[i]);
|
||||
free(pdbMenu->papChoiceValue[i]);
|
||||
}
|
||||
free((void *)pdbMenu->papChoiceName);
|
||||
free((void *)pdbMenu->papChoiceValue);
|
||||
free((void *)pdbMenu ->name);
|
||||
free((void *)pdbMenu);
|
||||
free(pdbMenu->papChoiceName);
|
||||
free(pdbMenu->papChoiceValue);
|
||||
free(pdbMenu ->name);
|
||||
free(pdbMenu);
|
||||
pdbMenu = pdbMenuNext;
|
||||
}
|
||||
pdrvSup = (drvSup *)ellFirst(&pdbbase->drvList);
|
||||
while(pdrvSup) {
|
||||
pdrvSupNext = (drvSup *)ellNext(&pdrvSup->node);
|
||||
ellDelete(&pdbbase->drvList,&pdrvSup->node);
|
||||
free((void *)pdrvSup->name);
|
||||
free((void *)pdrvSup);
|
||||
free(pdrvSup->name);
|
||||
free(pdrvSup);
|
||||
pdrvSup = pdrvSupNext;
|
||||
}
|
||||
while ((plinkSup = (linkSup *) ellGet(&pdbbase->linkList))) {
|
||||
@@ -547,25 +547,25 @@ void dbFreeBase(dbBase *pdbbase)
|
||||
while(ptext) {
|
||||
ptextNext = (dbText *)ellNext(&ptext->node);
|
||||
ellDelete(&pdbbase->registrarList,&ptext->node);
|
||||
free((void *)ptext->text);
|
||||
free((void *)ptext);
|
||||
free(ptext->text);
|
||||
free(ptext);
|
||||
ptext = ptextNext;
|
||||
}
|
||||
ptext = (dbText *)ellFirst(&pdbbase->functionList);
|
||||
while(ptext) {
|
||||
ptextNext = (dbText *)ellNext(&ptext->node);
|
||||
ellDelete(&pdbbase->functionList,&ptext->node);
|
||||
free((void *)ptext->text);
|
||||
free((void *)ptext);
|
||||
free(ptext->text);
|
||||
free(ptext);
|
||||
ptext = ptextNext;
|
||||
}
|
||||
pvar = (dbVariableDef *)ellFirst(&pdbbase->variableList);
|
||||
while(pvar) {
|
||||
pvarNext = (dbVariableDef *)ellNext(&pvar->node);
|
||||
ellDelete(&pdbbase->variableList,&pvar->node);
|
||||
free((void *)pvar->name);
|
||||
free((void *)pvar->type);
|
||||
free((void *)pvar);
|
||||
free(pvar->name);
|
||||
free(pvar->type);
|
||||
free(pvar);
|
||||
pvar = pvarNext;
|
||||
}
|
||||
pbrkTable = (brkTable *)ellFirst(&pdbbase->bptList);
|
||||
@@ -574,8 +574,8 @@ void dbFreeBase(dbBase *pdbbase)
|
||||
gphDelete(pdbbase->pgpHash,pbrkTable->name,&pdbbase->bptList);
|
||||
ellDelete(&pdbbase->bptList,&pbrkTable->node);
|
||||
free(pbrkTable->name);
|
||||
free((void *)pbrkTable->paBrkInt);
|
||||
free((void *)pbrkTable);
|
||||
free(pbrkTable->paBrkInt);
|
||||
free(pbrkTable);
|
||||
pbrkTable = pbrkTableNext;
|
||||
}
|
||||
pfilt = (chFilterPlugin *)ellFirst(&pdbbase->filterList);
|
||||
@@ -593,13 +593,13 @@ void dbFreeBase(dbBase *pdbbase)
|
||||
gphDelete(pdbbase->pgpHash, pguiGroup->name, &pdbbase->guiGroupList);
|
||||
ellDelete(&pdbbase->guiGroupList, &pguiGroup->node);
|
||||
free(pguiGroup->name);
|
||||
free((void *)pguiGroup);
|
||||
free(pguiGroup);
|
||||
pguiGroup = pguiGroupNext;
|
||||
}
|
||||
gphFreeMem(pdbbase->pgpHash);
|
||||
dbPvdFreeMem(pdbbase);
|
||||
dbFreePath(pdbbase);
|
||||
free((void *)pdbbase);
|
||||
free(pdbbase);
|
||||
pdbbase = NULL;
|
||||
return;
|
||||
}
|
||||
@@ -619,20 +619,20 @@ void dbFreeEntry(DBENTRY *pdbentry)
|
||||
if (!pdbentry)
|
||||
return;
|
||||
if (pdbentry->message)
|
||||
free((void *)pdbentry->message);
|
||||
free(pdbentry->message);
|
||||
dbmfFree(pdbentry);
|
||||
}
|
||||
|
||||
void dbInitEntry(dbBase *pdbbase,DBENTRY *pdbentry)
|
||||
{
|
||||
memset((char *)pdbentry,'\0',sizeof(DBENTRY));
|
||||
memset(pdbentry, '\0', sizeof(DBENTRY));
|
||||
pdbentry->pdbbase = pdbbase;
|
||||
}
|
||||
|
||||
void dbFinishEntry(DBENTRY *pdbentry)
|
||||
{
|
||||
if(pdbentry->message) {
|
||||
free((void *)pdbentry->message);
|
||||
free(pdbentry->message);
|
||||
pdbentry->message = NULL;
|
||||
}
|
||||
}
|
||||
@@ -675,7 +675,7 @@ long dbAddPath(DBBASE *pdbbase,const char *path)
|
||||
if(!ppathList) {
|
||||
ppathList = dbCalloc(1,sizeof(ELLLIST));
|
||||
ellInit(ppathList);
|
||||
pdbbase->pathPvt = (void *)ppathList;
|
||||
pdbbase->pathPvt = ppathList;
|
||||
}
|
||||
if (!path) return(0); /* Empty path strings are ignored */
|
||||
/* care is taken to properly deal with white space
|
||||
@@ -743,8 +743,8 @@ static long dbAddOnePath (DBBASE *pdbbase, const char *path, unsigned length)
|
||||
ppathList = (ELLLIST *)pdbbase->pathPvt;
|
||||
|
||||
pdbPathNode = (dbPathNode *)dbCalloc(1, sizeof(dbPathNode));
|
||||
pdbPathNode->directory = (char *)dbCalloc(length+1, sizeof(char));
|
||||
strncpy(pdbPathNode->directory, path, length);
|
||||
pdbPathNode->directory = (char *)dbMalloc(length+1);
|
||||
strncpy(pdbPathNode->directory, path, length+1);
|
||||
pdbPathNode->directory[length] = '\0';
|
||||
ellAdd(ppathList, &pdbPathNode->node);
|
||||
return 0;
|
||||
@@ -1886,7 +1886,7 @@ char * dbGetString(DBENTRY *pdbentry)
|
||||
switch (pflddes->field_type) {
|
||||
case DBF_STRING:
|
||||
/* Protect against a missing nil-terminator */
|
||||
dbMsgNCpy(pdbentry, (char *)pfield, pflddes->size);
|
||||
dbMsgNCpy(pdbentry, pfield, pflddes->size);
|
||||
break;
|
||||
case DBF_CHAR:
|
||||
case DBF_UCHAR:
|
||||
@@ -2212,7 +2212,7 @@ long dbInitRecordLinks(dbRecordType *rtyp, struct dbCommon *prec)
|
||||
if(!plink->text)
|
||||
continue;
|
||||
|
||||
if(dbParseLink(plink->text, pflddes->field_type, &link_info)!=0) {
|
||||
if(dbParseLink(plink->text, pflddes->field_type, &link_info, prec->name, pflddes->name)!=0) {
|
||||
/* This was already parsed once when ->text was set.
|
||||
* Any syntax error messages were printed at that time.
|
||||
*/
|
||||
@@ -2241,7 +2241,7 @@ void dbFreeLinkInfo(dbLinkInfo *pinfo)
|
||||
pinfo->target = NULL;
|
||||
}
|
||||
|
||||
long dbParseLink(const char *str, short ftype, dbLinkInfo *pinfo)
|
||||
long dbParseLink(const char *str, short ftype, dbLinkInfo *pinfo, const char *recname, const char *fieldname)
|
||||
{
|
||||
char *pstr;
|
||||
size_t len;
|
||||
@@ -2378,7 +2378,13 @@ long dbParseLink(const char *str, short ftype, dbLinkInfo *pinfo)
|
||||
/* filter modifiers based on link type */
|
||||
switch(ftype) {
|
||||
case DBF_INLINK: /* accept all */ break;
|
||||
case DBF_OUTLINK: pinfo->modifiers &= ~pvlOptCPP; break;
|
||||
case DBF_OUTLINK:
|
||||
if(pinfo->modifiers & (pvlOptCPP|pvlOptCP)){
|
||||
errlogPrintf(ERL_WARNING ": Discarding CP/CPP modifier in CA output link from %s.%s to %s.\n",
|
||||
recname, fieldname, pinfo->target);
|
||||
}
|
||||
pinfo->modifiers &= ~(pvlOptCPP|pvlOptCP);
|
||||
break;
|
||||
case DBF_FWDLINK: pinfo->modifiers &= pvlOptCA; break;
|
||||
}
|
||||
}
|
||||
@@ -2579,7 +2585,7 @@ long dbPutString(DBENTRY *pdbentry,const char *pstring)
|
||||
case DBF_STRING:
|
||||
if(!pfield) return(S_dbLib_fieldNotFound);
|
||||
if(strlen(pstring) >= (size_t)pflddes->size) return S_dbLib_strLen;
|
||||
strncpy((char *)pfield, pstring, pflddes->size-1);
|
||||
strncpy(pfield, pstring, pflddes->size-1);
|
||||
((char *)pfield)[pflddes->size-1] = 0;
|
||||
|
||||
if((pflddes->special == SPC_CALC) && !stringHasMacro) {
|
||||
@@ -2616,7 +2622,7 @@ long dbPutString(DBENTRY *pdbentry,const char *pstring)
|
||||
dbLinkInfo link_info;
|
||||
DBLINK *plink = (DBLINK *)pfield;
|
||||
|
||||
status = dbParseLink(pstring, pflddes->field_type, &link_info);
|
||||
status = dbParseLink(pstring, pflddes->field_type, &link_info, dbGetRecordName(pdbentry), dbGetFieldName(pdbentry));
|
||||
if (status) break;
|
||||
|
||||
if (plink->type==CONSTANT && plink->value.constantStr==NULL) {
|
||||
@@ -3045,7 +3051,7 @@ brkTable * dbFindBrkTable(dbBase *pdbbase,const char *name)
|
||||
{
|
||||
GPHENTRY *pgph;
|
||||
|
||||
pgph = gphFind(pdbbase->pgpHash,name,(void *)&pdbbase->bptList);
|
||||
pgph = gphFind(pdbbase->pgpHash, name, &pdbbase->bptList);
|
||||
if(!pgph) return(NULL);
|
||||
return((brkTable *)pgph->userPvt);
|
||||
}
|
||||
@@ -3078,7 +3084,7 @@ dbMenu * dbFindMenu(dbBase *pdbbase,const char *name)
|
||||
{
|
||||
GPHENTRY *pgph;
|
||||
|
||||
pgph = gphFind(pdbbase->pgpHash,name,(void *)&pdbbase->menuList);
|
||||
pgph = gphFind(pdbbase->pgpHash, name, &pdbbase->menuList);
|
||||
if(!pgph) return(NULL);
|
||||
return((dbMenu *)pgph->userPvt);
|
||||
}
|
||||
@@ -3330,7 +3336,7 @@ void dbDumpRecordType(DBBASE *pdbbase,const char *recordTypeName)
|
||||
printf("indvalFlddes %d name %s\n",pdbRecordType->indvalFlddes,
|
||||
pdbRecordType->pvalFldDes->name);
|
||||
printf("rset * %p rec_size %d\n",
|
||||
(void *)pdbRecordType->prset,pdbRecordType->rec_size);
|
||||
pdbRecordType->prset,pdbRecordType->rec_size);
|
||||
if(recordTypeName) break;
|
||||
}
|
||||
}
|
||||
@@ -3447,7 +3453,7 @@ void dbDumpDevice(DBBASE *pdbbase,const char *recordTypeName)
|
||||
printf(" device name: %s\n",pdevSup->name);
|
||||
printf("\tchoice: %s\n",pdevSup->choice);
|
||||
printf("\tlink_type: %d\n",pdevSup->link_type);
|
||||
printf("\tpdset: %p\n",(void *)pdevSup->pdset);
|
||||
printf("\tpdset: %p\n",pdevSup->pdset);
|
||||
if (pdevSup->pdset) {
|
||||
static const char *names[] = {
|
||||
" - report()",
|
||||
@@ -3462,15 +3468,15 @@ void dbDumpDevice(DBBASE *pdbbase,const char *recordTypeName)
|
||||
for (i = 0; i < n; ++i, ++pfunc) {
|
||||
const char *name = (i < NELEMENTS(names)) ? names[i] : "";
|
||||
|
||||
printf("\t func %d: %p%s\n", i, (void *)*pfunc, name);
|
||||
printf("\t func %d: %p%s\n", i, *pfunc, name);
|
||||
}
|
||||
}
|
||||
printf("\tpdsxt: %p\n",(void *)pdevSup->pdsxt);
|
||||
printf("\tpdsxt: %p\n", pdevSup->pdsxt);
|
||||
if (pdevSup->pdsxt) {
|
||||
printf("\t add_record: %p\n",
|
||||
(void *)pdevSup->pdsxt->add_record);
|
||||
pdevSup->pdsxt->add_record);
|
||||
printf("\t del_record: %p\n",
|
||||
(void *)pdevSup->pdsxt->del_record);
|
||||
pdevSup->pdsxt->del_record);
|
||||
}
|
||||
}
|
||||
if(recordTypeName) break;
|
||||
@@ -3600,7 +3606,7 @@ void dbReportDeviceConfig(dbBase *pdbbase, FILE *report)
|
||||
if (plink->text) { /* Not yet parsed */
|
||||
dbLinkInfo linfo;
|
||||
|
||||
if (dbParseLink(plink->text, pdbentry->pflddes->field_type, &linfo))
|
||||
if (dbParseLink(plink->text, pdbentry->pflddes->field_type, &linfo, dbGetRecordName(pdbentry), dbGetFieldName(pdbentry)))
|
||||
continue;
|
||||
|
||||
linkType = linfo.ltype;
|
||||
|
||||
@@ -74,7 +74,7 @@ long dbInitRecordLinks(dbRecordType *rtyp, struct dbCommon *prec);
|
||||
/* Parse link string. no record locks needed.
|
||||
* on success caller must free pinfo->target
|
||||
*/
|
||||
DBCORE_API long dbParseLink(const char *str, short ftype, dbLinkInfo *pinfo);
|
||||
DBCORE_API long dbParseLink(const char *str, short ftype, dbLinkInfo *pinfo, const char *recordname, const char *fieldname);
|
||||
/* Check if link type allow the parsed link value pinfo
|
||||
* to be assigned to the given link.
|
||||
* Record containing plink must be locked.
|
||||
|
||||
@@ -122,7 +122,7 @@ long dbAllocRecord(DBENTRY *pdbentry,const char *precordName)
|
||||
pflddes = pdbRecordType->papFldDes[i];
|
||||
if(!pflddes) continue;
|
||||
pfield = (char*)precord + pflddes->offset;
|
||||
pdbentry->pfield = (void *)pfield;
|
||||
pdbentry->pfield = pfield;
|
||||
pdbentry->pflddes = pflddes;
|
||||
pdbentry->indfield = i;
|
||||
switch(pflddes->field_type) {
|
||||
|
||||
@@ -26,7 +26,7 @@ static const iocshFuncDef dbLoadTemplateFuncDef = {
|
||||
"for each template in the substitution file, and load them using 'dbLoadRecords'.\n\n"
|
||||
"The second argument provides extra variables to substitute in the\n"
|
||||
"template files (not the substitution file). The third argument provides\n"
|
||||
"a list of paths to search through for the subsitution and template files.\n\n"
|
||||
"a list of paths to search through for the substitution and template files.\n\n"
|
||||
"See 'help dbLoadRecords' for more information.\n\n"
|
||||
"Example: dbLoadTemplate db/my.substitutions 'user=myself,host=myhost' 'path/to/subst:path2/to2/subst2'\n",
|
||||
};
|
||||
|
||||
@@ -49,7 +49,7 @@ discouraged.
|
||||
:::
|
||||
|
||||
::: {option} -o <file>
|
||||
Output will be written to the specifed \<file\> rather than to the
|
||||
Output will be written to the specified \<file\> rather than to the
|
||||
standard output.
|
||||
:::
|
||||
|
||||
@@ -166,7 +166,7 @@ expanded properly.
|
||||
However neither back-slash characters nor quotes of either variety are
|
||||
removed when generating the output file, so depending on what is being
|
||||
output the single quote behaviour may not be useful and may even be a
|
||||
hinderance. It cannot be disabled in the current version of msi.
|
||||
hindrance. It cannot be disabled in the current version of msi.
|
||||
|
||||
|
||||
### Template file commands
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user