Merge branch '7.0' into PSI-7.0
This commit is contained in:
2
.ci
2
.ci
Submodule .ci updated: 130e88b709...0e93b70855
14
.gitattributes
vendored
14
.gitattributes
vendored
@ -1,9 +1,11 @@
|
||||
.ci/ export-ignore
|
||||
.tools/ export-ignore
|
||||
.github/ export-ignore
|
||||
.appveyor/ export-ignore
|
||||
.appveyor.yml export-ignore
|
||||
README export-subst
|
||||
.appveyor.yml export-ignore
|
||||
.appveyor/ export-ignore
|
||||
.ci/ export-ignore
|
||||
.github/ export-ignore
|
||||
.gitmodules export-ignore
|
||||
.readthedocs.yml export-ignore
|
||||
.tools/ export-ignore
|
||||
README export-subst
|
||||
|
||||
#Which files need CRLF handling
|
||||
# default to automatic
|
||||
|
2
.github/workflows/check-editorconfig.yml
vendored
2
.github/workflows/check-editorconfig.yml
vendored
@ -8,6 +8,6 @@ jobs:
|
||||
editorconfig:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: EditorConfig-Action
|
||||
uses: greut/eclint-action@v0
|
||||
|
12
.github/workflows/ci-scripts-build.yml
vendored
12
.github/workflows/ci-scripts-build.yml
vendored
@ -237,10 +237,10 @@ jobs:
|
||||
matrix:
|
||||
# Job names also name artifacts, character limitations apply
|
||||
include:
|
||||
- name: "CentOS-7"
|
||||
image: centos:7
|
||||
cmp: gcc
|
||||
configuration: default
|
||||
#- name: "CentOS-7"
|
||||
# image: centos:7
|
||||
# cmp: gcc
|
||||
# configuration: default
|
||||
|
||||
- name: "Fedora-33"
|
||||
image: fedora:33
|
||||
@ -284,6 +284,10 @@ jobs:
|
||||
submodules: true
|
||||
- name: Automatic core dumper analysis
|
||||
uses: mdavidsaver/ci-core-dumper@master
|
||||
if: matrix.image!='centos:7'
|
||||
- name: Automatic core dumper analysis
|
||||
uses: mdavidsaver/ci-core-dumper@node16
|
||||
if: matrix.image=='centos:7'
|
||||
- name: Prepare and compile dependencies
|
||||
run: python .ci/cue.py prepare
|
||||
- name: Build main module
|
||||
|
@ -136,19 +136,20 @@ sed -i -e 's|^\./||' "$TDIR"/list.1
|
||||
|
||||
# Exclude files
|
||||
sed \
|
||||
-e '/\/\.ci\//d' \
|
||||
-e '/\/\.appveyor\.yml$/d' \
|
||||
-e '/\/\.appveyor\//d' \
|
||||
-e '/\/\.ci-local\//d' \
|
||||
-e '/\/\.tools\//d' \
|
||||
-e '/\/jenkins\//d' \
|
||||
-e '/\/\.ci\//d' \
|
||||
-e '/\/\.cproject$/d' \
|
||||
-e '/\/\.github\//d' \
|
||||
-e '/\/\.gitmodules$/d' \
|
||||
-e '/\/\.hgtags$/d' \
|
||||
-e '/\/\.cproject$/d' \
|
||||
-e '/\/\.project$/d' \
|
||||
-e '/\/\.lgtm\.yml$/d' \
|
||||
-e '/\/\.travis\.yml$/d' \
|
||||
-e '/\/\.appveyor\.yml$/d' \
|
||||
-e '/\/\.project$/d' \
|
||||
-e '/\/\.readthedocs\.yml$/d' \
|
||||
-e '/\/\.tools\//d' \
|
||||
-e '/\/\.travis\.yml$/d' \
|
||||
-e '/\/jenkins\//d' \
|
||||
"$TDIR"/list.1 > "$TDIR"/list.2
|
||||
|
||||
if ! diff -U 0 "$TDIR"/list.1 "$TDIR"/list.2
|
||||
|
@ -27,16 +27,16 @@ RANLIB = $(GNU_BIN)/$(CMPLR_PREFIX)ranlib$(CMPLR_SUFFIX)
|
||||
ASAN_FLAGS_YES = -fsanitize=address
|
||||
ASAN_LDFLAGS_YES = $(ASAN_FLAGS_YES)
|
||||
|
||||
# It makes sense to include debugging symbols even in optimized builds
|
||||
# in case you want to attach gdb to the process or examine a core-dump.
|
||||
# This does cost disk space, but not memory as debug symbols are not
|
||||
# loaded into RAM when the binary is loaded.
|
||||
PROF_CFLAGS_YES = -p
|
||||
GPROF_CFLAGS_YES = -pg
|
||||
CODE_CFLAGS = $(PROF_CFLAGS_$(PROFILE)) $(GPROF_CFLAGS_$(GPROF))
|
||||
CODE_CFLAGS += $(ASAN_FLAGS_$(ENABLE_ASAN))
|
||||
WARN_CFLAGS_YES = -Wall -Werror-implicit-function-declaration
|
||||
WARN_CFLAGS_NO = -w
|
||||
# It makes sense to include debugging symbols even in optimized builds
|
||||
# in case you want to attach gdb to the process or examine a core-dump.
|
||||
# This does cost disk space, but not memory as debug symbols are not
|
||||
# loaded into RAM when the binary is loaded.
|
||||
OPT_CFLAGS_YES = -O3 -g
|
||||
OPT_CFLAGS_NO = -g
|
||||
|
||||
|
@ -52,7 +52,7 @@ EPICS_MODIFICATION = 8
|
||||
|
||||
# EPICS_PATCH_LEVEL must be a number (win32 resource file requirement)
|
||||
# Not included in the official EPICS version number if zero
|
||||
EPICS_PATCH_LEVEL = 1
|
||||
EPICS_PATCH_LEVEL = 2
|
||||
|
||||
# Immediately after an official release the EPICS_PATCH_LEVEL is incremented
|
||||
# and the -DEV suffix is added (similar to the Maven -SNAPSHOT versions)
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
EPICS_CA_MAJOR_VERSION = 4
|
||||
EPICS_CA_MINOR_VERSION = 14
|
||||
EPICS_CA_MAINTENANCE_VERSION = 4
|
||||
EPICS_CA_MAINTENANCE_VERSION = 5
|
||||
|
||||
# Development flag, set to zero for release versions
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
EPICS_DATABASE_MAJOR_VERSION = 3
|
||||
EPICS_DATABASE_MINOR_VERSION = 23
|
||||
EPICS_DATABASE_MAINTENANCE_VERSION = 1
|
||||
EPICS_DATABASE_MAINTENANCE_VERSION = 2
|
||||
|
||||
# Development flag, set to zero for release versions
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
EPICS_LIBCOM_MAJOR_VERSION = 3
|
||||
EPICS_LIBCOM_MINOR_VERSION = 23
|
||||
EPICS_LIBCOM_MAINTENANCE_VERSION = 1
|
||||
EPICS_LIBCOM_MAINTENANCE_VERSION = 2
|
||||
|
||||
# Development flag, set to zero for release versions
|
||||
|
||||
|
@ -34,5 +34,9 @@ CFG += TOOLCHAIN.$(EPICS_HOST_ARCH).$(T_A)
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
|
||||
ifeq ($(GNU),YES)
|
||||
# Pass compiler flags to preprocessor to enable _FORTIFY_SOURCE
|
||||
TOOLCHAIN.$(EPICS_HOST_ARCH).$(T_A): CPPFLAGS += $(CFLAGS)
|
||||
endif
|
||||
TOOLCHAIN.$(EPICS_HOST_ARCH).$(T_A): toolchain.c
|
||||
$(PREPROCESS.cpp)
|
||||
|
@ -42,12 +42,6 @@ ARCH_DEP_LDFLAGS += $(ARCH_DEP_FLAGS)
|
||||
OP_SYS_CFLAGS += -isysroot $(SDK_DIR)
|
||||
OP_SYS_LDFLAGS += -isysroot $(SDK_DIR)
|
||||
|
||||
#--------------------------------------------------
|
||||
# Always compile in debugging symbol table information
|
||||
#
|
||||
OPT_CFLAGS_YES += -g
|
||||
OPT_CXXFLAGS_YES += -g
|
||||
|
||||
#-------------------------------------------------------
|
||||
# Compiler definitions:
|
||||
|
||||
|
@ -39,12 +39,6 @@ OP_SYS_CFLAGS += -fno-common
|
||||
#
|
||||
OP_SYS_CPPFLAGS += -Ddarwin
|
||||
|
||||
#
|
||||
# Always compile in debugging symbol table information
|
||||
#
|
||||
OPT_CFLAGS_YES += -g
|
||||
OPT_CXXFLAGS_YES += -g
|
||||
|
||||
#
|
||||
# Libraries for command-line editing.
|
||||
#
|
||||
|
@ -6,11 +6,3 @@
|
||||
# GNU_DIR used when COMMANDLINE_LIBRARY is READLINE
|
||||
#GNU_DIR=C:/cygwin
|
||||
|
||||
|
||||
# It makes sense to include debugging symbols even in optimized builds
|
||||
# in case you want to attach gdb to the process or examine a core-dump.
|
||||
# This does cost disk space, but not memory as debug symbols are not
|
||||
# loaded into RAM when the binary is loaded.
|
||||
OPT_CFLAGS_YES += -g
|
||||
OPT_CXXFLAGS_YES += -g
|
||||
|
||||
|
@ -3,10 +3,3 @@
|
||||
# Site specific definitions for native linux-aarch64 builds
|
||||
#-------------------------------------------------------
|
||||
|
||||
# It makes sense to include debugging symbols even in optimized builds
|
||||
# in case you want to attach gdb to the process or examine a core-dump.
|
||||
# This does cost disk space, but not memory as debug symbols are not
|
||||
# loaded into RAM when the binary is loaded.
|
||||
OPT_CFLAGS_YES += -g
|
||||
OPT_CXXFLAGS_YES += -g
|
||||
|
||||
|
@ -47,3 +47,8 @@ COMMANDLINE_LIBRARY ?= EPICS
|
||||
#else
|
||||
COMMANDLINE_LIBRARY ?= $(strip $(if $(wildcard $(if $(GNU_DIR),$(GNU_DIR)/include/readline/readline.h)), READLINE, EPICS))
|
||||
#endif
|
||||
|
||||
#if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE>2
|
||||
OP_SYS_CPPFLAGS += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2
|
||||
#endif
|
||||
|
||||
|
@ -20,9 +20,59 @@ should also be read to understand what has changed since earlier releases:
|
||||
|
||||
**This version of EPICS has not been released yet.**
|
||||
|
||||
## Changes made on the 7.0 branch since 7.0.8
|
||||
## Changes made on the 7.0 branch since 7.0.8.1
|
||||
|
||||
|
||||
-----
|
||||
|
||||
## EPICS Release 7.0.8.1
|
||||
|
||||
### Limit to `_FORTIFY_SOURCE=2`
|
||||
|
||||
GCC versions 12 and beyond and glibc have added some aggressive runtime
|
||||
checks for buffer overflows in libc functions at runtime, and the
|
||||
[Ubuntu 2024.04](https://wiki.ubuntu.com/ToolChain/CompilerFlags) release
|
||||
increased their default gcc fortification level from 2 to 3.
|
||||
This has started causing EPICS Base builds to fail on that version, and
|
||||
other OS releases may make that configuration change with similar results.
|
||||
This release detects a compiler configured with `_FORTIFY_SOURCE=3` and
|
||||
overrides it to 2.
|
||||
Later releases of Base will adjust the code, providing information to the
|
||||
compiler to avoid triggering these incorrect protections.
|
||||
|
||||
### Fix issue with compress record
|
||||
|
||||
In Base 7.0.8, an update to the compress record was added to allow for certain
|
||||
algorithms to use partially filled buffers in their computations. Unfortunately,
|
||||
this broke the behaviour of the records in certain cases. This has been fixed.
|
||||
|
||||
### Various minor changes
|
||||
|
||||
These included fixing minor memory leaks and documentation corrections. The
|
||||
`SIZV` field of lsi, lso and printf record VAL fields now can't exceed 32767
|
||||
characters, to match an internal limit.
|
||||
|
||||
### `epicsSocketAccept()` now returns `SOCKET`, not `int`
|
||||
|
||||
This might have some effect on downstream modules still using `int`, but the
|
||||
OS-specific osdSock.h headers which osiSock.h includes have all declared
|
||||
`SOCKET` (in most casese as a typedef for `int`) for many releases.
|
||||
This change removes a compiler warning on WIN32.
|
||||
Further details and the discussion about this change can be found
|
||||
[here](https://github.com/epics-base/epics-base/pull/458).
|
||||
|
||||
### `dbLoadRecords` allows macros with default values
|
||||
|
||||
Previously the parser assumed that files containing macro substitutions were
|
||||
bad if no macro definitions were provided; that assumption was made incorrect
|
||||
once macro substitutions were allowed to provide a default value.
|
||||
|
||||
### Hostname length limit in CA removed
|
||||
|
||||
Before this release, the CA client library only handled hostnames in address
|
||||
list environment variables up to 255 characters long.
|
||||
This limit has been removed.
|
||||
|
||||
-----
|
||||
|
||||
## EPICS Release 7.0.8
|
||||
|
@ -179,14 +179,10 @@ everything that has to be done since it's so easy to miss steps.</p>
|
||||
<li><tt>git grep UNRELEASED</tt> and insert the module version to any
|
||||
doxygen annotations that have a <tt>@since UNRELEASED</tt> comment.
|
||||
Commit (don't push yet).</li>
|
||||
|
||||
<li>Check that the module's Release Notes have been updated to cover
|
||||
all changes; add items as necessary, and set the module version
|
||||
number and release date if appropriate. Convert to HTML and view in
|
||||
a browser to check the formatting:
|
||||
<blockquote><tt>
|
||||
cd base-7.0/modules/<module>/documentation<br />
|
||||
pandoc -f gfm -t html -o RELEASE_NOTES.html RELEASE_NOTES.md
|
||||
</tt></blockquote>
|
||||
number and release date if appropriate.
|
||||
Commit these changes (don't push).</li>
|
||||
|
||||
<li>Edit the module's release version file
|
||||
@ -194,14 +190,37 @@ everything that has to be done since it's so easy to miss steps.</p>
|
||||
<tt>Doxyfile</tt>s in the top-level and/or documentation
|
||||
directories. In these, set <tt>DEVELOPMENT_FLAG</tt> to 0 and remove
|
||||
<tt>-dev</tt> from the <tt>PROJECT_NUMBER</tt> string. Commit these
|
||||
changes (don't push).</li>
|
||||
changes (don't push):
|
||||
<blockquote><tt>
|
||||
git ci -m 'Final commit for <module-version>'
|
||||
</tt></blockquote>
|
||||
</li>
|
||||
|
||||
<li>Tag the module:
|
||||
<blockquote><tt>
|
||||
git tag -m 'ANJ: Tag for EPICS 7.0.8' <module-version>
|
||||
git tag -m 'ANJ: Tag for EPICS 7.0.8.2' <module-version>
|
||||
</tt></blockquote>
|
||||
</li>
|
||||
|
||||
<li>Generate documentation or Release Notes using one of these:
|
||||
<ul>
|
||||
<li>For older modules with a RELEASE_NOTES.md file convert it to
|
||||
HTML and view in a browser to check the formatting as follows:
|
||||
<blockquote><tt>
|
||||
cd base-7.0/modules/<module>/documentation<br />
|
||||
pandoc -f gfm -t html -o RELEASE_NOTES.html RELEASE_NOTES.md
|
||||
</tt></blockquote>
|
||||
|
||||
<li>For newer modules with release_notes.dox file, generate the
|
||||
new github-pages website as follows:
|
||||
<blockquote><tt>
|
||||
cd base-7.0/modules/<module>/documentation<br />
|
||||
make commit
|
||||
git push --force upstream gh-pages
|
||||
</tt></blockquote>
|
||||
<i>Q: Delay this <tt>git push</tt> until later?</i></li>
|
||||
</ul></li>
|
||||
|
||||
<li>Update the git submodule on the Base-7.0 branch to the
|
||||
newly-tagged version, check the module's status matches the tag:
|
||||
<blockquote><tt>
|
||||
@ -269,7 +288,7 @@ everything that has to be done since it's so easy to miss steps.</p>
|
||||
<td>Tag the epics-base module in Git:
|
||||
<blockquote><tt>
|
||||
cd base-7.0<br />
|
||||
git tag -m 'ANJ: Tagged for release' R7.0.8
|
||||
git tag -m 'ANJ: Tagged for release' R7.0.8.2
|
||||
</tt></blockquote>
|
||||
<p>Don't push to GitHub yet.</p>
|
||||
</td>
|
||||
@ -303,12 +322,12 @@ everything that has to be done since it's so easy to miss steps.</p>
|
||||
files and directories that are only used for continuous integration:
|
||||
<blockquote><tt>
|
||||
cd base-7.0<br />
|
||||
./.tools/make-tar.sh R7.0.8 ../base-7.0.8.tar.gz base-7.0.8/
|
||||
./.tools/make-tar.sh R7.0.8.2 ../base-7.0.8.2.tar.gz base-7.0.8.2/
|
||||
</tt></blockquote>
|
||||
Create a GPG signature file of the tarfile as follows:
|
||||
<blockquote><tt>
|
||||
cd ..<br />
|
||||
gpg --armor --sign --detach-sig base-7.0.8.tar.gz
|
||||
gpg --armor --sign --detach-sig base-7.0.8.2.tar.gz
|
||||
</tt></blockquote>
|
||||
</td>
|
||||
</tr>
|
||||
@ -374,7 +393,7 @@ everything that has to be done since it's so easy to miss steps.</p>
|
||||
<td>Upload the tar file and its <tt>.asc</tt> signature file to the
|
||||
epics-controls web-server.
|
||||
<blockquote><tt>
|
||||
scp base-7.0.8.tar.gz base-7.0.8.tar.gz.asc epics-controls:download/base<br />
|
||||
scp base-7.0.8.2.tar.gz base-7.0.8.2.tar.gz.asc epics-controls:download/base<br />
|
||||
</tt></blockquote>
|
||||
</td>
|
||||
</tr>
|
||||
@ -397,8 +416,8 @@ everything that has to be done since it's so easy to miss steps.</p>
|
||||
<td><input type="checkbox"></td>
|
||||
<td>Release Manager</td>
|
||||
<td>Go to the GitHub
|
||||
<a href="https://github.com/epics-base/epics-base/releases/new?tag=R7.0.8">
|
||||
Create release from tag R7.0.8</a> page.
|
||||
<a href="https://github.com/epics-base/epics-base/releases/new?tag=R7.0.8.2">
|
||||
Create release from tag R7.0.8.2</a> page.
|
||||
Upload the tar file and its <tt>.asc</tt> signature file to the new
|
||||
GitHub release page.</td>
|
||||
</tr>
|
||||
|
@ -118,7 +118,6 @@ EXPAND_VARS = INSTALL_BIN=$(FINAL_LOCATION)/bin/$(T_A)
|
||||
SRC_DIRS += $(CURDIR)/test
|
||||
PROD_HOST += ca_test
|
||||
ca_test_SRCS = ca_test_main.c ca_test.c
|
||||
ca_test_LIBS = ca Com
|
||||
ca_test_SYS_LIBS_WIN32 = ws2_32 advapi32 user32
|
||||
|
||||
OBJS_vxWorks += ca_test
|
||||
|
@ -23,4 +23,4 @@ dbCore_SRCS += asIocRegister.c
|
||||
|
||||
PROD_HOST += ascheck
|
||||
ascheck_SRCS = ascheck.c
|
||||
ascheck_LIBS = dbCore ca Com
|
||||
ascheck_LIBS = dbCore ca
|
||||
|
@ -225,6 +225,11 @@ static void asCaTask(void)
|
||||
if(asCaDebug) printf("asCaTask has cleared all channels\n");
|
||||
epicsEventSignal(asCaTaskWait);
|
||||
}
|
||||
|
||||
/* ATM never reached, just a placeholder */
|
||||
cantProceed("Unreachable. Perpetual thread.");
|
||||
|
||||
taskwdRemove(0);
|
||||
}
|
||||
|
||||
void asCaStart(void)
|
||||
|
@ -112,7 +112,7 @@ void dbSpcAsRegisterCallback(SPC_ASCALLBACK func)
|
||||
|
||||
long dbPutSpecial(DBADDR *paddr,int pass)
|
||||
{
|
||||
long int (*pspecial)()=NULL;
|
||||
long int (*pspecial)(struct dbAddr *, int)=NULL;
|
||||
rset *prset;
|
||||
dbCommon *precord = paddr->precord;
|
||||
long status=0;
|
||||
|
@ -225,6 +225,7 @@ void testdbCaWaitForEvent(DBLINK *plink, unsigned long cnt, enum testEvent event
|
||||
|
||||
assert(plink->type==CA_LINK);
|
||||
pca = (caLink *)plink->value.pv_link.pvt;
|
||||
caLinkInc(pca);
|
||||
|
||||
epicsMutexMustLock(pca->lock);
|
||||
assert(!pca->monitor && !pca->connect && !pca->userPvt);
|
||||
@ -239,6 +240,8 @@ void testdbCaWaitForEvent(DBLINK *plink, unsigned long cnt, enum testEvent event
|
||||
dbScanUnlock(plink->precord);
|
||||
|
||||
epicsEventMustWait(evt);
|
||||
/* ensure worker has finished executing */
|
||||
dbCaSync();
|
||||
|
||||
dbScanLock(plink->precord);
|
||||
epicsMutexMustLock(pca->lock);
|
||||
@ -250,6 +253,7 @@ void testdbCaWaitForEvent(DBLINK *plink, unsigned long cnt, enum testEvent event
|
||||
|
||||
epicsEventDestroy(evt);
|
||||
epicsMutexUnlock(pca->lock);
|
||||
caLinkDec(pca);
|
||||
dbScanUnlock(plink->precord);
|
||||
}
|
||||
|
||||
@ -287,16 +291,15 @@ void dbCaSync(void)
|
||||
|
||||
epicsEventMustWait(wake);
|
||||
/* Worker holds workListLock when calling epicsEventMustTrigger()
|
||||
* we cycle through workListLock to ensure worker call to
|
||||
* we hold workListLock to ensure worker call to
|
||||
* epicsEventMustTrigger() returns before we destroy the event.
|
||||
*/
|
||||
epicsMutexMustLock(workListLock);
|
||||
epicsMutexUnlock(workListLock);
|
||||
|
||||
assert(templink.refcount==1);
|
||||
|
||||
epicsMutexDestroy(templink.lock);
|
||||
epicsEventDestroy(wake);
|
||||
epicsMutexUnlock(workListLock);
|
||||
}
|
||||
|
||||
void dbCaCallbackProcess(void *userPvt)
|
||||
|
@ -7,20 +7,38 @@
|
||||
* EPICS Base is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/* dbConvertFast.h */
|
||||
/** @file dbConvertFast.h
|
||||
* @brief Data conversion for scalar values
|
||||
*
|
||||
* The typedef FASTCONVERTFUNC is defined in link.h as:
|
||||
* @code
|
||||
* long convert(const void *from, void *to, const struct dbAddr *paddr);
|
||||
* @endcode
|
||||
*
|
||||
* The arrays declared here provide pointers to the fast conversion
|
||||
* routine where the first array index is the data type for the first
|
||||
* "from" pointer arg, and the second array index is the data type for
|
||||
* the second "to" pointer arg. The array index values are a subset of
|
||||
* the DBF_ enum values defined in dbFldTypes.h
|
||||
*/
|
||||
|
||||
#ifndef INCdbConvertFasth
|
||||
#define INCdbConvertFasth
|
||||
|
||||
#include "dbFldTypes.h"
|
||||
#include "dbCoreAPI.h"
|
||||
#include "link.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
DBCORE_API extern long (*dbFastGetConvertRoutine[DBF_DEVICE+1][DBR_ENUM+1])();
|
||||
DBCORE_API extern long (*dbFastPutConvertRoutine[DBR_ENUM+1][DBF_DEVICE+1])();
|
||||
/** Function pointers for get conversions */
|
||||
DBCORE_API extern const FASTCONVERTFUNC
|
||||
dbFastGetConvertRoutine[DBF_DEVICE+1][DBR_ENUM+1];
|
||||
/** Function pointers for put conversions */
|
||||
DBCORE_API extern const FASTCONVERTFUNC
|
||||
dbFastPutConvertRoutine[DBR_ENUM+1][DBF_DEVICE+1];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -19,8 +19,6 @@
|
||||
#include "dbConvertFast.h"
|
||||
#include "dbConvertJSON.h"
|
||||
|
||||
typedef long (*FASTCONVERT)();
|
||||
|
||||
typedef struct parseContext {
|
||||
int depth;
|
||||
short dbrType;
|
||||
@ -42,7 +40,7 @@ static int dbcj_boolean(void *ctx, int val) {
|
||||
static int dbcj_integer(void *ctx, long long num) {
|
||||
parseContext *parser = (parseContext *) ctx;
|
||||
epicsInt64 val64 = num;
|
||||
FASTCONVERT conv = dbFastPutConvertRoutine[DBF_INT64][parser->dbrType];
|
||||
FASTCONVERTFUNC conv = dbFastPutConvertRoutine[DBF_INT64][parser->dbrType];
|
||||
|
||||
if (parser->elems > 0) {
|
||||
conv(&val64, parser->pdest, NULL);
|
||||
@ -54,7 +52,7 @@ static int dbcj_integer(void *ctx, long long num) {
|
||||
|
||||
static int dbcj_double(void *ctx, double num) {
|
||||
parseContext *parser = (parseContext *) ctx;
|
||||
FASTCONVERT conv = dbFastPutConvertRoutine[DBF_DOUBLE][parser->dbrType];
|
||||
FASTCONVERTFUNC conv = dbFastPutConvertRoutine[DBF_DOUBLE][parser->dbrType];
|
||||
|
||||
if (parser->elems > 0) {
|
||||
conv(&num, parser->pdest, NULL);
|
||||
|
@ -98,8 +98,8 @@ struct event_user {
|
||||
unsigned char extra_labor; /* if set call extra labor func */
|
||||
unsigned char flowCtrlMode; /* replace existing monitor */
|
||||
unsigned char extraLaborBusy;
|
||||
void (*init_func)();
|
||||
epicsThreadId init_func_arg;
|
||||
void (*init_func)(void *);
|
||||
void *init_func_arg;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -133,7 +133,7 @@ void dbInitLink(struct link *plink, short dbfType)
|
||||
plink->value.pv_link.pvlMask |= pvlOptFWD;
|
||||
}
|
||||
else {
|
||||
errlogPrintf("Forward-link uses Channel Access "
|
||||
errlogPrintf(ERL_WARNING ": Forward-link uses Channel Access "
|
||||
"without pointing to PROC field\n"
|
||||
" %s.%s => %s\n",
|
||||
precord->name, dbLinkFieldName(plink),
|
||||
|
@ -307,7 +307,7 @@ typedef struct lset {
|
||||
*
|
||||
* @param plink the link
|
||||
* @param dbrType data type code
|
||||
* @param pbuffer where to put the value
|
||||
* @param pbuffer where the data is
|
||||
* @param nRequest number of elements to send
|
||||
* @returns status value
|
||||
*/
|
||||
@ -324,7 +324,7 @@ typedef struct lset {
|
||||
*
|
||||
* @param plink the link
|
||||
* @param dbrType data type code
|
||||
* @param pbuffer where to put the value
|
||||
* @param pbuffer where the data is
|
||||
* @param nRequest number of elements to send
|
||||
* @returns status value
|
||||
*/
|
||||
|
@ -918,7 +918,7 @@ long dblsr(char *recordname,int level)
|
||||
pdbFldDes = pdbRecordType->papFldDes[pdbRecordType->link_ind[link]];
|
||||
plink = (DBLINK *)((char *)precord + pdbFldDes->offset);
|
||||
if(plink->type != DB_LINK) continue;
|
||||
pdbAddr = (DBADDR *)(plink->value.pv_link.pvt);
|
||||
pdbAddr = &((dbChannel *)(plink->value.pv_link.pvt))->addr;
|
||||
printf("\t%s",pdbFldDes->name);
|
||||
if(pdbFldDes->field_type==DBF_INLINK) {
|
||||
printf("\t INLINK");
|
||||
|
@ -155,7 +155,7 @@ void scanStop(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (scanCtl == ctlExit) return;
|
||||
if (scanCtl == ctlInit || scanCtl == ctlExit) return;
|
||||
scanCtl = ctlExit;
|
||||
|
||||
interruptAccept = FALSE;
|
||||
@ -264,7 +264,7 @@ void scanAdd(struct dbCommon *precord)
|
||||
} else if (scan == menuScanI_O_Intr) {
|
||||
ioscan_head *piosh = NULL;
|
||||
int prio;
|
||||
DEVSUPFUN get_ioint_info;
|
||||
long (*get_ioint_info)(int, struct dbCommon *, IOSCANPVT*);
|
||||
|
||||
if (precord->dset == NULL){
|
||||
recGblRecordError(-1, (void *)precord,
|
||||
@ -332,7 +332,7 @@ void scanDelete(struct dbCommon *precord)
|
||||
} else if (scan == menuScanI_O_Intr) {
|
||||
ioscan_head *piosh = NULL;
|
||||
int prio;
|
||||
DEVSUPFUN get_ioint_info;
|
||||
long (*get_ioint_info)(int, struct dbCommon *, IOSCANPVT*);
|
||||
|
||||
if (precord->dset==NULL) {
|
||||
recGblRecordError(-1, (void *)precord,
|
||||
|
@ -680,7 +680,7 @@ long dbtpf(const char *pname, const char *pvalue)
|
||||
long dbior(const char *pdrvName,int interest_level)
|
||||
{
|
||||
drvSup *pdrvSup;
|
||||
struct drvet *pdrvet;
|
||||
drvet *pdrvet;
|
||||
dbRecordType *pdbRecordType;
|
||||
|
||||
if (!pdbbase) {
|
||||
|
@ -62,7 +62,7 @@ void recGblRecordError(long status, void *pdbc,
|
||||
dbCommon *precord = pdbc;
|
||||
char errMsg[256] = "";
|
||||
|
||||
if (status)
|
||||
if ( status>0 )
|
||||
errSymLookup(status, errMsg, sizeof(errMsg));
|
||||
|
||||
errlogPrintf("recGblRecordError: %s %s PV: %s\n",
|
||||
|
@ -11,6 +11,8 @@
|
||||
|
||||
SRC_DIRS += $(IOCDIR)/dbStatic
|
||||
|
||||
USR_CFLAGS += -DUSE_TYPED_DRVET
|
||||
|
||||
INC += dbBase.h
|
||||
INC += dbFldTypes.h
|
||||
INC += dbStaticLib.h
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "dbDefs.h"
|
||||
#include "recSup.h"
|
||||
#include "devSup.h"
|
||||
#include "drvSup.h"
|
||||
|
||||
typedef struct dbMenu {
|
||||
ELLNODE node;
|
||||
@ -33,7 +34,7 @@ typedef struct dbMenu {
|
||||
typedef struct drvSup {
|
||||
ELLNODE node;
|
||||
char *name;
|
||||
struct drvet *pdrvet;
|
||||
drvet *pdrvet;
|
||||
}drvSup;
|
||||
|
||||
typedef struct devSup {
|
||||
@ -119,7 +120,7 @@ typedef struct dbRecordNode {
|
||||
ELLLIST infoList; /*LIST head of info nodes*/
|
||||
int flags;
|
||||
/** Parse order of this record()
|
||||
* @since UNRELEASED
|
||||
* @since 7.0.8.1
|
||||
*/
|
||||
unsigned order;
|
||||
struct dbRecordNode *aliasedRecnode; /* NULL unless flags|DBRN_FLAGS_ISALIAS */
|
||||
@ -189,7 +190,7 @@ typedef struct dbBase {
|
||||
short ignoreMissingMenus;
|
||||
short loadCdefs;
|
||||
/** Total number of records.
|
||||
* @since UNRELEASED
|
||||
* @since 7.0.8.1
|
||||
*/
|
||||
unsigned no_records;
|
||||
}dbBase;
|
||||
|
@ -225,7 +225,7 @@ static long dbReadCOM(DBBASE **ppdbbase,const char *filename, FILE *fp,
|
||||
char **macPairs;
|
||||
|
||||
if (ellCount(&tempList)) {
|
||||
epicsPrintf("dbReadCOM: Parser stack dirty %d\n", ellCount(&tempList));
|
||||
fprintf(stderr, ERL_WARNING ": dbReadCOM: Parser stack dirty %d\n", ellCount(&tempList));
|
||||
}
|
||||
|
||||
if (getIocState() != iocVoid) {
|
||||
@ -250,7 +250,7 @@ static long dbReadCOM(DBBASE **ppdbbase,const char *filename, FILE *fp,
|
||||
if (substitutions == NULL)
|
||||
substitutions = "";
|
||||
if(macCreateHandle(&macHandle,NULL)) {
|
||||
epicsPrintf("macCreateHandle error\n");
|
||||
fprintf(stderr, ERL_ERROR ": macCreateHandle failed\n");
|
||||
status = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
@ -294,7 +294,7 @@ static long dbReadCOM(DBBASE **ppdbbase,const char *filename, FILE *fp,
|
||||
status = pvt_yy_parse();
|
||||
|
||||
if (ellCount(&tempList) && !yyAbort)
|
||||
epicsPrintf("dbReadCOM: Parser stack dirty w/o error. %d\n", ellCount(&tempList));
|
||||
fprintf(stderr, ERL_WARNING ": dbReadCOM: Parser stack dirty w/o error. %d\n", ellCount(&tempList));
|
||||
while (ellCount(&tempList))
|
||||
popFirstTemp(); /* Memory leak on parser failure */
|
||||
|
||||
@ -401,15 +401,15 @@ static void dbIncludePrint(void)
|
||||
inputFile *pinputFile = pinputFileNow;
|
||||
|
||||
while (pinputFile) {
|
||||
epicsPrintf(" in");
|
||||
fprintf(stderr, " in");
|
||||
if (pinputFile->path)
|
||||
epicsPrintf(" path \"%s\" ",pinputFile->path);
|
||||
fprintf(stderr, " path \"%s\" ",pinputFile->path);
|
||||
if (pinputFile->filename) {
|
||||
epicsPrintf(" file \"%s\"",pinputFile->filename);
|
||||
fprintf(stderr, " file \"%s\"",pinputFile->filename);
|
||||
} else {
|
||||
epicsPrintf(" standard input");
|
||||
fprintf(stderr, " standard input");
|
||||
}
|
||||
epicsPrintf(" line %d\n",pinputFile->line_num);
|
||||
fprintf(stderr, " line %d\n",pinputFile->line_num);
|
||||
pinputFile = (inputFile *)ellPrevious(&pinputFile->node);
|
||||
}
|
||||
return;
|
||||
@ -434,7 +434,7 @@ static void dbIncludeNew(char *filename)
|
||||
pinputFile->filename = macEnvExpand(filename);
|
||||
pinputFile->path = dbOpenFile(savedPdbbase, pinputFile->filename, &fp);
|
||||
if (!fp) {
|
||||
epicsPrintf("Can't open include file \"%s\"\n", filename);
|
||||
fprintf(stderr, "Can't open include file \"%s\"\n", filename);
|
||||
yyerror(NULL);
|
||||
free((void *)pinputFile->filename);
|
||||
free((void *)pinputFile);
|
||||
@ -696,7 +696,7 @@ static void dbRecordtypeEmpty(void)
|
||||
|
||||
ptempListNode = (tempListNode *)ellFirst(&tempList);
|
||||
pdbRecordType = ptempListNode->item;
|
||||
epicsPrintf("Declaration of recordtype(%s) preceeded full definition.\n",
|
||||
fprintf(stderr, "Declaration of recordtype(%s) preceeded full definition.\n",
|
||||
pdbRecordType->name);
|
||||
yyerrorAbort(NULL);
|
||||
}
|
||||
@ -801,7 +801,7 @@ static void dbDevice(char *recordtype,char *linktype,
|
||||
int i,link_type;
|
||||
pgphentry = gphFind(savedPdbbase->pgpHash,recordtype,&savedPdbbase->recordTypeList);
|
||||
if(!pgphentry) {
|
||||
epicsPrintf("Record type \"%s\" not found for device \"%s\"\n",
|
||||
fprintf(stderr, "Record type \"%s\" not found for device \"%s\"\n",
|
||||
recordtype, choicestring);
|
||||
yyerror(NULL);
|
||||
return;
|
||||
@ -814,7 +814,7 @@ static void dbDevice(char *recordtype,char *linktype,
|
||||
}
|
||||
}
|
||||
if(link_type==-1) {
|
||||
epicsPrintf("Bad link type \"%s\" for device \"%s\"\n",
|
||||
fprintf(stderr, "Bad link type \"%s\" for device \"%s\"\n",
|
||||
linktype, choicestring);
|
||||
yyerror(NULL);
|
||||
return;
|
||||
@ -1077,16 +1077,16 @@ int dbRecordNameValidate(const char *name)
|
||||
if(i==0) {
|
||||
/* first character restrictions */
|
||||
if(c=='-' || c=='+' || c=='[' || c=='{') {
|
||||
errlogPrintf("Warning: Record/Alias name '%s' should not begin with '%c'\n", name, c);
|
||||
fprintf(stderr, "Warning: Record/Alias name '%s' should not begin with '%c'\n", name, c);
|
||||
}
|
||||
}
|
||||
/* any character restrictions */
|
||||
if(c < ' ') {
|
||||
errlogPrintf("Warning: Record/Alias name '%s' should not contain non-printable 0x%02x\n",
|
||||
fprintf(stderr, "Warning: Record/Alias name '%s' should not contain non-printable 0x%02x\n",
|
||||
name, c);
|
||||
|
||||
} else if(c==' ' || c=='\t' || c=='"' || c=='\'' || c=='.' || c=='$') {
|
||||
epicsPrintf(ERL_ERROR ": Bad character '%c' in Record/Alias name \"%s\"\n",
|
||||
fprintf(stderr, ERL_ERROR ": Bad character '%c' in Record/Alias name \"%s\"\n",
|
||||
c, name);
|
||||
yyerrorAbort(NULL);
|
||||
return 1;
|
||||
@ -1113,7 +1113,7 @@ static void dbRecordHead(char *recordType, char *name, int visible)
|
||||
status = dbFindRecord(pdbentry, name);
|
||||
if (status == 0)
|
||||
return; /* done */
|
||||
epicsPrintf(ERL_ERROR ": Record \"%s\" not found\n", name);
|
||||
fprintf(stderr, ERL_ERROR ": Record \"%s\" not found\n", name);
|
||||
yyerror(NULL);
|
||||
duplicate = TRUE;
|
||||
return;
|
||||
@ -1121,7 +1121,7 @@ static void dbRecordHead(char *recordType, char *name, int visible)
|
||||
|
||||
status = dbFindRecordType(pdbentry, recordType);
|
||||
if (status) {
|
||||
epicsPrintf("Record \"%s\" is of unknown type \"%s\"\n",
|
||||
fprintf(stderr, "Record \"%s\" is of unknown type \"%s\"\n",
|
||||
name, recordType);
|
||||
yyerrorAbort(NULL);
|
||||
return;
|
||||
@ -1132,14 +1132,14 @@ static void dbRecordHead(char *recordType, char *name, int visible)
|
||||
status = dbCreateRecord(pdbentry,name);
|
||||
if (status == S_dbLib_recExists) {
|
||||
if (strcmp(recordType, dbGetRecordTypeName(pdbentry)) != 0) {
|
||||
epicsPrintf(ERL_ERROR ": Record \"%s\" of type \"%s\" redefined with new type "
|
||||
fprintf(stderr, ERL_ERROR ": Record \"%s\" of type \"%s\" redefined with new type "
|
||||
"\"%s\"\n", name, dbGetRecordTypeName(pdbentry), recordType);
|
||||
yyerror(NULL);
|
||||
duplicate = TRUE;
|
||||
return;
|
||||
}
|
||||
else if (dbRecordsOnceOnly) {
|
||||
epicsPrintf(ERL_ERROR ": Record \"%s\" already defined and dbRecordsOnceOnly set.\n"
|
||||
fprintf(stderr, ERL_ERROR ": Record \"%s\" already defined and dbRecordsOnceOnly set.\n"
|
||||
"Used record type \"*\" to append.\n",
|
||||
name);
|
||||
yyerror(NULL);
|
||||
@ -1147,7 +1147,7 @@ static void dbRecordHead(char *recordType, char *name, int visible)
|
||||
}
|
||||
}
|
||||
else if (status) {
|
||||
epicsPrintf("Can't create record \"%s\" of type \"%s\"\n",
|
||||
fprintf(stderr, "Can't create record \"%s\" of type \"%s\"\n",
|
||||
name, recordType);
|
||||
yyerrorAbort(NULL);
|
||||
}
|
||||
@ -1167,7 +1167,7 @@ static void dbRecordField(char *name,char *value)
|
||||
pdbentry = ptempListNode->item;
|
||||
status = dbFindField(pdbentry,name);
|
||||
if (status) {
|
||||
epicsPrintf("%s Record \"%s\" does not have a field \"%s\"\n",
|
||||
fprintf(stderr, "%s Record \"%s\" does not have a field \"%s\"\n",
|
||||
dbGetRecordTypeName(pdbentry), dbGetRecordName(pdbentry), name);
|
||||
if(dbGetRecordName(pdbentry)) {
|
||||
DBENTRY temp;
|
||||
@ -1183,17 +1183,17 @@ static void dbRecordField(char *name,char *value)
|
||||
}
|
||||
dbFinishEntry(&temp);
|
||||
if(bestSim>0.0) {
|
||||
epicsPrintf(" Did you mean \"%s\"?", bestFld->name);
|
||||
fprintf(stderr, " Did you mean \"%s\"?", bestFld->name);
|
||||
if(bestFld->prompt)
|
||||
epicsPrintf(" (%s)", bestFld->prompt);
|
||||
epicsPrintf("\n");
|
||||
fprintf(stderr, " (%s)", bestFld->prompt);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
}
|
||||
yyerror(NULL);
|
||||
return;
|
||||
}
|
||||
if (pdbentry->indfield == 0) {
|
||||
epicsPrintf("Can't set \"NAME\" field of record \"%s\"\n",
|
||||
fprintf(stderr, "Can't set \"NAME\" field of record \"%s\"\n",
|
||||
dbGetRecordName(pdbentry));
|
||||
yyerror(NULL);
|
||||
return;
|
||||
@ -1211,7 +1211,7 @@ static void dbRecordField(char *name,char *value)
|
||||
char msg[128];
|
||||
|
||||
errSymLookup(status, msg, sizeof(msg));
|
||||
epicsPrintf("Can't set \"%s.%s\" to \"%s\" %s : %s\n",
|
||||
fprintf(stderr, "Can't set \"%s.%s\" to \"%s\" %s : %s\n",
|
||||
dbGetRecordName(pdbentry), name, value, pdbentry->message ? pdbentry->message : "", msg);
|
||||
dbPutStringSuggest(pdbentry, value);
|
||||
yyerror(NULL);
|
||||
@ -1242,7 +1242,7 @@ static void dbRecordInfo(char *name, char *value)
|
||||
|
||||
status = dbPutInfo(pdbentry,name,value);
|
||||
if (status) {
|
||||
epicsPrintf("Can't set \"%s\" info \"%s\" to \"%s\"\n",
|
||||
fprintf(stderr, "Can't set \"%s\" info \"%s\" to \"%s\"\n",
|
||||
dbGetRecordName(pdbentry), name, value);
|
||||
yyerror(NULL);
|
||||
return;
|
||||
@ -1263,7 +1263,7 @@ static void dbRecordAlias(char *name)
|
||||
pdbentry = ptempListNode->item;
|
||||
status = dbCreateAlias(pdbentry, name);
|
||||
if (status) {
|
||||
epicsPrintf("Can't create alias \"%s\" for \"%s\"\n",
|
||||
fprintf(stderr, "Can't create alias \"%s\" for \"%s\"\n",
|
||||
name, dbGetRecordName(pdbentry));
|
||||
yyerror(NULL);
|
||||
return;
|
||||
@ -1280,12 +1280,12 @@ static void dbAlias(char *name, char *alias)
|
||||
|
||||
dbInitEntry(savedPdbbase, pdbEntry);
|
||||
if (dbFindRecord(pdbEntry, name)) {
|
||||
epicsPrintf("Alias \"%s\" refers to unknown record \"%s\"\n",
|
||||
fprintf(stderr, "Alias \"%s\" refers to unknown record \"%s\"\n",
|
||||
alias, name);
|
||||
yyerror(NULL);
|
||||
}
|
||||
else if (dbCreateAlias(pdbEntry, alias)) {
|
||||
epicsPrintf("Can't create alias \"%s\" referring to \"%s\"\n",
|
||||
fprintf(stderr, "Can't create alias \"%s\" referring to \"%s\"\n",
|
||||
alias, name);
|
||||
yyerror(NULL);
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
%{
|
||||
static int yyerror();
|
||||
static int yyerror(char *str);
|
||||
static int yy_start;
|
||||
static long pvt_yy_parse(void);
|
||||
static int yyFailed = 0;
|
||||
@ -370,11 +370,11 @@ json_value: jsonNULL { $$ = dbmfStrdup("null"); }
|
||||
static int yyerror(char *str)
|
||||
{
|
||||
if (str)
|
||||
epicsPrintf(ERL_ERROR ": %s\n", str);
|
||||
fprintf(stderr, ERL_ERROR ": %s\n", str);
|
||||
else
|
||||
epicsPrintf(ERL_ERROR "");
|
||||
fprintf(stderr, ERL_ERROR ": ");
|
||||
if (!yyFailed) { /* Only print this stuff once */
|
||||
epicsPrintf(" at or before '%s'", yytext);
|
||||
fprintf(stderr, " at or before '%s'", yytext);
|
||||
dbIncludePrint();
|
||||
yyFailed = TRUE;
|
||||
}
|
||||
|
@ -77,14 +77,14 @@ struct macro_link {
|
||||
char *macroStr;
|
||||
};
|
||||
|
||||
struct dbCommon;
|
||||
typedef long (*LINKCVT)();
|
||||
struct dbAddr;
|
||||
typedef long (*FASTCONVERTFUNC)(const void *from, void *to, const struct dbAddr *paddr);
|
||||
|
||||
struct pv_link {
|
||||
ELLNODE backlinknode;
|
||||
char *pvname; /* pvname link points to */
|
||||
void *pvt; /* CA or DB private */
|
||||
LINKCVT getCvt; /* input conversion function */
|
||||
FASTCONVERTFUNC getCvt; /* input conversion function */
|
||||
short pvlMask; /* Options mask */
|
||||
short lastGetdbrType; /* last dbrType for DB or CA get */
|
||||
};
|
||||
@ -188,8 +188,8 @@ union value {
|
||||
struct vxiio vxiio; /* vxi io */
|
||||
};
|
||||
|
||||
struct dbCommon;
|
||||
struct lset;
|
||||
|
||||
struct link {
|
||||
struct dbCommon *precord; /* Pointer to record owning link */
|
||||
short type;
|
||||
|
@ -14,7 +14,6 @@ SRC_DIRS += $(IOCDIR)/dbtemplate
|
||||
PROD_CMD += msi
|
||||
|
||||
msi_SRCS = msi.cpp
|
||||
msi_LIBS += Com
|
||||
HTMLS += msi.html
|
||||
|
||||
INC += dbLoadTemplate.h
|
||||
|
@ -114,7 +114,7 @@ int iocInit(void)
|
||||
static int iocBuild_1(void)
|
||||
{
|
||||
if (iocState != iocVoid) {
|
||||
errlogPrintf("iocBuild: IOC can only be initialized from uninitialized or stopped state\n");
|
||||
errlogPrintf("iocBuild: " ERL_ERROR " IOC can only be initialized from uninitialized or stopped state\n");
|
||||
return -1;
|
||||
}
|
||||
errlogInit(0);
|
||||
@ -126,7 +126,7 @@ static int iocBuild_1(void)
|
||||
|
||||
errlogPrintf("Starting iocInit\n");
|
||||
if (checkDatabase(pdbbase)) {
|
||||
errlogPrintf("iocBuild: Aborting, bad database definition (DBD)!\n");
|
||||
errlogPrintf("iocBuild: " ERL_ERROR " Aborting, bad database definition (DBD)!\n");
|
||||
return -1;
|
||||
}
|
||||
epicsSignalInstallSigHupIgnore();
|
||||
@ -237,7 +237,7 @@ int iocBuildIsolated(void)
|
||||
int iocRun(void)
|
||||
{
|
||||
if (iocState != iocPaused && iocState != iocBuilt) {
|
||||
errlogPrintf("iocRun: IOC not paused\n");
|
||||
errlogPrintf("iocRun: " ERL_WARNING " IOC not paused\n");
|
||||
return -1;
|
||||
}
|
||||
initHookAnnounce(initHookAtIocRun);
|
||||
@ -268,7 +268,7 @@ int iocRun(void)
|
||||
int iocPause(void)
|
||||
{
|
||||
if (iocState != iocRunning) {
|
||||
errlogPrintf("iocPause: IOC not running\n");
|
||||
errlogPrintf("iocPause: " ERL_WARNING " IOC not running\n");
|
||||
return -1;
|
||||
}
|
||||
initHookAnnounce(initHookAtIocPause);
|
||||
@ -306,59 +306,59 @@ static int checkDatabase(dbBase *pdbbase)
|
||||
const dbMenu *pMenu;
|
||||
|
||||
if (!pdbbase) {
|
||||
errlogPrintf("checkDatabase: No database definitions loaded.\n");
|
||||
errlogPrintf("checkDatabase: " ERL_ERROR " No database definitions loaded.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pMenu = dbFindMenu(pdbbase, "menuConvert");
|
||||
if (!pMenu) {
|
||||
errlogPrintf("checkDatabase: menuConvert not defined.\n");
|
||||
errlogPrintf("checkDatabase: " ERL_ERROR " menuConvert not defined.\n");
|
||||
return -1;
|
||||
}
|
||||
if (pMenu->nChoice <= menuConvertLINEAR) {
|
||||
errlogPrintf("checkDatabase: menuConvert has too few choices.\n");
|
||||
errlogPrintf("checkDatabase: " ERL_ERROR " menuConvert has too few choices.\n");
|
||||
return -1;
|
||||
}
|
||||
if (strcmp(pMenu->papChoiceName[menuConvertNO_CONVERSION],
|
||||
"menuConvertNO_CONVERSION")) {
|
||||
errlogPrintf("checkDatabase: menuConvertNO_CONVERSION doesn't match.\n");
|
||||
errlogPrintf("checkDatabase: " ERL_ERROR " menuConvertNO_CONVERSION doesn't match.\n");
|
||||
return -1;
|
||||
}
|
||||
if (strcmp(pMenu->papChoiceName[menuConvertSLOPE], "menuConvertSLOPE")) {
|
||||
errlogPrintf("checkDatabase: menuConvertSLOPE doesn't match.\n");
|
||||
errlogPrintf("checkDatabase: " ERL_ERROR " menuConvertSLOPE doesn't match.\n");
|
||||
return -1;
|
||||
}
|
||||
if (strcmp(pMenu->papChoiceName[menuConvertLINEAR], "menuConvertLINEAR")) {
|
||||
errlogPrintf("checkDatabase: menuConvertLINEAR doesn't match.\n");
|
||||
errlogPrintf("checkDatabase: " ERL_ERROR " menuConvertLINEAR doesn't match.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pMenu = dbFindMenu(pdbbase, "menuScan");
|
||||
if (!pMenu) {
|
||||
errlogPrintf("checkDatabase: menuScan not defined.\n");
|
||||
errlogPrintf("checkDatabase: " ERL_ERROR " menuScan not defined.\n");
|
||||
return -1;
|
||||
}
|
||||
if (pMenu->nChoice <= menuScanI_O_Intr) {
|
||||
errlogPrintf("checkDatabase: menuScan has too few choices.\n");
|
||||
errlogPrintf("checkDatabase: " ERL_ERROR " menuScan has too few choices.\n");
|
||||
return -1;
|
||||
}
|
||||
if (strcmp(pMenu->papChoiceName[menuScanPassive],
|
||||
"menuScanPassive")) {
|
||||
errlogPrintf("checkDatabase: menuScanPassive doesn't match.\n");
|
||||
errlogPrintf("checkDatabase: " ERL_ERROR " menuScanPassive doesn't match.\n");
|
||||
return -1;
|
||||
}
|
||||
if (strcmp(pMenu->papChoiceName[menuScanEvent],
|
||||
"menuScanEvent")) {
|
||||
errlogPrintf("checkDatabase: menuScanEvent doesn't match.\n");
|
||||
errlogPrintf("checkDatabase: " ERL_ERROR " menuScanEvent doesn't match.\n");
|
||||
return -1;
|
||||
}
|
||||
if (strcmp(pMenu->papChoiceName[menuScanI_O_Intr],
|
||||
"menuScanI_O_Intr")) {
|
||||
errlogPrintf("checkDatabase: menuScanI_O_Intr doesn't match.\n");
|
||||
errlogPrintf("checkDatabase: " ERL_ERROR " menuScanI_O_Intr doesn't match.\n");
|
||||
return -1;
|
||||
}
|
||||
if (pMenu->nChoice <= SCAN_1ST_PERIODIC) {
|
||||
errlogPrintf("checkDatabase: menuScan has no periodic choices.\n");
|
||||
errlogPrintf("checkDatabase: " ERL_ERROR " menuScan has no periodic choices.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -388,7 +388,7 @@ static void initDrvSup(void) /* Locate all driver support entry tables */
|
||||
|
||||
for (pdrvSup = (drvSup *)ellFirst(&pdbbase->drvList); pdrvSup;
|
||||
pdrvSup = (drvSup *)ellNext(&pdrvSup->node)) {
|
||||
struct drvet *pdrvet = registryDriverSupportFind(pdrvSup->name);
|
||||
drvet *pdrvet = registryDriverSupportFind(pdrvSup->name);
|
||||
|
||||
if (!pdrvet) {
|
||||
errlogPrintf("iocInit: driver %s not found\n", pdrvSup->name);
|
||||
|
@ -32,11 +32,12 @@ namespace {
|
||||
struct compareLoc {
|
||||
bool operator()(const recordTypeLocation& lhs, const recordTypeLocation& rhs) const
|
||||
{
|
||||
if(lhs.prset<rhs.prset)
|
||||
if (lhs.prset < rhs.prset)
|
||||
return true;
|
||||
else if(lhs.prset>rhs.prset)
|
||||
if (lhs.prset > rhs.prset)
|
||||
return false;
|
||||
return lhs.sizeOffset<rhs.sizeOffset;
|
||||
return reinterpret_cast<char *>(lhs.sizeOffset)
|
||||
< reinterpret_cast<char *>(rhs.sizeOffset);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -65,7 +65,7 @@ void registerDevices(DBBASE *pbase, int nDevices,
|
||||
}
|
||||
|
||||
void registerDrivers(DBBASE *pbase, int nDrivers,
|
||||
const char * const * driverSupportNames, struct drvet * const *drvsl)
|
||||
const char * const * driverSupportNames, drvet * const *drvsl)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < nDrivers; i++) {
|
||||
|
@ -29,7 +29,7 @@ DBCORE_API void registerDevices(
|
||||
const char * const *deviceSupportNames, const dset * const *devsl);
|
||||
DBCORE_API void registerDrivers(
|
||||
DBBASE *pbase, int nDrivers,
|
||||
const char * const *driverSupportNames, struct drvet * const *drvsl);
|
||||
const char * const *driverSupportNames, drvet * const *drvsl);
|
||||
DBCORE_API void registerJLinks(
|
||||
DBBASE *pbase, int nDrivers, jlif * const *jlifsl);
|
||||
|
||||
|
@ -18,12 +18,12 @@ static void *registryID = "driver support";
|
||||
|
||||
|
||||
DBCORE_API int registryDriverSupportAdd(
|
||||
const char *name, struct drvet *pdrvet)
|
||||
const char *name, drvet *pdrvet)
|
||||
{
|
||||
return registryAdd(registryID, name, pdrvet);
|
||||
}
|
||||
|
||||
DBCORE_API struct drvet * registryDriverSupportFind(
|
||||
DBCORE_API drvet * registryDriverSupportFind(
|
||||
const char *name)
|
||||
{
|
||||
return registryFind(registryID, name);
|
||||
|
@ -19,8 +19,8 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
DBCORE_API int registryDriverSupportAdd(
|
||||
const char *name, struct drvet *pdrvet);
|
||||
DBCORE_API struct drvet * registryDriverSupportFind(
|
||||
const char *name, drvet *pdrvet);
|
||||
DBCORE_API drvet * registryDriverSupportFind(
|
||||
const char *name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -120,6 +120,11 @@ static void req_server (void *pParm)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ATM never reached, just a placeholder */
|
||||
cantProceed("Unreachable. Perpetual thread.");
|
||||
|
||||
taskwdRemove(0);
|
||||
}
|
||||
|
||||
static
|
||||
@ -585,8 +590,7 @@ void rsrv_init (void)
|
||||
errlogPrintf ( "cas " ERL_WARNING ": reachable with UDP unicast (a host's IP in EPICS_CA_ADDR_LIST)\n" );
|
||||
}
|
||||
|
||||
epicsSnprintf(buf, sizeof(buf)-1u, "%u", ca_server_port);
|
||||
buf[sizeof(buf)-1u] = '\0';
|
||||
epicsSnprintf(buf, sizeof(buf), "%u", ca_server_port);
|
||||
epicsEnvSet("RSRV_SERVER_PORT", buf);
|
||||
}
|
||||
|
||||
@ -748,6 +752,7 @@ void rsrv_init (void)
|
||||
if(!havesometcp)
|
||||
cantProceed("CAS: No TCP server started\n");
|
||||
}
|
||||
free(socks);
|
||||
|
||||
/* servers list is considered read-only from this point */
|
||||
|
||||
|
@ -98,13 +98,10 @@ static void clean_addrq(struct client *client)
|
||||
}
|
||||
epicsMutexUnlock ( client->chanListLock );
|
||||
|
||||
# ifdef DEBUG
|
||||
if(ndelete){
|
||||
if (CASDEBUG>1 && ndelete){
|
||||
epicsPrintf ("CAS: %d CA channels have expired after %f sec\n",
|
||||
ndelete, maxdelay);
|
||||
}
|
||||
# endif
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -129,7 +129,11 @@ void rsrv_online_notify_task(void *pParm)
|
||||
}
|
||||
}
|
||||
|
||||
/* ATM never reached, just a placeholder */
|
||||
cantProceed("Unreachable. Perpetual thread.");
|
||||
|
||||
free(lastError);
|
||||
taskwdRemove(0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -36,8 +36,6 @@
|
||||
#include "epicsExport.h"
|
||||
|
||||
|
||||
typedef long (*FASTCONVERT)();
|
||||
|
||||
typedef struct calc_link {
|
||||
jlink jlink; /* embedded object */
|
||||
int nArgs;
|
||||
@ -558,7 +556,7 @@ static long lnkCalc_getValue(struct link *plink, short dbrType, void *pbuffer,
|
||||
dbCommon *prec = plink->precord;
|
||||
int i;
|
||||
long status;
|
||||
FASTCONVERT conv;
|
||||
FASTCONVERTFUNC conv;
|
||||
|
||||
if(INVALID_DB_REQ(dbrType))
|
||||
return S_db_badDbrtype;
|
||||
@ -638,7 +636,7 @@ static long lnkCalc_putValue(struct link *plink, short dbrType,
|
||||
dbCommon *prec = plink->precord;
|
||||
int i;
|
||||
long status;
|
||||
FASTCONVERT conv;
|
||||
FASTCONVERTFUNC conv;
|
||||
|
||||
if(INVALID_DB_REQ(dbrType))
|
||||
return S_db_badDbrtype;
|
||||
|
@ -23,8 +23,6 @@
|
||||
#include "epicsExport.h"
|
||||
|
||||
|
||||
typedef long (*FASTCONVERT)();
|
||||
|
||||
typedef struct const_link {
|
||||
jlink jlink; /* embedded object */
|
||||
int nElems;
|
||||
@ -458,7 +456,7 @@ static long lnkConst_loadArray(struct link *plink, short dbrType, void *pbuffer,
|
||||
short dbrSize;
|
||||
char *pdest = pbuffer;
|
||||
int nElems = clink->nElems;
|
||||
FASTCONVERT conv;
|
||||
FASTCONVERTFUNC conv;
|
||||
long status;
|
||||
|
||||
if(INVALID_DB_REQ(dbrType))
|
||||
@ -495,9 +493,11 @@ static long lnkConst_loadArray(struct link *plink, short dbrType, void *pbuffer,
|
||||
}
|
||||
else {
|
||||
/* Long string conversion */
|
||||
strncpy(pbuffer, clink->value.scalar_string, *pnReq);
|
||||
((char *)pbuffer)[*pnReq] = 0;
|
||||
nElems = strlen(pbuffer) + 1;
|
||||
if (*pnReq > 0) {
|
||||
strncpy(pbuffer, clink->value.scalar_string, *pnReq);
|
||||
((char *)pbuffer)[*pnReq - 1] = 0;
|
||||
nElems = strlen(pbuffer) + 1;
|
||||
}
|
||||
status = 0;
|
||||
}
|
||||
break;
|
||||
|
@ -34,8 +34,6 @@
|
||||
#include "epicsExport.h"
|
||||
|
||||
|
||||
typedef long (*FASTCONVERT)();
|
||||
|
||||
typedef struct state_link {
|
||||
jlink jlink; /* embedded object */
|
||||
char *name;
|
||||
@ -143,7 +141,7 @@ static long lnkState_getValue(struct link *plink, short dbrType, void *pbuffer,
|
||||
{
|
||||
state_link *slink = CONTAINER(plink->value.json.jlink,
|
||||
struct state_link, jlink);
|
||||
FASTCONVERT conv;
|
||||
FASTCONVERTFUNC conv;
|
||||
|
||||
if(INVALID_DB_REQ(dbrType))
|
||||
return S_db_badDbrtype;
|
||||
|
@ -16,7 +16,7 @@ has a number of additional features:
|
||||
|
||||
=item *
|
||||
|
||||
It provides 20 different input and output fields which can hold array or
|
||||
It provides 21 different input and output fields which can hold array or
|
||||
scalar values.
|
||||
The types and array capacities of these are user configurable, and they all
|
||||
have an associated input or output link.
|
||||
|
@ -1160,7 +1160,7 @@ See next section.
|
||||
|
||||
=head2 C<special>
|
||||
|
||||
This is called id CALC or OCAL is changed. C<special> calls postfix.
|
||||
This is called if CALC or OCAL is changed. C<special> calls postfix.
|
||||
|
||||
=head2 C<get_units>
|
||||
|
||||
|
@ -149,13 +149,16 @@ static int compare(const void *arg1, const void *arg2)
|
||||
else return 1;
|
||||
}
|
||||
|
||||
#define min(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
static int compress_array(compressRecord *prec,
|
||||
double *psource, int no_elements)
|
||||
{
|
||||
epicsInt32 i,j;
|
||||
epicsInt32 j;
|
||||
epicsInt32 n, nnew;
|
||||
epicsInt32 nsam = prec->nsam;
|
||||
double value;
|
||||
epicsUInt32 samples_written = 0;
|
||||
double value = 0.0;
|
||||
|
||||
/* skip out of limit data */
|
||||
if (prec->ilil < prec->ihil) {
|
||||
@ -167,61 +170,54 @@ static int compress_array(compressRecord *prec,
|
||||
}
|
||||
if (prec->n <= 0)
|
||||
prec->n = 1;
|
||||
if (no_elements < prec->n && prec->pbuf != menuYesNoYES)
|
||||
return 1; /*dont do anything*/
|
||||
n = no_elements;
|
||||
n = prec->n;
|
||||
|
||||
/* determine number of samples to take */
|
||||
if (no_elements < nsam * n)
|
||||
nnew = (no_elements / n);
|
||||
else nnew = nsam;
|
||||
nnew = min(no_elements, nsam * n);
|
||||
|
||||
/* compress according to specified algorithm */
|
||||
switch (prec->alg){
|
||||
case compressALG_N_to_1_Low_Value:
|
||||
/* compress N to 1 keeping the lowest value */
|
||||
for (i = 0; i < nnew; i++) {
|
||||
while (nnew > 0)
|
||||
{
|
||||
if (nnew < n && prec->pbuf != menuYesNoYES)
|
||||
break;
|
||||
|
||||
n = min(n, nnew);
|
||||
switch (prec->alg)
|
||||
{
|
||||
case compressALG_N_to_1_Low_Value:
|
||||
value = *psource++;
|
||||
for (j = 1; j < n; j++, psource++) {
|
||||
for (j = 1; j < n; j++, psource++)
|
||||
{
|
||||
if (value > *psource)
|
||||
value = *psource;
|
||||
}
|
||||
put_value(prec, &value, 1);
|
||||
}
|
||||
break;
|
||||
case compressALG_N_to_1_High_Value:
|
||||
/* compress N to 1 keeping the highest value */
|
||||
for (i = 0; i < nnew; i++){
|
||||
break;
|
||||
case compressALG_N_to_1_High_Value:
|
||||
value = *psource++;
|
||||
for (j = 1; j < n; j++, psource++) {
|
||||
for (j = 1; j < n; j++, psource++)
|
||||
{
|
||||
if (value < *psource)
|
||||
value = *psource;
|
||||
}
|
||||
put_value(prec, &value, 1);
|
||||
}
|
||||
break;
|
||||
case compressALG_N_to_1_Average:
|
||||
/* compress N to 1 keeping the average value */
|
||||
for (i = 0; i < nnew; i++) {
|
||||
value = 0;
|
||||
for (j = 0; j < n; j++, psource++)
|
||||
break;
|
||||
case compressALG_N_to_1_Average:
|
||||
value = *psource++;
|
||||
for (j = 1; j < n; j++, psource++)
|
||||
{
|
||||
value += *psource;
|
||||
value /= n;
|
||||
put_value(prec, &value, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case compressALG_N_to_1_Median:
|
||||
/* compress N to 1 keeping the median value */
|
||||
/* note: sorts source array (OK; it's a work pointer) */
|
||||
for (i = 0; i < nnew; i++, psource += nnew) {
|
||||
}
|
||||
value = value / n;
|
||||
break;
|
||||
case compressALG_N_to_1_Median:
|
||||
/* note: sorts source array (OK; it's a work pointer) */
|
||||
qsort(psource, n, sizeof(double), compare);
|
||||
value = psource[n / 2];
|
||||
put_value(prec, &value, 1);
|
||||
psource += n;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
nnew -= n;
|
||||
put_value(prec, &value, 1);
|
||||
samples_written++;
|
||||
}
|
||||
return 0;
|
||||
return (samples_written == 0);
|
||||
}
|
||||
|
||||
static int array_average(compressRecord *prec,
|
||||
|
@ -91,10 +91,10 @@ The BPTR field contains a pointer to the unsigned long array of frequency
|
||||
values. The VAL field references this array as well. However, the BPTR field is
|
||||
not accessible at run-time.
|
||||
|
||||
The MCNT field keeps counts the number of signal counts since the last monitor
|
||||
The MCNT field keeps the number of signal counts since the last monitor
|
||||
was invoked.
|
||||
|
||||
The collections controls field (CMD) is a menu field with five choices:
|
||||
The collections controls field (CMD) is a menu field with four choices:
|
||||
|
||||
=menu histogramCMD
|
||||
|
||||
@ -110,8 +110,6 @@ array. Unlike C<Read>, it doesn't clear the array first.
|
||||
|
||||
The C<Stop> command disables the reading of signal values into the array.
|
||||
|
||||
The C<Setup> command waits until the C<start> or C<read> command has been issued
|
||||
to start counting.
|
||||
|
||||
The CSTA or collections status field implements the CMD field choices by
|
||||
enabling or disabling the reading of values into the histogram array. While
|
||||
|
@ -49,6 +49,9 @@ static long init_record(struct dbCommon *pcommon, int pass)
|
||||
if (sizv < 16) {
|
||||
sizv = 16; /* Enforce a minimum size for the VAL field */
|
||||
prec->sizv = sizv;
|
||||
} else if (sizv > 0x7fff) {
|
||||
sizv = 0x7fff; /* SIZV is unsigned, but dbAddr::field_size is signed */
|
||||
prec->sizv = sizv;
|
||||
}
|
||||
|
||||
prec->val = callocMustSucceed(1, sizv, "lsi::init_record");
|
||||
|
@ -9,7 +9,7 @@
|
||||
=title Long String Input Record (lsi)
|
||||
|
||||
The long string input record is used to retrieve an arbitrary ASCII string with
|
||||
a maximum length of 65535 characters.
|
||||
a maximum length of 32767 characters.
|
||||
|
||||
This record type was included in base.dbd beginning with epics-base 3.15.0.2 .
|
||||
|
||||
@ -36,7 +36,7 @@ from. It can be a database or channel access link, or a constant. If constant,
|
||||
the VAL field is initialized with the constant and can be changed via dbPuts.
|
||||
Otherwise, the string is read from the specified location each time the record
|
||||
is processed and placed in the VAL field. The maximum number of characters in
|
||||
VAL is given by SIZV, and cannot be larger than 65535. In addition, the
|
||||
VAL is given by SIZV, and cannot be larger than 32767. In addition, the
|
||||
appropriate device support module must be entered into the DTYP field.
|
||||
|
||||
=fields VAL, OVAL, SIZV, INP, DTYP
|
||||
|
@ -53,6 +53,9 @@ static long init_record(struct dbCommon *pcommon, int pass)
|
||||
if (sizv < 16) {
|
||||
sizv = 16; /* Enforce a minimum size for the VAL field */
|
||||
prec->sizv = sizv;
|
||||
} else if (sizv > 0x7fff) {
|
||||
sizv = 0x7fff; /* SIZV is unsigned, but dbAddr::field_size is signed */
|
||||
prec->sizv = sizv;
|
||||
}
|
||||
|
||||
prec->val = callocMustSucceed(1, sizv, "lso::init_record");
|
||||
|
@ -9,7 +9,7 @@
|
||||
=title Long String Output Record (lso)
|
||||
|
||||
The long string output record is used to write an arbitrary ASCII string with a
|
||||
maximum length of 65535 characters.
|
||||
maximum length of 32767 characters.
|
||||
|
||||
This record type was included in base.dbd beginning with epics-base 3.15.0.2 .
|
||||
|
||||
@ -41,7 +41,7 @@ C<supervisory> is specified, DOL is ignored, the current value of VAL is
|
||||
written, and VAL can be changed externally via dbPuts at run-time.
|
||||
|
||||
The maximum number of characters in VAL is given by SIZV, and cannot be larger
|
||||
than 65535.
|
||||
than 32767.
|
||||
|
||||
DOL can also be a constant instead of a link, in which case VAL is initialized
|
||||
to the constant value. Most simple string constants are likely to be interpreted
|
||||
|
@ -337,6 +337,9 @@ static long init_record(struct dbCommon *pcommon, int pass)
|
||||
if (sizv < 16) {
|
||||
sizv = 16; /* Enforce a minimum size for the VAL field */
|
||||
prec->sizv = sizv;
|
||||
} else if (sizv > 0x7fff) {
|
||||
sizv = 0x7fff; /* SIZV is unsigned, but dbAddr::field_size is signed */
|
||||
prec->sizv = sizv;
|
||||
}
|
||||
|
||||
prec->val = callocMustSucceed(1, sizv, "printf::init_record");
|
||||
|
@ -152,7 +152,7 @@ Specification|https://docs.epics-controls.org/en/latest/guides/EPICS_Process_Dat
|
||||
for information on specifying links.
|
||||
|
||||
The formatted string is written to the VAL field. The maximum number of
|
||||
characters in VAL is given by SIZV, and cannot be larger than 65535. The LEN
|
||||
characters in VAL is given by SIZV, and cannot be larger than 32767. The LEN
|
||||
field contains the length of the formatted string in the VAL field.
|
||||
|
||||
=fields FMT, INP0, INP1, INP2, INP3, INP4, INP5, INP6, INP7, INP8, INP9, VAL, SIZV, LEN
|
||||
|
@ -17,10 +17,12 @@
|
||||
|
||||
#include <epicsGetopt.h>
|
||||
#include "registryFunction.h"
|
||||
#include "errlog.h"
|
||||
#include "epicsThread.h"
|
||||
#include "epicsExit.h"
|
||||
#include "epicsStdio.h"
|
||||
#include "epicsString.h"
|
||||
#include "errlog.h"
|
||||
#include "dbStaticLib.h"
|
||||
#include "subRecord.h"
|
||||
#include "dbAccess.h"
|
||||
@ -92,7 +94,7 @@ void usage(const char *arg0, const std::string& base_dbd) {
|
||||
"interactive IOC shell.\n"
|
||||
"\n"
|
||||
"Compiled-in path to softIoc.dbd is:\n"
|
||||
"\t"<<base_dbd.c_str()<<"\n";
|
||||
"\t"<<base_dbd.c_str()<<std::endl;
|
||||
}
|
||||
|
||||
void errIf(int ret, const std::string& msg)
|
||||
@ -239,7 +241,9 @@ int main(int argc, char *argv[])
|
||||
if (loadedDb) {
|
||||
if (verbose)
|
||||
std::cout<<"iocInit()\n";
|
||||
iocInit();
|
||||
if(iocInit()) {
|
||||
std::cerr<<ERL_ERROR " during iocInit()"<<std::endl;
|
||||
}
|
||||
epicsThreadSleep(0.2);
|
||||
}
|
||||
|
||||
@ -270,7 +274,8 @@ int main(int argc, char *argv[])
|
||||
return 0;
|
||||
|
||||
}catch(std::exception& e){
|
||||
std::cerr<<"Error: "<<e.what()<<"\n";
|
||||
errlogFlush();
|
||||
std::cerr<<ERL_ERROR ": "<<e.what()<<"\n";
|
||||
epicsExit(2);
|
||||
return 2;
|
||||
}
|
||||
|
@ -597,8 +597,12 @@ void testJLink(void)
|
||||
testNumZ(6);
|
||||
|
||||
testdbPutFieldOk("j1.INP", DBF_STRING, "{\"z\":{\"good\":4}}");
|
||||
testdbPutFieldOk("j1.PHAS", DBF_LONG, 0);
|
||||
testdbPutFieldOk("j1.OUTP", DBF_STRING, "{z:{good:99}}");
|
||||
testdbPutFieldOk("j1.PROC", DBF_LONG, 1);
|
||||
testdbGetFieldEqual("j1.VAL", DBF_LONG, 4);
|
||||
testdbGetFieldEqual("j1.PHAS", DBF_LONG, 4);
|
||||
testdbPutFieldOk("j1.OUTP", DBF_STRING, "");
|
||||
|
||||
testdbPutFieldOk("j2.TSEL", DBF_STRING, "{'z':{good:0}}");
|
||||
testdbPutFieldOk("j2.PROC", DBF_LONG, 1);
|
||||
@ -701,7 +705,7 @@ void testTSEL(void)
|
||||
|
||||
MAIN(dbPutLinkTest)
|
||||
{
|
||||
testPlan(348);
|
||||
testPlan(352);
|
||||
testLinkParse();
|
||||
testLinkFailParse();
|
||||
testCADBSet();
|
||||
|
@ -59,6 +59,9 @@ static unsigned int nrecords;
|
||||
|
||||
#define MAXLOCK 20
|
||||
|
||||
/* Verbose output from test if you set this to 1 */
|
||||
#define MULTI_DIAG 0
|
||||
|
||||
static dbCommon **precords;
|
||||
|
||||
typedef struct {
|
||||
@ -120,6 +123,9 @@ void doMulti(workerPriv *p)
|
||||
}
|
||||
dbScanUnlockMany(locker);
|
||||
|
||||
if (MULTI_DIAG)
|
||||
testDiag("sum = %d", sum);
|
||||
|
||||
dbLockerFree(locker);
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,6 @@ void z_open(struct link *plink)
|
||||
if(priv->isopen)
|
||||
testDiag("lsetZ re-open");
|
||||
priv->isopen = 1;
|
||||
testDiag("Open jlinkz %p", priv);
|
||||
}
|
||||
|
||||
static
|
||||
@ -50,8 +49,6 @@ void z_remove(struct dbLocker *locker, struct link *plink)
|
||||
|
||||
epicsMutexUnlock(priv->lock);
|
||||
|
||||
testDiag("Remove/free jlinkz %p", priv);
|
||||
|
||||
epicsAtomicDecrIntT(&numzalloc);
|
||||
|
||||
epicsMutexDestroy(priv->lock);
|
||||
@ -83,13 +80,13 @@ long z_getval(struct link *plink, short dbrType, void *pbuffer,
|
||||
long *pnRequest)
|
||||
{
|
||||
long ret;
|
||||
long (*pconv)(const epicsInt32 *, void *, const dbAddr *) = dbFastGetConvertRoutine[DBF_LONG][dbrType];
|
||||
FASTCONVERTFUNC pconv = dbFastGetConvertRoutine[DBF_LONG][dbrType];
|
||||
zpriv *priv = CONTAINER(plink->value.json.jlink, zpriv, base);
|
||||
|
||||
if(pnRequest && *pnRequest==0) return 0;
|
||||
|
||||
epicsMutexLock(priv->lock);
|
||||
ret = (*pconv)(&priv->value, pbuffer, NULL);
|
||||
ret = pconv(&priv->value, pbuffer, NULL);
|
||||
epicsMutexUnlock(priv->lock);
|
||||
if(ret==0 && pnRequest) *pnRequest = 1;
|
||||
return ret;
|
||||
@ -118,19 +115,20 @@ long z_putval(struct link *plink, short dbrType,
|
||||
const void *pbuffer, long nRequest)
|
||||
{
|
||||
long ret;
|
||||
long (*pconv)(epicsInt32 *, const void *, const dbAddr *);
|
||||
zpriv *priv = CONTAINER(plink->value.json.jlink, zpriv, base);
|
||||
FASTCONVERTFUNC pconv;
|
||||
|
||||
if(INVALID_DB_REQ(dbrType))
|
||||
return S_db_badDbrtype;
|
||||
|
||||
pconv = dbFastPutConvertRoutine[DBF_LONG][dbrType];
|
||||
pconv = dbFastPutConvertRoutine[dbrType][DBF_LONG];
|
||||
|
||||
if(nRequest==0) return 0;
|
||||
|
||||
epicsMutexLock(priv->lock);
|
||||
ret = (*pconv)(&priv->value, pbuffer, NULL);
|
||||
ret = pconv(pbuffer, &priv->value, NULL);
|
||||
epicsMutexUnlock(priv->lock);
|
||||
plink->precord->phas = priv->value;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -168,8 +166,6 @@ jlink* z_alloc(short dbfType)
|
||||
|
||||
epicsAtomicIncrIntT(&numzalloc);
|
||||
|
||||
testDiag("Alloc jlinkz %p", priv);
|
||||
|
||||
return &priv->base;
|
||||
fail:
|
||||
if(priv && priv->lock) epicsMutexDestroy(priv->lock);
|
||||
@ -185,8 +181,6 @@ void z_free(jlink *pj)
|
||||
if(priv->isopen)
|
||||
testDiag("lsetZ jlink free after open()");
|
||||
|
||||
testDiag("Free jlinkz %p", priv);
|
||||
|
||||
epicsAtomicDecrIntT(&numzalloc);
|
||||
|
||||
epicsMutexDestroy(priv->lock);
|
||||
|
@ -71,6 +71,7 @@ static long process(struct dbCommon *pcommon)
|
||||
ret = (*xset->process)(prec);
|
||||
monitor(prec);
|
||||
recGblGetTimeStamp(prec);
|
||||
dbPutLink(&prec->outp, DBR_LONG, &prec->val, 1);
|
||||
recGblFwdLink(prec);
|
||||
prec->pact = FALSE;
|
||||
return ret;
|
||||
|
@ -49,6 +49,9 @@ recordtype(x) {
|
||||
prompt("Input Link")
|
||||
special(SPC_MOD)
|
||||
}
|
||||
field(OUTP, DBF_OUTLINK) {
|
||||
prompt("Output Link")
|
||||
}
|
||||
field(CLBK, DBF_NOACCESS) {
|
||||
prompt("Processing callback")
|
||||
special(SPC_NOMOD)
|
||||
|
@ -469,6 +469,38 @@ testNto1Average(void) {
|
||||
testdbCleanup();
|
||||
}
|
||||
|
||||
void testNto2Average(void) {
|
||||
DBADDR wfaddr, caddr;
|
||||
|
||||
testDiag("Test N to 1 Average, NSAM=2, N=2");
|
||||
|
||||
testdbPrepare();
|
||||
|
||||
testdbReadDatabase("recTestIoc.dbd", NULL, NULL);
|
||||
|
||||
recTestIoc_registerRecordDeviceDriver(pdbbase);
|
||||
|
||||
testdbReadDatabase("compressTest.db", NULL, "INP=wf,ALG=N to 1 Average,BALG=FIFO Buffer,NSAM=2,N=2");
|
||||
|
||||
eltc(0);
|
||||
testIocInitOk();
|
||||
eltc(1);
|
||||
|
||||
fetchRecordOrDie("wf", wfaddr);
|
||||
fetchRecordOrDie("comp", caddr);
|
||||
|
||||
writeToWaveform(&wfaddr, 4, 1., 2., 3., 4.);
|
||||
|
||||
dbScanLock(caddr.precord);
|
||||
dbProcess(caddr.precord);
|
||||
|
||||
checkArrD("comp", 2, 1.5, 3.5, 0, 0);
|
||||
dbScanUnlock(caddr.precord);
|
||||
|
||||
testIocShutdownOk();
|
||||
testdbCleanup();
|
||||
}
|
||||
|
||||
void
|
||||
testNto1AveragePartial(void) {
|
||||
double buf = 0.0;
|
||||
@ -517,6 +549,36 @@ testNto1AveragePartial(void) {
|
||||
testdbCleanup();
|
||||
}
|
||||
|
||||
void
|
||||
testNtoMPartial(void) {
|
||||
DBADDR wfaddr, caddr;
|
||||
|
||||
testDiag("Test Average, N to M, Partial");
|
||||
|
||||
testdbPrepare();
|
||||
testdbReadDatabase("recTestIoc.dbd", NULL, NULL);
|
||||
recTestIoc_registerRecordDeviceDriver(pdbbase);
|
||||
testdbReadDatabase("compressTest.db", NULL, "INP=wf,ALG=N to 1 Average,BALG=FIFO Buffer,NSAM=2,N=3,PBUF=YES");
|
||||
|
||||
eltc(0);
|
||||
testIocInitOk();
|
||||
eltc(1);
|
||||
|
||||
fetchRecordOrDie("wf", wfaddr);
|
||||
fetchRecordOrDie("comp", caddr);
|
||||
|
||||
writeToWaveform(&wfaddr, 4, 1., 2., 3., 4.);
|
||||
|
||||
dbScanLock(caddr.precord);
|
||||
dbProcess(caddr.precord);
|
||||
|
||||
checkArrD("comp", 2, 2.0, 4.0, 0, 0);
|
||||
dbScanUnlock(caddr.precord);
|
||||
|
||||
testIocShutdownOk();
|
||||
testdbCleanup();
|
||||
}
|
||||
|
||||
void
|
||||
testNto1LowValue(void) {
|
||||
double buf = 0.0;
|
||||
@ -634,12 +696,14 @@ testAIAveragePartial(void) {
|
||||
|
||||
MAIN(compressTest)
|
||||
{
|
||||
testPlan(132);
|
||||
testPlan(134);
|
||||
testFIFOCirc();
|
||||
testLIFOCirc();
|
||||
testArrayAverage();
|
||||
testNto1Average();
|
||||
testNto2Average();
|
||||
testNto1AveragePartial();
|
||||
testNtoMPartial();
|
||||
testAIAveragePartial();
|
||||
testNto1LowValue();
|
||||
return testDone();
|
||||
|
@ -522,7 +522,7 @@ void errPrintf(long status, const char *pFileName, int lineno,
|
||||
errSymLookup(status, name, sizeof(name));
|
||||
}
|
||||
|
||||
nchar = epicsSnprintf(buf, pvt.maxMsgSize, "%s%sfilename=\"%s\" line number=%d",
|
||||
nchar = epicsSnprintf(buf, pvt.maxMsgSize, "%s%sfilename=\"%s\" line number=%d ",
|
||||
name, status ? " " : "", pFileName, lineno);
|
||||
if(nchar < pvt.maxMsgSize)
|
||||
nchar += epicsVsnprintf(buf + nchar, pvt.maxMsgSize - nchar, pformat, pvar);
|
||||
|
@ -1437,13 +1437,16 @@ static void varCallFunc(const iocshArgBuf *args)
|
||||
varHandler(v->pVarDef, NULL);
|
||||
found = 1;
|
||||
}
|
||||
if (!found && name != NULL)
|
||||
if (!found && name != NULL) {
|
||||
fprintf(epicsGetStderr(), ANSI_RED("No var matching") " %s found.\n", name);
|
||||
iocshSetError(1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
v = (iocshVariable *)registryFind(iocshVarID, args[0].sval);
|
||||
if (v == NULL) {
|
||||
fprintf(epicsGetStderr(), "Var %s " ANSI_RED("not found.") "\n", name);
|
||||
iocshSetError(1);
|
||||
}
|
||||
else {
|
||||
varHandler(v->pVarDef, value);
|
||||
@ -1460,7 +1463,7 @@ static const iocshFuncDef iocshCmdFuncDef = {"iocshCmd",1,iocshCmdArgs,
|
||||
" from vxWorks or RTEMS startup script (or command line)\n"};
|
||||
static void iocshCmdCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
iocshCmd(args[0].sval);
|
||||
iocshSetError(iocshCmd(args[0].sval));
|
||||
}
|
||||
|
||||
/* iocshLoad */
|
||||
@ -1472,7 +1475,7 @@ static const iocshFuncDef iocshLoadFuncDef = {"iocshLoad",2,iocshLoadArgs,
|
||||
" * (optional) replace macros within the file with provided values\n"};
|
||||
static void iocshLoadCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
iocshLoad(args[0].sval, args[1].sval);
|
||||
iocshSetError(iocshLoad(args[0].sval, args[1].sval));
|
||||
}
|
||||
|
||||
/* iocshRun */
|
||||
@ -1485,7 +1488,7 @@ static const iocshFuncDef iocshRunFuncDef = {"iocshRun",2,iocshRunArgs,
|
||||
" from vxWorks or RTEMS startup script (or command line)\n"};
|
||||
static void iocshRunCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
iocshRun(args[0].sval, args[1].sval);
|
||||
iocshSetError(iocshRun(args[0].sval, args[1].sval));
|
||||
}
|
||||
|
||||
/* on */
|
||||
|
Submodule modules/pvAccess updated: 7746ea3c6c...f1268adb8e
Submodule modules/pvDatabase updated: d18e0c913a...f207e512d6
Reference in New Issue
Block a user