diff --git a/.appveyor.yml b/.appveyor.yml index f384361fc..c830ae1a8 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -31,6 +31,8 @@ skip_commits: - 'documentation/*' - 'startup/*' - '.github/*' + - '.tools/*' + - '.gitattributes' - '**/*.html' - '**/*.md' @@ -64,6 +66,7 @@ environment: - CMP: vs2012 - CMP: vs2010 - CMP: gcc + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 # Platform: processor architecture platform: @@ -104,11 +107,11 @@ build_script: test_script: - cmd: python -m ci_core_dumper install - - cmd: python .ci/cue.py test + - cmd: python .ci/cue.py -T 20M test on_finish: - ps: Get-ChildItem *.tap -Recurse -Force | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name } - - cmd: python .ci/cue.py build test-results -s + - cmd: python .ci/cue.py -T 5M test-results on_failure: - cmd: python -m ci_core_dumper report diff --git a/.appveyor/epics-base-7.yml b/.appveyor/epics-base-7.yml index 410989d78..4a01ccde5 100644 --- a/.appveyor/epics-base-7.yml +++ b/.appveyor/epics-base-7.yml @@ -38,6 +38,8 @@ skip_commits: - 'documentation/*' - 'startup/*' - '.github/*' + - '.tools/*' + - '.gitattributes' - '**/*.html' - '**/*.md' @@ -111,11 +113,11 @@ build_script: test_script: - cmd: python -m ci_core_dumper install - - cmd: python .ci/cue.py test + - cmd: python .ci/cue.py -T 20M test on_finish: - ps: Get-ChildItem *.tap -Recurse -Force | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name } - - cmd: python .ci/cue.py build test-results -s + - cmd: python .ci/cue.py -T 5M test-results on_failure: - cmd: python -m ci_core_dumper report diff --git a/.ci b/.ci index 3db08b597..d675de24e 160000 --- a/.ci +++ b/.ci @@ -1 +1 @@ -Subproject commit 3db08b5977efd7a3ac8eecfa068b5bfdfdf84dd0 +Subproject commit d675de24e6a2be018f6ff1dc35618c16dd621727 diff --git a/.ci-local/travis-fixup.sh b/.ci-local/travis-fixup.sh deleted file mode 100755 index 7d1ea8235..000000000 --- a/.ci-local/travis-fixup.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/sh -set -e -u -x - -env|grep TRAVIS - -[ "$TRAVIS_OS_NAME" = "linux" ] || exit 0 - -# Ensure there is an interface with a (correct) broadcast address -# eg. 'trusty' VMs have interface broadcast address mis-configured -# (why oh why do people insist on setting this explicitly?) - -sudo ip tuntap add dev tap42 mode tap - -sudo ip addr add 192.168.240.1/24 broadcast + dev tap42 - -sudo ip link set dev tap42 up - -# note that this device will be UP but not RUNNING -# so java will see it as not UP since java confuses UP and RUNNING diff --git a/.gitattributes b/.gitattributes index 5842dd19a..5221674ea 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,5 +1,25 @@ .ci/ export-ignore .tools/ export-ignore +.github/ export-ignore +.appveyor/ export-ignore .appveyor.yml export-ignore -.travis.yml export-ignore README export-subst + +#Which files need CRLF handling +# default to automatic +* text=auto + +# batch script parser on windows requires CRLF +*.bat text eol=crlf + +# extensions for scripts which may be executable via. "#!..." must have LF +*.pl text eol=lf +*.plt text eol=lf +*.sh text eol=lf +*.cmd text eol=lf +# .cmd in unexpanded templates +*.cmd@* text eol=lf +# executable scripts w/o extensions +modules/ca/src/client/S99caRepeater@ text eol=lf +modules/libcom/src/log/S99logServer@ text eol=lf +startup/EpicsHostArch text eol=lf diff --git a/.github/workflows/ci-scripts-build.yml b/.github/workflows/ci-scripts-build.yml index 83bdd9dde..d94fbf312 100644 --- a/.github/workflows/ci-scripts-build.yml +++ b/.github/workflows/ci-scripts-build.yml @@ -14,9 +14,19 @@ on: - 'documentation/*' - 'startup/*' - '.appveyor/*' + - '.tools/*' + - '.gitattributes' - '**/*.html' - '**/*.md' pull_request: + paths-ignore: + - 'documentation/*' + - 'startup/*' + - '.appveyor/*' + - '.tools/*' + - '.gitattributes' + - '**/*.html' + - '**/*.md' env: SETUP_PATH: .ci-local:.ci @@ -33,7 +43,9 @@ jobs: BCFG: ${{ matrix.configuration }} WINE: ${{ matrix.wine }} RTEMS: ${{ matrix.rtems }} + RTEMS_TARGET: ${{ matrix.rtems_target }} EXTRA: ${{ matrix.extra }} + TEST: ${{ matrix.test }} strategy: fail-fast: false matrix: @@ -68,17 +80,66 @@ jobs: extra: "CMD_CXXFLAGS=-std=c++11" name: "Ub-20 clang-10 C++11" + - os: ubuntu-20.04 + cmp: gcc + configuration: default + rtems: "5" + rtems_target: RTEMS-pc686-qemu + name: "Ub-20 gcc-9 + RT-5.1 pc686" + + - os: ubuntu-20.04 + cmp: gcc + configuration: default + rtems: "5" + rtems_target: RTEMS-beatnik + test: NO + name: "Ub-20 gcc-9 + RT-5.1 beatnik" + + - os: ubuntu-20.04 + cmp: gcc + configuration: default + rtems: "5" + rtems_target: RTEMS-mvme3100 + test: NO + name: "Ub-20 gcc-9 + RT-5.1 mvme3100" + + - os: ubuntu-20.04 + cmp: gcc + configuration: default + rtems: "5" + rtems_target: RTEMS-qoriq_e500 + test: NO + name: "Ub-20 gcc-9 + RT-5.1 qoriq_e500" + + - os: ubuntu-20.04 + cmp: gcc + configuration: default + rtems: "5" + rtems_target: RTEMS-xilinx_zynq_a9_qemu + test: NO + name: "Ub-20 gcc-9 + RT-5.1 xilinx_zynq_a9_qemu" + + - os: ubuntu-20.04 + cmp: gcc + configuration: default + rtems: "5" + rtems_target: RTEMS-uC5282 + test: NO + name: "Ub-20 gcc-9 + RT-5.1 uC5282" + - os: ubuntu-20.04 cmp: gcc configuration: default rtems: "4.10" name: "Ub-20 gcc-9 + RT-4.10" + rtems_target: RTEMS-pc386-qemu - os: ubuntu-20.04 cmp: gcc configuration: default rtems: "4.9" name: "Ub-20 gcc-9 + RT-4.9" + rtems_target: RTEMS-pc386-qemu - os: ubuntu-16.04 cmp: gcc-4.8 @@ -98,6 +159,12 @@ jobs: configuration: default name: "Ub-20 gcc-8" + - os: ubuntu-20.04 + cmp: gcc-9 + utoolchain: "9" + configuration: default + name: "Ub-20 gcc-9" + - os: ubuntu-20.04 cmp: clang configuration: default @@ -118,6 +185,16 @@ jobs: configuration: static name: "Win2019 MSC-19, static" + - os: windows-2019 + cmp: vs2019 + configuration: debug + name: "Win2019 MSC-19, debug" + + - os: windows-2019 + cmp: gcc + configuration: default + name: "Win2019 mingw" + steps: - uses: actions/checkout@v2 with: @@ -142,11 +219,13 @@ jobs: - name: Build main module run: python .ci/cue.py build - name: Run main module tests - run: python .ci/cue.py test + run: python .ci/cue.py -T 20M test - name: Upload tapfiles Artifact + if: ${{ always() }} uses: actions/upload-artifact@v2 with: name: tapfiles ${{ matrix.name }} path: '**/O.*/*.tap' - name: Collect and show test results - run: python .ci/cue.py test-results + if: ${{ always() }} + run: python .ci/cue.py -T 5M test-results diff --git a/configure/CONFIG b/configure/CONFIG index fab3c245f..1c1242858 100644 --- a/configure/CONFIG +++ b/configure/CONFIG @@ -62,6 +62,9 @@ include $(CONFIG)/os/CONFIG.$(EPICS_HOST_ARCH).Common RELEASE_TOPS := $(shell $(CONVERTRELEASE) -T $(TOP) releaseTops) ifdef T_A + # Information from the target's compiler + # + -include $(EPICS_BASE)/cfg/TOOLCHAIN.$(EPICS_HOST_ARCH).$(T_A) # Cross compile specific definitions # diff --git a/configure/CONFIG.gnuCommon b/configure/CONFIG.gnuCommon index be77d4b38..355614e1a 100644 --- a/configure/CONFIG.gnuCommon +++ b/configure/CONFIG.gnuCommon @@ -56,8 +56,8 @@ STATIC_LDFLAGS_YES = -static STATIC_LDFLAGS_NO = SHRLIB_CFLAGS = -fPIC -SHRLIB_LDFLAGS = -shared -fPIC -LOADABLE_SHRLIB_LDFLAGS = -shared -fPIC +SHRLIB_LDFLAGS = -shared -fPIC -Wl,-h$@ +LOADABLE_SHRLIB_LDFLAGS = -shared -fPIC -Wl,-h$@ GNU_LDLIBS_YES = -lgcc diff --git a/configure/CONFIG_COMMON b/configure/CONFIG_COMMON index 825725973..8bbc4a624 100644 --- a/configure/CONFIG_COMMON +++ b/configure/CONFIG_COMMON @@ -71,6 +71,8 @@ INSTALL_DBD = $(INSTALL_LOCATION)/dbd INSTALL_DB = $(INSTALL_LOCATION)/db INSTALL_CONFIG = $(INSTALL_LOCATION)/configure +FINAL_LOCATION = $(shell $(PERL) $(TOOLS)/fullPathName.pl $(INSTALL_LOCATION)) + # Directory for OS independant build created files COMMON_DIR = ../O.Common @@ -142,9 +144,10 @@ BUILDLIB_SUFFIX = $(BUILDLIB_SUFFIX_$(SHARED_LIBRARIES)) #-------------------------------------------------- # vpath directories POSIX_YES = os/posix +OS_IMPL_DIRS = $(if $(OS_API),os/$(OS_CLASS)-$(OS_API),) os/$(OS_CLASS) GENERIC_SRC_DIRS = .. $(SRC_DIRS) OS_SRC_DIRS += . $(foreach dir, .. $(SRC_DIRS), \ - $(addprefix $(dir)/, os/$(OS_CLASS) $(POSIX_$(POSIX)) os/default )) + $(addprefix $(dir)/, $(OS_IMPL_DIRS) $(POSIX_$(POSIX)) os/default )) CMPLR_SRC_DIRS += . $(foreach dir, .. $(SRC_DIRS), \ $(addprefix $(dir)/, compiler/$(CMPLR_CLASS) compiler/default )) ALL_SRC_DIRS = $(CMPLR_SRC_DIRS) $(OS_SRC_DIRS) $(GENERIC_SRC_DIRS) diff --git a/configure/CONFIG_SITE b/configure/CONFIG_SITE index a575c61bf..03ec6d114 100644 --- a/configure/CONFIG_SITE +++ b/configure/CONFIG_SITE @@ -17,9 +17,8 @@ # Currently Supporting: # cygwin-x86 (cygwin compiler used for host builds) # cygwin-x86_64 (cygwin compiler used for host builds) -# darwin-ppc (PowerPC based Apple running OSX) -# darwin-ppcx86 (Universal binaries for both CPUs) -# darwin-x86 (Intel based Apple running OSX) +# darwin-aarch64 (M1 based Apple using CLANG compiler) +# darwin-x86 (Intel based Apple using CLANG compiler) # 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) @@ -62,16 +61,8 @@ # ios-arm (darwin-x86 host) # ios-386 (darwin-x86 host) -# linux-386 (linux-x86 host) -# linux-486 (linux-x86 host) -# linux-586 (linux-x86 host) -# linux-686 (linux-x86 host) # linux-arm (linux-x86 or -x86_64 host) # linux-aarch64 (linux-x86_64 host) -# linux-athlon (linux-x86 host) -# linux-cris (Axis GNU crosscompiler on linux-x86 host) -# linux-cris_v10 (Axis GNU crosscompiler on linux-x86 host) -# linux-cris_v32 (Axis GNU crosscompiler on linux-x86 host) # linux-microblaze # linux-xscale_be # vxWorks-486 @@ -85,18 +76,20 @@ # vxWorks-ppc604_altivec # vxWorks-mpc8540 # vxWorks-mpc8548 -# RTEMS-at91rm9200ek +# RTEMS-beagleboneblack # RTEMS-beatnik -# RTEMS-gen68360 -# RTEMS-mcp750 -# RTEMS-mvme167 # RTEMS-mvme2100 # RTEMS-mvme2700 # RTEMS-mvme3100 # RTEMS-mvme5500 -# RTEMS-pc386 -# RTEMS-psim +# RTEMS-pc386 (RTEMS 4) +# RTEMS-pc386-qemu (RTEMS 4) +# RTEMS-pc686 (RTEMS 5) +# RTEMS-pc686-qemu (RTEMS 5) +# RTEMS-qoriq_e500 # RTEMS-uC5282 +# RTEMS-xilinx-zynq-a9_qemu +# RTEMS-xilinx_zynq_zedboard # win32-x86-mingw (linux-x86 or -x86_64 host) # @@ -104,7 +97,6 @@ # Definitions in configure/os/CONFIG_SITE..Common # may override this setting. CROSS_COMPILER_TARGET_ARCHS= -#CROSS_COMPILER_TARGET_ARCHS=vxWorks-ppc32 # If only some of your host architectures can compile the # above CROSS_COMPILER_TARGET_ARCHS specify those host @@ -151,6 +143,14 @@ CROSS_WARN=YES # different location then uncomment and set this. #INSTALL_LOCATION= +# The location from which files placed in INSTALL_LOCATION will actually run. +# This path is compiled into executables, and so should be an absolute. +# May be used to achieve the effect of autotools. eg. +# ./configure --prefix= +# make DESTDIR= +# Defaults to the absolute expansion of $(INSTALL_LOCATION) +#FINAL_LOCATION= + # Use POSIX thread priority scheduling (if available). # Must be either YES or NO USE_POSIX_THREAD_PRIORITY_SCHEDULING = YES diff --git a/configure/Makefile b/configure/Makefile index f48278dd3..ba77d5089 100644 --- a/configure/Makefile +++ b/configure/Makefile @@ -15,7 +15,8 @@ include $(TOP)/configure/CONFIG TOOLS = $(TOP)/src/tools CONFIGS += $(subst ../,,$(wildcard ../CONFIG*)) -CONFIGS += $(subst ../,,$(wildcard ../os/CONFIG*)) +CONFIGS += $(subst ../,,$(wildcard ../os/CONFIG.*)) +CONFIGS += $(subst ../,,$(wildcard ../os/CONFIG_SITE.*)) CONFIGS += $(subst ../,,$(wildcard ../RELEASE*)) CONFIGS += $(subst ../,,$(wildcard ../RULES*)) @@ -29,5 +30,9 @@ CFG += CONFIG_CA_VERSION CFG += CONFIG_DATABASE_MODULE CFG += CONFIG_DATABASE_VERSION +CFG += TOOLCHAIN.$(EPICS_HOST_ARCH).$(T_A) + include $(TOP)/configure/RULES +TOOLCHAIN.$(EPICS_HOST_ARCH).$(T_A): toolchain.c + $(PREPROCESS.cpp) diff --git a/configure/RULES.Db b/configure/RULES.Db index 42a57430c..406c1eb16 100644 --- a/configure/RULES.Db +++ b/configure/RULES.Db @@ -196,12 +196,12 @@ endif #--------------------------------------------------------------- # build dependancies, clean rule -inc: $(COMMON_INC) $(INSTALL_INC) +inc: $(COMMON_INC) $(INSTALL_INC) $(COMMON_DBDS) $(COMMON_DBDCATS) \ + $(INSTALL_DBDS) $(INSTALL_DBD_INSTALLS) -build: $(COMMON_DBDS) $(COMMON_DBS) $(COMMON_DBDCATS) \ - $(INSTALL_DBDS) $(INSTALL_DBS) \ +build: $(COMMON_DBS) $(INSTALL_DBS) \ $(DBDDEPENDS_FILES) $(TARGETS) \ - $(INSTALL_DB_INSTALLS) $(INSTALL_DBD_INSTALLS) + $(INSTALL_DB_INSTALLS) clean: db_clean diff --git a/configure/RULES_BUILD b/configure/RULES_BUILD index bbd8e11d1..53297af52 100644 --- a/configure/RULES_BUILD +++ b/configure/RULES_BUILD @@ -103,17 +103,20 @@ include $(CONFIG)/RULES.Db #--------------------------------------------------------------- # Include defines and rules for prod, library and test* targets -#ifneq (,$(strip $(PROD) $(TESTPROD) $(LIBRARY) $(TESTLIBRARY) $(LOADABLE_LIBRARY) )) +ifneq (,$(strip $(PROD) $(TESTPROD) $(LIBRARY) $(TESTLIBRARY) \ + $(LOADABLE_LIBRARY))) include $(CONFIG)/RULES_TARGET -#endif +endif #--------------------------------------------------------------- # Read dependency files +ifneq (inc,$(strip $(MAKECMDGOALS))) ifneq (,$(strip $(HDEPENDS_FILES))) $(filter-out $(wildcard *$(DEP)), $(HDEPENDS_FILES)): | $(COMMON_INC) -include $(HDEPENDS_FILES) endif +endif #--------------------------------------------------------------- # Products and Object libraries @@ -161,12 +164,13 @@ build: inc build: $(OBJSNAME) $(LIBTARGETS) $(PRODTARGETS) $(TESTPRODTARGETS) \ $(TARGETS) $(TESTSCRIPTS) $(INSTALL_LIB_INSTALLS) -inc: $(COMMON_INC) $(INSTALL_INC) $(INSTALL_CONFIGS) +inc: $(COMMON_INC) $(INSTALL_INC) $(INSTALL_CONFIGS) $(INSTALLS_CFG) \ + $(INSTALL_HTMLS) $(INSTALLS_PERL_MODULES) $(INSTALL_SCRIPTS) buildInstall: \ - $(INSTALL_SCRIPTS) $(INSTALL_PROD) $(INSTALL_MUNCHS) \ + $(INSTALL_PROD) $(INSTALL_MUNCHS) \ $(INSTALL_TCLLIBS) $(INSTALL_TCLINDEX) \ - $(INSTALL_HTMLS) $(INSTALL_DOCS) \ + $(INSTALL_DOCS) \ $(INSTALL_OBJS) \ $(INSTALL_TEMPLATE) \ $(INSTALL_BIN_INSTALLS) diff --git a/configure/RULES_TARGET b/configure/RULES_TARGET index 5d77b105e..06f8a447d 100644 --- a/configure/RULES_TARGET +++ b/configure/RULES_TARGET @@ -21,7 +21,6 @@ $(foreach target, $(PROD) $(TESTPROD) $(LIBRARY) $(TESTLIBRARY) $(LOADABLE_LIBRA #----------------------------------------------------------------------- -# This define block requires GNU make 3.81 define PROD_template ifeq ($$(strip $$($(1)_OBJS) $$($(1)_SRCS) $$(PRODUCT_OBJS)),) $(1)_OBJS = $(1)$$(OBJ) diff --git a/configure/RULES_TOP b/configure/RULES_TOP index ec0597a49..60b52e0de 100644 --- a/configure/RULES_TOP +++ b/configure/RULES_TOP @@ -73,7 +73,7 @@ help: @echo "Usage: gnumake [options] [target] ..." @echo "Targets supported by all Makefiles:" @echo " all - Same as install (default rule)" - @echo " inc - Installs header files" + @echo " inc - Installs header, dbd and html files" @echo " build - Builds and installs all targets" @echo " install - Builds and installs all targets" @echo " buildInstall - Same as install (deprecated)" diff --git a/configure/os/CONFIG.Common.RTEMS b/configure/os/CONFIG.Common.RTEMS index 1319a7b50..b19b2071f 100644 --- a/configure/os/CONFIG.Common.RTEMS +++ b/configure/os/CONFIG.Common.RTEMS @@ -28,12 +28,13 @@ ifneq ($(CONFIG),$(TOP)/configure) endif #-------------------------------------------------- -# Set RTEMS_BSP from T_A if not already done +# Set RTEMS_BSP and GNU_TARGET if not already done RTEMS_BSP ?= $(subst RTEMS-,,$(T_A)) +GNU_TARGET ?= $(RTEMS_TARGET_CPU)-rtems #------------------------------------------------------- # Pick up the RTEMS tool/path definitions from the RTEMS BSP directory. -include $(RTEMS_BASE)/$(RTEMS_TARGET_CPU)-rtems$(RTEMS_VERSION)/$(RTEMS_BSP)/Makefile.inc +include $(RTEMS_BASE)/$(GNU_TARGET)$(RTEMS_VERSION)/$(RTEMS_BSP)/Makefile.inc include $(RTEMS_CUSTOM) include $(CONFIG.CC) @@ -41,7 +42,7 @@ include $(CONFIG.CC) # RTEMS cross-development tools CC = $(RTEMS_TOOLS)/bin/$(CC_FOR_TARGET) $(GCCSPECS) -fasm CCC = $(RTEMS_TOOLS)/bin/$(CXX) -CPP = $(RTEMS_TOOLS)/bin/$(CC_FOR_TARGET) -x c -E +CPP = $(RTEMS_TOOLS)/bin/$(CC_FOR_TARGET) -x c -E $(GCCSPECS) AR = $(RTEMS_TOOLS)/bin/$(AR_FOR_TARGET) LD = $(RTEMS_TOOLS)/bin/$(LD_FOR_TARGET) -r @@ -95,20 +96,39 @@ MODEXT=.obj OS_CLASS = RTEMS #-------------------------------------------------- -# Operating system flags -OP_SYS_LDLIBS += -lrtemsCom -lc -lrtemscpu -lCom -lnfs -lm -OP_SYS_LDFLAGS += $(CPU_CFLAGS) -u Init \ +# Operating system compile & link flags +OP_SYS_CFLAGS += -D__LINUX_ERRNO_EXTENSIONS__ + +OP_SYS_CFLAGS_NET_yes = -DRTEMS_LEGACY_STACK +OP_SYS_CFLAGS += $(OP_SYS_CFLAGS_NET_$(RTEMS_HAS_NETWORKING)) + +ifeq ($(RTEMS_HAS_POSIX_API),yes) +POSIX_CPPFLAGS = -D_GNU_SOURCE -D_DEFAULT_SOURCE +endif + +OP_SYS_LDLIBS_posix_NET_yes = -ltftpfs -lnfs -lz -ltelnetd +OP_SYS_LDLIBS_posix_NET_no = -ltftpfs -lbsd -lz +OP_SYS_LDLIBS_score_NET_yes = -lnfs +OP_SYS_LDLIBS_score_NET_no = -lnfs +OP_SYS_LDLIBS += -lrtemsCom -lCom +OP_SYS_LDLIBS += $(OP_SYS_LDLIBS_$(OS_API)_NET_$(RTEMS_HAS_NETWORKING)) +OP_SYS_LDLIBS += -lrtemscpu -lc -lm + +OP_SYS_LDFLAGS_posix = -u POSIX_Init +OP_SYS_LDFLAGS_score = -u Init \ $(PROJECT_RELEASE)/lib/no-dpmem.rel \ $(PROJECT_RELEASE)/lib/no-mp.rel \ $(PROJECT_RELEASE)/lib/no-part.rel \ $(PROJECT_RELEASE)/lib/no-signal.rel \ $(PROJECT_RELEASE)/lib/no-rtmon.rel +OP_SYS_LDFLAGS += $(CPU_CFLAGS) $(OP_SYS_LDFLAGS_$(OS_API)) +# Settings for GeSys MOD_SYS_LDFLAGS += $(CPU_CFLAGS) -Wl,-r -nostdlib # Do not link against libraries which are part of the Generic Image GESYS_LIBS += -lgcc -GESYS_LIBS += -lc -lm -lrtemscpu -lrtemsbsp -lrtems++ -lbspExt +GESYS_LIBS += -lc -lm -lrtemscpu -lrtemsbsp -lrtems++ GESYS_LIBS += -lcexp -ltecla_r -lspencer_regexp -lpmelf -lpmbfd GESYS_LIBS += -lnfs -ltelnetd -lrtems-gdb-stub diff --git a/configure/os/CONFIG.Common.RTEMS-at91rm9200ek b/configure/os/CONFIG.Common.RTEMS-at91rm9200ek deleted file mode 100644 index 735c07bb5..000000000 --- a/configure/os/CONFIG.Common.RTEMS-at91rm9200ek +++ /dev/null @@ -1,14 +0,0 @@ -# -# CONFIG.Common.RTEMS-at91rm9200ek -# Author: Ralf Hartmann -# BESSY -# Ralf.Hartmann@bessy.de -# -# Atmel AT91RM9200-EK evaluation kit -# using the AT91RM9200 ARM9-based 32-bit RISC microcontroller -# -# All RTEMS targets use the same Makefile fragment -# -RTEMS_BSP = at91rm9200ek -RTEMS_TARGET_CPU = arm -include $(CONFIG)/os/CONFIG.Common.RTEMS diff --git a/configure/os/CONFIG.Common.RTEMS-beagleboneblack b/configure/os/CONFIG.Common.RTEMS-beagleboneblack new file mode 100644 index 000000000..4b6107b05 --- /dev/null +++ b/configure/os/CONFIG.Common.RTEMS-beagleboneblack @@ -0,0 +1,18 @@ +# +# CONFIG.Common.RTEMS-beaglebineblack +# Author: Heinz Junkes +# +# All RTEMS targets use the same Makefile fragment +# +#EXE = .elf +RTEMS_BSP = beagleboneblack +RTEMS_TARGET_CPU = arm +GNU_TARGET = arm-rtems + +OP_SYS_LDLIBS += -Wl,--gc-sections +ARCH_DEP_LDFLAGS = -L$(RTEMS_BASE)/$(GNU_TARGET)$(RTEMS_VERSION)/beagleboneblack/lib/ + +include $(CONFIG)/os/CONFIG.Common.RTEMS + + + diff --git a/configure/os/CONFIG.Common.RTEMS-beatnik b/configure/os/CONFIG.Common.RTEMS-beatnik index aaa45e4c9..b133fd489 100644 --- a/configure/os/CONFIG.Common.RTEMS-beatnik +++ b/configure/os/CONFIG.Common.RTEMS-beatnik @@ -8,14 +8,16 @@ EXE = .elf RTEMS_BSP = beatnik RTEMS_TARGET_CPU = powerpc GNU_TARGET = powerpc-rtems -ARCH_DEP_CFLAGS += -DMY_DO_BOOTP=NULL +# optimization trouble in postfix.c +ARCH_DEP_CFLAGS += -DRTEMS_HAS_ALTIVEC +#will use bootp +#ARCH_DEP_CFLAGS += -DMY_DO_BOOTP=NULL ARCH_DEP_CFLAGS += -DHAVE_MOTLOAD ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_CONFIG_MBUF_SPACE=2048 ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_CONFIG_CLUSTER_SPACE=5120 -OP_SYS_LDLIBS += -lbspExt - MUNCH_SUFFIX = .boot +MUNCHNAME = $(PRODNAME:%$(EXE)=%$(MUNCH_SUFFIX)) define MUNCH_CMD $(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary $< $@ endef diff --git a/configure/os/CONFIG.Common.RTEMS-gen68360 b/configure/os/CONFIG.Common.RTEMS-gen68360 deleted file mode 100644 index 0a8a6e85e..000000000 --- a/configure/os/CONFIG.Common.RTEMS-gen68360 +++ /dev/null @@ -1,10 +0,0 @@ -# -# Author: W. Eric Norum -# Canadian Light Source -# eric@cls.usask.ca -# -# All RTEMS targets use the same Makefile fragment -# -RTEMS_BSP = gen68360 -RTEMS_TARGET_CPU = m68k -include $(CONFIG)/os/CONFIG.Common.RTEMS diff --git a/configure/os/CONFIG.Common.RTEMS-mcp750 b/configure/os/CONFIG.Common.RTEMS-mcp750 deleted file mode 100644 index 035e6eb36..000000000 --- a/configure/os/CONFIG.Common.RTEMS-mcp750 +++ /dev/null @@ -1,10 +0,0 @@ -# -# Author: W. Eric Norum -# Canadian Light Source -# eric@cls.usask.ca -# -# All RTEMS targets use the same Makefile fragment -# -RTEMS_BSP = mcp750 -RTEMS_TARGET_CPU = ppc -include $(CONFIG)/os/CONFIG.Common.RTEMS diff --git a/configure/os/CONFIG.Common.RTEMS-mvme167 b/configure/os/CONFIG.Common.RTEMS-mvme167 deleted file mode 100644 index 3651f966f..000000000 --- a/configure/os/CONFIG.Common.RTEMS-mvme167 +++ /dev/null @@ -1,10 +0,0 @@ -# -# Author: W. Eric Norum -# Canadian Light Source -# eric@cls.usask.ca -# -# All RTEMS targets use the same Makefile fragment -# -RTEMS_BSP = mvme167 -RTEMS_TARGET_CPU = m68k -include $(CONFIG)/os/CONFIG.Common.RTEMS diff --git a/configure/os/CONFIG.Common.RTEMS-mvme2100 b/configure/os/CONFIG.Common.RTEMS-mvme2100 index a8e8bf76e..1e222b5ab 100644 --- a/configure/os/CONFIG.Common.RTEMS-mvme2100 +++ b/configure/os/CONFIG.Common.RTEMS-mvme2100 @@ -11,8 +11,6 @@ GNU_TARGET = powerpc-rtems ARCH_DEP_CFLAGS += -DMY_DO_BOOTP=NULL ARCH_DEP_CFLAGS += -DHAVE_PPCBUG -OP_SYS_LDLIBS += -lbspExt - MUNCH_SUFFIX = .boot define MUNCH_CMD $(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary -R .comment -S $< rtems diff --git a/configure/os/CONFIG.Common.RTEMS-mvme2700 b/configure/os/CONFIG.Common.RTEMS-mvme2700 index a5ad7fbf5..655e0a5b0 100644 --- a/configure/os/CONFIG.Common.RTEMS-mvme2700 +++ b/configure/os/CONFIG.Common.RTEMS-mvme2700 @@ -20,6 +20,4 @@ define MUNCH_CMD rm -f rtems.gz endef -OP_SYS_LDLIBS += -lbspExt - include $(CONFIG)/os/CONFIG.Common.RTEMS diff --git a/configure/os/CONFIG.Common.RTEMS-mvme3100 b/configure/os/CONFIG.Common.RTEMS-mvme3100 index 283e7d680..2cbf49a84 100644 --- a/configure/os/CONFIG.Common.RTEMS-mvme3100 +++ b/configure/os/CONFIG.Common.RTEMS-mvme3100 @@ -13,8 +13,6 @@ ARCH_DEP_CFLAGS += -DHAVE_MOTLOAD ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_CONFIG_MBUF_SPACE=2048 ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_CONFIG_CLUSTER_SPACE=5120 -OP_SYS_LDLIBS += -lbspExt - MUNCH_SUFFIX = .boot define MUNCH_CMD $(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary $< $@ diff --git a/configure/os/CONFIG.Common.RTEMS-mvme5500 b/configure/os/CONFIG.Common.RTEMS-mvme5500 index 0329185bb..a240a298a 100644 --- a/configure/os/CONFIG.Common.RTEMS-mvme5500 +++ b/configure/os/CONFIG.Common.RTEMS-mvme5500 @@ -14,13 +14,9 @@ ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_CONFIG_MBUF_SPACE=2048 ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_CONFIG_CLUSTER_SPACE=5120 ARCH_DEP_CFLAGS += -DBSP_NVRAM_BASE_ADDR=0xf1110000 -OP_SYS_LDLIBS += -lbspExt - MUNCH_SUFFIX = .boot define MUNCH_CMD $(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary $< $@ endef -OP_SYS_LDLIBS += -lbspExt - include $(CONFIG)/os/CONFIG.Common.RTEMS diff --git a/configure/os/CONFIG.Common.RTEMS-pc386 b/configure/os/CONFIG.Common.RTEMS-pc386 index 8dfa7d2ba..9fc518d6b 100644 --- a/configure/os/CONFIG.Common.RTEMS-pc386 +++ b/configure/os/CONFIG.Common.RTEMS-pc386 @@ -1,12 +1,13 @@ +# CONFIG.Common.RTEMS-pc386 # -# Author: W. Eric Norum -# Canadian Light Source -# eric@cls.usask.ca -# -# All RTEMS targets use the same Makefile fragment +# Definitions for the RTEMS-pc386 target, RTEMS 4.x only +# Site-specific overrides go in CONFIG_SITE.Common.RTEMS-pc386 # +#------------------------------------------------------- + RTEMS_BSP = pc386 RTEMS_TARGET_CPU = i386 +GNU_TARGET = i386-rtems MUNCH_SUFFIX = .boot define MUNCH_CMD @@ -22,3 +23,10 @@ include $(CONFIG)/os/CONFIG.Common.RTEMS # Put text segment where it will work with etherboot # OP_SYS_LDFLAGS += -Wl,-Ttext,0x100000 + +# This check must appear after the above include +ifeq ($(RTEMS_VERSION),5) + $(info *** This target is not compatible with the configured RTEMS version.) + $(info *** Build the RTEMS-pc686 (-qemu) target for RTEMS 5.x) + $(error Can't continue) +endif diff --git a/configure/os/CONFIG.Common.RTEMS-pc386-qemu b/configure/os/CONFIG.Common.RTEMS-pc386-qemu index 684f01a19..07bf30e7c 100644 --- a/configure/os/CONFIG.Common.RTEMS-pc386-qemu +++ b/configure/os/CONFIG.Common.RTEMS-pc386-qemu @@ -6,6 +6,7 @@ #------------------------------------------------------- # Include definitions from RTEMS-pc386 +# For Tests overwrite it with pc686 include $(CONFIG)/os/CONFIG.Common.RTEMS-pc386 RTEMS_QEMU_FIXUPS = YES diff --git a/configure/os/CONFIG.Common.RTEMS-pc686 b/configure/os/CONFIG.Common.RTEMS-pc686 new file mode 100644 index 000000000..882a2f3cb --- /dev/null +++ b/configure/os/CONFIG.Common.RTEMS-pc686 @@ -0,0 +1,39 @@ +# CONFIG.Common.RTEMS-pc686 +# +# Definitions for the RTEMS-pc686 target, RTEMS 5.x only +# Site-specific overrides go in CONFIG_SITE.Common.RTEMS-pc686 +# +#------------------------------------------------------- +# +# Author: W. Eric Norum +# Canadian Light Source +# eric@cls.usask.ca +# +# All RTEMS targets use the same Makefile fragment +# +RTEMS_BSP = pc686 +RTEMS_TARGET_CPU = i386 +GNU_TARGET = i386-rtems + +MUNCH_SUFFIX = .boot +define MUNCH_CMD + $(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary -R .comment -S $< $@ +endef + +OP_SYS_LDLIBS += -Wl,--gc-sections +ARCH_DEP_LDFLAGS = -L$(RTEMS_BASE)/$(GNU_TARGET)$(RTEMS_VERSION)/pc686/lib/ + +include $(CONFIG)/os/CONFIG.Common.RTEMS + +# +# Put text segment where it will work with etherboot +# +OP_SYS_LDFLAGS += -Wl,-Ttext,0x100000 + + +# This check must appear after the above include +ifneq ($(RTEMS_VERSION),5) + $(info *** This target is not compatible with the configured RTEMS version.) + $(info *** Build the RTEMS-pc386 (-qemu) target for RTEMS 4.x) + $(error Can't continue) +endif diff --git a/configure/os/CONFIG.Common.RTEMS-pc686-qemu b/configure/os/CONFIG.Common.RTEMS-pc686-qemu new file mode 100644 index 000000000..1de543a30 --- /dev/null +++ b/configure/os/CONFIG.Common.RTEMS-pc686-qemu @@ -0,0 +1,11 @@ +# CONFIG.Common.RTEMS-pc686-qemu +# +# Definitions for the RTEMS-pc686-qemu target +# Site-specific overrides go in CONFIG_SITE.Common.RTEMS-pc686-qemu +# +#------------------------------------------------------- + +# Include definitions from RTEMS-pc686 +include $(CONFIG)/os/CONFIG.Common.RTEMS-pc686 + +RTEMS_QEMU_FIXUPS = YES diff --git a/configure/os/CONFIG.Common.RTEMS-psim b/configure/os/CONFIG.Common.RTEMS-psim deleted file mode 100644 index 58ad72852..000000000 --- a/configure/os/CONFIG.Common.RTEMS-psim +++ /dev/null @@ -1,10 +0,0 @@ -# -# Author: W. Eric Norum -# University of Saskatchewan -# eric.norum@usask.ca -# -# All RTEMS targets use the same Makefile fragment -# -RTEMS_BSP = psim -RTEMS_TARGET_CPU = ppc -include $(CONFIG)/os/CONFIG.Common.RTEMS diff --git a/configure/os/CONFIG.Common.RTEMS-qoriq_e500 b/configure/os/CONFIG.Common.RTEMS-qoriq_e500 new file mode 100644 index 000000000..7f5c42e8e --- /dev/null +++ b/configure/os/CONFIG.Common.RTEMS-qoriq_e500 @@ -0,0 +1,48 @@ +# +# CONFIG.Common.RTEMS-qoriq_e500 +# Author: Heinz Junkes +# +# All RTEMS targets use the same Makefile fragment +# +EXE = .elf +RTEMS_BSP = qoriq_e500 +RTEMS_TARGET_CPU = powerpc +GNU_TARGET = powerpc-rtems +# optimization trouble in postfix.c +ARCH_DEP_CFLAGS += -DRTEMS_HAS_ALTIVEC +#will use bootp +#ARCH_DEP_CFLAGS += -DMY_DO_BOOTP=NULL + +#ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_CONFIG_MBUF_SPACE=2048 +#ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_CONFIG_CLUSTER_SPACE=5120 + +#netbsdlib +#ARCH_DEP_CFLAGS += -I$(RTEMS_BASE)/powerpc-rtems5/qoriq_e500/lib/include + +#OP_SYS_LDLIBS += -lbspExt #does not use posix stuff ... want to ignore +OP_SYS_LDLIBS += -Wl,--gc-sections +#ARCH_DEP_LDFLAGS = -mcpu=8540 -meabi -msdata=sysv -mstrict-align -mspe -mabi=spe -mfloat-gprs=double +ARCH_DEP_LDFLAGS = -L$(RTEMS_BASE)/powerpc-rtems5/qoriq_e500/lib + +MUNCH_SUFFIX = .img +MUNCHNAME = $(PRODNAME:%$(EXE)=%$(MUNCH_SUFFIX)) +define MUNCH_CMD + $(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary $< $@ + gzip -9 -f $@ + $(RTEMS_TOOLS)/bin/mkimage.py -A ppc -O linux -T kernel -a 0x4000 -e 0x4000 -n $* -d $@.gz $*.img +endef + +include $(CONFIG)/os/CONFIG.Common.RTEMS + +RTEMSSYMS=$(PRODNAME:%$(EXE)=%.sym) +RTEMSIMGS=$(PRODNAME:%$(EXE)=%.bin) +INSTALL_RTEMSSYMS=$(RTEMSSYMS:%=$(INSTALL_BIN)/%) +INSTALL_RTEMSIMGS=$(RTEMSIMGS:%=$(INSTALL_BIN)/%) + +%.sym: %$(EXE) + $(XSYMS) $^ $@ + +%.bin: %$(EXE) + $(OBJCOPY) -Obinary $^ $@ + +#PRODTARGETS+=$(INSTALL_RTEMSSYMS) $(INSTALL_RTEMSIMGS) diff --git a/configure/os/CONFIG.Common.RTEMS-uC5282 b/configure/os/CONFIG.Common.RTEMS-uC5282 index 2cb215aca..c0cdaff74 100644 --- a/configure/os/CONFIG.Common.RTEMS-uC5282 +++ b/configure/os/CONFIG.Common.RTEMS-uC5282 @@ -9,6 +9,10 @@ RTEMS_BSP = uC5282 RTEMS_TARGET_CPU = m68k ARCH_DEP_CFLAGS += -DMY_DO_BOOTP=NULL +# Hopefully a temporary fix: +ARCH_DEP_CXXFLAGS_5 = -std=c++98 +ARCH_DEP_CXXFLAGS += $(ARCH_DEP_CXXFLAGS_$(RTEMS_VERSION)) + MUNCH_SUFFIX = .boot define MUNCH_CMD $(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary -R .comment -S $< $@ diff --git a/configure/os/CONFIG.Common.RTEMS-xilinx_zynq_a9_qemu b/configure/os/CONFIG.Common.RTEMS-xilinx_zynq_a9_qemu new file mode 100644 index 000000000..83b518b69 --- /dev/null +++ b/configure/os/CONFIG.Common.RTEMS-xilinx_zynq_a9_qemu @@ -0,0 +1,20 @@ +# +# CONFIG.Common.RTEMS-xilinx_zynq_a9_qemu +# Author: Heinz Junkes +# +# All RTEMS targets use the same Makefile fragment +# +#EXE = .elf +RTEMS_BSP = xilinx_zynq_a9_qemu +RTEMS_TARGET_CPU = arm +GNU_TARGET = arm-rtems + +#use dhcp/bootp +ARCH_DEP_CFLAGS += -DMY_DO_BOOTP=NULL + +OP_SYS_LDLIBS += -Wl,--gc-sections +ARCH_DEP_LDFLAGS = -L$(RTEMS_BASE)/$(GNU_TARGET)$(RTEMS_VERSION)/xilinx_zynq_a9_qemu/lib/ + + +include $(CONFIG)/os/CONFIG.Common.RTEMS + diff --git a/configure/os/CONFIG.Common.RTEMS-xilinx_zynq_zedboard b/configure/os/CONFIG.Common.RTEMS-xilinx_zynq_zedboard new file mode 100644 index 000000000..bac33eb91 --- /dev/null +++ b/configure/os/CONFIG.Common.RTEMS-xilinx_zynq_zedboard @@ -0,0 +1,19 @@ +# +# CONFIG.Common.RTEMS-xilinx_zynq_zedboard +# Author: Heinz Junkes +# +# All RTEMS targets use the same Makefile fragment +# +#EXE = .elf +RTEMS_BSP = xilinx_zynq_zedboard +RTEMS_TARGET_CPU = arm +GNU_TARGET = arm-rtems + +OP_SYS_LDLIBS += -Wl,--gc-sections +ARCH_DEP_LDFLAGS = -L$(RTEMS_BASE)/$(GNU_TARGET)$(RTEMS_VERSION)/xilinx_zynq_zedboard/lib/ + + +include $(CONFIG)/os/CONFIG.Common.RTEMS + + + diff --git a/configure/os/CONFIG.Common.darwin-ppc b/configure/os/CONFIG.Common.darwin-ppc deleted file mode 100644 index 7ac704314..000000000 --- a/configure/os/CONFIG.Common.darwin-ppc +++ /dev/null @@ -1,14 +0,0 @@ -# CONFIG.Common.darwin-ppc -# -# This file is maintained by the build community. -# -# Definitions for darwin-ppc target builds -# Sites may override these definitions in CONFIG_SITE.Common.darwin-ppc -#------------------------------------------------------- - -# -# To build universal binaries, configure ARCH_CLASS -# in the file CONFIG_SITE.Common.darwin-ppc - -# Include definitions common to all Darwin targets -include $(CONFIG)/os/CONFIG.darwinCommon.darwinCommon diff --git a/configure/os/CONFIG.Common.darwin-ppcx86 b/configure/os/CONFIG.Common.darwin-ppcx86 deleted file mode 100644 index 12107944f..000000000 --- a/configure/os/CONFIG.Common.darwin-ppcx86 +++ /dev/null @@ -1,14 +0,0 @@ -# CONFIG.Common.darwin-ppcx86 -# -# This file is maintained by the build community. -# -# Definitions for Darwin universal PowerPC + x86 target builds -# Sites may override these definitions in CONFIG_SITE.Common.darwin-ppcx86 -#------------------------------------------------------- - -# -# To build universal binaries, configure ARCH_CLASS -# in the file CONFIG_SITE.Common.darwin-ppcx86 - -# Include definitions common to all Darwin targets -include $(CONFIG)/os/CONFIG.darwinCommon.darwinCommon diff --git a/configure/os/CONFIG.Common.linux-386 b/configure/os/CONFIG.Common.linux-386 deleted file mode 100644 index a224ff328..000000000 --- a/configure/os/CONFIG.Common.linux-386 +++ /dev/null @@ -1,21 +0,0 @@ -# CONFIG.Common.linux-386 -# -# This file is maintained by the build community. -# -# Definitions for linux-386 target builds -# Sites may override these definitions in CONFIG_SITE.Common.linux-386 -#------------------------------------------------------- - -# Include definitions common to all linux x86 targets -include $(CONFIG)/os/CONFIG.Common.linux-x86 - -ARCH_DEP_CFLAGS = -march=i386 - -ifeq ($(BUILD_CLASS),CROSS) - VALID_BUILDS = Ioc Command -endif - -# If your crosscompiler name has a GNU target prefix like -gcc, -# e.g. i386-pc-linux-gnu-gcc, put a GNU_TARGET definition in -# CONFIG_SITE..linux-386 file, e.g. GNU_TARGET=i386-pc-linux-gnu - diff --git a/configure/os/CONFIG.Common.linux-486 b/configure/os/CONFIG.Common.linux-486 deleted file mode 100644 index 79b533015..000000000 --- a/configure/os/CONFIG.Common.linux-486 +++ /dev/null @@ -1,19 +0,0 @@ -# CONFIG.Common.linux-486 -# -# Definitions for linux-486 target builds -# Sites may override these definitions in CONFIG_SITE.Common.linux-486 -#------------------------------------------------------- - -# Include definitions common to all linux x86 targets -include $(CONFIG)/os/CONFIG.Common.linux-x86 - -ARCH_DEP_CFLAGS = -march=i486 - -ifeq ($(BUILD_CLASS),CROSS) - VALID_BUILDS = Ioc Command -endif - -# If your crosscompiler name has a GNU target prefix like -gcc, -# e.g. i486-pc-linux-gnu-gcc, put a GNU_TARGET definition in -# CONFIG_SITE..linux-486 file, e.g. GNU_TARGET=i486-pc-linux-gnu - diff --git a/configure/os/CONFIG.Common.linux-586 b/configure/os/CONFIG.Common.linux-586 deleted file mode 100644 index b2b3b9b5c..000000000 --- a/configure/os/CONFIG.Common.linux-586 +++ /dev/null @@ -1,21 +0,0 @@ -# CONFIG.Common.linux-586 -# -# Definitions for linux-586 target builds -# Sites may override these definitions in CONFIG_SITE.Common.linux-586 -#------------------------------------------------------- - -# Include definitions common to all linux x86 targets -include $(CONFIG)/os/CONFIG.Common.linux-x86 - -# i586 is equivalent to pentium -ARCH_DEP_CFLAGS = -march=i586 - -ifeq ($(BUILD_CLASS),CROSS) - VALID_BUILDS = Ioc Command -endif - -# If your crosscompiler name has a GNU target prefix like -gcc, -# e.g. i586-pc-linux-gnu-gcc, put a GNU_TARGET definition in -# CONFIG_SITE..linux-586 file, e.g. GNU_TARGET=i586-pc-linux-gnu - - diff --git a/configure/os/CONFIG.Common.linux-686 b/configure/os/CONFIG.Common.linux-686 deleted file mode 100644 index a327d7e43..000000000 --- a/configure/os/CONFIG.Common.linux-686 +++ /dev/null @@ -1,20 +0,0 @@ -# CONFIG.Common.linux-686 -# -# Definitions for linux-686 target builds -# Sites may override these definitions in CONFIG_SITE.Common.linux-686 -#------------------------------------------------------- - -# Include definitions common to all linux x86 targets -include $(CONFIG)/os/CONFIG.Common.linux-x86 - -# i686 is euivalent to pentiumpro -ARCH_DEP_CFLAGS = -march=i686 - -ifeq ($(BUILD_CLASS),CROSS) - VALID_BUILDS = Ioc Command -endif - -# If your crosscompiler name has a GNU target prefix like -gcc, -# e.g. i686-pc-linux-gnu-gcc, put a GNU_TARGET definition in -# CONFIG_SITE..linux-686 file, e.g. GNU_TARGET=i686-pc-linux-gnu - diff --git a/configure/os/CONFIG.Common.linux-athlon b/configure/os/CONFIG.Common.linux-athlon deleted file mode 100644 index a773a4996..000000000 --- a/configure/os/CONFIG.Common.linux-athlon +++ /dev/null @@ -1,19 +0,0 @@ -# CONFIG.Common.linux-athlon -# -# Definitions for linux-athlon target builds -# Sites may override these definitions in CONFIG_SITE.Common.linux-athlon -#------------------------------------------------------- - -# Include definitions common to all linux x86 targets -include $(CONFIG)/os/CONFIG.Common.linux-x86 - -ARCH_DEP_CFLAGS += -march=athlon-mp -mfpmath=sse - -ifeq ($(BUILD_CLASS),CROSS) - VALID_BUILDS = Ioc Command -endif - -# If your crosscompiler name has a GNU target prefix like -gcc, -# e.g. athlon-pc-linux-gnu-gcc, put a GNU_TARGET definition in -# CONFIG_SITE..linux-athlon file, e.g. GNU_TARGET=athlon-pc-linux-gnu - diff --git a/configure/os/CONFIG.Common.linux-cris b/configure/os/CONFIG.Common.linux-cris deleted file mode 100644 index d419b23e8..000000000 --- a/configure/os/CONFIG.Common.linux-cris +++ /dev/null @@ -1,58 +0,0 @@ -# CONFIG.Common.linux-cris -# -# Author: Peter Zumbruch -# GSI -# P.Zumbruch@gsi.de -# -# Definitions for linux-cris target builds -# Sites may override these definitions in CONFIG_SITE.Common.linux-cris -#------------------------------------------------------- - -# Include definitions common to all linux targets -include $(CONFIG)/os/CONFIG.Common.linuxCommon - -ARCH_CLASS = cris - -ifeq ($(BUILD_CLASS),CROSS) - GNU_TARGET = cris-axis-linux-gnu - - # prefix of compiler tools - CMPLR_SUFFIX = - CMPLR_PREFIX = $(addsuffix -,$(GNU_TARGET)) - - # CROSS_TOP_DIR - # usually AXIS_TOP_DIR is defined via - # the init_env script of the SDK provided by Axis - # - ## AXIS_TOP_DIR defined? Make missing mandatory variable visible - AXIS_TOP_DIR?=UNDEFINED_ENV__AXIS_TOP_DIR - AXIS_SDK_DIR?=$(AXIS_TOP_DIR) - - # CROSS_INCLUDES - AXIS_SDK_TARGET_INCLUDE_DIR = $(AXIS_SDK_DIR)/target/$(GNU_TARGET)/include - AXIS_SDK_TARGET_INCLUDE_DIR +=$(AXIS_SDK_DIR)/target/$(GNU_TARGET)/usr/include - - CROSS_INCLUDES = $(addprefix -isystem ,$(AXIS_SDK_TARGET_INCLUDE_DIR)) - - # CROSS_LDFLAGS - AXIS_SDK_TARGET_LIB_DIR = $(AXIS_SDK_DIR)/target/$(GNU_TARGET)/lib - AXIS_SDK_TARGET_LIB_DIR += $(AXIS_SDK_DIR)/target/$(GNU_TARGET)/usr/lib - - CROSS_LDFLAGS = $(addprefix -L,$(AXIS_SDK_TARGET_LIB_DIR)) - --include $(CONFIG)/os/CONFIG_SITE.Common.linux-cris -ifeq ($(EPICS_HOST_ARCH), linux-x86) --include $(CONFIG)/os/CONFIG.linux-x86.linux-cris --include $(CONFIG)/os/CONFIG_SITE.linux-x86.linux-cris -endif -endif - -SHARED_LIBRARIES=NO -STATIC_BUILD=YES - -ARCH_DEP_CFLAGS += -mno-mul-bug-workaround -OP_SYS_CFLAGS += -mlinux -ARCH_DEP_CPPFLAGS += -D_cris_ -mlinux - -#uncomment CRIS_COMPILER_DEBUG for debugging cris-compiled code -#CRIS_COMPILER_DEBUG diff --git a/configure/os/CONFIG.darwin-ppc.Common b/configure/os/CONFIG.darwin-ppc.Common deleted file mode 100644 index ac176878f..000000000 --- a/configure/os/CONFIG.darwin-ppc.Common +++ /dev/null @@ -1,8 +0,0 @@ -# CONFIG.darwin-ppc.Common -# -# Definitions for darwin-ppc host builds -# Sites may override these definitions in CONFIG_SITE.darwin-ppc.Common -#------------------------------------------------------- - -#Include definitions common to unix hosts -include $(CONFIG)/os/CONFIG.UnixCommon.Common diff --git a/configure/os/CONFIG.darwin-ppc.darwin-ppc-debug b/configure/os/CONFIG.darwin-ppc.darwin-ppc-debug deleted file mode 100644 index 985052031..000000000 --- a/configure/os/CONFIG.darwin-ppc.darwin-ppc-debug +++ /dev/null @@ -1,13 +0,0 @@ -# CONFIG.darwin-ppc.darwin-ppc-debug -# -# Definitions for darwin-ppc host - darwin-ppc-debug target build with debug compiler flags -# Sites may override these definitions in CONFIG_SITE.darwin-ppc.darwin-ppc-debug -#------------------------------------------------------- - --include $(CONFIG)/os/CONFIG.Common.darwin-ppc --include $(CONFIG)/os/CONFIG.darwin-ppc.darwin-ppc --include $(CONFIG)/os/CONFIG_SITE.Common.darwin-ppc --include $(CONFIG)/os/CONFIG_SITE.darwin-ppc.darwin-ppc - -BUILD_CLASS=HOST -HOST_OPT = NO diff --git a/configure/os/CONFIG.darwin-ppcx86.Common b/configure/os/CONFIG.darwin-ppcx86.Common deleted file mode 100644 index 749835ced..000000000 --- a/configure/os/CONFIG.darwin-ppcx86.Common +++ /dev/null @@ -1,8 +0,0 @@ -# CONFIG.darwin-ppcx86.Common -# -# Definitions for Darwin universal PowerPC + x86 host builds -# Sites may override these definitions in CONFIG_SITE.darwin-ppcx86.Common -#------------------------------------------------------- - -#Include definitions common to unix hosts -include $(CONFIG)/os/CONFIG.UnixCommon.Common diff --git a/configure/os/CONFIG.darwin-x86.Common b/configure/os/CONFIG.darwin-x86.Common index e779f7dc1..c88d8f7ea 100644 --- a/configure/os/CONFIG.darwin-x86.Common +++ b/configure/os/CONFIG.darwin-x86.Common @@ -3,6 +3,6 @@ # Definitions for darwin-x86 host builds # Sites may override these definitions in CONFIG_SITE.darwin-x86.Common #------------------------------------------------------- - +#support for IPv6 etc. #Include definitions common to unix hosts include $(CONFIG)/os/CONFIG.UnixCommon.Common diff --git a/configure/os/CONFIG.darwinCommon.darwinCommon b/configure/os/CONFIG.darwinCommon.darwinCommon index bfd61830d..3ee6fd5f9 100644 --- a/configure/os/CONFIG.darwinCommon.darwinCommon +++ b/configure/os/CONFIG.darwinCommon.darwinCommon @@ -30,6 +30,7 @@ ARCH_DEP_LDFLAGS += $(ARCH_DEP_FLAGS) # # Special flags for Darwin # No common blocks (as required when using shared libraries) +# OS provides socket address length # OP_SYS_CFLAGS += -fno-common diff --git a/configure/os/CONFIG.linux-386.Common b/configure/os/CONFIG.linux-386.Common deleted file mode 100644 index 9a3633bdf..000000000 --- a/configure/os/CONFIG.linux-386.Common +++ /dev/null @@ -1,10 +0,0 @@ -# CONFIG.linux-386.Common -# -# Definitions for linux-386 host builds -# Sites may override these definitions in CONFIG_SITE.linux-386.Common -#------------------------------------------------------- - -#Include definitions common to unix hosts -include $(CONFIG)/os/CONFIG.UnixCommon.Common - -WIND_HOST_TYPE = x86-linux2 diff --git a/configure/os/CONFIG.linux-386.linux-386 b/configure/os/CONFIG.linux-386.linux-386 deleted file mode 100644 index f65ac46b7..000000000 --- a/configure/os/CONFIG.linux-386.linux-386 +++ /dev/null @@ -1,8 +0,0 @@ -# CONFIG.linux-386.linux-386 -# -# Definitions for linux-386 host - linux-386 target builds -# Sites may override these definitions in CONFIG_SITE.linux-386.linux-386 -#------------------------------------------------------- - -# Include linux-x86 compiler definitions -include $(CONFIG)/os/CONFIG.linux-x86.linux-x86 diff --git a/configure/os/CONFIG.linux-486.Common b/configure/os/CONFIG.linux-486.Common deleted file mode 100644 index c151b3218..000000000 --- a/configure/os/CONFIG.linux-486.Common +++ /dev/null @@ -1,10 +0,0 @@ -# CONFIG.linux-486.Common -# -# Definitions for linux-486 host builds -# Sites may override these definitions in CONFIG_SITE.linux-486.Common -#------------------------------------------------------- - -#Include definitions common to unix hosts -include $(CONFIG)/os/CONFIG.UnixCommon.Common - -WIND_HOST_TYPE = x86-linux2 diff --git a/configure/os/CONFIG.linux-486.linux-486 b/configure/os/CONFIG.linux-486.linux-486 deleted file mode 100644 index 551cacc29..000000000 --- a/configure/os/CONFIG.linux-486.linux-486 +++ /dev/null @@ -1,9 +0,0 @@ -# CONFIG.linux-486.linux-486 -# -# Definitions for linux-486 host - linux-486 target builds -# Sites may override these definitions in CONFIG_SITE.linux-486.linux-486 -#------------------------------------------------------- - -# Include linux-x86 compiler definitions -include $(CONFIG)/os/CONFIG.linux-x86.linux-x86 - diff --git a/configure/os/CONFIG.linux-586.Common b/configure/os/CONFIG.linux-586.Common deleted file mode 100644 index 43463e8a0..000000000 --- a/configure/os/CONFIG.linux-586.Common +++ /dev/null @@ -1,10 +0,0 @@ -# CONFIG.linux-586.Common -# -# Definitions for linux-586 host builds -# Sites may override these definitions in CONFIG_SITE.linux-586.Common -#------------------------------------------------------- - -#Include definitions common to unix hosts -include $(CONFIG)/os/CONFIG.UnixCommon.Common - -WIND_HOST_TYPE = x86-linux2 diff --git a/configure/os/CONFIG.linux-586.linux-586 b/configure/os/CONFIG.linux-586.linux-586 deleted file mode 100644 index 990bfad74..000000000 --- a/configure/os/CONFIG.linux-586.linux-586 +++ /dev/null @@ -1,9 +0,0 @@ -# CONFIG.linux-586.linux-586 -# -# Definitions for linux-586 host - linux-586 target builds -# Sites may override these definitions in CONFIG_SITE.linux-586.linux-586 -#------------------------------------------------------- - -# Include linux-x86 compiler definitions -include $(CONFIG)/os/CONFIG.linux-x86.linux-x86 - diff --git a/configure/os/CONFIG.linux-686.Common b/configure/os/CONFIG.linux-686.Common deleted file mode 100644 index f36cddeac..000000000 --- a/configure/os/CONFIG.linux-686.Common +++ /dev/null @@ -1,10 +0,0 @@ -# CONFIG.linux-686.Common -# -# Definitions for linux-686 host builds -# Sites may override these definitions in CONFIG_SITE.linux-686.Common -#------------------------------------------------------- - -#Include definitions common to unix hosts -include $(CONFIG)/os/CONFIG.UnixCommon.Common - -WIND_HOST_TYPE = x86-linux2 diff --git a/configure/os/CONFIG.linux-686.linux-686 b/configure/os/CONFIG.linux-686.linux-686 deleted file mode 100644 index e4195a40a..000000000 --- a/configure/os/CONFIG.linux-686.linux-686 +++ /dev/null @@ -1,9 +0,0 @@ -# CONFIG.linux-686.linux-686 -# -# Definitions for linux-686 host - linux-686 target builds -# Sites may override these definitions in CONFIG_SITE.linux-686.linux-686 -#------------------------------------------------------- - -# Include linux-x86 compiler definitions -include $(CONFIG)/os/CONFIG.linux-x86.linux-x86 - diff --git a/configure/os/CONFIG.linux-x86.linux-cris b/configure/os/CONFIG.linux-x86.linux-cris deleted file mode 100644 index 8244916e5..000000000 --- a/configure/os/CONFIG.linux-x86.linux-cris +++ /dev/null @@ -1,38 +0,0 @@ -# CONFIG.linux-x86.linux-cris -# -# Author: Peter Zumbruch -# GSI -# P.Zumbruch@gsi.de -# -# Definitions for linux-x86 host - linux-cris target builds -# Sites may override these definitions in CONFIG_SITE.linux-x86.linux-cris -#------------------------------------------------------- - -GNU_DIR = $(CRIS_CROSS_COMPILER) - -#STATIC_... -STATIC_LDFLAGS_YES= -Wl,-Bstatic - -## debian-gcc Bug#438641 -GNU_LDLIBS_YES = -STATIC_LDFLAGS_YES += -static-libgcc - -# if not in debug mode strip all symbols -ifndef CRIS_COMPILER_DEBUG -STATIC_LDFLAGS_YES += -Wl,--strip-all -endif - -ifeq ($(GNU),YES) -STATIC_LDFLAGS_NO = -lgcc -else -STATIC_LDFLAGS_NO = -endif - -STATIC_LDLIBS_YES= -STATIC_LDLIBS_NO= - -OPT_CXXFLAGS_YES = -Os - -ifeq ($(STATIC_BUILD), YES) - $(shell echo yes) -endif diff --git a/configure/os/CONFIG.linux-x86.linux-cris_v10 b/configure/os/CONFIG.linux-x86.linux-cris_v10 deleted file mode 100644 index a227ac07c..000000000 --- a/configure/os/CONFIG.linux-x86.linux-cris_v10 +++ /dev/null @@ -1,20 +0,0 @@ -# CONFIG.linux-x86.linux-cris_v10 -# -# Author: Peter Zumbruch -# GSI -# P.Zumbruch@gsi.de -# -# Definitions for linux-x86 host - linux-cris_v10 target builds -# Sites may override these definitions in CONFIG_SITE.linux-x86.linux-cris_v10 -#------------------------------------------------------- - -# Include definitions common to all linux-cris targets -include $(CONFIG)/os/CONFIG.Common.linux-cris - -GNU_TARGET = cris-axis-linux-gnu - -ARCH_DEP_CFLAGS += -march=v10 - -# if you are using different places for cris_v10 cris_v32 -# you have to define for each architecture -# AXIS_SDK_DIR= diff --git a/configure/os/CONFIG.linux-x86.linux-cris_v32 b/configure/os/CONFIG.linux-x86.linux-cris_v32 deleted file mode 100644 index eee8f3344..000000000 --- a/configure/os/CONFIG.linux-x86.linux-cris_v32 +++ /dev/null @@ -1,20 +0,0 @@ -# CONFIG.linux-x86.linux-cris_v32 -# -# Author: Peter Zumbruch -# GSI -# P.Zumbruch@gsi.de -# -# Definitions for linux-x86 host - linux-cris_v32 target builds -# Sites may override these definitions in CONFIG_SITE.linux-x86.linux-cris_v32 -#------------------------------------------------------- - -# Include definitions common to all linux-cris targets -include $(CONFIG)/os/CONFIG.Common.linux-cris - -GNU_TARGET = crisv32-axis-linux-gnu - -ARCH_DEP_CFLAGS += -march=v32 - -# if you are using different places for cris_v10 cris_v32 -# you have to define for each architecture -# AXIS_SDK_DIR= diff --git a/configure/os/CONFIG.linux-x86.linux-x86 b/configure/os/CONFIG.linux-x86.linux-x86 index f6a79241a..153ce0d68 100644 --- a/configure/os/CONFIG.linux-x86.linux-x86 +++ b/configure/os/CONFIG.linux-x86.linux-x86 @@ -11,6 +11,3 @@ STATIC_LDFLAGS_YES= -Wl,-Bstatic STATIC_LDFLAGS_NO= STATIC_LDLIBS_YES= -Wl,-Bdynamic STATIC_LDLIBS_NO= - -SHRLIB_LDFLAGS += -Wl,-h$@ -LOADABLE_SHRLIB_LDFLAGS += -Wl,-h$@ diff --git a/configure/os/CONFIG.solaris-sparc-gnu.solaris-sparc-gnu b/configure/os/CONFIG.solaris-sparc-gnu.solaris-sparc-gnu index 03476b833..dfa1522ea 100644 --- a/configure/os/CONFIG.solaris-sparc-gnu.solaris-sparc-gnu +++ b/configure/os/CONFIG.solaris-sparc-gnu.solaris-sparc-gnu @@ -18,6 +18,6 @@ STATIC_LDLIBS_NO= OP_SYS_LDFLAGS += -z ignore -z combreloc -z lazyload -SHRLIB_LDFLAGS += -Wl,-z,defs -Wl,-z,text -Wl,-h,$@ -LOADABLE_SHRLIB_LDFLAGS += -Wl,-z,text -Wl,-h,$@ +SHRLIB_LDFLAGS += -Wl,-z,defs -Wl,-z,text +LOADABLE_SHRLIB_LDFLAGS += -Wl,-z,text GNU_LDLIBS_YES += -lc diff --git a/configure/os/CONFIG.win32-x86.win32-x86 b/configure/os/CONFIG.win32-x86.win32-x86 index a8115a714..767f4c7fa 100644 --- a/configure/os/CONFIG.win32-x86.win32-x86 +++ b/configure/os/CONFIG.win32-x86.win32-x86 @@ -49,9 +49,9 @@ OPT_CFLAGS_YES_NO = -Ox -Oy- OPT_CFLAGS_YES = $(OPT_CFLAGS_YES_$(OPT_WHOLE_PROGRAM)) # -# -Zi generate program database for debugging information +# -Z7 generate C7 compatible debugging information (inside .obj) # -RTCsu enable run-time error checks -OPT_CFLAGS_NO = -Zi -RTCsu +OPT_CFLAGS_NO = -Z7 -RTCsu # specify object file name and location OBJ_CFLAG = -Fo @@ -119,9 +119,9 @@ OPT_CXXFLAGS_YES_NO = -Ox -Oy- OPT_CXXFLAGS_YES = $(OPT_CXXFLAGS_YES_$(OPT_WHOLE_PROGRAM)) # -# -Zi generate program database for debugging information +# -Z7 generate C7 compatible debugging information (inside .obj) # -RTCsu enable run-time error checks -OPT_CXXFLAGS_NO = -RTCsu -Zi +OPT_CXXFLAGS_NO = -RTCsu -Z7 # specify object file name and location OBJ_CXXFLAG = -Fo @@ -143,20 +143,6 @@ STATIC_LDLIBS_NO= STATIC_LDFLAGS= RANLIB= -# -# option needed for parallel builds with Visual Studio 2013 onward -# VS2012 and above have VisualStudioVersion, so just need to exclude 2012 (11.0) -# -FS Force Synchronous PDB Writes -# -ifneq ($(VisualStudioVersion),) -ifneq ($(VisualStudioVersion),11.0) - OPT_CXXFLAGS_NO += -FS - OPT_CFLAGS_NO += -FS -endif -endif - - -# # add -profile here to run the ms profiler # -LTCG whole program optimization # -incremental:no full linking diff --git a/configure/os/CONFIG_SITE.Common.RTEMS b/configure/os/CONFIG_SITE.Common.RTEMS index 0b5d227ee..6857dc9a9 100644 --- a/configure/os/CONFIG_SITE.Common.RTEMS +++ b/configure/os/CONFIG_SITE.Common.RTEMS @@ -3,11 +3,26 @@ # Site-specific information for all RTEMS targets #------------------------------------------------------- -# Where to find RTEMS +# Where to find RTEMS, and what version is it # +# RTEMS_BASE must point to the specific installation of RTEMS to +# build the target code with. +# RTEMS_VERSION is used in the path to the toolsets inside that +# installation. For RTEMS 5 only the major version number is +# used, but for RTEMS 4.10.2 say all 3 components are required. +# + +# FHI: +#RTEMS_VERSION = 5 +#RTEMS_BASE = /home/h1/DBG/rtems +#RTEMS_BASE = /home/ad/MVME6100/rtems/$(RTEMS_VERSION) +#RTEMS_BASE = /opt/RTEMS/qoriq/rtems/$(RTEMS_VERSION) + # APS: -RTEMS_VERSION = 4.10.2 -RTEMS_BASE = /usr/local/vw/rtems/rtems-$(RTEMS_VERSION) +#RTEMS_VERSION = 4.10.2 +#RTEMS_BASE = /usr/local/vw/rtems/rtems-4.10.2 +#RTEMS_VERSION = 5 +#RTEMS_BASE = /usr/local/vw/rtems/rtems-5.1 # Cross-compile toolchain in $(RTEMS_TOOLS)/bin # diff --git a/configure/os/CONFIG_SITE.Common.RTEMS-pc386-qemu b/configure/os/CONFIG_SITE.Common.RTEMS-pc386-qemu index 027dcf4ab..0f930c5d9 100644 --- a/configure/os/CONFIG_SITE.Common.RTEMS-pc386-qemu +++ b/configure/os/CONFIG_SITE.Common.RTEMS-pc386-qemu @@ -6,4 +6,4 @@ # If you're building this architecture you _probably_ want to # run the tests for it under QEMU, but if not you can turn # them off here by commenting out this line: -CROSS_COMPILER_RUNTEST_ARCHS += RTEMS-pc386-qemu +CROSS_COMPILER_RUNTEST_ARCHS += $(T_A) diff --git a/configure/os/CONFIG_SITE.Common.RTEMS-pc686-qemu b/configure/os/CONFIG_SITE.Common.RTEMS-pc686-qemu new file mode 100644 index 000000000..4ed2ed36c --- /dev/null +++ b/configure/os/CONFIG_SITE.Common.RTEMS-pc686-qemu @@ -0,0 +1,9 @@ +# CONFIG_SITE.Common.RTEMS-pc686-qemu +# +# Site-specific overrides for the RTEMS-pc686-qemu target +# + +# If you're building this architecture you _probably_ want to +# run the tests for it under QEMU, but if not you can turn +# them off here by commenting out this line: +CROSS_COMPILER_RUNTEST_ARCHS += $(T_A) diff --git a/configure/os/CONFIG_SITE.Common.darwin-ppc b/configure/os/CONFIG_SITE.Common.darwin-ppc deleted file mode 100644 index a2550147f..000000000 --- a/configure/os/CONFIG_SITE.Common.darwin-ppc +++ /dev/null @@ -1,12 +0,0 @@ -# CONFIG_SITE.Common.darwin-ppc -# -# Site override definitions for darwin-ppc target builds -#------------------------------------------------------- - -# Select which CPU architectures to include in your universal binaries: -# ppc -# ppc64 - Not tested - -ARCH_CLASS = ppc -#ARCH_CLASS = ppc64 -#ARCH_CLASS = ppc ppc64 diff --git a/configure/os/CONFIG_SITE.Common.darwin-ppcx86 b/configure/os/CONFIG_SITE.Common.darwin-ppcx86 deleted file mode 100644 index 2191d54f8..000000000 --- a/configure/os/CONFIG_SITE.Common.darwin-ppcx86 +++ /dev/null @@ -1,20 +0,0 @@ -# CONFIG_SITE.Common.darwin-ppcx86 -# -# Site override definitions for darwin-ppcx86 target builds -#---------------------------------------------------------- - -# Select which CPU architectures to include in your universal binaries: -# ppc -# i386 -# ppc64 - Not tested -# x86_64 - Needs MacOS 10.4 with Universal SDK, or 10.5 or later. - -ARCH_CLASS = ppc i386 -#ARCH_CLASS = ppc x86_64 -#ARCH_CLASS = ppc i386 x86_64 -#ARCH_CLASS = ppc64 i386 -#ARCH_CLASS = ppc64 x86_64 -#ARCH_CLASS = ppc64 i386 x86_64 -#ARCH_CLASS = ppc ppc64 i386 -#ARCH_CLASS = ppc ppc64 x86_64 -#ARCH_CLASS = ppc ppc64 i386 x86_64 diff --git a/configure/os/CONFIG_SITE.Common.darwin-x86 b/configure/os/CONFIG_SITE.Common.darwin-x86 index 1c5c93696..e837d63f0 100644 --- a/configure/os/CONFIG_SITE.Common.darwin-x86 +++ b/configure/os/CONFIG_SITE.Common.darwin-x86 @@ -4,14 +4,12 @@ #------------------------------------------------------- # Select which CPU architecture(s) to include in your MacOS binaries: -# i386, x86_64, or both (fat binaries). +# x86_64 only, or arm64 as well (fat binaries). -#ARCH_CLASS = i386 ARCH_CLASS = x86_64 -#ARCH_CLASS = i386 x86_64 +#ARCH_CLASS = arm64 x86_64 -# -# Uncomment the following 3 lines to build with Apple's GCC instead of CLANG. +# Uncomment the following 3 lines to build with GCC instead of CLANG. # #CMPLR_CLASS = gcc #CC = gcc diff --git a/configure/os/CONFIG_SITE.Common.linux-cris b/configure/os/CONFIG_SITE.Common.linux-cris deleted file mode 100644 index 699f346ff..000000000 --- a/configure/os/CONFIG_SITE.Common.linux-cris +++ /dev/null @@ -1,34 +0,0 @@ -# CONFIG_SITE.Common.linux-cris -# -# Site-specific settings for the linux-cris target - -# NOTE: In most cases if SHARED_LIBRARIES is set to YES the -# shared libraries will be found automatically. However if the .so -# files are installed at a different path to their compile-time path -# then in order to be found at runtime do one of these: -# a) LD_LIBRARY_PATH must include the full absolute pathname to -# $(INSTALL_LOCATION)/lib/$(EPICS_HOST_ARCH) when invoking base -# executables. -# b) Add the runtime path to SHRLIB_DEPLIB_DIRS and PROD_DEPLIB_DIRS, which -# will add the named directory to the list contained in the executables. -# c) Add the runtime path to /etc/ld.so.conf and run ldconfig -# to inform the system of the shared library location. - - -# Use GNU Readline if the header file is installed -COMMANDLINE_LIBRARY = $(strip $(if $(wildcard \ - $(GNU_DIR)/include/readline/readline.h), READLINE, EPICS)) - -# If libreadline needs additional libraries to be linked with it, try -# uncommenting each of the lines below in turn, starting with the top -# one and working downwards, until the build succeeds. Do a 'make rebuild' -# from the top of the Base tree after changing this setting. - -# Needs -lncurses: -#COMMANDLINE_LIBRARY = READLINE_NCURSES - -# Needs -lcurses: -#COMMANDLINE_LIBRARY = READLINE_CURSES - -# Readline is broken or you don't want use it: -#COMMANDLINE_LIBRARY = EPICS diff --git a/configure/os/CONFIG_SITE.darwin-ppc.Common b/configure/os/CONFIG_SITE.darwin-ppc.Common deleted file mode 100644 index 05417e1f9..000000000 --- a/configure/os/CONFIG_SITE.darwin-ppc.Common +++ /dev/null @@ -1,4 +0,0 @@ -# CONFIG_SITE.darwin-ppc.Common -# -# Site override definitions for darwin-ppc host builds -#------------------------------------------------------- diff --git a/configure/os/CONFIG_SITE.darwin-ppcx86.Common b/configure/os/CONFIG_SITE.darwin-ppcx86.Common deleted file mode 100644 index 42bd00531..000000000 --- a/configure/os/CONFIG_SITE.darwin-ppcx86.Common +++ /dev/null @@ -1,4 +0,0 @@ -# CONFIG_SITE.darwin-ppcx86.Common -# -# Site override definitions for darwin-ppcx86 host builds -#------------------------------------------------------- diff --git a/configure/os/CONFIG_SITE.linux-x86.Common b/configure/os/CONFIG_SITE.linux-x86.Common index dc29e8f0d..afb74e914 100644 --- a/configure/os/CONFIG_SITE.linux-x86.Common +++ b/configure/os/CONFIG_SITE.linux-x86.Common @@ -3,7 +3,5 @@ # Site override definitions for linux-x86 host builds #------------------------------------------------------- -# JBA test override values -#CROSS_COMPILER_TARGET_ARCHS = vxWorks-68040 solaris-sparc -#CROSS_COMPILER_TARGET_ARCHS = vxWorks-68040 -#CROSS_COMPILER_TARGET_ARCHS = RTEMS-mvme2100 RTEMS-pc386 # RTEMS-mvme5500 RTEMS-mvme167 +#CROSS_COMPILER_TARGET_ARCHS = vxWorks-ppc32 +#CROSS_COMPILER_TARGET_ARCHS = RTEMS-mvme2100 RTEMS-pc386-qemu diff --git a/configure/os/CONFIG_SITE.linux-x86.linux-cris b/configure/os/CONFIG_SITE.linux-x86.linux-cris deleted file mode 100644 index eb756ca8a..000000000 --- a/configure/os/CONFIG_SITE.linux-x86.linux-cris +++ /dev/null @@ -1,14 +0,0 @@ -# CONFIG_SITE.linux-x86.linux-cris -# -# Author: Peter Zumbruch -# GSI -# P.Zumbruch@gsi.de -# -# Site specific definitions for linux-x86 host - linux-cris target builds -#------------------------------------------------------- - -# define site specific location of cris cross compiler's gnu directory -# but without bin sub directory, this will be added automatically. - -CRIS_CROSS_COMPILER ?= UNDEFINED_ENV__CRIS_CROSS_COMPILER - diff --git a/configure/toolchain.c b/configure/toolchain.c new file mode 100644 index 000000000..a97085ae3 --- /dev/null +++ b/configure/toolchain.c @@ -0,0 +1,37 @@ +#ifdef _COMMENT_ +/* Extract compiler pre-defined macros as Make variables + * + * Expanded as $(INSTALL_CFG)/TOOLCHAIN.$(EPICS_HOST_ARCH).$(T_A) + * + * Must be careful not to #include any C definitions + * into what is really a Makefile snippet + * + * cf. https://sourceforge.net/p/predef/wiki/Home/ + */ +/* GCC preprocessor drops C comments from output. + * MSVC preprocessor emits C comments in output + */ +#endif + +#if defined(__GNUC__) && !defined(__clang__) +GCC_MAJOR = __GNUC__ +GCC_MINOR = __GNUC_MINOR__ +GCC_PATCH = __GNUC_PATCHLEVEL__ + +#elif defined(__clang__) +CLANG_MAJOR = __clang_major__ +CLANG_MINOR = __clang_minor__ +CLANG_PATCH = __clang_patchlevel__ + +#elif defined(_MSC_VER) +MSVC_VER = _MSC_VER +#endif + +#ifdef __rtems__ +#include +# if __RTEMS_MAJOR__>=5 +OS_API = posix +# else +OS_API = score +# endif +#endif diff --git a/documentation/Doxyfile@ b/documentation/Doxyfile@ index 44e09f69e..bf53ee0ce 100644 --- a/documentation/Doxyfile@ +++ b/documentation/Doxyfile@ @@ -107,7 +107,7 @@ BRIEF_MEMBER_DESC = YES # brief descriptions will be completely suppressed. # The default value is: YES. -REPEAT_BRIEF = YES +REPEAT_BRIEF = NO # This tag implements a quasi-intelligent brief description abbreviator that is # used to form the text in various listings. Each string in this list, if found @@ -143,7 +143,7 @@ ALWAYS_DETAILED_SEC = NO # operators of the base classes will not be shown. # The default value is: NO. -INLINE_INHERITED_MEMB = NO +INLINE_INHERITED_MEMB = YES # If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path # before files name in the file list and in the header files. If set to NO the @@ -163,7 +163,7 @@ FULL_PATH_NAMES = YES # This tag requires that the tag FULL_PATH_NAMES is set to YES. STRIP_FROM_PATH = @TOP@/include \ - ../ + .. # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which @@ -173,7 +173,7 @@ STRIP_FROM_PATH = @TOP@/include \ # using the -I flag. STRIP_FROM_INC_PATH = @TOP@/include \ - ../ + .. # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but # less readable) file names. This can be useful is your file systems doesn't @@ -228,7 +228,7 @@ SEPARATE_MEMBER_PAGES = NO # uses this value to replace tabs by spaces in code fragments. # Minimum value: 1, maximum value: 16, default value: 4. -TAB_SIZE = 4 +TAB_SIZE = 8 # This tag can be used to specify a number of aliases that act as commands in # the documentation. An alias has the form: @@ -415,7 +415,7 @@ LOOKUP_CACHE_SIZE = 0 # normally produced when WARNINGS is set to YES. # The default value is: NO. -EXTRACT_ALL = YES +EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES all private members of a class will # be included in the documentation. @@ -543,7 +543,7 @@ INLINE_INFO = YES # name. If set to NO the members will appear in declaration order. # The default value is: YES. -SORT_MEMBER_DOCS = YES +SORT_MEMBER_DOCS = NO # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member @@ -818,7 +818,7 @@ EXCLUDE_SYMLINKS = NO # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* -EXCLUDE_PATTERNS = O.* +EXCLUDE_PATTERNS = /O.*/ # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the @@ -1987,7 +1987,7 @@ INCLUDE_FILE_PATTERNS = # recursively expanded use the := operator instead of the = operator. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. -PREDEFINED = +PREDEFINED = __cplusplus # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this # tag can be used to specify a list of macro names that should be expanded. The @@ -2006,7 +2006,7 @@ EXPAND_AS_DEFINED = # The default value is: YES. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. -SKIP_FUNCTION_MACROS = YES +SKIP_FUNCTION_MACROS = NO #--------------------------------------------------------------------------- # Configuration options related to external references diff --git a/documentation/README.cris b/documentation/README.cris deleted file mode 100644 index c44f31bb0..000000000 --- a/documentation/README.cris +++ /dev/null @@ -1,67 +0,0 @@ -cross compiling EPICS and - building IOC Applications for cris architectures - (linux-cris_v10, linux-cris_v32) -====================================================================== - -Please mail questions, comments, corrections, etc. ... -to P.Zumbruch@gsi.de -November 2007 - -Tools needed ------------- - - o Axis SDK - - Overview: - http://developer.axis.com/wiki/doku.php?id=axis:sdk - - Download: - http://www.axis.com/products/dev_sdk/download_dist.php - - Install HOWTO: - http://developer.axis.com/wiki/doku.php?id=axis:software_distribution_install_howto - o Axis GNU gcc release for cross compiling - - Download: - http://www.axis.com/products/dev_sdk/download_compiler.php - - Install HOWTO: - http://developer.axis.com/wiki/doku.php?id=axis:compiler_install - -Environment ------------ - - o CRIS_CROSS_COMPILER - - path to top directory of cris cross compiler, - where binaries are in sub directory bin/ - - if not set, the make process will stop at place - UNDEFINED_ENV__CRIS_CROSS_COMPILER - o AXIS_TOP_DIR?=UNDEFINED_ENV__AXIS_TOP_DIR - - path to axis SDK top directory - - if not set compile and link commands will contain references to - UNDEFINED_ENV__AXIS_TOP_DIR - - to set the necessary variables, execute - . ./init_env - in the top directory of the SDK provided here. - o CRIS_COMPILER_DEBUG - - if defined symbols won't be stripped, - resulting in comparably large files - -Building --------- - - o Edit the CONFIG_SITE files - - CONFIG_SITE.linux-x86.Common: - for CROSS_COMPILER_TARGET_ARCHS += linux-cris_v10 - for CROSS_COMPILER_TARGET_ARCHS += linux-cris_v32 - - optionally CONFIG_SITE.linux-x86.linux-cris - for setting CRIS_CROSS_COMPILER - - optionally create CONFIG_SITE.linux-x86.linux-cris_v10 - - optionally create CONFIG_SITE.linux-x86.linux-cris_v32 - o "make". - -Shared Libraries ----------------- - -Generating shared libraries is not supported. - - -Please feel free to contact me if you -encounter serious problems. - -Peter diff --git a/documentation/RELEASE_NOTES.md b/documentation/RELEASE_NOTES.md index 587b52448..eaee85dbc 100644 --- a/documentation/RELEASE_NOTES.md +++ b/documentation/RELEASE_NOTES.md @@ -17,6 +17,241 @@ should also be read to understand what has changed since earlier releases. +### Support for obsolete architectures removed + +These target architectures have been removed: + ++ darwin-ppc, darwin-ppcx86 ++ linux-386, linux-486, linux-586, linux-686, linux-athlon (cross-build) ++ linux-cris, linux-cris_v10, linux-cris_v32 (cross-build) ++ RTEMS-at91rm9200ek, RTEMS-gen68360, RTEMS-mcp750, RTEMS-mvme167, +RTEMS-psim (cross-build) + +### Experimental Support for RTEMS 5 + +The new major release of the RTEMS real-time OS contains many changes +including the ability to support SMP systems. This release of EPICS +can still be built with RTEMS 4.9.x or 4.10.x and should work just +the same as earlier releases, although due to code having moved around +we recommend thorough testing before this release is first used in +production systems. + +This release of EPICS comes with support for several new RTEMS targets +running on RTEMS 5: + +- RTEMS-beagleboneblack +- RTEMS-pc686 +- RTEMS-qoriq_e500 (MVME2500) +- RTEMS-xilinx-zynq-a9_qemu +- RTEMS-xilinx_zynq_zedboard + +The EPICS support for RTEMS 4 has always relied on RTEMS-specific +kernel APIs which cannot be used on an SMP system, so a new port was +created to use the Posix real-time APIs that are now recommended for +RTEMS 5. Note that a single installation of EPICS cannot build both +RTEMS 4 and RTEMS 5 targets, if you need to support targets running +on both versions you must use a separate installation, and be sure +to run `make distclean` if switching a single source tree from one +to the other (both header files and dependency files are different +between the two and must be cleaned out). + +The configuration variable RTEMS_VERSION in the EPICS config file +`configure/os/CONFIG_SITE.Common.RTEMS` must be set to the full 3- +part version number for RTEMS 4 releases, e.g. `4.9.1`, `4.10.2` +but for RTEMS 5.1 and later it must only contain the major version +number e.g. `5`. + +Some RTEMS BSPs can be built and may work with the newer libbsd +network stack which RTEMS is moving over to, but most of the MVME +boards (and the uC5282) still require the legacy network stack. + +The dependency on bspExt has been removed, EPICS now provides its +own routine for VMEbus probing (or uses one built into the BSP). + +Anyone using this release on RTEMS is advised to discuss problems +building or running it on either the tech-talk or core-talk email +lists so the core developers can help with and find out about any +problems with the old or new port. + +Known Issues: +- MVME2100 and MVME2700 need changes to the RTEMS 5 BSP to build. +- VMEBus support is not yet available for the MVME2500 BSP. +- There are some known issues with floating point on MVME2500, + probably related to its newer e500 FPU. +- Changed network driver for beatnik to work with libbsd. Some + issues with DHCP, but network stack usable. Can load env from + NVRAM. + +### `epicsEnvShow` accepts a glob pattern + +The optional argument to epicsEnvShow can now be a glob pattern. + +### New function `epicsStrnGlobMatch()` + +The function `epicsStrnGlobMatch(char* str, size_t len, char* pattern)` +works exactly the same as `epicsStrGlobMatch()` but takes an additional +length arguments which limits the number of characters of `str` to match. + +### Automatic fallback to thread when unable to exec caRepeater + +A process using libca which does not find an existing caRepeater process +will attempt to start one by running the caRepeater executable. +This is not always possible, usually when caRepeater is not in `$PATH`. +Now, instead of printing a warning, an internal caRepeater thread +will be started (as is done be RTEMS and vxWorks targets). + +If this fallback occurs, the lifetime of the caRepeater thread +may be shorter than the lifetime of a separate caRepeater process +would have been. + +It remains the recommended practice to explicitly start a caRepeater +instance. Examples of both systemd (`caRepeater.service`) and sysv +(`S99caRepeater`) scripts may be found under `bin/`. + +### Glob pattern allowed in `var` command + +When used with one argument, the `var` command can be used with a glob pattern +for printing matching variables. + +### Formalize/fix `FINAL_LOCATION` + +The `FINAL_LOCATION` make variable has for some time been an undocumented +means of performing a staged build. This is a build which "installs" to +a temporary location, which will later be moved to a final location. + +This has now been added to `configure/CONFIG_SITE`. + +Usage analogous to the autotools recipe + +```sh +./configure --prefix=/usr/lib/epics +make install DESTDIR=/tmp/build +``` + +would be + +```sh +make INSTALL_LOCATION=/tmp/build FINAL_LOCATION=/usr/lib/epics +``` + +`FINAL_LOCATION` is now correctly used in systemd and sysv init scripts +`caRepeater.service`, `S99caRepeater`, and `S99logServer`. + +### IOCsh sets `${PWD}` + +IOC shell will now ensure `${PWD}` is set on startup, +and updated by the `cd` iocsh function. + +### Add Alarm Message and Time Tag Fields + +Two new fields have been added to `dbCommon` so will be present in all +records: `AMSG` and `UTAG`. + +#### `AMSG` + +`AMSG` can hold an arbitrary 40-character string, providing additional +information about the alarm condition indicated in `STAT` and `SEVR`. With no +alarm it will hold an empty string. The new `recGblSetSevrMsg()` function can +be used in place of `recGblSetSevr()` to signal an alarm while providing a +message. + +For example, a device support's `read_bi()` routine for a hypothetical +multi-channel ethernet attached device might flag a communication error +between the IOC and controller, or an error involving a certain channel like +this: + +```c +static long read_bi(biRecord* prec) { + ... + if (!priv->connected) { + recGblSetSevrMsg(prec, COMM_ALARM, INVALID_ALARM, + "No controller connected"); + return S_dev_noDevice; + } + if (!priv->err) { + recGblSetSevrMsg(prec, READ_ALARM, INVALID_ALARM, + "Channel %u disconnexted", priv->chan); + return S_dev_noDevice; + } + return status; +} +``` + +#### `UTAG` + +`UTAG` holds an `epicsUInt64` value which is semantically part of the record's +timestamp (`TIME`). The value defaults to zero if not explicitly set. Device +support or an event time provider which supports this feature may write a tag +value directly to the `dbCommon::utag` field. + +`TSEL` links will copy both `TIME` and `UTAG` between records if the link type +supports this (CA links do not). + +A `utag` server side channel filter has been added which can be configured to +filter out monitor updates which don't pass the test `(UTAG & M) == V` where +`M` and `V` are client specified integers. For example running the command +`camonitor BPM0:X.{utag:{M:1,V:1}}` will only show updates for which +`(UTAG & 1) == 1` i.e. the least significant bit of the `UTAG` field is set. + +This feature is intended for use by intelligent devices which can provide +contextual information along with a value/alarm/time. For example, a beam +diagnostic device which is aware of whether a beam signal should be present +(eg. from a global timing system). + +#### Link Support + +Two new optional methods have been added to the Link Support Entry Table +(`struct lset`): `lset::getAlarmMsg()` and `lset::getTimeStampTag()`. See +comments in dbLink.h for details on implementing these. + +Two new accessor functions have also been added which call these methods: +`dbGetAlarmMsg()` and `dbGetTimeStampTag()`. + +#### Compatibility + +User code wishing to call these interfaces while maintaining compatibility with older +versions of Base may add some of the following macro definitions, and ensure +that the variables referenced by output pointers are initialized. + +```c +#ifndef HAS_ALARM_MESSAGE +# recGblSetSevrMsg(REC, STAT, SEVR, ...) recGblSetSevr(REC, STAT, SEVR) +#endif +#ifndef dbGetAlarmMsg +# define dbGetAlarmMsg(LINK, STAT, SEVR, BUF, BUFLEN) dbGetAlarm(LINK, STAT, SEVR) +#endif +#ifndef dbGetTimeStampTag +# define dbGetTimeStampTag(LINK, STAMP, TAG) dbGetTimeStamp(LINK, STAMP) +#endif +``` + + +### Timeouts for Unit Test Programs + +The unit test programs that are run by the `make runtests` or `make tapfiles` +commands get executed by a `.t` wrapper script which is normally generated by +the EPICS `makeTestfile.pl` program. Those generated wrapper scripts now +impose a time-limit on the test program they execute, and will kill it if it +runs for longer than 500 seconds (8 minutes 20) without exiting. That +time-limit can be changed for any such test by modifying the Makefile which +creates and runs the `.t` wrapper script. + +Setting the environment variable `EPICS_UNITTEST_TIMEOUT` to the desired +number of seconds while the Makefile is generating the test script changes the +timeout in that script. For example: + +``` + TESTSCRIPTS_HOST += hourLongTest.t + hourLongTest.t: export EPICS_UNITTEST_TIMEOUT=3600 +``` + +When selecting such a timeout remember that different Continuous Integration +systems such as GitHub Actions and Appveyor run on processors with different +speeds, so allow enough head-room for slower systems to complete the test. + +Test programs written directly in Perl as a `.plt` script should implement a +similar timeout for themselves. The "netget" test in Base does this in a way +that works on Windows as well as Unix-like hosts. ----- @@ -457,7 +692,7 @@ work with older Base releases. This would also be a good time to modify the device support to use the type-safe device support entry tables that were introduced in Base-3.16.2 -- see -[#type-safe-device-and-driver-support-tables](this entry below) for the +[this entry below](#type-safe-device-and-driver-support-tables) for the description of that change, which is also optional for now. Look at the aiRecord for example. Near the top of the generated `aiRecord.h` @@ -1690,6 +1925,15 @@ header and removed the need for dbScan.c to reach into the internals of its ## Changes made on the 3.15 branch since 3.15.8 +### Use waitable timers on Microsoft Windows + +The `epicsEventWaitWithTimeout` and `epicsThreadSleep` functions have +been changed to use waitable timers. On Windows 10 version 1803 or higher +they will use high resolution timers for more consistent timing. + +See https://groups.google.com/a/chromium.org/g/scheduler-dev/c/0GlSPYreJeY +for a comparison of the performance of different timers. + ### Change to the `junitfiles` self-test build target The names of the generated junit xml test output files have been changed diff --git a/modules/ca/src/client/Makefile b/modules/ca/src/client/Makefile index a8c0fed06..08394ea54 100644 --- a/modules/ca/src/client/Makefile +++ b/modules/ca/src/client/Makefile @@ -113,7 +113,7 @@ SCRIPTS_Linux = caRepeater.service EXPAND += S99caRepeater@ EXPAND += caRepeater.service@ -EXPAND_VARS = INSTALL_BIN=$(abspath $(INSTALL_BIN)) +EXPAND_VARS = INSTALL_BIN=$(FINAL_LOCATION)/bin/$(T_A) SRC_DIRS += $(CURDIR)/test PROD_HOST += ca_test diff --git a/modules/ca/src/client/caProto.h b/modules/ca/src/client/caProto.h index 1af7ec298..397b1edaf 100644 --- a/modules/ca/src/client/caProto.h +++ b/modules/ca/src/client/caProto.h @@ -17,6 +17,9 @@ #ifndef INC_caProto_H #define INC_caProto_H +// Pick up definition of IPPORT_USERRESERVED +#include + #define capStrOf(A) #A #define capStrOfX(A) capStrOf ( A ) diff --git a/modules/ca/src/client/udpiiu.cpp b/modules/ca/src/client/udpiiu.cpp index ba1caa99b..723117a71 100644 --- a/modules/ca/src/client/udpiiu.cpp +++ b/modules/ca/src/client/udpiiu.cpp @@ -629,8 +629,8 @@ void epicsStdCall caStartRepeaterIfNotInstalled ( unsigned repeaterPort ) * repeater's port) */ osiSpawnDetachedProcessReturn osptr = - osiSpawnDetachedProcess ( "CA Repeater", "caRepeater" ); - if ( osptr == osiSpawnDetachedProcessNoSupport ) { + osiSpawnDetachedProcess ( "!CA Repeater", "caRepeater" ); + if ( osptr != osiSpawnDetachedProcessSuccess ) { epicsThreadId tid; tid = epicsThreadCreate ( "CAC-repeater", epicsThreadPriorityLow, @@ -639,9 +639,6 @@ void epicsStdCall caStartRepeaterIfNotInstalled ( unsigned repeaterPort ) fprintf ( stderr, "caStartRepeaterIfNotInstalled : unable to create CA repeater daemon thread\n" ); } } - else if ( osptr == osiSpawnDetachedProcessFail ) { - fprintf ( stderr, "caStartRepeaterIfNotInstalled (): unable to start CA repeater daemon detached process\n" ); - } } } diff --git a/modules/ca/src/perl/Makefile b/modules/ca/src/perl/Makefile index 532780d4c..05500ad05 100644 --- a/modules/ca/src/perl/Makefile +++ b/modules/ca/src/perl/Makefile @@ -38,6 +38,7 @@ ifeq ($(wildcard $(PERL_h)),) endif endif +ifneq (inc,$(strip $(MAKECMDGOALS))) ifeq ($(T_A),$(EPICS_HOST_ARCH)) # No cross-builds (wrong Perl!) ifeq ($(strip $(XSUBPP)),) $(warning Perl's xsubpp program was not found.) @@ -62,6 +63,7 @@ endif endif endif endif +endif Cap5_SRCS = Cap5.xs Cap5_LIBS = ca Com diff --git a/modules/database/src/ioc/as/asCa.c b/modules/database/src/ioc/as/asCa.c index 77ca70b79..d2e9f7591 100644 --- a/modules/database/src/ioc/as/asCa.c +++ b/modules/database/src/ioc/as/asCa.c @@ -33,7 +33,6 @@ #include "caerr.h" #include "caeventmask.h" -#define epicsExportSharedSymbols #include "asCa.h" #include "asDbLib.h" #include "callback.h" diff --git a/modules/database/src/ioc/as/asCa.h b/modules/database/src/ioc/as/asCa.h index 03934c263..682686d6c 100644 --- a/modules/database/src/ioc/as/asCa.h +++ b/modules/database/src/ioc/as/asCa.h @@ -14,17 +14,17 @@ #include -#include "shareLib.h" +#include "dbCoreAPI.h" #ifdef __cplusplus extern "C" { #endif -epicsShareFunc void asCaStart(void); -epicsShareFunc void asCaStop(void); -epicsShareFunc int ascar(int level); -epicsShareFunc int ascarFP(FILE *fp, int level); -epicsShareFunc void ascaStats(int *pchans, int *pdiscon); +DBCORE_API void asCaStart(void); +DBCORE_API void asCaStop(void); +DBCORE_API int ascar(int level); +DBCORE_API int ascarFP(FILE *fp, int level); +DBCORE_API void ascaStats(int *pchans, int *pdiscon); #ifdef __cplusplus } diff --git a/modules/database/src/ioc/as/asDbLib.c b/modules/database/src/ioc/as/asDbLib.c index 66d4040a9..d0f996fef 100644 --- a/modules/database/src/ioc/as/asDbLib.c +++ b/modules/database/src/ioc/as/asDbLib.c @@ -25,7 +25,6 @@ #include "caeventmask.h" -#define epicsExportSharedSymbols #include "asCa.h" #include "asDbLib.h" #include "callback.h" diff --git a/modules/database/src/ioc/as/asDbLib.h b/modules/database/src/ioc/as/asDbLib.h index 30527ee41..aeef3f2d5 100644 --- a/modules/database/src/ioc/as/asDbLib.h +++ b/modules/database/src/ioc/as/asDbLib.h @@ -15,7 +15,7 @@ #include #include "callback.h" -#include "shareLib.h" +#include "dbCoreAPI.h" typedef struct { epicsCallback callback; @@ -28,25 +28,25 @@ struct dbChannel; extern "C" { #endif -epicsShareFunc int asSetFilename(const char *acf); -epicsShareFunc int asSetSubstitutions(const char *substitutions); -epicsShareFunc int asInit(void); -epicsShareFunc int asInitAsyn(ASDBCALLBACK *pcallback); -epicsShareFunc int asShutdown(void); -epicsShareFunc int asDbGetAsl(struct dbChannel *chan); -epicsShareFunc void * asDbGetMemberPvt(struct dbChannel *chan); -epicsShareFunc int asdbdump(void); -epicsShareFunc int asdbdumpFP(FILE *fp); -epicsShareFunc int aspuag(const char *uagname); -epicsShareFunc int aspuagFP(FILE *fp,const char *uagname); -epicsShareFunc int asphag(const char *hagname); -epicsShareFunc int asphagFP(FILE *fp,const char *hagname); -epicsShareFunc int asprules(const char *asgname); -epicsShareFunc int asprulesFP(FILE *fp,const char *asgname); -epicsShareFunc int aspmem(const char *asgname,int clients); -epicsShareFunc int aspmemFP( +DBCORE_API int asSetFilename(const char *acf); +DBCORE_API int asSetSubstitutions(const char *substitutions); +DBCORE_API int asInit(void); +DBCORE_API int asInitAsyn(ASDBCALLBACK *pcallback); +DBCORE_API int asShutdown(void); +DBCORE_API int asDbGetAsl(struct dbChannel *chan); +DBCORE_API void * asDbGetMemberPvt(struct dbChannel *chan); +DBCORE_API int asdbdump(void); +DBCORE_API int asdbdumpFP(FILE *fp); +DBCORE_API int aspuag(const char *uagname); +DBCORE_API int aspuagFP(FILE *fp,const char *uagname); +DBCORE_API int asphag(const char *hagname); +DBCORE_API int asphagFP(FILE *fp,const char *hagname); +DBCORE_API int asprules(const char *asgname); +DBCORE_API int asprulesFP(FILE *fp,const char *asgname); +DBCORE_API int aspmem(const char *asgname,int clients); +DBCORE_API int aspmemFP( FILE *fp,const char *asgname,int clients); -epicsShareFunc int astac( +DBCORE_API int astac( const char *recordname,const char *user,const char *location); #ifdef __cplusplus diff --git a/modules/database/src/ioc/as/asIocRegister.c b/modules/database/src/ioc/as/asIocRegister.c index 200da3e00..f4426786a 100644 --- a/modules/database/src/ioc/as/asIocRegister.c +++ b/modules/database/src/ioc/as/asIocRegister.c @@ -11,7 +11,6 @@ #include "asLib.h" #include "iocsh.h" -#define epicsExportSharedSymbols #include "asCa.h" #include "asDbLib.h" #include "asIocRegister.h" @@ -120,7 +119,9 @@ static void ascarCallFunc(const iocshArgBuf *args) } /* asDumpHash */ -static const iocshFuncDef asDumpHashFuncDef = {"asDumpHash",0,0}; +static const iocshFuncDef asDumpHashFuncDef = {"asDumpHash",0,0, + "Show the contents of the hash table used " + "to locate UAGs and HAGs.\n"}; static void asDumpHashCallFunc(const iocshArgBuf *args) { asDumpHash(); diff --git a/modules/database/src/ioc/as/asIocRegister.h b/modules/database/src/ioc/as/asIocRegister.h index bbe158b14..f7306ac8f 100644 --- a/modules/database/src/ioc/as/asIocRegister.h +++ b/modules/database/src/ioc/as/asIocRegister.h @@ -11,13 +11,13 @@ #ifndef INC_asIocRegister_H #define INC_asIocRegister_H -#include "shareLib.h" +#include "dbCoreAPI.h" #ifdef __cplusplus extern "C" { #endif -epicsShareFunc void asIocRegister(void); +DBCORE_API void asIocRegister(void); #ifdef __cplusplus } diff --git a/modules/database/src/ioc/bpt/Makefile b/modules/database/src/ioc/bpt/Makefile index ea1db1f14..a383d0864 100644 --- a/modules/database/src/ioc/bpt/Makefile +++ b/modules/database/src/ioc/bpt/Makefile @@ -19,7 +19,10 @@ BPT_DBD += bptTypeJdegC.dbd BPT_DBD += bptTypeJdegF.dbd BPT_DBD += bptTypeKdegC.dbd BPT_DBD += bptTypeKdegF.dbd + +ifneq (inc,$(strip $(MAKECMDGOALS))) DBD += $(BPT_DBD) +endif PROD_HOST += makeBpt diff --git a/modules/database/src/ioc/bpt/cvtTable.h b/modules/database/src/ioc/bpt/cvtTable.h index 8a5eef2fa..873614523 100644 --- a/modules/database/src/ioc/bpt/cvtTable.h +++ b/modules/database/src/ioc/bpt/cvtTable.h @@ -17,17 +17,17 @@ #ifndef INCcvtTableh #define INCcvtTableh 1 -#include "shareLib.h" +#include "dbCoreAPI.h" #ifdef __cplusplus extern "C" { #endif /* Global Routines*/ -epicsShareFunc long cvtEngToRawBpt( +DBCORE_API long cvtEngToRawBpt( double *pval,short linr,short init,void **ppbrk,short *plbrk); -epicsShareFunc long cvtRawToEngBpt( +DBCORE_API long cvtRawToEngBpt( double *pval,short linr,short init,void **ppbrk, short *plbrk); #ifdef __cplusplus diff --git a/modules/database/src/ioc/db/callback.c b/modules/database/src/ioc/db/callback.c index 84701e590..3fa249392 100644 --- a/modules/database/src/ioc/db/callback.c +++ b/modules/database/src/ioc/db/callback.c @@ -34,7 +34,6 @@ #include "errMdef.h" #include "taskwd.h" -#define epicsExportSharedSymbols #include "callback.h" #include "dbAccessDefs.h" #include "dbAddr.h" diff --git a/modules/database/src/ioc/db/callback.h b/modules/database/src/ioc/db/callback.h index fea12b437..ac600fd01 100644 --- a/modules/database/src/ioc/db/callback.h +++ b/modules/database/src/ioc/db/callback.h @@ -18,7 +18,7 @@ #ifndef INCcallbackh #define INCcallbackh 1 -#include "shareLib.h" +#include "dbCoreAPI.h" #ifdef __cplusplus extern "C" { @@ -69,23 +69,23 @@ typedef struct callbackQueueStats { #define callbackGetUser(USER, PCALLBACK) \ ( (USER) = (PCALLBACK)->user ) -epicsShareFunc void callbackInit(void); -epicsShareFunc void callbackStop(void); -epicsShareFunc void callbackCleanup(void); -epicsShareFunc int callbackRequest(epicsCallback *pCallback); -epicsShareFunc void callbackSetProcess( +DBCORE_API void callbackInit(void); +DBCORE_API void callbackStop(void); +DBCORE_API void callbackCleanup(void); +DBCORE_API int callbackRequest(epicsCallback *pCallback); +DBCORE_API void callbackSetProcess( epicsCallback *pcallback, int Priority, void *pRec); -epicsShareFunc int callbackRequestProcessCallback( +DBCORE_API int callbackRequestProcessCallback( epicsCallback *pCallback,int Priority, void *pRec); -epicsShareFunc void callbackRequestDelayed( +DBCORE_API void callbackRequestDelayed( epicsCallback *pCallback,double seconds); -epicsShareFunc void callbackCancelDelayed(epicsCallback *pcallback); -epicsShareFunc void callbackRequestProcessCallbackDelayed( +DBCORE_API void callbackCancelDelayed(epicsCallback *pcallback); +DBCORE_API void callbackRequestProcessCallbackDelayed( epicsCallback *pCallback, int Priority, void *pRec, double seconds); -epicsShareFunc int callbackSetQueueSize(int size); -epicsShareFunc int callbackQueueStatus(const int reset, callbackQueueStats *result); -epicsShareFunc void callbackQueueShow(const int reset); -epicsShareFunc int callbackParallelThreads(int count, const char *prio); +DBCORE_API int callbackSetQueueSize(int size); +DBCORE_API int callbackQueueStatus(const int reset, callbackQueueStats *result); +DBCORE_API void callbackQueueShow(const int reset); +DBCORE_API int callbackParallelThreads(int count, const char *prio); #ifdef __cplusplus } diff --git a/modules/database/src/ioc/db/chfPlugin.c b/modules/database/src/ioc/db/chfPlugin.c index b4ab72ca1..c84e08646 100644 --- a/modules/database/src/ioc/db/chfPlugin.c +++ b/modules/database/src/ioc/db/chfPlugin.c @@ -27,7 +27,6 @@ #include "epicsTypes.h" #include "errlog.h" -#define epicsExportSharedSymbols #include "chfPlugin.h" #include "dbStaticLib.h" diff --git a/modules/database/src/ioc/db/chfPlugin.h b/modules/database/src/ioc/db/chfPlugin.h index 8fe156f5f..5867a66f5 100644 --- a/modules/database/src/ioc/db/chfPlugin.h +++ b/modules/database/src/ioc/db/chfPlugin.h @@ -17,7 +17,7 @@ #ifndef CHFPLUGIN_H #define CHFPLUGIN_H -#include +#include #include #include #include @@ -302,7 +302,7 @@ typedef struct chfPluginArgDef { * @param def String to be returned when 'i' isn't a valid Enum index. * @return The string associated with 'i'. */ -epicsShareFunc const char* chfPluginEnumString(const chfPluginEnumType *Enums, int i, const char* def); +DBCORE_API const char* chfPluginEnumString(const chfPluginEnumType *Enums, int i, const char* def); /** @brief Register a plugin. * @@ -310,7 +310,7 @@ epicsShareFunc const char* chfPluginEnumString(const chfPluginEnumType *Enums, i * @param pif Pointer to the plugin's interface. * @param opts Pointer to the configuration argument description table. */ -epicsShareFunc int chfPluginRegister(const char* key, const chfPluginIf *pif, const chfPluginArgDef* opts); +DBCORE_API int chfPluginRegister(const char* key, const chfPluginIf *pif, const chfPluginArgDef* opts); #ifdef __cplusplus } diff --git a/modules/database/src/ioc/db/cvtBpt.c b/modules/database/src/ioc/db/cvtBpt.c index c72744c19..a318b8eb3 100644 --- a/modules/database/src/ioc/db/cvtBpt.c +++ b/modules/database/src/ioc/db/cvtBpt.c @@ -17,7 +17,6 @@ #include "epicsPrint.h" -#define epicsExportSharedSymbols #include "cvtTable.h" #include "dbAccess.h" #include "dbBase.h" diff --git a/modules/database/src/ioc/db/dbAccess.c b/modules/database/src/ioc/db/dbAccess.c index bac208f02..8aac52f00 100644 --- a/modules/database/src/ioc/db/dbAccess.c +++ b/modules/database/src/ioc/db/dbAccess.c @@ -35,7 +35,6 @@ #include "errlog.h" #include "errMdef.h" -#include "epicsExport.h" /* #define epicsExportSharedSymbols */ #include "caeventmask.h" #include "callback.h" #include "dbAccessDefs.h" @@ -62,6 +61,7 @@ #include "recGbl.h" #include "recSup.h" #include "special.h" +#include "epicsExport.h" struct dbBase *pdbbase = 0; volatile int interruptAccept=FALSE; @@ -360,6 +360,16 @@ static void getOptions(DBADDR *paddr, char **poriginal, long *options, *pushort++ = pcommon->ackt; pbuffer = (char *)pushort; } + if( (*options) & DBR_AMSG ) { + if (!pfl) { + STATIC_ASSERT(sizeof(pcommon->amsg)==sizeof(pfl->amsg)); + strncpy(pbuffer, pcommon->amsg, sizeof(pcommon->amsg)-1); + } else { + strncpy(pbuffer, pfl->amsg,sizeof(pfl->amsg)-1); + } + pbuffer[sizeof(pcommon->amsg)-1] = '\0'; + pbuffer += sizeof(pcommon->amsg); + } if( (*options) & DBR_UNITS ) { memset(pbuffer,'\0',dbr_units_size); if( prset && prset->get_units ){ @@ -392,6 +402,15 @@ static void getOptions(DBADDR *paddr, char **poriginal, long *options, } pbuffer = (char *)ptime; } + if( (*options) & DBR_UTAG ) { + epicsUInt64 *ptag = (epicsUInt64*)pbuffer; + if (!pfl) { + *ptag++ = pcommon->utag; + } else { + *ptag++ = pfl->utag; + } + pbuffer = (char *)ptag; + } if( (*options) & DBR_ENUM_STRS ) get_enum_strs(paddr, &pbuffer, prset, options); if( (*options) & (DBR_GR_LONG|DBR_GR_DOUBLE )) @@ -523,7 +542,7 @@ long dbProcess(dbCommon *precord) (precord->lcnt++ < MAX_LOCK) || (precord->sevr >= INVALID_ALARM)) goto all_done; - recGblSetSevr(precord, SCAN_ALARM, INVALID_ALARM); + recGblSetSevrMsg(precord, SCAN_ALARM, INVALID_ALARM, "Async in progress"); monitor_mask = recGblResetAlarms(precord); monitor_mask |= DBE_VALUE|DBE_LOG; pdbFldDes = pdbRecordType->papFldDes[pdbRecordType->indvalFlddes]; @@ -1357,7 +1376,8 @@ long dbPut(DBADDR *paddr, short dbrType, /* Always do special processing if needed */ if (special) { long status2 = dbPutSpecial(paddr, 1); - if (status2) goto done; + if (status2) + status = status2; } if (status) goto done; diff --git a/modules/database/src/ioc/db/dbAccess.h b/modules/database/src/ioc/db/dbAccess.h index f853f9010..7fa2bab9a 100644 --- a/modules/database/src/ioc/db/dbAccess.h +++ b/modules/database/src/ioc/db/dbAccess.h @@ -18,7 +18,7 @@ #include "dbFldTypes.h" #include "link.h" #include "dbBase.h" -#include "shareLib.h" +#include "dbCoreAPI.h" #include "dbAddr.h" #include "dbLock.h" #include "dbAccessDefs.h" diff --git a/modules/database/src/ioc/db/dbAccessDefs.h b/modules/database/src/ioc/db/dbAccessDefs.h index f2cf091a3..771084170 100644 --- a/modules/database/src/ioc/db/dbAccessDefs.h +++ b/modules/database/src/ioc/db/dbAccessDefs.h @@ -12,18 +12,10 @@ #ifndef INCdbAccessDefsh #define INCdbAccessDefsh -#ifdef epicsExportSharedSymbols -# define INCLdb_accessh_epicsExportSharedSymbols -# undef epicsExportSharedSymbols -#endif - #include "epicsTypes.h" #include "epicsTime.h" -#ifdef INCLdb_accessh_epicsExportSharedSymbols -# define epicsExportSharedSymbols -# include "shareLib.h" -#endif +#include "dbCoreAPI.h" #include "dbBase.h" #include "dbAddr.h" @@ -34,23 +26,25 @@ extern "C" { #endif -epicsShareExtern struct dbBase *pdbbase; -epicsShareExtern volatile int interruptAccept; -epicsShareExtern int dbAccessDebugPUTF; +DBCORE_API extern struct dbBase *pdbbase; +DBCORE_API extern volatile int interruptAccept; +DBCORE_API extern int dbAccessDebugPUTF; /* The database field and request types are defined in dbFldTypes.h*/ /* Data Base Request Options */ #define DBR_STATUS 0x00000001 -#define DBR_UNITS 0x00000002 -#define DBR_PRECISION 0x00000004 -#define DBR_TIME 0x00000008 -#define DBR_ENUM_STRS 0x00000010 -#define DBR_GR_LONG 0x00000020 -#define DBR_GR_DOUBLE 0x00000040 -#define DBR_CTRL_LONG 0x00000080 -#define DBR_CTRL_DOUBLE 0x00000100 -#define DBR_AL_LONG 0x00000200 -#define DBR_AL_DOUBLE 0x00000400 +#define DBR_AMSG 0x00000002 +#define DBR_UNITS 0x00000004 +#define DBR_PRECISION 0x00000008 +#define DBR_TIME 0x00000010 +#define DBR_UTAG 0x00000020 +#define DBR_ENUM_STRS 0x00000040 +#define DBR_GR_LONG 0x00000080 +#define DBR_GR_DOUBLE 0x00000100 +#define DBR_CTRL_LONG 0x00000200 +#define DBR_CTRL_DOUBLE 0x00000400 +#define DBR_AL_LONG 0x00000800 +#define DBR_AL_DOUBLE 0x00001000 /********************************************************************** * The next page contains macros for defining requests. @@ -108,6 +102,9 @@ epicsShareExtern int dbAccessDebugPUTF; epicsUInt16 severity; /* alarm severity*/\ epicsUInt16 acks; /* alarm ack severity*/\ epicsUInt16 ackt; /* Acknowledge transient alarms?*/ +#define DB_AMSG_SIZE 40 +#define DBRamsg \ + char amsg[DB_AMSG_SIZE]; #define DB_UNITS_SIZE 16 #define DBRunits \ char units[DB_UNITS_SIZE]; /* units */ @@ -120,7 +117,9 @@ epicsShareExtern int dbAccessDebugPUTF; * too late to change now. DBRprecision must be padded to * maintain 8-byte alignment. */ #define DBRtime \ - epicsTimeStamp time; /* time stamp*/ + epicsTimeStamp time; /* time stamp*/ +#define DBRutag \ + epicsUTag utag; #define DBRenumStrs \ epicsUInt32 no_str; /* number of strings*/\ epicsInt32 padenumStrs; /*padding to force 8 byte align*/\ @@ -207,67 +206,67 @@ struct dbr_alDouble {DBRalDouble}; struct dbEntry; -epicsShareFunc long dbPutSpecial(struct dbAddr *paddr,int pass); -epicsShareFunc rset * dbGetRset(const struct dbAddr *paddr); -epicsShareFunc long dbPutAttribute( +DBCORE_API long dbPutSpecial(struct dbAddr *paddr,int pass); +DBCORE_API rset * dbGetRset(const struct dbAddr *paddr); +DBCORE_API long dbPutAttribute( const char *recordTypename,const char *name,const char*value); -epicsShareFunc int dbIsValueField(const struct dbFldDes *pdbFldDes); -epicsShareFunc int dbGetFieldIndex(const struct dbAddr *paddr); -epicsShareFunc long dbScanPassive( +DBCORE_API int dbIsValueField(const struct dbFldDes *pdbFldDes); +DBCORE_API int dbGetFieldIndex(const struct dbAddr *paddr); +DBCORE_API long dbScanPassive( struct dbCommon *pfrom,struct dbCommon *pto); -epicsShareFunc long dbProcess(struct dbCommon *precord); -epicsShareFunc long dbNameToAddr(const char *pname, struct dbAddr *paddr); +DBCORE_API long dbProcess(struct dbCommon *precord); +DBCORE_API long dbNameToAddr(const char *pname, struct dbAddr *paddr); /** Initialize DBADDR from a dbEntry * Also handles SPC_DBADDR processing. This is really an internal * routine for use by dbNameToAddr() and dbChannelCreate(). */ -epicsShareFunc long dbEntryToAddr(const struct dbEntry *pdbentry, +DBCORE_API long dbEntryToAddr(const struct dbEntry *pdbentry, struct dbAddr *paddr); /** Initialize DBENTRY from a valid dbAddr* * Constant time equivalent of dbInitEntry() then dbFindRecord(), * and finally dbFollowAlias(). */ -epicsShareFunc void dbInitEntryFromAddr(struct dbAddr *paddr, +DBCORE_API void dbInitEntryFromAddr(struct dbAddr *paddr, struct dbEntry *pdbentry); /** Initialize DBENTRY from a valid record (dbCommon*) * Constant time equivalent of dbInitEntry() then dbFindRecord(), * and finally dbFollowAlias() when no field is specified. */ -epicsShareFunc void dbInitEntryFromRecord(struct dbCommon *prec, +DBCORE_API void dbInitEntryFromRecord(struct dbCommon *prec, struct dbEntry *pdbentry); -epicsShareFunc devSup* dbDTYPtoDevSup(dbRecordType *prdes, int dtyp); -epicsShareFunc devSup* dbDSETtoDevSup(dbRecordType *prdes, dset *pdset); -epicsShareFunc long dbGetField( +DBCORE_API devSup* dbDTYPtoDevSup(dbRecordType *prdes, int dtyp); +DBCORE_API devSup* dbDSETtoDevSup(dbRecordType *prdes, dset *pdset); +DBCORE_API long dbGetField( struct dbAddr *,short dbrType,void *pbuffer,long *options, long *nRequest,void *pfl); -epicsShareFunc long dbGet( +DBCORE_API long dbGet( struct dbAddr *,short dbrType,void *pbuffer,long *options, long *nRequest,void *pfl); -epicsShareFunc long dbPutField( +DBCORE_API long dbPutField( struct dbAddr *,short dbrType,const void *pbuffer,long nRequest); -epicsShareFunc long dbPut( +DBCORE_API long dbPut( struct dbAddr *,short dbrType,const void *pbuffer,long nRequest); typedef void(*SPC_ASCALLBACK)(struct dbCommon *); /*dbSpcAsRegisterCallback called by access security */ -epicsShareFunc void dbSpcAsRegisterCallback(SPC_ASCALLBACK func); -epicsShareFunc long dbBufferSize( +DBCORE_API void dbSpcAsRegisterCallback(SPC_ASCALLBACK func); +DBCORE_API long dbBufferSize( short dbrType,long options,long nRequest); -epicsShareFunc long dbValueSize(short dbrType); +DBCORE_API long dbValueSize(short dbrType); /* Hook Routine */ typedef void (*DB_LOAD_RECORDS_HOOK_ROUTINE)(const char* filename, const char* substitutions); -epicsShareExtern DB_LOAD_RECORDS_HOOK_ROUTINE dbLoadRecordsHook; +DBCORE_API extern DB_LOAD_RECORDS_HOOK_ROUTINE dbLoadRecordsHook; -epicsShareFunc int dbLoadDatabase( +DBCORE_API int dbLoadDatabase( const char *filename, const char *path, const char *substitutions); -epicsShareFunc int dbLoadRecords( +DBCORE_API int dbLoadRecords( const char* filename, const char* substitutions); #ifdef __cplusplus diff --git a/modules/database/src/ioc/db/dbBkpt.c b/modules/database/src/ioc/db/dbBkpt.c index 665ea077b..18a357ebe 100644 --- a/modules/database/src/ioc/db/dbBkpt.c +++ b/modules/database/src/ioc/db/dbBkpt.c @@ -53,7 +53,6 @@ #include "errlog.h" #include "errMdef.h" -#define epicsExportSharedSymbols #include "dbAccessDefs.h" #include "dbAddr.h" #include "dbBase.h" diff --git a/modules/database/src/ioc/db/dbBkpt.h b/modules/database/src/ioc/db/dbBkpt.h index e51882cdd..5265d3de6 100644 --- a/modules/database/src/ioc/db/dbBkpt.h +++ b/modules/database/src/ioc/db/dbBkpt.h @@ -20,7 +20,7 @@ #include "epicsEvent.h" #include "epicsThread.h" #include "epicsTime.h" -#include "shareLib.h" +#include "dbCoreAPI.h" #ifdef __cplusplus extern "C" { #endif @@ -81,18 +81,18 @@ struct LS_LIST { #define MAX_EP_COUNT 99999 -epicsShareFunc void dbBkptInit(void); -epicsShareFunc long dbb(const char *recordname); -epicsShareFunc long dbd(const char *recordname); -epicsShareFunc long dbc(const char *recordname); -epicsShareFunc long dbs(const char *recordname); -epicsShareFunc long dbstat(void); -epicsShareFunc long dbp( +DBCORE_API void dbBkptInit(void); +DBCORE_API long dbb(const char *recordname); +DBCORE_API long dbd(const char *recordname); +DBCORE_API long dbc(const char *recordname); +DBCORE_API long dbs(const char *recordname); +DBCORE_API long dbstat(void); +DBCORE_API long dbp( const char *record_name, int interest_level); -epicsShareFunc long dbap(const char *record_name); -epicsShareFunc int dbBkpt(struct dbCommon *precord); -epicsShareFunc void dbPrint(struct dbCommon *precord); -epicsShareFunc long dbprc(char *record_name); +DBCORE_API long dbap(const char *record_name); +DBCORE_API int dbBkpt(struct dbCommon *precord); +DBCORE_API void dbPrint(struct dbCommon *precord); +DBCORE_API long dbprc(char *record_name); extern long lset_stack_count; diff --git a/modules/database/src/ioc/db/dbCAC.h b/modules/database/src/ioc/db/dbCAC.h index ab4018139..9fbba07cd 100644 --- a/modules/database/src/ioc/db/dbCAC.h +++ b/modules/database/src/ioc/db/dbCAC.h @@ -19,11 +19,6 @@ #ifndef dbCACh #define dbCACh -#ifdef epicsExportSharedSymbols -# define dbCACh_restore_epicsExportSharedSymbols -# undef epicsExportSharedSymbols -#endif - #include "stdlib.h" #include // std::auto_ptr @@ -34,10 +29,7 @@ #include "cacIO.h" #include "compilerDependencies.h" -#ifdef dbCACh_restore_epicsExportSharedSymbols -# define epicsExportSharedSymbols -# include "shareLib.h" -#endif +#include "dbCoreAPI.h" #include "db_access.h" #include "dbNotify.h" diff --git a/modules/database/src/ioc/db/dbCa.c b/modules/database/src/ioc/db/dbCa.c index 0397064d7..70f939897 100644 --- a/modules/database/src/ioc/db/dbCa.c +++ b/modules/database/src/ioc/db/dbCa.c @@ -40,7 +40,6 @@ /* We can't include dbStaticLib.h here */ #define dbCalloc(nobj,size) callocMustSucceed(nobj,size,"dbCalloc") -#define epicsExportSharedSymbols #include "db_access_routines.h" #include "dbCa.h" #include "dbCaPvt.h" @@ -233,7 +232,7 @@ void dbCaSync(void) epicsEventDestroy(wake); } -epicsShareFunc unsigned long dbCaGetUpdateCount(struct link *plink) +DBCORE_API unsigned long dbCaGetUpdateCount(struct link *plink) { caLink *pca = (caLink *)plink->value.pv_link.pvt; unsigned long ret; diff --git a/modules/database/src/ioc/db/dbCa.h b/modules/database/src/ioc/db/dbCa.h index cd92ba0a7..42ce1b338 100644 --- a/modules/database/src/ioc/db/dbCa.h +++ b/modules/database/src/ioc/db/dbCa.h @@ -19,37 +19,37 @@ extern "C" { #endif typedef void (*dbCaCallback)(void *userPvt); -epicsShareFunc void dbCaCallbackProcess(void *usrPvt); +DBCORE_API void dbCaCallbackProcess(void *usrPvt); -epicsShareFunc void dbCaLinkInit(void); /* internal initialization for iocBuild() */ -epicsShareFunc void dbCaLinkInitIsolated(void); /* internal initialization for iocBuildIsolated() */ -epicsShareFunc void dbCaRun(void); -epicsShareFunc void dbCaPause(void); -epicsShareFunc void dbCaShutdown(void); +DBCORE_API void dbCaLinkInit(void); /* internal initialization for iocBuild() */ +DBCORE_API void dbCaLinkInitIsolated(void); /* internal initialization for iocBuildIsolated() */ +DBCORE_API void dbCaRun(void); +DBCORE_API void dbCaPause(void); +DBCORE_API void dbCaShutdown(void); struct dbLocker; -epicsShareFunc void dbCaAddLinkCallback(struct link *plink, +DBCORE_API void dbCaAddLinkCallback(struct link *plink, dbCaCallback connect, dbCaCallback monitor, void *userPvt); -epicsShareFunc long dbCaAddLink(struct dbLocker *locker, struct link *plink, short dbfType); -epicsShareFunc void dbCaRemoveLink(struct dbLocker *locker, struct link *plink); +DBCORE_API long dbCaAddLink(struct dbLocker *locker, struct link *plink, short dbfType); +DBCORE_API void dbCaRemoveLink(struct dbLocker *locker, struct link *plink); -epicsShareFunc long dbCaGetLink(struct link *plink, +DBCORE_API long dbCaGetLink(struct link *plink, short dbrType, void *pbuffer, long *nRequest); -epicsShareFunc long dbCaGetAttributes(const struct link *plink, +DBCORE_API long dbCaGetAttributes(const struct link *plink, dbCaCallback callback, void *userPvt); -epicsShareFunc long dbCaPutLinkCallback(struct link *plink, +DBCORE_API long dbCaPutLinkCallback(struct link *plink, short dbrType, const void *pbuffer,long nRequest, dbCaCallback callback, void *userPvt); -epicsShareFunc long dbCaPutLink(struct link *plink,short dbrType, +DBCORE_API long dbCaPutLink(struct link *plink,short dbrType, const void *pbuffer,long nRequest); extern struct ca_client_context * dbCaClientContext; #ifdef EPICS_DBCA_PRIVATE_API -epicsShareFunc void dbCaSync(void); -epicsShareFunc unsigned long dbCaGetUpdateCount(struct link *plink); +DBCORE_API void dbCaSync(void); +DBCORE_API unsigned long dbCaGetUpdateCount(struct link *plink); #endif /* These macros are for backwards compatibility */ diff --git a/modules/database/src/ioc/db/dbCaTest.c b/modules/database/src/ioc/db/dbCaTest.c index 43c1090dc..1610a8d59 100644 --- a/modules/database/src/ioc/db/dbCaTest.c +++ b/modules/database/src/ioc/db/dbCaTest.c @@ -26,9 +26,7 @@ #include "epicsPrint.h" #include "epicsStdio.h" -#define epicsExportSharedSymbols #include "dbStaticLib.h" -#undef epicsExportSharedSymbols /*definitions needed because of old vs new database access*/ #undef DBR_SHORT #undef DBR_PUT_ACKT @@ -42,7 +40,6 @@ /*define DB_CONVERT_GBLSOURCE because db_access.c does not include db_access.h*/ #define DB_CONVERT_GBLSOURCE -#define epicsExportSharedSymbols #include "db_access.h" #include "db_access_routines.h" #include "dbCa.h" diff --git a/modules/database/src/ioc/db/dbCaTest.h b/modules/database/src/ioc/db/dbCaTest.h index f38d76297..05a86ac2b 100644 --- a/modules/database/src/ioc/db/dbCaTest.h +++ b/modules/database/src/ioc/db/dbCaTest.h @@ -11,14 +11,14 @@ #ifndef INC_dbCaTest_H #define INC_dbCaTest_H -#include "shareLib.h" +#include "dbCoreAPI.h" #ifdef __cplusplus extern "C" { #endif -epicsShareFunc long dbcar(char *recordname,int level); -epicsShareFunc void dbcaStats(int *pchans, int *pdiscon); +DBCORE_API long dbcar(char *recordname,int level); +DBCORE_API void dbcaStats(int *pchans, int *pdiscon); #ifdef __cplusplus } diff --git a/modules/database/src/ioc/db/dbChannel.c b/modules/database/src/ioc/db/dbChannel.c index c71d8426f..a806f3cfa 100644 --- a/modules/database/src/ioc/db/dbChannel.c +++ b/modules/database/src/ioc/db/dbChannel.c @@ -29,7 +29,6 @@ #include "gpHash.h" #include "yajl_parse.h" -#define epicsExportSharedSymbols #include "dbAccessDefs.h" #include "dbBase.h" #include "dbChannel.h" diff --git a/modules/database/src/ioc/db/dbChannelIO.cpp b/modules/database/src/ioc/db/dbChannelIO.cpp index 61c260a94..449717e73 100644 --- a/modules/database/src/ioc/db/dbChannelIO.cpp +++ b/modules/database/src/ioc/db/dbChannelIO.cpp @@ -25,7 +25,6 @@ #include "db_access.h" #include "errlog.h" -#define epicsExportSharedSymbols #include "db_access_routines.h" #include "dbCAC.h" #include "dbChannelIO.h" diff --git a/modules/database/src/ioc/db/dbChannelIO.h b/modules/database/src/ioc/db/dbChannelIO.h index 661fbb4e4..6921b12eb 100644 --- a/modules/database/src/ioc/db/dbChannelIO.h +++ b/modules/database/src/ioc/db/dbChannelIO.h @@ -20,17 +20,8 @@ #ifndef dbChannelIOh #define dbChannelIOh -#ifdef epicsExportSharedSymbols -# define dbChannelIOh_restore_epicsExportSharedSymbols -# undef epicsExportSharedSymbols -#endif - #include "compilerDependencies.h" -#ifdef dbChannelIOh_restore_epicsExportSharedSymbols -# define epicsExportSharedSymbols -#endif - class dbChannelIO : public cacChannel, public dbContextPrivateListOfIO { public: dbChannelIO ( diff --git a/modules/database/src/ioc/db/dbCommon.dbd.pod b/modules/database/src/ioc/db/dbCommon.dbd.pod index 36b9c1adb..5ad4627c5 100644 --- a/modules/database/src/ioc/db/dbCommon.dbd.pod +++ b/modules/database/src/ioc/db/dbCommon.dbd.pod @@ -279,6 +279,11 @@ support routines which write to the VAL field are responsible for setting UDF. special(SPC_NOMOD) menu(menuAlarmSevr) } + field(AMSG,DBF_STRING) { + prompt("Alarm Message") + special(SPC_NOMOD) + size(40) + } field(NSTA,DBF_MENU) { prompt("New Alarm Status") special(SPC_NOMOD) @@ -291,6 +296,11 @@ support routines which write to the VAL field are responsible for setting UDF. interest(2) menu(menuAlarmSevr) } + field(NAMSG,DBF_STRING) { + prompt("New Alarm Message") + special(SPC_NOMOD) + size(40) + } field(ACKS,DBF_MENU) { prompt("Alarm Ack Severity") special(SPC_NOMOD) @@ -514,6 +524,11 @@ field which is then used to acquire a timestamp. interest(2) extra("epicsTimeStamp time") } + field(UTAG,DBF_UINT64) { + prompt("Time Tag") + special(SPC_NOMOD) + interest(3) + } field(FLNK,DBF_FWDLINK) { prompt("Forward Process Link") promptgroup("20 - Scan") diff --git a/modules/database/src/ioc/db/dbConstLink.c b/modules/database/src/ioc/db/dbConstLink.c index 5ba79f2b0..282493992 100644 --- a/modules/database/src/ioc/db/dbConstLink.c +++ b/modules/database/src/ioc/db/dbConstLink.c @@ -19,7 +19,6 @@ #include "dbDefs.h" #include "epicsStdlib.h" -#define epicsExportSharedSymbols #include "dbAccessDefs.h" #include "dbAddr.h" #include "dbCommon.h" diff --git a/modules/database/src/ioc/db/dbConstLink.h b/modules/database/src/ioc/db/dbConstLink.h index bf1559795..759a04771 100644 --- a/modules/database/src/ioc/db/dbConstLink.h +++ b/modules/database/src/ioc/db/dbConstLink.h @@ -16,7 +16,7 @@ #ifndef INC_dbConstLink_H #define INC_dbConstLink_H -#include "shareLib.h" +#include "dbCoreAPI.h" #ifdef __cplusplus extern "C" { @@ -24,8 +24,8 @@ extern "C" { struct link; -epicsShareFunc void dbConstInitLink(struct link *plink); -epicsShareFunc void dbConstAddLink(struct link *plink); +DBCORE_API void dbConstInitLink(struct link *plink); +DBCORE_API void dbConstAddLink(struct link *plink); #ifdef __cplusplus } diff --git a/modules/database/src/ioc/db/dbContext.cpp b/modules/database/src/ioc/db/dbContext.cpp index 4dea545dd..dc3087602 100644 --- a/modules/database/src/ioc/db/dbContext.cpp +++ b/modules/database/src/ioc/db/dbContext.cpp @@ -25,7 +25,6 @@ #include "epicsThread.h" #include "errlog.h" -#define epicsExportSharedSymbols #include "db_access_routines.h" #include "dbCAC.h" #include "dbChannel.h" diff --git a/modules/database/src/ioc/db/dbContextReadNotifyCache.cpp b/modules/database/src/ioc/db/dbContextReadNotifyCache.cpp index 5c343937a..efcfa1d74 100644 --- a/modules/database/src/ioc/db/dbContextReadNotifyCache.cpp +++ b/modules/database/src/ioc/db/dbContextReadNotifyCache.cpp @@ -20,7 +20,6 @@ #include "cadef.h" // this can be eliminated when the callbacks use the new interface #include "db_access.h" // should be eliminated here in the future -#define epicsExportSharedSymbols #include "db_access_routines.h" #include "dbCAC.h" diff --git a/modules/database/src/ioc/db/dbConvert.c b/modules/database/src/ioc/db/dbConvert.c index d4c1f91ee..84f36ed28 100644 --- a/modules/database/src/ioc/db/dbConvert.c +++ b/modules/database/src/ioc/db/dbConvert.c @@ -26,7 +26,6 @@ #include "errlog.h" #include "errMdef.h" -#define epicsExportSharedSymbols #include "dbAccessDefs.h" #include "dbAddr.h" #include "dbBase.h" diff --git a/modules/database/src/ioc/db/dbConvert.h b/modules/database/src/ioc/db/dbConvert.h index 54be3634c..92fec61bc 100644 --- a/modules/database/src/ioc/db/dbConvert.h +++ b/modules/database/src/ioc/db/dbConvert.h @@ -14,7 +14,7 @@ #include "dbFldTypes.h" #include "dbAddr.h" -#include "shareLib.h" +#include "dbCoreAPI.h" #ifdef __cplusplus extern "C" { @@ -25,8 +25,8 @@ typedef long (*GETCONVERTFUNC)(const DBADDR *paddr, void *pbuffer, typedef long (*PUTCONVERTFUNC)(DBADDR *paddr, const void *pbuffer, long nRequest, long no_elements, long offset); -epicsShareExtern GETCONVERTFUNC dbGetConvertRoutine[DBF_DEVICE+1][DBR_ENUM+1]; -epicsShareExtern PUTCONVERTFUNC dbPutConvertRoutine[DBR_ENUM+1][DBF_DEVICE+1]; +DBCORE_API extern GETCONVERTFUNC dbGetConvertRoutine[DBF_DEVICE+1][DBR_ENUM+1]; +DBCORE_API extern PUTCONVERTFUNC dbPutConvertRoutine[DBR_ENUM+1][DBF_DEVICE+1]; #ifdef __cplusplus } diff --git a/modules/database/src/ioc/db/dbConvertFast.h b/modules/database/src/ioc/db/dbConvertFast.h index cf621433c..7ab630b91 100644 --- a/modules/database/src/ioc/db/dbConvertFast.h +++ b/modules/database/src/ioc/db/dbConvertFast.h @@ -13,14 +13,14 @@ #define INCdbConvertFasth #include "dbFldTypes.h" -#include "shareLib.h" +#include "dbCoreAPI.h" #ifdef __cplusplus extern "C" { #endif -epicsShareExtern long (*dbFastGetConvertRoutine[DBF_DEVICE+1][DBR_ENUM+1])(); -epicsShareExtern long (*dbFastPutConvertRoutine[DBR_ENUM+1][DBF_DEVICE+1])(); +DBCORE_API extern long (*dbFastGetConvertRoutine[DBF_DEVICE+1][DBR_ENUM+1])(); +DBCORE_API extern long (*dbFastPutConvertRoutine[DBR_ENUM+1][DBF_DEVICE+1])(); #ifdef __cplusplus } diff --git a/modules/database/src/ioc/db/dbConvertJSON.c b/modules/database/src/ioc/db/dbConvertJSON.c index 81bec8858..2f54aa0d9 100644 --- a/modules/database/src/ioc/db/dbConvertJSON.c +++ b/modules/database/src/ioc/db/dbConvertJSON.c @@ -15,7 +15,6 @@ #include "yajl_alloc.h" #include "yajl_parse.h" -#define epicsExportSharedSymbols #include "dbAccessDefs.h" #include "dbConvertFast.h" #include "dbConvertJSON.h" diff --git a/modules/database/src/ioc/db/dbConvertJSON.h b/modules/database/src/ioc/db/dbConvertJSON.h index 5f4565b11..e01ad29aa 100644 --- a/modules/database/src/ioc/db/dbConvertJSON.h +++ b/modules/database/src/ioc/db/dbConvertJSON.h @@ -10,16 +10,16 @@ #ifndef INC_dbConvertJSON_H #define INC_dbConvertJSON_H -#include +#include #ifdef __cplusplus extern "C" { #endif /* This name should probably be changed to inclue "array" */ -epicsShareFunc long dbPutConvertJSON(const char *json, short dbrType, +DBCORE_API long dbPutConvertJSON(const char *json, short dbrType, void *pdest, long *psize); -epicsShareFunc long dbLSConvertJSON(const char *json, char *pdest, +DBCORE_API long dbLSConvertJSON(const char *json, char *pdest, epicsUInt32 size, epicsUInt32 *plen); #ifdef __cplusplus } diff --git a/modules/database/src/ioc/db/dbDbLink.c b/modules/database/src/ioc/db/dbDbLink.c index b2813145c..f8cfd8b5e 100644 --- a/modules/database/src/ioc/db/dbDbLink.c +++ b/modules/database/src/ioc/db/dbDbLink.c @@ -52,7 +52,6 @@ #include "caeventmask.h" -#define epicsExportSharedSymbols #include "dbAccessDefs.h" #include "dbAddr.h" #include "dbBase.h" @@ -338,8 +337,8 @@ static long dbDbGetUnits(const struct link *plink, char *units, int unitsSize) return 0; } -static long dbDbGetAlarm(const struct link *plink, epicsEnum16 *status, - epicsEnum16 *severity) +static long dbDbGetAlarmMsg(const struct link *plink, epicsEnum16 *status, + epicsEnum16 *severity, char *msgbuf, size_t msgbuflen) { dbChannel *chan = linkChannel(plink); dbCommon *precord = dbChannelRecord(chan); @@ -347,14 +346,20 @@ static long dbDbGetAlarm(const struct link *plink, epicsEnum16 *status, *status = precord->stat; if (severity) *severity = precord->sevr; + if (msgbuf && msgbuflen) { + strncpy(msgbuf, precord->amsg, msgbuflen-1); + msgbuf[msgbuflen-1] = '\0'; + } return 0; } -static long dbDbGetTimeStamp(const struct link *plink, epicsTimeStamp *pstamp) +static long dbDbGetTimeStampTag(const struct link *plink, epicsTimeStamp *pstamp, epicsUTag *ptag) { dbChannel *chan = linkChannel(plink); dbCommon *precord = dbChannelRecord(chan); *pstamp = precord->time; + if(ptag) + *ptag = precord->utag; return 0; } @@ -402,9 +407,11 @@ static lset dbDb_lset = { dbDbGetValue, dbDbGetControlLimits, dbDbGetGraphicLimits, dbDbGetAlarmLimits, dbDbGetPrecision, dbDbGetUnits, - dbDbGetAlarm, dbDbGetTimeStamp, + NULL, NULL, dbDbPutValue, NULL, - dbDbScanFwdLink, doLocked + dbDbScanFwdLink, doLocked, + dbDbGetAlarmMsg, + dbDbGetTimeStampTag, }; diff --git a/modules/database/src/ioc/db/dbDbLink.h b/modules/database/src/ioc/db/dbDbLink.h index 66bd452ee..939d8bdbd 100644 --- a/modules/database/src/ioc/db/dbDbLink.h +++ b/modules/database/src/ioc/db/dbDbLink.h @@ -16,7 +16,7 @@ #ifndef INC_dbDbLink_H #define INC_dbDbLink_H -#include "shareLib.h" +#include "dbCoreAPI.h" #ifdef __cplusplus extern "C" { @@ -25,8 +25,8 @@ extern "C" { struct link; struct dbLocker; -epicsShareFunc long dbDbInitLink(struct link *plink, short dbfType); -epicsShareFunc void dbDbAddLink(struct dbLocker *locker, struct link *plink, +DBCORE_API long dbDbInitLink(struct link *plink, short dbfType); +DBCORE_API void dbDbAddLink(struct dbLocker *locker, struct link *plink, short dbfType, dbChannel *ptarget); #ifdef __cplusplus diff --git a/modules/database/src/ioc/db/dbEvent.c b/modules/database/src/ioc/db/dbEvent.c index 1db01f2cd..7342a0852 100644 --- a/modules/database/src/ioc/db/dbEvent.c +++ b/modules/database/src/ioc/db/dbEvent.c @@ -37,7 +37,6 @@ #include "caeventmask.h" -#define epicsExportSharedSymbols #include "dbAccessDefs.h" #include "dbAddr.h" #include "dbBase.h" @@ -333,7 +332,7 @@ fail: } -epicsShareFunc void db_cleanup_events(void) +DBCORE_API void db_cleanup_events(void) { if(dbevEventUserFreeList) freeListCleanup(dbevEventUserFreeList); dbevEventUserFreeList = NULL; @@ -676,7 +675,10 @@ static db_field_log* db_create_field_log (struct dbChannel *chan, int use_val) struct dbCommon *prec = dbChannelRecord(chan); pLog->stat = prec->stat; pLog->sevr = prec->sevr; + strncpy(pLog->amsg, prec->amsg, sizeof(pLog->amsg)-1); + pLog->amsg[sizeof(pLog->amsg)-1] = '\0'; pLog->time = prec->time; + pLog->utag = prec->utag; pLog->field_type = dbChannelFieldType(chan); pLog->field_size = dbChannelFieldSize(chan); pLog->no_elements = dbChannelElements(chan); @@ -715,6 +717,7 @@ db_field_log* db_create_event_log (struct evSubscrip *pevent) { db_field_log *pLog = db_create_field_log(pevent->chan, pevent->useValque); if (pLog) { + pLog->mask = pevent->select; pLog->ctx = dbfl_context_event; } return pLog; diff --git a/modules/database/src/ioc/db/dbEvent.h b/modules/database/src/ioc/db/dbEvent.h index 2c6feca11..277d6c07e 100644 --- a/modules/database/src/ioc/db/dbEvent.h +++ b/modules/database/src/ioc/db/dbEvent.h @@ -20,18 +20,9 @@ #ifndef INCLdbEventh #define INCLdbEventh -#ifdef epicsExportSharedSymbols -# undef epicsExportSharedSymbols -# define INCLdbEventhExporting -#endif - #include "epicsThread.h" -#ifdef INCLdbEventhExporting -# define epicsExportSharedSymbols -#endif - -#include "shareLib.h" +#include "dbCoreAPI.h" #ifdef __cplusplus extern "C" { @@ -41,50 +32,50 @@ struct dbChannel; struct db_field_log; struct evSubscrip; -epicsShareFunc int db_event_list ( +DBCORE_API int db_event_list ( const char *name, unsigned level); -epicsShareFunc int dbel ( +DBCORE_API int dbel ( const char *name, unsigned level); -epicsShareFunc int db_post_events ( +DBCORE_API int db_post_events ( void *pRecord, void *pField, unsigned caEventMask ); typedef void * dbEventCtx; typedef void EXTRALABORFUNC (void *extralabor_arg); -epicsShareFunc dbEventCtx db_init_events (void); -epicsShareFunc int db_start_events ( +DBCORE_API dbEventCtx db_init_events (void); +DBCORE_API int db_start_events ( dbEventCtx ctx, const char *taskname, void (*init_func)(void *), void *init_func_arg, unsigned osiPriority ); -epicsShareFunc void db_close_events (dbEventCtx ctx); -epicsShareFunc void db_event_flow_ctrl_mode_on (dbEventCtx ctx); -epicsShareFunc void db_event_flow_ctrl_mode_off (dbEventCtx ctx); -epicsShareFunc int db_add_extra_labor_event ( +DBCORE_API void db_close_events (dbEventCtx ctx); +DBCORE_API void db_event_flow_ctrl_mode_on (dbEventCtx ctx); +DBCORE_API void db_event_flow_ctrl_mode_off (dbEventCtx ctx); +DBCORE_API int db_add_extra_labor_event ( dbEventCtx ctx, EXTRALABORFUNC *func, void *arg); -epicsShareFunc void db_flush_extra_labor_event (dbEventCtx); -epicsShareFunc int db_post_extra_labor (dbEventCtx ctx); -epicsShareFunc void db_event_change_priority ( dbEventCtx ctx, unsigned epicsPriority ); +DBCORE_API void db_flush_extra_labor_event (dbEventCtx); +DBCORE_API int db_post_extra_labor (dbEventCtx ctx); +DBCORE_API void db_event_change_priority ( dbEventCtx ctx, unsigned epicsPriority ); #ifdef EPICS_PRIVATE_API -epicsShareFunc void db_cleanup_events(void); -epicsShareFunc void db_init_event_freelists (void); +DBCORE_API void db_cleanup_events(void); +DBCORE_API void db_init_event_freelists (void); #endif typedef void EVENTFUNC (void *user_arg, struct dbChannel *chan, int eventsRemaining, struct db_field_log *pfl); typedef void * dbEventSubscription; -epicsShareFunc dbEventSubscription db_add_event ( +DBCORE_API dbEventSubscription db_add_event ( dbEventCtx ctx, struct dbChannel *chan, EVENTFUNC *user_sub, void *user_arg, unsigned select); -epicsShareFunc void db_cancel_event (dbEventSubscription es); -epicsShareFunc void db_post_single_event (dbEventSubscription es); -epicsShareFunc void db_event_enable (dbEventSubscription es); -epicsShareFunc void db_event_disable (dbEventSubscription es); +DBCORE_API void db_cancel_event (dbEventSubscription es); +DBCORE_API void db_post_single_event (dbEventSubscription es); +DBCORE_API void db_event_enable (dbEventSubscription es); +DBCORE_API void db_event_disable (dbEventSubscription es); -epicsShareFunc struct db_field_log* db_create_event_log (struct evSubscrip *pevent); -epicsShareFunc struct db_field_log* db_create_read_log (struct dbChannel *chan); -epicsShareFunc void db_delete_field_log (struct db_field_log *pfl); -epicsShareFunc int db_available_logs(void); +DBCORE_API struct db_field_log* db_create_event_log (struct evSubscrip *pevent); +DBCORE_API struct db_field_log* db_create_read_log (struct dbChannel *chan); +DBCORE_API void db_delete_field_log (struct db_field_log *pfl); +DBCORE_API int db_available_logs(void); #define DB_EVENT_OK 0 #define DB_EVENT_ERROR (-1) diff --git a/modules/database/src/ioc/db/dbExtractArray.c b/modules/database/src/ioc/db/dbExtractArray.c index 197e66c3a..ec6d0392f 100644 --- a/modules/database/src/ioc/db/dbExtractArray.c +++ b/modules/database/src/ioc/db/dbExtractArray.c @@ -23,7 +23,6 @@ #include "epicsTypes.h" -#define epicsExportSharedSymbols #include "dbAddr.h" #include "dbExtractArray.h" diff --git a/modules/database/src/ioc/db/dbExtractArray.h b/modules/database/src/ioc/db/dbExtractArray.h index 9755ac570..efff6fecf 100644 --- a/modules/database/src/ioc/db/dbExtractArray.h +++ b/modules/database/src/ioc/db/dbExtractArray.h @@ -16,7 +16,7 @@ #include "dbFldTypes.h" #include "dbAddr.h" -#include "shareLib.h" +#include "dbCoreAPI.h" #ifdef __cplusplus extern "C" { @@ -49,7 +49,7 @@ extern "C" { * @param offset Wrap-around point in source array. * @param increment Copy only every increment'th element. */ -epicsShareFunc void dbExtractArray(const void *pfrom, void *pto, +DBCORE_API void dbExtractArray(const void *pfrom, void *pto, short field_size, long nRequest, long no_elements, long offset, long increment); diff --git a/modules/database/src/ioc/db/dbFastLinkConv.c b/modules/database/src/ioc/db/dbFastLinkConv.c index 3e1c7e815..fd2defb32 100644 --- a/modules/database/src/ioc/db/dbFastLinkConv.c +++ b/modules/database/src/ioc/db/dbFastLinkConv.c @@ -27,7 +27,6 @@ #include "errlog.h" #include "errMdef.h" -#define epicsExportSharedSymbols #include "dbAccessDefs.h" #include "dbAddr.h" #include "dbBase.h" diff --git a/modules/database/src/ioc/db/dbIocRegister.c b/modules/database/src/ioc/db/dbIocRegister.c index 5bd908ace..4df5ae336 100644 --- a/modules/database/src/ioc/db/dbIocRegister.c +++ b/modules/database/src/ioc/db/dbIocRegister.c @@ -10,7 +10,6 @@ #include "iocsh.h" -#define epicsExportSharedSymbols #include "callback.h" #include "dbAccess.h" #include "dbBkpt.h" @@ -26,7 +25,7 @@ #include "db_test.h" #include "dbTest.h" -epicsShareExtern int callbackParallelThreadsDefault; +DBCORE_API extern int callbackParallelThreadsDefault; /* dbLoadDatabase */ static const iocshArg dbLoadDatabaseArg0 = { "file name",iocshArgString}; diff --git a/modules/database/src/ioc/db/dbIocRegister.h b/modules/database/src/ioc/db/dbIocRegister.h index af850ac83..99d371087 100644 --- a/modules/database/src/ioc/db/dbIocRegister.h +++ b/modules/database/src/ioc/db/dbIocRegister.h @@ -11,13 +11,13 @@ #ifndef INC_dbIocRegister_H #define INC_dbIocRegister_H -#include "shareLib.h" +#include "dbCoreAPI.h" #ifdef __cplusplus extern "C" { #endif -epicsShareFunc void dbIocRegister(void); +DBCORE_API void dbIocRegister(void); #ifdef __cplusplus } diff --git a/modules/database/src/ioc/db/dbJLink.c b/modules/database/src/ioc/db/dbJLink.c index 8c63c4cd7..d3aacf060 100644 --- a/modules/database/src/ioc/db/dbJLink.c +++ b/modules/database/src/ioc/db/dbJLink.c @@ -16,7 +16,6 @@ #include "yajl_alloc.h" #include "yajl_parse.h" -#define epicsExportSharedSymbols #include "dbAccessDefs.h" #include "dbCommon.h" #include "dbStaticLib.h" diff --git a/modules/database/src/ioc/db/dbJLink.h b/modules/database/src/ioc/db/dbJLink.h index 106c51640..1899736e4 100644 --- a/modules/database/src/ioc/db/dbJLink.h +++ b/modules/database/src/ioc/db/dbJLink.h @@ -22,7 +22,7 @@ typedef enum { jlif_continue = 1 } jlif_result; -epicsShareExtern const char *jlif_result_name[2]; +DBCORE_API extern const char *jlif_result_name[2]; typedef enum { jlif_key_stop = jlif_stop, @@ -30,7 +30,7 @@ typedef enum { jlif_key_child_inlink, jlif_key_child_outlink, jlif_key_child_fwdlink } jlif_key_result; -epicsShareExtern const char *jlif_key_result_name[5]; +DBCORE_API extern const char *jlif_key_result_name[5]; struct link; struct lset; diff --git a/modules/database/src/ioc/db/dbLink.c b/modules/database/src/ioc/db/dbLink.c index ef8336818..f5d286447 100644 --- a/modules/database/src/ioc/db/dbLink.c +++ b/modules/database/src/ioc/db/dbLink.c @@ -28,7 +28,6 @@ #include "caeventmask.h" -#define epicsExportSharedSymbols #include "dbAccessDefs.h" #include "dbAddr.h" #include "dbBase.h" @@ -314,10 +313,16 @@ long dbTryGetLink(struct link *plink, short dbrType, void *pbuffer, return plset->getValue(plink, dbrType, pbuffer, pnRequest); } +static +void setLinkAlarm(struct link* plink) +{ + recGblSetSevrMsg(plink->precord, LINK_ALARM, INVALID_ALARM, + "field %s", dbLinkFieldName(plink)); +} + long dbGetLink(struct link *plink, short dbrType, void *pbuffer, long *poptions, long *pnRequest) { - struct dbCommon *precord = plink->precord; long status; if (poptions && *poptions) { @@ -329,7 +334,7 @@ long dbGetLink(struct link *plink, short dbrType, void *pbuffer, if (status == S_db_noLSET) return -1; if (status) - recGblSetSevr(precord, LINK_ALARM, INVALID_ALARM); + setLinkAlarm(plink); return status; } @@ -386,24 +391,42 @@ long dbGetUnits(const struct link *plink, char *units, int unitsSize) } long dbGetAlarm(const struct link *plink, epicsEnum16 *status, - epicsEnum16 *severity) + epicsEnum16 *severity) +{ + return dbGetAlarmMsg(plink, status, severity, NULL, 0); +} + +long dbGetAlarmMsg(const struct link *plink, epicsEnum16 *status, + epicsEnum16 *severity, char *msgbuf, size_t msgbuflen) { lset *plset = plink->lset; - if (!plset || !plset->getAlarm) + if (plset && plset->getAlarmMsg) { + return plset->getAlarmMsg(plink, status, severity, msgbuf, msgbuflen); + } else if(plset && plset->getAlarm) { + return plset->getAlarm(plink, status, severity); + } else { return S_db_noLSET; - - return plset->getAlarm(plink, status, severity); + } } long dbGetTimeStamp(const struct link *plink, epicsTimeStamp *pstamp) +{ + return dbGetTimeStampTag(plink, pstamp, NULL); +} + +long dbGetTimeStampTag(const struct link *plink, + epicsTimeStamp *pstamp, epicsUTag *ptag) { lset *plset = plink->lset; - if (!plset || !plset->getTimeStamp) + if (plset && plset->getTimeStampTag) { + return plset->getTimeStampTag(plink, pstamp, ptag); + } else if(plset && plset->getTimeStamp) { + return plset->getTimeStamp(plink, pstamp); + } else { return S_db_noLSET; - - return plset->getTimeStamp(plink, pstamp); + } } long dbPutLink(struct link *plink, short dbrType, const void *pbuffer, @@ -417,9 +440,7 @@ long dbPutLink(struct link *plink, short dbrType, const void *pbuffer, status = plset->putValue(plink, dbrType, pbuffer, nRequest); if (status) { - struct dbCommon *precord = plink->precord; - - recGblSetSevr(precord, LINK_ALARM, INVALID_ALARM); + setLinkAlarm(plink); } return status; } @@ -444,9 +465,7 @@ long dbPutLinkAsync(struct link *plink, short dbrType, const void *pbuffer, status = plset->putAsync(plink, dbrType, pbuffer, nRequest); if (status) { - struct dbCommon *precord = plink->precord; - - recGblSetSevr(precord, LINK_ALARM, INVALID_ALARM); + setLinkAlarm(plink); } return status; } diff --git a/modules/database/src/ioc/db/dbLink.h b/modules/database/src/ioc/db/dbLink.h index f7c11c748..1933952b9 100644 --- a/modules/database/src/ioc/db/dbLink.h +++ b/modules/database/src/ioc/db/dbLink.h @@ -17,7 +17,7 @@ #define INC_dbLink_H #include "link.h" -#include "shareLib.h" +#include "dbCoreAPI.h" #include "epicsTypes.h" #include "epicsTime.h" #include "dbAddr.h" @@ -361,64 +361,99 @@ typedef struct lset { * @returns status value */ long (*doLocked)(struct link *plink, dbLinkUserCallback rtn, void *priv); + + /** @brief Extended version of getAlarm + * + * Equivalent of getAlarm() and also copy out alarm message string. + * The msgbuf argument may be NULL and/or msgbuflen==0, in which case + * the effect must be the same as a call to getAlarm(). + * + * Implementations must write a trailing nil to msgbuf whenever + * @code msgbuf!=NULL && msgbuflen>0 @endcode . + * + * @since UNRELEASED + */ + long (*getAlarmMsg)(const struct link *plink, epicsEnum16 *status, + epicsEnum16 *severity, char *msgbuf, size_t msgbuflen); + + /** @brief Extended version of getTimeStamp + * + * Equivalent of getTimeStamp() and also copy out time tag. + * ptag may be NULL. + * + * @since Added after UNRELEASED + */ + long (*getTimeStampTag)(const struct link *plink, epicsTimeStamp *pstamp, epicsUTag *ptag); } lset; #define dbGetSevr(link, sevr) \ dbGetAlarm(link, NULL, sevr) -epicsShareFunc const char * dbLinkFieldName(const struct link *plink); +DBCORE_API const char * dbLinkFieldName(const struct link *plink); -epicsShareFunc void dbInitLink(struct link *plink, short dbfType); -epicsShareFunc void dbAddLink(struct dbLocker *locker, struct link *plink, +DBCORE_API void dbInitLink(struct link *plink, short dbfType); +DBCORE_API void dbAddLink(struct dbLocker *locker, struct link *plink, short dbfType, dbChannel *ptarget); -epicsShareFunc void dbLinkOpen(struct link *plink); -epicsShareFunc void dbRemoveLink(struct dbLocker *locker, struct link *plink); +DBCORE_API void dbLinkOpen(struct link *plink); +DBCORE_API void dbRemoveLink(struct dbLocker *locker, struct link *plink); -epicsShareFunc int dbLinkIsDefined(const struct link *plink); /* 0 or 1 */ -epicsShareFunc int dbLinkIsConstant(const struct link *plink); /* 0 or 1 */ -epicsShareFunc int dbLinkIsVolatile(const struct link *plink); /* 0 or 1 */ +DBCORE_API int dbLinkIsDefined(const struct link *plink); /* 0 or 1 */ +DBCORE_API int dbLinkIsConstant(const struct link *plink); /* 0 or 1 */ +DBCORE_API int dbLinkIsVolatile(const struct link *plink); /* 0 or 1 */ -epicsShareFunc long dbLoadLink(struct link *plink, short dbrType, +DBCORE_API long dbLoadLink(struct link *plink, short dbrType, void *pbuffer); -epicsShareFunc long dbLoadLinkArray(struct link *, short dbrType, void *pbuffer, +DBCORE_API long dbLoadLinkArray(struct link *, short dbrType, void *pbuffer, long *pnRequest); -epicsShareFunc long dbGetNelements(const struct link *plink, long *pnElements); -epicsShareFunc int dbIsLinkConnected(const struct link *plink); /* 0 or 1 */ -epicsShareFunc int dbGetLinkDBFtype(const struct link *plink); -epicsShareFunc long dbTryGetLink(struct link *, short dbrType, void *pbuffer, +DBCORE_API long dbGetNelements(const struct link *plink, long *pnElements); +DBCORE_API int dbIsLinkConnected(const struct link *plink); /* 0 or 1 */ +DBCORE_API int dbGetLinkDBFtype(const struct link *plink); +DBCORE_API long dbTryGetLink(struct link *, short dbrType, void *pbuffer, long *nRequest); -epicsShareFunc long dbGetLink(struct link *, short dbrType, void *pbuffer, +DBCORE_API long dbGetLink(struct link *, short dbrType, void *pbuffer, long *options, long *nRequest); -epicsShareFunc long dbGetControlLimits(const struct link *plink, double *low, +DBCORE_API long dbGetControlLimits(const struct link *plink, double *low, double *high); -epicsShareFunc long dbGetGraphicLimits(const struct link *plink, double *low, +DBCORE_API long dbGetGraphicLimits(const struct link *plink, double *low, double *high); -epicsShareFunc long dbGetAlarmLimits(const struct link *plink, double *lolo, +DBCORE_API long dbGetAlarmLimits(const struct link *plink, double *lolo, double *low, double *high, double *hihi); -epicsShareFunc long dbGetPrecision(const struct link *plink, short *precision); -epicsShareFunc long dbGetUnits(const struct link *plink, char *units, +DBCORE_API long dbGetPrecision(const struct link *plink, short *precision); +DBCORE_API long dbGetUnits(const struct link *plink, char *units, int unitsSize); -epicsShareFunc long dbGetAlarm(const struct link *plink, epicsEnum16 *status, +DBCORE_API long dbGetAlarm(const struct link *plink, epicsEnum16 *status, epicsEnum16 *severity); -epicsShareFunc long dbGetTimeStamp(const struct link *plink, +/** Get link alarm and message string. + * To ensure the complete message string is copied, ensure @code msgbuflen >= sizeof (dbCommon::amsg) @endcode . + * A trailing nil will be added whenever @code msgbuflen > 0 @endcode . + * @since UNRELEASED + */ +DBCORE_API long dbGetAlarmMsg(const struct link *plink, epicsEnum16 *status, + epicsEnum16 *severity, char *msgbuf, size_t msgbuflen); +#define dbGetAlarmMsg(LINK, STAT, SEVR, BUF, BUFLEN) dbGetAlarmMsg(LINK, STAT, SEVR, BUF, BUFLEN) +DBCORE_API long dbGetTimeStamp(const struct link *plink, epicsTimeStamp *pstamp); -epicsShareFunc long dbPutLink(struct link *plink, short dbrType, +/** @since UNRELEASED */ +DBCORE_API long dbGetTimeStampTag(const struct link *plink, + epicsTimeStamp *pstamp, epicsUTag *ptag); +#define dbGetTimeStampTag(LINK, STAMP, TAG) dbGetTimeStampTag(LINK, STAMP, TAG) +DBCORE_API long dbPutLink(struct link *plink, short dbrType, const void *pbuffer, long nRequest); -epicsShareFunc void dbLinkAsyncComplete(struct link *plink); -epicsShareFunc long dbPutLinkAsync(struct link *plink, short dbrType, +DBCORE_API void dbLinkAsyncComplete(struct link *plink); +DBCORE_API long dbPutLinkAsync(struct link *plink, short dbrType, const void *pbuffer, long nRequest); -epicsShareFunc void dbScanFwdLink(struct link *plink); +DBCORE_API void dbScanFwdLink(struct link *plink); -epicsShareFunc long dbLinkDoLocked(struct link *plink, dbLinkUserCallback rtn, +DBCORE_API long dbLinkDoLocked(struct link *plink, dbLinkUserCallback rtn, void *priv); -epicsShareFunc long dbLoadLinkLS(struct link *plink, char *pbuffer, +DBCORE_API long dbLoadLinkLS(struct link *plink, char *pbuffer, epicsUInt32 size, epicsUInt32 *plen); -epicsShareFunc long dbGetLinkLS(struct link *plink, char *pbuffer, +DBCORE_API long dbGetLinkLS(struct link *plink, char *pbuffer, epicsUInt32 buffer_size, epicsUInt32 *plen); -epicsShareFunc long dbPutLinkLS(struct link *plink, char *pbuffer, +DBCORE_API long dbPutLinkLS(struct link *plink, char *pbuffer, epicsUInt32 len); #ifdef __cplusplus diff --git a/modules/database/src/ioc/db/dbLock.c b/modules/database/src/ioc/db/dbLock.c index 002b5cfc2..6d2acaf2f 100644 --- a/modules/database/src/ioc/db/dbLock.c +++ b/modules/database/src/ioc/db/dbLock.c @@ -25,7 +25,6 @@ #include "epicsThread.h" #include "errMdef.h" -#define epicsExportSharedSymbols #include "dbAccessDefs.h" #include "dbAddr.h" #include "dbBase.h" diff --git a/modules/database/src/ioc/db/dbLock.h b/modules/database/src/ioc/db/dbLock.h index bb26657c1..3d617f995 100644 --- a/modules/database/src/ioc/db/dbLock.h +++ b/modules/database/src/ioc/db/dbLock.h @@ -16,7 +16,7 @@ #include #include "ellLib.h" -#include "shareLib.h" +#include "dbCoreAPI.h" #ifdef __cplusplus extern "C" { @@ -26,38 +26,38 @@ struct dbCommon; struct dbBase; typedef struct dbLocker dbLocker; -epicsShareFunc void dbScanLock(struct dbCommon *precord); -epicsShareFunc void dbScanUnlock(struct dbCommon *precord); +DBCORE_API void dbScanLock(struct dbCommon *precord); +DBCORE_API void dbScanUnlock(struct dbCommon *precord); -epicsShareFunc dbLocker *dbLockerAlloc(struct dbCommon * const *precs, +DBCORE_API dbLocker *dbLockerAlloc(struct dbCommon * const *precs, size_t nrecs, unsigned int flags); -epicsShareFunc void dbLockerFree(dbLocker *); +DBCORE_API void dbLockerFree(dbLocker *); -epicsShareFunc void dbScanLockMany(dbLocker*); -epicsShareFunc void dbScanUnlockMany(dbLocker*); +DBCORE_API void dbScanLockMany(dbLocker*); +DBCORE_API void dbScanUnlockMany(dbLocker*); -epicsShareFunc unsigned long dbLockGetLockId( +DBCORE_API unsigned long dbLockGetLockId( struct dbCommon *precord); -epicsShareFunc void dbLockInitRecords(struct dbBase *pdbbase); -epicsShareFunc void dbLockCleanupRecords(struct dbBase *pdbbase); +DBCORE_API void dbLockInitRecords(struct dbBase *pdbbase); +DBCORE_API void dbLockCleanupRecords(struct dbBase *pdbbase); /* Lock Set Report */ -epicsShareFunc long dblsr(char *recordname,int level); +DBCORE_API long dblsr(char *recordname,int level); /* If recordname NULL then all records*/ /* level = (0,1,2) (lock set state, + recordname, +DB links) */ -epicsShareFunc long dbLockShowLocked(int level); +DBCORE_API long dbLockShowLocked(int level); /*KLUDGE to support field TPRO*/ -epicsShareFunc int * dbLockSetAddrTrace(struct dbCommon *precord); +DBCORE_API int * dbLockSetAddrTrace(struct dbCommon *precord); /* debugging */ -epicsShareFunc unsigned long dbLockGetRefs(struct dbCommon*); -epicsShareFunc unsigned long dbLockCountSets(void); +DBCORE_API unsigned long dbLockGetRefs(struct dbCommon*); +DBCORE_API unsigned long dbLockCountSets(void); #ifdef __cplusplus } diff --git a/modules/database/src/ioc/db/dbLockPvt.h b/modules/database/src/ioc/db/dbLockPvt.h index dd9de6bd0..520241c3e 100644 --- a/modules/database/src/ioc/db/dbLockPvt.h +++ b/modules/database/src/ioc/db/dbLockPvt.h @@ -92,9 +92,9 @@ extern "C" { #endif /* These are exported for testing only */ -epicsShareFunc lockSet* dbLockGetRef(lockRecord *lr); /* lookup lockset and increment ref count */ -epicsShareFunc void dbLockIncRef(lockSet* ls); -epicsShareFunc void dbLockDecRef(lockSet *ls); +DBCORE_API lockSet* dbLockGetRef(lockRecord *lr); /* lookup lockset and increment ref count */ +DBCORE_API void dbLockIncRef(lockSet* ls); +DBCORE_API void dbLockDecRef(lockSet *ls); /* Calling dbLockerPrepare directly is an internal * optimization used when dbLocker on the stack. diff --git a/modules/database/src/ioc/db/dbNotify.c b/modules/database/src/ioc/db/dbNotify.c index 45c759f46..e596285c2 100644 --- a/modules/database/src/ioc/db/dbNotify.c +++ b/modules/database/src/ioc/db/dbNotify.c @@ -33,7 +33,6 @@ #include "errlog.h" #include "errMdef.h" -#define epicsExportSharedSymbols #include "callback.h" #include "dbAccessDefs.h" #include "dbBase.h" diff --git a/modules/database/src/ioc/db/dbNotify.h b/modules/database/src/ioc/db/dbNotify.h index 6de2b13ea..3262009c9 100644 --- a/modules/database/src/ioc/db/dbNotify.h +++ b/modules/database/src/ioc/db/dbNotify.h @@ -12,7 +12,7 @@ #ifndef INCdbNotifyh #define INCdbNotifyh -#include "shareLib.h" +#include "dbCoreAPI.h" #include "ellLib.h" #ifdef __cplusplus @@ -70,32 +70,32 @@ typedef struct processNotify { /* dbProcessNotify and dbNotifyCancel are called by user*/ -epicsShareFunc void dbProcessNotify(processNotify *pprocessNotify); -epicsShareFunc void dbNotifyCancel(processNotify *pprocessNotify); +DBCORE_API void dbProcessNotify(processNotify *pprocessNotify); +DBCORE_API void dbNotifyCancel(processNotify *pprocessNotify); /* dbProcessNotifyInit called by iocInit */ -epicsShareFunc void dbProcessNotifyInit(void); -epicsShareFunc void dbProcessNotifyExit(void); +DBCORE_API void dbProcessNotifyInit(void); +DBCORE_API void dbProcessNotifyExit(void); /*dbNotifyAdd called by dbScanPassive and dbScanLink*/ -epicsShareFunc void dbNotifyAdd( +DBCORE_API void dbNotifyAdd( struct dbCommon *pfrom,struct dbCommon *pto); /*dbNotifyCompletion called by recGblFwdLink or dbAccess*/ -epicsShareFunc void dbNotifyCompletion(struct dbCommon *precord); +DBCORE_API void dbNotifyCompletion(struct dbCommon *precord); /* db_put_process defined here since it requires dbNotify. * src_type is the old DBR type * This is called by a dbNotify putCallback that uses oldDbr types */ -epicsShareFunc int db_put_process( +DBCORE_API int db_put_process( processNotify *processNotify,notifyPutType type, int src_type,const void *psrc, int no_elements); /* dbtpn is test routine for dbNotify putProcessRequest */ -epicsShareFunc long dbtpn(char *recordname,char *value); +DBCORE_API long dbtpn(char *recordname,char *value); /* dbNotifyDump is an INVASIVE debug utility. Don't use this needlessly*/ -epicsShareFunc int dbNotifyDump(void); +DBCORE_API int dbNotifyDump(void); /* This module provides code to handle process notify. * client code semantics are: diff --git a/modules/database/src/ioc/db/dbPutNotifyBlocker.cpp b/modules/database/src/ioc/db/dbPutNotifyBlocker.cpp index 20346073e..394b50c50 100644 --- a/modules/database/src/ioc/db/dbPutNotifyBlocker.cpp +++ b/modules/database/src/ioc/db/dbPutNotifyBlocker.cpp @@ -31,7 +31,6 @@ #include "caerr.h" // this needs to be eliminated #include "db_access.h" // this needs to be eliminated -#define epicsExportSharedSymbols #include "dbCAC.h" #include "dbChannelIO.h" #include "dbPutNotifyBlocker.h" diff --git a/modules/database/src/ioc/db/dbPutNotifyBlocker.h b/modules/database/src/ioc/db/dbPutNotifyBlocker.h index 8c2c872d3..c96858717 100644 --- a/modules/database/src/ioc/db/dbPutNotifyBlocker.h +++ b/modules/database/src/ioc/db/dbPutNotifyBlocker.h @@ -17,18 +17,9 @@ #ifndef dbPutNotifyBlockerh #define dbPutNotifyBlockerh -#ifdef epicsExportSharedSymbols -#define dbPutNotifyBlockerh_restore_epicsExportSharedSymbols -#undef epicsExportSharedSymbols -#endif - #include "tsFreeList.h" #include "compilerDependencies.h" -#ifdef dbPutNotifyBlockerh_restore_epicsExportSharedSymbols -#define epicsExportSharedSymbols -#endif - class dbPutNotifyBlocker : public dbBaseIO { public: dbPutNotifyBlocker ( epicsMutex & ); diff --git a/modules/database/src/ioc/db/dbScan.c b/modules/database/src/ioc/db/dbScan.c index 256fe4ac7..0b951dd4b 100644 --- a/modules/database/src/ioc/db/dbScan.c +++ b/modules/database/src/ioc/db/dbScan.c @@ -37,7 +37,6 @@ #include "epicsTime.h" #include "taskwd.h" -#define epicsExportSharedSymbols #include "callback.h" #include "dbAccessDefs.h" #include "dbAddr.h" diff --git a/modules/database/src/ioc/db/dbScan.h b/modules/database/src/ioc/db/dbScan.h index 2baee6f78..1839ae321 100644 --- a/modules/database/src/ioc/db/dbScan.h +++ b/modules/database/src/ioc/db/dbScan.h @@ -18,7 +18,7 @@ #include #include "menuScan.h" -#include "shareLib.h" +#include "dbCoreAPI.h" #include "compilerDependencies.h" #include "devSup.h" @@ -50,37 +50,37 @@ typedef struct scanOnceQueueStats { int numOverflow; } scanOnceQueueStats; -epicsShareFunc long scanInit(void); -epicsShareFunc void scanRun(void); -epicsShareFunc void scanPause(void); -epicsShareFunc void scanStop(void); -epicsShareFunc void scanCleanup(void); +DBCORE_API long scanInit(void); +DBCORE_API void scanRun(void); +DBCORE_API void scanPause(void); +DBCORE_API void scanStop(void); +DBCORE_API void scanCleanup(void); -epicsShareFunc EVENTPVT eventNameToHandle(const char* event); -epicsShareFunc void postEvent(EVENTPVT epvt); -epicsShareFunc void post_event(int event); -epicsShareFunc void scanAdd(struct dbCommon *); -epicsShareFunc void scanDelete(struct dbCommon *); -epicsShareFunc double scanPeriod(int scan); -epicsShareFunc int scanOnce(struct dbCommon *); -epicsShareFunc int scanOnceCallback(struct dbCommon *, once_complete cb, void *usr); -epicsShareFunc int scanOnceSetQueueSize(int size); -epicsShareFunc int scanOnceQueueStatus(const int reset, scanOnceQueueStats *result); -epicsShareFunc void scanOnceQueueShow(const int reset); +DBCORE_API EVENTPVT eventNameToHandle(const char* event); +DBCORE_API void postEvent(EVENTPVT epvt); +DBCORE_API void post_event(int event); +DBCORE_API void scanAdd(struct dbCommon *); +DBCORE_API void scanDelete(struct dbCommon *); +DBCORE_API double scanPeriod(int scan); +DBCORE_API int scanOnce(struct dbCommon *); +DBCORE_API int scanOnceCallback(struct dbCommon *, once_complete cb, void *usr); +DBCORE_API int scanOnceSetQueueSize(int size); +DBCORE_API int scanOnceQueueStatus(const int reset, scanOnceQueueStats *result); +DBCORE_API void scanOnceQueueShow(const int reset); /*print periodic lists*/ -epicsShareFunc int scanppl(double rate); +DBCORE_API int scanppl(double rate); /*print event lists*/ -epicsShareFunc int scanpel(const char *event_name); +DBCORE_API int scanpel(const char *event_name); /*print io_event list*/ -epicsShareFunc int scanpiol(void); +DBCORE_API int scanpiol(void); -epicsShareFunc void scanIoInit(IOSCANPVT *ppios); -epicsShareFunc unsigned int scanIoRequest(IOSCANPVT pios); -epicsShareFunc unsigned int scanIoImmediate(IOSCANPVT pios, int prio); -epicsShareFunc void scanIoSetComplete(IOSCANPVT, io_scan_complete, void *usr); +DBCORE_API void scanIoInit(IOSCANPVT *ppios); +DBCORE_API unsigned int scanIoRequest(IOSCANPVT pios); +DBCORE_API unsigned int scanIoImmediate(IOSCANPVT pios, int prio); +DBCORE_API void scanIoSetComplete(IOSCANPVT, io_scan_complete, void *usr); #ifdef __cplusplus } diff --git a/modules/database/src/ioc/db/dbServer.c b/modules/database/src/ioc/db/dbServer.c index bc9263356..d39b345e0 100644 --- a/modules/database/src/ioc/db/dbServer.c +++ b/modules/database/src/ioc/db/dbServer.c @@ -18,7 +18,6 @@ #include "envDefs.h" #include "epicsStdio.h" -#define epicsExportSharedSymbols #include "dbServer.h" static ELLLIST serverList = ELLLIST_INIT; diff --git a/modules/database/src/ioc/db/dbServer.h b/modules/database/src/ioc/db/dbServer.h index 9440fcba0..326166060 100644 --- a/modules/database/src/ioc/db/dbServer.h +++ b/modules/database/src/ioc/db/dbServer.h @@ -28,7 +28,7 @@ #include #include "ellLib.h" -#include "shareLib.h" +#include "dbCoreAPI.h" #ifdef __cplusplus extern "C" { @@ -118,14 +118,14 @@ typedef struct dbServer { * This should only be called once for each server layer. * @param psrv Server information structure for the server */ -epicsShareFunc int dbRegisterServer(dbServer *psrv); +DBCORE_API int dbRegisterServer(dbServer *psrv); /** @brief Unregister a server layer * * This should only be called when the servers are inactive. * @param psrv Server information structure for the server */ -epicsShareFunc int dbUnregisterServer(dbServer *psrv); +DBCORE_API int dbUnregisterServer(dbServer *psrv); /** @brief Print dbServer Reports. * @@ -133,7 +133,7 @@ epicsShareFunc int dbUnregisterServer(dbServer *psrv); * This routine is provided as an IOC Shell command. * @param level Interest level, specifies how much detail to print. */ -epicsShareFunc void dbsr(unsigned level); +DBCORE_API void dbsr(unsigned level); /** @brief Query servers for client's identity. * @@ -143,31 +143,31 @@ epicsShareFunc void dbsr(unsigned level); * of the calling thread is printed along with the record name whenever * the record is subsequently processed. */ -epicsShareFunc int dbServerClient(char *pBuf, size_t bufSize); +DBCORE_API int dbServerClient(char *pBuf, size_t bufSize); /** @brief Initialize all registered servers. * * Calls all dbServer::init() methods. */ -epicsShareFunc void dbInitServers(void); +DBCORE_API void dbInitServers(void); /** @brief Run all registered servers. * * Calls all dbServer::run() methods. */ -epicsShareFunc void dbRunServers(void); +DBCORE_API void dbRunServers(void); /** @brief Pause all registered servers. * * Calls all dbServer::pause() methods. */ -epicsShareFunc void dbPauseServers(void); +DBCORE_API void dbPauseServers(void); /** @brief Stop all registered servers. * * Calls all dbServer::stop() methods. */ -epicsShareFunc void dbStopServers(void); +DBCORE_API void dbStopServers(void); #ifdef __cplusplus } diff --git a/modules/database/src/ioc/db/dbState.c b/modules/database/src/ioc/db/dbState.c index 97ad94cff..f75d9203c 100644 --- a/modules/database/src/ioc/db/dbState.c +++ b/modules/database/src/ioc/db/dbState.c @@ -19,7 +19,6 @@ #include "epicsString.h" #include "iocsh.h" -#define epicsExportSharedSymbols #include "dbDefs.h" #include "dbState.h" #include "dbStaticLib.h" diff --git a/modules/database/src/ioc/db/dbState.h b/modules/database/src/ioc/db/dbState.h index 7a3142167..7e57af68e 100644 --- a/modules/database/src/ioc/db/dbState.h +++ b/modules/database/src/ioc/db/dbState.h @@ -14,7 +14,7 @@ #ifndef INCdbStateH #define INCdbStateH -#include "shareLib.h" +#include "dbCoreAPI.h" #ifdef __cplusplus extern "C" { @@ -45,14 +45,14 @@ typedef struct dbState *dbStateId; * @param name Db state name. * @return Id of db state, NULL for failure. */ -epicsShareFunc dbStateId dbStateCreate(const char *name); +DBCORE_API dbStateId dbStateCreate(const char *name); /** @brief Find db state. * * @param name Db state name. * @return Id of db state, NULL if not found. */ -epicsShareFunc dbStateId dbStateFind(const char *name); +DBCORE_API dbStateId dbStateFind(const char *name); /** @brief Set db state to TRUE. * @@ -60,7 +60,7 @@ epicsShareFunc dbStateId dbStateFind(const char *name); * * @param id Db state id. */ -epicsShareFunc void dbStateSet(dbStateId id); +DBCORE_API void dbStateSet(dbStateId id); /** @brief Set db state to FALSE. * @@ -68,14 +68,14 @@ epicsShareFunc void dbStateSet(dbStateId id); * * @param id Db state id. */ -epicsShareFunc void dbStateClear(dbStateId id); +DBCORE_API void dbStateClear(dbStateId id); /** @brief Get db state. * * @param id Db state id. * @return Current db state (0|1). */ -epicsShareFunc int dbStateGet(dbStateId id); +DBCORE_API int dbStateGet(dbStateId id); /** @brief Print info about db state. * @@ -84,7 +84,7 @@ epicsShareFunc int dbStateGet(dbStateId id); * @param id Db state id. * @param level Interest level. */ -epicsShareFunc void dbStateShow(dbStateId id, unsigned int level); +DBCORE_API void dbStateShow(dbStateId id, unsigned int level); /** @brief Print info about all db states. * @@ -92,7 +92,7 @@ epicsShareFunc void dbStateShow(dbStateId id, unsigned int level); * * @param level Interest level. */ -epicsShareFunc void dbStateShowAll(unsigned int level); +DBCORE_API void dbStateShowAll(unsigned int level); #ifdef __cplusplus diff --git a/modules/database/src/ioc/db/dbSubscriptionIO.cpp b/modules/database/src/ioc/db/dbSubscriptionIO.cpp index b8c0bc51b..674ee1dc6 100644 --- a/modules/database/src/ioc/db/dbSubscriptionIO.cpp +++ b/modules/database/src/ioc/db/dbSubscriptionIO.cpp @@ -27,7 +27,6 @@ #include "cadef.h" // this can be eliminated when the callbacks use the new interface #include "errlog.h" -#define epicsExportSharedSymbols #include "dbCAC.h" #include "dbChannelIO.h" #include "db_access_routines.h" diff --git a/modules/database/src/ioc/db/dbTest.c b/modules/database/src/ioc/db/dbTest.c index 6106027a8..6f5c3eab2 100644 --- a/modules/database/src/ioc/db/dbTest.c +++ b/modules/database/src/ioc/db/dbTest.c @@ -23,7 +23,6 @@ #include "epicsString.h" #include "errlog.h" -#define epicsExportSharedSymbols #include "callback.h" #include "dbAccessDefs.h" #include "dbAddr.h" diff --git a/modules/database/src/ioc/db/dbTest.h b/modules/database/src/ioc/db/dbTest.h index bf891896d..f774b1751 100644 --- a/modules/database/src/ioc/db/dbTest.h +++ b/modules/database/src/ioc/db/dbTest.h @@ -11,42 +11,42 @@ #ifndef INC_dbTest_H #define INC_dbTest_H -#include "shareLib.h" +#include "dbCoreAPI.h" #ifdef __cplusplus extern "C" { #endif /*dbAddr info */ -epicsShareFunc long dba(const char *pname); +DBCORE_API long dba(const char *pname); /*list records*/ -epicsShareFunc long dbl( +DBCORE_API long dbl( const char *precordTypename,const char *fields); /*list number of records of each type*/ -epicsShareFunc long dbnr(int verbose); +DBCORE_API long dbnr(int verbose); /* list aliases */ -epicsShareFunc long dbla(const char *pmask); +DBCORE_API long dbla(const char *pmask); /* list infos */ -epicsShareFunc long dbli(const char *patern); +DBCORE_API long dbli(const char *patern); /*list records with mask*/ -epicsShareFunc long dbgrep(const char *pmask); +DBCORE_API long dbgrep(const char *pmask); /*get field value*/ -epicsShareFunc long dbgf(const char *pname); +DBCORE_API long dbgf(const char *pname); /*put field value*/ -epicsShareFunc long dbpf(const char *pname,const char *pvalue); +DBCORE_API long dbpf(const char *pname,const char *pvalue); /*print record*/ -epicsShareFunc long dbpr(const char *pname,int interest_level); +DBCORE_API long dbpr(const char *pname,int interest_level); /*test record*/ -epicsShareFunc long dbtr(const char *pname); +DBCORE_API long dbtr(const char *pname); /*test get field*/ -epicsShareFunc long dbtgf(const char *pname); +DBCORE_API long dbtgf(const char *pname); /*test put field*/ -epicsShareFunc long dbtpf(const char *pname,const char *pvalue); +DBCORE_API long dbtpf(const char *pname,const char *pvalue); /*I/O report */ -epicsShareFunc long dbior( +DBCORE_API long dbior( const char *pdrvName,int interest_level); /*Hardware Configuration Report*/ -epicsShareFunc int dbhcr(void); +DBCORE_API int dbhcr(void); #ifdef __cplusplus } diff --git a/modules/database/src/ioc/db/dbUnitTest.c b/modules/database/src/ioc/db/dbUnitTest.c index 65c817bbb..a4830a37c 100644 --- a/modules/database/src/ioc/db/dbUnitTest.c +++ b/modules/database/src/ioc/db/dbUnitTest.c @@ -23,7 +23,6 @@ #include "epicsEvent.h" #include "epicsThread.h" -#define epicsExportSharedSymbols #include "dbAccess.h" #include "dbBase.h" #include "dbChannel.h" @@ -112,12 +111,13 @@ union anybuf { long testdbVPutField(const char* pv, short dbrType, va_list ap) { - DBADDR addr; + dbChannel *chan = dbChannelCreate(pv); union anybuf pod; + long ret = S_dbLib_recNotFound; - if (dbNameToAddr(pv, &addr)) { - testFail("Missing PV \"%s\"", pv); - return S_dbLib_recNotFound; + if(!chan || (ret=dbChannelOpen(chan))) { + testFail("Channel error (%p, %ld) : %s", chan, ret, pv); + goto done; } switch(dbrType) { @@ -125,14 +125,18 @@ long testdbVPutField(const char* pv, short dbrType, va_list ap) const char *uarg = va_arg(ap,char*); strncpy(pod.valStr, uarg, sizeof(pod.valStr)); pod.valStr[sizeof(pod.valStr)-1] = '\0'; - return dbPutField(&addr, dbrType, pod.valStr, 1); + ret = dbChannelPutField(chan, dbrType, pod.valStr, 1); + break; } /* The Type parameter takes into consideration * the C language rules for promotion of argument types * in variadic functions. */ -#define OP(DBR,Type,mem) case DBR: {pod.val.mem = va_arg(ap,Type); break;} +#define OP(DBR,Type,mem) case DBR: \ + pod.val.mem = va_arg(ap,Type); \ + ret = dbChannelPutField(chan, dbrType, pod.bytes, 1); \ + break; OP(DBR_CHAR, int, int8); OP(DBR_UCHAR, int, uInt8); OP(DBR_SHORT, int, int16); @@ -147,11 +151,15 @@ long testdbVPutField(const char* pv, short dbrType, va_list ap) #undef OP default: testFail("invalid DBR: dbPutField(\"%s\", %d, ...)", - addr.precord->name, dbrType); - return S_db_badDbrtype; + dbChannelName(chan), dbrType); + ret = S_db_badDbrtype; + break; } - return dbPutField(&addr, dbrType, pod.bytes, 1); +done: + if(chan) + dbChannelDelete(chan); + return ret; } void testdbPutFieldOk(const char* pv, int dbrType, ...) @@ -190,23 +198,35 @@ void testdbGetFieldEqual(const char* pv, int dbrType, ...) void testdbVGetFieldEqual(const char* pv, short dbrType, va_list ap) { - DBADDR addr; + dbChannel *chan = dbChannelCreate(pv); + db_field_log *pfl = NULL; long nReq = 1; union anybuf pod; - long status; + long status = S_dbLib_recNotFound; - if(dbNameToAddr(pv, &addr)) { - testFail("Missing PV \"%s\"", pv); - return; + if(!chan || (status=dbChannelOpen(chan))) { + testFail("Channel error (%p, %ld) : %s", chan, status, pv); + goto done; } - status = dbGetField(&addr, dbrType, pod.bytes, NULL, &nReq, NULL); + if(ellCount(&chan->filters)) { + pfl = db_create_read_log(chan); + if (!pfl) { + testFail("can't db_create_read_log w/ %s", pv); + goto done; + } + + pfl = dbChannelRunPreChain(chan, pfl); + pfl = dbChannelRunPostChain(chan, pfl); + } + + status = dbChannelGetField(chan, dbrType, pod.bytes, NULL, &nReq, pfl); if (status) { testFail("dbGetField(\"%s\", %d, ...) -> %#lx (%s)", pv, dbrType, status, errSymMsg(status)); - return; + goto done; } else if(nReq==0) { testFail("dbGetField(\"%s\", %d, ...) -> zero length", pv, dbrType); - return; + goto done; } switch(dbrType) { @@ -236,35 +256,56 @@ void testdbVGetFieldEqual(const char* pv, short dbrType, va_list ap) default: testFail("dbGetField(\"%s\", %d) -> unsupported dbf", pv, dbrType); } + +done: + db_delete_field_log(pfl); + if(chan) + dbChannelDelete(chan); } void testdbPutArrFieldOk(const char* pv, short dbrType, unsigned long count, const void *pbuf) { - DBADDR addr; + dbChannel *chan = dbChannelCreate(pv); long status; - if (dbNameToAddr(pv, &addr)) { - testFail("Missing PV \"%s\"", pv); - return; + if(!chan || (status=dbChannelOpen(chan))) { + testFail("Channel error (%p, %ld) : %s", chan, status, pv); + goto done; } - status = dbPutField(&addr, dbrType, pbuf, count); + status = dbChannelPutField(chan, dbrType, pbuf, count); testOk(status==0, "dbPutField(\"%s\", dbr=%d, count=%lu, ...) -> %ld", pv, dbrType, count, status); + +done: + if(chan) + dbChannelDelete(chan); } void testdbGetArrFieldEqual(const char* pv, short dbfType, long nRequest, unsigned long cnt, const void *pbufraw) { - DBADDR addr; + dbChannel *chan = dbChannelCreate(pv); + db_field_log *pfl = NULL; const long vSize = dbValueSize(dbfType); const long nStore = vSize * nRequest; - long status; + long status = S_dbLib_recNotFound; char *gbuf, *gstore; const char *pbuf = pbufraw; - if(dbNameToAddr(pv, &addr)) { - testFail("Missing PV \"%s\"", pv); - return; + if(!chan || (status=dbChannelOpen(chan))) { + testFail("Channel error (%p, %ld) : %s", chan, status, pv); + goto done; + } + + if(ellCount(&chan->filters)) { + pfl = db_create_read_log(chan); + if (!pfl) { + testFail("can't db_create_read_log w/ %s", pv); + goto done; + } + + pfl = dbChannelRunPreChain(chan, pfl); + pfl = dbChannelRunPostChain(chan, pfl); } gbuf = gstore = malloc(nStore); @@ -273,7 +314,7 @@ void testdbGetArrFieldEqual(const char* pv, short dbfType, long nRequest, unsign return; } - status = dbGetField(&addr, dbfType, gbuf, NULL, &nRequest, NULL); + status = dbChannelGetField(chan, dbfType, gbuf, NULL, &nRequest, pfl); if (status) { testFail("dbGetField(\"%s\", %d, ...) -> %#lx", pv, dbfType, status); @@ -318,7 +359,10 @@ void testdbGetArrFieldEqual(const char* pv, short dbfType, long nRequest, unsign testOk(match, "dbGetField(\"%s\", dbrType=%d, nRequest=%ld ...) match", pv, dbfType, nRequest); } +done: free(gstore); + if(chan) + dbChannelDelete(chan); } dbCommon* testdbRecordPtr(const char* pv) diff --git a/modules/database/src/ioc/db/dbUnitTest.h b/modules/database/src/ioc/db/dbUnitTest.h index db0c269c2..57ccd0259 100644 --- a/modules/database/src/ioc/db/dbUnitTest.h +++ b/modules/database/src/ioc/db/dbUnitTest.h @@ -6,9 +6,11 @@ * in file LICENSE that is included with this distribution. \*************************************************************************/ -/* - * Author: Michael Davidsaver - * Ralph Lange +/** @file dbUnitTest.h + * @brief Helpers for unitests of process database + * @author Michael Davidsaver, Ralph Lange + * + * @see @ref dbunittest */ #ifndef EPICSUNITTESTDB_H @@ -20,45 +22,95 @@ #include "dbAddr.h" #include "dbCommon.h" -#include "shareLib.h" +#include "dbCoreAPI.h" #ifdef __cplusplus extern "C" { #endif -epicsShareFunc void testdbPrepare(void); -epicsShareFunc void testdbReadDatabase(const char* file, +/** First step in test database setup + * + * @see @ref dbtestskel + */ +DBCORE_API void testdbPrepare(void); +/** Read .dbd or .db file + * + * @see @ref dbtestskel + */ +DBCORE_API void testdbReadDatabase(const char* file, const char* path, const char* substitutions); -epicsShareFunc void testIocInitOk(void); -epicsShareFunc void testIocShutdownOk(void); -epicsShareFunc void testdbCleanup(void); - -/* Correct argument types must be used with this var-arg function! - * Doing otherwise will result in corruption of argument values! +/** Assert success of iocInit() * - * int for DBR_UCHAR, DBR_CHAR, DBR_USHORT, DBR_SHORT, DBR_LONG - * unsigned int for DBR_ULONG - * long long for DBF_INT64 - * unsigned long long for DBF_UINT64 - * double for DBR_FLOAT and DBR_DOUBLE - * const char* for DBR_STRING - * - * eg. - * testdbPutFieldOk("pvname", DBF_ULONG, (unsigned int)5); - * testdbPutFieldOk("pvname", DBF_FLOAT, (double)4.1); - * testdbPutFieldOk("pvname", DBF_STRING, "hello world"); + * @see @ref dbtestskel */ -epicsShareFunc void testdbPutFieldOk(const char* pv, int dbrType, ...); -/* Tests for put failure */ -epicsShareFunc void testdbPutFieldFail(long status, const char* pv, int dbrType, ...); +DBCORE_API void testIocInitOk(void); +/** Shutdown test database processing. + * + * eg. Stops scan threads + * + * @see @ref dbtestskel + */ +DBCORE_API void testIocShutdownOk(void); +/** Final step in test database cleanup + * + * @see @ref dbtestskel + */ +DBCORE_API void testdbCleanup(void); -epicsShareFunc long testdbVPutField(const char* pv, short dbrType, va_list ap); +/** Assert that a dbPutField() scalar operation will complete successfully. + * + * @code + * testdbPutFieldOk("some.TPRO", DBF_LONG, 1); + * @endcode + * + * @see @ref dbtestactions + */ +DBCORE_API void testdbPutFieldOk(const char* pv, int dbrType, ...); -epicsShareFunc void testdbGetFieldEqual(const char* pv, int dbrType, ...); -epicsShareFunc void testdbVGetFieldEqual(const char* pv, short dbrType, va_list ap); +/** Assert that a dbPutField() operation will fail with a certain S_\* code + * + * @see @ref dbtestactions + */ +DBCORE_API void testdbPutFieldFail(long status, const char* pv, int dbrType, ...); -epicsShareFunc void testdbPutArrFieldOk(const char* pv, short dbrType, unsigned long count, const void *pbuf); +/** Assert that a dbPutField() scalar operation will complete successfully. + * + * @see @ref dbtestactions + */ +DBCORE_API long testdbVPutField(const char* pv, short dbrType, va_list ap); + +/** Assert that a dbGetField() scalar operation will complete successfully, with the provided value. + * + * @code + * testdbGetFieldEqual("some.TPRO", DBF_LONG, 0); + * @endcode + * + * @see @ref dbtestactions + */ +DBCORE_API void testdbGetFieldEqual(const char* pv, int dbrType, ...); + +/** Assert that a dbGetField() scalar operation will complete successfully, with the provided value. + * + * @see @ref dbtestactions + */ +DBCORE_API void testdbVGetFieldEqual(const char* pv, short dbrType, va_list ap); + +/** Assert that a dbPutField() array operation will complete successfully. + * + * @param pv a PV name, possibly including filter expression + * @param a DBF_\* type code (cf. dbfType in dbFldTypes.h) + * @param count Number of elements in pbuf array + * @param pbuf Array of values to write + * + * @code + * static const epicsUInt32 putval[] = {1,2,3}; + * testdbVGetFieldEqual("some:wf", DBF_ULONG, NELEMENTS(putval), putval); + * @endcode + * + * @see @ref dbtestactions + */ +DBCORE_API void testdbPutArrFieldOk(const char* pv, short dbrType, unsigned long count, const void *pbuf); /** * @param pv PV name string @@ -75,91 +127,215 @@ epicsShareFunc void testdbPutArrFieldOk(const char* pv, short dbrType, unsigned * nRequest < pbufcnt always fails. * nRequest ==pbufcnt checks prefix (actual may be longer than expected) */ -epicsShareFunc void testdbGetArrFieldEqual(const char* pv, short dbfType, long nRequest, unsigned long pbufcnt, const void *pbuf); +DBCORE_API void testdbGetArrFieldEqual(const char* pv, short dbfType, long nRequest, unsigned long pbufcnt, const void *pbuf); -epicsShareFunc dbCommon* testdbRecordPtr(const char* pv); +/** Obtain pointer to record. + * + * Calls testAbort() on failure. Will never return NULL. + * + * @note Remember to dbScanLock() when accessing mutable fields. + */ +DBCORE_API dbCommon* testdbRecordPtr(const char* pv); typedef struct testMonitor testMonitor; -/* Begin monitoring the named PV for changes */ -epicsShareFunc testMonitor* testMonitorCreate(const char* pvname, unsigned dbe_mask, unsigned opt); -/* End monitoring */ -epicsShareFunc void testMonitorDestroy(testMonitor*); -/* Return immediately if it has been updated since create, last wait, +/** Setup monitoring the named PV for changes */ +DBCORE_API testMonitor* testMonitorCreate(const char* pvname, unsigned dbe_mask, unsigned opt); +/** Stop monitoring */ +DBCORE_API void testMonitorDestroy(testMonitor*); +/** Return immediately if it has been updated since create, last wait, * or reset (count w/ reset=1). * Otherwise, block until the value of the target PV is updated. */ -epicsShareFunc void testMonitorWait(testMonitor*); -/* Return the number of monitor events which have occured since create, +DBCORE_API void testMonitorWait(testMonitor*); +/** Return the number of monitor events which have occured since create, * or a pervious reset (called reset=1). * Calling w/ reset=0 only returns the count. * Calling w/ reset=1 resets the count to zero and ensures that the next * wait will block unless subsequent events occur. Returns the previous * count. */ -epicsShareFunc unsigned testMonitorCount(testMonitor*, unsigned reset); +DBCORE_API unsigned testMonitorCount(testMonitor*, unsigned reset); /** Synchronize the shared callback queues. * * Block until all callback queue jobs which were queued, or running, * have completed. */ -epicsShareFunc void testSyncCallback(void); +DBCORE_API void testSyncCallback(void); -/** Global mutex for use by test code. +/** Lock Global convenience mutex for use by test code. * - * This utility mutex is intended to be used to avoid races in situations - * where some other syncronization primitive is being destroyed (epicsEvent, - * epicsMutex, ...). - * - * For example. The following has a subtle race where the event may be - * destroyed (free()'d) before the call to epicsEventMustSignal() has - * returned. On some targets this leads to a use after free() error. - * - @code - epicsEventId evt; - void thread1() { - evt = epicsEventMustCreate(...); - // spawn thread2() - epicsEventMustWait(evt); - epicsEventDestroy(evt); - } - // ... - void thread2() { - epicsEventMustSignal(evt); - } - @endcode - * - * One way to avoid this race is to use a global mutex to ensure - * that epicsEventMustSignal() has returned before destroying - * the event. - * - @code - epicsEventId evt; - void thread1() { - evt = epicsEventMustCreate(...); - // spawn thread2() - epicsEventMustWait(evt); - testGlobalLock(); // <-- added - epicsEventDestroy(evt); - testGlobalUnlock(); // <-- added - } - // ... - void thread2() { - testGlobalLock(); // <-- added - epicsEventMustSignal(evt); - testGlobalUnlock(); // <-- added - } - @endcode - * - * This must be a global mutex to avoid simply shifting the race - * from the event to a locally allocated mutex. + * @see @ref dbtestmutex */ -epicsShareFunc void testGlobalLock(void); -epicsShareFunc void testGlobalUnlock(void); +DBCORE_API void testGlobalLock(void); + +/** Unlock Global convenience mutex for use by test code. + * + * @see @ref dbtestmutex + */ +DBCORE_API void testGlobalUnlock(void); #ifdef __cplusplus } #endif +/** @page dbunittest Unit testing of record processing + * + * @see @ref epicsUnitTest.h + * + * @section dbtestskel Test skeleton + * + * For the impatient, the skeleton of a test: + * + * @code + * #include + * + * int mytest_registerRecordDeviceDriver(DBBASE *pbase); + * void testCase(void) { + * testdbPrepare(); + * testdbReadDatabase("mytest.dbd", 0, 0); + * mytest_registerRecordDeviceDriver(pdbbase); + * testdbReadDatabase("some.db", 0, "VAR=value"); + * testIocInitOk(); + * // database running ... + * testIocShutdownOk(); + * testdbCleanup(); + * } + * + * MAIN(mytestmain) { + * testPlan(0); + * testCase(); + * testCase(); // may be repeated if desirable. + * return testDone(); + * } + * @endcode + * + * @code + * TARGETS += $(COMMON_DIR)/mytest.dbd + * DBDDEPENDS_FILES += mytest.dbd$(DEP) + * TESTFILES += $(COMMON_DIR)/mytest.dbd + * mytest_DBD += base.dbd + * mytest_DBD += someother.dbd + * + * TESTPROD_HOST += mytest + * mytest_SRCS += mytestmain.c # see above + * mytest_SRCS += mytest_registerRecordDeviceDriver.cpp + * TESTFILES += some.db + * @endcode + * + * @section dbtestactions Actions + * + * Several helper functions are provided to interact with a running database. + * + * @li testdbPutFieldOk() + * @li testdbPutFieldFail() + * @li testdbPutArrFieldOk() + * @li testdbVPutField() + * @li testdbGetFieldEqual() + * @li testdbVGetFieldEqual() + * + * Correct argument types must be used with var-arg functions. + * + * @li int for DBR_UCHAR, DBR_CHAR, DBR_USHORT, DBR_SHORT, DBR_LONG + * @li unsigned int for DBR_ULONG + * @li long long for DBF_INT64 + * @li unsigned long long for DBF_UINT64 + * @li double for DBR_FLOAT and DBR_DOUBLE + * @li const char* for DBR_STRING + * + * @see enum dbfType in dbFldTypes.h + * + * @code + * testdbPutFieldOk("pvname", DBF_ULONG, (unsigned int)5); + * testdbPutFieldOk("pvname", DBF_FLOAT, (double)4.1); + * testdbPutFieldOk("pvname", DBF_STRING, "hello world"); + * @endcode + * + * @section dbtestmonitor Monitoring for changes + * + * When Put and Get aren't sufficient, testMonitor may help to setup and monitor for changes. + * + * @li testMonitorCreate() + * @li testMonitorDestroy() + * @li testMonitorWait() + * @li testMonitorCount() + * + * @section dbtestsync Synchronizing + * + * Helpers to synchronize with some database worker threads + * + * @li testSyncCallback() + * + * @section dbtestmutex Global mutex for use by test code. + * + * This utility mutex is intended to be used to avoid races in situations + * where some other synchronization primitive is being destroyed (epicsEvent, + * epicsMutex, ...) and use of epicsThreadMustJoin() is impractical. + * + * For example. The following has a subtle race where the event may be + * destroyed (free()'d) before the call to epicsEventMustSignal() has + * returned. On some targets this leads to a use after free() error. + * + * @code + * epicsEventId evt; + * void thread1() { + * evt = epicsEventMustCreate(...); + * // spawn thread2() + * epicsEventMustWait(evt); + * epicsEventDestroy(evt); // <- Racer + * } + * // ... + * void thread2() { + * epicsEventMustSignal(evt); // <- Racer + * } + * @endcode + * + * When possible, the best way to avoid this race would be to join the worker + * before destroying the event. + * + * @code + * epicsEventId evt; + * void thread1() { + * epicsThreadOpts opts = EPICS_THREAD_OPTS_INIT; + * epicsThreadId t2; + * opts.joinable = 1; + * evt = epicsEventMustCreate(...); + * t2 = epicsThreadCreateOpt("thread2", &thread2, NULL, &opts); + * assert(t2); + * epicsEventMustWait(evt); + * epicsThreadMustJoin(t2); + * epicsEventDestroy(evt); + * } + * void thread2() { + * epicsEventMustSignal(evt); + * } + * @endcode + * + * Another way to avoid this race is to use a global mutex to ensure + * that epicsEventMustSignal() has returned before destroying the event. + * testGlobalLock() and testGlobalUnlock() provide access to such a mutex. + * + * @code + * epicsEventId evt; + * void thread1() { + * evt = epicsEventMustCreate(...); + * // spawn thread2() + * epicsEventMustWait(evt); + * testGlobalLock(); // <-- added + * epicsEventDestroy(evt); + * testGlobalUnlock(); // <-- added + * } + * // ... + * void thread2() { + * testGlobalLock(); // <-- added + * epicsEventMustSignal(evt); + * testGlobalUnlock(); // <-- added + * } + * @endcode + * + * This must be a global mutex to avoid simply shifting the race + * from the event to a locally allocated mutex. + */ + #endif // EPICSUNITTESTDB_H diff --git a/modules/database/src/ioc/db/db_access.c b/modules/database/src/ioc/db/db_access.c index f508de16a..0943315cf 100644 --- a/modules/database/src/ioc/db/db_access.c +++ b/modules/database/src/ioc/db/db_access.c @@ -33,7 +33,6 @@ #include "db_access.h" #undef db_accessHFORdb_accessC -#define epicsExportSharedSymbols #include "dbAccessDefs.h" #include "db_access_routines.h" #include "dbBase.h" diff --git a/modules/database/src/ioc/db/db_access_routines.h b/modules/database/src/ioc/db/db_access_routines.h index d8cef602d..cd8b09c40 100644 --- a/modules/database/src/ioc/db/db_access_routines.h +++ b/modules/database/src/ioc/db/db_access_routines.h @@ -20,21 +20,21 @@ extern "C" { #endif -#include "shareLib.h" +#include "dbCoreAPI.h" -epicsShareExtern struct dbBase *pdbbase; -epicsShareExtern volatile int interruptAccept; +DBCORE_API extern struct dbBase *pdbbase; +DBCORE_API extern volatile int interruptAccept; /* * Adaptors for db_access users */ -epicsShareFunc struct dbChannel * dbChannel_create(const char *pname); -epicsShareFunc int dbChannel_get(struct dbChannel *chan, +DBCORE_API struct dbChannel * dbChannel_create(const char *pname); +DBCORE_API int dbChannel_get(struct dbChannel *chan, int buffer_type, void *pbuffer, long no_elements, void *pfl); -epicsShareFunc int dbChannel_put(struct dbChannel *chan, int src_type, +DBCORE_API int dbChannel_put(struct dbChannel *chan, int src_type, const void *psrc, long no_elements); -epicsShareFunc int dbChannel_get_count(struct dbChannel *chan, +DBCORE_API int dbChannel_get_count(struct dbChannel *chan, int buffer_type, void *pbuffer, long *nRequest, void *pfl); diff --git a/modules/database/src/ioc/db/db_convert.h b/modules/database/src/ioc/db/db_convert.h index 892377c7a..9ee907571 100644 --- a/modules/database/src/ioc/db/db_convert.h +++ b/modules/database/src/ioc/db/db_convert.h @@ -16,29 +16,29 @@ extern "C" { #endif -#include "shareLib.h" +#include "dbCoreAPI.h" #include "dbAddr.h" -epicsShareExtern struct dbBase *pdbbase; -epicsShareExtern volatile int interruptAccept; +DBCORE_API extern struct dbBase *pdbbase; +DBCORE_API extern volatile int interruptAccept; /*Definitions that allow old database access to use new conversion routines*/ #define newDBF_DEVICE 13 #define newDBR_ENUM 11 -epicsShareExtern long (*dbGetConvertRoutine[newDBF_DEVICE+1][newDBR_ENUM+1]) +DBCORE_API extern long (*dbGetConvertRoutine[newDBF_DEVICE+1][newDBR_ENUM+1]) (struct dbAddr *paddr, void *pbuffer,long nRequest, long no_elements, long offset); -epicsShareExtern long (*dbPutConvertRoutine[newDBR_ENUM+1][newDBF_DEVICE+1]) +DBCORE_API extern long (*dbPutConvertRoutine[newDBR_ENUM+1][newDBF_DEVICE+1]) (struct dbAddr *paddr, const void *pbuffer,long nRequest, long no_elements, long offset); -epicsShareExtern long (*dbFastGetConvertRoutine[newDBF_DEVICE+1][newDBR_ENUM+1]) +DBCORE_API extern long (*dbFastGetConvertRoutine[newDBF_DEVICE+1][newDBR_ENUM+1]) (const void *from, void *to, dbAddr *paddr); -epicsShareExtern long (*dbFastPutConvertRoutine[newDBR_ENUM+1][newDBF_DEVICE+1]) +DBCORE_API extern long (*dbFastPutConvertRoutine[newDBR_ENUM+1][newDBF_DEVICE+1]) (const void *from, void *to, dbAddr *paddr); /*Conversion between old and new DBR types*/ -epicsShareExtern unsigned short dbDBRoldToDBFnew[DBR_DOUBLE+1]; -epicsShareExtern unsigned short dbDBRnewToDBRold[newDBR_ENUM+1]; +DBCORE_API extern unsigned short dbDBRoldToDBFnew[DBR_DOUBLE+1]; +DBCORE_API extern unsigned short dbDBRnewToDBRold[newDBR_ENUM+1]; #ifdef DB_CONVERT_GBLSOURCE unsigned short dbDBRoldToDBFnew[DBR_DOUBLE+1] = { 0, /*DBR_STRING to DBF_STRING*/ diff --git a/modules/database/src/ioc/db/db_field_log.h b/modules/database/src/ioc/db/db_field_log.h index e517d529f..b9deb6fe9 100644 --- a/modules/database/src/ioc/db/db_field_log.h +++ b/modules/database/src/ioc/db/db_field_log.h @@ -109,10 +109,14 @@ typedef struct db_field_log { unsigned int type:1; /* type (union) selector */ /* ctx is used for all types */ unsigned int ctx:1; /* context (operation type) */ + /* only for dbfl_context_event */ + unsigned char mask; /* DBE_* mask */ /* the following are used for value and reference types */ epicsTimeStamp time; /* Time stamp */ + epicsUTag utag; unsigned short stat; /* Alarm Status */ unsigned short sevr; /* Alarm Severity */ + char amsg[40]; short field_type; /* DBF type of data */ short field_size; /* Size of a single element */ long no_elements; /* No of valid array elements */ diff --git a/modules/database/src/ioc/db/db_test.c b/modules/database/src/ioc/db/db_test.c index bca0a1d5a..30ef0cfb3 100644 --- a/modules/database/src/ioc/db/db_test.c +++ b/modules/database/src/ioc/db/db_test.c @@ -24,7 +24,6 @@ #include "errlog.h" #include "epicsEvent.h" -#define epicsExportSharedSymbols #include "db_access_routines.h" #include "dbChannel.h" #include "dbCommon.h" diff --git a/modules/database/src/ioc/db/db_test.h b/modules/database/src/ioc/db/db_test.h index c20744b19..7dcdad1a9 100644 --- a/modules/database/src/ioc/db/db_test.h +++ b/modules/database/src/ioc/db/db_test.h @@ -11,15 +11,15 @@ #ifndef INCLdb_testh #define INCLdb_testh -#include "shareLib.h" +#include "dbCoreAPI.h" #ifdef __cplusplus extern "C" { #endif -epicsShareFunc int gft(const char *pname); -epicsShareFunc int pft(const char *pname, const char *pvalue); -epicsShareFunc int tpn(const char *pname, const char *pvalue); +DBCORE_API int gft(const char *pname); +DBCORE_API int pft(const char *pname, const char *pvalue); +DBCORE_API int tpn(const char *pname, const char *pvalue); #ifdef __cplusplus } #endif diff --git a/modules/database/src/ioc/db/recGbl.c b/modules/database/src/ioc/db/recGbl.c index 5d383f45e..9f5b90479 100644 --- a/modules/database/src/ioc/db/recGbl.c +++ b/modules/database/src/ioc/db/recGbl.c @@ -24,12 +24,12 @@ #include "epicsMath.h" #include "epicsPrint.h" #include "epicsStdlib.h" +#include "epicsStdio.h" #include "epicsTime.h" #include "errlog.h" #include "caeventmask.h" -#define epicsExportSharedSymbols #include "dbAccessDefs.h" #include "dbStaticLib.h" #include "dbAddr.h" @@ -185,6 +185,11 @@ unsigned short recGblResetAlarms(void *precord) if (new_sevr > INVALID_ALARM) new_sevr = INVALID_ALARM; + if(strcmp(pdbc->namsg, pdbc->amsg)!=0) { + strcpy(pdbc->amsg, pdbc->namsg); + stat_mask = DBE_ALARM; + } + pdbc->stat = new_stat; pdbc->sevr = new_sevr; pdbc->nsta = 0; @@ -199,6 +204,7 @@ unsigned short recGblResetAlarms(void *precord) } if (stat_mask) { db_post_events(pdbc, &pdbc->stat, stat_mask); + db_post_events(pdbc, &pdbc->amsg, stat_mask); val_mask = DBE_ALARM; if (!pdbc->ackt || new_sevr >= pdbc->acks) { @@ -212,18 +218,44 @@ unsigned short recGblResetAlarms(void *precord) } return val_mask; } +int recGblSetSevrMsg(void *precord, epicsEnum16 new_stat, + epicsEnum16 new_sevr, + const char *msg, ...) +{ + int ret; + va_list args; + va_start(args, msg); + ret = recGblSetSevrVMsg(precord, new_stat, new_sevr, msg, args); + va_end(args); + return ret; +} -int recGblSetSevr(void *precord, epicsEnum16 new_stat, epicsEnum16 new_sevr) +int recGblSetSevrVMsg(void *precord, epicsEnum16 new_stat, + epicsEnum16 new_sevr, + const char *msg, va_list args) { struct dbCommon *prec = precord; if (prec->nsev < new_sevr) { prec->nsta = new_stat; prec->nsev = new_sevr; + if(msg) { + epicsVsnprintf(prec->namsg, sizeof(prec->namsg)-1, msg, args); + prec->namsg[sizeof(prec->namsg)-1] = '\0'; + + } else { + prec->namsg[0] = '\0'; + } + prec->namsg[sizeof(prec->namsg)-1] = '\0'; return TRUE; } return FALSE; } +int recGblSetSevr(void *precord, epicsEnum16 new_stat, epicsEnum16 new_sevr) +{ + return recGblSetSevrMsg(precord, new_stat, new_sevr, NULL); +} + void recGblInheritSevr(int msMode, void *precord, epicsEnum16 stat, epicsEnum16 sevr) { @@ -272,7 +304,7 @@ void recGblGetTimeStampSimm(void *pvoid, const epicsEnum16 simm, struct link *si if (!dbLinkIsConstant(plink)) { if (plink->flags & DBLINK_FLAG_TSELisTIME) { - if (dbGetTimeStamp(plink, &prec->time)) + if (dbGetTimeStampTag(plink, &prec->time, &prec->utag)) errlogPrintf("recGblGetTimeStamp: dbGetTimeStamp failed for %s.TSEL\n", prec->name); return; diff --git a/modules/database/src/ioc/db/recGbl.h b/modules/database/src/ioc/db/recGbl.h index b0b2ed020..269777ec6 100644 --- a/modules/database/src/ioc/db/recGbl.h +++ b/modules/database/src/ioc/db/recGbl.h @@ -15,13 +15,24 @@ #ifndef INCrecGblh #define INCrecGblh 1 +#include + +#include "compilerDependencies.h" #include "epicsTypes.h" -#include "shareLib.h" +#include "dbCoreAPI.h" #ifdef __cplusplus extern "C" { #endif +/** Feature test macro for alarm message (AMSG) field and support + * + * Covers addition of dbCommon::amsg, recGblSetSevrMsg(), lset::getAlarmMsg() + * + * @since UNRELEASED + */ +#define HAS_ALARM_MESSAGE 1 + /*************************************************************************/ /* Structures needed for args */ @@ -37,43 +48,49 @@ struct dbCommon; typedef void (*RECGBL_ALARM_HOOK_ROUTINE)(struct dbCommon *prec, epicsEnum16 prev_sevr, epicsEnum16 prev_stat); -epicsShareExtern RECGBL_ALARM_HOOK_ROUTINE recGblAlarmHook; +DBCORE_API extern RECGBL_ALARM_HOOK_ROUTINE recGblAlarmHook; /* Global Record Support Routines */ -epicsShareFunc void recGblDbaddrError(long status, const struct dbAddr *paddr, +DBCORE_API void recGblDbaddrError(long status, const struct dbAddr *paddr, const char *pcaller_name); -epicsShareFunc void recGblRecordError(long status, void *precord, +DBCORE_API void recGblRecordError(long status, void *precord, const char *pcaller_name); -epicsShareFunc void recGblRecSupError(long status, const struct dbAddr *paddr, +DBCORE_API void recGblRecSupError(long status, const struct dbAddr *paddr, const char *pcaller_name, const char *psupport_name); -epicsShareFunc void recGblGetGraphicDouble(const struct dbAddr *paddr, +DBCORE_API void recGblGetGraphicDouble(const struct dbAddr *paddr, struct dbr_grDouble *pgd); -epicsShareFunc void recGblGetControlDouble( +DBCORE_API void recGblGetControlDouble( const struct dbAddr *paddr, struct dbr_ctrlDouble *pcd); -epicsShareFunc void recGblGetAlarmDouble(const struct dbAddr *paddr, +DBCORE_API void recGblGetAlarmDouble(const struct dbAddr *paddr, struct dbr_alDouble *pad); -epicsShareFunc void recGblGetPrec(const struct dbAddr *paddr, +DBCORE_API void recGblGetPrec(const struct dbAddr *paddr, long *pprecision); -epicsShareFunc int recGblInitConstantLink(struct link *plink, +DBCORE_API int recGblInitConstantLink(struct link *plink, short dbftype, void *pdest); -epicsShareFunc unsigned short recGblResetAlarms(void *precord); -epicsShareFunc int recGblSetSevr(void *precord, epicsEnum16 new_stat, +DBCORE_API unsigned short recGblResetAlarms(void *precord); +DBCORE_API int recGblSetSevr(void *precord, epicsEnum16 new_stat, epicsEnum16 new_sevr); -epicsShareFunc void recGblInheritSevr(int msMode, void *precord, epicsEnum16 stat, +DBCORE_API void recGblInheritSevr(int msMode, void *precord, epicsEnum16 stat, epicsEnum16 sevr); -epicsShareFunc void recGblFwdLink(void *precord); -epicsShareFunc void recGblGetTimeStamp(void *precord); -epicsShareFunc void recGblGetTimeStampSimm(void *prec, const epicsEnum16 simm, struct link *siol); -epicsShareFunc void recGblCheckDeadband(epicsFloat64 *poldval, const epicsFloat64 newval, +DBCORE_API int recGblSetSevrMsg(void *precord, epicsEnum16 new_stat, + epicsEnum16 new_sevr, + const char *msg, ...) EPICS_PRINTF_STYLE(4,5); +DBCORE_API int recGblSetSevrVMsg(void *precord, epicsEnum16 new_stat, + epicsEnum16 new_sevr, + const char *msg, va_list args); +DBCORE_API void recGblFwdLink(void *precord); +DBCORE_API void recGblGetTimeStamp(void *precord); +DBCORE_API void recGblGetTimeStampSimm(void *prec, const epicsEnum16 simm, struct link *siol); +DBCORE_API void recGblCheckDeadband(epicsFloat64 *poldval, const epicsFloat64 newval, const epicsFloat64 deadband, unsigned *monitor_mask, const unsigned add_mask); -epicsShareFunc void recGblSaveSimm(const epicsEnum16 sscn, +DBCORE_API void recGblSaveSimm(const epicsEnum16 sscn, epicsEnum16 *poldsimm, const epicsEnum16 simm); -epicsShareFunc void recGblCheckSimm(struct dbCommon *prec, epicsEnum16 *psscn, +DBCORE_API void recGblCheckSimm(struct dbCommon *prec, epicsEnum16 *psscn, const epicsEnum16 oldsimm, const epicsEnum16 simm); -epicsShareFunc void recGblInitSimm(struct dbCommon *prec, epicsEnum16 *psscn, +DBCORE_API void recGblInitSimm(struct dbCommon *prec, epicsEnum16 *psscn, epicsEnum16 *poldsimm, epicsEnum16 *psimm, struct link *psiml); -epicsShareFunc long recGblGetSimm(struct dbCommon *prec, epicsEnum16 *psscn, +DBCORE_API long recGblGetSimm(struct dbCommon *prec, epicsEnum16 *psscn, epicsEnum16 *poldsimm, epicsEnum16 *psimm, struct link *psiml); #ifdef __cplusplus diff --git a/modules/database/src/ioc/dbStatic/dbFldTypes.h b/modules/database/src/ioc/dbStatic/dbFldTypes.h index b7997d7b0..ee48eaeb9 100644 --- a/modules/database/src/ioc/dbStatic/dbFldTypes.h +++ b/modules/database/src/ioc/dbStatic/dbFldTypes.h @@ -14,7 +14,7 @@ #ifndef INCdbFldTypesh #define INCdbFldTypesh 1 -#include "shareLib.h" +#include "dbCoreAPI.h" #ifdef __cplusplus extern "C" { @@ -48,7 +48,7 @@ typedef struct mapdbfType{ dbfType value; }mapdbfType; -epicsShareExtern mapdbfType pamapdbfType[]; +DBCORE_API extern mapdbfType pamapdbfType[]; #ifdef DBFLDTYPES_GBLSOURCE mapdbfType pamapdbfType[DBF_NTYPES] = { {"DBF_STRING",DBF_STRING}, diff --git a/modules/database/src/ioc/dbStatic/dbLexRoutines.c b/modules/database/src/ioc/dbStatic/dbLexRoutines.c index 787ce29d8..525846186 100644 --- a/modules/database/src/ioc/dbStatic/dbLexRoutines.c +++ b/modules/database/src/ioc/dbStatic/dbLexRoutines.c @@ -28,7 +28,6 @@ #include "gpHash.h" #include "macLib.h" -#define epicsExportSharedSymbols #include "dbBase.h" #include "dbFldTypes.h" #include "dbStaticLib.h" diff --git a/modules/database/src/ioc/dbStatic/dbPvdLib.c b/modules/database/src/ioc/dbStatic/dbPvdLib.c index 6728b64e3..9110c6041 100644 --- a/modules/database/src/ioc/dbStatic/dbPvdLib.c +++ b/modules/database/src/ioc/dbStatic/dbPvdLib.c @@ -21,7 +21,6 @@ #include "epicsStdio.h" #include "epicsString.h" -#define epicsExportSharedSymbols #include "dbBase.h" #include "dbStaticLib.h" #include "dbStaticPvt.h" diff --git a/modules/database/src/ioc/dbStatic/dbStaticIocRegister.c b/modules/database/src/ioc/dbStatic/dbStaticIocRegister.c index 1a1960636..6851d41fc 100644 --- a/modules/database/src/ioc/dbStatic/dbStaticIocRegister.c +++ b/modules/database/src/ioc/dbStatic/dbStaticIocRegister.c @@ -10,7 +10,6 @@ #include "iocsh.h" -#define epicsExportSharedSymbols #include "dbStaticIocRegister.h" #include "dbStaticLib.h" #include "dbStaticPvt.h" @@ -34,8 +33,10 @@ static void dbDumpPathCallFunc(const iocshArgBuf *args) static const iocshArg dbDumpRecordArg2 = { "interest level",iocshArgInt}; static const iocshArg * const dbDumpRecordArgs[] = {&argPdbbase, &argRecType, &dbDumpRecordArg2}; -static const iocshFuncDef dbDumpRecordFuncDef = - {"dbDumpRecord",3,dbDumpRecordArgs}; +static const iocshFuncDef dbDumpRecordFuncDef = {"dbDumpRecord",3,dbDumpRecordArgs, + "Dump information about the recordTypeName with 'interest level' details.\n" + "Example: dbDumpRecord ai 2\n" + "If last argument(s) are missing, dump all recordType information in the database.\n"}; static void dbDumpRecordCallFunc(const iocshArgBuf *args) { dbDumpRecord(*iocshPpdbbase,args[1].sval,args[2].ival); @@ -45,7 +46,10 @@ static void dbDumpRecordCallFunc(const iocshArgBuf *args) static const iocshArg dbDumpMenuArg1 = { "menuName",iocshArgString}; static const iocshArg * const dbDumpMenuArgs[] = { &argPdbbase, &dbDumpMenuArg1}; -static const iocshFuncDef dbDumpMenuFuncDef = {"dbDumpMenu",2,dbDumpMenuArgs}; +static const iocshFuncDef dbDumpMenuFuncDef = {"dbDumpMenu",2,dbDumpMenuArgs, + "Dump information about the available menuNames and choices defined withing each menuName.\n" + "Example: dbDumpMenu pdbbase menuAlarmStat \n" + "If last argument(s) are missing, dump all menuNames information in the database.\n"}; static void dbDumpMenuCallFunc(const iocshArgBuf *args) { dbDumpMenu(*iocshPpdbbase,args[1].sval); @@ -54,8 +58,10 @@ static void dbDumpMenuCallFunc(const iocshArgBuf *args) /* dbDumpRecordType */ static const iocshArg * const dbDumpRecordTypeArgs[] = {&argPdbbase, &argRecType}; -static const iocshFuncDef dbDumpRecordTypeFuncDef = - {"dbDumpRecordType",2,dbDumpRecordTypeArgs}; +static const iocshFuncDef dbDumpRecordTypeFuncDef = {"dbDumpRecordType",2,dbDumpRecordTypeArgs, + "Dump information about available fields in the recortTypeName sorted by index and name.\n" + "Example: dbDumpRecordType pdbbase calcout\n" + "If last argument(s) are missing, dump fields information for all records in the database.\n"}; static void dbDumpRecordTypeCallFunc(const iocshArgBuf *args) { dbDumpRecordType(*iocshPpdbbase,args[1].sval); @@ -65,7 +71,11 @@ static void dbDumpRecordTypeCallFunc(const iocshArgBuf *args) static const iocshArg dbDumpFieldArg2 = { "fieldName",iocshArgString}; static const iocshArg * const dbDumpFieldArgs[] = {&argPdbbase, &argRecType,&dbDumpFieldArg2}; -static const iocshFuncDef dbDumpFieldFuncDef = {"dbDumpField",3,dbDumpFieldArgs}; +static const iocshFuncDef dbDumpFieldFuncDef = {"dbDumpField",3,dbDumpFieldArgs, + "Dump information about the fieldName in the recordTypeName.\n" + "Example: dbDumpField pdbbase calcout A\n" + "If last argument(s) are missing, dump information\n" + "about all fieldName in all recordTypeName in the database.\n"}; static void dbDumpFieldCallFunc(const iocshArgBuf *args) { dbDumpField(*iocshPpdbbase,args[1].sval,args[2].sval); @@ -74,7 +84,11 @@ static void dbDumpFieldCallFunc(const iocshArgBuf *args) /* dbDumpDevice */ static const iocshArg * const dbDumpDeviceArgs[] = { &argPdbbase, &argRecType}; -static const iocshFuncDef dbDumpDeviceFuncDef = {"dbDumpDevice",2,dbDumpDeviceArgs}; +static const iocshFuncDef dbDumpDeviceFuncDef = {"dbDumpDevice",2,dbDumpDeviceArgs, + "Dump device support information for the recordTypeName.\n" + "Example: dbDumpDevice pdbbase ai\n" + "If last argument(s) are missing, dump device support\n" + "information for all records in the database.\n"}; static void dbDumpDeviceCallFunc(const iocshArgBuf *args) { dbDumpDevice(*iocshPpdbbase,args[1].sval); @@ -82,7 +96,9 @@ static void dbDumpDeviceCallFunc(const iocshArgBuf *args) /* dbDumpDriver */ static const iocshArg * const dbDumpDriverArgs[] = { &argPdbbase}; -static const iocshFuncDef dbDumpDriverFuncDef = {"dbDumpDriver",1,dbDumpDriverArgs}; +static const iocshFuncDef dbDumpDriverFuncDef = {"dbDumpDriver",1,dbDumpDriverArgs, + "Dump device support information.\n" + "Example: dbDumpDriver pdbbase\n"}; static void dbDumpDriverCallFunc(const iocshArgBuf *args) { dbDumpDriver(*iocshPpdbbase); @@ -98,7 +114,10 @@ static void dbDumpLinkCallFunc(const iocshArgBuf *args) /* dbDumpRegistrar */ static const iocshArg * const dbDumpRegistrarArgs[] = { &argPdbbase}; -static const iocshFuncDef dbDumpRegistrarFuncDef = {"dbDumpRegistrar",1,dbDumpRegistrarArgs}; +static const iocshFuncDef dbDumpRegistrarFuncDef = {"dbDumpRegistrar",1,dbDumpRegistrarArgs, + "Dump list of registered functions including ones for subroutine records,\n" + "and ones that can be invoked from iocsh.\n" + "Example: dbDumpRegistrar pdbbase\n"}; static void dbDumpRegistrarCallFunc(const iocshArgBuf *args) { dbDumpRegistrar(*iocshPpdbbase); @@ -106,7 +125,9 @@ static void dbDumpRegistrarCallFunc(const iocshArgBuf *args) /* dbDumpFunction */ static const iocshArg * const dbDumpFunctionArgs[] = { &argPdbbase}; -static const iocshFuncDef dbDumpFunctionFuncDef = {"dbDumpFunction",1,dbDumpFunctionArgs}; +static const iocshFuncDef dbDumpFunctionFuncDef = {"dbDumpFunction",1,dbDumpFunctionArgs, + "Dump list of registered subroutine functions.\n" + "Example: dbDumpFunction pddbase\n"}; static void dbDumpFunctionCallFunc(const iocshArgBuf *args) { dbDumpFunction(*iocshPpdbbase); @@ -114,7 +135,9 @@ static void dbDumpFunctionCallFunc(const iocshArgBuf *args) /* dbDumpVariable */ static const iocshArg * const dbDumpVariableArgs[] = { &argPdbbase}; -static const iocshFuncDef dbDumpVariableFuncDef = {"dbDumpVariable",1,dbDumpVariableArgs}; +static const iocshFuncDef dbDumpVariableFuncDef = {"dbDumpVariable",1,dbDumpVariableArgs, + "Dump list of variables used in the database.\n" + "Example: dbDumpVariable pddbase\n"}; static void dbDumpVariableCallFunc(const iocshArgBuf *args) { dbDumpVariable(*iocshPpdbbase); @@ -124,8 +147,7 @@ static void dbDumpVariableCallFunc(const iocshArgBuf *args) static const iocshArg dbDumpBreaktableArg1 = { "tableName",iocshArgString}; static const iocshArg * const dbDumpBreaktableArgs[] = {&argPdbbase,&dbDumpBreaktableArg1}; -static const iocshFuncDef dbDumpBreaktableFuncDef = - {"dbDumpBreaktable",2,dbDumpBreaktableArgs}; +static const iocshFuncDef dbDumpBreaktableFuncDef = {"dbDumpBreaktable",2,dbDumpBreaktableArgs}; static void dbDumpBreaktableCallFunc(const iocshArgBuf *args) { dbDumpBreaktable(*iocshPpdbbase,args[1].sval); @@ -145,8 +167,7 @@ static void dbPvdDumpCallFunc(const iocshArgBuf *args) static const iocshArg dbPvdTableSizeArg0 = { "size",iocshArgInt}; static const iocshArg * const dbPvdTableSizeArgs[1] = {&dbPvdTableSizeArg0}; -static const iocshFuncDef dbPvdTableSizeFuncDef = - {"dbPvdTableSize",1,dbPvdTableSizeArgs}; +static const iocshFuncDef dbPvdTableSizeFuncDef = {"dbPvdTableSize",1,dbPvdTableSizeArgs}; static void dbPvdTableSizeCallFunc(const iocshArgBuf *args) { dbPvdTableSize(args[0].ival); @@ -154,8 +175,7 @@ static void dbPvdTableSizeCallFunc(const iocshArgBuf *args) /* dbReportDeviceConfig */ static const iocshArg * const dbReportDeviceConfigArgs[] = {&argPdbbase}; -static const iocshFuncDef dbReportDeviceConfigFuncDef = { - "dbReportDeviceConfig",1,dbReportDeviceConfigArgs}; +static const iocshFuncDef dbReportDeviceConfigFuncDef = {"dbReportDeviceConfig",1,dbReportDeviceConfigArgs}; static void dbReportDeviceConfigCallFunc(const iocshArgBuf *args) { dbReportDeviceConfig(*iocshPpdbbase,stdout); diff --git a/modules/database/src/ioc/dbStatic/dbStaticIocRegister.h b/modules/database/src/ioc/dbStatic/dbStaticIocRegister.h index 2764befc2..c84404e80 100644 --- a/modules/database/src/ioc/dbStatic/dbStaticIocRegister.h +++ b/modules/database/src/ioc/dbStatic/dbStaticIocRegister.h @@ -11,13 +11,13 @@ #ifndef INC_dbStaticIocRegister_H #define INC_dbStaticIocRegister_H -#include "shareLib.h" +#include "dbCoreAPI.h" #ifdef __cplusplus extern "C" { #endif -epicsShareFunc void dbStaticIocRegister(void); +DBCORE_API void dbStaticIocRegister(void); #ifdef __cplusplus } diff --git a/modules/database/src/ioc/dbStatic/dbStaticLib.c b/modules/database/src/ioc/dbStatic/dbStaticLib.c index 63a76d321..35433d9cd 100644 --- a/modules/database/src/ioc/dbStatic/dbStaticLib.c +++ b/modules/database/src/ioc/dbStatic/dbStaticLib.c @@ -34,7 +34,6 @@ #define DBFLDTYPES_GBLSOURCE #define SPECIAL_GBLSOURCE -#define epicsExportSharedSymbols #include "dbChannel.h" #include "dbFldTypes.h" #include "dbStaticLib.h" diff --git a/modules/database/src/ioc/dbStatic/dbStaticLib.h b/modules/database/src/ioc/dbStatic/dbStaticLib.h index e1c25eafa..ea42efccb 100644 --- a/modules/database/src/ioc/dbStatic/dbStaticLib.h +++ b/modules/database/src/ioc/dbStatic/dbStaticLib.h @@ -18,7 +18,7 @@ #include #include -#include "shareLib.h" +#include "dbCoreAPI.h" #include "dbFldTypes.h" #include "dbBase.h" #include "link.h" @@ -43,192 +43,192 @@ typedef struct dbEntry { } DBENTRY; /* Static database access routines*/ -epicsShareFunc DBBASE * dbAllocBase(void); -epicsShareFunc void dbFreeBase(DBBASE *pdbbase); -epicsShareFunc DBENTRY * dbAllocEntry(DBBASE *pdbbase); -epicsShareFunc void dbFreeEntry(DBENTRY *pdbentry); -epicsShareFunc void dbInitEntry(DBBASE *pdbbase, +DBCORE_API DBBASE * dbAllocBase(void); +DBCORE_API void dbFreeBase(DBBASE *pdbbase); +DBCORE_API DBENTRY * dbAllocEntry(DBBASE *pdbbase); +DBCORE_API void dbFreeEntry(DBENTRY *pdbentry); +DBCORE_API void dbInitEntry(DBBASE *pdbbase, DBENTRY *pdbentry); -epicsShareFunc void dbFinishEntry(DBENTRY *pdbentry); -epicsShareFunc DBENTRY * dbCopyEntry(DBENTRY *pdbentry); -epicsShareFunc void dbCopyEntryContents(DBENTRY *pfrom, +DBCORE_API void dbFinishEntry(DBENTRY *pdbentry); +DBCORE_API DBENTRY * dbCopyEntry(DBENTRY *pdbentry); +DBCORE_API void dbCopyEntryContents(DBENTRY *pfrom, DBENTRY *pto); -epicsShareExtern int dbBptNotMonotonic; +DBCORE_API extern int dbBptNotMonotonic; -epicsShareFunc long dbReadDatabase(DBBASE **ppdbbase, +DBCORE_API long dbReadDatabase(DBBASE **ppdbbase, const char *filename, const char *path, const char *substitutions); -epicsShareFunc long dbReadDatabaseFP(DBBASE **ppdbbase, +DBCORE_API long dbReadDatabaseFP(DBBASE **ppdbbase, FILE *fp, const char *path, const char *substitutions); -epicsShareFunc long dbPath(DBBASE *pdbbase, const char *path); -epicsShareFunc long dbAddPath(DBBASE *pdbbase, const char *path); -epicsShareFunc char * dbGetPromptGroupNameFromKey(DBBASE *pdbbase, +DBCORE_API long dbPath(DBBASE *pdbbase, const char *path); +DBCORE_API long dbAddPath(DBBASE *pdbbase, const char *path); +DBCORE_API char * dbGetPromptGroupNameFromKey(DBBASE *pdbbase, const short key); -epicsShareFunc short dbGetPromptGroupKeyFromName(DBBASE *pdbbase, +DBCORE_API short dbGetPromptGroupKeyFromName(DBBASE *pdbbase, const char *name); -epicsShareFunc long dbWriteRecord(DBBASE *ppdbbase, +DBCORE_API long dbWriteRecord(DBBASE *ppdbbase, const char *filename, const char *precordTypename, int level); -epicsShareFunc long dbWriteRecordFP(DBBASE *ppdbbase, +DBCORE_API long dbWriteRecordFP(DBBASE *ppdbbase, FILE *fp, const char *precordTypename, int level); -epicsShareFunc long dbWriteMenu(DBBASE *pdbbase, +DBCORE_API long dbWriteMenu(DBBASE *pdbbase, const char *filename, const char *menuName); -epicsShareFunc long dbWriteMenuFP(DBBASE *pdbbase, +DBCORE_API long dbWriteMenuFP(DBBASE *pdbbase, FILE *fp, const char *menuName); -epicsShareFunc long dbWriteRecordType(DBBASE *pdbbase, +DBCORE_API long dbWriteRecordType(DBBASE *pdbbase, const char *filename, const char *recordTypeName); -epicsShareFunc long dbWriteRecordTypeFP(DBBASE *pdbbase, +DBCORE_API long dbWriteRecordTypeFP(DBBASE *pdbbase, FILE *fp, const char *recordTypeName); -epicsShareFunc long dbWriteDevice(DBBASE *pdbbase, +DBCORE_API long dbWriteDevice(DBBASE *pdbbase, const char *filename); -epicsShareFunc long dbWriteDeviceFP(DBBASE *pdbbase, FILE *fp); -epicsShareFunc long dbWriteDriver(DBBASE *pdbbase, +DBCORE_API long dbWriteDeviceFP(DBBASE *pdbbase, FILE *fp); +DBCORE_API long dbWriteDriver(DBBASE *pdbbase, const char *filename); -epicsShareFunc long dbWriteDriverFP(DBBASE *pdbbase, FILE *fp); -epicsShareFunc long dbWriteLinkFP(DBBASE *pdbbase, FILE *fp); -epicsShareFunc long dbWriteRegistrarFP(DBBASE *pdbbase, FILE *fp); -epicsShareFunc long dbWriteFunctionFP(DBBASE *pdbbase, FILE *fp); -epicsShareFunc long dbWriteVariableFP(DBBASE *pdbbase, FILE *fp); -epicsShareFunc long dbWriteBreaktable(DBBASE *pdbbase, +DBCORE_API long dbWriteDriverFP(DBBASE *pdbbase, FILE *fp); +DBCORE_API long dbWriteLinkFP(DBBASE *pdbbase, FILE *fp); +DBCORE_API long dbWriteRegistrarFP(DBBASE *pdbbase, FILE *fp); +DBCORE_API long dbWriteFunctionFP(DBBASE *pdbbase, FILE *fp); +DBCORE_API long dbWriteVariableFP(DBBASE *pdbbase, FILE *fp); +DBCORE_API long dbWriteBreaktable(DBBASE *pdbbase, const char *filename); -epicsShareFunc long dbWriteBreaktableFP(DBBASE *pdbbase, +DBCORE_API long dbWriteBreaktableFP(DBBASE *pdbbase, FILE *fp); -epicsShareFunc long dbFindRecordType(DBENTRY *pdbentry, +DBCORE_API long dbFindRecordType(DBENTRY *pdbentry, const char *recordTypename); -epicsShareFunc long dbFirstRecordType(DBENTRY *pdbentry); -epicsShareFunc long dbNextRecordType(DBENTRY *pdbentry); -epicsShareFunc char * dbGetRecordTypeName(DBENTRY *pdbentry); -epicsShareFunc int dbGetNRecordTypes(DBENTRY *pdbentry); -epicsShareFunc long dbPutRecordAttribute(DBENTRY *pdbentry, +DBCORE_API long dbFirstRecordType(DBENTRY *pdbentry); +DBCORE_API long dbNextRecordType(DBENTRY *pdbentry); +DBCORE_API char * dbGetRecordTypeName(DBENTRY *pdbentry); +DBCORE_API int dbGetNRecordTypes(DBENTRY *pdbentry); +DBCORE_API long dbPutRecordAttribute(DBENTRY *pdbentry, const char *name, const char*value); -epicsShareFunc long dbGetRecordAttribute(DBENTRY *pdbentry, +DBCORE_API long dbGetRecordAttribute(DBENTRY *pdbentry, const char *name); -epicsShareFunc long dbGetAttributePart(DBENTRY *pdbentry, +DBCORE_API long dbGetAttributePart(DBENTRY *pdbentry, const char **ppname); -epicsShareFunc long dbFirstField(DBENTRY *pdbentry, int dctonly); -epicsShareFunc long dbNextField(DBENTRY *pdbentry, int dctonly); -epicsShareFunc int dbGetNFields(DBENTRY *pdbentry, int dctonly); -epicsShareFunc char * dbGetFieldName(DBENTRY *pdbentry); -epicsShareFunc int dbGetFieldDbfType(DBENTRY *pdbentry); -epicsShareFunc char * dbGetDefault(DBENTRY *pdbentry); -epicsShareFunc char * dbGetPrompt(DBENTRY *pdbentry); -epicsShareFunc int dbGetPromptGroup(DBENTRY *pdbentry); +DBCORE_API long dbFirstField(DBENTRY *pdbentry, int dctonly); +DBCORE_API long dbNextField(DBENTRY *pdbentry, int dctonly); +DBCORE_API int dbGetNFields(DBENTRY *pdbentry, int dctonly); +DBCORE_API char * dbGetFieldName(DBENTRY *pdbentry); +DBCORE_API int dbGetFieldDbfType(DBENTRY *pdbentry); +DBCORE_API char * dbGetDefault(DBENTRY *pdbentry); +DBCORE_API char * dbGetPrompt(DBENTRY *pdbentry); +DBCORE_API int dbGetPromptGroup(DBENTRY *pdbentry); -epicsShareFunc long dbCreateRecord(DBENTRY *pdbentry, +DBCORE_API long dbCreateRecord(DBENTRY *pdbentry, const char *pname); -epicsShareFunc long dbDeleteRecord(DBENTRY *pdbentry); -epicsShareFunc long dbFreeRecords(DBBASE *pdbbase); -epicsShareFunc long dbFindRecordPart(DBENTRY *pdbentry, +DBCORE_API long dbDeleteRecord(DBENTRY *pdbentry); +DBCORE_API long dbFreeRecords(DBBASE *pdbbase); +DBCORE_API long dbFindRecordPart(DBENTRY *pdbentry, const char **ppname); -epicsShareFunc long dbFindRecord(DBENTRY *pdbentry, +DBCORE_API long dbFindRecord(DBENTRY *pdbentry, const char *pname); -epicsShareFunc long dbFirstRecord(DBENTRY *pdbentry); -epicsShareFunc long dbNextRecord(DBENTRY *pdbentry); -epicsShareFunc int dbGetNRecords(DBENTRY *pdbentry); -epicsShareFunc int dbGetNAliases(DBENTRY *pdbentry); -epicsShareFunc char * dbGetRecordName(DBENTRY *pdbentry); -epicsShareFunc long dbCopyRecord(DBENTRY *pdbentry, +DBCORE_API long dbFirstRecord(DBENTRY *pdbentry); +DBCORE_API long dbNextRecord(DBENTRY *pdbentry); +DBCORE_API int dbGetNRecords(DBENTRY *pdbentry); +DBCORE_API int dbGetNAliases(DBENTRY *pdbentry); +DBCORE_API char * dbGetRecordName(DBENTRY *pdbentry); +DBCORE_API long dbCopyRecord(DBENTRY *pdbentry, const char *newRecordName, int overWriteOK); -epicsShareFunc long dbVisibleRecord(DBENTRY *pdbentry); -epicsShareFunc long dbInvisibleRecord(DBENTRY *pdbentry); -epicsShareFunc int dbIsVisibleRecord(DBENTRY *pdbentry); +DBCORE_API long dbVisibleRecord(DBENTRY *pdbentry); +DBCORE_API long dbInvisibleRecord(DBENTRY *pdbentry); +DBCORE_API int dbIsVisibleRecord(DBENTRY *pdbentry); -epicsShareFunc long dbCreateAlias(DBENTRY *pdbentry, +DBCORE_API long dbCreateAlias(DBENTRY *pdbentry, const char *paliasName); -epicsShareFunc int dbIsAlias(DBENTRY *pdbentry); +DBCORE_API int dbIsAlias(DBENTRY *pdbentry); /* Follow alias to actual record */ -epicsShareFunc int dbFollowAlias(DBENTRY *pdbentry); -epicsShareFunc long dbDeleteAliases(DBENTRY *pdbentry); +DBCORE_API int dbFollowAlias(DBENTRY *pdbentry); +DBCORE_API long dbDeleteAliases(DBENTRY *pdbentry); -epicsShareFunc long dbFindFieldPart(DBENTRY *pdbentry, +DBCORE_API long dbFindFieldPart(DBENTRY *pdbentry, const char **ppname); -epicsShareFunc long dbFindField(DBENTRY *pdbentry, +DBCORE_API long dbFindField(DBENTRY *pdbentry, const char *pfieldName); -epicsShareFunc int dbFoundField(DBENTRY *pdbentry); -epicsShareFunc char * dbGetString(DBENTRY *pdbentry); -epicsShareFunc long dbPutString(DBENTRY *pdbentry, +DBCORE_API int dbFoundField(DBENTRY *pdbentry); +DBCORE_API char * dbGetString(DBENTRY *pdbentry); +DBCORE_API long dbPutString(DBENTRY *pdbentry, const char *pstring); -epicsShareFunc char * dbVerify(DBENTRY *pdbentry, +DBCORE_API char * dbVerify(DBENTRY *pdbentry, const char *pstring); -epicsShareFunc int dbIsDefaultValue(DBENTRY *pdbentry); +DBCORE_API int dbIsDefaultValue(DBENTRY *pdbentry); -epicsShareFunc long dbFirstInfo(DBENTRY *pdbentry); -epicsShareFunc long dbNextInfo(DBENTRY *pdbentry); -epicsShareFunc long dbFindInfo(DBENTRY *pdbentry, +DBCORE_API long dbFirstInfo(DBENTRY *pdbentry); +DBCORE_API long dbNextInfo(DBENTRY *pdbentry); +DBCORE_API long dbFindInfo(DBENTRY *pdbentry, const char *name); -epicsShareFunc long dbNextMatchingInfo(DBENTRY *pdbentry, +DBCORE_API long dbNextMatchingInfo(DBENTRY *pdbentry, const char *pattern); -epicsShareFunc long dbDeleteInfo(DBENTRY *pdbentry); -epicsShareFunc const char * dbGetInfoName(DBENTRY *pdbentry); -epicsShareFunc const char * dbGetInfoString(DBENTRY *pdbentry); -epicsShareFunc long dbPutInfoString(DBENTRY *pdbentry, +DBCORE_API long dbDeleteInfo(DBENTRY *pdbentry); +DBCORE_API const char * dbGetInfoName(DBENTRY *pdbentry); +DBCORE_API const char * dbGetInfoString(DBENTRY *pdbentry); +DBCORE_API long dbPutInfoString(DBENTRY *pdbentry, const char *string); -epicsShareFunc long dbPutInfoPointer(DBENTRY *pdbentry, +DBCORE_API long dbPutInfoPointer(DBENTRY *pdbentry, void *pointer); -epicsShareFunc void * dbGetInfoPointer(DBENTRY *pdbentry); -epicsShareFunc const char * dbGetInfo(DBENTRY *pdbentry, +DBCORE_API void * dbGetInfoPointer(DBENTRY *pdbentry); +DBCORE_API const char * dbGetInfo(DBENTRY *pdbentry, const char *name); -epicsShareFunc long dbPutInfo(DBENTRY *pdbentry, +DBCORE_API long dbPutInfo(DBENTRY *pdbentry, const char *name, const char *string); -epicsShareFunc brkTable * dbFindBrkTable(DBBASE *pdbbase, +DBCORE_API brkTable * dbFindBrkTable(DBBASE *pdbbase, const char *name); -epicsShareFunc const char * dbGetFieldTypeString(int dbfType); -epicsShareFunc int dbFindFieldType(const char *type); +DBCORE_API const char * dbGetFieldTypeString(int dbfType); +DBCORE_API int dbFindFieldType(const char *type); -epicsShareFunc dbMenu * dbFindMenu(DBBASE *pdbbase, +DBCORE_API dbMenu * dbFindMenu(DBBASE *pdbbase, const char *name); -epicsShareFunc char ** dbGetMenuChoices(DBENTRY *pdbentry); -epicsShareFunc int dbGetMenuIndex(DBENTRY *pdbentry); -epicsShareFunc long dbPutMenuIndex(DBENTRY *pdbentry, int index); -epicsShareFunc int dbGetNMenuChoices(DBENTRY *pdbentry); -epicsShareFunc char * dbGetMenuStringFromIndex(DBENTRY *pdbentry, +DBCORE_API char ** dbGetMenuChoices(DBENTRY *pdbentry); +DBCORE_API int dbGetMenuIndex(DBENTRY *pdbentry); +DBCORE_API long dbPutMenuIndex(DBENTRY *pdbentry, int index); +DBCORE_API int dbGetNMenuChoices(DBENTRY *pdbentry); +DBCORE_API char * dbGetMenuStringFromIndex(DBENTRY *pdbentry, int index); -epicsShareFunc int dbGetMenuIndexFromString(DBENTRY *pdbentry, +DBCORE_API int dbGetMenuIndexFromString(DBENTRY *pdbentry, const char *choice); -epicsShareFunc drvSup * dbFindDriver(dbBase *pdbbase, +DBCORE_API drvSup * dbFindDriver(dbBase *pdbbase, const char *name); -epicsShareFunc char * dbGetRelatedField(DBENTRY *pdbentry); +DBCORE_API char * dbGetRelatedField(DBENTRY *pdbentry); -epicsShareFunc linkSup * dbFindLinkSup(dbBase *pdbbase, +DBCORE_API linkSup * dbFindLinkSup(dbBase *pdbbase, const char *name); -epicsShareFunc int dbGetNLinks(DBENTRY *pdbentry); -epicsShareFunc long dbGetLinkField(DBENTRY *pdbentry, int index); +DBCORE_API int dbGetNLinks(DBENTRY *pdbentry); +DBCORE_API long dbGetLinkField(DBENTRY *pdbentry, int index); /* Dump routines */ -epicsShareFunc void dbDumpPath(DBBASE *pdbbase); -epicsShareFunc void dbDumpRecord(DBBASE *pdbbase, +DBCORE_API void dbDumpPath(DBBASE *pdbbase); +DBCORE_API void dbDumpRecord(DBBASE *pdbbase, const char *precordTypename, int level); -epicsShareFunc void dbDumpMenu(DBBASE *pdbbase, +DBCORE_API void dbDumpMenu(DBBASE *pdbbase, const char *menuName); -epicsShareFunc void dbDumpRecordType(DBBASE *pdbbase, +DBCORE_API void dbDumpRecordType(DBBASE *pdbbase, const char *recordTypeName); -epicsShareFunc void dbDumpField(DBBASE *pdbbase, +DBCORE_API void dbDumpField(DBBASE *pdbbase, const char *recordTypeName, const char *fname); -epicsShareFunc void dbDumpDevice(DBBASE *pdbbase, +DBCORE_API void dbDumpDevice(DBBASE *pdbbase, const char *recordTypeName); -epicsShareFunc void dbDumpDriver(DBBASE *pdbbase); -epicsShareFunc void dbDumpLink(DBBASE *pdbbase); -epicsShareFunc void dbDumpRegistrar(DBBASE *pdbbase); -epicsShareFunc void dbDumpFunction(DBBASE *pdbbase); -epicsShareFunc void dbDumpVariable(DBBASE *pdbbase); -epicsShareFunc void dbDumpBreaktable(DBBASE *pdbbase, +DBCORE_API void dbDumpDriver(DBBASE *pdbbase); +DBCORE_API void dbDumpLink(DBBASE *pdbbase); +DBCORE_API void dbDumpRegistrar(DBBASE *pdbbase); +DBCORE_API void dbDumpFunction(DBBASE *pdbbase); +DBCORE_API void dbDumpVariable(DBBASE *pdbbase); +DBCORE_API void dbDumpBreaktable(DBBASE *pdbbase, const char *name); -epicsShareFunc void dbPvdDump(DBBASE *pdbbase, int verbose); -epicsShareFunc void dbReportDeviceConfig(DBBASE *pdbbase, +DBCORE_API void dbPvdDump(DBBASE *pdbbase, int verbose); +DBCORE_API void dbReportDeviceConfig(DBBASE *pdbbase, FILE *report); /* Misc useful routines*/ #define dbCalloc(nobj,size) callocMustSucceed(nobj,size,"dbCalloc") #define dbMalloc(size) mallocMustSucceed(size,"dbMalloc") -epicsShareFunc void dbCatString(char **string, int *stringLength, +DBCORE_API void dbCatString(char **string, int *stringLength, char *pnew, char *separator); extern int dbStaticDebug; diff --git a/modules/database/src/ioc/dbStatic/dbStaticPvt.h b/modules/database/src/ioc/dbStatic/dbStaticPvt.h index 0ff9bdbce..0abc12864 100644 --- a/modules/database/src/ioc/dbStatic/dbStaticPvt.h +++ b/modules/database/src/ioc/dbStatic/dbStaticPvt.h @@ -66,7 +66,7 @@ long dbInitRecordLinks(dbRecordType *rtyp, struct dbCommon *prec); /* Parse link string. no record locks needed. * on success caller must free pinfo->target */ -epicsShareFunc long dbParseLink(const char *str, short ftype, dbLinkInfo *pinfo); +DBCORE_API long dbParseLink(const char *str, short ftype, dbLinkInfo *pinfo); /* Check if link type allow the parsed link value pinfo * to be assigned to the given link. * Record containing plink must be locked. @@ -79,7 +79,7 @@ long dbCanSetLink(DBLINK *plink, dbLinkInfo *pinfo, devSup *devsup); */ long dbSetLink(DBLINK *plink, dbLinkInfo *pinfo, devSup *dset); /* Free dbLinkInfo storage */ -epicsShareFunc void dbFreeLinkInfo(dbLinkInfo *pinfo); +DBCORE_API void dbFreeLinkInfo(dbLinkInfo *pinfo); /* The following is for path */ typedef struct dbPathNode { @@ -101,7 +101,7 @@ typedef struct{ dbRecordType *precordType; dbRecordNode *precnode; }PVDENTRY; -epicsShareFunc int dbPvdTableSize(int size); +DBCORE_API int dbPvdTableSize(int size); extern int dbStaticDebug; void dbPvdInitPvt(DBBASE *pdbbase); PVDENTRY *dbPvdFind(DBBASE *pdbbase,const char *name,size_t lenname); diff --git a/modules/database/src/ioc/dbStatic/dbStaticRun.c b/modules/database/src/ioc/dbStatic/dbStaticRun.c index 6d3fd5f60..198ff5c1a 100644 --- a/modules/database/src/ioc/dbStatic/dbStaticRun.c +++ b/modules/database/src/ioc/dbStatic/dbStaticRun.c @@ -23,7 +23,6 @@ #include "epicsTypes.h" #include "errMdef.h" -#include "epicsExport.h" /* #define epicsExportSharedSymbols */ #include "dbBase.h" #include "dbCommonPvt.h" #include "dbStaticLib.h" @@ -31,6 +30,7 @@ #include "dbAccess.h" #include "devSup.h" #include "special.h" +#include "epicsExport.h" int dbConvertStrict = 0; epicsExportAddress(int, dbConvertStrict); @@ -217,7 +217,7 @@ char *dbRecordName(DBENTRY *pdbentry) int dbIsMacroOk(DBENTRY *pdbentry) { return(FALSE); } -epicsShareFunc int dbIsDefaultValue(DBENTRY *pdbentry) +DBCORE_API int dbIsDefaultValue(DBENTRY *pdbentry) { dbFldDes *pflddes = pdbentry->pflddes; void *pfield = pdbentry->pfield; @@ -508,7 +508,7 @@ long dbPutStringNum(DBENTRY *pdbentry, const char *pstring) } } -epicsShareFunc int dbGetMenuIndex(DBENTRY *pdbentry) +DBCORE_API int dbGetMenuIndex(DBENTRY *pdbentry) { dbFldDes *pflddes = pdbentry->pflddes; void *pfield = pdbentry->pfield; @@ -527,7 +527,7 @@ epicsShareFunc int dbGetMenuIndex(DBENTRY *pdbentry) return -1; } -epicsShareFunc long dbPutMenuIndex(DBENTRY *pdbentry, int index) +DBCORE_API long dbPutMenuIndex(DBENTRY *pdbentry, int index) { dbFldDes *pflddes = pdbentry->pflddes; epicsEnum16 *pfield = pdbentry->pfield; diff --git a/modules/database/src/ioc/dbStatic/devSup.h b/modules/database/src/ioc/dbStatic/devSup.h index 7ebbf6562..c41b834ea 100644 --- a/modules/database/src/ioc/dbStatic/devSup.h +++ b/modules/database/src/ioc/dbStatic/devSup.h @@ -21,7 +21,7 @@ #define INCdevSuph 1 #include "errMdef.h" -#include "shareLib.h" +#include "dbCoreAPI.h" /* structures defined elsewhere */ struct dbCommon; @@ -158,12 +158,12 @@ typedef dset unambiguous_dset; * * Recommended for use in device support init_record() */ -epicsShareFunc struct link* dbGetDevLink(struct dbCommon* prec); +DBCORE_API struct link* dbGetDevLink(struct dbCommon* prec); -epicsShareExtern dsxt devSoft_DSXT; /* Allow anything table */ +DBCORE_API extern dsxt devSoft_DSXT; /* Allow anything table */ -epicsShareFunc void devExtend(dsxt *pdsxt); -epicsShareFunc void dbInitDevSup(struct devSup *pdevSup, dset *pdset); +DBCORE_API void devExtend(dsxt *pdsxt); +DBCORE_API void dbInitDevSup(struct devSup *pdevSup, dset *pdset); #define S_dev_noDevSup (M_devSup| 1) /*SDR_DEVSUP: Device support missing*/ diff --git a/modules/database/src/ioc/dbStatic/link.h b/modules/database/src/ioc/dbStatic/link.h index c3c004581..c5481fd74 100644 --- a/modules/database/src/ioc/dbStatic/link.h +++ b/modules/database/src/ioc/dbStatic/link.h @@ -18,7 +18,7 @@ #include "dbDefs.h" #include "ellLib.h" -#include "shareLib.h" +#include "dbCoreAPI.h" #ifdef __cplusplus extern "C" { @@ -47,7 +47,7 @@ typedef struct maplinkType { int value; } maplinkType; -epicsShareExtern maplinkType pamaplinkType[]; +DBCORE_API extern maplinkType pamaplinkType[]; #define VXIDYNAMIC 0 #define VXISTATIC 1 diff --git a/modules/database/src/ioc/dbtemplate/dbLoadTemplate.h b/modules/database/src/ioc/dbtemplate/dbLoadTemplate.h index 91fe5b75a..71aa9620a 100644 --- a/modules/database/src/ioc/dbtemplate/dbLoadTemplate.h +++ b/modules/database/src/ioc/dbtemplate/dbLoadTemplate.h @@ -12,13 +12,13 @@ #ifndef INCdbLoadTemplateh #define INCdbLoadTemplateh -#include "shareLib.h" +#include "dbCoreAPI.h" #ifdef __cplusplus extern "C" { #endif -epicsShareFunc int dbLoadTemplate( +DBCORE_API int dbLoadTemplate( const char *sub_file, const char *cmd_collect); #ifdef __cplusplus diff --git a/modules/database/src/ioc/dbtemplate/dbtoolsIocRegister.c b/modules/database/src/ioc/dbtemplate/dbtoolsIocRegister.c index 2714a14d4..8ee6b2c40 100644 --- a/modules/database/src/ioc/dbtemplate/dbtoolsIocRegister.c +++ b/modules/database/src/ioc/dbtemplate/dbtoolsIocRegister.c @@ -8,7 +8,6 @@ #include "iocsh.h" -#define epicsExportSharedSymbols #include "dbtoolsIocRegister.h" #include "dbLoadTemplate.h" diff --git a/modules/database/src/ioc/dbtemplate/dbtoolsIocRegister.h b/modules/database/src/ioc/dbtemplate/dbtoolsIocRegister.h index 2b1452f43..0c8e449b9 100644 --- a/modules/database/src/ioc/dbtemplate/dbtoolsIocRegister.h +++ b/modules/database/src/ioc/dbtemplate/dbtoolsIocRegister.h @@ -9,13 +9,13 @@ #ifndef INC_dbtoolsIocRegister_H #define INC_dbtoolsIocRegister_H -#include "shareLib.h" +#include "dbCoreAPI.h" #ifdef __cplusplus extern "C" { #endif -epicsShareFunc void dbtoolsIocRegister(void); +DBCORE_API void dbtoolsIocRegister(void); #ifdef __cplusplus } diff --git a/modules/database/src/ioc/dbtemplate/msi.cpp b/modules/database/src/ioc/dbtemplate/msi.cpp index 2e8c15747..6445c22f1 100644 --- a/modules/database/src/ioc/dbtemplate/msi.cpp +++ b/modules/database/src/ioc/dbtemplate/msi.cpp @@ -301,11 +301,11 @@ static void makeSubstitutions(inputData * const inputPvt, char *pstart; char *pend; int cmdind=-1; - int i; + size_t i; for (i = 0; i < NELEMENTS(cmdNames); i++) { if (strstr(command, cmdNames[i])) { - cmdind = i; + cmdind = (int)i; } } if (cmdind < 0) goto endcmd; diff --git a/modules/database/src/ioc/misc/epicsRelease.c b/modules/database/src/ioc/misc/epicsRelease.c index e0cd68f6b..c1801179f 100644 --- a/modules/database/src/ioc/misc/epicsRelease.c +++ b/modules/database/src/ioc/misc/epicsRelease.c @@ -15,11 +15,10 @@ #include "epicsStdio.h" #include "epicsVersion.h" -#define epicsExportSharedSymbols #include "epicsRelease.h" #include "epicsVCS.h" -epicsShareFunc int coreRelease(void) +DBCORE_API int coreRelease(void) { printf ( "############################################################################\n" ); printf ( "## %s\n", epicsReleaseVersion ); diff --git a/modules/database/src/ioc/misc/epicsRelease.h b/modules/database/src/ioc/misc/epicsRelease.h index 86fad6cf6..a94d4aa93 100644 --- a/modules/database/src/ioc/misc/epicsRelease.h +++ b/modules/database/src/ioc/misc/epicsRelease.h @@ -16,8 +16,8 @@ extern "C" { #endif -#include "shareLib.h" -epicsShareFunc int coreRelease(void); +#include "dbCoreAPI.h" +DBCORE_API int coreRelease(void); #ifdef __cplusplus } diff --git a/modules/database/src/ioc/misc/iocInit.h b/modules/database/src/ioc/misc/iocInit.h index bef70174d..6b4c944d4 100644 --- a/modules/database/src/ioc/misc/iocInit.h +++ b/modules/database/src/ioc/misc/iocInit.h @@ -12,7 +12,7 @@ #ifndef INCiocInith #define INCiocInith -#include "shareLib.h" +#include "dbCoreAPI.h" enum iocStateEnum { iocVoid, iocBuilding, iocBuilt, iocRunning, iocPaused @@ -22,13 +22,13 @@ enum iocStateEnum { extern "C" { #endif -epicsShareFunc enum iocStateEnum getIocState(void); -epicsShareFunc int iocInit(void); -epicsShareFunc int iocBuild(void); -epicsShareFunc int iocBuildIsolated(void); -epicsShareFunc int iocRun(void); -epicsShareFunc int iocPause(void); -epicsShareFunc int iocShutdown(void); +DBCORE_API enum iocStateEnum getIocState(void); +DBCORE_API int iocInit(void); +DBCORE_API int iocBuild(void); +DBCORE_API int iocBuildIsolated(void); +DBCORE_API int iocRun(void); +DBCORE_API int iocPause(void); +DBCORE_API int iocShutdown(void); #ifdef __cplusplus } diff --git a/modules/database/src/ioc/misc/iocshRegisterCommon.c b/modules/database/src/ioc/misc/iocshRegisterCommon.c index 205e17859..eba0678fa 100644 --- a/modules/database/src/ioc/misc/iocshRegisterCommon.c +++ b/modules/database/src/ioc/misc/iocshRegisterCommon.c @@ -13,7 +13,6 @@ #include "iocsh.h" #include "libComRegister.h" -#define epicsExportSharedSymbols #include "asIocRegister.h" #include "dbAccess.h" #include "dbIocRegister.h" diff --git a/modules/database/src/ioc/misc/iocshRegisterCommon.h b/modules/database/src/ioc/misc/iocshRegisterCommon.h index e1e4562a1..eb615ed42 100644 --- a/modules/database/src/ioc/misc/iocshRegisterCommon.h +++ b/modules/database/src/ioc/misc/iocshRegisterCommon.h @@ -13,7 +13,7 @@ #ifndef INCiocshRegisterCommonH #define INCiocshRegisterCommonH -#include "shareLib.h" +#include "dbCoreAPI.h" #ifdef __cplusplus extern "C" { @@ -22,19 +22,19 @@ extern "C" { struct dbBase; /* register many useful commands */ -epicsShareFunc void iocshRegisterCommon(void); +DBCORE_API void iocshRegisterCommon(void); #define HAS_registerAllRecordDeviceDrivers -epicsShareFunc +DBCORE_API long registerAllRecordDeviceDrivers(struct dbBase *pdbbase); -epicsShareFunc +DBCORE_API void runRegistrarOnce(void (*reg_func)(void)); #ifdef EPICS_PRIVATE_API -epicsShareFunc +DBCORE_API void clearRegistrarOnce(void); #endif diff --git a/modules/database/src/ioc/misc/miscIocRegister.c b/modules/database/src/ioc/misc/miscIocRegister.c index f88db7586..1b472114a 100644 --- a/modules/database/src/ioc/misc/miscIocRegister.c +++ b/modules/database/src/ioc/misc/miscIocRegister.c @@ -13,42 +13,49 @@ #include "iocsh.h" #include "errlog.h" -#define epicsExportSharedSymbols #include "iocInit.h" #include "epicsExport.h" #include "epicsRelease.h" #include "miscIocRegister.h" /* iocInit */ -static const iocshFuncDef iocInitFuncDef = {"iocInit",0,NULL}; +static const iocshFuncDef iocInitFuncDef = {"iocInit",0,NULL, + "Initializes the various epics components and starts the IOC running.\n"}; static void iocInitCallFunc(const iocshArgBuf *args) { iocshSetError(iocInit()); } /* iocBuild */ -static const iocshFuncDef iocBuildFuncDef = {"iocBuild",0,NULL}; +static const iocshFuncDef iocBuildFuncDef = {"iocBuild",0,NULL, + "First step of the IOC initialization, puts the IOC into a ready-to-run (quiescent) state.\n" + "Needs iocRun() to make the IOC live.\n"}; static void iocBuildCallFunc(const iocshArgBuf *args) { iocshSetError(iocBuild()); } /* iocRun */ -static const iocshFuncDef iocRunFuncDef = {"iocRun",0,NULL}; +static const iocshFuncDef iocRunFuncDef = {"iocRun",0,NULL, + "Bring the IOC out of its initial quiescent state to the running state.\n" + "See more: iocBuild, iocPause"}; static void iocRunCallFunc(const iocshArgBuf *args) { iocshSetError(iocRun()); } /* iocPause */ -static const iocshFuncDef iocPauseFuncDef = {"iocPause",0,NULL}; +static const iocshFuncDef iocPauseFuncDef = {"iocPause",0,NULL, + "Brings a running IOC to a quiescent state with all record processing frozen.\n" + "See more: iocBuild, iocRub, iocInit"}; static void iocPauseCallFunc(const iocshArgBuf *args) { iocshSetError(iocPause()); } /* coreRelease */ -static const iocshFuncDef coreReleaseFuncDef = {"coreRelease",0,NULL}; +static const iocshFuncDef coreReleaseFuncDef = {"coreRelease",0,NULL, + "Print release information for iocCore.\n"}; static void coreReleaseCallFunc(const iocshArgBuf *args) { coreRelease (); @@ -75,7 +82,11 @@ void miscIocRegister(void) #ifndef SYSTEM_UNAVAILABLE static const iocshArg systemArg0 = { "command string",iocshArgString}; static const iocshArg * const systemArgs[] = {&systemArg0}; -static const iocshFuncDef systemFuncDef = {"system",1,systemArgs}; +static const iocshFuncDef systemFuncDef = {"system",1,systemArgs, + "Send command string to the system command interpreter for execution.\n" + "Not available on all OSs.\n" + "To enable this command, add registrar(iocshSystemCommand) to an application dbd file,\n" + "or include system.dbd\n"}; static void systemCallFunc(const iocshArgBuf *args) { iocshSetError(system(args[0].sval)); diff --git a/modules/database/src/ioc/misc/miscIocRegister.h b/modules/database/src/ioc/misc/miscIocRegister.h index 7d2794b70..1b03809c2 100644 --- a/modules/database/src/ioc/misc/miscIocRegister.h +++ b/modules/database/src/ioc/misc/miscIocRegister.h @@ -11,13 +11,13 @@ #ifndef INC_miscIocRegister_H #define INC_miscIocRegister_H -#include "shareLib.h" +#include "dbCoreAPI.h" #ifdef __cplusplus extern "C" { #endif -epicsShareFunc void miscIocRegister(void); +DBCORE_API void miscIocRegister(void); #ifdef __cplusplus } diff --git a/modules/database/src/ioc/misc/registerAllRecordDeviceDrivers.cpp b/modules/database/src/ioc/misc/registerAllRecordDeviceDrivers.cpp index 8ba5182d0..a744578d3 100644 --- a/modules/database/src/ioc/misc/registerAllRecordDeviceDrivers.cpp +++ b/modules/database/src/ioc/misc/registerAllRecordDeviceDrivers.cpp @@ -17,7 +17,6 @@ #include #include -#define epicsExportSharedSymbols #include #include #include diff --git a/modules/database/src/ioc/registry/registryCommon.c b/modules/database/src/ioc/registry/registryCommon.c index dba9ab54e..273e4d5ec 100644 --- a/modules/database/src/ioc/registry/registryCommon.c +++ b/modules/database/src/ioc/registry/registryCommon.c @@ -16,7 +16,6 @@ #include "errlog.h" -#define epicsExportSharedSymbols #include "registryCommon.h" #include "registryDeviceSupport.h" #include "registryDriverSupport.h" diff --git a/modules/database/src/ioc/registry/registryCommon.h b/modules/database/src/ioc/registry/registryCommon.h index 1428afd8c..b2ff5eb07 100644 --- a/modules/database/src/ioc/registry/registryCommon.h +++ b/modules/database/src/ioc/registry/registryCommon.h @@ -15,22 +15,22 @@ #include "devSup.h" #include "dbJLink.h" #include "registryRecordType.h" -#include "shareLib.h" +#include "dbCoreAPI.h" #ifdef __cplusplus extern "C" { #endif -epicsShareFunc void registerRecordTypes( +DBCORE_API void registerRecordTypes( DBBASE *pbase, int nRecordTypes, const char * const *recordTypeNames, const recordTypeLocation *rtl); -epicsShareFunc void registerDevices( +DBCORE_API void registerDevices( DBBASE *pbase, int nDevices, const char * const *deviceSupportNames, const dset * const *devsl); -epicsShareFunc void registerDrivers( +DBCORE_API void registerDrivers( DBBASE *pbase, int nDrivers, const char * const *driverSupportNames, struct drvet * const *drvsl); -epicsShareFunc void registerJLinks( +DBCORE_API void registerJLinks( DBBASE *pbase, int nDrivers, jlif * const *jlifsl); #ifdef __cplusplus diff --git a/modules/database/src/ioc/registry/registryDeviceSupport.c b/modules/database/src/ioc/registry/registryDeviceSupport.c index dd197ec92..0bbf5e389 100644 --- a/modules/database/src/ioc/registry/registryDeviceSupport.c +++ b/modules/database/src/ioc/registry/registryDeviceSupport.c @@ -11,20 +11,19 @@ /* Author: Marty Kraimer Date: 08JUN99 */ -#define epicsExportSharedSymbols #include "registry.h" #include "registryDeviceSupport.h" static void *registryID = "device support"; -epicsShareFunc int registryDeviceSupportAdd( +DBCORE_API int registryDeviceSupportAdd( const char *name, const dset *pdset) { return registryAdd(registryID, name, (void *)pdset); } -epicsShareFunc dset * registryDeviceSupportFind( +DBCORE_API dset * registryDeviceSupportFind( const char *name) { return registryFind(registryID, name); diff --git a/modules/database/src/ioc/registry/registryDeviceSupport.h b/modules/database/src/ioc/registry/registryDeviceSupport.h index b3ccc1525..8030da906 100644 --- a/modules/database/src/ioc/registry/registryDeviceSupport.h +++ b/modules/database/src/ioc/registry/registryDeviceSupport.h @@ -12,15 +12,15 @@ #define INC_registryDeviceSupport_H #include "devSup.h" -#include "shareLib.h" +#include "dbCoreAPI.h" #ifdef __cplusplus extern "C" { #endif -epicsShareFunc int registryDeviceSupportAdd( +DBCORE_API int registryDeviceSupportAdd( const char *name, const dset *pdset); -epicsShareFunc dset * registryDeviceSupportFind( +DBCORE_API dset * registryDeviceSupportFind( const char *name); #ifdef __cplusplus diff --git a/modules/database/src/ioc/registry/registryDriverSupport.c b/modules/database/src/ioc/registry/registryDriverSupport.c index 2dd7f5a35..36ac0a82e 100644 --- a/modules/database/src/ioc/registry/registryDriverSupport.c +++ b/modules/database/src/ioc/registry/registryDriverSupport.c @@ -11,20 +11,19 @@ /* Author: Marty Kraimer Date: 08JUN99 */ -#define epicsExportSharedSymbols #include "registry.h" #include "registryDriverSupport.h" static void *registryID = "driver support"; -epicsShareFunc int registryDriverSupportAdd( +DBCORE_API int registryDriverSupportAdd( const char *name, struct drvet *pdrvet) { return registryAdd(registryID, name, pdrvet); } -epicsShareFunc struct drvet * registryDriverSupportFind( +DBCORE_API struct drvet * registryDriverSupportFind( const char *name) { return registryFind(registryID, name); diff --git a/modules/database/src/ioc/registry/registryDriverSupport.h b/modules/database/src/ioc/registry/registryDriverSupport.h index 4d777b6b0..8857d97b2 100644 --- a/modules/database/src/ioc/registry/registryDriverSupport.h +++ b/modules/database/src/ioc/registry/registryDriverSupport.h @@ -12,15 +12,15 @@ #define INC_registryDriverSupport_H #include "drvSup.h" -#include "shareLib.h" +#include "dbCoreAPI.h" #ifdef __cplusplus extern "C" { #endif -epicsShareFunc int registryDriverSupportAdd( +DBCORE_API int registryDriverSupportAdd( const char *name, struct drvet *pdrvet); -epicsShareFunc struct drvet * registryDriverSupportFind( +DBCORE_API struct drvet * registryDriverSupportFind( const char *name); #ifdef __cplusplus diff --git a/modules/database/src/ioc/registry/registryFunction.c b/modules/database/src/ioc/registry/registryFunction.c index dabc27066..dc00784ba 100644 --- a/modules/database/src/ioc/registry/registryFunction.c +++ b/modules/database/src/ioc/registry/registryFunction.c @@ -13,20 +13,19 @@ #include -#define epicsExportSharedSymbols #include "registry.h" #include "registryFunction.h" static void * const registryID = "function"; -epicsShareFunc int registryFunctionAdd( +DBCORE_API int registryFunctionAdd( const char *name, REGISTRYFUNCTION func) { return registryAdd(registryID, name, func); } -epicsShareFunc REGISTRYFUNCTION registryFunctionFind( +DBCORE_API REGISTRYFUNCTION registryFunctionFind( const char *name) { REGISTRYFUNCTION func = registryFind(registryID, name); @@ -38,7 +37,7 @@ epicsShareFunc REGISTRYFUNCTION registryFunctionFind( return func; } -epicsShareFunc int registryFunctionRefAdd( +DBCORE_API int registryFunctionRefAdd( registryFunctionRef ref[], int nfunctions) { int i; diff --git a/modules/database/src/ioc/registry/registryFunction.h b/modules/database/src/ioc/registry/registryFunction.h index bad96db16..baa6d5080 100644 --- a/modules/database/src/ioc/registry/registryFunction.h +++ b/modules/database/src/ioc/registry/registryFunction.h @@ -11,7 +11,7 @@ #ifndef INC_registryFunction_H #define INC_registryFunction_H -#include "shareLib.h" +#include "dbCoreAPI.h" #ifdef __cplusplus extern "C" { @@ -25,11 +25,11 @@ typedef struct registryFunctionRef { } registryFunctionRef; -epicsShareFunc int registryFunctionAdd( +DBCORE_API int registryFunctionAdd( const char *name, REGISTRYFUNCTION func); -epicsShareFunc REGISTRYFUNCTION registryFunctionFind( +DBCORE_API REGISTRYFUNCTION registryFunctionFind( const char *name); -epicsShareFunc int registryFunctionRefAdd( +DBCORE_API int registryFunctionRefAdd( registryFunctionRef ref[], int nfunctions); #ifdef __cplusplus diff --git a/modules/database/src/ioc/registry/registryIocRegister.c b/modules/database/src/ioc/registry/registryIocRegister.c index 208dae0b0..e45534fa7 100644 --- a/modules/database/src/ioc/registry/registryIocRegister.c +++ b/modules/database/src/ioc/registry/registryIocRegister.c @@ -10,7 +10,6 @@ #include "iocsh.h" -#define epicsExportSharedSymbols #include "registryDeviceSupport.h" #include "registryDriverSupport.h" #include "registryFunction.h" diff --git a/modules/database/src/ioc/registry/registryIocRegister.h b/modules/database/src/ioc/registry/registryIocRegister.h index 833d1d4c7..648d29f0f 100644 --- a/modules/database/src/ioc/registry/registryIocRegister.h +++ b/modules/database/src/ioc/registry/registryIocRegister.h @@ -11,13 +11,13 @@ #ifndef INC_registryIocRegister_H #define INC_registryIocRegister_H -#include "shareLib.h" +#include "dbCoreAPI.h" #ifdef __cplusplus extern "C" { #endif -epicsShareFunc void registryIocRegister(void); +DBCORE_API void registryIocRegister(void); #ifdef __cplusplus } diff --git a/modules/database/src/ioc/registry/registryJLinks.c b/modules/database/src/ioc/registry/registryJLinks.c index 1744f03d2..9b238c8e7 100644 --- a/modules/database/src/ioc/registry/registryJLinks.c +++ b/modules/database/src/ioc/registry/registryJLinks.c @@ -8,13 +8,12 @@ /* registryJLinks.c */ #include "registry.h" -#define epicsExportSharedSymbols #include "dbBase.h" #include "dbStaticLib.h" #include "registryJLinks.h" #include "dbJLink.h" -epicsShareFunc int registryJLinkAdd(DBBASE *pbase, struct jlif *pjlif) +DBCORE_API int registryJLinkAdd(DBBASE *pbase, struct jlif *pjlif) { linkSup *plinkSup = dbFindLinkSup(pbase, pjlif->name); diff --git a/modules/database/src/ioc/registry/registryJLinks.h b/modules/database/src/ioc/registry/registryJLinks.h index 11940b970..a4aecd634 100644 --- a/modules/database/src/ioc/registry/registryJLinks.h +++ b/modules/database/src/ioc/registry/registryJLinks.h @@ -13,13 +13,13 @@ #include "dbBase.h" #include "dbJLink.h" -#include "shareLib.h" +#include "dbCoreAPI.h" #ifdef __cplusplus extern "C" { #endif -epicsShareFunc int registryJLinkAdd(DBBASE *pbase, jlif *pjlif); +DBCORE_API int registryJLinkAdd(DBBASE *pbase, jlif *pjlif); #ifdef __cplusplus } diff --git a/modules/database/src/ioc/registry/registryRecordType.c b/modules/database/src/ioc/registry/registryRecordType.c index 3ff3f2074..3212371a3 100644 --- a/modules/database/src/ioc/registry/registryRecordType.c +++ b/modules/database/src/ioc/registry/registryRecordType.c @@ -11,20 +11,19 @@ /* Author: Marty Kraimer Date: 08JUN99 */ -#define epicsExportSharedSymbols #include "registry.h" #include "registryRecordType.h" static void * const registryID = "record type"; -epicsShareFunc int registryRecordTypeAdd( +DBCORE_API int registryRecordTypeAdd( const char *name, const recordTypeLocation *prtl) { return registryAdd(registryID, name, (void *)prtl); } -epicsShareFunc recordTypeLocation * registryRecordTypeFind( +DBCORE_API recordTypeLocation * registryRecordTypeFind( const char *name) { return registryFind(registryID, name); diff --git a/modules/database/src/ioc/registry/registryRecordType.h b/modules/database/src/ioc/registry/registryRecordType.h index 3ee8ef817..6f9fed5a0 100644 --- a/modules/database/src/ioc/registry/registryRecordType.h +++ b/modules/database/src/ioc/registry/registryRecordType.h @@ -12,7 +12,7 @@ #define INC_registryRecordType_H #include "recSup.h" -#include "shareLib.h" +#include "dbCoreAPI.h" #ifdef __cplusplus extern "C" { @@ -28,9 +28,9 @@ typedef struct recordTypeLocation { computeSizeOffset sizeOffset; }recordTypeLocation; -epicsShareFunc int registryRecordTypeAdd( +DBCORE_API int registryRecordTypeAdd( const char *name, const recordTypeLocation *prtl); -epicsShareFunc recordTypeLocation * registryRecordTypeFind( +DBCORE_API recordTypeLocation * registryRecordTypeFind( const char *name); int registerRecordDeviceDriver(struct dbBase *pdbbase); diff --git a/modules/database/src/ioc/rsrv/camessage.c b/modules/database/src/ioc/rsrv/camessage.c index c0b6fe416..21c835b8f 100644 --- a/modules/database/src/ioc/rsrv/camessage.c +++ b/modules/database/src/ioc/rsrv/camessage.c @@ -38,7 +38,6 @@ #include "caerr.h" #include "net_convert.h" -#define epicsExportSharedSymbols #include "asDbLib.h" #include "callback.h" #include "db_access.h" diff --git a/modules/database/src/ioc/rsrv/camsgtask.c b/modules/database/src/ioc/rsrv/camsgtask.c index 74613d79e..bcd30d1bd 100644 --- a/modules/database/src/ioc/rsrv/camsgtask.c +++ b/modules/database/src/ioc/rsrv/camsgtask.c @@ -29,7 +29,6 @@ #include "caerr.h" -#define epicsExportSharedSymbols #include "db_access.h" #include "rsrv.h" #include "server.h" diff --git a/modules/database/src/ioc/rsrv/caserverio.c b/modules/database/src/ioc/rsrv/caserverio.c index 67c33c646..9703197a0 100644 --- a/modules/database/src/ioc/rsrv/caserverio.c +++ b/modules/database/src/ioc/rsrv/caserverio.c @@ -30,7 +30,6 @@ #include "caerr.h" #include "net_convert.h" -#define epicsExportSharedSymbols #include "server.h" /* diff --git a/modules/database/src/ioc/rsrv/caservertask.c b/modules/database/src/ioc/rsrv/caservertask.c index 3499fb0ac..4b37ab7e9 100644 --- a/modules/database/src/ioc/rsrv/caservertask.c +++ b/modules/database/src/ioc/rsrv/caservertask.c @@ -37,7 +37,6 @@ #include "epicsExport.h" -#define epicsExportSharedSymbols #include "dbChannel.h" #include "dbCommon.h" #include "dbEvent.h" diff --git a/modules/database/src/ioc/rsrv/cast_server.c b/modules/database/src/ioc/rsrv/cast_server.c index febdd3d0f..0668c63a9 100644 --- a/modules/database/src/ioc/rsrv/cast_server.c +++ b/modules/database/src/ioc/rsrv/cast_server.c @@ -46,7 +46,6 @@ #include "osiSock.h" #include "taskwd.h" -#define epicsExportSharedSymbols #include "rsrv.h" #include "server.h" diff --git a/modules/database/src/ioc/rsrv/online_notify.c b/modules/database/src/ioc/rsrv/online_notify.c index 08431c1f1..7f75bde37 100644 --- a/modules/database/src/ioc/rsrv/online_notify.c +++ b/modules/database/src/ioc/rsrv/online_notify.c @@ -31,7 +31,6 @@ #include "osiSock.h" #include "taskwd.h" -#define epicsExportSharedSymbols #include "server.h" /* diff --git a/modules/database/src/ioc/rsrv/rsrv.h b/modules/database/src/ioc/rsrv/rsrv.h index 8700dccbe..9ac1bb45d 100644 --- a/modules/database/src/ioc/rsrv/rsrv.h +++ b/modules/database/src/ioc/rsrv/rsrv.h @@ -19,7 +19,7 @@ #define rsrvh #include -#include "shareLib.h" +#include "dbCoreAPI.h" #define RSRV_OK 0 #define RSRV_ERROR (-1) @@ -28,12 +28,12 @@ extern "C" { #endif -epicsShareFunc void rsrv_register_server(void); +DBCORE_API void rsrv_register_server(void); -epicsShareFunc void casr (unsigned level); -epicsShareFunc int casClientInitiatingCurrentThread ( +DBCORE_API void casr (unsigned level); +DBCORE_API int casClientInitiatingCurrentThread ( char * pBuf, size_t bufSize ); -epicsShareFunc void casStatsFetch ( +DBCORE_API void casStatsFetch ( unsigned *pChanCount, unsigned *pConnCount ); #ifdef __cplusplus diff --git a/modules/database/src/ioc/rsrv/rsrvIocRegister.c b/modules/database/src/ioc/rsrv/rsrvIocRegister.c index 05b2e7d6b..ba1e5e229 100644 --- a/modules/database/src/ioc/rsrv/rsrvIocRegister.c +++ b/modules/database/src/ioc/rsrv/rsrvIocRegister.c @@ -11,7 +11,6 @@ #include "osiSock.h" #include "iocsh.h" -#define epicsExportSharedSymbols #include "rsrv.h" #include "server.h" #include "epicsExport.h" @@ -20,7 +19,12 @@ /* casr */ static const iocshArg casrArg0 = { "level",iocshArgInt}; static const iocshArg * const casrArgs[1] = {&casrArg0}; -static const iocshFuncDef casrFuncDef = {"casr",1,casrArgs}; +static const iocshFuncDef casrFuncDef = {"casr",1,casrArgs, + "Channel Access Server Report with following levels:\n" + " 0 - server’s protocol version level and summary for each attached client\n" + " 1 - extends report with information about connected clients and beacons\n" + " 2 - extends report with specific channel names and UDP search requests\n" + " 3+ - expert\n"}; static void casrCallFunc(const iocshArgBuf *args) { casr(args[0].ival); diff --git a/modules/database/src/ioc/rsrv/server.h b/modules/database/src/ioc/rsrv/server.h index c2d86128c..c0593739e 100644 --- a/modules/database/src/ioc/rsrv/server.h +++ b/modules/database/src/ioc/rsrv/server.h @@ -16,11 +16,6 @@ #ifndef INCLserverh #define INCLserverh -#ifdef epicsExportSharedSymbols -# define rsrvRestore_epicsExportSharedSymbols -# undef epicsExportSharedSymbols -#endif /* ifdef epicsExportSharedSymbols */ - #include "epicsThread.h" #include "epicsMutex.h" #include "epicsEvent.h" @@ -35,10 +30,6 @@ #include "epicsAssert.h" #include "osiSock.h" -#ifdef rsrvRestore_epicsExportSharedSymbols -#define epicsExportSharedSymbols -#endif - /* a modified ca header with capacity for large arrays */ typedef struct caHdrLargeArray { ca_uint32_t m_postsize; /* size of message extension */ diff --git a/modules/database/src/std/dev/devEnviron.c b/modules/database/src/std/dev/devEnviron.c index 77b89d001..910f1f0c7 100644 --- a/modules/database/src/std/dev/devEnviron.c +++ b/modules/database/src/std/dev/devEnviron.c @@ -63,7 +63,7 @@ static long read_lsi(lsiRecord *prec) prec->val[0] = 0; prec->len = 1; prec->udf = TRUE; - recGblSetSevr(prec, UDF_ALARM, prec->udfs); + recGblSetSevrMsg(prec, UDF_ALARM, prec->udfs, "No such ENV"); } return 0; @@ -114,7 +114,7 @@ static long read_stringin(stringinRecord *prec) else { prec->val[0] = 0; prec->udf = TRUE; - recGblSetSevr(prec, UDF_ALARM, prec->udfs); + recGblSetSevrMsg(prec, UDF_ALARM, prec->udfs, "No such ENV"); } return 0; diff --git a/modules/database/src/std/filters/Makefile b/modules/database/src/std/filters/Makefile index ee6a0ae68..b02999403 100644 --- a/modules/database/src/std/filters/Makefile +++ b/modules/database/src/std/filters/Makefile @@ -16,6 +16,7 @@ dbRecStd_SRCS += dbnd.c dbRecStd_SRCS += arr.c dbRecStd_SRCS += sync.c dbRecStd_SRCS += decimate.c +dbRecStd_SRCS += utag.c HTMLS += filters.html diff --git a/modules/database/src/std/filters/filters.dbd.pod b/modules/database/src/std/filters/filters.dbd.pod index 27e356f83..7b3146609 100644 --- a/modules/database/src/std/filters/filters.dbd.pod +++ b/modules/database/src/std/filters/filters.dbd.pod @@ -16,6 +16,8 @@ The following filters are available in this release: =item * L +=item * L + =back =head2 Using Filters @@ -285,3 +287,26 @@ once every minute: ... =cut + +registrar(utagInitialize) + +=head3 UTag Filter C<"utag"> + +This filter applies a test UTAG&M==V to the value taken from the UTAG record field +and drops those updates which evaluate as false. + +=head4 Parameters + +=over + +=item Mask C<"M"> + +Bit mask. + +=item Value C<"V"> + +Required value. + +=back + +=cut diff --git a/modules/database/src/std/filters/utag.c b/modules/database/src/std/filters/utag.c new file mode 100644 index 000000000..b17f3e8a0 --- /dev/null +++ b/modules/database/src/std/filters/utag.c @@ -0,0 +1,99 @@ +/*************************************************************************\ +* 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 + +#include +#include +#include +#include +#include + +typedef struct { + epicsInt32 mask, value; + int first; +} utagPvt; + +static const +chfPluginArgDef opts[] = { + chfInt32(utagPvt, mask, "M", 0, 1), + chfInt32(utagPvt, value, "V", 0, 1), + chfPluginArgEnd +}; + +static void * allocPvt(void) +{ + utagPvt *pvt; + pvt = calloc(1, sizeof(utagPvt)); + pvt->mask = 0xffffffff; + return pvt; +} + +static void freePvt(void *pvt) +{ + free(pvt); +} + +static int parse_ok(void *raw) +{ + utagPvt *pvt = (utagPvt*)raw; + pvt->first = 1; + return 0; +} + +static db_field_log* filter(void* raw, dbChannel *chan, db_field_log *pfl) +{ + utagPvt *pvt = (utagPvt*)raw; + epicsUTag utag = pfl->utag; + int drop = (utag&pvt->mask)!=pvt->value; + + if(pfl->ctx!=dbfl_context_event || pfl->mask&DBE_PROPERTY) { + /* never drop for reads, or property events */ + + } else if(pvt->first) { + /* never drop first */ + pvt->first = 0; + + } else if(drop) { + db_delete_field_log(pfl); + pfl = NULL; + } + + return pfl; +} + +static void channelRegisterPre(dbChannel *chan, void *pvt, + chPostEventFunc **cb_out, void **arg_out, db_field_log *probe) +{ + *cb_out = filter; + *arg_out = pvt; +} + +static void channel_report(dbChannel *chan, void *raw, int level, const unsigned short indent) +{ + utagPvt *pvt = (utagPvt*)raw; + printf("%*sutag : mask=0x%08x value=0x%08x\n", indent, "", (epicsUInt32)pvt->mask, (epicsUInt32)pvt->value); +} + +static const +chfPluginIf pif = { + allocPvt, + freePvt, + NULL, /* parse_error */ + parse_ok, /* parse_ok */ + NULL, /* channel_open */ + channelRegisterPre, + NULL, /* channelRegisterPost */ + channel_report, + NULL, /* channel_close */ +}; + +static +void utagInitialize(void) +{ + chfPluginRegister("utag", &pif, opts); +} +epicsExportRegistrar(utagInitialize); diff --git a/modules/database/src/std/link/lnkCalc.c b/modules/database/src/std/link/lnkCalc.c index 8d7f72c69..46655850e 100644 --- a/modules/database/src/std/link/lnkCalc.c +++ b/modules/database/src/std/link/lnkCalc.c @@ -53,6 +53,7 @@ typedef struct calc_link { } pstate; epicsEnum16 stat; epicsEnum16 sevr; + char amsg[DB_AMSG_SIZE]; short prec; char *expr; char *major; @@ -66,6 +67,7 @@ typedef struct calc_link { struct link out; double arg[CALCPERFORM_NARGS]; epicsTimeStamp time; + epicsUTag utag; double val; } calc_link; @@ -385,9 +387,10 @@ static void lnkCalc_report(const jlink *pjlink, int level, int indent) if (level > 0) { if (clink->sevr) - printf("%*s Alarm: %s, %s\n", indent, "", + printf("%*s Alarm: %s, %s, \"%s\"\n", indent, "", epicsAlarmSeverityStrings[clink->sevr], - epicsAlarmConditionStrings[clink->stat]); + epicsAlarmConditionStrings[clink->stat], + clink->amsg); if (clink->post_major) printf("%*s Major expression: \"%s\"\n", indent, "", @@ -532,6 +535,7 @@ static long lnkCalc_getElements(const struct link *plink, long *nelements) struct lcvt { double *pval; epicsTimeStamp *ptime; + epicsUTag *ptag; }; static long readLocked(struct link *pinp, void *vvt) @@ -541,7 +545,7 @@ static long readLocked(struct link *pinp, void *vvt) long status = dbGetLink(pinp, DBR_DOUBLE, pvt->pval, NULL, &nReq); if (!status && pvt->ptime) - dbGetTimeStamp(pinp, pvt->ptime); + dbGetTimeStampTag(pinp, pvt->ptime, pvt->ptag); return status; } @@ -567,7 +571,7 @@ static long lnkCalc_getValue(struct link *plink, short dbrType, void *pbuffer, long nReq = 1; if (i == clink->tinp) { - struct lcvt vt = {&clink->arg[i], &clink->time}; + struct lcvt vt = {&clink->arg[i], &clink->time, &clink->utag}; status = dbLinkDoLocked(child, readLocked, &vt); if (status == S_db_noLSET) @@ -576,6 +580,7 @@ static long lnkCalc_getValue(struct link *plink, short dbrType, void *pbuffer, if (dbLinkIsConstant(&prec->tsel) && prec->tse == epicsTimeEventDeviceTime) { prec->time = clink->time; + prec->utag = clink->utag; } } else @@ -583,6 +588,7 @@ static long lnkCalc_getValue(struct link *plink, short dbrType, void *pbuffer, } clink->stat = 0; clink->sevr = 0; + clink->amsg[0] = '\0'; if (clink->post_expr) { status = calcPerform(clink->arg, &clink->val, clink->post_expr); @@ -604,7 +610,8 @@ static long lnkCalc_getValue(struct link *plink, short dbrType, void *pbuffer, if (!status && alval) { clink->stat = LINK_ALARM; clink->sevr = MAJOR_ALARM; - recGblSetSevr(prec, clink->stat, clink->sevr); + strcpy(clink->amsg, "post_major error"); + recGblSetSevrMsg(prec, clink->stat, clink->sevr, "post_major error"); } } @@ -615,7 +622,8 @@ static long lnkCalc_getValue(struct link *plink, short dbrType, void *pbuffer, if (!status && alval) { clink->stat = LINK_ALARM; clink->sevr = MINOR_ALARM; - recGblSetSevr(prec, clink->stat, clink->sevr); + strcpy(clink->amsg, "post_minor error"); + recGblSetSevrMsg(prec, clink->stat, clink->sevr, "post_minor error"); } } @@ -643,7 +651,7 @@ static long lnkCalc_putValue(struct link *plink, short dbrType, long nReq = 1; if (i == clink->tinp) { - struct lcvt vt = {&clink->arg[i], &clink->time}; + struct lcvt vt = {&clink->arg[i], &clink->time, &clink->utag}; status = dbLinkDoLocked(child, readLocked, &vt); if (status == S_db_noLSET) @@ -652,6 +660,7 @@ static long lnkCalc_putValue(struct link *plink, short dbrType, if (dbLinkIsConstant(&prec->tsel) && prec->tse == epicsTimeEventDeviceTime) { prec->time = clink->time; + prec->utag = clink->utag; } } else @@ -659,6 +668,7 @@ static long lnkCalc_putValue(struct link *plink, short dbrType, } clink->stat = 0; clink->sevr = 0; + clink->amsg[0] = '\0'; /* Get the value being output as VAL */ status = conv(pbuffer, &clink->val, NULL); @@ -673,7 +683,8 @@ static long lnkCalc_putValue(struct link *plink, short dbrType, if (!status && alval) { clink->stat = LINK_ALARM; clink->sevr = MAJOR_ALARM; - recGblSetSevr(prec, clink->stat, clink->sevr); + strcpy(clink->amsg, "post_major error"); + recGblSetSevrMsg(prec, clink->stat, clink->sevr, "post_major error"); } } @@ -684,7 +695,8 @@ static long lnkCalc_putValue(struct link *plink, short dbrType, if (!status && alval) { clink->stat = LINK_ALARM; clink->sevr = MINOR_ALARM; - recGblSetSevr(prec, clink->stat, clink->sevr); + strcpy(clink->amsg, "post_major error"); + recGblSetSevrMsg(prec, clink->stat, clink->sevr, "post_minor error"); } } @@ -718,8 +730,8 @@ static long lnkCalc_getUnits(const struct link *plink, char *units, int len) return 0; } -static long lnkCalc_getAlarm(const struct link *plink, epicsEnum16 *status, - epicsEnum16 *severity) +static long lnkCalc_getAlarmMsg(const struct link *plink, epicsEnum16 *status, + epicsEnum16 *severity, char *msgbuf, size_t msgbuflen) { calc_link *clink = CONTAINER(plink->value.json.jlink, struct calc_link, jlink); @@ -728,17 +740,23 @@ static long lnkCalc_getAlarm(const struct link *plink, epicsEnum16 *status, *status = clink->stat; if (severity) *severity = clink->sevr; + if (msgbuf && msgbuflen) { + strncpy(msgbuf, clink->amsg, msgbuflen-1); + msgbuf[msgbuflen-1] = '\0'; + } return 0; } -static long lnkCalc_getTimestamp(const struct link *plink, epicsTimeStamp *pstamp) +static long lnkCalc_getTimestampTag(const struct link *plink, epicsTimeStamp *pstamp, epicsUTag *ptag) { calc_link *clink = CONTAINER(plink->value.json.jlink, struct calc_link, jlink); if (clink->tinp >= 0) { *pstamp = clink->time; + if(ptag) + *ptag = clink->utag; return 0; } @@ -761,9 +779,11 @@ static lset lnkCalc_lset = { lnkCalc_getValue, NULL, NULL, NULL, lnkCalc_getPrecision, lnkCalc_getUnits, - lnkCalc_getAlarm, lnkCalc_getTimestamp, + NULL, NULL, lnkCalc_putValue, NULL, - NULL, doLocked + NULL, doLocked, + lnkCalc_getAlarmMsg, + lnkCalc_getTimestampTag, }; static jlif lnkCalcIf = { diff --git a/modules/database/src/std/rec/aiRecord.c b/modules/database/src/std/rec/aiRecord.c index c149211b9..8d31b07ff 100644 --- a/modules/database/src/std/rec/aiRecord.c +++ b/modules/database/src/std/rec/aiRecord.c @@ -432,7 +432,7 @@ static void convert(aiRecord *prec) default: /* must use breakpoint table */ if (cvtRawToEngBpt(&val,prec->linr,prec->init,(void *)&prec->pbrk,&prec->lbrk)!=0) { - recGblSetSevr(prec,SOFT_ALARM,MAJOR_ALARM); + recGblSetSevrMsg(prec,SOFT_ALARM,MAJOR_ALARM, "BPT Error"); } } diff --git a/modules/database/src/std/rec/calcoutRecord.c b/modules/database/src/std/rec/calcoutRecord.c index dbd6be3f9..eadcc5862 100644 --- a/modules/database/src/std/rec/calcoutRecord.c +++ b/modules/database/src/std/rec/calcoutRecord.c @@ -236,7 +236,7 @@ static long process(struct dbCommon *pcommon) } if (fetch_values(prec) == 0) { if (calcPerform(&prec->a, &prec->val, prec->rpcl)) { - recGblSetSevr(prec, CALC_ALARM, INVALID_ALARM); + recGblSetSevrMsg(prec, CALC_ALARM, INVALID_ALARM, "calcPerform"); } else { prec->udf = isnan(prec->val); } @@ -610,7 +610,7 @@ static void execOutput(calcoutRecord *prec) break; case calcoutDOPT_Use_OVAL: if (calcPerform(&prec->a, &prec->oval, prec->orpc)) { - recGblSetSevr(prec, CALC_ALARM, INVALID_ALARM); + recGblSetSevrMsg(prec, CALC_ALARM, INVALID_ALARM, "OCAL calcPerform"); } else { prec->udf = isnan(prec->oval); } @@ -770,7 +770,7 @@ static long writeValue(calcoutRecord *prec) if (!pcalcoutDSET || !pcalcoutDSET->write) { errlogPrintf("%s DSET write does not exist\n", prec->name); - recGblSetSevr(prec, SOFT_ALARM, INVALID_ALARM); + recGblSetSevrMsg(prec, SOFT_ALARM, INVALID_ALARM, "DSET write does not exist"); prec->pact = TRUE; return(-1); } diff --git a/modules/database/src/std/softIoc/Makefile b/modules/database/src/std/softIoc/Makefile index a432d358d..35ef6cb34 100644 --- a/modules/database/src/std/softIoc/Makefile +++ b/modules/database/src/std/softIoc/Makefile @@ -28,7 +28,5 @@ softIoc_LIBS = $(EPICS_BASE_IOC_LIBS) DB += softIocExit.db -FINAL_LOCATION ?= $(shell $(PERL) $(TOOLS)/fullPathName.pl $(INSTALL_LOCATION)) - CLEANS += epicsInstallDir.h diff --git a/modules/database/src/std/softIoc/softMain.cpp b/modules/database/src/std/softIoc/softMain.cpp index cdb0f4a81..367e23ed8 100644 --- a/modules/database/src/std/softIoc/softMain.cpp +++ b/modules/database/src/std/softIoc/softMain.cpp @@ -249,7 +249,10 @@ int main(int argc, char *argv[]) } else { if (loadedDb || ranScript) { - epicsThreadExitMain(); + // non-interactive IOC. spin forever + while(true) { + epicsThreadSleep(1000.0); + } } else { usage(argv[0], dbd_file); diff --git a/modules/database/src/tools/DBD/Menu.pm b/modules/database/src/tools/DBD/Menu.pm index 38a2aba99..5480b3952 100644 --- a/modules/database/src/tools/DBD/Menu.pm +++ b/modules/database/src/tools/DBD/Menu.pm @@ -67,13 +67,16 @@ sub toDeclaration { my $name = $this->name; my $macro_name = "${name}_NUM_CHOICES"; my @choices = map { - sprintf " %-31s /* %s */", @{$_}[0], escapeCcomment(@{$_}[1]); + sprintf " %-31s /**< \@brief State string \"%s\" */", + @{$_}[0], escapeCcomment(@{$_}[1]); } $this->choices; my $num = scalar @choices; return "#ifndef $macro_name\n" . + "/** \@brief Enumerated type from menu $name */\n" . "typedef enum {\n" . join(",\n", @choices) . "\n} $name;\n" . + "/** \@brief Number of states defined for menu $name */\n" . "#define $macro_name $num\n" . "#endif\n\n"; } diff --git a/modules/database/src/tools/DBD/Recfield.pm b/modules/database/src/tools/DBD/Recfield.pm index cc49bcc46..b4bd5d318 100644 --- a/modules/database/src/tools/DBD/Recfield.pm +++ b/modules/database/src/tools/DBD/Recfield.pm @@ -185,7 +185,7 @@ sub toDeclaration { my $name = $this->C_name; my $result = sprintf " %-19s %-12s", $ctype, "$name;"; my $prompt = $this->attribute('prompt'); - $result .= "/* $prompt */" if defined $prompt; + $result .= "/**< \@brief $prompt */" if defined $prompt; return $result; } @@ -217,7 +217,7 @@ sub toDeclaration { my $size = $this->attribute('size'); my $result = sprintf " %-19s %-12s", 'char', "${name}[${size}];"; my $prompt = $this->attribute('prompt'); - $result .= "/* $prompt */" if defined $prompt; + $result .= "/**< \@brief $prompt */" if defined $prompt; return $result; } @@ -540,7 +540,7 @@ sub toDeclaration { my $extra = $this->attribute('extra'); my $result = sprintf " %-31s ", "$extra;"; my $prompt = $this->attribute('prompt'); - $result .= "/* $prompt */" if defined $prompt; + $result .= "/**< \@brief $prompt */" if defined $prompt; return $result; } diff --git a/modules/database/src/tools/DBD/Recordtype.pm b/modules/database/src/tools/DBD/Recordtype.pm index a602f5da4..1e626fdf8 100644 --- a/modules/database/src/tools/DBD/Recordtype.pm +++ b/modules/database/src/tools/DBD/Recordtype.pm @@ -132,10 +132,15 @@ sub toDeclaration { $_->toDeclaration } $this->fields; my $name = $this->name; - $name .= "Record" unless $name eq "dbCommon"; - return "typedef struct $name {\n" . - join("\n", @fields) . - "\n} $name;\n\n"; + my $doc = $name; + if ($name ne 'dbCommon') { + $name .= 'Record'; + $doc .= ' record type.'; + } + return "/** \@brief Declaration of $doc */\n" . + "typedef struct $name {\n" . + join("\n", @fields) . + "\n} $name;\n\n"; } 1; diff --git a/modules/database/src/tools/Makefile b/modules/database/src/tools/Makefile index f54ab9c07..41bf086d3 100644 --- a/modules/database/src/tools/Makefile +++ b/modules/database/src/tools/Makefile @@ -40,7 +40,6 @@ HTMLS += dbdToHtml.html # Build Package Config Files -FINAL_LOCATION ?= $(shell $(PERL) $(TOOLS)/fullPathName.pl $(INSTALL_LOCATION)) C_CFLAGS += $(filter-out -g,$(filter-out -O%,$(filter-out -W%,$(CPPFLAGS)))) C_CFLAGS += $(filter-out -g,$(filter-out -O%,$(filter-out -W%,$(CFLAGS)))) PKGVARS += FINAL_LOCATION OS_CLASS CMPLR_CLASS C_CFLAGS LDFLAGS LDLIBS diff --git a/modules/database/src/tools/dbdToMenuH.pl b/modules/database/src/tools/dbdToMenuH.pl index 10f1904fb..71352edff 100644 --- a/modules/database/src/tools/dbdToMenuH.pl +++ b/modules/database/src/tools/dbdToMenuH.pl @@ -11,6 +11,8 @@ use FindBin qw($Bin); use lib ("$Bin/../../lib/perl"); +use strict; + use EPICS::Getopts; use File::Basename; use DBD; @@ -57,7 +59,9 @@ if ($opt_D) { print map { "$_:\n" } @uniqfiles; } else { open OUTFILE, ">$outfile" or die "$tool: Can't open $outfile: $!\n"; - print OUTFILE "/* $outbase generated from $inbase */\n\n", + print OUTFILE "/** \@file $outbase\n", + " * \@brief Declarations generated from $inbase\n", + " */\n\n", "#ifndef $guard_name\n", "#define $guard_name\n\n"; my $menus = $dbd->menus; diff --git a/modules/database/src/tools/dbdToRecordtypeH.pl b/modules/database/src/tools/dbdToRecordtypeH.pl index 76bae7fbf..0bb3839fe 100644 --- a/modules/database/src/tools/dbdToRecordtypeH.pl +++ b/modules/database/src/tools/dbdToRecordtypeH.pl @@ -61,13 +61,19 @@ if ($opt_D) { # Output dependencies only, to stdout print "$outfile: ", join(" \\\n ", @uniqfiles), "\n\n"; print map { "$_:\n" } @uniqfiles; } else { + our ($rn, $rtyp) = each %{$rtypes}; + my $rtn = $rn; + $rtn .= 'Record' if $rn ne 'dbCommon'; + open OUTFILE, ">$outfile" or die "$tool: Can't open $outfile: $!\n"; - print OUTFILE "/* $outbase generated from $inbase */\n\n", + print OUTFILE "/** \@file $outbase\n", + " * \@brief Declarations for the \@ref $rtn \"$rn\" record type.\n", + " *\n", + " * This header was generated from $inbase\n", + " */\n\n", "#ifndef $guard_name\n", "#define $guard_name\n\n"; - our ($rn, $rtyp) = each %{$rtypes}; - print OUTFILE $rtyp->toCdefs; my @menu_fields = grep { diff --git a/modules/database/src/tools/registerRecordDeviceDriver.pl b/modules/database/src/tools/registerRecordDeviceDriver.pl index 49354fbd7..f95230dee 100644 --- a/modules/database/src/tools/registerRecordDeviceDriver.pl +++ b/modules/database/src/tools/registerRecordDeviceDriver.pl @@ -77,6 +77,7 @@ print $out (<< "END"); #include "iocshRegisterCommon.h" #include "registryCommon.h" #include "recSup.h" +#include "shareLib.h" END diff --git a/modules/database/test/ioc/db/Makefile b/modules/database/test/ioc/db/Makefile index a34da94bf..11f74f238 100644 --- a/modules/database/test/ioc/db/Makefile +++ b/modules/database/test/ioc/db/Makefile @@ -117,6 +117,13 @@ testHarness_SRCS += dbCACTest.cpp TESTS += dbCaLinkTest TESTFILES += ../dbCaLinkTest1.db ../dbCaLinkTest2.db ../dbCaLinkTest3.db +TESTPROD_HOST += dbDbLinkTest +dbDbLinkTest_SRCS += dbDbLinkTest.c +dbDbLinkTest_SRCS += dbTestIoc_registerRecordDeviceDriver.cpp +testHarness_SRCS += dbDbLinkTest.c +TESTS += dbDbLinkTest +TESTFILES += ../dbDbLinkTest.db + TESTPROD_HOST += scanIoTest scanIoTest_SRCS += scanIoTest.c scanIoTest_SRCS += dbTestIoc_registerRecordDeviceDriver.cpp @@ -200,7 +207,9 @@ include $(TOP)/configure/RULES arrRecord$(DEP): $(COMMON_DIR)/arrRecord.h dbCaLinkTest$(DEP): $(COMMON_DIR)/xRecord.h $(COMMON_DIR)/arrRecord.h +dbDbLinkTest$(DEP): $(COMMON_DIR)/xRecord.h dbPutLinkTest$(DEP): $(COMMON_DIR)/xRecord.h +dbPutGetTest$(DEP): $(COMMON_DIR)/xRecord.h dbStressLock$(DEP): $(COMMON_DIR)/xRecord.h devx$(DEP): $(COMMON_DIR)/xRecord.h scanIoTest$(DEP): $(COMMON_DIR)/xRecord.h diff --git a/modules/database/test/ioc/db/callbackParallelTest.c b/modules/database/test/ioc/db/callbackParallelTest.c index 731ed361b..7955fb6a1 100644 --- a/modules/database/test/ioc/db/callbackParallelTest.c +++ b/modules/database/test/ioc/db/callbackParallelTest.c @@ -54,7 +54,7 @@ typedef struct myPvt { int resultFail; } myPvt; -epicsEventId finished; +static epicsEventId finished; static void myCallback(epicsCallback *pCallback) { diff --git a/modules/database/test/ioc/db/callbackTest.c b/modules/database/test/ioc/db/callbackTest.c index e83943b4a..2863720f0 100644 --- a/modules/database/test/ioc/db/callbackTest.c +++ b/modules/database/test/ioc/db/callbackTest.c @@ -54,7 +54,7 @@ typedef struct myPvt { int resultFail; } myPvt; -epicsEventId finished; +static epicsEventId finished; static void myCallback(epicsCallback *pCallback) diff --git a/modules/database/test/ioc/db/dbCaLinkTest.c b/modules/database/test/ioc/db/dbCaLinkTest.c index 7916dd1eb..b433db9c6 100644 --- a/modules/database/test/ioc/db/dbCaLinkTest.c +++ b/modules/database/test/ioc/db/dbCaLinkTest.c @@ -27,6 +27,7 @@ #include "dbAccess.h" #include "epicsStdio.h" #include "dbEvent.h" +#include "shareLib.h" /* Declarations from cadef.h and db_access.h which we can't include here */ typedef void * chid; diff --git a/modules/database/test/ioc/db/dbDbLinkTest.c b/modules/database/test/ioc/db/dbDbLinkTest.c new file mode 100644 index 000000000..489df4daf --- /dev/null +++ b/modules/database/test/ioc/db/dbDbLinkTest.c @@ -0,0 +1,136 @@ +/*************************************************************************\ + * Copyright (c) 2020 Michael Davidsaver + * SPDX-License-Identifier: EPICS + * EPICS BASE is distributed subject to a Software License Agreement found + * in file LICENSE that is included with this distribution. + \*************************************************************************/ + +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include "xRecord.h" + +void dbTestIoc_registerRecordDeviceDriver(struct dbBase *); + +static +void checkTime(void) +{ + epicsTimeStamp stamp; + epicsUTag tag; + + dbCommon* target = testdbRecordPtr("target"); + dbCommon* src = testdbRecordPtr("src"); + + testDiag("checkTime()"); + + dbScanLock(target); + target->time.secPastEpoch = 0x12345678; + target->time.nsec = 0x9abcdef0; + target->utag = 0xdeadbeef; + dbScanUnlock(target); + + dbScanLock(src); + testOk1(0==dbGetTimeStamp(dbGetDevLink(src), &stamp)); + dbScanUnlock(src); + + testOk1(stamp.secPastEpoch==0x12345678); + testOk1(stamp.nsec==0x9abcdef0); + stamp.secPastEpoch = 0; + stamp.nsec = 0; + + dbScanLock(src); + testOk1(0==dbGetTimeStampTag(dbGetDevLink(src), &stamp, &tag)); + dbScanUnlock(src); + + testOk1(stamp.secPastEpoch==0x12345678); + testOk1(stamp.nsec==0x9abcdef0); + testOk1(tag==0xdeadbeef); +} + +static +void alarmProc(xRecord *prec) +{ + recGblSetSevrMsg(prec, READ_ALARM, MAJOR_ALARM, "a %s", "message"); + prec->val = 0; +} + +static +void checkAlarm(void) +{ + epicsEnum16 stat, sevr; + + xRecord* target = (xRecord*)testdbRecordPtr("target"); + dbCommon* src = testdbRecordPtr("src"); + + char amsg[sizeof(src->amsg)]; + + testDiag("checkAlarm()"); + + dbScanLock((dbCommon*)target); + target->clbk = &alarmProc; + dbProcess((dbCommon*)target); + target->clbk = NULL; + dbScanUnlock((dbCommon*)target); + + dbScanLock(src); + testOk1(0==dbGetAlarm(dbGetDevLink(src), &stat, &sevr)); + dbScanUnlock(src); + + testOk1(stat==READ_ALARM); + testOk1(sevr==MAJOR_ALARM); + stat = sevr = 0; + + dbScanLock(src); + testOk1(0==dbGetAlarmMsg(dbGetDevLink(src), &stat, &sevr, amsg, sizeof(amsg))); + dbScanUnlock(src); + + testOk1(stat==READ_ALARM); + testOk1(sevr==MAJOR_ALARM); + testOk1(strcmp(amsg, "a message")==0); + stat = sevr = 0; + memset(amsg, 0, sizeof(amsg)); + + dbScanLock(src); + testOk1(0==dbGetAlarmMsg(dbGetDevLink(src), &stat, &sevr, amsg, 5)); + dbScanUnlock(src); + + testOk1(stat==READ_ALARM); + testOk1(sevr==MAJOR_ALARM); + testOk1(strcmp(amsg, "a me")==0); +} + +MAIN(dbDbLinkTest) +{ + testPlan(18); + + testdbPrepare(); + + testdbReadDatabase("dbTestIoc.dbd", NULL, NULL); + + dbTestIoc_registerRecordDeviceDriver(pdbbase); + + testdbReadDatabase("dbDbLinkTest.db", NULL, NULL); + + eltc(0); + testIocInitOk(); + eltc(1); + + checkTime(); + checkAlarm(); + + testIocShutdownOk(); + + testdbCleanup(); + + return testDone(); +} diff --git a/modules/database/test/ioc/db/dbDbLinkTest.db b/modules/database/test/ioc/db/dbDbLinkTest.db new file mode 100644 index 000000000..39ce5d8ae --- /dev/null +++ b/modules/database/test/ioc/db/dbDbLinkTest.db @@ -0,0 +1,6 @@ +record(x, "target") { +} + +record(x, "src") { + field(INP, "target.VAL") +} diff --git a/modules/database/test/ioc/db/dbPutGetTest.c b/modules/database/test/ioc/db/dbPutGetTest.c index 742318e3a..e1492a5a9 100644 --- a/modules/database/test/ioc/db/dbPutGetTest.c +++ b/modules/database/test/ioc/db/dbPutGetTest.c @@ -7,12 +7,186 @@ #include #include +#include #include #include #include +#include +#include #include #include +#include "xRecord.h" + +typedef struct { + DBRstatus + DBRamsg + DBRunits + DBRprecision + DBRtime + DBRutag + DBRgrDouble + DBRctrlDouble + DBRalDouble +} dbMetaDouble; + +enum {dbMetaDoubleMask = DBR_STATUS | DBR_AMSG | DBR_UNITS | DBR_PRECISION | DBR_TIME | DBR_UTAG | DBR_GR_DOUBLE | DBR_CTRL_DOUBLE | DBR_AL_DOUBLE}; + +static +void testdbMetaDoubleSizes(void) +{ + dbMetaDouble meta; + size_t pos=0; + + testDiag("dbMetaDouble may not have padding"); +#define testOffset(FLD) do {\ + testOk(offsetof(dbMetaDouble, FLD)==pos, "offset(meta, " #FLD "), %u == %u", (unsigned)offsetof(dbMetaDouble, FLD), (unsigned)pos); \ + pos += sizeof(meta.FLD); \ +}while(0) + + testOffset(status); + testOffset(severity); + testOffset(acks); + testOffset(ackt); + testOffset(amsg); + testOffset(units); + testOffset(precision); + testOffset(time); + testOffset(utag); + testOffset(upper_disp_limit); + testOffset(lower_disp_limit); + testOffset(upper_ctrl_limit); + testOffset(lower_ctrl_limit); + testOffset(upper_alarm_limit); + testOffset(upper_warning_limit); + testOffset(lower_warning_limit); + testOffset(lower_alarm_limit); +#undef testOffset + testOk(sizeof(dbMetaDouble)==pos, "sizeof(dbMetaDouble), %u == %u", (unsigned)sizeof(dbMetaDouble), (unsigned)pos); +} + +static +void checkDoubleGet(dbChannel *chan, db_field_log* pfl) +{ + dbMetaDouble meta; + long options = (long)dbMetaDoubleMask; + long nReq = 0; + long status; + + status=dbChannelGet(chan, DBF_DOUBLE, &meta, &options, &nReq, pfl); + testOk(status==0, "dbGet OTST : %ld", status); + + testOk1(meta.severity==INVALID_ALARM); + testOk1(meta.status==UDF_ALARM); + testOk1(meta.acks==MAJOR_ALARM); + testOk1(meta.ackt==1); + testOk1(strncmp(meta.amsg, "oops", DB_UNITS_SIZE)==0); + testOk1(meta.time.secPastEpoch==0x12345678); + testOk1(meta.time.nsec==0x90abcdef); + testOk1(meta.utag==0x10203040); + testOk1(meta.precision.dp==0x12345678); + testOk1(strncmp(meta.units, "arbitrary", DB_UNITS_SIZE)==0); +#define limitEq(UL, FL, VAL) testOk(meta.UL ## _ ## FL ## _limit == (VAL), #UL "_" #FL "_limit (%f) == %f", meta.UL ## _ ## FL ## _limit, VAL) + limitEq(lower, disp, 10000000.0-1.0); + limitEq(upper, disp, 10000000.0+1.0); + limitEq(lower, ctrl, 10000000.0-2.0); + limitEq(upper, ctrl, 10000000.0+2.0); + limitEq(lower, alarm, 10000000.0-3.0); + limitEq(lower, warning, 10000000.0-4.0); + limitEq(upper, warning, 10000000.0+4.0); + limitEq(upper, alarm, 10000000.0+3.0); +#undef limitEq + +} + +static +void testdbMetaDoubleGet(void) +{ + xRecord* prec = (xRecord*)testdbRecordPtr("recmeta"); + dbChannel *chan = dbChannelCreate("recmeta.OTST"); + db_field_log *pfl; + evSubscrip evsub; + long status; + dbMetaDouble meta; + + STATIC_ASSERT(sizeof(meta.amsg)==sizeof(prec->amsg)); + STATIC_ASSERT(sizeof(meta.amsg)==sizeof(pfl->amsg)); + + if(!chan) + testAbort("Missing recmeta OTST"); + if((status=dbChannelOpen(chan))!=0) + testAbort("can't open recmeta OTST : %ld", status); + + dbScanLock((dbCommon*)prec); + /* ensure that all meta-data has different non-zero values */ + prec->otst = 10000000.0; + prec->sevr = INVALID_ALARM; + prec->stat = UDF_ALARM; + strcpy(prec->amsg, "oops"); + prec->acks = MAJOR_ALARM; + prec->time.secPastEpoch = 0x12345678; + prec->time.nsec = 0x90abcdef; + prec->utag = 0x10203040; + + testDiag("dbGet directly from record"); + checkDoubleGet(chan, NULL); + + testDiag("dbGet from field log"); + + /* bare minimum init for db_create_event_log() */ + memset(&evsub, 0, sizeof(evsub)); + evsub.chan = chan; + evsub.useValque = 1; + pfl = db_create_event_log(&evsub); + /* spoil things which should now come from field log */ + prec->sevr = 0; + prec->stat = 0; + strcpy(prec->amsg, "invalid"); + prec->time.secPastEpoch = 0xdeadbeef; + prec->time.nsec = 0xdeadbeef; + prec->utag = 0xdeadbeef; + + /* never any filters, so skip pre/post */ + checkDoubleGet(chan, pfl); + db_delete_field_log(pfl); + + dbScanUnlock((dbCommon*)prec); +} + +typedef struct { + DBRstatus + DBRamsg + DBRtime + DBRutag + DBRenumStrs +} dbMetaEnum; + +static +void testdbMetaEnumSizes(void) +{ + dbMetaEnum meta; + size_t pos=0; + + testDiag("dbMetaEnum may not have implicit padding"); +#define testOffset(FLD) do {\ + testOk(offsetof(dbMetaEnum, FLD)==pos, "offset(meta, " #FLD "), %u == %u", (unsigned)offsetof(dbMetaEnum, FLD), (unsigned)pos); \ + pos += sizeof(meta.FLD); \ +}while(0) + + testOffset(status); + testOffset(severity); + testOffset(acks); + testOffset(ackt); + testOffset(amsg); + testOffset(time); + testOffset(utag); + testOffset(no_str); + testOffset(padenumStrs); + testOffset(strs); +#undef testOffset + testOk(sizeof(dbMetaEnum)==pos, "sizeof(dbMetaEnum), %u == %u", (unsigned)sizeof(dbMetaEnum), (unsigned)pos); +} + static void testdbGetStringEqual(const char *pv, const char *expected) { @@ -143,9 +317,12 @@ void dbTestIoc_registerRecordDeviceDriver(struct dbBase *); MAIN(dbPutGet) { - testPlan(44); + testPlan(111); testdbPrepare(); + testdbMetaDoubleSizes(); + testdbMetaEnumSizes(); + testdbReadDatabase("dbTestIoc.dbd", NULL, NULL); dbTestIoc_registerRecordDeviceDriver(pdbbase); testdbReadDatabase("dbPutGetTest.db", NULL, NULL); @@ -158,6 +335,8 @@ MAIN(dbPutGet) testIocInitOk(); eltc(1); + testdbMetaDoubleGet(); + testLongLink(); testLongAttr(); testLongField(); diff --git a/modules/database/test/ioc/db/dbPutGetTest.db b/modules/database/test/ioc/db/dbPutGetTest.db index 816dc73f0..68485e4ba 100644 --- a/modules/database/test/ioc/db/dbPutGetTest.db +++ b/modules/database/test/ioc/db/dbPutGetTest.db @@ -44,3 +44,5 @@ record(arr, "arr") { field(FTVL, "ULONG") field(NELM, "10") } + +record(x, "recmeta") {} diff --git a/modules/database/test/ioc/db/epicsRunDbTests.c b/modules/database/test/ioc/db/epicsRunDbTests.c index 602b15e05..6c7ce84c9 100644 --- a/modules/database/test/ioc/db/epicsRunDbTests.c +++ b/modules/database/test/ioc/db/epicsRunDbTests.c @@ -30,6 +30,7 @@ int dbLockTest(void); int dbPutLinkTest(void); int dbStaticTest(void); int dbCaLinkTest(void); +int dbDbLinkTest(void); int testDbChannel(void); int chfPluginTest(void); int arrShorthandTest(void); @@ -52,6 +53,7 @@ void epicsRunDbTests(void) runTest(dbPutLinkTest); runTest(dbStaticTest); runTest(dbCaLinkTest); + runTest(dbDbLinkTest); runTest(testDbChannel); runTest(arrShorthandTest); runTest(recGblCheckDeadbandTest); diff --git a/modules/database/test/ioc/db/xRecord.c b/modules/database/test/ioc/db/xRecord.c index 7cbcf1508..83ca9b15c 100644 --- a/modules/database/test/ioc/db/xRecord.c +++ b/modules/database/test/ioc/db/xRecord.c @@ -76,7 +76,82 @@ static long process(struct dbCommon *pcommon) return ret; } +long get_units(struct dbAddr *paddr, char *units) +{ + if(dbGetFieldIndex(paddr)==xRecordOTST) { + strncpy(units, "arbitrary", DB_UNITS_SIZE); + } + return 0; +} + +long get_precision(const struct dbAddr *paddr, long *precision) +{ + if(dbGetFieldIndex(paddr)==xRecordOTST) { + *precision = 0x12345678; + } + return 0; +} + +long get_graphic_double(struct dbAddr *paddr, struct dbr_grDouble *p) +{ + xRecord *prec = (xRecord *)paddr->precord; + if(dbGetFieldIndex(paddr)==xRecordOTST) { + p->lower_disp_limit = prec->otst-1.0; + p->upper_disp_limit = prec->otst+1.0; + } + return 0; +} + +long get_control_double(struct dbAddr *paddr, struct dbr_ctrlDouble *p) +{ + xRecord *prec = (xRecord *)paddr->precord; + if(dbGetFieldIndex(paddr)==xRecordOTST) { + p->lower_ctrl_limit = prec->otst-2.0; + p->upper_ctrl_limit = prec->otst+2.0; + } + return 0; +} +long get_alarm_double(struct dbAddr *paddr, struct dbr_alDouble *p) +{ + xRecord *prec = (xRecord *)paddr->precord; + if(dbGetFieldIndex(paddr)==xRecordOTST) { + p->lower_alarm_limit = prec->otst-3.0; + p->lower_warning_limit = prec->otst-4.0; + p->upper_warning_limit = prec->otst+4.0; + p->upper_alarm_limit = prec->otst+3.0; + } + return 0; +} + +#define report NULL +#define initialize NULL +#define special NULL +#define get_value NULL +#define cvt_dbaddr NULL +#define get_array_info NULL +#define put_array_info NULL +#define get_enum_str NULL +#define get_enum_strs NULL +#define put_enum_str NULL + static rset xRSET = { - RSETNUMBER, NULL, NULL, init_record, process + RSETNUMBER, + report, + initialize, + init_record, + process, + special, + get_value, + cvt_dbaddr, + get_array_info, + put_array_info, + get_units, + get_precision, + get_enum_str, + get_enum_strs, + put_enum_str, + get_graphic_double, + get_control_double, + get_alarm_double }; epicsExportAddress(rset,xRSET); diff --git a/modules/database/test/ioc/db/xRecord.dbd b/modules/database/test/ioc/db/xRecord.dbd index 25013c042..13fcb3f3e 100644 --- a/modules/database/test/ioc/db/xRecord.dbd +++ b/modules/database/test/ioc/db/xRecord.dbd @@ -46,4 +46,8 @@ recordtype(x) { special(SPC_NOMOD) extra("void (*clbk)(struct xRecord*)") } + field(OTST, DBF_DOUBLE) { + prompt("dbGet() options test") + special(SPC_NOMOD) + } } diff --git a/modules/database/test/std/rec/Makefile b/modules/database/test/std/rec/Makefile index e8c546442..52db82400 100644 --- a/modules/database/test/std/rec/Makefile +++ b/modules/database/test/std/rec/Makefile @@ -175,8 +175,12 @@ dbHeaderTestxx_SRCS += dbHeaderTestxx.cpp ifeq ($(T_A),$(EPICS_HOST_ARCH)) # Host-only tests of softIoc/softIocPVA, caget and pvget (if present) +# Unfortunately hangs too often on CI systems: +ifndef CI TESTS += netget endif +endif + # epicsRunRecordTests runs all the test programs in a known working order. testHarness_SRCS += epicsRunRecordTests.c diff --git a/modules/database/test/std/rec/asTest.c b/modules/database/test/std/rec/asTest.c index 3a956efcb..448a762fd 100644 --- a/modules/database/test/std/rec/asTest.c +++ b/modules/database/test/std/rec/asTest.c @@ -37,6 +37,8 @@ #include "testMain.h" +#include "shareLib.h" + epicsShareFunc void testRestore(void); #include "epicsExport.h" diff --git a/modules/database/test/std/rec/netget.plt b/modules/database/test/std/rec/netget.plt index 075717d78..af2787967 100644 --- a/modules/database/test/std/rec/netget.plt +++ b/modules/database/test/std/rec/netget.plt @@ -3,13 +3,16 @@ use strict; use warnings; +use if $^O eq 'MSWin32', "Win32::Process"; +use if $^O eq 'MSWin32', "Win32"; + use lib '@TOP@/lib/perl'; use Test::More tests => 3; use EPICS::IOC; # Set to 1 to echo all IOC and client communications -my $debug = 1; +my $debug = 0; $ENV{HARNESS_ACTIVE} = 1 if scalar @ARGV && shift eq '-tap'; @@ -35,7 +38,7 @@ $ioc->debug($debug); $SIG{__DIE__} = $SIG{INT} = $SIG{QUIT} = sub { $ioc->exit; - BAIL_OUT('Caught signal'); + BAIL_OUT("Caught signal: $_[0]"); }; @@ -50,11 +53,21 @@ sub kill_bail { } sub watchdog (&$$) { - my ($do, $timeout, $abort) = @_; - $SIG{ALRM} = $abort; - alarm $timeout; - &$do; - alarm 0; + my ($code, $timeout, $fail) = @_; + my $bark = "Woof $$\n"; + my $result; + eval { + local $SIG{__DIE__}; + local $SIG{ALRM} = sub { die $bark }; + alarm $timeout; + $result = &$code; + alarm 0; + }; + if ($@) { + die if $@ ne $bark; + $result = &$fail; + } + return $result; } @@ -90,19 +103,6 @@ like($version, qr/^ \d+ \. \d+ \. \d+ /x, "Got BaseVersion '$version' from iocsh"); -# Client Tests - -my $client = EPICS::IOC->new; -$client->debug($debug); - -sub close_client { - my $doing = shift; - return sub { - diag("Timeout $doing"); - $client->close; - } -} - # Channel Access SKIP: { @@ -119,17 +119,9 @@ SKIP: { # CA Client test - watchdog { - $client->start($caget, '-w5', $pv); - my $caVersion = $client->_getline; - like($caVersion, qr/^ $pv \s+ \Q$version\E $/x, - 'Got same BaseVersion from caget'); - my @errors = $client->_geterrors; - note("Errors from caget:\n", - map(" $_\n", @errors)) - if scalar @errors; - $client->close; - } 15, close_client('doing caget'); + my $caVersion = qx_timeout(15, "$caget -w5 $pv"); + like($caVersion, qr/^ $pv \s+ \Q$version\E $/x, + 'Got same BaseVersion from caget'); } @@ -152,17 +144,71 @@ SKIP: { # PVA Client test - watchdog { - $client->start($pvget, '-w5', $pv); - my $pvaVersion = $client->_getline; - like($pvaVersion, qr/^ $pv \s .* \Q$version\E \s* $/x, - 'Got same BaseVersion from pvget'); - my @errors = $client->_geterrors; - note("Errors from pvget:\n", - map(" $_\n", @errors)) - if scalar @errors; - $client->close; - } 10, close_client('doing pvget'); + my $pvaVersion = qx_timeout(15, "$pvget -w5 $pv"); + like($pvaVersion, qr/^ $pv \s .* \Q$version\E \s* $/x, + 'Got same BaseVersion from pvget'); } $ioc->exit; + + +# Process timeout utilities + +sub system_timeout { + my ($timeout, $cmdline) = @_; + my $status; + if ($^O eq 'MSWin32') { + my $proc; + (my $app) = split ' ', $cmdline; + if (! Win32::Process::Create($proc, $app, $cmdline, + 1, &Win32::Process::NORMAL_PRIORITY_CLASS, '.')) { + my $err = Win32::FormatMessage(Win32::GetLastError()); + die "Can't create Process for '$cmdline': $err\n"; + } + if (! $proc->Wait(1000 * $timeout)) { + $proc->Kill(1); + note("Timed out '$cmdline' after $timeout seconds\n"); + } + my $status; + $proc->GetExitCode($status); + return $status; + } + else { + my $pid; + $status = watchdog { + $pid = fork(); + die "Can't fork: $!\n" + unless defined $pid; + exec $cmdline + or die "Can't exec: $!\n" + unless $pid; + waitpid $pid, 0; + return $? >> 8; + } $timeout, sub { + kill 9, $pid if $pid; + note("Timed out '$cmdline' after $timeout seconds\n"); + return -2; + }; + } + return $status; +} + +sub qx_timeout { + my ($timeout, $cmdline) = @_; + open(my $stdout, '>&STDOUT') + or die "Can't save STDOUT: $!\n"; + my $outfile = "stdout-$$.txt"; + unlink $outfile; + open STDOUT, '>', $outfile; + my $text; + if (system_timeout($timeout, $cmdline) == 0 && -r $outfile) { + open(my $file, '<', $outfile) + or die "Can't open $outfile: $!\n"; + $text = join '', <$file>; + close $file; + } + open(STDOUT, '>&', $stdout) + or die "Can't restore STDOUT: $!\n"; + unlink $outfile; + return $text; +} diff --git a/modules/database/test/std/rec/simmTest.c b/modules/database/test/std/rec/simmTest.c index f755196de..14deb7a1f 100644 --- a/modules/database/test/std/rec/simmTest.c +++ b/modules/database/test/std/rec/simmTest.c @@ -12,9 +12,11 @@ #include #include #include +#include #include #include #include +#include #include "recSup.h" #include "aiRecord.h" @@ -428,6 +430,15 @@ void testSiolWrite(const char *name, * Asynchronous processing using simm:DELAY */ +static void +ping(CALLBACK *pcb) +{ + epicsEventId ev; + callbackGetUser(ev, pcb); + + epicsEventMustTrigger(ev); +} + static void testSimmDelay(const char *name, epicsFloat64 *psdly, @@ -436,6 +447,14 @@ void testSimmDelay(const char *name, epicsTimeStamp now; const double delay = 0.01; /* 10 ms */ double diff; + epicsEventId poked; + CALLBACK cb; + + memset(&cb, 0, sizeof(CALLBACK)); + poked = epicsEventMustCreate(epicsEventEmpty); + callbackSetCallback(ping, &cb); + callbackSetPriority(priorityLow, &cb); + callbackSetUser(poked, &cb); testDiag("## Asynchronous processing with simm:DELAY ##"); @@ -457,14 +476,11 @@ void testSimmDelay(const char *name, testdbPutFieldOk(namePROC, DBR_LONG, 0); testdbGetFieldEqual(namePACT, DBR_USHORT, 1); epicsTimeGetCurrent(&now); - epicsThreadSleep(1.75*delay); - if(testImpreciseTiming()) - testTodoBegin("imprecise"); + callbackRequestDelayed(&cb, 1.5 * delay); + epicsEventWait(poked); testdbGetFieldEqual(namePACT, DBR_USHORT, 0); diff = epicsTimeDiffInSeconds(mytime, &now); testOk(diff >= 0.0, "time stamp is recent (%.9f sec)", diff); - if(testImpreciseTiming()) - testTodoEnd(); /* Reset delay */ *psdly = -1.; diff --git a/modules/database/test/tools/Menu.plt b/modules/database/test/tools/Menu.plt index 25b0c2020..8e667c833 100644 --- a/modules/database/test/tools/Menu.plt +++ b/modules/database/test/tools/Menu.plt @@ -30,10 +30,12 @@ is_deeply $menu->choice(2), undef, 'Third choice undefined'; like $menu->toDeclaration, qr/ ^ \s* \# \s* ifndef \s+ test_NUM_CHOICES \s* \n + \s* \/\*\* [^*]* \*\/ \s* \n \s* typedef \s+ enum \s+ \{ \s* \n - \s* ch1 \s+ \/\* [^*]* \*\/, \s* \n - \s* ch2 \s+ \/\* [^*]* \*\/ \s* \n + \s* ch1 \s+ \/\*\* [^*]* \*\/, \s* \n + \s* ch2 \s+ \/\*\* [^*]* \*\/ \s* \n \s* \} \s* test \s* ; \s* \n + \s* \/\*\* [^*]* \*\/ \s* \n \s* \# \s* define \s+ test_NUM_CHOICES \s+ 2 \s* \n \s* \# \s* endif \s* \n \s* $ /x, 'C declaration'; diff --git a/modules/libcom/RTEMS/Makefile b/modules/libcom/RTEMS/Makefile index b46889db1..c939563fc 100644 --- a/modules/libcom/RTEMS/Makefile +++ b/modules/libcom/RTEMS/Makefile @@ -11,10 +11,14 @@ TOP = ../../.. include $(TOP)/configure/CONFIG include $(TOP)/configure/CONFIG_LIBCOM_VERSION +# check check +SRC_DIRS += ../$(OS_API) + PERL_SCRIPTS += epicsMakeMemFs.pl INC += epicsRtemsInitHooks.h INC += epicsMemFs.h +INC += epicsNtp.h ifeq ($(RTEMS_QEMU_FIXUPS),YES) rtems_init_CPPFLAGS += -DQEMU_FIXUPS @@ -27,11 +31,14 @@ rtemsCom_SRCS += setBootConfigFromNVRAM.c rtemsCom_SRCS += epicsRtemsInitHookPre.c rtemsCom_SRCS += epicsRtemsInitHookPost.c rtemsCom_SRCS += epicsMemFs.c +rtemsCom_SRCS += epicsNtp.c -ifeq ($(RTEMS_BSP),pc386) +ifeq ($(RTEMS_TARGET_CPU),i386) rtemsCom_SRCS += ne2kpci.c endif +rtems_config_CPPFLAGS += -DBSP_$(RTEMS_BSP) + LIBRARY_RTEMS = rtemsCom # shared library ABI version. diff --git a/modules/libcom/RTEMS/epicsNtp.c b/modules/libcom/RTEMS/epicsNtp.c new file mode 100644 index 000000000..760d62610 --- /dev/null +++ b/modules/libcom/RTEMS/epicsNtp.c @@ -0,0 +1,85 @@ +/*************************************************************************\ +* (C) 2014 David Lettier. +* http://www.lettier.com/ +* SPDX-License-Identifier: BSD-3-Clause +\*************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "epicsNtp.h" + +int epicsNtpGetTime(char *ntpIp, struct timespec *now) +{ + + int sockfd, n; // Socket file descriptor and the n return result from writing/reading from the socket. + int portno = 123; // NTP UDP port number. + + // Create and zero out the packet. All 48 bytes worth. + ntp_packet packet = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + memset( &packet, 0, sizeof( ntp_packet ) ); + // Set the first byte's bits to 00,011,011 for li = 0, vn = 3, and mode = 3. The rest will be left set to zero. + *( ( char * ) &packet + 0 ) = 0x1b; // Represents 27 in base 10 or 00011011 in base 2. + + // Create a UDP socket, convert the host-name to an IP address, set the port number, + // connect to the server, send the packet, and then read in the return packet. + struct sockaddr_in serv_addr; // Server address data structure. + + sockfd = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ); // Create a UDP socket. + + if ( sockfd < 0 ) { + perror( "epicsNtpGetTime" ); + return -1; + } + + // Zero out the server address structure. + memset( ( char* ) &serv_addr, 0, sizeof( serv_addr ) ); + + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = inet_addr(ntpIp); + + serv_addr.sin_port = htons( portno ); + + // Call up the server using its IP address and port number. + if ( connect( sockfd, ( struct sockaddr * ) &serv_addr, sizeof( serv_addr) ) < 0 ) { + perror( "epicsNtpGetTime" ); + return -1; + } + + // Send it the NTP packet it wants. If n == -1, it failed. + n = write( sockfd, ( char* ) &packet, sizeof( ntp_packet ) ); + if ( n < 0 ) { + perror( "epicsNtpGetTime" ); + return -1; + } + +// Wait and receive the packet back from the server. If n == -1, it failed. + n = read( sockfd, ( char* ) &packet, sizeof( ntp_packet ) ); + if ( n < 0 ) { + perror( "epicsNtpGetTime" ); + return -1; + } + + // These two fields contain the time-stamp seconds as the packet left the NTP server. + // The number of seconds correspond to the seconds passed since 1900. + // ntohl() converts the bit/byte order from the network's to host's "endianness". + packet.txTm_s = ntohl( packet.txTm_s ); // Time-stamp seconds. + packet.txTm_f = ntohl( packet.txTm_f ); // Time-stamp fraction of a second. + + // Extract the 32 bits that represent the time-stamp seconds (since NTP epoch) from when the packet left the server. + // Subtract 70 years worth of seconds from the seconds since 1900. + // This leaves the seconds since the UNIX epoch of 1970. + // (1900)------------------(1970)**************************************(Time Packet Left the Server) + time_t txTm = ( time_t ) ( packet.txTm_s - NTP_TIMESTAMP_DELTA ); + now->tv_sec = txTm; + return 0; +} diff --git a/modules/libcom/RTEMS/epicsNtp.h b/modules/libcom/RTEMS/epicsNtp.h new file mode 100644 index 000000000..062970f30 --- /dev/null +++ b/modules/libcom/RTEMS/epicsNtp.h @@ -0,0 +1,42 @@ +/*************************************************************************\ +* (C) 2014 David Lettier. +* http://www.lettier.com/ +* SPDX-License-Identifier: BSD-3-Clause +\*************************************************************************/ +#ifndef EPICSNTP_H +#define EPICSNTP_H + +#define NTP_TIMESTAMP_DELTA 2208988800ull + +int epicsNtpGetTime(char *ntpIp, struct timespec *now); + +typedef struct +{ + + uint8_t li_vn_mode; // Eight bits. li, vn, and mode. + // li. Two bits. Leap indicator. + // vn. Three bits. Version number of the protocol. + // mode. Three bits. Client will pick mode 3 for client. + + uint8_t stratum; // Eight bits. Stratum level of the local clock. + uint8_t poll; // Eight bits. Maximum interval between successive messages. + uint8_t precision; // Eight bits. Precision of the local clock. + + uint32_t rootDelay; // 32 bits. Total round trip delay time. + uint32_t rootDispersion; // 32 bits. Max error aloud from primary clock source. + uint32_t refId; // 32 bits. Reference clock identifier. + + uint32_t refTm_s; // 32 bits. Reference time-stamp seconds. + uint32_t refTm_f; // 32 bits. Reference time-stamp fraction of a second. + + uint32_t origTm_s; // 32 bits. Originate time-stamp seconds. + uint32_t origTm_f; // 32 bits. Originate time-stamp fraction of a second. + + uint32_t rxTm_s; // 32 bits. Received time-stamp seconds. + uint32_t rxTm_f; // 32 bits. Received time-stamp fraction of a second. + + uint32_t txTm_s; // 32 bits and the most important field the client cares about. Transmit time-stamp seconds. + uint32_t txTm_f; // 32 bits. Transmit time-stamp fraction of a second. + +} ntp_packet; // Total: 384 bits or 48 bytes. +#endif // EPICSNTP_H diff --git a/modules/libcom/RTEMS/epicsRtemsInitHookPost.c b/modules/libcom/RTEMS/epicsRtemsInitHookPost.c index ba14aae4c..674c32662 100644 --- a/modules/libcom/RTEMS/epicsRtemsInitHookPost.c +++ b/modules/libcom/RTEMS/epicsRtemsInitHookPost.c @@ -10,9 +10,10 @@ * Dummy version -- use if application does not provide its own version */ #include "epicsRtemsInitHooks.h" - +#ifdef RTEMS_LEGACY_STACK int epicsRtemsInitPostSetBootConfigFromNVRAM(struct rtems_bsdnet_config *config) { return 0; } +#endif diff --git a/modules/libcom/RTEMS/epicsRtemsInitHookPre.c b/modules/libcom/RTEMS/epicsRtemsInitHookPre.c index 4c8544745..b84fa7ac3 100644 --- a/modules/libcom/RTEMS/epicsRtemsInitHookPre.c +++ b/modules/libcom/RTEMS/epicsRtemsInitHookPre.c @@ -10,9 +10,10 @@ * Dummy version -- use if application does not provide its own version */ #include "epicsRtemsInitHooks.h" - +#ifdef RTEMS_LEGACY_STACK int epicsRtemsInitPreSetBootConfigFromNVRAM(struct rtems_bsdnet_config *config) { return 0; } +#endif diff --git a/modules/libcom/RTEMS/epicsRtemsInitHooks.h b/modules/libcom/RTEMS/epicsRtemsInitHooks.h index cdbc74315..e08b7fa35 100644 --- a/modules/libcom/RTEMS/epicsRtemsInitHooks.h +++ b/modules/libcom/RTEMS/epicsRtemsInitHooks.h @@ -10,7 +10,9 @@ * Hooks into RTEMS startup code */ #include +#ifdef RTEMS_LEGACY_STACK #include +#endif extern char *env_nfsServer; extern char *env_nfsPath; @@ -23,8 +25,10 @@ extern "C" { /* * Return 0 for success, non-zero for failure (will cause panic) */ +#ifdef RTEMS_LEGACY_STACK int epicsRtemsInitPreSetBootConfigFromNVRAM(struct rtems_bsdnet_config *config); int epicsRtemsInitPostSetBootConfigFromNVRAM(struct rtems_bsdnet_config *config); +#endif /* Return 0 if local file system was setup, or non-zero (will fall back to network */ int epicsRtemsMountLocalFilesystem(char **argv); diff --git a/modules/libcom/RTEMS/posix/rtems_config.c b/modules/libcom/RTEMS/posix/rtems_config.c new file mode 100644 index 000000000..c9fa8a8d7 --- /dev/null +++ b/modules/libcom/RTEMS/posix/rtems_config.c @@ -0,0 +1,173 @@ +/*************************************************************************\ +* Copyright (c) 2002 The University of Saskatchewan +* EPICS BASE Versions 3.13.7 +* and higher are distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ +/* + * RTEMS configuration for EPICS + * Author: W. Eric Norum + * norume@aps.anl.gov + * (630) 252-4793 + */ + +#include + +/* + *********************************************************************** + * RTEMS CONFIGURATION * + *********************************************************************** + */ + +extern void *POSIX_Init(void *argument); + +#define CONFIGURE_POSIX_INIT_THREAD_TABLE +#define CONFIGURE_POSIX_INIT_THREAD_ENTRY_POINT POSIX_Init +#define CONFIGURE_POSIX_INIT_THREAD_STACK_SIZE (64*1024) + +#define CONFIGURE_MAXIMUM_PERIODS 5 +#define CONFIGURE_MICROSECONDS_PER_TICK 10000 +#define CONFIGURE_MALLOC_STATISTICS 1 +/* MINIMUM_STACK_SIZE == 8K */ +#define CONFIGURE_EXTRA_TASK_STACKS (4000 * RTEMS_MINIMUM_STACK_SIZE) + +#if __RTEMS_MAJOR__ > 4 +#define CONFIGURE_FILESYSTEM_DEVFS +#define CONFIGURE_FILESYSTEM_TFTPFS +#endif +#define CONFIGURE_FILESYSTEM_NFS +#define CONFIGURE_FILESYSTEM_IMFS + +#ifndef RTEMS_LEGACY_STACK +#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM +/* + * Configure LibBSD. + */ +//#define RTEMS_BSD_CONFIG_NET_PF_UNIX +//#define RTEMS_BSD_CONFIG_NET_IF_BRIDGE +//#define RTEMS_BSD_CONFIG_NET_IF_LAGG +//#define RTEMS_BSD_CONFIG_NET_IF_VLAN +#define RTEMS_BSD_CONFIG_BSP_CONFIG +#define RTEMS_BSD_CONFIG_INIT +#include +#endif // not LEGACY_STACK + +/* + * Configure RTEMS. + */ +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_STUB_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_ZERO_DRIVER + +/* Max FDs cannot exceed FD_SETSIZE from newlib (64) */ +#define CONFIGURE_MAXIMUM_FILE_DESCRIPTORS 64 +#define CONFIGURE_IMFS_ENABLE_MKFIFO 2 + +#define CONFIGURE_MAXIMUM_NFS_MOUNTS 3 +#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 5 + +#define CONFIGURE_UNLIMITED_ALLOCATION_SIZE 32 +#define CONFIGURE_UNLIMITED_OBJECTS +#define CONFIGURE_UNIFIED_WORK_AREAS + +#define CONFIGURE_STACK_CHECKER_ENABLED + +#define CONFIGURE_APPLICATION_NEEDS_LIBBLOCK +#define CONFIGURE_BDBUF_BUFFER_MAX_SIZE (64 * 1024) +#define CONFIGURE_BDBUF_MAX_READ_AHEAD_BLOCKS 4 +#define CONFIGURE_BDBUF_CACHE_MEMORY_SIZE (1 * 1024 * 1024) + +/* we are using POSIX_INIT needed by V4 +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE +#define CONFIGURE_INIT_TASK_STACK_SIZE (32 * 1024) +#define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES +#define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_FLOATING_POINT +#endif +*/ + +//#define RTEMS_PCI_CONFIG_LIB +//#define CONFIGURE_PCI_LIB PCI_LIB_AUTO + +#if __RTEMS_MAJOR__ > 4 +#define CONFIGURE_SHELL_COMMANDS_INIT + +#include + +#ifndef RTEMS_LEGACY_STACK +#include + +#define CONFIGURE_SHELL_USER_COMMANDS \ + &bsp_interrupt_shell_command, \ + &rtems_shell_HOSTNAME_Command, \ + &rtems_shell_PING_Command, \ + &rtems_shell_ROUTE_Command, \ + &rtems_shell_NETSTAT_Command, \ + &rtems_shell_IFCONFIG_Command, \ + &rtems_shell_TCPDUMP_Command, \ + &rtems_shell_PFCTL_Command, \ + &rtems_shell_SYSCTL_Command +#else // LEGACY_STACK: +#define CONFIGURE_SHELL_USER_COMMANDS \ + &bsp_interrupt_shell_command, \ + &rtems_shell_PING_Command, \ + &rtems_shell_ROUTE_Command, \ + &rtems_shell_IFCONFIG_Command +#endif + +#define CONFIGURE_SHELL_COMMAND_CPUUSE +#define CONFIGURE_SHELL_COMMAND_PERIODUSE +#define CONFIGURE_SHELL_COMMAND_STACKUSE +#define CONFIGURE_SHELL_COMMAND_PROFREPORT + +#define CONFIGURE_SHELL_COMMAND_CP +#define CONFIGURE_SHELL_COMMAND_PWD +#define CONFIGURE_SHELL_COMMAND_LS +#define CONFIGURE_SHELL_COMMAND_LN +#define CONFIGURE_SHELL_COMMAND_LSOF +#define CONFIGURE_SHELL_COMMAND_CHDIR +#define CONFIGURE_SHELL_COMMAND_CD +#define CONFIGURE_SHELL_COMMAND_MKDIR +#define CONFIGURE_SHELL_COMMAND_RMDIR +#define CONFIGURE_SHELL_COMMAND_CAT +#define CONFIGURE_SHELL_COMMAND_MV +#define CONFIGURE_SHELL_COMMAND_RM +#define CONFIGURE_SHELL_COMMAND_MALLOC_INFO +#define CONFIGURE_SHELL_COMMAND_SHUTDOWN + +#include +#define RTEMS_BSD_CONFIG_BSP_CONFIG +#define RTEMS_BSD_CONFIG_SERVICE_TELNETD +#define RTEMS_BSD_CONFIG_TELNETD_STACK_SIZE (16 * 1024) +#define RTEMS_BSD_CONFIG_SERVICE_FTPD +#define RTEMS_BSD_CONFIG_FIREWALL_PF +#else +#include +#endif // not LEGACY_STACK + +#if __RTEMS_MAJOR__ < 5 // still needed in Version 4? +#define CONFIGURE_MAXIMUM_TASKS rtems_resource_unlimited(30) +#endif + +#define CONFIGURE_MAXIMUM_DRIVERS 40 + +/* + * This should be made BSP dependent, not CPU dependent but I know of no + * appropriate conditionals to use. + * The new general time support makes including the RTC driver less important. + */ +#if !defined(mpc604) && !defined(__mc68040__) && !defined(__mcf5200__) && \ + !defined(mpc7455) && !defined(__arm__) && !defined(__nios2__) + /* don't have RTC code */ +#define CONFIGURE_APPLICATION_NEEDS_RTC_DRIVER +#endif + +#if defined(BSP_pc386) || defined(BSP_pc686) +#define RTEMS_BSD_CONFIG_DOMAIN_PAGE_MBUFS_SIZE (64 * 1024 * 1024) +#elif defined(BSP_qoriq_e500) +#define RTEMS_BSD_CONFIG_DOMAIN_PAGE_MBUFS_SIZE (32 * 1024 * 1024) +#endif + +#define CONFIGURE_INIT + +#include diff --git a/modules/libcom/RTEMS/posix/rtems_init.c b/modules/libcom/RTEMS/posix/rtems_init.c new file mode 100644 index 000000000..09c7d60a5 --- /dev/null +++ b/modules/libcom/RTEMS/posix/rtems_init.c @@ -0,0 +1,1183 @@ +/*************************************************************************\ +* Copyright (c) 2002 The University of Saskatchewan +* EPICS BASE Versions 3.13.7 +* and higher are distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ +/* + * RTEMS startup task for EPICS + * Author: W. Eric Norum + * eric.norum@usask.ca + * (306) 966-5394 + */ + +/* + * This is the first implementation with posix and rtems5. + * Currently only dhcp is supported with libbsd. The reading of the + * environment variables from e.g. u-boot environment is still missing. + * Extensive tests so far only with qemu. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if __RTEMS_MAJOR__ > 4 +#include +#else +#include +#endif + +#ifdef RTEMS_LEGACY_STACK +#include +#include +#else // libbsd stack +#include +#include +#include +#include +#endif + +#include +#if __RTEMS_MAJOR__ > 4 +#include +#endif +#include "epicsVersion.h" +#include "epicsThread.h" +#include "epicsTime.h" +#include "epicsExit.h" +#include "envDefs.h" +#include "errlog.h" +#include "logClient.h" +#include "osiUnistd.h" +#include "iocsh.h" +#include "osdTime.h" +#include "epicsMemFs.h" +#include "epicsEvent.h" +#include "errlog.h" + +#include "epicsRtemsInitHooks.h" + +#ifndef RTEMS_LEGACY_STACK +// setup own ntp-client to get time +#include "epicsNtp.h" +epicsEventId dhcpDone; +#endif + +/* these settings are needed by the rtems startup + * may provide by dhcp/bootp + * or environments from the "BIOS" like u-boot, motboot etc. + */ +char rtemsInit_NTP_server_ip[16] = "10.0.5.1"; +char bootp_server_name_init[128] = "1001.1001@10.0.5.1:/epics"; +char bootp_boot_file_name_init[128] = "/epics/myExample/bin/RTEMS-beatnik/myExample.boot"; +char bootp_cmdline_init[128] = "/epics/myExample/iocBoot/iocmyExample/st.cmd"; + +struct in_addr rtems_bsdnet_bootp_server_address; +/* TODO check rtems_bsdnet_bootp_cmdline */ +#ifndef RTEMS_LEGACY_STACK +char *rtems_bsdnet_bootp_server_name = bootp_server_name_init; +char *rtems_bsdnet_bootp_boot_file_name = bootp_boot_file_name_init; +char *rtems_bsdnet_bootp_cmdline = bootp_cmdline_init; +#endif // not LEGACY Stack + +/* + * Prototypes for some functions not in header files + */ +//void tzset(void); +int fileno(FILE *); +int main(int argc, char **argv); + +static void +logReset (void) +{ + void rtems_bsp_reset_cause(char *buf, size_t capacity) __attribute__((weak)); + void (*fp)(char *buf, size_t capacity) = rtems_bsp_reset_cause; + + if (fp) { + char buf[80]; + fp(buf, sizeof buf); + errlogPrintf ("Startup after %s.\n", buf); + } + else { + errlogPrintf ("Startup.\n"); + } +} + +/* + *********************************************************************** + * FATAL ERROR REPORTING * + *********************************************************************** + */ +/* + * Delay for a while, then terminate + */ +static void +delayedPanic (const char *msg) +{ + rtems_task_wake_after (rtems_clock_get_ticks_per_second()); + rtems_task_wake_after (rtems_clock_get_ticks_per_second()); + rtems_panic ("%s", msg); +} + +/* + * Log error and terminate + */ +void +LogFatal (const char *msg, ...) +{ + va_list ap; + + va_start (ap, msg); + errlogVprintf (msg, ap); + va_end (ap); + delayedPanic (msg); +} + +/* + * Log RTEMS error and terminate + */ +void +LogRtemsFatal (const char *msg, rtems_status_code sc) +{ + errlogPrintf ("%s: %s\n", msg, rtems_status_text (sc)); + delayedPanic (msg); +} + +/* + * Log network error and terminate + */ +void +LogNetFatal (const char *msg, int err) +{ + errlogPrintf ("%s: %d\n", msg, err); + delayedPanic (msg); +} + +void * +mustMalloc(int size, const char *msg) +{ + void *p; + + if ((p = malloc (size)) == NULL) + LogFatal ("Can't allocate space for %s.\n", msg); + return p; +} + +/* + *********************************************************************** + * REMOTE FILE ACCESS * + *********************************************************************** + */ +#ifdef OMIT_NFS_SUPPORT +# include +#endif + +const epicsMemFS *epicsRtemsFSImage __attribute__((weak)); +const epicsMemFS *epicsRtemsFSImage = (void*)&epicsRtemsFSImage; + +/* hook to allow app specific FS setup */ +int +epicsRtemsMountLocalFilesystem(char **argv) __attribute__((weak)); +int +epicsRtemsMountLocalFilesystem(char **argv) +{ + if(epicsRtemsFSImage==(void*)&epicsRtemsFSImage) + return -1; /* no FS image provided. */ + else if(epicsRtemsFSImage==NULL) + return 0; /* no FS image provided, but none is needed. */ + else { + printf("***** Using compiled in file data *****\n"); + if (epicsMemFsLoad(epicsRtemsFSImage) != 0) { + printf("Can't unpack tar filesystem\n"); + return -1; + } else { + argv[1] = "/"; + return 0; + } + } +} + +static int +initialize_local_filesystem(char **argv) +{ + extern char _DownloadLocation[] __attribute__((weak)); + extern char _FlashBase[] __attribute__((weak)); + extern char _FlashSize[] __attribute__((weak)); + + argv[0] = rtems_bsdnet_bootp_boot_file_name; + if (epicsRtemsMountLocalFilesystem(argv)==0) { + return 1; /* FS setup successful */ +#ifdef RTEMS_LEGACY_STACK + } else if (_FlashSize && (_DownloadLocation || _FlashBase)) { + extern char _edata[]; + size_t flashIndex = _edata - _DownloadLocation; + char *header = _FlashBase + flashIndex; + + if (memcmp(header + 257, "ustar ", 8) == 0) { + int fd; + printf ("***** Unpack in-memory file system (IMFS) *****\n"); + if (rtems_tarfs_load("/", (unsigned char *)header, (size_t)_FlashSize - flashIndex) != 0) { + printf("Can't unpack tar filesystem\n"); + return 0; + } + if ((fd = open(rtems_bsdnet_bootp_cmdline, 0)) >= 0) { + close(fd); + printf ("***** Found startup script (%s) in IMFS *****\n", rtems_bsdnet_bootp_cmdline); + argv[1] = rtems_bsdnet_bootp_cmdline; + return 1; + } + printf ("***** Startup script (%s) not in IMFS *****\n", rtems_bsdnet_bootp_cmdline); + } +#endif /* only with old stack, check check libbsd dependency! */ + } + return 0; +} + +#ifndef OMIT_NFS_SUPPORT +int +nfsMount(char *uidhost, char *path, char *mntpoint) +{ + int devl = strlen(uidhost) + strlen(path) + 2; + char *dev; + int rval = -1; + + if ((dev = malloc(devl)) == NULL) { + fprintf(stderr,"nfsMount: out of memory\n"); + return -1; + } + sprintf(dev, "%s:%s", uidhost, path); + printf("Mount %s on %s\n", dev, mntpoint); + rval = mount_and_make_target_path ( + dev, mntpoint, RTEMS_FILESYSTEM_TYPE_NFS, + RTEMS_FILESYSTEM_READ_WRITE, NULL ); + if(rval) + perror("mount failed"); + free(dev); + return rval; +} +#define NFS_INIT +#endif + + +static void +initialize_remote_filesystem(char **argv, int hasLocalFilesystem) +{ +#ifdef OMIT_NFS_SUPPORT + printf ("***** Initializing TFTP *****\n"); + mount_and_make_target_path(NULL, + "/TFTP", + RTEMS_FILESYSTEM_TYPE_TFTPFS, + RTEMS_FILESYSTEM_READ_WRITE, + NULL); + if (!hasLocalFilesystem) { + char *path; + int pathsize = 200; + int l; + + path = mustMalloc(pathsize, "Command path name "); + strcpy (path, "/TFTP/BOOTP_HOST/epics/"); + l = strlen (path); + if (gethostname (&path[l], pathsize - l - 10) || (path[l] == '\0')) + { + LogFatal ("Can't get host name"); + } + strcat (path, "/st.cmd"); + argv[1] = path; + } +#else + char *server_name; + char *server_path; + char *mount_point; + char *cp; + int l = 0; + + printf ("***** Initializing NFS *****\n"); + NFS_INIT + if (env_nfsServer && env_nfsPath && env_nfsMountPoint) { + server_name = env_nfsServer; + server_path = env_nfsPath; + mount_point = env_nfsMountPoint; + cp = mount_point; + while ((cp = strchr(cp+1, '/')) != NULL) { + *cp = '\0'; + if ((mkdir (mount_point, 0755) != 0) + && (errno != EEXIST)) + LogFatal("Can't create directory \"%s\": %s.\n", + mount_point, strerror(errno)); + *cp = '/'; + } + argv[1] = rtems_bsdnet_bootp_cmdline; + } + else if (hasLocalFilesystem) { + return; + } + else { + /* + * Use first component of nvram/bootp command line pathname + * to set up initial NFS mount. A "/tftpboot/" is prepended + * if the pathname does not begin with a '/'. This allows + * NFS and TFTP to have a similar view of the remote system. + */ + if (rtems_bsdnet_bootp_cmdline[0] == '/') + cp = rtems_bsdnet_bootp_cmdline + 1; + else + cp = rtems_bsdnet_bootp_cmdline; + cp = strchr(cp, '/'); + if ((cp == NULL) + || ((l = cp - rtems_bsdnet_bootp_cmdline) == 0)) + LogFatal("\"%s\" is not a valid command pathname.\n", rtems_bsdnet_bootp_cmdline); + cp = mustMalloc(l + 20, "NFS mount paths"); + server_path = cp; + server_name = rtems_bsdnet_bootp_server_name; + if (rtems_bsdnet_bootp_cmdline[0] == '/') { + mount_point = server_path; + strncpy(mount_point, rtems_bsdnet_bootp_cmdline, l); + mount_point[l] = '\0'; + argv[1] = rtems_bsdnet_bootp_cmdline; + /* + * Its probably common to embed the mount point in the server + * name so, when this is occurring, dont clobber the mount point + * by appending the first node from the command path. This allows + * the mount point to be a different path then the server's mount + * path. + * + * This allows for example a line similar to as follows the DHCP + * configuration file. + * + * server-name "159.233@192.168.0.123:/vol/vol0/bootRTEMS"; + */ + if ( server_name ) { + const size_t allocSize = strlen ( server_name ) + 2; + char * const pServerName = mustMalloc( allocSize, + "NFS mount paths"); + char * const pServerPath = mustMalloc ( allocSize, + "NFS mount paths"); + const int scanfStatus = sscanf ( + server_name, + "%[^:] : / %s", + pServerName, + pServerPath + 1u ); + if ( scanfStatus == 2 ) { + pServerPath[0u]= '/'; + server_name = pServerName; + // is this a general solution? + server_path = mount_point = pServerPath; + } + else { + free ( pServerName ); + free ( pServerPath ); + } + } + } + else { + char *abspath = mustMalloc(strlen(rtems_bsdnet_bootp_cmdline)+2,"Absolute command path"); + strcpy(server_path, "/tftpboot/"); + mount_point = server_path + strlen(server_path); + strncpy(mount_point, rtems_bsdnet_bootp_cmdline, l); + mount_point[l] = '\0'; + mount_point--; + strcpy(abspath, "/"); + strcat(abspath, rtems_bsdnet_bootp_cmdline); + argv[1] = abspath; + } + } + errlogPrintf("nfsMount(\"%s\", \"%s\", \"%s\")\n", + server_name, server_path, mount_point); + nfsMount(server_name, server_path, mount_point); +#endif +} + +static +char rtems_etc_hosts[] = "127.0.0.1 localhost\n"; + +/* If it doesn't already exist, create /etc/hosts with an entry for 'localhost' */ +static +void fixup_hosts(void) +{ + FILE *fp; + int ret; + struct stat STAT; + + ret=stat("/etc/hosts", &STAT); + if(ret==0) + { + return; /* already exists, assume file */ + } else if(errno!=ENOENT) { + perror("error: fixup_hosts stat /etc/hosts"); + return; + } + + ret = mkdir("/etc", 0775); + if(ret!=0 && errno!=EEXIST) + { + perror("error: fixup_hosts create /etc"); + return; + } + + if((fp=fopen("/etc/hosts", "w"))==NULL) + { + perror("error: fixup_hosts create /etc/hosts"); + } + + if(fwrite(rtems_etc_hosts, 1, sizeof(rtems_etc_hosts)-1, fp)!=sizeof(rtems_etc_hosts)-1) + { + perror("error: failed to write /etc/hosts"); + } + + fclose(fp); +} + +/* + * Get to the startup script directory + * The TFTP filesystem requires a trailing '/' on chdir arguments. + */ +static void +set_directory (const char *commandline) +{ + const char *cp; + char *directoryPath; + int l; + + cp = strrchr(commandline, '/'); + if (cp == NULL) { + l = 0; + cp = "/"; + } + else { + l = cp - commandline; + cp = commandline; + } + directoryPath = mustMalloc(l + 2, "Command path directory "); + strncpy(directoryPath, cp, l); + directoryPath[l] = '/'; + directoryPath[l+1] = '\0'; + if (chdir (directoryPath) < 0) + LogFatal ("Can't set initial directory(%s): %s\n", directoryPath, strerror(errno)); + else + errlogPrintf("chdir(\"%s\")\n", directoryPath); + free(directoryPath); +} + +/* + *********************************************************************** + * RTEMS/EPICS COMMANDS * + *********************************************************************** + */ + +static const iocshArg rtshellArg0 = { "cmd", iocshArgString}; +static const iocshArg rtshellArg1 = { "args", iocshArgArgv}; +static const iocshArg * rtshellArgs[2] = { &rtshellArg0, &rtshellArg1}; +static const iocshFuncDef rtshellFuncDef = { "rt",2, rtshellArgs +#ifdef IOCSHFUNCDEF_HAS_USAGE + , "run rtems shell command" +#endif + }; + +static void rtshellCallFunc(const iocshArgBuf *args) +{ + rtems_shell_cmd_t *cmd = rtems_shell_lookup_cmd(args[0].sval); + int ret; + + if (!cmd) { + fprintf(stderr, "ERR: No such command\n"); + + } else { + fflush(stdout); + fflush(stderr); + ret = (*cmd->command)(args[1].aval.ac,args[1].aval.av); + fflush(stdout); + fflush(stderr); + if(ret) + fprintf(stderr, "ERR: %d\n",ret); + } +} + +/* + * RTEMS status + */ +static void +rtems_netstat (unsigned int level) +{ +#ifndef RTEMS_LEGACY_STACK + printf ("***** Sorry not implemented yet with the new network stack (bsdlib)\n"); +#else + rtems_bsdnet_show_if_stats (); + rtems_bsdnet_show_mbuf_stats (); + if (level >= 1) { + rtems_bsdnet_show_inet_routes (); + } + if (level >= 2) { + rtems_bsdnet_show_ip_stats (); + rtems_bsdnet_show_icmp_stats (); + rtems_bsdnet_show_udp_stats (); + rtems_bsdnet_show_tcp_stats (); + } +#endif +} + +static const iocshArg netStatArg0 = { "level",iocshArgInt}; +static const iocshArg * const netStatArgs[1] = {&netStatArg0}; +static const iocshFuncDef netStatFuncDef = {"netstat",1,netStatArgs +#ifdef IOCSHFUNCDEF_HAS_USAGE + , "show network status" +#endif + }; +static void netStatCallFunc(const iocshArgBuf *args) +{ + rtems_netstat(args[0].ival); +} + +static const iocshFuncDef heapSpaceFuncDef = {"heapSpace",0,NULL +#ifdef IOCSHFUNCDEF_HAS_USAGE + , "show malloc statistic" +#endif + }; +static void heapSpaceCallFunc(const iocshArgBuf *args) +{ +#if __RTEMS_MAJOR__ > 4 + Heap_Information_block info; + double x; + + malloc_info (&info); + x = info.Stats.size - (unsigned long) + (info.Stats.lifetime_allocated - info.Stats.lifetime_freed); + if (x >= 1024*1024) + printf("Heap space: %.1f MB\n", x / (1024 * 1024)); + else + printf("Heap space: %.1f kB\n", x / 1024); +#else + rtems_malloc_statistics_t s; + double x; + + malloc_get_statistics(&s); + x = s.space_available - (unsigned long)(s.lifetime_allocated - s.lifetime_freed); + if (x >= 1024*1024) + printf("Heap space: %.1f MB\n", x / (1024 * 1024)); + else + printf("Heap space: %.1f kB\n", x / 1024); +#endif // RTEMS < 5 +} + +#ifndef OMIT_NFS_SUPPORT +static const iocshArg nfsMountArg0 = { "[uid.gid@]host",iocshArgString}; +static const iocshArg nfsMountArg1 = { "server path",iocshArgString}; +static const iocshArg nfsMountArg2 = { "mount point",iocshArgString}; +static const iocshArg * const nfsMountArgs[3] = {&nfsMountArg0,&nfsMountArg1, + &nfsMountArg2}; +static const iocshFuncDef nfsMountFuncDef = {"nfsMount",3,nfsMountArgs +#ifdef IOCSHFUNCDEF_HAS_USAGE + , "mount nfs drive" +#endif + }; +static void nfsMountCallFunc(const iocshArgBuf *args) +{ + char *cp = args[2].sval; + while ((cp = strchr(cp+1, '/')) != NULL) { + *cp = '\0'; + if ((mkdir (args[2].sval, 0755) != 0) && (errno != EEXIST)) { + printf("Can't create directory \"%s\": %s.\n", + args[2].sval, strerror(errno)); + return; + } + *cp = '/'; + } + nfsMount(args[0].sval, args[1].sval, args[2].sval); +} +#endif + + +void zoneset(const char *zone) +{ + if(zone) + setenv("TZ", zone, 1); + else + unsetenv("TZ"); + tzset(); +} + +static const iocshArg zonesetArg0 = {"zone string", iocshArgString}; +static const iocshArg * const zonesetArgs[1] = {&zonesetArg0}; +static const iocshFuncDef zonesetFuncDef = {"zoneset",1,zonesetArgs +#ifdef IOCSHFUNCDEF_HAS_USAGE + , "set timezone (obsolete?)" +#endif + }; +static void zonesetCallFunc(const iocshArgBuf *args) +{ + zoneset(args[0].sval); +} + + +/* + * Register RTEMS-specific commands + */ +static void iocshRegisterRTEMS (void) +{ + iocshRegister(&netStatFuncDef, netStatCallFunc); + iocshRegister(&heapSpaceFuncDef, heapSpaceCallFunc); +#ifndef OMIT_NFS_SUPPORT + iocshRegister(&nfsMountFuncDef, nfsMountCallFunc); +#endif + iocshRegister(&zonesetFuncDef, &zonesetCallFunc); + iocshRegister(&rtshellFuncDef, &rtshellCallFunc); +#if __RTEMS_MAJOR__ > 4 + rtems_shell_init_environment(); +#endif +} + +/* + * Set up the console serial line (no handshaking) + */ +static void +initConsole (void) +{ + struct termios t; + +printf("\n initConsole --- Info ---\n"); +printf("stdin: fileno: %d, ttyname: %s\n", fileno(stdin), ttyname(fileno(stdin))); +printf("stdout: fileno: %d, ttyname: %s\n", fileno(stdout), ttyname(fileno(stdout))); +printf("stderr: fileno: %d, ttyname: %s\n", fileno(stderr), ttyname(fileno(stderr))); + + if (tcgetattr (fileno (stdin), &t) < 0) { + printf ("tcgetattr failed: %s\n", strerror (errno)); + return; + } + t.c_iflag &= ~(IXOFF | IXON | IXANY); + if (tcsetattr (fileno (stdin), TCSANOW, &t) < 0) { + printf ("tcsetattr failed: %s\n", strerror (errno)); + return; + } +} + +/* + * Hook to ensure that BSP cleanup code gets run on exit + */ +static void +exitHandler(void) +{ + rtems_shutdown_executive(0); +} + +#ifndef RTEMS_LEGACY_STACK +static char* getPrimaryNetworkInterface(void) +{ + // lookup available network interfaces + char ifnamebuf[IF_NAMESIZE]; + char *ifname; + // get primary network interface + ifname = if_indextoname(1, &ifnamebuf[0]); + if (ifname == NULL) return (NULL); + printf("\n***** Primary Network interface : %s *****\n", ifname); + return (ifname); +} + +static void +dhcpcd_hook_handler(rtems_dhcpcd_hook *hook, char *const *env) +{ + int bound = 0; + char iName[16]; + char *name; + char *value; + char * env_position; + + (void)hook; + + char ifnamebuf[IF_NAMESIZE]; + sprintf(ifnamebuf, "%s", getPrimaryNetworkInterface()); + + while (*env != NULL) { + char const * interface = "interface"; + char const * reason = "reason"; + char const * bound_str = "BOUND"; + + name = strtok_r(*env,"=", &env_position); + value = strtok_r(NULL,"=", &env_position); + printf("all out ---> %s = %s\n", name, value); + + if (!strncmp(name, interface, strlen(interface)) && + !strcmp(value, ifnamebuf)) { + snprintf(iName, sizeof(iName), "%s", value); + } + + if (!strncmp(name, reason, strlen(reason)) && + !strncmp(value, bound_str, strlen(bound_str))) { + printf ("Interface %s bounded\n", iName); + bound = 1; + } + + if (bound) { + // as there is no ntp-support in rtems-libbsd, we call our own client + char const * new_ntp_servers = "new_ntp_servers"; + char const * new_host_name = "new_host_name"; + char const * new_tftp_server_name = "new_tftp_server_name"; + + if (!strncmp(name, new_ntp_servers, strlen(new_ntp_servers))) + snprintf(rtemsInit_NTP_server_ip, + sizeof(rtemsInit_NTP_server_ip), + "%s", value); + + if (!strncmp(name, new_host_name, strlen(new_host_name))) + sethostname (value, strlen (value)); + + if (!strncmp(name, new_tftp_server_name, strlen(new_tftp_server_name))){ + snprintf(rtems_bsdnet_bootp_server_name, + sizeof(bootp_server_name_init), + "%s", value); + printf(" rtems_bsdnet_bootp_server_name : %s\n", rtems_bsdnet_bootp_server_name); + } + if(!strncmp(name, "new_bootfile_name", 20)){ + snprintf(rtems_bsdnet_bootp_boot_file_name, + sizeof(bootp_boot_file_name_init), + "%s", value); + printf(" rtems_bsdnet_bootp_boot_file_name : %s\n", rtems_bsdnet_bootp_boot_file_name); + } + if(!strncmp(name, "new_rtems_cmdline", 20)){ + snprintf(rtems_bsdnet_bootp_cmdline, + sizeof(bootp_cmdline_init), + "%s", value); + printf(" rtems_bsdnet_bootp_cmdline : %s\n", rtems_bsdnet_bootp_cmdline); + } + } + ++env; + } + if (bound) + epicsEventSignal(dhcpDone); +} + +static rtems_dhcpcd_hook dhcpcd_hook = { + .name = "ioc boot", + .handler = dhcpcd_hook_handler +}; + +static void +default_network_on_exit(int exit_code, void *arg) +{ + rtems_printer printer; + + (void)arg; + + rtems_print_printer_printf(&printer); + rtems_stack_checker_report_usage_with_plugin(&printer); +} + +static void +default_network_set_self_prio(rtems_task_priority prio) +{ + rtems_status_code sc; + + sc = rtems_task_set_priority(RTEMS_SELF, prio, &prio); + assert(sc == RTEMS_SUCCESSFUL); +} + +static void +default_network_dhcpcd(void) +{ + static const char default_cfg[] = "clientid test client\n"; + rtems_status_code sc; + int fd; + int rv; + ssize_t n; + struct stat statbuf; + + if (ENOENT == stat("/etc/dhcpcd.conf", &statbuf)) { + fd = open("/etc/dhcpcd.conf", O_CREAT | O_WRONLY, + S_IRWXU | S_IRWXG | S_IRWXO); + assert(fd >= 0); + + n = write(fd, default_cfg, sizeof(default_cfg) - 1); + assert(n == (ssize_t) sizeof(default_cfg) - 1); + + static const char fhi_cfg[] = + "nodhcp6\n" + "ipv4only\n" + "option ntp_servers\n" + "option rtems_cmdline\n" + "option tftp_server_name\n" + "option bootfile_name\n" + "define 129 string rtems_cmdline\n" + "timeout 0"; + + n = write(fd, fhi_cfg, sizeof(fhi_cfg) - 1); + assert(n == (ssize_t) sizeof(fhi_cfg) - 1); + + rv = close(fd); + assert(rv == 0); + } + + sc = rtems_dhcpcd_start(NULL); + assert(sc == RTEMS_SUCCESSFUL); +} +#endif // not RTEMS_LEGACY_STACK + +#if __RTEMS_MAJOR__>4 +/* + *********************************************************************** + * TELNET DAEMON * + *********************************************************************** + */ +#define LINE_SIZE 256 +static void +telnet_pseudoIocsh(char *name, __attribute__((unused))void *arg) +{ + char line[LINE_SIZE]; + int fid[3], save_fid[3]; + + printf("info: pty dev name = %s\n", name); + + save_fid[1] = dup2(1,1); + fid[1] = dup2( fileno(stdout), 1); + if (fid[1] == -1 ) printf("Can't dup stdout\n"); + save_fid[2] = dup2(2,2); + fid[2] = dup2( fileno(stderr), 2); + if (fid[2] == -1 ) printf("Can't dup stderr\n"); + + const char *prompt = "tIocSh> "; + + while (1) { + fputs(prompt, stdout); + fflush(stdout); + /* telnet close not detected ??? tbd */ + if (fgets(line, LINE_SIZE, stdin) == NULL) { + dup2(save_fid[1],1); + dup2(save_fid[2],2); + return; + } + if (line[strlen(line)-1] == '\n') line[strlen(line)-1] = 0; + if (!strncmp( line, "bye",3)) { + printf( "%s", "Will end session\n"); + dup2(save_fid[1],1); + dup2(save_fid[2],2); + return; + } + iocshCmd(line); + } +} + +#define SHELL_ENTRY telnet_pseudoIocsh + +/* + * Telnet daemon configuration + * 0 or NULL for most fields in thsi struct indicate default values to RTEMS. + */ +rtems_telnetd_config_table rtems_telnetd_config = { + .command = SHELL_ENTRY, + .arg = NULL, + .priority = 0, + .stack_size = 0, + .client_maximum = 0, + .login_check = NULL, + .keep_stdio = false +}; + +#endif + + +/* + * RTEMS Startup task + */ +void * +POSIX_Init ( void *argument __attribute__((unused))) +{ + int result; + char *argv[3] = { NULL, NULL, NULL }; + rtems_status_code sc; + struct timespec now; + char timeBuff[100]; + + initConsole (); + + /* + * Use BSP-supplied time of day if available otherwise supply default time. + * It is very likely that other time synchronization facilities in EPICS + * will soon override this value. + */ + /* check for RTC ... unfortunately seems to be missing with libbsd and qemu ? + if (checkRealtime() >= 0) { + setRealTimeToRTEMS(); + } else + */ + { + // set time to 14.4.2014 + now.tv_sec = 1397460606; + now.tv_nsec = 0; + sc = clock_settime(CLOCK_REALTIME, &now); + if (sc < 0) + printf ("***** Can't set time: %s\n", rtems_status_text (sc)); + } + sc = clock_gettime( CLOCK_REALTIME, &now); + if ( sc < 0) { + printf ("***** Can't get time: %s\n", rtems_status_text (sc)); + } else { + strftime(timeBuff, sizeof timeBuff, "%D %T", gmtime(&now.tv_sec)); + printf("time set to : %s.%09ld UTC\n", timeBuff, now.tv_nsec); + } + + /* + * Explain why we're here + */ + logReset(); + + /* TBD ... + * Architecture-specific hooks + */ +#ifdef RTEMS_LEGACY_STACK + if (epicsRtemsInitPreSetBootConfigFromNVRAM(&rtems_bsdnet_config) != 0) + delayedPanic("epicsRtemsInitPreSetBootConfigFromNVRAM"); + if (rtems_bsdnet_config.bootp == NULL) { + extern void setBootConfigFromNVRAM(void); + setBootConfigFromNVRAM(); + } + if (epicsRtemsInitPostSetBootConfigFromNVRAM(&rtems_bsdnet_config) != 0) + delayedPanic("epicsRtemsInitPostSetBootConfigFromNVRAM"); +#endif + /* + * Override RTEMS Posix configuration, it gets started with posix prio 2 + */ + epicsThreadSetPriority(epicsThreadGetIdSelf(), epicsThreadPriorityIocsh); + + /* + * Create a reasonable environment + */ + + putenv ("TERM=xterm"); + putenv ("IOCSH_HISTSIZE=20"); + + /* + * Display some OS information + */ + printf("\n***** RTEMS Version: %s *****\n", + rtems_get_version_string()); + +#ifndef RTEMS_LEGACY_STACK + /* + * Start network (libbsd) + * + * start qemu like this + * qemu-system-i386 -m 64 -no-reboot -serial stdio -display none \ + * -net nic,model=rtl8139,macaddr=0e:b0:ba:5e:ba:11 -net user,restrict=yes \ + * -append "--video=off --console=/dev/com1" -kernel libComTestHarness + */ + printf("\n***** Initializing network (libbsd, dhcpcd) *****\n"); + rtems_bsd_setlogpriority("debug"); + on_exit(default_network_on_exit, NULL); + + /* Let other tasks run to complete background work */ + default_network_set_self_prio(RTEMS_MAXIMUM_PRIORITY - 1U); + + /* supress all output from bsd network initialization */ + rtems_bsd_set_vprintf_handler(rtems_bsd_vprintf_handler_mute); + + sc = rtems_bsd_initialize(); + assert(sc == RTEMS_SUCCESSFUL); + + /* Let the callout timer allocate its resources */ + sc = rtems_task_wake_after(2); + assert(sc == RTEMS_SUCCESSFUL); + + printf("\n***** ifconfig lo0 *****\n"); + rtems_bsd_ifconfig_lo0(); + + printf("\n***** add dhcpcd hook *****\n"); + dhcpDone = epicsEventMustCreate(epicsEventEmpty); + rtems_dhcpcd_add_hook(&dhcpcd_hook); + + printf("\n***** Start default network dhcpcd *****\n"); + // if MY_BOOTP??? + default_network_dhcpcd(); + + /* this seems to be hard coded in the BSP -> Sebastian Huber ? */ + printf("\n--Info (hpj)-- bsd task prio IRQS: %d -----\n", rtems_bsd_get_task_priority("IRQS")); + printf("\n--Info (hpj)-- bsd task prio TIME: %d -----\n", rtems_bsd_get_task_priority("TIME")); + + + // wait for dhcp done ... should be if SYNCDHCP is used + epicsEventWaitStatus stat; + printf("\n ---- Waiting for DHCP ...\n"); + stat = epicsEventWaitWithTimeout(dhcpDone, 600); + if (stat == epicsEventOK) + epicsEventDestroy(dhcpDone); + else if (stat == epicsEventWaitTimeout) + printf("\n ---- DHCP timed out!\n"); + else + printf("\n ---- dhcpDone Event Unknown state %d\n", stat); + + const char* ifconfg_args[] = { + "ifconfig", NULL + }; + const char* netstat_args[] = { + "netstat", "-rn", NULL + }; + + printf("-------------- IFCONFIG -----------------\n"); + rtems_bsd_command_ifconfig(1, (char**) ifconfg_args); + printf("-------------- NETSTAT ------------------\n"); + rtems_bsd_command_netstat(2, (char**) netstat_args); + + /* until now there is no NTP support in libbsd -> Sebastian Huber ... */ + printf("\n***** Until now no NTP support in RTEMS 5 with rtems-libbsd *****\n"); + printf("\n***** Ask ntp server once... *****\n"); + if (epicsNtpGetTime(rtemsInit_NTP_server_ip, &now) < 0) { + printf ("***** Can't get time from ntp ...\n"); + } else { + if (clock_settime(CLOCK_REALTIME, &now) < 0){ + printf ("***** Can't set time: %s\n", rtems_status_text (sc)); + } else { + strftime(timeBuff, sizeof timeBuff, "%D %T", gmtime(&now.tv_sec)); + printf("time from ntp : %s.%09ld UTC\n", timeBuff, now.tv_nsec); + } + } +#else // Legacy stack, old network initialization + char *cp; + if ((cp = getenv("EPICS_TS_NTP_INET")) != NULL) + rtems_bsdnet_config.ntp_server[0] = cp; + + int rtems_bsdnet_ntpserver_count = 1; + struct in_addr rtems_bsdnet_ntpserver[rtems_bsdnet_ntpserver_count]; + memcpy(rtems_bsdnet_ntpserver, rtems_bsdnet_config.ntp_server, sizeof(struct in_addr)); + + if (rtems_bsdnet_config.network_task_priority == 0) + { + unsigned int p; + if (epicsThreadHighestPriorityLevelBelow(epicsThreadPriorityScanLow, &p) + == epicsThreadBooleanStatusSuccess) + { + rtems_bsdnet_config.network_task_priority = p; + } + } + printf("\n***** Initializing network (Legacy Stack) *****\n"); + rtems_bsdnet_initialize_network(); + printf("\n***** Network Status *****\n"); + rtems_netstat(3); + rtems_bsdnet_synchronize_ntp (0, 0); +#endif // not RTEMS_LEGACY_STACK + + /* show messages from network after initialization ? good idea? */ + //rtems_bsd_set_vprintf_handler(bsd_vprintf_handler_old); + + printf("\n***** Setting up file system *****\n"); + initialize_remote_filesystem(argv, initialize_local_filesystem(argv)); + fixup_hosts(); + + /* + * More environment: iocsh prompt and hostname + */ + { + char hostname[1024]; + gethostname(hostname, 1023); + char *cp = mustMalloc(strlen(hostname)+3, "iocsh prompt"); + sprintf(cp, "%s> ", hostname); + epicsEnvSet ("IOCSH_PS1", cp); + epicsEnvSet("IOC_NAME", hostname); + } + + if (getenv("") == NULL) { + const char *tzp = envGetConfigParamPtr(&EPICS_TZ); + if (tzp == NULL) { + printf("Warning -- no timezone information available -- times will be displayed as GMT.\n"); + } + + } + tzset(); + printf(" check for time registered , C++ initialization ...\n"); + //osdTimeRegister(); + /*/Volumes/Epics/myExample/bin/RTEMS-xilinx_zynq_a9_qemu + * Run the EPICS startup script + */ +#if __RTEMS_MAJOR__>4 + // if telnetd is requested ... + // printf(" Will try to start telnetd with prio %d ...\n", rtems_telnetd_config.priority); + // result = rtems_telnetd_initialize(); + // printf (" telnetd initialized with result %d\n", result); +#endif + + printf ("***** Preparing EPICS application *****\n"); + iocshRegisterRTEMS (); + set_directory (argv[1]); + epicsEnvSet ("IOC_STARTUP_SCRIPT", argv[1]); + atexit(exitHandler); + errlogFlush(); + printf ("***** Starting EPICS application *****\n"); + +#if 0 +// Start an rtems shell before main, for debugging RTEMS system issues + rtems_shell_init("SHLL", RTEMS_MINIMUM_STACK_SIZE * 4, + 100, "/dev/console", + false, true, + NULL); +#endif + + result = main ((sizeof argv / sizeof argv[0]) - 1, argv); + printf ("***** IOC application terminating *****\n"); + epicsThreadSleep(1.0); + epicsExit(result); + +#if defined(__rtems__) + delayedPanic("will reset rtems ... end of POSIX_Init"); +#endif + exit(0); +} + +#if defined(QEMU_FIXUPS) +/* Override some hooks (weak symbols) + * if BSP defaults aren't configured for running tests. + */ + + +/* Ensure that stdio goes to serial (so it can be captured) */ +#if defined(__i386__) && !USE_COM1_AS_CONSOLE +#include +#if __RTEMS_MAJOR__ > 4 +#include +#endif + +extern int BSPPrintkPort; +void bsp_predriver_hook(void) +{ +#if __RTEMS_MAJOR__ > 4 + Console_Port_Minor = BSP_CONSOLE_PORT_COM1; +#else + BSPConsolePort = BSP_CONSOLE_PORT_COM1; + +#endif + BSPPrintkPort = BSP_CONSOLE_PORT_COM1; +} +#endif + +/* reboot immediately when done. */ +#if defined(__i386__) && BSP_PRESS_KEY_FOR_RESET +void bsp_cleanup(void) +{ + void bsp_reset(); + bsp_reset(); +} +#endif + +#endif /* QEMU_FIXUPS */ + +int cexpdebug __attribute__((weak)); diff --git a/modules/libcom/RTEMS/rtems_netconfig.c b/modules/libcom/RTEMS/rtems_netconfig.c index 4f7a84149..0207512c7 100644 --- a/modules/libcom/RTEMS/rtems_netconfig.c +++ b/modules/libcom/RTEMS/rtems_netconfig.c @@ -15,8 +15,24 @@ */ #include #include +#include + +#define RTEMS_VERSION_INT VERSION_INT(__RTEMS_MAJOR__, __RTEMS_MINOR__, 0, 0) + +#ifdef RTEMS_LEGACY_STACK // old non libbsd stack #include +/* + * Comment (by sebastian.huber): + * + * This rtems_bsdnet_loopattach() was a hack and is no longer needed in RTEMS + * 4.11. + * + * -- + * Ticket URL: + */ + +#if RTEMS_VERSION_INT<=VERSION_INT(4,10,0,0) extern void rtems_bsdnet_loopattach(); static struct rtems_bsdnet_ifconfig loopback_config = { "lo0", /* name */ @@ -25,7 +41,7 @@ static struct rtems_bsdnet_ifconfig loopback_config = { "127.0.0.1", /* IP address */ "255.0.0.0", /* IP net mask */ }; - +#endif /* * The following conditionals select the network interface card. * @@ -37,19 +53,23 @@ static struct rtems_bsdnet_ifconfig loopback_config = { * application directory and make the appropriate changes. */ #if defined(__i386__) - extern int rtems_ne2kpci_driver_attach (struct rtems_bsdnet_ifconfig *config, int attach); static struct rtems_bsdnet_ifconfig ne2k_driver_config = { "ne2", /* name */ rtems_ne2kpci_driver_attach, /* attach function */ +#if RTEMS_VERSION_INT<=VERSION_INT(4,10,0,0) &loopback_config, /* link to next interface */ +#else + NULL, +#endif }; + extern int rtems_fxp_attach (struct rtems_bsdnet_ifconfig *, int); static struct rtems_bsdnet_ifconfig fxp_driver_config = { "fxp1", /* name */ rtems_fxp_attach, /* attach function */ - &ne2k_driver_config, /* link to next interface */ + &ne2k_driver_config, /* link to next interface */ }; extern int rtems_3c509_driver_attach (struct rtems_bsdnet_ifconfig *, int); static struct rtems_bsdnet_ifconfig e3c509_driver_config = { @@ -73,12 +93,14 @@ static struct rtems_bsdnet_ifconfig e3c509_driver_config = { # endif # endif -static struct rtems_bsdnet_ifconfig bsp_driver_config = { +static struct rtems_bsdnet_ifconfig netdriver_config = { RTEMS_BSP_NETWORK_DRIVER_NAME, /* name */ RTEMS_BSP_NETWORK_DRIVER_ATTACH, /* attach function */ +#if RTEMS_VERSION_INT<=VERSION_INT(4,10,0,0) &loopback_config, /* link to next interface */ +#endif }; -#define FIRST_DRIVER_CONFIG &bsp_driver_config +#define FIRST_DRIVER_CONFIG &netdriver_config #endif @@ -127,3 +149,11 @@ struct rtems_bsdnet_config rtems_bsdnet_config = { NULL, /* Host name */ MY_DOMAINNAME, /* Domain name */ }; +#else // libbsd "new" stack +// nothing to do?? +#endif // RTEMS_LEGACY_STACK + + + + + diff --git a/modules/libcom/RTEMS/rtems_config.c b/modules/libcom/RTEMS/score/rtems_config.c similarity index 100% rename from modules/libcom/RTEMS/rtems_config.c rename to modules/libcom/RTEMS/score/rtems_config.c diff --git a/modules/libcom/RTEMS/rtems_init.c b/modules/libcom/RTEMS/score/rtems_init.c similarity index 100% rename from modules/libcom/RTEMS/rtems_init.c rename to modules/libcom/RTEMS/score/rtems_init.c diff --git a/modules/libcom/RTEMS/setBootConfigFromNVRAM.c b/modules/libcom/RTEMS/setBootConfigFromNVRAM.c index 6fcca54b2..deb9f0654 100644 --- a/modules/libcom/RTEMS/setBootConfigFromNVRAM.c +++ b/modules/libcom/RTEMS/setBootConfigFromNVRAM.c @@ -12,7 +12,9 @@ #include #include #include +#ifdef RTEMS_LEGACY_STACK #include +#endif #include #include #include @@ -26,6 +28,7 @@ char *env_nfsServer; char *env_nfsPath; char *env_nfsMountPoint; +extern char* rtems_bsdnet_bootp_cmdline; /* * Split argument string of form nfs_server:nfs_export: * The nfs_export component will be used as: diff --git a/modules/libcom/src/calc/postfix.c b/modules/libcom/src/calc/postfix.c index 6519d9a39..b3a99e08b 100644 --- a/modules/libcom/src/calc/postfix.c +++ b/modules/libcom/src/calc/postfix.c @@ -27,6 +27,10 @@ #include "postfixPvt.h" #include "libComAPI.h" +#ifdef RTEMS_HAS_ALTIVEC +#pragma GCC push_options +#pragma GCC optimize ("O0") +#endif /* declarations for postfix */ @@ -626,3 +630,6 @@ LIBCOM_API void } } } +#ifdef RTEMS_HAS_ALTIVEC +#pragma GCC pop_options +#endif diff --git a/modules/libcom/src/cvtFast/cvtFast.h b/modules/libcom/src/cvtFast/cvtFast.h index 97217deda..4bfd665ba 100644 --- a/modules/libcom/src/cvtFast/cvtFast.h +++ b/modules/libcom/src/cvtFast/cvtFast.h @@ -7,12 +7,17 @@ * EPICS BASE is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ -/* - * Fast numeric to string conversions +/** + * \file cvtFast.h + * \author Bob Dalesio, Mark Anderson, Marty Kraimer * - * Original Authors: - * Bob Dalesio, Mark Anderson and Marty Kraimer - * Date: 12 January 1993 + * \brief Fast numeric to string conversions + * + * \details + * Provides routines for converting various numeric types into an ascii string. + * They off a combination of speed and convenience not available with sprintf(). + * + * All functions return the number of characters in the output */ #ifndef INCcvtFasth @@ -27,9 +32,6 @@ extern "C" { #endif -/* - * All functions return the number of characters in the output - */ LIBCOM_API int cvtFloatToString(float val, char *pdest, epicsUInt16 prec); LIBCOM_API int diff --git a/modules/libcom/src/error/errlog.h b/modules/libcom/src/error/errlog.h index 425e78ac6..02f2c0816 100644 --- a/modules/libcom/src/error/errlog.h +++ b/modules/libcom/src/error/errlog.h @@ -11,6 +11,20 @@ #ifndef INC_errlog_H #define INC_errlog_H +/** \file errlog.h + * \brief Functions for interacting with the errlog task + * + * This file contains functions for passing error messages with varying severity, + * registering and un-registering listeners and modifying the log buffer size and + * max message size. + * + * Some of these functions are similar to the standard C library functions printf + * and vprintf. For details on the arguments and return codes it is useful to consult + * any book that describes the standard C library such as + * `The C Programming Language ANSI C Edition` by Kernighan and Ritchie. + * + */ + #include #include #include @@ -22,8 +36,15 @@ extern "C" { #endif +/** + * errlogListener function type. + * + * This is used when adding or removing log listeners in ::errlogAddListener + * and ::errlogRemoveListeners. + */ typedef void (*errlogListener)(void *pPrivate, const char *message); +/** errlog severity enums */ typedef enum { errlogInfo, errlogMinor, @@ -45,37 +66,171 @@ LIBCOM_API extern int errVerbose; LIBCOM_API extern const char * errlogSevEnumString[]; #endif -/* errMessage is a macro so it can get the file and line number */ +/** + * errMessage is a macro so it can get the file and line number. It prints the message, + * the status symbol and string values, and the name of the task which invoked errMessage. + * It also prints the name of the source file and the line number from which the call was issued. + * + * The status code used for the 1st argument is: + * - 0: Find latest vxWorks or Unix error (errno value). + * - -1: Don’t report status. + * - Other: Use this status code and lookup the string value + * + * \param S Status code + * \param PM The message to print + */ #define errMessage(S, PM) \ errPrintf(S, __FILE__, __LINE__, "%s", PM) -/* epicsPrintf and epicsVprintf are old names for errlog routines*/ + +/** epicsPrintf is an old name for errlog routines */ #define epicsPrintf errlogPrintf + +/** epicsVprintf is an old name for errlog routines */ #define epicsVprintf errlogVprintf +/** + * errlogPrintf is like the printf function provided by the standard C library, except + * that the output is sent to the errlog task. Unless configured not to, the output + * will appear on the console as well. + */ LIBCOM_API int errlogPrintf(const char *pformat, ...) EPICS_PRINTF_STYLE(1,2); + +/** + * errlogVprintf is like the vprintf function provided by the standard C library, except + * that the output is sent to the errlog task. Unless configured not to, the output + * will appear on the console as well. + */ LIBCOM_API int errlogVprintf(const char *pformat, va_list pvar); + +/** + * This function is like ::errlogPrintf except that it adds the severity to the beginning + * of the message in the form `sevr=` where value is one of the enumerated + * severities in ::errlogSevEnum. Also the message is suppressed if severity is less than + * the current severity to suppress. + * + * \param severity One of the severity enums from ::errlogSevEnum + * \param pFormat The message to log or print + * \return int Consult printf documentation in C standard library + */ LIBCOM_API int errlogSevPrintf(const errlogSevEnum severity, const char *pformat, ...) EPICS_PRINTF_STYLE(2,3); + +/** + * This function is like ::errlogVprintf except that it adds the severity to the beginning + * of the message in the form `sevr=` where value is one of the enumerated + * severities in ::errlogSevEnum. Also the message is suppressed if severity is less than + * the current severity to suppress. If epicsThreadIsOkToBlock is true, which is + * true during iocInit, errlogSevVprintf does NOT send output to the + * errlog task. + * + * \param severity One of the severity enums from ::errlogSevEnum + * \param pFormat The message to log or print + * \param pvar va_list + * \return int Consult printf documentation in C standard library + */ LIBCOM_API int errlogSevVprintf(const errlogSevEnum severity, const char *pformat, va_list pvar); + +/** + * Sends message to the errlog task. + * + * \param message The message to send + */ LIBCOM_API int errlogMessage(const char *message); +/** + * Gets the string value of severity. + * + * \param severity The severity from ::errlogSevEnum + * \return The string value + */ LIBCOM_API const char * errlogGetSevEnumString(errlogSevEnum severity); + +/** + * Sets the severity to log + * + * \param severity The severity from ::errlogSevEnum + */ LIBCOM_API void errlogSetSevToLog(errlogSevEnum severity); + +/** + * Gets the current severity to log + * + * \return ::errlogSevEnum + */ LIBCOM_API errlogSevEnum errlogGetSevToLog(void); +/** + * Any code can receive errlog message. This function will add a listener callback. + * + * \param listener Function pointer of type ::errlogListener + * \param pPrivate This will be passed as the first argument of listener() + */ LIBCOM_API void errlogAddListener(errlogListener listener, void *pPrivate); + +/** + * This function will remove a listener callback. + * + * \param listener Function pointer of type ::errlogListener + * \param pPrivate This will be passed as the first argument of listener() + */ LIBCOM_API int errlogRemoveListeners(errlogListener listener, void *pPrivate); +/** + * Normally the errlog system displays all messages on the console. + * During error message storms this function can be used to suppress console messages. + * A argument of 0 suppresses the messages, any other value lets messages go to the console. + * + * \param yesno (0=No, 1=Yes) + * \return 0 + */ LIBCOM_API int eltc(int yesno); + +/** + * Sets a new stream to write the messages to + * + * \param stream Pointer to file handle + * \return 0 + */ LIBCOM_API int errlogSetConsole(FILE *stream); +/** + * Can be used to initialize the error logging system with a larger buffer. The default buffer size is 1280 bytes. + * + * \param bufsize The desired buffer size + */ LIBCOM_API int errlogInit(int bufsize); + +/** + * errlogInit2 can be used to initialize the error logging system with a larger buffer and maximum message size. + * The default buffer size is 1280 bytes, and the default maximum message size is 256. + * + * \param bufsize The desired buffer size + * \param maxMsgSize The desired max message size + */ LIBCOM_API int errlogInit2(int bufsize, int maxMsgSize); + +/** Wakes up the errlog task and then waits until all messages are flushed from the queue. */ LIBCOM_API void errlogFlush(void); +/** + * Routine errPrintf is normally called as follows: + * `errPrintf(status, __FILE__, __LINE__,"",...); ` + * + * Where status is defined as: + * - 0: Find latest vxWorks or Unix error. + * - -1: Don’t report status. + * - Other: Use this status code and lookup the string value + * + * \param status See above + * \param __FILE__ As shown or NULL if the file name and line number should not be printed. + * \param __LINE__ As shown + * + * The remaining arguments are just like the arguments to the C printf routine. + * ::errVerbose determines if the filename and line number are shown. + */ LIBCOM_API void errPrintf(long status, const char *pFileName, int lineno, const char *pformat, ...) EPICS_PRINTF_STYLE(4,5); @@ -83,6 +238,13 @@ LIBCOM_API int errlogPrintfNoConsole(const char *pformat, ...) EPICS_PRINTF_STYLE(1,2); LIBCOM_API int errlogVprintfNoConsole(const char *pformat,va_list pvar); +/** + * Lookup the status code and return the string value in pBuf + * + * \param status The status code to lookup + * \param pBuf The char buffer to write the string value into + * \param bufLength The max size of pBuf + */ LIBCOM_API void errSymLookup(long status, char *pBuf, size_t bufLength); #ifdef __cplusplus diff --git a/modules/libcom/src/freeList/freeList.h b/modules/libcom/src/freeList/freeList.h index c259c1700..3cf978cb6 100644 --- a/modules/libcom/src/freeList/freeList.h +++ b/modules/libcom/src/freeList/freeList.h @@ -7,7 +7,17 @@ * EPICS Base is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ -/* Author: Marty Kraimer Date: 04-19-94 */ +/** + * \file freeList.h + * \author Marty Kraimer + * + * \brief Allocate and free fixed size memory elements. + * + * \details + * Describes routines to allocate and free fixed size memory elements. + * Free elements are maintained on a free list rather than being returned to the heap via calls to free. + * When it is necessary to call malloc(), memory is allocated in multiples of the element size. + */ #ifndef INCfreeListh #define INCfreeListh @@ -19,7 +29,7 @@ extern "C" { #endif -LIBCOM_API void epicsStdCall freeListInitPvt(void **ppvt,int size,int nmalloc); +LIBCOM_API void epicsStdCall freeListInitPvt(void **ppvt, int size, int malloc); LIBCOM_API void * epicsStdCall freeListCalloc(void *pvt); LIBCOM_API void * epicsStdCall freeListMalloc(void *pvt); LIBCOM_API void epicsStdCall freeListFree(void *pvt,void*pmem); @@ -31,3 +41,4 @@ LIBCOM_API size_t epicsStdCall freeListItemsAvail(void *pvt); #endif #endif /*INCfreeListh*/ + \ No newline at end of file diff --git a/modules/libcom/src/freeList/freeListLib.c b/modules/libcom/src/freeList/freeListLib.c old mode 100755 new mode 100644 diff --git a/modules/libcom/src/iocsh/iocsh.cpp b/modules/libcom/src/iocsh/iocsh.cpp index b626e1530..69313bd5e 100644 --- a/modules/libcom/src/iocsh/iocsh.cpp +++ b/modules/libcom/src/iocsh/iocsh.cpp @@ -163,7 +163,12 @@ const iocshCmdDef * epicsStdCall iocshFindCommand(const char *name) static const iocshArg varCmdArg0 = { "[variable", iocshArgString}; static const iocshArg varCmdArg1 = { "[value]]", iocshArgString}; static const iocshArg *varCmdArgs[2] = {&varCmdArg0, &varCmdArg1}; -static const iocshFuncDef varFuncDef = {"var", 2, varCmdArgs}; +static const iocshFuncDef varFuncDef = {"var", 2, varCmdArgs, + "Print all, print single variable or set value to single variable\n" + " (default) - print all variables and their values" + " defined in database definitions files\n" + " variable - if only parameter print value for this variable\n" + " value - set the value to variable\n"}; void epicsStdCall iocshRegisterVariable (const iocshVarDef *piocshVarDef) { @@ -1121,17 +1126,26 @@ static void varHandler(const iocshVarDef *v, const char *setString) static void varCallFunc(const iocshArgBuf *args) { struct iocshVariable *v; - if(args[0].sval == NULL) { + const char *name = args[0].sval; + const char *value = args[1].sval; + + if (!value) { + int found = 0; for (v = iocshVariableHead ; v != NULL ; v = v->next) - varHandler(v->pVarDef, args[1].sval); + if (!name || epicsStrGlobMatch(v->pVarDef->name, name) != 0) { + varHandler(v->pVarDef, NULL); + found = 1; + } + if (!found && name != NULL) + fprintf(epicsGetStderr(), "No var matching %s found.\n", name); } else { v = (iocshVariable *)registryFind(iocshVarID, args[0].sval); if (v == NULL) { - fprintf(epicsGetStderr(), "Var %s not found.\n", args[0].sval); + fprintf(epicsGetStderr(), "Var %s not found.\n", name); } else { - varHandler(v->pVarDef, args[1].sval); + varHandler(v->pVarDef, value); } } } @@ -1139,7 +1153,10 @@ static void varCallFunc(const iocshArgBuf *args) /* iocshCmd */ static const iocshArg iocshCmdArg0 = { "command",iocshArgString}; static const iocshArg *iocshCmdArgs[1] = {&iocshCmdArg0}; -static const iocshFuncDef iocshCmdFuncDef = {"iocshCmd",1,iocshCmdArgs}; +static const iocshFuncDef iocshCmdFuncDef = {"iocshCmd",1,iocshCmdArgs, + "Takes a single IOC shell command and executes it\n" + " * This function is most useful to execute a single IOC shell command\n" + " from vxWorks or RTEMS startup script (or command line)\n"}; static void iocshCmdCallFunc(const iocshArgBuf *args) { iocshCmd(args[0].sval); @@ -1149,7 +1166,9 @@ static void iocshCmdCallFunc(const iocshArgBuf *args) static const iocshArg iocshLoadArg0 = { "pathname",iocshArgString}; static const iocshArg iocshLoadArg1 = { "macros", iocshArgString}; static const iocshArg *iocshLoadArgs[2] = {&iocshLoadArg0, &iocshLoadArg1}; -static const iocshFuncDef iocshLoadFuncDef = {"iocshLoad",2,iocshLoadArgs}; +static const iocshFuncDef iocshLoadFuncDef = {"iocshLoad",2,iocshLoadArgs, + "Execute IOC shell commands provided in file from first parameter\n" + " * (optional) replace macros within the file with provided values\n"}; static void iocshLoadCallFunc(const iocshArgBuf *args) { iocshLoad(args[0].sval, args[1].sval); @@ -1159,7 +1178,10 @@ static void iocshLoadCallFunc(const iocshArgBuf *args) static const iocshArg iocshRunArg0 = { "command",iocshArgString}; static const iocshArg iocshRunArg1 = { "macros", iocshArgString}; static const iocshArg *iocshRunArgs[2] = {&iocshRunArg0, &iocshRunArg1}; -static const iocshFuncDef iocshRunFuncDef = {"iocshRun",2,iocshRunArgs}; +static const iocshFuncDef iocshRunFuncDef = {"iocshRun",2,iocshRunArgs, + "Takes a single IOC shell command, replaces macros and executes it\n" + " * This function is most useful to execute a single IOC shell command\n" + " from vxWorks or RTEMS startup script (or command line)\n"}; static void iocshRunCallFunc(const iocshArgBuf *args) { iocshRun(args[0].sval, args[1].sval); diff --git a/modules/libcom/src/iocsh/libComRegister.c b/modules/libcom/src/iocsh/libComRegister.c index 12ec7a9fe..431951a01 100644 --- a/modules/libcom/src/iocsh/libComRegister.c +++ b/modules/libcom/src/iocsh/libComRegister.c @@ -27,6 +27,30 @@ #include "epicsGeneralTime.h" #include "libComRegister.h" +/* Register the PWD environment variable when the cd IOC shell function is + * registered. This variable contains the current directory path. + */ +static void updatePWD() { + static int lasterror; + char buf[1024]; + char *pwd = getcwd(buf, sizeof(buf)); + if (pwd) { + pwd[sizeof(buf) - 1] = '\0'; + lasterror = 0; + epicsEnvSet("PWD", buf); + } else { + if(lasterror!=errno) { + lasterror = errno; + if (errno == ERANGE) { + fprintf(stderr, "Warning: Current path exceeds %u characters\n", + (unsigned)sizeof(buf)); + } else { + perror("getcwd"); + } + fprintf(stderr, "Warning: Unable to update $PWD\n"); + } + } +} /* date */ void date(const char *format) @@ -46,7 +70,9 @@ void date(const char *format) static const iocshArg dateArg0 = { "format",iocshArgString}; static const iocshArg * const dateArgs[] = {&dateArg0}; -static const iocshFuncDef dateFuncDef = {"date", 1, dateArgs}; +static const iocshFuncDef dateFuncDef = {"date", 1, dateArgs, + "Print current date and time\n" + " (default) - '%Y/%m/%d %H:%M:%S.%06f'\n"}; static void dateCallFunc (const iocshArgBuf *args) { date(args[0].sval); @@ -64,7 +90,8 @@ IOCSH_STATIC_FUNC void echo(char* str) static const iocshArg echoArg0 = { "string",iocshArgString}; static const iocshArg * const echoArgs[1] = {&echoArg0}; -static const iocshFuncDef echoFuncDef = {"echo",1,echoArgs}; +static const iocshFuncDef echoFuncDef = {"echo",1,echoArgs, + "Print string after expanding macros and environment variables\n"}; static void echoCallFunc(const iocshArgBuf *args) { echo(args[0].sval); @@ -73,22 +100,27 @@ static void echoCallFunc(const iocshArgBuf *args) /* chdir */ static const iocshArg chdirArg0 = { "directory name",iocshArgString}; static const iocshArg * const chdirArgs[1] = {&chdirArg0}; -static const iocshFuncDef chdirFuncDef = {"cd",1,chdirArgs}; +static const iocshFuncDef chdirFuncDef = {"cd",1,chdirArgs, + "Change directory to new directory provided as parameter\n"}; static void chdirCallFunc(const iocshArgBuf *args) { if (args[0].sval == NULL || iocshSetError(chdir(args[0].sval))) { fprintf(stderr, "Invalid directory path, ignored\n"); + } else { + updatePWD(); } } /* print current working directory */ -static const iocshFuncDef pwdFuncDef = { "pwd", 0, 0 }; +static const iocshFuncDef pwdFuncDef = {"pwd", 0, 0, + "Print name of current/working directory\n"}; static void pwdCallFunc (const iocshArgBuf *args) { - char buf[256]; - char *pwd = getcwd ( buf, sizeof(buf) - 1 ); + char buf[1024]; + char *pwd = getcwd ( buf, sizeof(buf) ); if ( pwd ) { + buf[sizeof(buf)-1u] = '\0'; printf ( "%s\n", pwd ); } } @@ -97,7 +129,8 @@ static void pwdCallFunc (const iocshArgBuf *args) static const iocshArg epicsEnvSetArg0 = { "name",iocshArgString}; static const iocshArg epicsEnvSetArg1 = { "value",iocshArgString}; static const iocshArg * const epicsEnvSetArgs[2] = {&epicsEnvSetArg0,&epicsEnvSetArg1}; -static const iocshFuncDef epicsEnvSetFuncDef = {"epicsEnvSet",2,epicsEnvSetArgs}; +static const iocshFuncDef epicsEnvSetFuncDef = {"epicsEnvSet",2,epicsEnvSetArgs, + "Set environment variable name to value\n"}; static void epicsEnvSetCallFunc(const iocshArgBuf *args) { char *name = args[0].sval; @@ -117,7 +150,8 @@ static void epicsEnvSetCallFunc(const iocshArgBuf *args) /* epicsEnvUnset */ static const iocshArg epicsEnvUnsetArg0 = { "name",iocshArgString}; static const iocshArg * const epicsEnvUnsetArgs[1] = {&epicsEnvUnsetArg0}; -static const iocshFuncDef epicsEnvUnsetFuncDef = {"epicsEnvUnset",1,epicsEnvUnsetArgs}; +static const iocshFuncDef epicsEnvUnsetFuncDef = {"epicsEnvUnset",1,epicsEnvUnsetArgs, + "Remove variable name from the environment\n"}; static void epicsEnvUnsetCallFunc(const iocshArgBuf *args) { char *name = args[0].sval; @@ -135,14 +169,16 @@ IOCSH_STATIC_FUNC void epicsParamShow() epicsPrtEnvParams (); } -static const iocshFuncDef epicsParamShowFuncDef = {"epicsParamShow",0,NULL}; +static const iocshFuncDef epicsParamShowFuncDef = {"epicsParamShow",0,NULL, + "Show the environment variable parameters used by iocCore\n"}; static void epicsParamShowCallFunc(const iocshArgBuf *args) { epicsParamShow (); } /* epicsPrtEnvParams */ -static const iocshFuncDef epicsPrtEnvParamsFuncDef = {"epicsPrtEnvParams",0,0}; +static const iocshFuncDef epicsPrtEnvParamsFuncDef = {"epicsPrtEnvParams",0,0, + "Show the environment variable parameters used by iocCore\n"}; static void epicsPrtEnvParamsCallFunc(const iocshArgBuf *args) { epicsPrtEnvParams (); @@ -151,21 +187,29 @@ static void epicsPrtEnvParamsCallFunc(const iocshArgBuf *args) /* epicsEnvShow */ static const iocshArg epicsEnvShowArg0 = { "[name]",iocshArgString}; static const iocshArg * const epicsEnvShowArgs[1] = {&epicsEnvShowArg0}; -static const iocshFuncDef epicsEnvShowFuncDef = {"epicsEnvShow",1,epicsEnvShowArgs}; +static const iocshFuncDef epicsEnvShowFuncDef = {"epicsEnvShow",1,epicsEnvShowArgs, + "Show environment variables on your system\n" + " (default) - show all environment variables\n" + " name - show value of specific environment variable\n"}; static void epicsEnvShowCallFunc(const iocshArgBuf *args) { epicsEnvShow (args[0].sval); } /* registryDump */ -static const iocshFuncDef registryDumpFuncDef = {"registryDump",0,NULL}; +static const iocshFuncDef registryDumpFuncDef = {"registryDump",0,NULL, + "Dump a hash table of EPICS registry\n"}; static void registryDumpCallFunc(const iocshArgBuf *args) { registryDump (); } /* iocLogInit */ -static const iocshFuncDef iocLogInitFuncDef = {"iocLogInit",0}; +static const iocshFuncDef iocLogInitFuncDef = {"iocLogInit",0,0, + "Initialize IOC logging\n" + " * EPICS environment variable 'EPICS_IOC_LOG_INET' has to be defined\n" + " * Logging controled via 'iocLogDisable' variable\n" + " see 'setIocLogDisable' command\n"}; static void iocLogInitCallFunc(const iocshArgBuf *args) { iocLogInit (); @@ -179,7 +223,10 @@ IOCSH_STATIC_FUNC void setIocLogDisable(int val) static const iocshArg iocLogDisableArg0 = {"(0,1)=>(false,true)",iocshArgInt}; static const iocshArg * const iocLogDisableArgs[1] = {&iocLogDisableArg0}; -static const iocshFuncDef iocLogDisableFuncDef = {"setIocLogDisable",1,iocLogDisableArgs}; +static const iocshFuncDef iocLogDisableFuncDef = {"setIocLogDisable",1,iocLogDisableArgs, + "Controls the 'iocLogDisable' variable\n" + " 0 - enable logging\n" + " 1 - disable logging\n"}; static void iocLogDisableCallFunc(const iocshArgBuf *args) { setIocLogDisable(args[0].ival); @@ -188,7 +235,8 @@ static void iocLogDisableCallFunc(const iocshArgBuf *args) /* iocLogShow */ static const iocshArg iocLogShowArg0 = {"level",iocshArgInt}; static const iocshArg * const iocLogShowArgs[1] = {&iocLogShowArg0}; -static const iocshFuncDef iocLogShowFuncDef = {"iocLogShow",1,iocLogShowArgs}; +static const iocshFuncDef iocLogShowFuncDef = {"iocLogShow",1,iocLogShowArgs, + "Determine if a IOC Log Prefix has been set\n"}; static void iocLogShowCallFunc(const iocshArgBuf *args) { iocLogShow (args[0].ival); @@ -197,17 +245,22 @@ static void iocLogShowCallFunc(const iocshArgBuf *args) /* eltc */ static const iocshArg eltcArg0 = {"(0,1)=>(false,true)",iocshArgInt}; static const iocshArg * const eltcArgs[1] = {&eltcArg0}; -static const iocshFuncDef eltcFuncDef = {"eltc",1,eltcArgs}; +static const iocshFuncDef eltcFuncDef = {"eltc",1,eltcArgs, + "Control display of error log messages on console\n" + " 0 - no\n" + " 1 - yes (default)\n"}; static void eltcCallFunc(const iocshArgBuf *args) { eltc(args[0].ival); } /* errlogInit */ -static const iocshArg errlogInitArg0 = { "bufsize",iocshArgInt}; +static const iocshArg errlogInitArg0 = { "bufSize",iocshArgInt}; static const iocshArg * const errlogInitArgs[1] = {&errlogInitArg0}; static const iocshFuncDef errlogInitFuncDef = - {"errlogInit",1,errlogInitArgs}; + {"errlogInit",1,errlogInitArgs, + "Initialize error log client buffer size\n" + " bufSize - size of circular buffer (default = 1280 bytes)\n"}; static void errlogInitCallFunc(const iocshArgBuf *args) { errlogInit(args[0].ival); @@ -219,7 +272,10 @@ static const iocshArg errlogInit2Arg1 = { "maxMsgSize",iocshArgInt}; static const iocshArg * const errlogInit2Args[] = {&errlogInit2Arg0, &errlogInit2Arg1}; static const iocshFuncDef errlogInit2FuncDef = - {"errlogInit2", 2, errlogInit2Args}; + {"errlogInit2", 2, errlogInit2Args, + "Initialize error log client buffer size and maximum message size\n" + " bufSize - size of circular buffer (default = 1280 bytes)\n" + " maxMsgSize - maximum size of error message (default = 256 bytes)\n"}; static void errlogInit2CallFunc(const iocshArgBuf *args) { errlogInit2(args[0].ival, args[1].ival); @@ -233,7 +289,8 @@ IOCSH_STATIC_FUNC void errlog(const char *message) static const iocshArg errlogArg0 = { "message",iocshArgString}; static const iocshArg * const errlogArgs[1] = {&errlogArg0}; -static const iocshFuncDef errlogFuncDef = {"errlog",1,errlogArgs}; +static const iocshFuncDef errlogFuncDef = {"errlog",1,errlogArgs, + "Send message to errlog\n"}; static void errlogCallFunc(const iocshArgBuf *args) { errlog(args[0].sval); @@ -243,7 +300,8 @@ static void errlogCallFunc(const iocshArgBuf *args) /* iocLogPrefix */ static const iocshArg iocLogPrefixArg0 = { "prefix",iocshArgString}; static const iocshArg * const iocLogPrefixArgs[1] = {&iocLogPrefixArg0}; -static const iocshFuncDef iocLogPrefixFuncDef = {"iocLogPrefix",1,iocLogPrefixArgs}; +static const iocshFuncDef iocLogPrefixFuncDef = {"iocLogPrefix",1,iocLogPrefixArgs, + "Create the prefix for all messages going into IOC log\n"}; static void iocLogPrefixCallFunc(const iocshArgBuf *args) { iocLogPrefix(args[0].sval); @@ -253,7 +311,8 @@ static void iocLogPrefixCallFunc(const iocshArgBuf *args) static const iocshArg epicsThreadShowAllArg0 = { "level",iocshArgInt}; static const iocshArg * const epicsThreadShowAllArgs[1] = {&epicsThreadShowAllArg0}; static const iocshFuncDef epicsThreadShowAllFuncDef = - {"epicsThreadShowAll",1,epicsThreadShowAllArgs}; + {"epicsThreadShowAll",1,epicsThreadShowAllArgs, + "Display info about all threads\n"}; static void epicsThreadShowAllCallFunc(const iocshArgBuf *args) { epicsThreadShowAll(args[0].ival); @@ -262,7 +321,8 @@ static void epicsThreadShowAllCallFunc(const iocshArgBuf *args) /* epicsThreadShow */ static const iocshArg threadArg0 = { "[-level] [thread ...]", iocshArgArgv}; static const iocshArg * const threadArgs[1] = { &threadArg0 }; -static const iocshFuncDef threadFuncDef = {"epicsThreadShow",1,threadArgs}; +static const iocshFuncDef threadFuncDef = {"epicsThreadShow",1,threadArgs, + "Display info about the specified thread\n"}; static void threadCallFunc(const iocshArgBuf *args) { int i = 1; @@ -308,7 +368,8 @@ static void threadCallFunc(const iocshArgBuf *args) static const iocshArg taskwdShowArg0 = { "level",iocshArgInt}; static const iocshArg * const taskwdShowArgs[1] = {&taskwdShowArg0}; static const iocshFuncDef taskwdShowFuncDef = - {"taskwdShow",1,taskwdShowArgs}; + {"taskwdShow",1,taskwdShowArgs, + "Show number of tasks and monitors registered\n"}; static void taskwdShowCallFunc(const iocshArgBuf *args) { taskwdShow(args[0].ival); @@ -320,7 +381,10 @@ static const iocshArg epicsMutexShowAllArg1 = { "level",iocshArgInt}; static const iocshArg * const epicsMutexShowAllArgs[2] = {&epicsMutexShowAllArg0,&epicsMutexShowAllArg1}; static const iocshFuncDef epicsMutexShowAllFuncDef = - {"epicsMutexShowAll",2,epicsMutexShowAllArgs}; + {"epicsMutexShowAll",2,epicsMutexShowAllArgs, + "Display information about all epicsMutex semaphores\n" + " onlyLocked - non-zero to show only locked semaphores\n" + " level - desired information level to report\n"}; static void epicsMutexShowAllCallFunc(const iocshArgBuf *args) { epicsMutexShowAll(args[0].ival,args[1].ival); @@ -330,7 +394,8 @@ static void epicsMutexShowAllCallFunc(const iocshArgBuf *args) static const iocshArg epicsThreadSleepArg0 = { "seconds",iocshArgDouble}; static const iocshArg * const epicsThreadSleepArgs[1] = {&epicsThreadSleepArg0}; static const iocshFuncDef epicsThreadSleepFuncDef = - {"epicsThreadSleep",1,epicsThreadSleepArgs}; + {"epicsThreadSleep",1,epicsThreadSleepArgs, + "Pause execution of IOC shell for seconds\n"}; static void epicsThreadSleepCallFunc(const iocshArgBuf *args) { epicsThreadSleep(args[0].dval); @@ -339,7 +404,10 @@ static void epicsThreadSleepCallFunc(const iocshArgBuf *args) /* epicsThreadResume */ static const iocshArg epicsThreadResumeArg0 = { "[thread ...]", iocshArgArgv}; static const iocshArg * const epicsThreadResumeArgs[1] = { &epicsThreadResumeArg0 }; -static const iocshFuncDef epicsThreadResumeFuncDef = {"epicsThreadResume",1,epicsThreadResumeArgs}; +static const iocshFuncDef epicsThreadResumeFuncDef = {"epicsThreadResume",1,epicsThreadResumeArgs, + "Resume a suspended thread.\n" + "Only do this if you know that it is safe to " + "resume a suspended thread\n"}; static void epicsThreadResumeCallFunc(const iocshArgBuf *args) { int i; @@ -381,14 +449,19 @@ static void epicsThreadResumeCallFunc(const iocshArgBuf *args) /* generalTimeReport */ static const iocshArg generalTimeReportArg0 = { "interest_level", iocshArgArgv}; static const iocshArg * const generalTimeReportArgs[1] = { &generalTimeReportArg0 }; -static const iocshFuncDef generalTimeReportFuncDef = {"generalTimeReport",1,generalTimeReportArgs}; +static const iocshFuncDef generalTimeReportFuncDef = {"generalTimeReport",1,generalTimeReportArgs, + "Display time providers and their priority levels" + " for current and event times\n"}; static void generalTimeReportCallFunc(const iocshArgBuf *args) { generalTimeReport(args[0].ival); } /* installLastResortEventProvider */ -static const iocshFuncDef installLastResortEventProviderFuncDef = {"installLastResortEventProvider", 0, NULL}; +static const iocshFuncDef installLastResortEventProviderFuncDef = {"installLastResortEventProvider", 0, NULL, + "Installs the optional Last Resort event provider" + " at priority 999,\nwhich returns the current time" + " for every event number\n"}; static void installLastResortEventProviderCallFunc(const iocshArgBuf *args) { installLastResortEventProvider(); @@ -403,6 +476,8 @@ void epicsStdCall libComRegister(void) iocshRegister(&chdirFuncDef, chdirCallFunc); iocshRegister(&pwdFuncDef, pwdCallFunc); + updatePWD(); + iocshRegister(&epicsEnvSetFuncDef, epicsEnvSetCallFunc); iocshRegister(&epicsEnvUnsetFuncDef, epicsEnvUnsetCallFunc); iocshRegister(&epicsParamShowFuncDef, epicsParamShowCallFunc); diff --git a/modules/libcom/src/log/Makefile b/modules/libcom/src/log/Makefile index 2dcfbc516..74d173575 100644 --- a/modules/libcom/src/log/Makefile +++ b/modules/libcom/src/log/Makefile @@ -24,5 +24,5 @@ iocLogServer_SYS_LIBS_WIN32 += user32 ws2_32 dbghelp SCRIPTS_HOST = S99logServer EXPAND += S99logServer@ -EXPAND_VARS = INSTALL_BIN=$(abspath $(INSTALL_BIN)) +EXPAND_VARS = INSTALL_BIN=$(FINAL_LOCATION)/bin/$(T_A) diff --git a/modules/libcom/src/misc/epicsStdlib.h b/modules/libcom/src/misc/epicsStdlib.h index 219a1fb0a..e3cb69f91 100644 --- a/modules/libcom/src/misc/epicsStdlib.h +++ b/modules/libcom/src/misc/epicsStdlib.h @@ -13,6 +13,20 @@ #ifndef INC_epicsStdlib_H #define INC_epicsStdlib_H +/** + * \file epicsStdlib.h + * \brief Functions to convert strings to primative types + * + * These routines convert a string into an integer of the indicated type and + * number base, or into a floating point type. The units pointer argument may + * be NULL, but if not it will be left pointing to the first non-whitespace + * character following the numeric string, or to the terminating zero byte. + * + * The return value from these routines is a status code, zero meaning OK. + * For the macro functions beginning with `epicsScan` the return code is 0 + * or 1 (0=failure or 1=success, similar to the sscanf() function). + */ + #include #include @@ -25,57 +39,167 @@ extern "C" { #endif +/** Return code for `No digits to convert` */ #define S_stdlib_noConversion (M_stdlib | 1) /* No digits to convert */ +/** Return code for `Extraneous characters` */ #define S_stdlib_extraneous (M_stdlib | 2) /* Extraneous characters */ +/** Return code for `Too small to represent` */ #define S_stdlib_underflow (M_stdlib | 3) /* Too small to represent */ +/** Return code for `Too large to represent` */ #define S_stdlib_overflow (M_stdlib | 4) /* Too large to represent */ +/** Return code for `Number base not supported` */ #define S_stdlib_badBase (M_stdlib | 5) /* Number base not supported */ - -LIBCOM_API int +/** + * \brief Convert a string to a long type + * + * \param str Pointer to a constant character array + * \param to Pointer to the specified type (this will be set during the conversion) + * \param base The number base to use + * \param units Pointer to a char * (this will be set with the units string) + * \return Status code (0=OK, see macro definitions for possible errors) + */ +LIBCOM_API int epicsParseLong(const char *str, long *to, int base, char **units); + +/** + * \brief Convert a string to a unsigned long type + * \copydetails epicsParseLong + */ LIBCOM_API int epicsParseULong(const char *str, unsigned long *to, int base, char **units); + +/** + * \brief Convert a string to a long long type + * \copydetails epicsParseLong + */ LIBCOM_API int epicsParseLLong(const char *str, long long *to, int base, char **units); + +/** + * \brief Convert a string to a unsigned long long type + * \copydetails epicsParseLong + */ LIBCOM_API int epicsParseULLong(const char *str, unsigned long long *to, int base, char **units); + +/** + * \brief Convert a string to a double type + * + * \param str Pointer to a constant character array + * \param to Pointer to the specified type (this will be set during the conversion) + * \param units Pointer to a char * (this will be set with the units string) + * \return Status code (0=OK, see macro definitions for possible errors) + */ LIBCOM_API int epicsParseDouble(const char *str, double *to, char **units); +/** + * \brief Convert a string to a float type + * \copydetails epicsParseDouble + */ LIBCOM_API int epicsParseFloat(const char *str, float *to, char **units); +/** + * \brief Convert a string to an epicsInt8 type + * \copydetails epicsParseLong + */ LIBCOM_API int epicsParseInt8(const char *str, epicsInt8 *to, int base, char **units); + +/** + * \brief Convert a string to an epicsUInt8 type + * \copydetails epicsParseLong + */ LIBCOM_API int epicsParseUInt8(const char *str, epicsUInt8 *to, int base, char **units); + +/** + * \brief Convert a string to an epicsInt16 type + * \copydetails epicsParseLong + */ LIBCOM_API int epicsParseInt16(const char *str, epicsInt16 *to, int base, char **units); + +/** + * \brief Convert a string to an epicsUInt16 type + * \copydetails epicsParseLong + */ LIBCOM_API int epicsParseUInt16(const char *str, epicsUInt16 *to, int base, char **units); +/** + * \brief Convert a string to an epicsInt32 type + * \copydetails epicsParseLong + */ LIBCOM_API int epicsParseInt32(const char *str, epicsInt32 *to, int base, char **units); + +/** + * \brief Convert a string to an epicsUInt32 type + * \copydetails epicsParseLong + */ LIBCOM_API int epicsParseUInt32(const char *str, epicsUInt32 *to, int base, char **units); +/** + * \brief Convert a string to an epicsInt64 type + * \copydetails epicsParseLong + */ LIBCOM_API int epicsParseInt64(const char *str, epicsInt64 *to, int base, char **units); + +/** + * \brief Convert a string to an epicsUInt64 type + * \copydetails epicsParseLong + */ LIBCOM_API int epicsParseUInt64(const char *str, epicsUInt64 *to, int base, char **units); +/** Macro utilizing ::epicsParseFloat to convert */ #define epicsParseFloat32(str, to, units) epicsParseFloat(str, to, units) +/** Macro utilizing ::epicsParseDouble to convert */ #define epicsParseFloat64(str, to, units) epicsParseDouble(str, to, units) /* These macros return 1 if successful, 0 on failure. * This is analagous to the return value from sscanf() */ + +/** + * Macro utilizing ::epicsParseLong to convert + * \return 0=failure, 1=success + */ #define epicsScanLong(str, to, base) (!epicsParseLong(str, to, base, NULL)) + +/** + * Macro utilizing ::epicsParseULong to convert + * \return 0=failure, 1=success + */ #define epicsScanULong(str, to, base) (!epicsParseULong(str, to, base, NULL)) + +/** + * Macro utilizing ::epicsParseLLong to convert + * \return 0=failure, 1=success + */ #define epicsScanLLong(str, to, base) (!epicsParseLLong(str, to, base, NULL)) + +/** + * Macro utilizing ::epicsParseULLong to convert + * \return 0=failure, 1=success + */ #define epicsScanULLong(str, to, base) (!epicsParseULLong(str, to, base, NULL)) + +/** + * Macro utilizing ::epicsParseFloat to convert + * \return 0=failure, 1=success + */ #define epicsScanFloat(str, to) (!epicsParseFloat(str, to, NULL)) + +/** + * Macro utilizing ::epicsParseDouble to convert + * \return 0=failure, 1=success + */ #define epicsScanDouble(str, to) (!epicsParseDouble(str, to, NULL)) #ifdef __cplusplus diff --git a/modules/libcom/src/misc/epicsString.c b/modules/libcom/src/misc/epicsString.c index e18d9214a..be6463438 100644 --- a/modules/libcom/src/misc/epicsString.c +++ b/modules/libcom/src/misc/epicsString.c @@ -23,6 +23,15 @@ #include #include +#ifndef vxWorks +#include +#else +/* VxWorks automaticaly includes stdint.h defining SIZE_MAX in 6.9 but not earlier */ +#ifndef SIZE_MAX +#define SIZE_MAX (size_t)-1 +#endif +#endif + #include "epicsAssert.h" #include "epicsStdio.h" #include "cantProceed.h" @@ -259,30 +268,31 @@ size_t epicsStrnLen(const char *s, size_t maxlen) return i; } -int epicsStrGlobMatch(const char *str, const char *pattern) +int epicsStrnGlobMatch(const char *str, size_t len, const char *pattern) { - const char *cp = NULL, *mp = NULL; + const char *mp = NULL; + size_t cp = 0, i = 0; - while ((*str) && (*pattern != '*')) { - if ((*pattern != *str) && (*pattern != '?')) + while ((i < len) && (str[i]) && (*pattern != '*')) { + if ((*pattern != str[i]) && (*pattern != '?')) return 0; pattern++; - str++; + i++; } - while (*str) { + while ((i < len) && str[i]) { if (*pattern == '*') { if (!*++pattern) return 1; mp = pattern; - cp = str+1; + cp = i+1; } - else if ((*pattern == *str) || (*pattern == '?')) { + else if ((*pattern == str[i]) || (*pattern == '?')) { pattern++; - str++; + i++; } else { pattern = mp; - str = cp++; + i = cp++; } } while (*pattern == '*') @@ -290,6 +300,10 @@ int epicsStrGlobMatch(const char *str, const char *pattern) return !*pattern; } +int epicsStrGlobMatch(const char *str, const char *pattern) { + return epicsStrnGlobMatch(str, SIZE_MAX, pattern); +} + char * epicsStrtok_r(char *s, const char *delim, char **lasts) { const char *spanp; diff --git a/modules/libcom/src/misc/epicsString.h b/modules/libcom/src/misc/epicsString.h index 854b552c6..5bb8c87c1 100644 --- a/modules/libcom/src/misc/epicsString.h +++ b/modules/libcom/src/misc/epicsString.h @@ -36,7 +36,30 @@ LIBCOM_API char * epicsStrnDup(const char *s, size_t len); LIBCOM_API int epicsStrPrintEscaped(FILE *fp, const char *s, size_t n); #define epicsStrSnPrintEscaped epicsStrnEscapedFromRaw LIBCOM_API size_t epicsStrnLen(const char *s, size_t maxlen); + +/** Matches a string against a pattern. + * + * Checks if str matches the glob style pattern, which may contain ? or * wildcards. + * A ? matches any single character. + * A * matched any sub-string. + * + * @returns 1 if str matches the pattern, 0 if not. + * + * @since EPICS 3.14.7 + */ LIBCOM_API int epicsStrGlobMatch(const char *str, const char *pattern); + +/** Matches a string against a pattern. + * + * Like epicsStrGlobMatch but with limited string length. + * If the length of str is less than len, the full string is matched. + * + * @returns 1 if the first len characters of str match the pattern, 0 if not. + * + * @since UNRELEASED + */ +LIBCOM_API int epicsStrnGlobMatch(const char *str, size_t len, const char *pattern); + LIBCOM_API char * epicsStrtok_r(char *s, const char *delim, char **lasts); LIBCOM_API unsigned int epicsStrHash(const char *str, unsigned int seed); LIBCOM_API unsigned int epicsMemHash(const char *str, size_t length, diff --git a/modules/libcom/src/misc/epicsTypes.h b/modules/libcom/src/misc/epicsTypes.h index 1beb5d2e4..09e550d78 100644 --- a/modules/libcom/src/misc/epicsTypes.h +++ b/modules/libcom/src/misc/epicsTypes.h @@ -8,9 +8,11 @@ * in file LICENSE that is included with this distribution. \*************************************************************************/ -/* - * Author: Jeff Hill - * Date: 5-95 +/** + * \file epicsTypes.h + * \author: Jeff Hill + * + * \brief The core data types used by epics */ #ifndef INC_epicsTypes_H @@ -32,9 +34,12 @@ typedef enum { epicsTrue = 1 } epicsBoolean EPICS_DEPRECATED; -/* +/** + * \name epicsTypes * Architecture Independent Data Types + * * These are sufficient for all our current archs + * @{ */ typedef char epicsInt8; typedef unsigned char epicsUInt8; @@ -49,25 +54,28 @@ typedef epicsUInt16 epicsEnum16; typedef float epicsFloat32; typedef double epicsFloat64; typedef epicsInt32 epicsStatus; + /** @} */ +#define MAX_STRING_SIZE 40 +/** + * \brief !! Dont use this - it may vanish in the future !! + */ typedef struct { unsigned length; char *pString; } epicsString; -/* - * !! Dont use this - it may vanish in the future !! +/** + * \brief !! Dont use this - it may vanish in the future !! * * Provided only for backwards compatibility with * db_access.h - * */ -#define MAX_STRING_SIZE 40 typedef char epicsOldString[MAX_STRING_SIZE]; -/* - * union of all types +/** + * \brief Union of all types * * Strings included here as pointers only so that we support * large string types. @@ -90,11 +98,11 @@ typedef union epics_any { epicsString string; } epicsAny; -/* - * Corresponding Type Codes +/** + * \brief Corresponding Type Codes * (this enum must start at zero) * - * !! Update epicsTypeToDBR_XXXX[] and DBR_XXXXToEpicsType + * !! Update \ref epicsTypeToDBR_XXXX[] and \ref DBR_XXXXToEpicsType * in db_access.h if you edit this enum !! */ typedef enum { @@ -116,8 +124,9 @@ typedef enum { #define invalidEpicsType(x) ((xlastEpicsType)) -/* - * The enumeration "epicsType" is an index to this array +/** + * \brief An array providing the names for each type + * The enumeration \ref epicsType is an index to this array * of type name strings. */ #ifdef epicsTypesGLOBAL @@ -138,8 +147,9 @@ const char *epicsTypeNames [lastEpicsType+1] = { LIBCOM_API extern const char *epicsTypeNames [lastEpicsType+1]; #endif /* epicsTypesGLOBAL */ -/* - * The enumeration "epicsType" is an index to this array +/** + * \brief An array providing the names for each type code + * The enumeration \ref epicsType is an index to this array * of type code name strings. */ #ifdef epicsTypesGLOBAL @@ -160,6 +170,11 @@ const char *epicsTypeCodeNames [lastEpicsType+1] = { LIBCOM_API extern const char *epicsTypeCodeNames [lastEpicsType+1]; #endif /* epicsTypesGLOBAL */ +/** + * \brief An array providing the sizes for each type + * The enumeration \ref epicsType is an index to this array + * of type code name strings. + */ #ifdef epicsTypesGLOBAL const unsigned epicsTypeSizes [lastEpicsType+1] = { sizeof (epicsInt8), @@ -178,10 +193,6 @@ const unsigned epicsTypeSizes [lastEpicsType+1] = { LIBCOM_API extern const unsigned epicsTypeSizes [lastEpicsType+1]; #endif /* epicsTypesGLOBAL */ -/* - * The enumeration "epicsType" is an index to this array - * of type class identifiers. - */ typedef enum { epicsIntC, epicsUIntC, @@ -191,6 +202,11 @@ typedef enum { epicsOldStringC } epicsTypeClass; +/** + * \brief An array providing the class of each type + * The enumeration \ref epicsType is an index to this array + * of type class identifiers. + */ #ifdef epicsTypesGLOBAL const epicsTypeClass epicsTypeClasses [lastEpicsType+1] = { epicsIntC, @@ -209,7 +225,11 @@ const epicsTypeClass epicsTypeClasses [lastEpicsType+1] = { LIBCOM_API extern const epicsTypeClass epicsTypeClasses [lastEpicsType+1]; #endif /* epicsTypesGLOBAL */ - +/** + * \brief An array providing the field name for each type + * The enumeration \ref epicsType is an index to this array + * of type code name strings. + */ #ifdef epicsTypesGLOBAL const char *epicsTypeAnyFieldName [lastEpicsType+1] = { "int8", diff --git a/modules/libcom/src/osi/epicsThread.h b/modules/libcom/src/osi/epicsThread.h index f294c1d75..a9ad476b3 100644 --- a/modules/libcom/src/osi/epicsThread.h +++ b/modules/libcom/src/osi/epicsThread.h @@ -59,6 +59,7 @@ #include #include "libComAPI.h" +#include "compilerDependencies.h" #ifdef __cplusplus extern "C" { @@ -142,8 +143,12 @@ LIBCOM_API void epicsThreadRealtimeLock(void); * call this routine. This should be the last call in main, except the * final return. On most systems epicsThreadExitMain never returns.This * must only be called by the main thread. + * + * @deprecated Deprecated for lack of use. Please report any usage. + * Recommended replacement is loop + epicsThreadSleep(), + * epicsEventMustWait(), or similar. **/ -LIBCOM_API void epicsStdCall epicsThreadExitMain(void); +LIBCOM_API void epicsStdCall epicsThreadExitMain(void) EPICS_DEPRECATED; /** For use with epicsThreadCreateOpt() */ typedef struct epicsThreadOpts { diff --git a/modules/libcom/src/osi/epicsTime.h b/modules/libcom/src/osi/epicsTime.h index 0c3587fef..090fb5c48 100644 --- a/modules/libcom/src/osi/epicsTime.h +++ b/modules/libcom/src/osi/epicsTime.h @@ -36,6 +36,10 @@ typedef struct epicsTimeStamp { epicsUInt32 nsec; /**< \brief nanoseconds within second */ } epicsTimeStamp; +/** \brief Type of UTAG field (dbCommon::utag) + */ +typedef epicsUInt64 epicsUTag; + /** \brief Old time-stamp data type, deprecated. * \deprecated TS_STAMP was provided for compatibility with Base-3.13 code. * It will be removed in some future release of EPICS 7. diff --git a/modules/libcom/src/osi/os/Darwin/osdEnv.c b/modules/libcom/src/osi/os/Darwin/osdEnv.c deleted file mode 100644 index 8d4b100e3..000000000 --- a/modules/libcom/src/osi/os/Darwin/osdEnv.c +++ /dev/null @@ -1,72 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Saskatchewan -* SPDX-License-Identifier: EPICS -* EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ -/* osdEnv.c */ -/* - * Author: Eric Norum - * Date: May 7, 2001 - * - * Routines to modify/display environment variables and EPICS parameters - * - */ - -#include -#include -#include -#include -#include - -/* - * Starting in Mac OS X 10.5 (Leopard) shared libraries and - * bundles don't have direct access to environ (man environ). - */ -#include -#define environ (*_NSGetEnviron()) - -#include "epicsStdio.h" -#include "envDefs.h" -#include "iocsh.h" - -/* - * Set the value of an environment variable - */ -LIBCOM_API void epicsStdCall epicsEnvSet (const char *name, const char *value) -{ - if (!name) return; - iocshEnvClear(name); - setenv(name, value, 1); -} - -/* - * Unset an environment variable - */ - -LIBCOM_API void epicsStdCall epicsEnvUnset (const char *name) -{ - iocshEnvClear(name); - unsetenv(name); -} - -/* - * Show the value of the specified, or all, environment variables - */ -LIBCOM_API void epicsStdCall epicsEnvShow (const char *name) -{ - if (name == NULL) { - extern char **environ; - char **sp; - - for (sp = environ ; (sp != NULL) && (*sp != NULL) ; sp++) - printf ("%s\n", *sp); - } - else { - const char *cp = getenv (name); - if (cp == NULL) - printf ("%s is not an environment variable.\n", name); - else - printf ("%s=%s\n", name, cp); - } -} diff --git a/modules/libcom/src/osi/os/RTEMS-posix/devLibVMEOSD.c b/modules/libcom/src/osi/os/RTEMS-posix/devLibVMEOSD.c new file mode 100644 index 000000000..8ae1503ec --- /dev/null +++ b/modules/libcom/src/osi/os/RTEMS-posix/devLibVMEOSD.c @@ -0,0 +1,6 @@ +#ifdef RTEMS_LEGACY_STACK +#include "os/RTEMS-score/devLibVMEOSD.c" +#else +#pragma message "\n VME Support requires the RTEMS Legacy stack\n" +#include "os/default/devLibVMEOSD.c" +#endif diff --git a/modules/libcom/src/osi/os/RTEMS-posix/osdMessageQueue.c b/modules/libcom/src/osi/os/RTEMS-posix/osdMessageQueue.c new file mode 100644 index 000000000..7c7ea8aad --- /dev/null +++ b/modules/libcom/src/osi/os/RTEMS-posix/osdMessageQueue.c @@ -0,0 +1,160 @@ +/*************************************************************************\ +* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* National Laboratory. +* Copyright (c) 2002 The Regents of the University of California, as +* Operator of Los Alamos National Laboratory. +* SPDX-License-Identifier: EPICS +* EPICS Base is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ +/* + * Author W. Eric Norum + * norume@aps.anl.gov + * 630 252 4793 + */ + +/* + * We want to access information which is + * normally hidden from application programs. + */ +#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__ 1 + +#define epicsExportSharedSymbols +#include +#include +#include +#include +#include +#include +#include "epicsMessageQueue.h" +#include "errlog.h" +#include + +#include +#include +#include + +static int idCnt; + +LIBCOM_API epicsMessageQueueId epicsStdCall +epicsMessageQueueCreate(unsigned int capacity, unsigned int maximumMessageSize) +{ + struct mq_attr the_attr; + epicsMessageQueueId id = (epicsMessageQueueId)calloc(1, sizeof(*id)); + sprintf(id->name, "MQ_%0d", epicsAtomicIncrIntT(&idCnt)); + the_attr.mq_maxmsg = capacity; + the_attr.mq_msgsize = maximumMessageSize; + id->id = mq_open(id->name, O_RDWR | O_CREAT | O_EXCL, 0644, &the_attr); + if (id->id <0) { + fprintf (stderr, "Can't create message queue: %s\n", strerror (errno)); + return NULL; + } + return id; +} + +LIBCOM_API void epicsStdCall epicsMessageQueueDestroy( + epicsMessageQueueId id) +{ + int rv; + rv = mq_close(id->id); + if( rv ) { + fprintf(stderr, "epicsMessageQueueDestroy mq_close failed: %s\n", + strerror(rv)); + } + rv = mq_unlink(id->name); + if( rv ) { + fprintf(stderr,"epicsMessageQueueDestroy mq_unlink %s failed: %s\n", + id->name, strerror(rv)); + } + free(id); +} + + +LIBCOM_API int epicsStdCall epicsMessageQueueTrySend( + epicsMessageQueueId id, + void *message, + unsigned int messageSize) +{ + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + return mq_timedsend(id->id, (char const *)message, messageSize, 0, &ts); +} + +LIBCOM_API int epicsStdCall epicsMessageQueueSendWithTimeout( + epicsMessageQueueId id, + void *message, + unsigned int messageSize, + double timeout) +{ + struct timespec ts; + unsigned long micros; + + // assume timeout in sec + micros = (unsigned long)(timeout * 1000000.0); + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += micros / 1000000L; + ts.tv_nsec += (micros % 1000000L) * 1000L; + + return mq_timedsend (id->id, (const char *)message, messageSize, 0, &ts); +} + +LIBCOM_API int epicsStdCall epicsMessageQueueTryReceive( + epicsMessageQueueId id, + void *message, + unsigned int size) +{ + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + return mq_timedreceive(id->id, (char *)message, size, NULL, &ts); +} + +LIBCOM_API int epicsStdCall epicsMessageQueueReceiveWithTimeout( + epicsMessageQueueId id, + void *message, + unsigned int size, + double timeout) +{ + unsigned long micros; + struct timespec ts; + + micros = (unsigned long)(timeout * 1000000.0); + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += micros / 1000000L; + ts.tv_nsec += (micros % 1000000L) * 1000L; + + return mq_timedreceive(id->id, (char *)message, size, NULL, &ts); +} + +LIBCOM_API int epicsStdCall epicsMessageQueuePending( + epicsMessageQueueId id) +{ + int rv; + struct mq_attr the_attr; + + rv = mq_getattr(id->id, &the_attr); + if (rv) { + fprintf(stderr, "Epics Message queue %x (%s) get attr failed: %s\n", + (unsigned int)id->id, id->name, strerror(rv)); + return -1; + } + return the_attr.mq_curmsgs; +} +LIBCOM_API void epicsStdCall epicsMessageQueueShow( + epicsMessageQueueId id, + int level) +{ + int rv; + struct mq_attr the_attr; + + rv = mq_getattr(id->id, &the_attr); + if (rv) { + fprintf(stderr, "Epics Message queue %x (%s) get attr failed: %s\n", + (unsigned int)id->id, id->name, strerror(rv)); + } + + printf("Message Queue Used:%ld Max Msg:%lu", the_attr.mq_curmsgs, the_attr.mq_maxmsg); + if (level >= 1) + printf(" Maximum size:%lu", the_attr.mq_msgsize); + + printf("\n"); +} diff --git a/modules/libcom/src/osi/os/RTEMS-posix/osdMessageQueue.h b/modules/libcom/src/osi/os/RTEMS-posix/osdMessageQueue.h new file mode 100644 index 000000000..95e66e73e --- /dev/null +++ b/modules/libcom/src/osi/os/RTEMS-posix/osdMessageQueue.h @@ -0,0 +1,28 @@ +/*************************************************************************\ +* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* National Laboratory. +* Copyright (c) 2002 The Regents of the University of California, as +* Operator of Los Alamos National Laboratory. +* EPICS BASE Versions 3.13.7 +* and higher are distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ +/* + * Author W. Eric Norum + * norume@aps.anl.gov + * 630 252 4793 + */ + +/* + * Very thin shims around RTEMS routines + */ +#include +#include + +struct epicsMessageQueueOSD { + mqd_t id; + char name[24]; +}; +#define epicsMessageQueueSend(q,m,l) (mq_send((q)->id, (const char*)(m), (l), 0)) +#define epicsMessageQueueReceive(q,m,s) (mq_receive((q)->id, (char*)(m), (s), NULL)) + diff --git a/modules/libcom/src/osi/os/RTEMS-posix/osdMutex.c b/modules/libcom/src/osi/os/RTEMS-posix/osdMutex.c new file mode 100644 index 000000000..2ee16bf88 --- /dev/null +++ b/modules/libcom/src/osi/os/RTEMS-posix/osdMutex.c @@ -0,0 +1,8 @@ +#include +#include +#include +#ifndef RTEMS_LEGACY_STACK +#include +#endif + +#include "../posix/osdMutex.c" diff --git a/modules/libcom/src/osi/os/RTEMS-posix/osdPoolStatus.c b/modules/libcom/src/osi/os/RTEMS-posix/osdPoolStatus.c new file mode 100644 index 000000000..5b202fd1d --- /dev/null +++ b/modules/libcom/src/osi/os/RTEMS-posix/osdPoolStatus.c @@ -0,0 +1,43 @@ +/*************************************************************************\ +* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* National Laboratory. +* Copyright (c) 2002 The Regents of the University of California, as +* Operator of Los Alamos National Laboratory. +* EPICS BASE Versions 3.13.7 +* and higher are distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ +#include +#include +#include +#define epicsExportSharedSymbols +#include "osiPoolStatus.h" + +#if __RTEMS_MAJOR__<5 +/* + * * osiSufficentSpaceInPool () + * */ +LIBCOM_API int epicsStdCall osiSufficentSpaceInPool ( size_t contiguousBlockSize ) +{ + rtems_malloc_statistics_t s; + unsigned long n; + + malloc_get_statistics(&s); + n = s.space_available - (unsigned long)(s.lifetime_allocated - s.lifetime_freed); + return (n > (50000 + contiguousBlockSize)); +} + +#else +/* + * osiSufficentSpaceInPool () + */ +LIBCOM_API int epicsStdCall osiSufficentSpaceInPool ( size_t contiguousBlockSize ) +{ + unsigned long n; + Heap_Information_block info; + + malloc_info( &info ); + n = info.Stats.size - (unsigned long)(info.Stats.lifetime_allocated - info.Stats.lifetime_freed); + return (n > (50000 + contiguousBlockSize)); +} +#endif diff --git a/modules/libcom/src/osi/os/RTEMS-posix/osdSock.h b/modules/libcom/src/osi/os/RTEMS-posix/osdSock.h new file mode 100644 index 000000000..5d765b3a7 --- /dev/null +++ b/modules/libcom/src/osi/os/RTEMS-posix/osdSock.h @@ -0,0 +1,80 @@ +/*************************************************************************\ +* Copyright (c) 2002 The University of Chicago, as Operator of Argonne +* National Laboratory. +* Copyright (c) 2002 The Regents of the University of California, as +* Operator of Los Alamos National Laboratory. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +/* + * Linux specific socket include + */ + +#ifndef osdSockH +#define osdSockH + +#include + +#include +#include /* for MAXHOSTNAMELEN */ +#include +#include +#include +#include +#include +#include +#include +#include +#include /* close() and others */ + +typedef int SOCKET; +#define INVALID_SOCKET (-1) +#define SOCKERRNO errno +#define socket_ioctl(A,B,C) ioctl(A,B,C) +typedef int osiSockIoctl_t; +typedef socklen_t osiSocklen_t; +typedef char osiSockOptMcastLoop_t; +typedef char osiSockOptMcastTTL_t; + +#define FD_IN_FDSET(FD) ((FD)ifr_addr.sa_len + sizeof(pifreq->ifr_name)) + +#ifndef IPPORT_USERRESERVED +#define IPPORT_USERRESERVED 5000 +#endif + +#endif /*osdSockH*/ diff --git a/modules/libcom/src/osi/os/RTEMS/devLibVMEOSD.c b/modules/libcom/src/osi/os/RTEMS-score/devLibVMEOSD.c similarity index 85% rename from modules/libcom/src/osi/os/RTEMS/devLibVMEOSD.c rename to modules/libcom/src/osi/os/RTEMS-score/devLibVMEOSD.c index f8b05421c..ed310eebc 100644 --- a/modules/libcom/src/osi/os/RTEMS/devLibVMEOSD.c +++ b/modules/libcom/src/osi/os/RTEMS-score/devLibVMEOSD.c @@ -19,12 +19,16 @@ #include #include "devLibVME.h" #include +#include +#include #if defined(__PPC__) || defined(__mcf528x__) +/* EPICS VME support requires various routines to be provided by the + * BSP. Most MVME PowerPC BSPs provide them, plus the uC5282. + */ #if defined(__PPC__) #include -#include #endif @@ -126,8 +130,7 @@ static long rtemsDevInit(void) { /* assume the vme bridge has been initialized by bsp */ - /* init BSP extensions [memProbe etc.] */ - return bspExtInit(); + return 0; } /* @@ -245,18 +248,70 @@ static long rtemsDevMapAddr (epicsAddressType addrType, unsigned options, return 0; } +#if defined(__m68k__) +/* All RTEMS m68k BSPs define this, m68k/shared/[misc/]memProbe.c */ +extern +rtems_status_code bspExtMemProbe(void *addr, int write, int size, void *pval); +#else + +static +rtems_status_code bspExtMemProbe(void *addr, int write, int size, void *pval) +{ + rtems_interrupt_level flags; + rtems_status_code ret = RTEMS_SUCCESSFUL; + epicsUInt32 val; + + /* bspExt allows caller to write uninitialized values, we don't */ + if(write && !pval) + return RTEMS_INVALID_NUMBER; + + switch(size) { + case 1: + case 2: + case 4: + break; + default: + return RTEMS_INVALID_SIZE; + } + + if(write) + memcpy(&val, pval, size); + + rtems_interrupt_disable(flags); + _BSP_clear_hostbridge_errors(0,1); + + if(!write) { + switch(size) { + case 1: val = ioread8(addr)<<24; break; + case 2: val = nat_ioread16(addr)<<16; break; + case 4: val = nat_ioread32(addr); break; + } + } else { + switch(size) { + case 1: iowrite8(addr, val>>24); break; + case 2: nat_iowrite16(addr, val>>16); break; + case 4: nat_iowrite32(addr, val); break; + } + } + + ret = _BSP_clear_hostbridge_errors(0,1); + rtems_interrupt_enable(flags); + + if(!write && pval) + memcpy(pval, &val, size); + + return ret; +} +#endif + /* * a bus error safe "wordSize" read at the specified address which returns * unsuccessful status if the device isnt present */ -rtems_status_code bspExtMemProbe(void *addr, int write, int size, void *pval); static long rtemsDevReadProbe (unsigned wordSize, volatile const void *ptr, void *pValue) { long status; - /* - * this global variable exists in the nivxi library - */ status = bspExtMemProbe ((void*)ptr, 0/*read*/, wordSize, pValue); if (status!=RTEMS_SUCCESSFUL) { return S_dev_noDevice; @@ -273,9 +328,6 @@ static long rtemsDevWriteProbe (unsigned wordSize, volatile void *ptr, const voi { long status; - /* - * this global variable exists in the nivxi library - */ status = bspExtMemProbe ((void*)ptr, 1/*write*/, wordSize, (void*)pValue); if (status!=RTEMS_SUCCESSFUL) { return S_dev_noDevice; @@ -359,7 +411,7 @@ devLibVME *pdevLibVME; #endif /* defined(__PPC__) || defined(__mcf528x__) */ /* - * Some vxWorks convenience routines + * Some convenience routines */ void bcopyLongs(char *source, char *destination, int nlongs) diff --git a/modules/libcom/src/osi/os/RTEMS/epicsAtomicOSD.cpp b/modules/libcom/src/osi/os/RTEMS-score/epicsAtomicOSD.cpp similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/epicsAtomicOSD.cpp rename to modules/libcom/src/osi/os/RTEMS-score/epicsAtomicOSD.cpp diff --git a/modules/libcom/src/osi/os/RTEMS/epicsAtomicOSD.h b/modules/libcom/src/osi/os/RTEMS-score/epicsAtomicOSD.h similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/epicsAtomicOSD.h rename to modules/libcom/src/osi/os/RTEMS-score/epicsAtomicOSD.h diff --git a/modules/libcom/src/osi/os/RTEMS/epicsMath.h b/modules/libcom/src/osi/os/RTEMS-score/epicsMath.h similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/epicsMath.h rename to modules/libcom/src/osi/os/RTEMS-score/epicsMath.h diff --git a/modules/libcom/src/osi/os/RTEMS/osdEvent.c b/modules/libcom/src/osi/os/RTEMS-score/osdEvent.c similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdEvent.c rename to modules/libcom/src/osi/os/RTEMS-score/osdEvent.c diff --git a/modules/libcom/src/osi/os/RTEMS/osdEvent.h b/modules/libcom/src/osi/os/RTEMS-score/osdEvent.h similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdEvent.h rename to modules/libcom/src/osi/os/RTEMS-score/osdEvent.h diff --git a/modules/libcom/src/osi/os/RTEMS/osdFindSymbol.c b/modules/libcom/src/osi/os/RTEMS-score/osdFindSymbol.c similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdFindSymbol.c rename to modules/libcom/src/osi/os/RTEMS-score/osdFindSymbol.c diff --git a/modules/libcom/src/osi/os/RTEMS/osdMutex.c b/modules/libcom/src/osi/os/RTEMS-score/osdMutex.c similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdMutex.c rename to modules/libcom/src/osi/os/RTEMS-score/osdMutex.c diff --git a/modules/libcom/src/osi/os/RTEMS/osdMutex.h b/modules/libcom/src/osi/os/RTEMS-score/osdMutex.h similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdMutex.h rename to modules/libcom/src/osi/os/RTEMS-score/osdMutex.h diff --git a/modules/libcom/src/osi/os/RTEMS/osdPoolStatus.c b/modules/libcom/src/osi/os/RTEMS-score/osdPoolStatus.c similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdPoolStatus.c rename to modules/libcom/src/osi/os/RTEMS-score/osdPoolStatus.c diff --git a/modules/libcom/src/osi/os/RTEMS/osdProcess.c b/modules/libcom/src/osi/os/RTEMS-score/osdProcess.c similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdProcess.c rename to modules/libcom/src/osi/os/RTEMS-score/osdProcess.c diff --git a/modules/libcom/src/osi/os/RTEMS/osdReadline.c b/modules/libcom/src/osi/os/RTEMS-score/osdReadline.c similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdReadline.c rename to modules/libcom/src/osi/os/RTEMS-score/osdReadline.c diff --git a/modules/libcom/src/osi/os/RTEMS/osdSignal.cpp b/modules/libcom/src/osi/os/RTEMS-score/osdSignal.cpp similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdSignal.cpp rename to modules/libcom/src/osi/os/RTEMS-score/osdSignal.cpp diff --git a/modules/libcom/src/osi/os/RTEMS/osdSock.h b/modules/libcom/src/osi/os/RTEMS-score/osdSock.h similarity index 97% rename from modules/libcom/src/osi/os/RTEMS/osdSock.h rename to modules/libcom/src/osi/os/RTEMS-score/osdSock.h index 49023fe78..3090234af 100644 --- a/modules/libcom/src/osi/os/RTEMS/osdSock.h +++ b/modules/libcom/src/osi/os/RTEMS-score/osdSock.h @@ -37,6 +37,10 @@ int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, str } #endif +#ifndef IPPORT_USERRESERVED +#define IPPORT_USERRESERVED 5000 +#endif + typedef int SOCKET; #define INVALID_SOCKET (-1) #define SOCKERRNO errno @@ -68,7 +72,6 @@ typedef unsigned char osiSockOptMcastTTL_t; #define SOCK_ENOTSOCK ENOTSOCK #define SOCK_EBADF EBADF -#define bzero(p,n) memset(p,0,n) #include #include #include diff --git a/modules/libcom/src/osi/os/RTEMS/osdSpin.c b/modules/libcom/src/osi/os/RTEMS-score/osdSpin.c similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdSpin.c rename to modules/libcom/src/osi/os/RTEMS-score/osdSpin.c diff --git a/modules/libcom/src/osi/os/RTEMS/osdStrtod.h b/modules/libcom/src/osi/os/RTEMS-score/osdStrtod.h similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdStrtod.h rename to modules/libcom/src/osi/os/RTEMS-score/osdStrtod.h diff --git a/modules/libcom/src/osi/os/RTEMS/osdThread.c b/modules/libcom/src/osi/os/RTEMS-score/osdThread.c similarity index 99% rename from modules/libcom/src/osi/os/RTEMS/osdThread.c rename to modules/libcom/src/osi/os/RTEMS-score/osdThread.c index dd65692c6..71a532e62 100644 --- a/modules/libcom/src/osi/os/RTEMS/osdThread.c +++ b/modules/libcom/src/osi/os/RTEMS-score/osdThread.c @@ -219,6 +219,8 @@ threadWrapper (rtems_task_argument arg) */ void epicsThreadExitMain (void) { + cantProceed("epicsThreadExitMain() has been deprecated for lack of usage." + " Please report if you see this message."); } static rtems_status_code diff --git a/modules/libcom/src/osi/os/RTEMS/osdThread.h b/modules/libcom/src/osi/os/RTEMS-score/osdThread.h similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdThread.h rename to modules/libcom/src/osi/os/RTEMS-score/osdThread.h diff --git a/modules/libcom/src/osi/os/RTEMS/osdThreadExtra.c b/modules/libcom/src/osi/os/RTEMS-score/osdThreadExtra.c similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdThreadExtra.c rename to modules/libcom/src/osi/os/RTEMS-score/osdThreadExtra.c diff --git a/modules/libcom/src/osi/os/RTEMS/osdTime.cpp b/modules/libcom/src/osi/os/RTEMS-score/osdTime.cpp similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdTime.cpp rename to modules/libcom/src/osi/os/RTEMS-score/osdTime.cpp diff --git a/modules/libcom/src/osi/os/RTEMS/osdTime.h b/modules/libcom/src/osi/os/RTEMS-score/osdTime.h similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osdTime.h rename to modules/libcom/src/osi/os/RTEMS-score/osdTime.h diff --git a/modules/libcom/src/osi/os/RTEMS/osiUnistd.h b/modules/libcom/src/osi/os/RTEMS-score/osiUnistd.h similarity index 100% rename from modules/libcom/src/osi/os/RTEMS/osiUnistd.h rename to modules/libcom/src/osi/os/RTEMS-score/osiUnistd.h diff --git a/modules/libcom/src/osi/os/RTEMS/osdEnv.c b/modules/libcom/src/osi/os/RTEMS/osdEnv.c deleted file mode 100644 index 125aee97e..000000000 --- a/modules/libcom/src/osi/os/RTEMS/osdEnv.c +++ /dev/null @@ -1,62 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Saskatchewan -* SPDX-License-Identifier: EPICS -* EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ -/* osdEnv.c */ -/* - * Author: Eric Norum - * Date: May 7, 2001 - * - * Routines to modify/display environment variables and EPICS parameters - * - */ - -#include -#include - -#include "epicsStdio.h" -#include "envDefs.h" -#include "osiUnistd.h" -#include "iocsh.h" - -/* - * Set the value of an environment variable - */ -LIBCOM_API void epicsStdCall epicsEnvSet (const char *name, const char *value) -{ - iocshEnvClear(name); - setenv(name, value, 1); -} - -/* - * Unset an environment variable - */ - -LIBCOM_API void epicsStdCall epicsEnvUnset (const char *name) -{ - iocshEnvClear(name); - unsetenv(name); -} - -/* - * Show the value of the specified, or all, environment variables - */ -LIBCOM_API void epicsStdCall epicsEnvShow (const char *name) -{ - if (name == NULL) { - extern char **environ; - char **sp; - - for (sp = environ ; (sp != NULL) && (*sp != NULL) ; sp++) - printf ("%s\n", *sp); - } - else { - const char *cp = getenv (name); - if (cp == NULL) - printf ("%s is not an environment variable.\n", name); - else - printf ("%s=%s\n", name, cp); - } -} diff --git a/modules/libcom/src/osi/os/WIN32/osdEnv.c b/modules/libcom/src/osi/os/WIN32/osdEnv.c index be884ac61..18e66cb6b 100644 --- a/modules/libcom/src/osi/os/WIN32/osdEnv.c +++ b/modules/libcom/src/osi/os/WIN32/osdEnv.c @@ -15,18 +15,25 @@ #include #include -#include #include #include #include "epicsStdio.h" +#include "epicsString.h" #include "errlog.h" -#include "cantProceed.h" #include "envDefs.h" #include "osiUnistd.h" #include "epicsFindSymbol.h" #include "iocsh.h" +static +void setEnv(const char *name, const char *value) +{ + errno_t err = _putenv_s(name, value); + if(err) + errlogPrintf("Can't set environment %s=\"%s\" : %d\n", name, value, (int)err); +} + /* * Set the value of an environment variable * Leaks memory, but the assumption is that this routine won't be @@ -34,25 +41,8 @@ */ LIBCOM_API void epicsStdCall epicsEnvSet (const char *name, const char *value) { - char *cp; - iocshEnvClear(name); - - cp = mallocMustSucceed (strlen (name) + strlen (value) + 2, "epicsEnvSet"); - strcpy (cp, name); - strcat (cp, "="); - strcat (cp, value); - if (putenv (cp) < 0) { - errPrintf( - -1L, - __FILE__, - __LINE__, - "Failed to set environment parameter \"%s\" to \"%s\": %s\n", - name, - value, - strerror (errno)); - free (cp); - } + setEnv(name, value); } /* @@ -63,8 +53,7 @@ LIBCOM_API void epicsStdCall epicsEnvSet (const char *name, const char *value) LIBCOM_API void epicsStdCall epicsEnvUnset (const char *name) { iocshEnvClear(name); - if (getenv(name) != NULL) - epicsEnvSet((char*)name, ""); + setEnv(name, ""); } /* @@ -72,18 +61,10 @@ LIBCOM_API void epicsStdCall epicsEnvUnset (const char *name) */ LIBCOM_API void epicsStdCall epicsEnvShow (const char *name) { - if (name == NULL) { - extern char **environ; - char **sp; + char **sp; - for (sp = environ ; (sp != NULL) && (*sp != NULL) ; sp++) + for (sp = environ ; (sp != NULL) && (*sp != NULL) ; sp++) { + if (!name || epicsStrnGlobMatch(*sp, strchr(*sp, '=') - *sp, name)) printf ("%s\n", *sp); } - else { - const char *cp = getenv (name); - if (cp == NULL) - printf ("%s is not an environment variable.\n", name); - else - printf ("%s=%s\n", name, cp); - } } diff --git a/modules/libcom/src/osi/os/WIN32/osdEvent.c b/modules/libcom/src/osi/os/WIN32/osdEvent.c index 996dbd3be..62117cb16 100644 --- a/modules/libcom/src/osi/os/WIN32/osdEvent.c +++ b/modules/libcom/src/osi/os/WIN32/osdEvent.c @@ -26,6 +26,8 @@ #include "libComAPI.h" #include "epicsEvent.h" +#include "osdThreadPvt.h" + typedef struct epicsEventOSD { HANDLE handle; } epicsEventOSD; @@ -90,27 +92,47 @@ LIBCOM_API epicsEventStatus epicsEventWait ( epicsEventId pSem ) LIBCOM_API epicsEventStatus epicsEventWaitWithTimeout ( epicsEventId pSem, double timeOut ) { - static const unsigned mSecPerSec = 1000; + /* waitable timers use 100 nanosecond intervals, like FILETIME */ + static const unsigned ivalPerSec = 10000000u; /* number of 100ns intervals per second */ + static const unsigned mSecPerSec = 1000u; /* milliseconds per second */ + HANDLE handles[2]; DWORD status; - DWORD tmo; + LARGE_INTEGER tmo; + HANDLE timer; + LONGLONG nIvals; /* number of intervals */ if ( timeOut <= 0.0 ) { - tmo = 0u; + tmo.QuadPart = 0u; } - else if ( timeOut >= INFINITE / mSecPerSec ) { - tmo = INFINITE - 1; + else if ( timeOut >= INFINITE / mSecPerSec ) { + /* we need to apply a maximum wait time to stop an overflow. We choose (INFINITE - 1) milliseconds, + to be compatible with previous WaitForSingleObject() implementation */ + nIvals = (LONGLONG)(INFINITE - 1) * (ivalPerSec / mSecPerSec); + tmo.QuadPart = -nIvals; /* negative value means a relative time offset for timer */ } else { - tmo = ( DWORD ) ( ( timeOut * mSecPerSec ) + 0.5 ); - if ( tmo == 0 ) { - tmo = 1; - } + nIvals = (LONGLONG)(timeOut * ivalPerSec + 0.999999); + tmo.QuadPart = -nIvals; + } + + if (tmo.QuadPart < 0) { + timer = osdThreadGetTimer(); + if (!SetWaitableTimer(timer, &tmo, 0, NULL, NULL, 0)) { + return epicsEventError; + } + handles[0] = pSem->handle; + handles[1] = timer; + status = WaitForMultipleObjects (2, handles, FALSE, INFINITE); + } + else { + status = WaitForSingleObject(pSem->handle, 0); } - status = WaitForSingleObject ( pSem->handle, tmo ); if ( status == WAIT_OBJECT_0 ) { return epicsEventOK; } - else if ( status == WAIT_TIMEOUT ) { + else if ( status == WAIT_OBJECT_0 + 1 || status == WAIT_TIMEOUT ) { + /* WaitForMultipleObjects will trigger WAIT_OBJECT_0 + 1, + WaitForSingleObject will trigger WAIT_TIMEOUT */ return epicsEventWaitTimeout; } else { diff --git a/modules/libcom/src/osi/os/WIN32/osdProcess.c b/modules/libcom/src/osi/os/WIN32/osdProcess.c index 0f137bf37..cff1ed4bd 100644 --- a/modules/libcom/src/osi/os/WIN32/osdProcess.c +++ b/modules/libcom/src/osi/os/WIN32/osdProcess.c @@ -50,10 +50,14 @@ LIBCOM_API osiGetUserNameReturn epicsStdCall osiGetUserName (char *pBuf, unsigne LIBCOM_API osiSpawnDetachedProcessReturn epicsStdCall osiSpawnDetachedProcess ( const char *pProcessName, const char *pBaseExecutableName ) { + BOOL silent = pProcessName && pProcessName[0]=='!'; BOOL status; STARTUPINFO startupInfo; PROCESS_INFORMATION processInfo; + if(silent) + pProcessName++; /* skip '!' */ + GetStartupInfo ( &startupInfo ); startupInfo.lpReserved = NULL; startupInfo.lpTitle = (char *) pProcessName; @@ -115,7 +119,7 @@ LIBCOM_API osiSpawnDetachedProcessReturn epicsStdCall osiSpawnDetachedProcess /* Free the buffer. */ LocalFree (errStrMsgBuf); } - else { + else if(!silent) { fprintf (stderr, "!!WARNING!!\n"); fprintf (stderr, "Unable to locate executable \"%s\".\n", pBaseExecutableName); fprintf (stderr, "You may need to modify your \"path\" environment variable.\n"); diff --git a/modules/libcom/src/osi/os/WIN32/osdStrtod.h b/modules/libcom/src/osi/os/WIN32/osdStrtod.h index f7ad78a02..665abf646 100644 --- a/modules/libcom/src/osi/os/WIN32/osdStrtod.h +++ b/modules/libcom/src/osi/os/WIN32/osdStrtod.h @@ -13,11 +13,6 @@ extern "C" { #endif -/* - * epicsStrtod() for systems with broken strtod() routine - */ -LIBCOM_API double epicsStrtod(const char *str, char **endp); - /* * Microsoft apparently added strto[u]ll() in VS2013 * Older compilers have these equivalents though @@ -28,6 +23,19 @@ LIBCOM_API double epicsStrtod(const char *str, char **endp); # define strtoull _strtoui64 #endif +/* + * strtod works in MSVC 1900 and mingw, use + * the OS version in those and our own otherwise + */ +#if (_MSC_VER < 1900) && !defined(_MINGW) +/* + * epicsStrtod() for systems with broken strtod() routine + */ +LIBCOM_API double epicsStrtod(const char *str, char **endp); +#else +# define epicsStrtod strtod +#endif + #ifdef __cplusplus } #endif diff --git a/modules/libcom/src/osi/os/WIN32/osdThread.c b/modules/libcom/src/osi/os/WIN32/osdThread.c index 6c00be4ca..cff3e45d4 100644 --- a/modules/libcom/src/osi/os/WIN32/osdThread.c +++ b/modules/libcom/src/osi/os/WIN32/osdThread.c @@ -19,9 +19,6 @@ #define VC_EXTRALEAN #define STRICT -#ifndef _WIN32_WINNT -# define _WIN32_WINNT 0x400 /* No support for W95 */ -#endif #include #include /* for _endthread() etc */ @@ -33,6 +30,7 @@ #include "ellLib.h" #include "epicsExit.h" #include "epicsAtomic.h" +#include "osdThreadPvt.h" LIBCOM_API void osdThreadHooksRun(epicsThreadId id); @@ -55,6 +53,7 @@ typedef struct epicsThreadOSD { unsigned epicsPriority; char isSuspended; int joinable; + HANDLE timer; /* waitable timer */ } win32ThreadParam; typedef struct epicsThreadPrivateOSD { @@ -221,6 +220,19 @@ static win32ThreadGlobal * fetchWin32ThreadGlobal ( void ) return pWin32ThreadGlobal; } +static void epicsParmCleanupDataWIN32 ( win32ThreadParam * pParm ) +{ + if ( pParm ) { + if ( pParm->handle ) { + CloseHandle ( pParm->handle ); + } + if ( pParm->timer ) { + CloseHandle ( pParm->timer ); + } + free ( pParm ); + } +} + static void epicsParmCleanupWIN32 ( win32ThreadParam * pParm ) { win32ThreadGlobal * pGbl = fetchWin32ThreadGlobal (); @@ -239,8 +251,7 @@ static void epicsParmCleanupWIN32 ( win32ThreadParam * pParm ) ellDelete ( & pGbl->threadList, & pParm->node ); LeaveCriticalSection ( & pGbl->mutex ); - CloseHandle ( pParm->handle ); - free ( pParm ); + epicsParmCleanupDataWIN32 ( pParm ); } } @@ -249,7 +260,8 @@ static void epicsParmCleanupWIN32 ( win32ThreadParam * pParm ) */ LIBCOM_API void epicsStdCall epicsThreadExitMain ( void ) { - _endthread (); + cantProceed("epicsThreadExitMain() has been deprecated for lack of usage." + " Please report if you see this message."); } /* @@ -470,10 +482,10 @@ static unsigned WINAPI epicsWin32ThreadEntry ( LPVOID lpParameter ) } epicsExitCallAtThreadExits (); + /* * CAUTION: !!!! the thread id might continue to be used after this thread exits !!!! */ - if ( pGbl ) { TlsSetValue ( pGbl->tlsIndexThreadLibraryEPICS, (void*)0xdeadbeef ); } @@ -493,6 +505,16 @@ static win32ThreadParam * epicsThreadParmCreate ( const char *pName ) strcpy ( pParmWIN32->pName, pName ); pParmWIN32->isSuspended = 0; epicsAtomicIncrIntT(&pParmWIN32->refcnt); +#ifdef CREATE_WAITABLE_TIMER_HIGH_RESOLUTION + pParmWIN32->timer = CreateWaitableTimerEx(NULL, NULL, CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS); +#endif + if (pParmWIN32->timer == NULL) { + pParmWIN32->timer = CreateWaitableTimer(NULL, 0, NULL); + } + if (pParmWIN32->timer == NULL) { + free(pParmWIN32); + return NULL; + } } return pParmWIN32; } @@ -590,7 +612,7 @@ epicsThreadId epicsThreadCreateOpt ( CREATE_SUSPENDED | STACK_SIZE_PARAM_IS_A_RESERVATION, & threadId ); if ( pParmWIN32->handle == 0 ) { - free ( pParmWIN32 ); + epicsParmCleanupDataWIN32 ( pParmWIN32 ); return NULL; } /* weird win32 interface threadId parameter inconsistency */ @@ -600,8 +622,7 @@ epicsThreadId epicsThreadCreateOpt ( osdPriority = epicsThreadGetOsdPriorityValue (opts->priority); bstat = SetThreadPriority ( pParmWIN32->handle, osdPriority ); if (!bstat) { - CloseHandle ( pParmWIN32->handle ); - free ( pParmWIN32 ); + epicsParmCleanupDataWIN32 ( pParmWIN32 ); return NULL; } @@ -611,11 +632,10 @@ epicsThreadId epicsThreadCreateOpt ( wstat = ResumeThread ( pParmWIN32->handle ); if (wstat==0xFFFFFFFF) { - EnterCriticalSection ( & pGbl->mutex ); - ellDelete ( & pGbl->threadList, & pParmWIN32->node ); - LeaveCriticalSection ( & pGbl->mutex ); - CloseHandle ( pParmWIN32->handle ); - free ( pParmWIN32 ); + EnterCriticalSection ( & pGbl->mutex ); + ellDelete ( & pGbl->threadList, & pParmWIN32->node ); + LeaveCriticalSection ( & pGbl->mutex ); + epicsParmCleanupDataWIN32 ( pParmWIN32 ); return NULL; } @@ -777,24 +797,62 @@ LIBCOM_API int epicsStdCall epicsThreadIsSuspended ( epicsThreadId id ) } } +/** + * osdThreadGetTimer () + * return stored waitable timer object for thread + */ +HANDLE osdThreadGetTimer() +{ + win32ThreadGlobal * pGbl = fetchWin32ThreadGlobal (); + win32ThreadParam * pParm; + + assert ( pGbl ); + + pParm = ( win32ThreadParam * ) + TlsGetValue ( pGbl->tlsIndexThreadLibraryEPICS ); + + return pParm->timer; +} + /* * epicsThreadSleep () */ LIBCOM_API void epicsStdCall epicsThreadSleep ( double seconds ) { - static const unsigned mSecPerSec = 1000; - DWORD milliSecDelay; + /* waitable timers use 100 nanosecond intervals, like FILETIME */ + static const unsigned ivalPerSec = 10000000u; /* number of 100ns intervals per second */ + static const unsigned mSecPerSec = 1000u; /* milliseconds per second */ + LARGE_INTEGER tmo; + HANDLE timer; + LONGLONG nIvals; /* number of intervals */ - if ( seconds > 0.0 ) { - seconds *= mSecPerSec; - seconds += 0.99999999; /* 8 9s here is optimal */ - milliSecDelay = ( seconds >= INFINITE ) ? - INFINITE - 1 : ( DWORD ) seconds; + if ( seconds <= 0.0 ) { + tmo.QuadPart = 0u; } - else { /* seconds <= 0 or NAN */ - milliSecDelay = 0u; + else if ( seconds >= INFINITE / mSecPerSec ) { + /* we need to apply a maximum wait time to stop an overflow. We choose (INFINITE - 1) milliseconds, + to be compatible with previous WaitForSingleObject() implementation */ + nIvals = (LONGLONG)(INFINITE - 1) * (ivalPerSec / mSecPerSec); + tmo.QuadPart = -nIvals; /* negative value means a relative time offset for timer */ + } + else { + nIvals = (LONGLONG)(seconds * ivalPerSec + 0.999999); + tmo.QuadPart = -nIvals; + } + + if (tmo.QuadPart == 0) { + Sleep ( 0 ); + } + else { + timer = osdThreadGetTimer(); + if (!SetWaitableTimer(timer, &tmo, 0, NULL, NULL, 0)) { + fprintf ( stderr, "epicsThreadSleep: SetWaitableTimer failed %lu\n", GetLastError() ); + return; + } + if (WaitForSingleObject(timer, INFINITE) != WAIT_OBJECT_0) { + fprintf ( stderr, "epicsThreadSleep: WaitForSingleObject failed %lu\n", GetLastError() ); + } } - Sleep ( milliSecDelay ); } /* diff --git a/modules/libcom/src/osi/os/WIN32/osdThreadPvt.h b/modules/libcom/src/osi/os/WIN32/osdThreadPvt.h new file mode 100644 index 000000000..f069841ef --- /dev/null +++ b/modules/libcom/src/osi/os/WIN32/osdThreadPvt.h @@ -0,0 +1,20 @@ +/*************************************************************************\ +* SPDX-License-Identifier: EPICS +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +#ifndef osdThreadPvth +#define osdThreadPvth + +#ifdef __cplusplus +extern "C" { +#endif + +extern HANDLE osdThreadGetTimer(void); + +#ifdef __cplusplus +} +#endif + +#endif /* osdThreadPvth */ diff --git a/modules/libcom/src/osi/os/default/osdEnv.c b/modules/libcom/src/osi/os/default/osdEnv.c index f95a3f032..74b5b8041 100644 --- a/modules/libcom/src/osi/os/default/osdEnv.c +++ b/modules/libcom/src/osi/os/default/osdEnv.c @@ -15,18 +15,30 @@ #include #include -#include #include #include #include "epicsStdio.h" +#include "epicsString.h" +#include "epicsVersion.h" #include "errlog.h" -#include "cantProceed.h" #include "envDefs.h" #include "osiUnistd.h" #include "epicsFindSymbol.h" #include "iocsh.h" +#ifdef __rtems__ +# include +# define RTEMS_VERSION_INT VERSION_INT(__RTEMS_MAJOR__, __RTEMS_MINOR__, 0, 0) +#endif + +#if defined(__RTEMS_MAJOR__) && RTEMS_VERSION_INT %d\n", name, value, errno); } /* @@ -64,8 +59,8 @@ LIBCOM_API void epicsStdCall epicsEnvSet (const char *name, const char *value) LIBCOM_API void epicsStdCall epicsEnvUnset (const char *name) { iocshEnvClear(name); - if (getenv(name) != NULL) - putenv((char*)name); + if(unSetEnv(name)) + errlogPrintf("unsetenv(\"%s\") -> %d\n", name, errno); } /* @@ -73,18 +68,11 @@ LIBCOM_API void epicsStdCall epicsEnvUnset (const char *name) */ LIBCOM_API void epicsStdCall epicsEnvShow (const char *name) { - if (name == NULL) { - extern char **environ; - char **sp; + extern char **environ; + char **sp; - for (sp = environ ; (sp != NULL) && (*sp != NULL) ; sp++) + for (sp = environ ; (sp != NULL) && (*sp != NULL) ; sp++) { + if (!name || epicsStrnGlobMatch(*sp, strchr(*sp, '=') - *sp, name)) printf ("%s\n", *sp); } - else { - const char *cp = getenv (name); - if (cp == NULL) - printf ("%s is not an environment variable.\n", name); - else - printf ("%s=%s\n", name, cp); - } } diff --git a/modules/libcom/src/osi/os/iOS/osdEnv.c b/modules/libcom/src/osi/os/iOS/osdEnv.c deleted file mode 100644 index 665141951..000000000 --- a/modules/libcom/src/osi/os/iOS/osdEnv.c +++ /dev/null @@ -1,69 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Saskatchewan -* SPDX-License-Identifier: EPICS -* EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ - -/* osdEnv.c */ -/* - * Author: Eric Norum - * Date: May 7, 2001 - * - * Routines to modify/display environment variables and EPICS parameters - */ - -#include -#include -#include -#include -#include - -#include "epicsStdio.h" -#include -#include -#include -#include -#include "epicsFindSymbol.h" -#include - -/* - * Set the value of an environment variable - */ -LIBCOM_API void epicsStdCall epicsEnvSet (const char *name, const char *value) -{ - if (!name) return; - iocshEnvClear(name); - setenv(name, value, 1); -} - -/* - * Unset an environment variable - */ - -LIBCOM_API void epicsStdCall epicsEnvUnset (const char *name) -{ - iocshEnvClear(name); - unsetenv(name); -} - -/* - * Show the value of the specified, or all, environment variables - */ -LIBCOM_API void epicsStdCall epicsEnvShow (const char *name) -{ - if (name == NULL) { - extern char **environ; - char **sp; - - for (sp = environ ; (sp != NULL) && (*sp != NULL) ; sp++) - printf ("%s\n", *sp); - } - else { - const char *cp = getenv (name); - if (cp == NULL) - printf ("%s is not an environment variable.\n", name); - else - printf ("%s=%s\n", name, cp); - } -} diff --git a/modules/libcom/src/osi/os/posix/osdFindSymbol.c b/modules/libcom/src/osi/os/posix/osdFindSymbol.c index 6c26696c8..fc175fc60 100644 --- a/modules/libcom/src/osi/os/posix/osdFindSymbol.c +++ b/modules/libcom/src/osi/os/posix/osdFindSymbol.c @@ -7,9 +7,10 @@ \*************************************************************************/ /* osi/os/posix/osdFindSymbol.c */ +#include "epicsFindSymbol.h" + #include -#include "epicsFindSymbol.h" /* non-POSIX extension available on Linux (glibc at least) and OSX. */ diff --git a/modules/libcom/src/osi/os/posix/osdProcess.c b/modules/libcom/src/osi/os/posix/osdProcess.c index 56267d0b8..b2c26beb4 100644 --- a/modules/libcom/src/osi/os/posix/osdProcess.c +++ b/modules/libcom/src/osi/os/posix/osdProcess.c @@ -24,7 +24,9 @@ #include #include #include +#include #include +#include #include "osiProcess.h" #include "errlog.h" @@ -61,12 +63,22 @@ LIBCOM_API osiSpawnDetachedProcessReturn epicsStdCall osiSpawnDetachedProcess (const char *pProcessName, const char *pBaseExecutableName) { int status; + int silent = pProcessName && pProcessName[0]=='!'; + int fds[2]; /* [reader, writer] */ + + if(silent) + pProcessName++; /* skip '!' */ + + if(pipe(fds)) + return osiSpawnDetachedProcessFail; /* * create a duplicate process */ status = fork (); if (status < 0) { + close(fds[0]); + close(fds[1]); return osiSpawnDetachedProcessFail; } @@ -75,11 +87,29 @@ LIBCOM_API osiSpawnDetachedProcessReturn epicsStdCall osiSpawnDetachedProcess * in the initiating (parent) process */ if (status) { - return osiSpawnDetachedProcessSuccess; - } + osiSpawnDetachedProcessReturn ret = osiSpawnDetachedProcessSuccess; + char buf; + ssize_t n; + close(fds[1]); - /* - * This is executed only by the new child process. + n = read(fds[0], &buf, 1); + /* Success if child exec'd without sending a '!'. + * Of course child may crash soon after, but can't + * wait around for this to happen. + */ + if(n!=0) { + ret = osiSpawnDetachedProcessFail; + } + + close(fds[0]); + return ret; + } + close(fds[0]); + (void)fcntl ( fds[1], F_SETFD, FD_CLOEXEC ); + + /* This is executed only by the new child process. + * Since we may be called from a library, we don't assume that + * all other code has set properly set FD_CLOEXEC. * Close all open files except for STDIO, so they will not * be inherited by the new program. */ @@ -89,6 +119,8 @@ LIBCOM_API osiSpawnDetachedProcessReturn epicsStdCall osiSpawnDetachedProcess if (fd==STDIN_FILENO) continue; if (fd==STDOUT_FILENO) continue; if (fd==STDERR_FILENO) continue; + /* pipe to our parent will be closed automatically via FD_CLOEXEC */ + if (fd==fds[1]) continue; close (fd); } } @@ -109,12 +141,16 @@ LIBCOM_API osiSpawnDetachedProcessReturn epicsStdCall osiSpawnDetachedProcess * Run the specified executable */ status = execlp (pBaseExecutableName, pBaseExecutableName, (char *)NULL); - if ( status < 0 ) { + if ( status < 0 && !silent ) { fprintf ( stderr, "**** The executable \"%s\" couldn't be located\n", pBaseExecutableName ); fprintf ( stderr, "**** because of errno = \"%s\".\n", strerror (errno) ); fprintf ( stderr, "**** You may need to modify your PATH environment variable.\n" ); fprintf ( stderr, "**** Unable to start \"%s\" process.\n", pProcessName); } + /* signal error to parent */ + ssize_t ret = write(fds[1], "!", 1); + (void)ret; /* not much we could do about this */ + close(fds[1]); /* Don't run our parent's atexit() handlers */ _exit ( -1 ); } diff --git a/modules/libcom/src/osi/os/posix/osdSock.c b/modules/libcom/src/osi/os/posix/osdSock.c index 52f52a085..4ebd0db73 100644 --- a/modules/libcom/src/osi/os/posix/osdSock.c +++ b/modules/libcom/src/osi/os/posix/osdSock.c @@ -36,6 +36,7 @@ /* with glibc, SOCK_CLOEXEC does not expand to a simple constant */ # define HAVE_SOCK_CLOEXEC #else +# undef SOCK_CLOEXEC # define SOCK_CLOEXEC (0) #endif diff --git a/modules/libcom/src/osi/os/posix/osdThread.c b/modules/libcom/src/osi/os/posix/osdThread.c index 0eb5f5fd2..50bb714e0 100644 --- a/modules/libcom/src/osi/os/posix/osdThread.c +++ b/modules/libcom/src/osi/os/posix/osdThread.c @@ -24,8 +24,9 @@ #include #include -#if defined(_POSIX_MEMLOCK) && _POSIX_MEMLOCK > 0 -#include +#define USE_MEMLOCK (defined(_POSIX_MEMLOCK) && (_POSIX_MEMLOCK > 0) && !defined(__rtems__)) +#if USE_MEMLOCK +#include #endif #include "epicsStdio.h" @@ -426,7 +427,8 @@ static void epicsThreadInit(void) LIBCOM_API void epicsThreadRealtimeLock(void) { -#if defined(_POSIX_MEMLOCK) && _POSIX_MEMLOCK > 0 +#if USE_MEMLOCK +#ifndef RTEMS_LEGACY_STACK // seems to be part of libbsd? if (pcommonAttr->maxPriority > pcommonAttr->minPriority) { int status = mlockall(MCL_CURRENT | MCL_FUTURE); @@ -451,6 +453,7 @@ void epicsThreadRealtimeLock(void) } } } +#endif // LEGACY STACK #endif } @@ -687,6 +690,10 @@ LIBCOM_API void epicsStdCall epicsThreadExitMain(void) epicsThreadOSD *pthreadInfo; epicsThreadInit(); + + cantProceed("epicsThreadExitMain() has been deprecated for lack of usage." + " Please report if you see this message."); + pthreadInfo = (epicsThreadOSD *)pthread_getspecific(getpthreadInfo); if(pthreadInfo==NULL) pthreadInfo = createImplicit(); diff --git a/modules/libcom/src/osi/os/posix/osdTime.cpp b/modules/libcom/src/osi/os/posix/osdTime.cpp index 6d7b86048..b3bb84725 100644 --- a/modules/libcom/src/osi/os/posix/osdTime.cpp +++ b/modules/libcom/src/osi/os/posix/osdTime.cpp @@ -125,3 +125,15 @@ extern "C" LIBCOM_API void ++wakeTime->tv_sec; } } + +#ifdef __rtems__ +int osdTickGet() +{ + return epicsMonotonicGet(); // ns +} +int osdTickRateGet() +{ + return 1000000000; +} +void osdNTPReport() {} +#endif diff --git a/modules/libcom/src/osi/os/posix/osdTime.h b/modules/libcom/src/osi/os/posix/osdTime.h index 807b6d682..2aab01f3e 100644 --- a/modules/libcom/src/osi/os/posix/osdTime.h +++ b/modules/libcom/src/osi/os/posix/osdTime.h @@ -31,6 +31,14 @@ extern "C" { LIBCOM_API void epicsStdCall convertDoubleToWakeTime(double timeout,struct timespec *wakeTime); +#ifdef __rtems__ +void osdNTPInit(void); +int osdNTPGet(struct timespec *now); +int osdTickGet(void); +int osdTickRateGet(void); +void osdNTPReport(void); +#endif + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/modules/libcom/src/osi/os/solaris/osdEnv.c b/modules/libcom/src/osi/os/solaris/osdEnv.c deleted file mode 100644 index 125aee97e..000000000 --- a/modules/libcom/src/osi/os/solaris/osdEnv.c +++ /dev/null @@ -1,62 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Saskatchewan -* SPDX-License-Identifier: EPICS -* EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. -\*************************************************************************/ -/* osdEnv.c */ -/* - * Author: Eric Norum - * Date: May 7, 2001 - * - * Routines to modify/display environment variables and EPICS parameters - * - */ - -#include -#include - -#include "epicsStdio.h" -#include "envDefs.h" -#include "osiUnistd.h" -#include "iocsh.h" - -/* - * Set the value of an environment variable - */ -LIBCOM_API void epicsStdCall epicsEnvSet (const char *name, const char *value) -{ - iocshEnvClear(name); - setenv(name, value, 1); -} - -/* - * Unset an environment variable - */ - -LIBCOM_API void epicsStdCall epicsEnvUnset (const char *name) -{ - iocshEnvClear(name); - unsetenv(name); -} - -/* - * Show the value of the specified, or all, environment variables - */ -LIBCOM_API void epicsStdCall epicsEnvShow (const char *name) -{ - if (name == NULL) { - extern char **environ; - char **sp; - - for (sp = environ ; (sp != NULL) && (*sp != NULL) ; sp++) - printf ("%s\n", *sp); - } - else { - const char *cp = getenv (name); - if (cp == NULL) - printf ("%s is not an environment variable.\n", name); - else - printf ("%s=%s\n", name, cp); - } -} diff --git a/modules/libcom/src/osi/os/vxWorks/osdEnv.c b/modules/libcom/src/osi/os/vxWorks/osdEnv.c index 051d80187..517bb2bd6 100644 --- a/modules/libcom/src/osi/os/vxWorks/osdEnv.c +++ b/modules/libcom/src/osi/os/vxWorks/osdEnv.c @@ -16,18 +16,18 @@ /* This is needed for vxWorks 6.8 to prevent an obnoxious compiler warning */ #define _VSB_CONFIG_FILE <../lib/h/config/vsbConfig.h> -#include #include -#include +#include #include #include -#include "cantProceed.h" #include "epicsFindSymbol.h" #include "epicsStdio.h" +#include "epicsString.h" #include "errlog.h" #include "iocsh.h" + /* * Set the value of an environment variable * Leaks memory, but the assumption is that this routine won't be @@ -35,25 +35,32 @@ */ LIBCOM_API void epicsStdCall epicsEnvSet (const char *name, const char *value) { - char *cp; + size_t alen = (!name || !value) ? 2u : strlen(name) + strlen(value) + 2u; /* '=' '\0' */ + const int onstack = alen <= 512u; /* use on-stack dynamic array for small strings */ + char stackarr[ onstack ? alen : 1u]; /* gcc specific dynamic array */ + char *allocd = onstack ? NULL : malloc(alen); + char *cp = onstack ? stackarr : allocd; - if (!name) { + if (!name || !value) { printf ("Usage: epicsEnvSet \"name\", \"value\"\n"); - return; - } - iocshEnvClear(name); + } else if(!cp) { + errlogPrintf("epicsEnvSet(\"%s\", \"%s\" insufficient memory\n", name, value); - cp = mallocMustSucceed (strlen (name) + strlen (value) + 2, "epicsEnvSet"); - strcpy (cp, name); - strcat (cp, "="); - strcat (cp, value); - if (putenv (cp) < 0) { - errPrintf(-1L, __FILE__, __LINE__, - "Failed to set environment parameter \"%s\" to \"%s\": %s\n", - name, value, strerror (errno)); - free (cp); + } else { + int err; + + strcpy (cp, name); + strcat (cp, "="); + strcat (cp, value); + + iocshEnvClear(name); + + if((err=putenv(cp)) < 0) + errlogPrintf("epicsEnvSet(\"%s\", \"%s\" -> %d\n", name, value, err); } + /* from at least vxWorks 5.5 putenv() is making a copy, so we can free */ + free (allocd); } /* @@ -80,14 +87,12 @@ LIBCOM_API void epicsStdCall epicsEnvUnset (const char *name) */ LIBCOM_API void epicsStdCall epicsEnvShow (const char *name) { - if (name == NULL) { - envShow (0); - } - else { - const char *cp = getenv (name); - if (cp == NULL) - printf ("%s is not an environment variable.\n", name); - else - printf ("%s=%s\n", name, cp); + extern char **ppGlobalEnviron; /* Used in 'environ' macro but not declared in envLib.h */ + char **sp; + + for (sp = environ ; (sp != NULL) && (*sp != NULL) ; sp++) { + if (!**sp) continue; /* skip unset environment variables */ + if (!name || epicsStrnGlobMatch(*sp, strchr(*sp, '=') - *sp, name)) + printf ("%s\n", *sp); } } diff --git a/modules/libcom/src/osi/os/vxWorks/osdThread.c b/modules/libcom/src/osi/os/vxWorks/osdThread.c index 56a8183e8..d0e087108 100644 --- a/modules/libcom/src/osi/os/vxWorks/osdThread.c +++ b/modules/libcom/src/osi/os/vxWorks/osdThread.c @@ -353,7 +353,8 @@ void epicsThreadResume(epicsThreadId id) void epicsThreadExitMain(void) { - errlogPrintf("epicsThreadExitMain was called for vxWorks. Why?\n"); + cantProceed("epicsThreadExitMain() has been deprecated for lack of usage." + " Please report if you see this message."); } unsigned int epicsThreadGetPriority(epicsThreadId id) diff --git a/modules/libcom/src/osi/osiClockTime.c b/modules/libcom/src/osi/osiClockTime.c index 5368898d7..8b9dfd77b 100644 --- a/modules/libcom/src/osi/osiClockTime.c +++ b/modules/libcom/src/osi/osiClockTime.c @@ -58,14 +58,26 @@ static void ClockTimeSync(void *dummy); /* ClockTime_Report iocsh command */ static const iocshArg ReportArg0 = { "interest_level", iocshArgArgv}; static const iocshArg * const ReportArgs[1] = { &ReportArg0 }; -static const iocshFuncDef ReportFuncDef = {"ClockTime_Report", 1, ReportArgs}; +static const iocshFuncDef ReportFuncDef = {"ClockTime_Report", 1, ReportArgs, + "Reports clock synchronization status:\n" + " - On vxWorks and RTEMS:\n" + " * synchronization state\n" + " * last synchronization time with provider\n" + " * synchronization interval\n" + " - On workstation (WIN,*NIX):\n" + " * minimal report\n"}; static void ReportCallFunc(const iocshArgBuf *args) { ClockTime_Report(args[0].ival); } /* ClockTime_Shutdown iocsh command */ -static const iocshFuncDef ShutdownFuncDef = {"ClockTime_Shutdown", 0, NULL}; +static const iocshFuncDef ShutdownFuncDef = {"ClockTime_Shutdown", 0, NULL, + "Stops the OS synchronization thread\n" + " - On vxWorks and RTEMS:\n" + " * OS clock will free run\n" + " - On workstation (WIN,*NIX):\n" + " * no change\n"}; static void ShutdownCallFunc(const iocshArgBuf *args) { ClockTime_Shutdown(NULL); diff --git a/modules/libcom/src/osi/osiNTPTime.c b/modules/libcom/src/osi/osiNTPTime.c index fa5217faf..bd9821e4c 100644 --- a/modules/libcom/src/osi/osiNTPTime.c +++ b/modules/libcom/src/osi/osiNTPTime.c @@ -64,14 +64,21 @@ static void NTPTimeSync(void *dummy); /* NTPTime_Report iocsh command */ static const iocshArg ReportArg0 = { "interest_level", iocshArgArgv}; static const iocshArg * const ReportArgs[1] = { &ReportArg0 }; -static const iocshFuncDef ReportFuncDef = {"NTPTime_Report", 1, ReportArgs}; +static const iocshFuncDef ReportFuncDef = {"NTPTime_Report", 1, ReportArgs, + "Display time provider synchronization state\n" + " interest_level - with level 1 it also shows:\n" + " * synchronization interval\n" + " * time when last synchronized\n" + " * nominal and measured system tick rates\n" + " * server address (vxWorks only)\n"}; static void ReportCallFunc(const iocshArgBuf *args) { NTPTime_Report(args[0].ival); } /* NTPTime_Shutdown iocsh command */ -static const iocshFuncDef ShutdownFuncDef = {"NTPTime_Shutdown", 0, NULL}; +static const iocshFuncDef ShutdownFuncDef = {"NTPTime_Shutdown", 0, NULL, + "Shuts down NTP time synchronization thread\n"}; static void ShutdownCallFunc(const iocshArgBuf *args) { NTPTime_Shutdown(NULL); diff --git a/modules/libcom/src/valgrind/valgrind.h b/modules/libcom/src/valgrind/valgrind.h old mode 100755 new mode 100644 diff --git a/modules/libcom/src/yajl/yajl_parser.c b/modules/libcom/src/yajl/yajl_parser.c index b400709a6..b134228d2 100644 --- a/modules/libcom/src/yajl/yajl_parser.c +++ b/modules/libcom/src/yajl/yajl_parser.c @@ -29,6 +29,8 @@ #include "yajl_encode.h" #include "yajl_bytestack.h" +#include + #ifndef LLONG_MAX #define LLONG_MAX 0x7FFFFFFFFFFFFFFFLL #define LLONG_MIN (-0x7FFFFFFFFFFFFFFFLL - 1) @@ -334,7 +336,7 @@ yajl_do_parse(yajl_handle hand, const unsigned char * jsonText, yajl_buf_clear(hand->decodeBuf); yajl_buf_append(hand->decodeBuf, buf, bufLen); buf = yajl_buf_data(hand->decodeBuf); - d = strtod((char *) buf, NULL); + d = epicsStrtod((char *) buf, NULL); if ((d == HUGE_VAL || d == -HUGE_VAL) && errno == ERANGE) { diff --git a/modules/libcom/test/Makefile b/modules/libcom/test/Makefile old mode 100755 new mode 100644 index 3ad869afb..ef8605002 --- a/modules/libcom/test/Makefile +++ b/modules/libcom/test/Makefile @@ -337,3 +337,10 @@ include $(TOP)/configure/RULES rtemsTestData.c : $(TESTFILES) $(TOOLS)/epicsMakeMemFs.pl $(PERL) $(TOOLS)/epicsMakeMemFs.pl $@ epicsRtemsFSImage $(TESTFILES) + +epicsLoadTest$(DEP): epicsInstallDir.h + +# use INSTALL_LOCATION instead of FINAL_LOCATION since test executables are not installed. +epicsInstallDir.h: $(TOP)/configure/CONFIG_SITE* + $(ECHO) "INSTALL_LOCATION=$(INSTALL_LOCATION)" + $(PERL) $(TOP)/modules/database/src/std/softIoc/makeInstallDir.pl "$(INSTALL_LOCATION)" > $@ diff --git a/modules/libcom/test/epicsEnvTest.c b/modules/libcom/test/epicsEnvTest.c index 531f6c4bd..dc3cffdc5 100644 --- a/modules/libcom/test/epicsEnvTest.c +++ b/modules/libcom/test/epicsEnvTest.c @@ -48,13 +48,11 @@ static void child(void *arg) epicsEnvSet(CHILD, CHILD); } -MAIN(epicsEnvTest) +static void testThreadEnv(void) { unsigned int stackSize = epicsThreadGetStackSize(epicsThreadStackSmall); const char *value; - testPlan(3); - epicsEnvSet(PARENT, PARENT); value = getenv(PARENT); @@ -72,8 +70,43 @@ MAIN(epicsEnvTest) value = getenv(PARENT); testOk(value && (strcmp(value, PARENT) == 0), "PARENT environment variable not modified"); - - testDone(); - return 0; +} + +static void testChangeEnv(void) +{ + const char *foo = "foo", *bar = "bar", *name = "testChangeEnv"; + const char *temp; + testDiag("Changing env"); + + temp = getenv("testChangeEnv"); + testOk(!temp, "temp=\"%s\"", temp); + + /* make sure that "foo" has been copied into environ instead of referencing + * our string constant + */ + epicsEnvSet(name, foo); + temp = getenv("testChangeEnv"); + testOk(temp && temp!=foo && temp!=name && strcmp(temp, foo)==0, + "env set temp=\"%s\" name=\"%s\" foo=\"%s\"", temp, name, foo); + + /* check the same when changing */ + epicsEnvSet(name, bar); + temp = getenv("testChangeEnv"); + testOk(temp && temp!=foo && temp!=name && temp!=bar && strcmp(temp, bar)==0, + "env change temp=\"%s\" name=\"%s\" foo=\"%s\" bar=\"%s\"", temp, name, foo, bar); + + epicsEnvUnset(name); + + temp = getenv("testChangeEnv"); + testOk(!temp, "temp=\"%s\"", temp); +} + +MAIN(epicsEnvTest) +{ + + testPlan(7); + testThreadEnv(); + testChangeEnv(); + return testDone(); } diff --git a/modules/libcom/test/epicsLoadTest.cpp b/modules/libcom/test/epicsLoadTest.cpp index 304c42d73..3ffc89949 100644 --- a/modules/libcom/test/epicsLoadTest.cpp +++ b/modules/libcom/test/epicsLoadTest.cpp @@ -16,6 +16,8 @@ #include "epicsFindSymbol.h" #include "epicsThread.h" +#include "epicsInstallDir.h" + namespace { void loadBad() @@ -52,9 +54,9 @@ void loadCA() std::ostringstream strm; // running in eg. modules/libcom/test/O.linux-x86_64-debug #ifdef _WIN32 - strm<<"..\\..\\..\\..\\bin\\"<unicode_escape_url($section); - $section = '_' unless length $section; - return $section; + my($self, $t) = @_; + for ($t) { + s/<[^>]+>//g; # Strip HTML. + s/&[^;]+;//g; # Strip entities. + s/^\s+//; s/\s+$//; # Strip white space. + s/^([^a-zA-Z]+)$/pod$1/; # Prepend "pod" if no valid chars. + s/^[^a-zA-Z]+//; # First char must be a letter. + s/[^-a-zA-Z0-9_:.]+/-/g; # All other chars must be valid. + s/[-:.]+$//; # Strip trailing punctuation. + } + return $t; } 1; diff --git a/src/tools/EpicsHostArch.pl b/src/tools/EpicsHostArch.pl index 52c427253..abff49007 100644 --- a/src/tools/EpicsHostArch.pl +++ b/src/tools/EpicsHostArch.pl @@ -36,6 +36,7 @@ sub HostArch { 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 'linux-ppc64' if m/^powerpc64-linux/; return 'windows-x64' if m/^MSWin32-x64/; return 'win32-x86' if m/^MSWin32-x86/; return "cygwin-x86_64" if m/^x86_64-cygwin/; @@ -46,9 +47,8 @@ sub HostArch { my ($kernel, $hostname, $release, $version, $cpu) = uname; if (m/^darwin/) { for ($cpu) { - return 'darwin-x86' if m/^(i386|x86_64)/; - return 'darwin-ppc' if m/Power Macintosh/; - return 'darwin-aarch64' if m/arm64/; + return 'darwin-x86' if m/^x86_64/; + return 'darwin-aarch64' if m/^arm64/; } die "$0: macOS CPU type '$cpu' not recognized\n"; } diff --git a/src/tools/convertRelease.pl b/src/tools/convertRelease.pl index 3375eb4f2..b8c596edb 100644 --- a/src/tools/convertRelease.pl +++ b/src/tools/convertRelease.pl @@ -227,6 +227,12 @@ sub envPaths { # Check RELEASE file consistency with support modules # sub checkRelease { + die "\nEPICS_BASE must be set in a configure/RELEASE file.\n\n" + unless grep(m/^(EPICS_BASE)$/, @apps) && + exists $macros{EPICS_BASE} && + $macros{EPICS_BASE} ne '' && + -f "$macros{EPICS_BASE}/configure/CONFIG_BASE"; + my $status = 0; delete $macros{RULES}; delete $macros{TOP}; diff --git a/src/tools/makeTestfile.pl b/src/tools/makeTestfile.pl index 7a8234962..9bfb46f4f 100644 --- a/src/tools/makeTestfile.pl +++ b/src/tools/makeTestfile.pl @@ -6,7 +6,7 @@ # Operator of Los Alamos National Laboratory. # SPDX-License-Identifier: EPICS # EPICS BASE is distributed subject to a Software License Agreement found -# in file LICENSE that is included with this distribution. +# in file LICENSE that is included with this distribution. #************************************************************************* # The makeTestfile.pl script generates a file $target.t which is needed @@ -21,43 +21,91 @@ # target.t is the name of the Perl script to generate # executable is the name of the file the script runs +# Test programs that need more than 500 seconds to run should have the +# EPICS_UNITTEST_TIMEOUT environment variable set in their Makefile: +# longRunningTest.t: export EPICS_UNITTEST_TIMEOUT=3600 +# That embeds the timeout into the .t file. The timeout variable can also +# be set at runtime, which will override any compiled-in setting but the +# 'make runtests' command can't give a different timeout for each test. + use strict; +use File::Basename; +my $tool = basename($0); + +my $timeout = $ENV{EPICS_UNITTEST_TIMEOUT} // 500; # 8 min 20 sec + my ($TA, $HA, $target, $exe) = @ARGV; -my $exec; +my ($exec, $error); -# Use WINE to run windows target executables on non-windows host -if( $TA =~ /^win32-x86/ && $HA !~ /^win/ ) { - # new deb. derivatives have wine32 and wine64 - # older have wine and wine64 - # prefer wine32 if present - my $wine32 = "/usr/bin/wine32"; - $wine32 = "/usr/bin/wine" if ! -x $wine32; - $exec = "$wine32 $exe"; -} elsif( $TA =~ /^windows-x64/ && $HA !~ /^win/ ) { - $exec = "wine64 $exe"; - -# Run pc386 test harness w/ QEMU -} elsif( $TA =~ /^RTEMS-pc386-qemu$/ ) { - $exec = "qemu-system-i386 -m 64 -no-reboot -serial stdio -display none -net nic,model=ne2k_pci -net user,restrict=yes -kernel $exe"; - -# Explicitly fail for other RTEMS targets -} elsif( $TA =~ /^RTEMS-/ ) { - die "$0: I don't know how to create scripts for testing $TA on $HA\n"; - -} else { - $exec = "./$exe"; +if ($TA =~ /^win32-x86/ && $HA !~ /^win/) { + # Use WINE to run win32-x86 executables on non-windows hosts. + # New Debian derivatives have wine32 and wine64, older ones have + # wine and wine64. We prefer wine32 if present. + my $wine32 = "/usr/bin/wine32"; + $wine32 = "/usr/bin/wine" if ! -x $wine32; + $error = $exec = "$wine32 $exe"; +} +elsif ($TA =~ /^windows-x64/ && $HA !~ /^win/) { + # Use WINE to run windows-x64 executables on non-windows hosts. + $error = $exec = "wine64 $exe"; +} +elsif ($TA =~ /^RTEMS-pc[36]86-qemu$/) { + # Run the pc386 and pc686 test harness w/ QEMU + $exec = "qemu-system-i386 -m 64 -no-reboot " + . "-serial stdio -display none " + . "-net nic,model=e1000 -net nic,model=ne2k_pci " + . "-net user,restrict=yes " + . "-append --console=/dev/com1 " + . "-kernel $exe"; + $error = "qemu-system-i386 ... -kernel $exe"; +} +elsif ($TA =~ /^RTEMS-/) { + # Explicitly fail for other RTEMS targets + die "$tool: I don't know how to create scripts for testing $TA on $HA\n"; +} +else { + # Assume it's directly executable on other targets + $error = $exec = "./$exe"; } -# Ensure that Windows interactive error handling is disabled. -# This setting is inherited by the test process. -# Set SEM_FAILCRITICALERRORS (1) Disable critical-error-handler dialog -# Clear SEM_NOGPFAULTERRORBOX (2) Enabled WER to allow automatic post mortem debugging (AeDebug) -# Clear SEM_NOALIGNMENTFAULTEXCEPT (4) Allow alignment fixups -# Set SEM_NOOPENFILEERRORBOX (0x8000) Prevent dialog on some I/O errors -# https://docs.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-seterrormode?redirectedfrom=MSDN -my $sem = $^O ne 'MSWin32' ? '' : <', $target) + or die "$tool: Can't create $target: $!\n"; + +print $OUT <<__EOT__; +#!/usr/bin/env perl +# This file was generated by $tool + +use strict; +use Cwd 'abs_path'; +use File::Basename; +my \$tool = basename(\$0); + +\$ENV{HARNESS_ACTIVE} = 1 if scalar \@ARGV && shift eq '-tap'; +\$ENV{TOP} = abs_path(\$ENV{TOP}) if exists \$ENV{TOP}; + +# The timeout value below can be set in the Makefile that builds +# this test script. Add this line and adjust the value (in seconds): +# $target: export EPICS_UNITTEST_TIMEOUT=$timeout +my \$timeout = \$ENV{EPICS_UNITTEST_TIMEOUT} // $timeout; +__EOT__ + +if ($^O eq 'MSWin32') { + ######################################## Code for Windows run-hosts + print $OUT <<__WIN32__; + +use Win32::Process; +use Win32; + BEGIN { + # Ensure that Windows interactive error handling is disabled. + # This setting is inherited by the test process. + # Set SEM_FAILCRITICALERRORS (1) Disable critical-error-handler dialog + # Clear SEM_NOGPFAULTERRORBOX (2) Enabled WER to allow automatic post mortem debugging (AeDebug) + # Clear SEM_NOALIGNMENTFAULTEXCEPT (4) Allow alignment fixups + # Set SEM_NOOPENFILEERRORBOX (0x8000) Prevent dialog on some I/O errors + # https://docs.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-seterrormode my \$sem = 'SetErrorMode'; eval { require Win32::ErrorMode; @@ -69,30 +117,53 @@ BEGIN { } if \$@; SetErrorMode(0x8001) unless \$@; } -ENDBEGIN -open(my $OUT, '>', $target) or die "Can't create $target: $!\n"; +my \$proc; +if (! Win32::Process::Create(\$proc, abs_path('$exec'), + '$exec', 1, NORMAL_PRIORITY_CLASS, '.')) { + my \$err = Win32::FormatMessage(Win32::GetLastError()); + die "\$tool: Can't create Process for '$error': \$err\\n"; +} +if (! \$proc->Wait(1000 * \$timeout)) { + \$proc->Kill(1); + print "\\n#### Test stopped by \$tool after \$timeout seconds\\n"; + die "\$tool: Timed out '$error' after \$timeout seconds\\n"; +} +my \$status; +\$proc->GetExitCode(\$status); +exit \$status; -print $OUT <> 8; +__WIN32__ } else { - exec '$exec' or die "Can't run $exec: \$!\\n"; -} -EOF + ######################################## Code for Unix run-hosts + print $OUT <<__UNIX__; -close $OUT or die "Can't close $target: $!\n"; +my \$pid = fork(); +die "\$tool: Can't fork for '$error': \$!\\n" + unless defined \$pid; + +if (\$pid) { + # Parent process + \$SIG{ALRM} = sub { + # Time's up, kill the child + kill 9, \$pid; + print "\\n#### Test stopped by \$tool after \$timeout seconds\\n"; + die "\$tool: Timed out '$error' after \$timeout seconds\\n"; + }; + + alarm \$timeout; + waitpid \$pid, 0; + alarm 0; + exit \$? >> 8; +} +else { + # Child process + exec '$exec' + or die "\$tool: Can't run '$error': \$!\\n"; +} +__UNIX__ +} + +close $OUT + or die "$tool: Can't close '$target': $!\n"; diff --git a/startup/win32.bat b/startup/win32.bat index dc50e6a72..818912547 100755 --- a/startup/win32.bat +++ b/startup/win32.bat @@ -1,106 +1,106 @@ -@echo off -rem ************************************************************************* -rem Copyright (c) 2017 UChicago Argonne LLC, as Operator of Argonne -rem National Laboratory. -rem Copyright (c) 2002 The Regents of the University of California, as -rem Operator of Los Alamos National Laboratory. -rem SPDX-License-Identifier: EPICS -rem EPICS BASE is distributed subject to a Software License Agreement found -rem in file LICENSE that is included with this distribution. -rem ************************************************************************* -rem -rem Site-specific EPICS environment settings -rem -rem Sets EPICS_HOST_ARCH and the environment for Microsoft Visual Studio. -rem Optionally, resets PATH, adds Strawberry Perl to PATH, and adds the -rem EPICS Base install host architecture bin directory to PATH. -rem - -rem ---------------------------------------------------------------------- -rem Site serviceable parts (These definitions may be modified) -rem ---------------------------------------------------------------------- - -rem The values of the definitions in this section must not contain -rem double-quotes. -rem -rem * Right: set _foo=C:\foo -rem * Right: set "_foo=C:\foo" -rem * Wrong: set _foo="C:\foo" - -rem Automatically set up the environment when possible ("yes" or "no"). -rem If set to yes, as much of the environment will be set up as possible. -rem If set to no, just the minimum environment will be set up. More -rem specific _auto_* definitions take precedence over this definition. -set _auto=no - -rem Automatically reset PATH ("yes" or "no"). If set to yes, PATH will -rem be reset to the value of _path_new. If set to no, PATH will not be -rem reset. -set _auto_path_reset=%_auto% - -rem Automatically append to PATH ("yes" or "no"). If set to yes, the -rem EPICS Base install host architecture bin directory will be added to -rem PATH if possible. If set to no, the bin directory will not be added -rem to PATH. -set _auto_path_append=%_auto% - -rem The new value for PATH. If _auto_path_reset is yes, PATH will be set -rem to it. -set _path_new=C:\Windows\System32;C:\Windows;C:\Windows\System32\wbem - -rem The location of Strawberry Perl (pathname). If empty, Strawberry Perl -rem is assumed to already be in PATH and will not be added. If nonempty, -rem Strawberry Perl will be added to PATH. -set _strawberry_perl_home=C:\Strawberry - -rem The location of Microsoft Visual Studio (pathname). -set _visual_studio_home=C:\Program Files (x86)\Microsoft Visual Studio\2019\Community - -rem The EPICS host architecture specification for EPICS_HOST_ARCH -rem (-[-] as defined in configure/CONFIG_SITE). -set _epics_host_arch=win32-x86 - -rem The install location of EPICS Base (pathname). If nonempty and -rem _auto_path_append is yes, it will be used to add the host architecture -rem bin directory to PATH. -set _epics_base= - -rem ---------------------------------------------------------------------- -rem Internal parts (There is typically no need to modify these) -rem ---------------------------------------------------------------------- - -rem Reset PATH -if "%_auto_path_reset%" == "yes" ( - set "PATH=%_path_new%" -) - -rem Add Strawberry Perl to PATH -if "%_strawberry_perl_home%" == "" goto after_add_strawberry_perl -rem Can't do this inside parentheses because PATH would be read only once -set "PATH=%PATH%;%_strawberry_perl_home%\c\bin" -set "PATH=%PATH%;%_strawberry_perl_home%\perl\site\bin" -set "PATH=%PATH%;%_strawberry_perl_home%\perl\bin" -:after_add_strawberry_perl - -rem Set the environment for Microsoft Visual Studio -call "%_visual_studio_home%\VC\Auxiliary\Build\vcvarsall.bat" x86 - -rem Set the EPICS host architecture specification -set "EPICS_HOST_ARCH=%_epics_host_arch%" - -rem Add the EPICS Base host architecture bin directory to PATH -if "%_auto_path_append%" == "yes" ( - if not "%_epics_base%" == "" ( - set "PATH=%PATH%;%_epics_base%\bin\%_epics_host_arch%" - ) -) - -rem Don't leak variables into the environment -set _auto= -set _auto_path_reset= -set _auto_path_append= -set _path_new= -set _strawberry_perl_home= -set _visual_studio_home= -set _epics_host_arch= -set _epics_base= +@echo off +rem ************************************************************************* +rem Copyright (c) 2017 UChicago Argonne LLC, as Operator of Argonne +rem National Laboratory. +rem Copyright (c) 2002 The Regents of the University of California, as +rem Operator of Los Alamos National Laboratory. +rem SPDX-License-Identifier: EPICS +rem EPICS BASE is distributed subject to a Software License Agreement found +rem in file LICENSE that is included with this distribution. +rem ************************************************************************* +rem +rem Site-specific EPICS environment settings +rem +rem Sets EPICS_HOST_ARCH and the environment for Microsoft Visual Studio. +rem Optionally, resets PATH, adds Strawberry Perl to PATH, and adds the +rem EPICS Base install host architecture bin directory to PATH. +rem + +rem ---------------------------------------------------------------------- +rem Site serviceable parts (These definitions may be modified) +rem ---------------------------------------------------------------------- + +rem The values of the definitions in this section must not contain +rem double-quotes. +rem +rem * Right: set _foo=C:\foo +rem * Right: set "_foo=C:\foo" +rem * Wrong: set _foo="C:\foo" + +rem Automatically set up the environment when possible ("yes" or "no"). +rem If set to yes, as much of the environment will be set up as possible. +rem If set to no, just the minimum environment will be set up. More +rem specific _auto_* definitions take precedence over this definition. +set _auto=no + +rem Automatically reset PATH ("yes" or "no"). If set to yes, PATH will +rem be reset to the value of _path_new. If set to no, PATH will not be +rem reset. +set _auto_path_reset=%_auto% + +rem Automatically append to PATH ("yes" or "no"). If set to yes, the +rem EPICS Base install host architecture bin directory will be added to +rem PATH if possible. If set to no, the bin directory will not be added +rem to PATH. +set _auto_path_append=%_auto% + +rem The new value for PATH. If _auto_path_reset is yes, PATH will be set +rem to it. +set _path_new=C:\Windows\System32;C:\Windows;C:\Windows\System32\wbem + +rem The location of Strawberry Perl (pathname). If empty, Strawberry Perl +rem is assumed to already be in PATH and will not be added. If nonempty, +rem Strawberry Perl will be added to PATH. +set _strawberry_perl_home=C:\Strawberry + +rem The location of Microsoft Visual Studio (pathname). +set _visual_studio_home=C:\Program Files (x86)\Microsoft Visual Studio\2019\Community + +rem The EPICS host architecture specification for EPICS_HOST_ARCH +rem (-[-] as defined in configure/CONFIG_SITE). +set _epics_host_arch=win32-x86 + +rem The install location of EPICS Base (pathname). If nonempty and +rem _auto_path_append is yes, it will be used to add the host architecture +rem bin directory to PATH. +set _epics_base= + +rem ---------------------------------------------------------------------- +rem Internal parts (There is typically no need to modify these) +rem ---------------------------------------------------------------------- + +rem Reset PATH +if "%_auto_path_reset%" == "yes" ( + set "PATH=%_path_new%" +) + +rem Add Strawberry Perl to PATH +if "%_strawberry_perl_home%" == "" goto after_add_strawberry_perl +rem Can't do this inside parentheses because PATH would be read only once +set "PATH=%PATH%;%_strawberry_perl_home%\c\bin" +set "PATH=%PATH%;%_strawberry_perl_home%\perl\site\bin" +set "PATH=%PATH%;%_strawberry_perl_home%\perl\bin" +:after_add_strawberry_perl + +rem Set the environment for Microsoft Visual Studio +call "%_visual_studio_home%\VC\Auxiliary\Build\vcvarsall.bat" x86 + +rem Set the EPICS host architecture specification +set "EPICS_HOST_ARCH=%_epics_host_arch%" + +rem Add the EPICS Base host architecture bin directory to PATH +if "%_auto_path_append%" == "yes" ( + if not "%_epics_base%" == "" ( + set "PATH=%PATH%;%_epics_base%\bin\%_epics_host_arch%" + ) +) + +rem Don't leak variables into the environment +set _auto= +set _auto_path_reset= +set _auto_path_append= +set _path_new= +set _strawberry_perl_home= +set _visual_studio_home= +set _epics_host_arch= +set _epics_base= diff --git a/startup/windows.bat b/startup/windows.bat index a36e43fdb..27b6dcc0b 100644 --- a/startup/windows.bat +++ b/startup/windows.bat @@ -1,106 +1,106 @@ -@echo off -rem ************************************************************************* -rem Copyright (c) 2017 UChicago Argonne LLC, as Operator of Argonne -rem National Laboratory. -rem Copyright (c) 2002 The Regents of the University of California, as -rem Operator of Los Alamos National Laboratory. -rem SPDX-License-Identifier: EPICS -rem EPICS BASE is distributed subject to a Software License Agreement found -rem in file LICENSE that is included with this distribution. -rem ************************************************************************* -rem -rem Site-specific EPICS environment settings -rem -rem Sets EPICS_HOST_ARCH and the environment for Microsoft Visual Studio. -rem Optionally, resets PATH, adds Strawberry Perl to PATH, and adds the -rem EPICS Base install host architecture bin directory to PATH. -rem - -rem ---------------------------------------------------------------------- -rem Site serviceable parts (These definitions may be modified) -rem ---------------------------------------------------------------------- - -rem The values of the definitions in this section must not contain -rem double-quotes. -rem -rem * Right: set _foo=C:\foo -rem * Right: set "_foo=C:\foo" -rem * Wrong: set _foo="C:\foo" - -rem Automatically set up the environment when possible ("yes" or "no"). -rem If set to yes, as much of the environment will be set up as possible. -rem If set to no, just the minimum environment will be set up. More -rem specific _auto_* definitions take precedence over this definition. -set _auto=no - -rem Automatically reset PATH ("yes" or "no"). If set to yes, PATH will -rem be reset to the value of _path_new. If set to no, PATH will not be -rem reset. -set _auto_path_reset=%_auto% - -rem Automatically append to PATH ("yes" or "no"). If set to yes, the -rem EPICS Base install host architecture bin directory will be added to -rem PATH if possible. If set to no, the bin directory will not be added -rem to PATH. -set _auto_path_append=%_auto% - -rem The new value for PATH. If _auto_path_reset is yes, PATH will be set -rem to it. -set _path_new=C:\Windows\System32;C:\Windows;C:\Windows\System32\wbem - -rem The location of Strawberry Perl (pathname). If empty, Strawberry Perl -rem is assumed to already be in PATH and will not be added. If nonempty, -rem Strawberry Perl will be added to PATH. -set _strawberry_perl_home=C:\Strawberry - -rem The location of Microsoft Visual Studio (pathname). -set _visual_studio_home=C:\Program Files (x86)\Microsoft Visual Studio\2019\Community - -rem The EPICS host architecture specification for EPICS_HOST_ARCH -rem (-[-] as defined in configure/CONFIG_SITE). -set _epics_host_arch=windows-x64 - -rem The install location of EPICS Base (pathname). If nonempty and -rem _auto_path_append is yes, it will be used to add the host architecture -rem bin directory to PATH. -set _epics_base= - -rem ---------------------------------------------------------------------- -rem Internal parts (There is typically no need to modify these) -rem ---------------------------------------------------------------------- - -rem Reset PATH -if "%_auto_path_reset%" == "yes" ( - set "PATH=%_path_new%" -) - -rem Add Strawberry Perl to PATH -if "%_strawberry_perl_home%" == "" goto after_add_strawberry_perl -rem Can't do this inside parentheses because PATH would be read only once -set "PATH=%PATH%;%_strawberry_perl_home%\c\bin" -set "PATH=%PATH%;%_strawberry_perl_home%\perl\site\bin" -set "PATH=%PATH%;%_strawberry_perl_home%\perl\bin" -:after_add_strawberry_perl - -rem Set the environment for Microsoft Visual Studio -call "%_visual_studio_home%\VC\Auxiliary\Build\vcvarsall.bat" x64 - -rem Set the EPICS host architecture specification -set "EPICS_HOST_ARCH=%_epics_host_arch%" - -rem Add the EPICS Base host architecture bin directory to PATH -if "%_auto_path_append%" == "yes" ( - if not "%_epics_base%" == "" ( - set "PATH=%PATH%;%_epics_base%\bin\%_epics_host_arch%" - ) -) - -rem Don't leak variables into the environment -set _auto= -set _auto_path_reset= -set _auto_path_append= -set _path_new= -set _strawberry_perl_home= -set _visual_studio_home= -set _epics_host_arch= -set _epics_base= +@echo off +rem ************************************************************************* +rem Copyright (c) 2017 UChicago Argonne LLC, as Operator of Argonne +rem National Laboratory. +rem Copyright (c) 2002 The Regents of the University of California, as +rem Operator of Los Alamos National Laboratory. +rem SPDX-License-Identifier: EPICS +rem EPICS BASE is distributed subject to a Software License Agreement found +rem in file LICENSE that is included with this distribution. +rem ************************************************************************* +rem +rem Site-specific EPICS environment settings +rem +rem Sets EPICS_HOST_ARCH and the environment for Microsoft Visual Studio. +rem Optionally, resets PATH, adds Strawberry Perl to PATH, and adds the +rem EPICS Base install host architecture bin directory to PATH. +rem + +rem ---------------------------------------------------------------------- +rem Site serviceable parts (These definitions may be modified) +rem ---------------------------------------------------------------------- + +rem The values of the definitions in this section must not contain +rem double-quotes. +rem +rem * Right: set _foo=C:\foo +rem * Right: set "_foo=C:\foo" +rem * Wrong: set _foo="C:\foo" + +rem Automatically set up the environment when possible ("yes" or "no"). +rem If set to yes, as much of the environment will be set up as possible. +rem If set to no, just the minimum environment will be set up. More +rem specific _auto_* definitions take precedence over this definition. +set _auto=no + +rem Automatically reset PATH ("yes" or "no"). If set to yes, PATH will +rem be reset to the value of _path_new. If set to no, PATH will not be +rem reset. +set _auto_path_reset=%_auto% + +rem Automatically append to PATH ("yes" or "no"). If set to yes, the +rem EPICS Base install host architecture bin directory will be added to +rem PATH if possible. If set to no, the bin directory will not be added +rem to PATH. +set _auto_path_append=%_auto% + +rem The new value for PATH. If _auto_path_reset is yes, PATH will be set +rem to it. +set _path_new=C:\Windows\System32;C:\Windows;C:\Windows\System32\wbem + +rem The location of Strawberry Perl (pathname). If empty, Strawberry Perl +rem is assumed to already be in PATH and will not be added. If nonempty, +rem Strawberry Perl will be added to PATH. +set _strawberry_perl_home=C:\Strawberry + +rem The location of Microsoft Visual Studio (pathname). +set _visual_studio_home=C:\Program Files (x86)\Microsoft Visual Studio\2019\Community + +rem The EPICS host architecture specification for EPICS_HOST_ARCH +rem (-[-] as defined in configure/CONFIG_SITE). +set _epics_host_arch=windows-x64 + +rem The install location of EPICS Base (pathname). If nonempty and +rem _auto_path_append is yes, it will be used to add the host architecture +rem bin directory to PATH. +set _epics_base= + +rem ---------------------------------------------------------------------- +rem Internal parts (There is typically no need to modify these) +rem ---------------------------------------------------------------------- + +rem Reset PATH +if "%_auto_path_reset%" == "yes" ( + set "PATH=%_path_new%" +) + +rem Add Strawberry Perl to PATH +if "%_strawberry_perl_home%" == "" goto after_add_strawberry_perl +rem Can't do this inside parentheses because PATH would be read only once +set "PATH=%PATH%;%_strawberry_perl_home%\c\bin" +set "PATH=%PATH%;%_strawberry_perl_home%\perl\site\bin" +set "PATH=%PATH%;%_strawberry_perl_home%\perl\bin" +:after_add_strawberry_perl + +rem Set the environment for Microsoft Visual Studio +call "%_visual_studio_home%\VC\Auxiliary\Build\vcvarsall.bat" x64 + +rem Set the EPICS host architecture specification +set "EPICS_HOST_ARCH=%_epics_host_arch%" + +rem Add the EPICS Base host architecture bin directory to PATH +if "%_auto_path_append%" == "yes" ( + if not "%_epics_base%" == "" ( + set "PATH=%PATH%;%_epics_base%\bin\%_epics_host_arch%" + ) +) + +rem Don't leak variables into the environment +set _auto= +set _auto_path_reset= +set _auto_path_append= +set _path_new= +set _strawberry_perl_home= +set _visual_studio_home= +set _epics_host_arch= +set _epics_base=