Compare commits
32 Commits
R7.0.4.1
...
merge_7.0.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8fd36d8eef | ||
|
|
baced535e3 | ||
|
|
be7c6a0a0a | ||
|
|
14476391c0 | ||
|
|
223b292c33 | ||
|
|
68121ec907 | ||
|
|
228ad79b7a | ||
|
|
bbc0a56d2b | ||
|
|
9726b9efc9 | ||
|
|
3e891a12ff | ||
|
|
22ee229aca | ||
|
|
1ae3bd6c70 | ||
|
|
cbba08b1ef | ||
|
|
53044571fb | ||
|
|
f8df3473ab | ||
|
|
e8bee54531 | ||
|
|
0cae0db98b | ||
|
|
df6981ceae | ||
|
|
11984633dc | ||
|
|
051ba20fe1 | ||
|
|
d6cf29e942 | ||
|
|
bdd41cca13 | ||
|
|
e40970bd5e | ||
|
|
9e3d5d52ab | ||
|
|
2c389a90d1 | ||
|
|
8d98387245 | ||
|
|
b36e5262c7 | ||
|
|
79d7ac9315 | ||
|
|
03c4fe8a8d | ||
|
|
ad3728d00d | ||
|
|
c465354c67 | ||
| cc616371b1 |
@@ -1,6 +1,12 @@
|
||||
# .appveyor.yml for use with EPICS Base ci-scripts
|
||||
# (see: https://github.com/epics-base/ci-scripts)
|
||||
|
||||
# branches to build
|
||||
branches:
|
||||
# whitelist
|
||||
only:
|
||||
- 7.0
|
||||
|
||||
# Version format
|
||||
version: base-{branch}-{build}
|
||||
|
||||
|
||||
102
.tools/adjustver.py
Executable file
102
.tools/adjustver.py
Executable file
@@ -0,0 +1,102 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import logging
|
||||
import sys
|
||||
import re
|
||||
from io import StringIO
|
||||
|
||||
_log = logging.getLogger(__name__)
|
||||
|
||||
def main(args):
|
||||
logging.basicConfig(level=args.level)
|
||||
|
||||
if args.dev is True:
|
||||
actions=[
|
||||
('DEVELOPMENT_FLAG', '1'),
|
||||
('DEV_SNAPSHOT', '-DEV'),
|
||||
]
|
||||
|
||||
elif args.dev is False:
|
||||
actions=[
|
||||
('DEVELOPMENT_FLAG', '0'),
|
||||
('DEV_SNAPSHOT', ''),
|
||||
]
|
||||
|
||||
elif args.version:
|
||||
M=re.match(r'R?(\d+).(\d+).(\d+)(?:.(\d+))?(-.*)?', args.version)
|
||||
actions=[
|
||||
('SITE_VERSION', None),
|
||||
('SHORT_VERSION', None),
|
||||
|
||||
('MINOR_VERSION', M[2]),
|
||||
('REVISION', M[2]),
|
||||
|
||||
('MODIFICATION', M[3]),
|
||||
('MAINTENANCE_VERSION', M[3]),
|
||||
|
||||
('PATCH_LEVEL', M[4] or '0'),
|
||||
|
||||
('DEVELOPMENT_FLAG', '1' if (M[5] or '').upper().endswith('-DEV') else '0'),
|
||||
('DEV_SNAPSHOT', M[5] or ''),
|
||||
|
||||
('MAJOR_VERSION', M[1]),
|
||||
('VERSION', M[1]), # plain _VERSION must be last to resolve ambiguity
|
||||
]
|
||||
|
||||
elif args.dry_run:
|
||||
_log.debug('Print existing')
|
||||
for fname in args.conf:
|
||||
print('# ', fname)
|
||||
with open(fname, 'r') as F:
|
||||
sys.stdout.write(F.read())
|
||||
return
|
||||
|
||||
else:
|
||||
print('One of --version, --release, --dev, or --dry-run is required')
|
||||
sys.exit(1)
|
||||
|
||||
for name, val in actions:
|
||||
_log.debug('Pattern "%s" -> "%s"', name, val)
|
||||
|
||||
for fname in args.conf:
|
||||
OUT=StringIO()
|
||||
|
||||
with open(fname, 'r') as F:
|
||||
for line in F:
|
||||
_log.debug('Line: %s', repr(line))
|
||||
for name, val in actions:
|
||||
M = re.match(r'(\s*[A-Z_]+' + name + r'\s*=[\t ]*)(\S*)(\s*)', line)
|
||||
if M and val is None:
|
||||
_log.debug('Ignore')
|
||||
OUT.write(line)
|
||||
break
|
||||
elif M:
|
||||
_log.debug(' Match %s -> %s', M.re.pattern, M.groups())
|
||||
OUT.write(M[1]+val+M[3])
|
||||
break
|
||||
else:
|
||||
_log.debug('No match')
|
||||
OUT.write(line)
|
||||
|
||||
if args.dry_run:
|
||||
print('# ', fname)
|
||||
print(OUT.getvalue())
|
||||
else:
|
||||
with open(fname, 'w') as F:
|
||||
F.write(OUT.getvalue())
|
||||
|
||||
def getargs():
|
||||
from argparse import ArgumentParser
|
||||
P = ArgumentParser()
|
||||
P.add_argument('-n','--dry-run', action='store_true', default=False)
|
||||
P.add_argument('-d','--debug', dest='level', action='store_const',
|
||||
const=logging.DEBUG, default=logging.INFO)
|
||||
P.add_argument('-V', '--version', help='A version in R1.2.3-xyz or 1.2.3 form')
|
||||
P.add_argument('-D', '--dev', action='store_true', default=None)
|
||||
P.add_argument('-R', '--release', dest='dev', action='store_false')
|
||||
P.add_argument('conf', nargs='+',
|
||||
help='A configure/CONFIG_*_VERSION file name')
|
||||
return P
|
||||
|
||||
if __name__=='__main__':
|
||||
main(getargs().parse_args())
|
||||
@@ -52,11 +52,11 @@ EPICS_MODIFICATION = 4
|
||||
|
||||
# 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)
|
||||
EPICS_DEV_SNAPSHOT=
|
||||
EPICS_DEV_SNAPSHOT=-DEV
|
||||
|
||||
# No changes should be needed below here
|
||||
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
EPICS_CA_MAJOR_VERSION = 4
|
||||
EPICS_CA_MINOR_VERSION = 13
|
||||
EPICS_CA_MAINTENANCE_VERSION = 7
|
||||
EPICS_CA_MAINTENANCE_VERSION = 8
|
||||
|
||||
# Development flag, set to zero for release versions
|
||||
|
||||
EPICS_CA_DEVELOPMENT_FLAG = 0
|
||||
EPICS_CA_DEVELOPMENT_FLAG = 1
|
||||
|
||||
# Immediately after a release the MAINTENANCE_VERSION
|
||||
# will be incremented and the DEVELOPMENT_FLAG set to 1
|
||||
|
||||
@@ -24,3 +24,5 @@ MSI3_15 = $(EPICS_DATABASE_HOST_BIN)/msi$(HOSTEXE)
|
||||
|
||||
# Libraries needed to link a basic IOC
|
||||
EPICS_BASE_IOC_LIBS = dbRecStd dbCore ca Com
|
||||
|
||||
HAS_registerAllRecordDeviceDrivers=YES
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
EPICS_DATABASE_MAJOR_VERSION = 3
|
||||
EPICS_DATABASE_MINOR_VERSION = 18
|
||||
EPICS_DATABASE_MAINTENANCE_VERSION = 1
|
||||
EPICS_DATABASE_MAINTENANCE_VERSION = 2
|
||||
|
||||
# Development flag, set to zero for release versions
|
||||
|
||||
EPICS_DATABASE_DEVELOPMENT_FLAG = 0
|
||||
EPICS_DATABASE_DEVELOPMENT_FLAG = 1
|
||||
|
||||
# Immediately after a release the MAINTENANCE_VERSION
|
||||
# will be incremented and the DEVELOPMENT_FLAG set to 1
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
EPICS_LIBCOM_MAJOR_VERSION = 3
|
||||
EPICS_LIBCOM_MINOR_VERSION = 18
|
||||
EPICS_LIBCOM_MAINTENANCE_VERSION = 1
|
||||
EPICS_LIBCOM_MAINTENANCE_VERSION = 2
|
||||
|
||||
# Development flag, set to zero for release versions
|
||||
|
||||
EPICS_LIBCOM_DEVELOPMENT_FLAG = 0
|
||||
EPICS_LIBCOM_DEVELOPMENT_FLAG = 1
|
||||
|
||||
# Immediately after a release the MAINTENANCE_VERSION
|
||||
# will be incremented and the DEVELOPMENT_FLAG set to 1
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
# darwin-x86 (Intel based Apple running OSX)
|
||||
# freebsd-x86 (GNU compiler used for host builds)
|
||||
# freebsd-x86_64 (GNU compiler used for host builds)
|
||||
# linux-aarch64 (GNU compiler used for host builds)
|
||||
# linux-arm (GNU compiler used for host builds)
|
||||
# linux-ppc (GNU compiler used for host builds)
|
||||
# linux-ppc64 (GNU compiler used for host builds)
|
||||
@@ -51,7 +52,6 @@
|
||||
# windows-x64-debug (MS Visual C++ compiler with debug option for host builds)
|
||||
|
||||
|
||||
# EPICS_HOST_ARCH is a required environment variable
|
||||
# Do not set EPICS_HOST_ARCH in this file.
|
||||
# Use base/startup files to set EPICS_HOST_ARCH or
|
||||
# provide EPICS_HOST_ARCH on the GNU make command line.
|
||||
|
||||
@@ -33,7 +33,7 @@ UNINSTALL_DIRS += $(INSTALL_INCLUDE) $(INSTALL_TEMPLATES) $(DIRECTORY_TARGETS)
|
||||
ifneq ($(INSTALL_LOCATION),$(TOP))
|
||||
UNINSTALL_DIRS += $(INSTALL_CONFIG)
|
||||
endif
|
||||
uninstallDirs:
|
||||
uninstallDirs: | clean
|
||||
$(RMDIR) $(UNINSTALL_DIRS)
|
||||
|
||||
# Remove the bin and lib directories if they have no sub-directories
|
||||
@@ -41,12 +41,12 @@ uninstallDirs:
|
||||
EMPTY_INSTALL_DIRS = \
|
||||
$(if $(wildcard $(INSTALL_LOCATION_BIN)/*),,$(INSTALL_LOCATION_BIN)) \
|
||||
$(if $(wildcard $(INSTALL_LOCATION_LIB)/*),,$(INSTALL_LOCATION_LIB))
|
||||
uninstall: archuninstall uninstallDirs
|
||||
uninstall: archuninstall uninstallDirs | clean
|
||||
$(RMDIR) $(EMPTY_INSTALL_DIRS)
|
||||
|
||||
archuninstall: $(addprefix uninstall$(DIVIDER),$(BUILD_ARCHS))
|
||||
|
||||
uninstall$(DIVIDER)%:
|
||||
uninstall$(DIVIDER)%: | clean
|
||||
$(RMDIR) $(addsuffix /$(subst uninstall$(DIVIDER),,$@), \
|
||||
$(INSTALL_LOCATION_BIN) $(INSTALL_LOCATION_LIB))
|
||||
|
||||
|
||||
8
configure/os/CONFIG.linux-aarch64.Common
Normal file
8
configure/os/CONFIG.linux-aarch64.Common
Normal file
@@ -0,0 +1,8 @@
|
||||
# CONFIG.linux-aarch64.Common
|
||||
#
|
||||
# Definitions for linux-aarch64 host builds
|
||||
# Sites may override these definitions in CONFIG_SITE.linux-aarch64.Common
|
||||
#-------------------------------------------------------
|
||||
|
||||
#Include definitions common to unix hosts
|
||||
include $(CONFIG)/os/CONFIG.UnixCommon.Common
|
||||
8
configure/os/CONFIG.linux-aarch64.linux-aarch64
Normal file
8
configure/os/CONFIG.linux-aarch64.linux-aarch64
Normal file
@@ -0,0 +1,8 @@
|
||||
# CONFIG.linux-aarch64.linux-aarch64
|
||||
#
|
||||
# Definitions for native linux-aarch64 builds
|
||||
# Override these definitions in CONFIG_SITE.linux-aarch64.linux-aarch64
|
||||
#-------------------------------------------------------
|
||||
|
||||
# Include common gnu compiler definitions
|
||||
include $(CONFIG)/CONFIG.gnuCommon
|
||||
@@ -16,3 +16,9 @@ COMMANDLINE_LIBRARY = READLINE_NCURSESW
|
||||
|
||||
# No other libraries needed
|
||||
#COMMANDLINE_LIBRARY = READLINE
|
||||
|
||||
|
||||
# WARNING: Variables that are set in $(CONFIG)/CONFIG.gnuCommon cannot be
|
||||
# overridden in this file for native builds, e.g. variables such as
|
||||
# OPT_CFLAGS_YES, WARN_CFLAGS, SHRLIB_LDFLAGS
|
||||
# They must be set in CONFIG_SITE.cygwin-x86.cygwin-x86 instead.
|
||||
|
||||
@@ -11,10 +11,8 @@
|
||||
#LDLIBS_READLINE = -lreadline -lcurses
|
||||
|
||||
|
||||
# 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
|
||||
# WARNING: Variables that are set in $(CONFIG)/CONFIG.gnuCommon cannot be
|
||||
# overridden in this file for native builds, e.g. variables such as
|
||||
# OPT_CFLAGS_YES, WARN_CFLAGS, SHRLIB_LDFLAGS
|
||||
# They must be set in CONFIG_SITE.cygwin-x86_64.cygwin-x86_64 instead.
|
||||
|
||||
|
||||
@@ -30,3 +30,9 @@
|
||||
# Needs -lcurses (older versions)
|
||||
#COMMANDLINE_LIBRARY = READLINE_CURSES
|
||||
|
||||
|
||||
# WARNING: Variables that are set in $(CONFIG)/CONFIG.gnuCommon cannot be
|
||||
# overridden in this file for native builds, e.g. variables such as
|
||||
# OPT_CFLAGS_YES, WARN_CFLAGS, SHRLIB_LDFLAGS
|
||||
# They must be set in CONFIG_SITE.linux-aarch64.linux-aarch64 instead.
|
||||
|
||||
|
||||
@@ -33,3 +33,12 @@ COMMANDLINE_LIBRARY = $(strip $(if $(wildcard \
|
||||
|
||||
# Readline is broken or you don't want use it:
|
||||
#COMMANDLINE_LIBRARY = EPICS
|
||||
|
||||
|
||||
# WARNING: Variables that are set in $(CONFIG)/CONFIG.gnuCommon cannot be
|
||||
# overridden in this file for native builds, e.g. variables such as
|
||||
# OPT_CFLAGS_YES, WARN_CFLAGS, SHRLIB_LDFLAGS
|
||||
# They must be set in CONFIG_SITE.linux-arm.linux-arm instead.
|
||||
|
||||
# Permit access to 64-bit file-systems
|
||||
OP_SYS_CFLAGS += -D_FILE_OFFSET_BITS=64
|
||||
|
||||
@@ -34,22 +34,17 @@ COMMANDLINE_LIBRARY = $(strip $(if $(wildcard \
|
||||
#COMMANDLINE_LIBRARY = EPICS
|
||||
|
||||
|
||||
# WARNING: Variables that are set in $(CONFIG)/CONFIG.gnuCommon cannot be
|
||||
# overridden in this file for native builds, e.g. variables such as
|
||||
# OPT_CFLAGS_YES, WARN_CFLAGS, SHRLIB_LDFLAGS
|
||||
# They must be set in CONFIG_SITE.linux-x86.linux-x86 instead.
|
||||
|
||||
# Permit access to 64-bit file-systems
|
||||
OP_SYS_CFLAGS += -D_FILE_OFFSET_BITS=64
|
||||
|
||||
|
||||
# Uncomment the followings lines to build with CLANG instead of GCC.
|
||||
#
|
||||
#GNU = NO
|
||||
#CMPLR_CLASS = clang
|
||||
#CC = clang
|
||||
#CCC = clang++
|
||||
|
||||
|
||||
# Tune GNU compiler output for a specific 32-bit cpu-type
|
||||
# (e.g. generic, native, i386, i686, pentium2/3/4, prescott, k6, athlon etc.)
|
||||
GNU_TUNE_CFLAGS = -mtune=generic
|
||||
|
||||
|
||||
# Developers using a suitable compiler may enable its address sanitizer:
|
||||
#ENABLE_ASAN = YES
|
||||
|
||||
@@ -34,18 +34,14 @@ COMMANDLINE_LIBRARY = $(strip $(if $(wildcard \
|
||||
#COMMANDLINE_LIBRARY = EPICS
|
||||
|
||||
|
||||
# Uncomment the followings lines to build with CLANG instead of GCC.
|
||||
#
|
||||
#GNU = NO
|
||||
#CMPLR_CLASS = clang
|
||||
#CC = clang
|
||||
#CCC = clang++
|
||||
|
||||
# WARNING: Variables that are set in $(CONFIG)/CONFIG.gnuCommon cannot be
|
||||
# overridden in this file for native builds, e.g. variables such as
|
||||
# OPT_CFLAGS_YES, WARN_CFLAGS, SHRLIB_LDFLAGS
|
||||
# They must be set in CONFIG_SITE.linux-x86_64.linux-x86_64 instead.
|
||||
|
||||
# Tune GNU compiler output for a specific 64-bit cpu-type
|
||||
# (e.g. generic, native, core2, nocona, k8, opteron, athlon64, barcelona etc.)
|
||||
GNU_TUNE_CFLAGS = -mtune=generic
|
||||
|
||||
|
||||
# Developers using a suitable compiler may enable its address sanitizer:
|
||||
#ENABLE_ASAN = YES
|
||||
|
||||
@@ -2,10 +2,9 @@
|
||||
#
|
||||
# Site-specific settings for all linux targets
|
||||
|
||||
# WARNING: Variables that are set in $(CONFIG)/CONFIG.gnuCommon cannot be
|
||||
# overridden in this file for native builds, e.g. variables such as
|
||||
# OPT_CFLAGS_YES, WARN_CFLAGS, SHRLIB_LDFLAGS
|
||||
# They must be set in the host+target specific file instead:
|
||||
# CONFIG_SITE.<linux-arch>.<linux-arch>
|
||||
|
||||
# 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
|
||||
|
||||
@@ -6,3 +6,11 @@
|
||||
# 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
|
||||
|
||||
|
||||
12
configure/os/CONFIG_SITE.linux-aarch64.linux-aarch64
Normal file
12
configure/os/CONFIG_SITE.linux-aarch64.linux-aarch64
Normal file
@@ -0,0 +1,12 @@
|
||||
# CONFIG_SITE.linux-aarch64.linux-aarch64
|
||||
#
|
||||
# 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
|
||||
|
||||
@@ -3,3 +3,17 @@
|
||||
# Site specific definitions for linux-x86 host - linux-x86 target 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
|
||||
|
||||
# Uncomment the followings lines to build with CLANG instead of GCC.
|
||||
#
|
||||
#GNU = NO
|
||||
#CMPLR_CLASS = clang
|
||||
#CC = clang
|
||||
#CCC = clang++
|
||||
|
||||
|
||||
@@ -3,4 +3,17 @@
|
||||
# Site specific definitions for linux-x86_64 host - linux-x86_64 target 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
|
||||
|
||||
# Uncomment the followings lines to build with CLANG instead of GCC.
|
||||
#
|
||||
#GNU = NO
|
||||
#CMPLR_CLASS = clang
|
||||
#CC = clang
|
||||
#CCC = clang++
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Installation Instructions {#install}
|
||||
|
||||
## EPICS Base Release 7.0.3.1
|
||||
## EPICS Base Release 7.0.4.1
|
||||
|
||||
-----
|
||||
|
||||
@@ -237,7 +237,7 @@ Files in the base/startup directory have been provided to help set
|
||||
required path and other environment variables.
|
||||
|
||||
* `EPICS_HOST_ARCH`
|
||||
Before you can build or use EPICS R3.15, the environment variable
|
||||
Before you can build or use this EPICS base, the environment variable
|
||||
`EPICS_HOST_ARCH` must be defined. A perl script EpicsHostArch.pl in
|
||||
the base/startup directory has been provided to help set
|
||||
`EPICS_HOST_ARCH.` You should have `EPICS_HOST_ARCH` set to your
|
||||
@@ -263,7 +263,7 @@ ranlib in your path, and the C compiler may require as and ld in
|
||||
your path. On solaris systems you need uname in your path.
|
||||
|
||||
* `LD_LIBRARY_PATH`
|
||||
R3.15 shared libraries and executables normally contain the full
|
||||
EPICS shared libraries and executables normally contain the full
|
||||
path to any libraries they require. However, if you move the EPICS
|
||||
files or directories from their build-time location then in order
|
||||
for the shared libraries to be found at runtime `LD_LIBRARY_PATH`
|
||||
@@ -336,10 +336,10 @@ A perl tool, makeBaseApp.pl is included in the distribution file. This
|
||||
script will create a sample application that can be built and then
|
||||
executed to try out this release of base.
|
||||
|
||||
Instructions for building and executing the 3.15 example application
|
||||
Instructions for building and executing the EPICS example application
|
||||
can be found in the section "Example Application" of Chapter 2,
|
||||
"Getting Started", in the "IOC Application Developer's Guide" for this
|
||||
release. The "Example IOC Application" section briefly explains how to
|
||||
"Getting Started", in the "EPICS Application Developer's Guide".
|
||||
The "Example IOC Application" section briefly explains how to
|
||||
create and build an example application in a user created <top>
|
||||
directory. It also explains how to run the example application on a
|
||||
vxWorks ioc or as a process on the host system. By running the example
|
||||
|
||||
@@ -17,6 +17,40 @@ should also be read to understand what has changed since earlier releases.
|
||||
|
||||
<!-- Insert new items immediately below here ... -->
|
||||
|
||||
### Add registerAllRecordDeviceDrivers()
|
||||
|
||||
Addition of registerAllRecordDeviceDrivers() as an iocsh function
|
||||
and in iocshRegisterCommon.h. This function uses dynamic lookup with epicsFindSymbol()
|
||||
to perform the same function as a generated \*_registerRecordDeviceDriver() function.
|
||||
This allows dynamic loading/linking of support modules without code generation.
|
||||
|
||||
This feature is not intended for use by IOCs constructed using the standard EPICS application
|
||||
build process and booted from a startup script in an iocBoot subdirectory, although it might
|
||||
work in some of those cases (the IOC's registerRecordDeviceDriver.cpp file is still required
|
||||
to link everything into the executable). It also won't work with some static build
|
||||
configurations or where the symbol table has been stripped from the executable.
|
||||
|
||||
### Using a `{const:"string"}` to initialize an array of `DBF_CHAR`
|
||||
|
||||
It is now possible to use a JSON Const link with a string value to initialize
|
||||
an aai or waveform record that has `FTVL` set to `CHAR` through the INP link.
|
||||
The string length is not limited to 40 characters. This should also work for
|
||||
aSub record inputs similarly configured as long strings.
|
||||
|
||||
```
|
||||
record(waveform, "wf") {
|
||||
field(NELM, 100)
|
||||
field(FTVL, CHAR)
|
||||
field(INP, {const:"This is a waveform and more than 40 characters"})
|
||||
}
|
||||
```
|
||||
|
||||
### RELEASE files may use `undefine`
|
||||
|
||||
GNUmake added the directive `undefine` in version 3.82 to allow variables to
|
||||
be undefined. Support for this has been added to the EPICS Release file parser,
|
||||
so `undefine` can now be used in configure/RELEASE files to unset variables.
|
||||
|
||||
## EPICS Release 7.0.4.1
|
||||
|
||||
### ARM Architecture Changes
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
# Record Reference Documentation {#recordrefmanual}
|
||||
|
||||
The following documentation for the record types and menus include with Base was
|
||||
The documentation below for the record types and menus included with Base was
|
||||
converted from the old EPICS Wiki pages and updated. This list only includes the
|
||||
record types supplied with Base.
|
||||
record types supplied with Base. The first two links below are to an external
|
||||
website where these original reference chapters are now being published.
|
||||
|
||||
* [Introduction to EPICS](https://docs.epics-controls.org/en/latest/guides/EPICS_Intro.html)
|
||||
* [Process Database Concepts](https://docs.epics-controls.org/en/latest/guides/EPICS_Process_Database_Concepts.html)
|
||||
* [Fields Common to All Record Types](dbCommonRecord.html)
|
||||
* [Fields Common to Input Record Types](dbCommonInput.html)
|
||||
* [Fields Common to Output Record Types](dbCommonOutput.html)
|
||||
@@ -35,7 +38,7 @@ record types supplied with Base.
|
||||
* [Multi-Bit Binary Output Direct Record (mbboDirect)](mbboDirectRecord.html)
|
||||
* [Multi-Bit Binary Output Record (mbbo)](mbboRecord.html)
|
||||
* [Permissive Record (permissive)](permissiveRecord.html)
|
||||
* [Printf Record (prinf)](printfRecord.html)
|
||||
* [Printf Record (printf)](printfRecord.html)
|
||||
* [Select Record (sel)](selRecord.html)
|
||||
* [Sequence Record (seq)](seqRecord.html)
|
||||
* [State Record (state)](stateRecord.html)
|
||||
|
||||
@@ -1048,7 +1048,11 @@ static void event_task (void *pParm)
|
||||
epicsEventDestroy(evUser->pflush_sem);
|
||||
epicsMutexDestroy(evUser->lock);
|
||||
|
||||
freeListFree(dbevEventUserFreeList, evUser);
|
||||
if (dbevEventUserFreeList)
|
||||
freeListFree(dbevEventUserFreeList, evUser);
|
||||
else
|
||||
fprintf(stderr, "%s exiting but dbevEventUserFreeList already NULL\n",
|
||||
__FUNCTION__);
|
||||
|
||||
taskwdRemove(epicsThreadGetIdSelf());
|
||||
|
||||
|
||||
@@ -1076,13 +1076,10 @@ static void addToList(struct dbCommon *precord, scan_list *psl)
|
||||
pse->pscan_list = psl;
|
||||
ptemp = (scan_element *)ellLast(&psl->list);
|
||||
while (ptemp) {
|
||||
if (ptemp->precord->phas <= precord->phas) {
|
||||
ellInsert(&psl->list, &ptemp->node, &pse->node);
|
||||
break;
|
||||
}
|
||||
if (ptemp->precord->phas <= precord->phas) break;
|
||||
ptemp = (scan_element *)ellPrevious(&ptemp->node);
|
||||
}
|
||||
if (ptemp == NULL) ellAdd(&psl->list, (void *)pse);
|
||||
ellInsert(&psl->list, (ptemp ? &ptemp->node : NULL), &pse->node);
|
||||
psl->modified = TRUE;
|
||||
epicsMutexUnlock(psl->lock);
|
||||
}
|
||||
@@ -1108,7 +1105,7 @@ static void deleteFromList(struct dbCommon *precord, scan_list *psl)
|
||||
return;
|
||||
}
|
||||
pse->pscan_list = NULL;
|
||||
ellDelete(&psl->list, (void *)pse);
|
||||
ellDelete(&psl->list, &pse->node);
|
||||
psl->modified = TRUE;
|
||||
epicsMutexUnlock(psl->lock);
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "initHooks.h"
|
||||
#include "iocInit.h"
|
||||
#include "errSymTbl.h"
|
||||
#include "iocshRegisterCommon.h"
|
||||
|
||||
static dbEventCtx testEvtCtx;
|
||||
static epicsMutexId testEvtLock;
|
||||
@@ -98,6 +99,7 @@ void testdbCleanup(void)
|
||||
db_cleanup_events();
|
||||
initHookFree();
|
||||
registryFree();
|
||||
clearRegistrarOnce();
|
||||
pdbbase = NULL;
|
||||
dbmfFreeChunks();
|
||||
}
|
||||
|
||||
@@ -2331,8 +2331,7 @@ long dbParseLink(const char *str, short ftype, dbLinkInfo *pinfo)
|
||||
}
|
||||
|
||||
/* Link may be an array constant */
|
||||
if (pstr[0] == '[' && pstr[len-1] == ']' &&
|
||||
(strchr(pstr, ',') || strchr(pstr, '"'))) {
|
||||
if (pstr[0] == '[' && pstr[len-1] == ']') {
|
||||
pinfo->ltype = CONSTANT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -25,5 +25,6 @@ dbCore_SRCS += iocInit.c
|
||||
dbCore_SRCS += miscIocRegister.c
|
||||
dbCore_SRCS += dlload.c
|
||||
dbCore_SRCS += iocshRegisterCommon.c
|
||||
dbCore_SRCS += registerAllRecordDeviceDrivers.cpp
|
||||
|
||||
miscIocRegister_CFLAGS_iOS = -DSYSTEM_UNAVAILABLE
|
||||
|
||||
@@ -26,6 +26,16 @@
|
||||
#define quote(v) #v
|
||||
#define str(v) quote(v)
|
||||
|
||||
/* registerAllRecordDeviceDrivers */
|
||||
static const iocshArg rrddArg0 = {"pdbbase", iocshArgPdbbase};
|
||||
static const iocshArg *rrddArgs[] = {&rrddArg0};
|
||||
static const iocshFuncDef rrddFuncDef =
|
||||
{"registerAllRecordDeviceDrivers", 1, rrddArgs};
|
||||
static void rrddCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
iocshSetError(registerAllRecordDeviceDrivers(*iocshPpdbbase));
|
||||
}
|
||||
|
||||
void iocshRegisterCommon(void)
|
||||
{
|
||||
const char *targetArch = envGetConfigParamPtr(&EPICS_BUILD_TARGET_ARCH);
|
||||
@@ -53,4 +63,5 @@ void iocshRegisterCommon(void)
|
||||
asIocRegister();
|
||||
miscIocRegister();
|
||||
libComRegister();
|
||||
iocshRegister(&rrddFuncDef, rrddCallFunc);
|
||||
}
|
||||
|
||||
@@ -19,9 +19,25 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct dbBase;
|
||||
|
||||
/* register many useful commands */
|
||||
epicsShareFunc void iocshRegisterCommon(void);
|
||||
|
||||
#define HAS_registerAllRecordDeviceDrivers
|
||||
|
||||
epicsShareFunc
|
||||
long
|
||||
registerAllRecordDeviceDrivers(struct dbBase *pdbbase);
|
||||
|
||||
epicsShareFunc
|
||||
void runRegistrarOnce(void (*reg_func)(void));
|
||||
|
||||
#ifdef EPICS_PRIVATE_API
|
||||
epicsShareFunc
|
||||
void clearRegistrarOnce(void);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
240
modules/database/src/ioc/misc/registerAllRecordDeviceDrivers.cpp
Normal file
240
modules/database/src/ioc/misc/registerAllRecordDeviceDrivers.cpp
Normal file
@@ -0,0 +1,240 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2020 Michael Davidsaver
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
#include <exception>
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include <map>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define EPICS_PRIVATE_API
|
||||
|
||||
#include <iocsh.h>
|
||||
|
||||
#include <epicsStdio.h>
|
||||
#include <epicsFindSymbol.h>
|
||||
#define epicsExportSharedSymbols
|
||||
#include <registryRecordType.h>
|
||||
#include <registryDeviceSupport.h>
|
||||
#include <registryDriverSupport.h>
|
||||
#include <iocshRegisterCommon.h>
|
||||
#include <registryCommon.h>
|
||||
#include <dbAccess.h>
|
||||
#include <dbBase.h>
|
||||
#include <dbStaticLib.h>
|
||||
|
||||
namespace {
|
||||
|
||||
struct compareLoc {
|
||||
bool operator()(const recordTypeLocation& lhs, const recordTypeLocation& rhs) const
|
||||
{
|
||||
if(lhs.prset<rhs.prset)
|
||||
return true;
|
||||
else if(lhs.prset>rhs.prset)
|
||||
return false;
|
||||
return lhs.sizeOffset<rhs.sizeOffset;
|
||||
}
|
||||
};
|
||||
|
||||
// storage which will be referenced by pdbbase. Must never be free'd
|
||||
std::set<std::string> names;
|
||||
std::set<recordTypeLocation, compareLoc> reclocs;
|
||||
|
||||
template<typename T, typename Y>
|
||||
const T& intern(std::set<T,Y>& coll, const T& val)
|
||||
{
|
||||
return *coll.insert(val).first;
|
||||
}
|
||||
|
||||
std::set<void*> registrarsRun;
|
||||
|
||||
// gcc circa 4.4 doesn't like iocshVarDef[2] as mapped_type
|
||||
struct varDef {
|
||||
iocshVarDef def[2];
|
||||
};
|
||||
typedef std::map<std::string, varDef> vardefs_t;
|
||||
vardefs_t vardefs;
|
||||
|
||||
template<typename T>
|
||||
T lookupAs(const char* a, const char* b =0, const char* c =0, const char* d =0)
|
||||
{
|
||||
std::string name(a);
|
||||
if(b)
|
||||
name += b;
|
||||
if(c)
|
||||
name += c;
|
||||
if(d)
|
||||
name += d;
|
||||
|
||||
T ret = (T)epicsFindSymbol(name.c_str());
|
||||
if(!ret) {
|
||||
fprintf(stderr, "Unable to find symbol '%s' : %s\n", name.c_str(), epicsLoadError());
|
||||
// all pvar_* are pointers to the exported object
|
||||
} else if(ret && !*ret) {
|
||||
fprintf(stderr, "symbol '%s' holds NULL\n", name.c_str());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void runRegistrarOnce(void (*reg_func)(void))
|
||||
{
|
||||
if(registrarsRun.find((void*)reg_func)!=registrarsRun.end())
|
||||
return;
|
||||
|
||||
registrarsRun.insert((void*)reg_func);
|
||||
|
||||
reg_func();
|
||||
}
|
||||
|
||||
void clearRegistrarOnce()
|
||||
{
|
||||
registrarsRun.clear();
|
||||
}
|
||||
|
||||
long
|
||||
registerAllRecordDeviceDrivers(DBBASE *pdbbase)
|
||||
{
|
||||
DBENTRY entry;
|
||||
|
||||
if(!pdbbase) {
|
||||
fprintf(stderr, "Must call dbLoadRecords() before registerAllRecordDeviceDrivers(pdbbase)\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
dbInitEntry(pdbbase, &entry);
|
||||
try {
|
||||
// for each recordType
|
||||
for(long status=dbFirstRecordType(&entry); !status; status=dbNextRecordType(&entry)) {
|
||||
dbRecordType *rtype = entry.precordType;
|
||||
|
||||
if(!registryRecordTypeFind(rtype->name)) {
|
||||
|
||||
rset** prset = lookupAs<rset**>("pvar_rset_", rtype->name, "RSET");
|
||||
computeSizeOffset* sizeOffset = lookupAs<computeSizeOffset*>("pvar_func_", rtype->name, "RecordSizeOffset");
|
||||
|
||||
if(!prset || !*prset || !sizeOffset || !*sizeOffset) {
|
||||
fprintf(stderr, "Unable to find support for record type '%s' : %s\n",
|
||||
rtype->name, epicsLoadError());
|
||||
return 1;
|
||||
}
|
||||
|
||||
recordTypeLocation sup;
|
||||
sup.prset = *prset;
|
||||
sup.sizeOffset = *sizeOffset;
|
||||
|
||||
const char *cname = intern<std::string>(names, rtype->name).c_str();
|
||||
const recordTypeLocation* csup = &intern<recordTypeLocation>(reclocs, sup);
|
||||
registerRecordTypes(pdbbase, 1, &cname, csup);
|
||||
}
|
||||
|
||||
// for each device support for this recordType
|
||||
for(ELLNODE *cur = ellFirst(&rtype->devList); cur; cur = ellNext(cur)) {
|
||||
devSup& devsup = *CONTAINER(cur, devSup, node);
|
||||
|
||||
if(registryDeviceSupportFind(devsup.name))
|
||||
continue;
|
||||
|
||||
dset** ptr = lookupAs<dset**>("pvar_dset_", devsup.name);
|
||||
|
||||
if(!ptr || !*ptr) {
|
||||
fprintf(stderr, "Unable to find dset for record type '%s' support '%s' : %s\n",
|
||||
rtype->name, devsup.name, epicsLoadError());
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *cname = intern<std::string>(names, devsup.name).c_str();
|
||||
registerDevices(pdbbase, 1, &cname, ptr);
|
||||
}
|
||||
}
|
||||
|
||||
// for each driver
|
||||
for(ELLNODE *cur = ellFirst(&pdbbase->drvList); cur; cur = ellNext(cur)) {
|
||||
drvSup& drv = *CONTAINER(cur, drvSup, node);
|
||||
|
||||
if(registryDriverSupportFind(drv.name))
|
||||
continue;
|
||||
|
||||
drvet** ptr = lookupAs<drvet**>("pvar_drvet_", drv.name);
|
||||
|
||||
if(!ptr || !*ptr) {
|
||||
fprintf(stderr, "Unable to find drvet '%s' : %s\n", drv.name, epicsLoadError());
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *cname = intern<std::string>(names, drv.name).c_str();
|
||||
registerDrivers(pdbbase, 1, &cname, ptr);
|
||||
}
|
||||
|
||||
// for each link support
|
||||
for(ELLNODE *cur = ellFirst(&pdbbase->linkList); cur; cur = ellNext(cur)) {
|
||||
linkSup& lnk = *CONTAINER(cur, linkSup, node);
|
||||
|
||||
jlif** ptr = lookupAs<jlif**>("pvar_jlif_", lnk.jlif_name);
|
||||
|
||||
if(!ptr || !*ptr) {
|
||||
fprintf(stderr, "Unable to find link support '%s' : %s\n", lnk.jlif_name, epicsLoadError());
|
||||
return 1;
|
||||
}
|
||||
|
||||
registerJLinks(pdbbase, 1, ptr);
|
||||
}
|
||||
|
||||
// for each registrar()
|
||||
for(ELLNODE *cur = ellFirst(&pdbbase->registrarList); cur; cur = ellNext(cur)) {
|
||||
dbText& reg = *CONTAINER(cur, dbText, node);
|
||||
|
||||
typedef void(*registrar)(void);
|
||||
registrar* ptr = lookupAs<registrar*>("pvar_func_", reg.text);
|
||||
|
||||
if(!ptr || !*ptr) {
|
||||
fprintf(stderr, "Unable to find registar '%s' : %s\n", reg.text, epicsLoadError());
|
||||
return 1;
|
||||
}
|
||||
|
||||
runRegistrarOnce(*ptr);
|
||||
}
|
||||
|
||||
// for each iocsh variable
|
||||
for(ELLNODE *cur = ellFirst(&pdbbase->variableList); cur; cur = ellNext(cur)) {
|
||||
dbVariableDef& var = *CONTAINER(cur, dbVariableDef, node);
|
||||
|
||||
if(iocshFindVariable(var.name))
|
||||
continue;
|
||||
|
||||
void** ptr = lookupAs<void**>("pvar_", var.type, "_", var.name);
|
||||
|
||||
if(!ptr || !*ptr) {
|
||||
fprintf(stderr, "Unable to find variable '%s' : %s\n", var.name, epicsLoadError());
|
||||
return 1;
|
||||
}
|
||||
|
||||
vardefs_t::mapped_type& vdef = vardefs[var.name];
|
||||
vdef.def[0].name = intern<std::string>(names, var.name).c_str();
|
||||
vdef.def[0].pval = *ptr;
|
||||
if(strcmp(var.type, "double")==0) {
|
||||
vdef.def[0].type = iocshArgDouble;
|
||||
} else if(strcmp(var.type, "int")==0) {
|
||||
vdef.def[0].type = iocshArgInt;
|
||||
} else {
|
||||
fprintf(stderr, "Unsupported type %s of variable '%s' : %s\n", var.type, var.name, epicsLoadError());
|
||||
return 1;
|
||||
}
|
||||
vdef.def[1].name = 0;
|
||||
iocshRegisterVariable(vdef.def);
|
||||
}
|
||||
|
||||
dbFinishEntry(&entry);
|
||||
return 0;
|
||||
|
||||
} catch(std::exception& e) {
|
||||
dbFinishEntry(&entry);
|
||||
fprintf(stderr, "Error: %s\n", e.what());
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
@@ -489,8 +489,17 @@ static long lnkConst_loadArray(struct link *plink, short dbrType, void *pbuffer,
|
||||
case sc40:
|
||||
if (clink->jlink.debug)
|
||||
printf(" sc40 '%s'\n", clink->value.scalar_string);
|
||||
status = dbFastPutConvertRoutine[DBF_STRING][dbrType]
|
||||
(clink->value.scalar_string, pbuffer, NULL);
|
||||
if (dbrType != DBF_CHAR) {
|
||||
status = dbFastPutConvertRoutine[DBF_STRING][dbrType]
|
||||
(clink->value.scalar_string, pbuffer, NULL);
|
||||
}
|
||||
else {
|
||||
/* Long string conversion */
|
||||
strncpy(pbuffer, clink->value.scalar_string, *pnReq);
|
||||
((char *)pbuffer)[*pnReq] = 0;
|
||||
nElems = strlen(pbuffer) + 1;
|
||||
status = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case ai64:
|
||||
|
||||
@@ -90,7 +90,7 @@ The VAL field is set to the value returned by the user subroutine.
|
||||
The value is treated as an error status value where zero mean success.
|
||||
The output links OUTA ... OUTU will only be used to forward the associated
|
||||
output value fields when the subroutine has returned a zero status.
|
||||
If the return status was non-zero, the record will be put into C<SOFT_ALARM>
|
||||
If the return status was less than zero, the record will be put into C<SOFT_ALARM>
|
||||
state with severity given by the BRSV field.
|
||||
|
||||
The INAM field may be used to name a subroutine that will be called once at
|
||||
@@ -1363,7 +1363,7 @@ be sent through the OUTA ... OUTU links during record processing.
|
||||
The previous values of the output fields.
|
||||
These are used to determine when to post events if EFLG is set to C<ON CHANGE>.
|
||||
|
||||
=fields VALA, VALB, VALC, VALD, VALE, VALF, VALG, VALH, VALI, VALJ, VALK, VALL, VALM, VALN, VALO, VALP, VALQ, VALR, VALS, VALT, VALU
|
||||
=fields OVLA, OVLB, OVLC, OVLD, OVLE, OVLF, OVLG, OVLH, OVLI, OVLJ, OVLK, OVLL, OVLM, OVLN, OVLO, OVLP, OVLQ, OVLR, OVLS, OVLT, OVLU
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
@@ -47,13 +47,15 @@ extern "C" int softIoc_registerRecordDeviceDriver(struct dbBase *pdbbase);
|
||||
|
||||
namespace {
|
||||
|
||||
bool verbose = false;
|
||||
|
||||
static void exitSubroutine(subRecord *precord) {
|
||||
epicsExitLater((precord->a == 0.0) ? EXIT_SUCCESS : EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void usage(const char *arg0, const std::string& base_dbd) {
|
||||
std::cout<<"Usage: "<<arg0<<
|
||||
" [-D softIoc.dbd] [-h] [-S] [-s] [-a ascf]\n"
|
||||
" [-D softIoc.dbd] [-h] [-S] [-s] [-v] [-a ascf]\n"
|
||||
"[-m macro=value,macro2=value2] [-d file.db]\n"
|
||||
"[-x prefix] [st.cmd]\n"
|
||||
"\n"
|
||||
@@ -66,6 +68,8 @@ void usage(const char *arg0, const std::string& base_dbd) {
|
||||
"\n"
|
||||
" -s Previously caused a shell to be started. Now accepted and ignored.\n"
|
||||
"\n"
|
||||
" -v Verbose, display steps taken during startup.\n"
|
||||
"\n"
|
||||
" -a <acf> Access Security configuration file. Macro substitution is\n"
|
||||
" performed.\n"
|
||||
"\n"
|
||||
@@ -103,12 +107,14 @@ void lazy_dbd(const std::string& dbd_file) {
|
||||
if(lazy_dbd_loaded) return;
|
||||
lazy_dbd_loaded = true;
|
||||
|
||||
if (verbose)
|
||||
std::cout<<"dbLoadDatabase(\""<<dbd_file<<"\")\n";
|
||||
errIf(dbLoadDatabase(dbd_file.c_str(), NULL, NULL),
|
||||
std::string("Failed to load DBD file: ")+dbd_file);
|
||||
std::cout<<"dbLoadDatabase(\""<<dbd_file<<"\")\n";
|
||||
|
||||
if (verbose)
|
||||
std::cout<<"softIoc_registerRecordDeviceDriver(pdbbase)\n";
|
||||
softIoc_registerRecordDeviceDriver(pdbbase);
|
||||
std::cout<<"softIoc_registerRecordDeviceDriver(pdbbase)\n";
|
||||
registryFunctionAdd("exit", (REGISTRYFUNCTION) exitSubroutine);
|
||||
}
|
||||
|
||||
@@ -144,7 +150,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
int opt;
|
||||
|
||||
while ((opt = getopt(argc, argv, "ha:D:d:m:Ssx:")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "ha:D:d:m:Ssx:v")) != -1) {
|
||||
switch (opt) {
|
||||
case 'h': /* Print usage */
|
||||
usage(argv[0], dbd_file);
|
||||
@@ -158,13 +164,15 @@ int main(int argc, char *argv[])
|
||||
case 'a':
|
||||
lazy_dbd(dbd_file);
|
||||
if (!macros.empty()) {
|
||||
if (verbose)
|
||||
std::cout<<"asSetSubstitutions(\""<<macros<<"\")\n";
|
||||
if(asSetSubstitutions(macros.c_str()))
|
||||
throw std::bad_alloc();
|
||||
std::cout<<"asSetSubstitutions(\""<<macros<<"\")\n";
|
||||
}
|
||||
if (verbose)
|
||||
std::cout<<"asSetFilename(\""<<optarg<<"\")\n";
|
||||
if(asSetFilename(optarg))
|
||||
throw std::bad_alloc();
|
||||
std::cout<<"asSetFilename(\""<<optarg<<"\")\n";
|
||||
break;
|
||||
case 'D':
|
||||
if(lazy_dbd_loaded) {
|
||||
@@ -174,12 +182,14 @@ int main(int argc, char *argv[])
|
||||
break;
|
||||
case 'd':
|
||||
lazy_dbd(dbd_file);
|
||||
if (verbose) {
|
||||
std::cout<<"dbLoadRecords(\""<<optarg<<"\"";
|
||||
if(!macros.empty())
|
||||
std::cout<<", \""<<macros<<"\"";
|
||||
std::cout<<")\n";
|
||||
}
|
||||
errIf(dbLoadRecords(optarg, macros.c_str()),
|
||||
std::string("Failed to load: ")+optarg);
|
||||
std::cout<<"dbLoadRecords(\""<<optarg<<"\"";
|
||||
if(!macros.empty())
|
||||
std::cout<<", \""<<macros<<"\"";
|
||||
std::cout<<")\n";
|
||||
loadedDb = true;
|
||||
break;
|
||||
case 'm':
|
||||
@@ -190,6 +200,9 @@ int main(int argc, char *argv[])
|
||||
break;
|
||||
case 's':
|
||||
break; // historical
|
||||
case 'v':
|
||||
verbose = true;
|
||||
break;
|
||||
case 'x':
|
||||
lazy_dbd(dbd_file);
|
||||
xmacro = "IOC=";
|
||||
@@ -207,17 +220,20 @@ int main(int argc, char *argv[])
|
||||
// run script
|
||||
// ignore any extra positional args (historical)
|
||||
|
||||
std::cout<<"# Begin "<<argv[optind]<<"\n";
|
||||
if (verbose)
|
||||
std::cout<<"# Begin "<<argv[optind]<<"\n";
|
||||
errIf(iocsh(argv[optind]),
|
||||
std::string("Error in ")+argv[optind]);
|
||||
std::cout<<"# End "<<argv[optind]<<"\n";
|
||||
if (verbose)
|
||||
std::cout<<"# End "<<argv[optind]<<"\n";
|
||||
|
||||
epicsThreadSleep(0.2);
|
||||
loadedDb = true; /* Give it the benefit of the doubt... */
|
||||
}
|
||||
|
||||
if (loadedDb) {
|
||||
std::cout<<"iocInit()\n";
|
||||
if (verbose)
|
||||
std::cout<<"iocInit()\n";
|
||||
iocInit();
|
||||
epicsThreadSleep(0.2);
|
||||
}
|
||||
|
||||
@@ -258,7 +258,7 @@ print $out (<< 'END') if %links;
|
||||
END
|
||||
|
||||
print $out (<< "END") for @registrars;
|
||||
pvar_func_$_();
|
||||
runRegistrarOnce(pvar_func_$_);
|
||||
END
|
||||
|
||||
print $out (<< 'END') if %variables;
|
||||
|
||||
@@ -37,6 +37,9 @@ TESTS += arrayOpTest
|
||||
|
||||
TESTPROD_HOST += recMiscTest
|
||||
recMiscTest_SRCS += recMiscTest.c
|
||||
ifeq (NO,$(STATIC_BUILD))
|
||||
recMiscTest_CFLAGS += -DLINK_DYNAMIC
|
||||
endif
|
||||
recMiscTest_SRCS += recTestIoc_registerRecordDeviceDriver.cpp
|
||||
testHarness_SRCS += recMiscTest.c
|
||||
TESTFILES += ../recMiscTest.db
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "dbAccess.h"
|
||||
#include "errlog.h"
|
||||
#include "dbStaticLib.h"
|
||||
#include "iocshRegisterCommon.h"
|
||||
#include "dbUnitTest.h"
|
||||
#include "testMain.h"
|
||||
|
||||
@@ -63,13 +64,22 @@ void recTestIoc_registerRecordDeviceDriver(struct dbBase *);
|
||||
|
||||
MAIN(recMiscTest)
|
||||
{
|
||||
testPlan(10);
|
||||
testPlan(12);
|
||||
|
||||
testdbPrepare();
|
||||
|
||||
testdbReadDatabase("recTestIoc.dbd", NULL, NULL);
|
||||
|
||||
#ifdef LINK_DYNAMIC
|
||||
/* A smoke test of registerAllRecordDeviceDrivers to check for idempotence */
|
||||
testOk1(registerAllRecordDeviceDrivers(pdbbase)==0);
|
||||
#else
|
||||
testSkip(2, "only testing registerAllRecordDeviceDrivers() with dynamic linking");
|
||||
#endif
|
||||
recTestIoc_registerRecordDeviceDriver(pdbbase);
|
||||
#ifdef LINK_DYNAMIC
|
||||
testOk1(registerAllRecordDeviceDrivers(pdbbase)==0);
|
||||
#endif
|
||||
|
||||
testdbReadDatabase("recMiscTest.db", NULL, NULL);
|
||||
|
||||
|
||||
@@ -46,8 +46,10 @@ int main ()
|
||||
tsSLIter<fred> iter1 = list.firstIter ();
|
||||
tsSLIter<fred> iter2 = iter1;
|
||||
tsSLIter<fred> iter3 = iter1;
|
||||
assert ( iter1 == iter3++ );
|
||||
assert ( iter3 == ++iter2 );
|
||||
tsSLIter<fred> itert = iter3++
|
||||
assert ( iter1 == itert );
|
||||
itert = ++iter2;
|
||||
assert ( iter3 == itert );
|
||||
list.remove ( *pFredII ); // removes pFred
|
||||
}
|
||||
list.add ( *pFred );
|
||||
|
||||
@@ -181,7 +181,7 @@ void epicsStdCall iocshRegisterVariable (const iocshVarDef *piocshVarDef)
|
||||
for (l = NULL, p = iocshVariableHead ; p != NULL ; l = p, p = p->next) {
|
||||
i = strcmp (piocshVarDef->name, p->pVarDef->name);
|
||||
if (i == 0) {
|
||||
if (p->pVarDef != piocshVarDef) {
|
||||
if ((p->pVarDef->type != piocshVarDef->type) && (p->pVarDef->pval != piocshVarDef->pval)) {
|
||||
errlogPrintf("Warning: iocshRegisterVariable redefining %s.\n",
|
||||
piocshVarDef->name);
|
||||
p->pVarDef = piocshVarDef;
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
#include <netdb.h>
|
||||
#include <unistd.h> /* close() and others */
|
||||
|
||||
#ifndef IPPORT_USERRESERVED
|
||||
#define IPPORT_USERRESERVED 5000
|
||||
#endif
|
||||
|
||||
typedef int SOCKET;
|
||||
#define INVALID_SOCKET (-1)
|
||||
|
||||
@@ -63,10 +63,10 @@ LIBCOM_API int epicsStdCall osiSockAttach()
|
||||
DWORD titleLength = GetConsoleTitle(title, sizeof(title));
|
||||
if (titleLength) {
|
||||
titleLength = strlen (title);
|
||||
strncat (title, " " EPICS_VERSION_STRING, sizeof(title));
|
||||
strncat (title, " " EPICS_VERSION_STRING, sizeof(title)-1);
|
||||
}
|
||||
else {
|
||||
strncpy(title, EPICS_VERSION_STRING, sizeof(title));
|
||||
strncpy(title, EPICS_VERSION_STRING, sizeof(title)-1);
|
||||
}
|
||||
title[sizeof(title)-1]= '\0';
|
||||
SetConsoleTitle(title);
|
||||
|
||||
@@ -58,12 +58,32 @@ sub readRelease {
|
||||
while (<$IN>) {
|
||||
chomp;
|
||||
s/ \r $//x; # Shouldn't need this, but sometimes...
|
||||
s/^ \s+ //x; # Remove leading whitespace
|
||||
next if m/^ $/x; # Skip blank lines
|
||||
s/ # .* $//x; # Remove trailing comments
|
||||
s/ \s+ $//x; # Remove trailing whitespace
|
||||
next if m/^ \s* $/x; # Skip blank lines
|
||||
|
||||
# Handle "undefine <variable>"
|
||||
my ($uvar) = m/^ undefine \s+ ($MVAR)/x;
|
||||
if ($uvar ne '') {
|
||||
delete $Rmacros->{$uvar};
|
||||
next;
|
||||
}
|
||||
|
||||
# Handle "include <path>" and "-include <path>" syntax
|
||||
my ($op, $path) = m/^ (-? include) \s+ (.*)/x;
|
||||
if ($op ne '') {
|
||||
$path = expandMacros($path, $Rmacros);
|
||||
if (-e $path) {
|
||||
&readRelease($path, $Rmacros, $Rapps, $Ractive);
|
||||
} elsif ($op eq "include") {
|
||||
warn "EPICS/Release.pm: Include file '$path' not found\n";
|
||||
}
|
||||
next;
|
||||
}
|
||||
|
||||
# Handle "<variable> = <path>" plus the := and ?= variants
|
||||
my ($var, $op, $val) = m/^ \s* ($MVAR) \s* ([?:]?=) \s* (.*) /x;
|
||||
my ($var, $op, $val) = m/^ ($MVAR) \s* ([?:]?=) \s* (.*) /x;
|
||||
if ($var ne '') {
|
||||
$var = 'TOP' if $var =~ m/^ INSTALL_LOCATION /x;
|
||||
if (exists $Rmacros->{$var}) {
|
||||
@@ -75,14 +95,6 @@ sub readRelease {
|
||||
$Rmacros->{$var} = $val;
|
||||
next;
|
||||
}
|
||||
# Handle "include <path>" and "-include <path>" syntax
|
||||
my ($op, $path) = m/^ \s* (-? include) \s+ (.*)/x;
|
||||
$path = expandMacros($path, $Rmacros);
|
||||
if (-e $path) {
|
||||
&readRelease($path, $Rmacros, $Rapps, $Ractive);
|
||||
} elsif ($op eq "include") {
|
||||
warn "EPICS/Release.pm: Include file '$path' not found\n";
|
||||
}
|
||||
}
|
||||
$Ractive->{$file}--;
|
||||
close $IN;
|
||||
|
||||
@@ -35,6 +35,7 @@ sub HostArch {
|
||||
return 'linux-x86_64' if m/^x86_64-linux/;
|
||||
return 'linux-x86' if m/^i[3-6]86-linux/;
|
||||
return 'linux-arm' if m/^arm-linux/;
|
||||
return 'linux-aarch64' if m/^aarch64-linux/;
|
||||
return 'windows-x64' if m/^MSWin32-x64/;
|
||||
return 'win32-x86' if m/^MSWin32-x86/;
|
||||
return "cygwin-x86_64" if m/^x86_64-cygwin/;
|
||||
|
||||
Reference in New Issue
Block a user