Compare commits
100 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 157b0867fa | |||
| 56529964f3 | |||
| c28e240fce | |||
| b04b2dab22 | |||
| 8edcd7b07f | |||
| ca78451122 | |||
| 4cc44e3dce | |||
| e81d3a1d7d | |||
| 53dd61b80a | |||
|
|
841ef37820 | ||
|
|
f550f278ad | ||
|
|
1706da98cc | ||
|
|
e8be04bc43 | ||
|
|
dee526f2f6 | ||
|
|
59cffd51ae | ||
|
|
9b5034f307 | ||
|
|
e2881fb37e | ||
|
|
afd9697290 | ||
|
|
9988be0906 | ||
|
|
a6812c5869 | ||
|
|
b89494a840 | ||
|
|
771ad6a442 | ||
|
|
d214d81794 | ||
|
|
c70b1a9a29 | ||
|
|
c9c4eea0f8 | ||
|
|
78ce2dac05 | ||
|
|
b2285bb8aa | ||
|
|
59cb5ba6a0 | ||
|
|
c8e5deca76 | ||
|
|
5b09bb6e71 | ||
|
|
ede52d96b8 | ||
|
|
ceccafe823 | ||
|
|
f955199805 | ||
|
|
2af0c10470 | ||
|
|
89f0f1338a | ||
|
|
6ce8dfec01 | ||
|
|
c1ab30142a | ||
|
|
2db2f1a53f | ||
|
|
b811d3402f | ||
|
|
a64cb4a877 | ||
|
|
e75a72ef76 | ||
|
|
33e099a51b | ||
|
|
345cfcffa8 | ||
|
|
655c5bed92 | ||
|
|
2c99c36ef9 | ||
|
|
71d4d3ecbd | ||
|
|
86138fdd23 | ||
|
|
8c993405b4 | ||
|
|
96259b7bdc | ||
|
|
bf8ff4e5f1 | ||
|
|
25576c316a | ||
|
|
2d3de1916b | ||
|
|
fe34c6f35e | ||
|
|
52cdfe0a44 | ||
|
|
16ddcaeaed | ||
|
|
297206e247 | ||
|
|
3110322f8c | ||
|
|
63bf8a8219 | ||
|
|
ec7193d0be | ||
|
|
17dea964a6 | ||
|
|
12283ce25a | ||
|
|
f486dba478 | ||
|
|
1f95d0db12 | ||
|
|
e02c5c3026 | ||
|
|
8e9d75ad71 | ||
|
|
630663caa8 | ||
|
|
7a84a1abba | ||
|
|
a9dbd4dd39 | ||
|
|
ccf34ae3d0 | ||
|
|
f559c36a6f | ||
|
|
8217fa86fe | ||
|
|
f0e118da91 | ||
|
|
5a55aa17d9 | ||
|
|
f79f2cf8fa | ||
|
|
f0f7a1ef06 | ||
|
|
1412abadf9 | ||
|
|
3a0371894b | ||
|
|
e92a9ae426 | ||
|
|
3a5fb898d6 | ||
|
|
95cb81c286 | ||
|
|
a9606dbf6e | ||
|
|
409ee26fae | ||
|
|
9a4787155c | ||
|
|
84dba0d2b7 | ||
|
|
87f6c3dec9 | ||
|
|
940814becf | ||
|
|
68a1a529b2 | ||
|
|
ce38caf41b | ||
|
|
f03f10e664 | ||
|
|
b4f4fb853d | ||
|
|
b518ebe85b | ||
|
|
e461d782f4 | ||
|
|
ef2a381e92 | ||
|
|
265d4962a4 | ||
|
|
db9267bbd5 | ||
|
|
1cf3fa9ba9 | ||
|
|
3e8b0028dc | ||
|
|
d8f18c27f4 | ||
|
|
801c01b9b6 | ||
|
|
0c1874bbfe |
@@ -48,6 +48,7 @@ environment:
|
||||
TOOLCHAIN: 2017
|
||||
- TOOLCHAIN: cygwin
|
||||
- TOOLCHAIN: mingw
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
|
||||
# Platform: architecture
|
||||
platform:
|
||||
@@ -60,6 +61,10 @@ matrix:
|
||||
# VS Express installs don't have the 64 bit compiler
|
||||
- platform: x64
|
||||
TOOLCHAIN: 10.0
|
||||
# Cygwin static-debug has compiler problems
|
||||
- configuration: static-debug
|
||||
TOOLCHAIN: cygwin
|
||||
|
||||
|
||||
#---------------------------------#
|
||||
# building & testing #
|
||||
@@ -81,6 +86,9 @@ test_script:
|
||||
|
||||
notifications:
|
||||
|
||||
- provider: Slack
|
||||
incoming_webhook:
|
||||
secure: RYOm3FIUYeZGjWKaeTVKwq+C3fzK54AKwbmAoECED45mex3lN+8HmrC845a6mg9xPUJ/ND51RopWVaKDD9/UzaM0SO195RQLKqUTIUafiuM=
|
||||
- provider: Email
|
||||
to:
|
||||
- core-talk@aps.anl.gov
|
||||
on_build_success: false
|
||||
|
||||
- provider: GitHubPullRequest
|
||||
|
||||
@@ -42,13 +42,13 @@ if "%TOOLCHAIN%"=="mingw" (
|
||||
set "MAKE=mingw32-make"
|
||||
if "%OS%"=="64BIT" (
|
||||
set "EPICS_HOST_ARCH=windows-x64-mingw"
|
||||
set "INCLUDE=C:\tools\mingw64\include;%INCLUDE%"
|
||||
set "PATH=C:\tools\mingw64\bin;%PATH%"
|
||||
set "INCLUDE=C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\include;%INCLUDE%"
|
||||
set "PATH=C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin;%PATH%"
|
||||
echo [INFO] MinGW Toolchain 64bit
|
||||
) else (
|
||||
set "EPICS_HOST_ARCH=win32-x86-mingw"
|
||||
set "INCLUDE=C:\tools\mingw32\include;%INCLUDE%"
|
||||
set "PATH=C:\tools\mingw32\bin;%PATH%"
|
||||
set "INCLUDE=C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\include;%INCLUDE%"
|
||||
set "PATH=C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\bin;%PATH%"
|
||||
echo [INFO] MinGW Toolchain 32bit
|
||||
)
|
||||
echo [INFO] Compiler Version
|
||||
|
||||
@@ -55,16 +55,9 @@ if "%TOOLCHAIN%"=="mingw" (
|
||||
) || (
|
||||
echo [INFO] EPICS set up for optimized build
|
||||
)
|
||||
if "%OS%"=="64BIT" (
|
||||
echo [INFO] Installing MinGW 64bit
|
||||
cinst mingw || cinst mingw
|
||||
) else (
|
||||
echo [INFO] Installing MinGW 32bit
|
||||
cinst mingw --x86 || cinst mingw --x86
|
||||
)
|
||||
)
|
||||
|
||||
echo [INFO] Installing Make 4.1
|
||||
curl -fsS --retry 3 -o C:\tools\make-4.1.zip https://epics.anl.gov/download/tools/make-4.1-win64.zip
|
||||
echo [INFO] Installing Make 4.2.1 from ANL web site
|
||||
curl -fsS --retry 3 -o C:\tools\make-4.2.1.zip https://epics.anl.gov/download/tools/make-4.2.1-win64.zip
|
||||
cd \tools
|
||||
"C:\Program Files\7-Zip\7z" e make-4.1.zip
|
||||
"C:\Program Files\7-Zip\7z" e make-4.2.1.zip
|
||||
|
||||
@@ -16,23 +16,46 @@ PREFIX="$3"
|
||||
if ! [ "$TOPREV" ]
|
||||
then
|
||||
cat <<EOF >&2
|
||||
usage: $0 [rev] [outfile.tar.gz] [prefix/]
|
||||
usage: $0 <rev> [<outfile> [<prefix>]]
|
||||
|
||||
<rev> may be any git revision spec. (tag, branch, or commit id).
|
||||
|
||||
Output file may be .tar.gz, .tar.bz2, or any extension supported by "tar -a".
|
||||
If output file name is omitted, "base-<rev>.tar.gz" will be used.
|
||||
If <prefix> is omitted, the default prefix is "base-<rev>/".
|
||||
If provided, <outfile> must end with ".tar", ".tar.gz" or ".tar.bz2".
|
||||
If <outfile> is omitted, "base-<rev>.tar.gz" will be used.
|
||||
If provided, <prefix> must end with "/". If <prefix> is omitted,
|
||||
the default is "base-<rev>/".
|
||||
EOF
|
||||
exit 1
|
||||
fi
|
||||
|
||||
[ "$FINALTAR" ] || FINALTAR="base-$TOPREV.tar.gz"
|
||||
[ "$PREFIX" ] || PREFIX="base-$TOPREV/"
|
||||
case "$FINALTAR" in
|
||||
"")
|
||||
TAROPT=-z
|
||||
FINALTAR="base-$TOPREV.tar.gz"
|
||||
;;
|
||||
*.tar)
|
||||
TAROPT=""
|
||||
;;
|
||||
*.tar.gz)
|
||||
TAROPT=-z
|
||||
;;
|
||||
*.tar.bz2)
|
||||
TAROPT=-j
|
||||
;;
|
||||
*)
|
||||
die "outfile must end with '.tar.gz' or '.tar.bz2'"
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$PREFIX" in
|
||||
*/) ;;
|
||||
*) die "Prefix must end with '/'";;
|
||||
"")
|
||||
PREFIX="base-$TOPREV/"
|
||||
;;
|
||||
*/)
|
||||
;;
|
||||
*)
|
||||
die "Prefix must end with '/'"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Check for both <tag> and R<tag>
|
||||
@@ -97,13 +120,11 @@ then
|
||||
fi
|
||||
|
||||
# Use the filtered list to build the final tar
|
||||
# The -a option chooses compression automatically based on output file name.
|
||||
|
||||
tar -C "$TDIR"/tar --files-from="$TDIR"/list.2 -caf "$FINALTAR"
|
||||
tar -c $TAROPT -C "$TDIR"/tar -T "$TDIR"/list.2 -f "$FINALTAR"
|
||||
|
||||
echo "Wrote $FINALTAR"
|
||||
|
||||
tar -taf "$FINALTAR" > "$TDIR"/list.3
|
||||
tar -t $TAROPT -f "$FINALTAR" > "$TDIR"/list.3
|
||||
|
||||
# make sure we haven't picked up anything extra
|
||||
if ! diff -u "$TDIR"/list.2 "$TDIR"/list.3
|
||||
|
||||
@@ -34,7 +34,7 @@ CODE_CFLAGS = $(PROF_CFLAGS_$(PROFILE)) $(GPROF_CFLAGS_$(GPROF))
|
||||
CODE_CFLAGS += $(ASAN_FLAGS_$(ENABLE_ASAN))
|
||||
WARN_CFLAGS_YES = -Wall
|
||||
WARN_CFLAGS_NO = -w
|
||||
OPT_CFLAGS_YES = -O3
|
||||
OPT_CFLAGS_YES = -O3 -g
|
||||
OPT_CFLAGS_NO = -g
|
||||
|
||||
PROF_CXXFLAGS_YES = -p
|
||||
@@ -43,7 +43,7 @@ CODE_CXXFLAGS = $(PROF_CXXFLAGS_$(PROFILE)) $(GPROF_CXXFLAGS_$(GPROF))
|
||||
CODE_CXXFLAGS += $(ASAN_FLAGS_$(ENABLE_ASAN))
|
||||
WARN_CXXFLAGS_YES = -Wall
|
||||
WARN_CXXFLAGS_NO = -w
|
||||
OPT_CXXFLAGS_YES = -O3
|
||||
OPT_CXXFLAGS_YES = -O3 -g
|
||||
OPT_CXXFLAGS_NO = -g
|
||||
|
||||
CODE_LDFLAGS = $(PROF_CXXFLAGS_$(PROFILE)) $(GPROF_CXXFLAGS_$(GPROF))
|
||||
|
||||
@@ -30,10 +30,11 @@ endif # BASE_TOP
|
||||
#---------------------------------------------------------------
|
||||
# Where to find the installed build tools
|
||||
# Windows does not like commands with relative paths starting ../
|
||||
# but the Perl scripts in TOP/src/tools are OK
|
||||
# so TOOLS must be an absolute path, although Perl scripts are OK.
|
||||
# FIND_TOOL is for scripts run before the build reaches src/tools.
|
||||
|
||||
TOOLS = $(abspath $(EPICS_BASE_HOST_BIN))
|
||||
FIND_TOOL = $(firstword $(wildcard $(TOOLS)/$(1) $(TOP)/src/tools/$(1)))
|
||||
FIND_TOOL = $(firstword $(wildcard $(TOOLS)/$(1) $(EPICS_BASE)/src/tools/$(1)))
|
||||
|
||||
#---------------------------------------------------------------
|
||||
# EPICS Base build tools and tool flags
|
||||
@@ -54,3 +55,8 @@ INSTALL_LIBRARY = $(INSTALL)
|
||||
# tools for making header dependencies and variable replacement
|
||||
MKMF = $(PERL) $(TOOLS)/mkmf.pl
|
||||
REPLACEVAR = $(PERL) $(TOOLS)/replaceVAR.pl
|
||||
|
||||
#---------------------------------------------------------------
|
||||
# tools for cleaning out unwanted files
|
||||
CVSCLEAN = $(call FIND_TOOL,cvsclean.pl)
|
||||
DEPCLEAN = $(call FIND_TOOL,depclean.pl)
|
||||
|
||||
@@ -48,16 +48,16 @@ EPICS_VERSION = 7
|
||||
EPICS_REVISION = 0
|
||||
|
||||
# EPICS_MODIFICATION must be a number >=0 and <256
|
||||
EPICS_MODIFICATION = 2
|
||||
EPICS_MODIFICATION = 3
|
||||
|
||||
# EPICS_PATCH_LEVEL must be a number (win32 resource file requirement)
|
||||
# Not included if zero
|
||||
EPICS_PATCH_LEVEL = 2
|
||||
# Not included in the official EPICS version number if zero
|
||||
EPICS_PATCH_LEVEL = 0
|
||||
|
||||
# Between official releases, the EPICS_PATCH_LEVEL gets incremented
|
||||
# and a -DEV suffix is added (similar to the Maven -SNAPSHOT versions)
|
||||
#EPICS_DEV_SNAPSHOT=
|
||||
EPICS_DEV_SNAPSHOT=-DEV
|
||||
EPICS_DEV_SNAPSHOT=
|
||||
#EPICS_DEV_SNAPSHOT=-DEV
|
||||
#EPICS_DEV_SNAPSHOT=-pre1
|
||||
#EPICS_DEV_SNAPSHOT=-pre1-DEV
|
||||
#EPICS_DEV_SNAPSHOT=-pre2
|
||||
|
||||
@@ -564,6 +564,6 @@ include $(CONFIG)/RULES_EXPAND
|
||||
include $(CONFIG)/RULES_COMMON
|
||||
|
||||
else
|
||||
$(warning RULES_BUILD included more than once. \
|
||||
Use 'make show-makefiles' to work out why.)
|
||||
$(warning Warning: Base configure/RULES_BUILD file included more than once. \
|
||||
Does configure/RELEASE have multiple pointers to $(EPICS_BASE)?)
|
||||
endif # BASE_RULES_BUILD
|
||||
|
||||
@@ -8,16 +8,18 @@
|
||||
# These rules show the set of Makefiles, config files and
|
||||
# rules files loaded by GNUmake.
|
||||
|
||||
# Protect against filenames containing colons (Windows)
|
||||
SAFE_MAKEFILES = $(subst :,__colon__,$(MAKEFILE_LIST))
|
||||
SHOW_MAKEFILES = $(SAFE_MAKEFILES:%=show-makefile.%)
|
||||
show-makefiles: $(SHOW_MAKEFILES)
|
||||
show-makefiles::
|
||||
@echo
|
||||
@echo Makefiles read:
|
||||
define SHOW_MAKEFILE_template
|
||||
show-makefiles::
|
||||
@echo " $(1)"
|
||||
endef
|
||||
$(foreach file,$(MAKEFILE_LIST), \
|
||||
$(eval $(call SHOW_MAKEFILE_template,$(file))))
|
||||
|
||||
# The sort prevents warnings about duplicate targets:
|
||||
$(sort $(SHOW_MAKEFILES)): show-makefile.%:
|
||||
@echo " $(subst __colon__,:,$(@:show-makefile.%=%))"
|
||||
.PHONY: show-makefiles
|
||||
|
||||
.PHONY: show-makefiles show-makefile.%
|
||||
|
||||
# These rules support printing a Makefile variable values.
|
||||
# Many variables are only set inside an O.<arch> build directory.
|
||||
@@ -30,6 +32,17 @@ PRINT.%:
|
||||
.PHONY: PRINT PRINT.%
|
||||
|
||||
|
||||
# Clean rules for recursively deleting editor backup files
|
||||
# and dependency (.d) files from CWD and below.
|
||||
|
||||
cvsclean:
|
||||
$(PERL) $(CVSCLEAN)
|
||||
depclean:
|
||||
$(PERL) $(DEPCLEAN)
|
||||
|
||||
.PHONY: cvsclean depclean
|
||||
|
||||
|
||||
# User specific rules
|
||||
#
|
||||
-include $(HOME)/configure/RULES_USER
|
||||
|
||||
@@ -86,10 +86,11 @@ $(DIRS) $(dirActionTargets) $(dirArchTargets) $(dirActionArchTargets) :
|
||||
$(ARCHS) $(ACTIONS) $(actionArchTargets) :%: \
|
||||
$(foreach dir, $(DIRS), $(dir)$(DIVIDER)%)
|
||||
|
||||
.PHONY : $(DIRS) all host rebuild
|
||||
.PHONY : $(ARCHS) $(ACTIONS)
|
||||
.PHONY : $(dirActionTargets) $(dirArchTargets)
|
||||
.PHONY : $(dirActionArchTargets)
|
||||
.PHONY : $(actionArchTargets)
|
||||
|
||||
.PHONY: $(DIRS) all host rebuild
|
||||
.PHONY: $(ARCHS) $(ACTIONS)
|
||||
.PHONY: $(dirActionTargets) $(dirArchTargets)
|
||||
.PHONY: $(dirActionArchTargets)
|
||||
.PHONY: $(actionArchTargets)
|
||||
|
||||
include $(CONFIG)/RULES_COMMON
|
||||
|
||||
47
configure/RULES_MODULES
Normal file
47
configure/RULES_MODULES
Normal file
@@ -0,0 +1,47 @@
|
||||
#*************************************************************************
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
|
||||
# Support modules can use these rules to build submodules too.
|
||||
#
|
||||
# The requirements to do so are:
|
||||
# 1. Create a file CONFIG_SITE.local in the same directory as the
|
||||
# Makefile, which defines these variables (the last one is empty):
|
||||
# PARENT_MODULE - The name submodules call their parent
|
||||
# INSTALL_LOCATION := $($(PARENT_MODULE))
|
||||
# CONFIG_INSTALLS =
|
||||
# 2. The Makefile must set TOP and include $(TOP)/configure/CONFIG and
|
||||
# CONFIG_SITE.local
|
||||
# 3. Submodules are added to the SUBMODULES variable in the Makefile
|
||||
# 4. Dependencies between submodules must be set using
|
||||
# <name>_DEPEND_DIRS = <prerequisites>
|
||||
# 5. The Makefile must end by including $(TOP)/configure/RULES_MODULES
|
||||
# 6. Submodules must have a configure/RELEASE file that contains
|
||||
# -include $(TOP)/../RELEASE.$(EPICS_HOST_ARCH).local
|
||||
# 7. Submodules must have a configure/CONFIG_SITE file that contains
|
||||
# -include $(TOP)/../CONFIG_SITE.local
|
||||
|
||||
# Add checked-out submodules to DIRS
|
||||
DIRS += $(subst /Makefile,,$(wildcard $(addsuffix /Makefile, $(SUBMODULES))))
|
||||
|
||||
include $(CONFIG)/RULES_DIRS
|
||||
|
||||
INSTALL_LOCATION_ABS := $(abspath $(INSTALL_LOCATION))
|
||||
RELEASE_LOCAL := RELEASE.$(EPICS_HOST_ARCH).local
|
||||
|
||||
# Ensure that RELEASE.<host>.local exists before doing anything else
|
||||
all host $(DIRS) $(ARCHS) $(ACTIONS) $(dirActionTargets) $(dirArchTargets) \
|
||||
$(dirActionArchTargets) $(actionArchTargets): | $(RELEASE_LOCAL)
|
||||
|
||||
# Convenience target
|
||||
RELEASE.host: $(RELEASE_LOCAL)
|
||||
|
||||
$(RELEASE_LOCAL): Makefile CONFIG_SITE.local
|
||||
$(ECHO) Creating $@ with
|
||||
$(ECHO) " $(PARENT_MODULE) = $(INSTALL_LOCATION_ABS)"
|
||||
@echo $(PARENT_MODULE) = $(INSTALL_LOCATION_ABS)> $@
|
||||
realclean:
|
||||
$(RM) $(wildcard RELEASE.*.local)
|
||||
|
||||
.PHONY: RELEASE.host realclean
|
||||
@@ -9,26 +9,30 @@
|
||||
|
||||
include $(CONFIG)/RULES_DIRS
|
||||
|
||||
# Disable most top rules when installing into a parent's tree, indicated
|
||||
# by PARENT_MODULE being set in the modules/CONFIG_SITE.local file and
|
||||
# INSTALL_LOCATION pointing to the the same place as in the parent.
|
||||
ifeq ($(origin PARENT_MODULE),file)
|
||||
ifeq ($(INSTALL_LOCATION),$($(PARENT_MODULE)))
|
||||
DISABLE_TOP_RULES=YES
|
||||
endif
|
||||
endif
|
||||
|
||||
ifndef DISABLE_TOP_RULES
|
||||
#
|
||||
# Rules for a regular application top directory
|
||||
#
|
||||
|
||||
distclean: realclean cvsclean realuninstall
|
||||
|
||||
CVSCLEAN = $(call FIND_TOOL,cvsclean.pl)
|
||||
cvsclean:
|
||||
$(PERL) $(CVSCLEAN)
|
||||
|
||||
DEPCLEAN = $(call FIND_TOOL,depclean.pl)
|
||||
depclean:
|
||||
$(PERL) $(DEPCLEAN)
|
||||
|
||||
realuninstall: uninstallDirs
|
||||
$(RMDIR) $(INSTALL_LOCATION_BIN)
|
||||
$(RMDIR) $(INSTALL_LOCATION_LIB)
|
||||
|
||||
UNINSTALL_DIRS += $(INSTALL_DBD) $(INSTALL_INCLUDE) $(INSTALL_DOC) \
|
||||
$(INSTALL_HTML) $(INSTALL_TEMPLATES) $(INSTALL_DB) $(DIRECTORY_TARGETS)
|
||||
UNINSTALL_DIRS += $(INSTALL_DB) $(INSTALL_DBD) $(INSTALL_DOC) $(INSTALL_HTML)
|
||||
UNINSTALL_DIRS += $(INSTALL_INCLUDE) $(INSTALL_TEMPLATES) $(DIRECTORY_TARGETS)
|
||||
ifneq ($(INSTALL_LOCATION),$(TOP))
|
||||
ifneq ($(INSTALL_LOCATION),$(EPICS_BASE))
|
||||
UNINSTALL_DIRS += $(INSTALL_CONFIG)
|
||||
endif
|
||||
UNINSTALL_DIRS += $(INSTALL_CONFIG)
|
||||
endif
|
||||
uninstallDirs:
|
||||
$(RMDIR) $(UNINSTALL_DIRS)
|
||||
@@ -42,6 +46,8 @@ uninstall$(DIVIDER)%:
|
||||
$(RMDIR) $(INSTALL_LOCATION_BIN)/$(archPart)
|
||||
$(RMDIR) $(INSTALL_LOCATION_LIB)/$(archPart)
|
||||
|
||||
# Remove the bin and lib directories if they have no sub-directories
|
||||
#
|
||||
cleandirs:
|
||||
@$(NOP)
|
||||
ifeq ($(wildcard $(INSTALL_LOCATION_BIN)/*),)
|
||||
@@ -51,6 +57,16 @@ ifeq ($(wildcard $(INSTALL_LOCATION_LIB)/*),)
|
||||
$(RMDIR) $(INSTALL_LOCATION_LIB)
|
||||
endif
|
||||
|
||||
else
|
||||
#
|
||||
# Using a disabled rule aborts
|
||||
#
|
||||
|
||||
cleandirs distclean uninstall realuninstall archuninstall:
|
||||
$(error Target '$@' not available in a submodule)
|
||||
|
||||
endif # DISABLE_TOP_RULES
|
||||
|
||||
|
||||
help:
|
||||
@echo "Usage: gnumake [options] [target] ..."
|
||||
@@ -66,33 +82,39 @@ help:
|
||||
@echo " Cannot be used within an O.<arch> dir"
|
||||
@echo " rebuild - Same as clean install"
|
||||
@echo " archclean - Removes O.<arch> dirs but not O.Common dir"
|
||||
@echo " runtests - Run self-tests, summarize results"
|
||||
@echo " depclean - Removes .d files from all O.<arch> dirs."
|
||||
@echo " cvsclean - Removes backup files etc. from all dirs below"
|
||||
@echo " runtests - Run self-tests, summarize results immediately"
|
||||
@echo " tapfiles - Run self-tests, save to O.<arch>/*.tap files"
|
||||
@echo " test-results - Summarize all O.<arch>/*.tap files"
|
||||
@echo " clean-tests - Removes all O.<arch>/*.tap files"
|
||||
@echo "\"Partial\" build targets supported by Makefiles:"
|
||||
@echo " host - Builds and installs $(EPICS_HOST_ARCH) only."
|
||||
@echo " inc$(DIVIDER)<arch> - Installs <arch> only header files."
|
||||
@echo " build$(DIVIDER)<arch> - Builds and installs <arch> only."
|
||||
@echo " install$(DIVIDER)<arch> - Builds and installs <arch> only."
|
||||
@echo " clean$(DIVIDER)<arch> - Cleans <arch> binaries in O.<arch> dirs only."
|
||||
@echo " uninstall$(DIVIDER)<arch> - Remove bin & lib directories for <arch> only."
|
||||
@echo "Targets supported by top level Makefile:"
|
||||
ifndef DISABLE_TOP_RULES
|
||||
@echo " archuninstall - Remove bin & lib directories created by this hostarch."
|
||||
@echo " uninstall$(DIVIDER)<arch> - Remove bin & lib directories for <arch> only."
|
||||
@echo " uninstall - Remove install directories created by this hostarch."
|
||||
@echo " realuninstall - Removes ALL install dirs"
|
||||
@echo " distclean - Same as realclean cvsclean realuninstall."
|
||||
@echo " depclean - Removes all .d files from O.<arch> directories."
|
||||
@echo " cvsclean - Removes cvs .#* files in all dirs of directory tree"
|
||||
endif
|
||||
@echo " help - Prints this list of valid make targets "
|
||||
@echo "Indiv. object targets are supported by O.<arch> level Makefile .e.g"
|
||||
@echo "Object targets are supported by the O.<arch> level Makefile .e.g"
|
||||
@echo " xxxRecord.o"
|
||||
|
||||
.PHONY: cleandirs distclean cvsclean depclean
|
||||
.PHONY: cleandirs distclean uninstall help
|
||||
.PHONY: realuninstall archuninstall uninstallDirs
|
||||
.PHONY: uninstall help
|
||||
|
||||
# Include <top>/cfg/TOP_RULES* files from tops defined in RELEASE* files
|
||||
#
|
||||
RELEASE_CFG_TOP_RULES = $(foreach top, $(RELEASE_TOPS), \
|
||||
$(wildcard $($(top))/cfg/TOP_RULES*))
|
||||
ifneq ($(RELEASE_CFG_TOP_RULES),)
|
||||
include $(RELEASE_CFG_TOP_RULES)
|
||||
ifndef DISABLE_TOP_RULES
|
||||
# Include <top>/cfg/TOP_RULES* files from tops defined in RELEASE* files
|
||||
#
|
||||
RELEASE_CFG_TOP_RULES = $(foreach top, $(RELEASE_TOPS), \
|
||||
$(wildcard $($(top))/cfg/TOP_RULES*))
|
||||
ifneq ($(RELEASE_CFG_TOP_RULES),)
|
||||
include $(RELEASE_CFG_TOP_RULES)
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Include definitions common to linux pentium targets
|
||||
include $(CONFIG)/os/CONFIG.Common.linux-x86_64
|
||||
|
||||
COMMANDLINE_LIBRARY = READLINE
|
||||
ARCH_DEP_CXXFLAGS += -fno-strict-aliasing
|
||||
|
||||
@@ -1,3 +1 @@
|
||||
include $(CONFIG)/os/CONFIG.Common.linux-clang
|
||||
|
||||
COMMANDLINE_LIBRARY = READLINE
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
# Include definitions common to linux pentium targets
|
||||
include $(CONFIG)/os/CONFIG.Common.linux-x86
|
||||
|
||||
COMMANDLINE_LIBRARY = READLINE
|
||||
|
||||
ARCH_DEP_CFLAGS += -march=i686
|
||||
|
||||
# remove warning in anyscalar.h
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
# Include definitions common to linux pentium targets
|
||||
include $(CONFIG)/os/CONFIG.Common.linux-x86_64
|
||||
|
||||
COMMANDLINE_LIBRARY = READLINE
|
||||
|
||||
# remove warning in anyscalar.h
|
||||
ARCH_DEP_CXXFLAGS += -fno-strict-aliasing
|
||||
|
||||
@@ -1,3 +1 @@
|
||||
include $(CONFIG)/os/CONFIG.Common.linux-clang
|
||||
|
||||
COMMANDLINE_LIBRARY = READLINE
|
||||
|
||||
@@ -18,10 +18,8 @@ OBJ = .o
|
||||
LIB_PREFIX = lib
|
||||
LIB_SUFFIX = .a
|
||||
SHRLIB_SUFFIX_BASE = .so
|
||||
#SHRLIB_SUFFIX = $(SHRLIB_SUFFIX_BASE)$(addprefix .,$(SHRLIB_VERSION))
|
||||
SHRLIB_SUFFIX = $(SHRLIB_SUFFIX_BASE)
|
||||
#LOADABLE_SHRLIB_SUFFIX = $(SHRLIB_SUFFIX_BASE)$(addprefix .,$(LOADABLE_SHRLIB_VERSION))
|
||||
LOADABLE_SHRLIB_SUFFIX = $(SHRLIB_SUFFIX_BASE)
|
||||
SHRLIB_SUFFIX = $(SHRLIB_SUFFIX_BASE)$(addprefix .,$(SHRLIB_VERSION))
|
||||
LOADABLE_SHRLIB_SUFFIX = $(SHRLIB_SUFFIX_BASE)$(addprefix .,$(LOADABLE_SHRLIB_VERSION))
|
||||
LOADABLE_SHRLIB_PREFIX = lib
|
||||
|
||||
#-------------------------------------------------------
|
||||
|
||||
@@ -14,9 +14,9 @@ GNU_DIR=$(ELDK)/usr
|
||||
# This cross tool chain is installed in a somehow weired way
|
||||
# Without the following lines it does not work on RHEL7
|
||||
# but it worked on SL6
|
||||
ARCH_DEP_CXXFLAGS += -I $(ELDK)/$(GNU_TARGET)/usr/include/c++/4.2.2
|
||||
ARCH_DEP_CXXFLAGS += -I $(ELDK)/$(GNU_TARGET)/usr/include/c++/4.2.2/powerpc-linux
|
||||
ARCH_DEP_CXXFLAGS += -I $(ELDK)/$(GNU_TARGET)/usr/include/c++/4.2.2/backward
|
||||
ARCH_DEP_CXXFLAGS += -I $(ELDK)/$(GNU_TARGET)/usr/include/c++/4.2.2
|
||||
ARCH_DEP_CXXFLAGS += -I $(ELDK)/$(GNU_TARGET)/usr/include/c++/4.2.2/powerpc-linux
|
||||
ARCH_DEP_CXXFLAGS += -I $(ELDK)/$(GNU_TARGET)/usr/include/c++/4.2.2/backward
|
||||
|
||||
ARCH_DEP_LDFLAGS += -Wl,-rpath-link,$(ELDK)/$(GNU_TARGET)/lib
|
||||
ARCH_DEP_LDFLAGS += -Wl,-rpath-link,$(ELDK)/$(GNU_TARGET)/usr/lib
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
# Include definitions common to all Linux targets
|
||||
include $(CONFIG)/os/CONFIG.Common.linuxCommon
|
||||
|
||||
COMMANDLINE_LIBRARY = READLINE
|
||||
|
||||
ARCH_CLASS = ppc
|
||||
|
||||
SDK = eldk
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
# Include definitions common to all Linux targets
|
||||
include $(CONFIG)/os/CONFIG.Common.linuxCommon
|
||||
|
||||
COMMANDLINE_LIBRARY = READLINE
|
||||
|
||||
ARCH_CLASS = ppc
|
||||
|
||||
SDK = eldk
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
# Include definitions common to all Linux targets
|
||||
include $(CONFIG)/os/CONFIG.Common.linuxCommon
|
||||
|
||||
COMMANDLINE_LIBRARY = READLINE
|
||||
|
||||
ARCH_CLASS = ppc
|
||||
|
||||
SDK = eldk
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
# Include definitions common to all Linux targets
|
||||
include $(CONFIG)/os/CONFIG.Common.linuxCommon
|
||||
|
||||
COMMANDLINE_LIBRARY = READLINE
|
||||
|
||||
ARCH_CLASS = ppc
|
||||
|
||||
SDK = fslsdk
|
||||
|
||||
@@ -8,7 +8,7 @@ include $(CONFIG)/os/CONFIG.Common.linuxCommon
|
||||
|
||||
# Using readline:
|
||||
# Due to missing/messed up libs in the toolchain, readline needs copies of
|
||||
# libtinfo.so.5.9 and libreadline.so.6.2 from a Raspbian 7 rootfs
|
||||
# libtinfo.so.5.9 and libreadline.so.6.2 from a Raspbian 7 rootfs
|
||||
# /lib/arm-linux-gnueabihf/ to the toolchain, e.g.
|
||||
# $(SDK_DIR)/gcc-linaro-arm-linux-gnueabihf-raspbian/arm-linux-gnueabihf/libc/lib/arm-linux-gnueabihf/
|
||||
# and manually created links libtinfo.so.5 and libreadline.so.
|
||||
@@ -18,8 +18,6 @@ include $(CONFIG)/os/CONFIG.Common.linuxCommon
|
||||
# Also copy /usr/include/readline/ directory from some readline 6 installation
|
||||
# to $(SDK_DIR)/gcc-linaro-arm-linux-gnueabihf-raspbian/arm-linux-gnueabihf/libc/usr/include/
|
||||
|
||||
COMMANDLINE_LIBRARY = READLINE
|
||||
|
||||
ARCH_CLASS = arm
|
||||
|
||||
SDK_DIR = /opt/raspberrypi/arm-bcm2708
|
||||
|
||||
@@ -13,7 +13,7 @@ CMPLR_SUFFIX = ppc
|
||||
ARCH_CLASS = ppc
|
||||
|
||||
# Architecture specific build flags
|
||||
ARCH_DEP_CPPFLAGS = -DCPU=PPC603
|
||||
ARCH_DEP_CPPFLAGS = -DCPU=PPC603
|
||||
ARCH_DEP_CFLAGS = -mcpu=603 -mstrict-align
|
||||
|
||||
GNU_TARGET = powerpc-wrs-vxworks
|
||||
|
||||
@@ -63,7 +63,6 @@ VXWORKS_MAJOR_VERSION = $(basename $(basename $(VXWORKS_VERSION)))
|
||||
|
||||
# These are needed for vxWorks 6.x; the GNU toolset version number
|
||||
# is in the path to the compiler tools:
|
||||
VX_GNU_VERSION_5 = 2.96
|
||||
VX_GNU_VERSION_6.0 = 3.3.2
|
||||
VX_GNU_VERSION_6.1 = 3.3.2
|
||||
VX_GNU_VERSION_6.2 = 3.3.2
|
||||
@@ -74,17 +73,9 @@ VX_GNU_VERSION_6.6 = 4.1.2
|
||||
VX_GNU_VERSION_6.7 = 4.1.2
|
||||
VX_GNU_VERSION_6.8 = 4.1.2
|
||||
VX_GNU_VERSION_6.9 = 4.3.3
|
||||
VX_GNU_VERSION_6 = $(VX_GNU_VERSION_$(VXWORKS_VERSION))
|
||||
VX_GNU_VERSION = $(VX_GNU_VERSION_$(VXWORKS_MAJOR_VERSION))
|
||||
VX_GNU_VERSION = $(VX_GNU_VERSION_$(VXWORKS_VERSION))
|
||||
|
||||
VX_GNU_MAJOR_VERSION = $(basename $(basename $(VX_GNU_VERSION)))
|
||||
VX_GNU_MINOR_VERSION = $(basename $(patsubst $(VX_GNU_MAJOR_VERSION).%,%,$(VX_GNU_VERSION)))
|
||||
|
||||
# gcc version before 3.4 are "old" and need special treatment
|
||||
VX_OLD_GCC_2 = OLD
|
||||
VX_OLD_GCC_3.3 = OLD
|
||||
VX_OLD_GCC_3 = $(VX_OLD_GCC_3.$(VX_GNU_MINOR_VERSION))
|
||||
VX_OLD_GCC = $(VX_OLD_GCC_$(VX_GNU_MAJOR_VERSION))
|
||||
|
||||
#--------------------------------------------------
|
||||
# Fix old Linux WIND_HOST_TYPE
|
||||
@@ -94,21 +85,14 @@ endif
|
||||
|
||||
#--------------------------------------------------
|
||||
# vxWorks directory definitions
|
||||
VX_DIR_5 = $(WIND_BASE)
|
||||
VX_DIR_6 = $(WIND_BASE)/vxworks-$(VXWORKS_VERSION)
|
||||
VX_DIR = $(VX_DIR_$(VXWORKS_MAJOR_VERSION))
|
||||
VX_DIR = $(WIND_BASE)/vxworks-$(VXWORKS_VERSION)
|
||||
|
||||
VX_INCLUDE_DIRS_5 = $(VX_DIR)/target/h
|
||||
VX_INCLUDE_DIRS_6 = $(VX_DIR)/target/h $(VX_DIR)/target/h/wrn/coreip
|
||||
GNU_TARGET_INCLUDE_DIR = $(VX_INCLUDE_DIRS_$(VXWORKS_MAJOR_VERSION))
|
||||
TARGET_CPPFLAGS = -isystem $(VX_DIR)/target/h
|
||||
GNU_TARGET_INCLUDE_DIR = $(VX_DIR)/target/h $(VX_DIR)/target/h/wrn/coreip
|
||||
|
||||
#--------------------------------------------------
|
||||
# vxWorks GNU directories
|
||||
|
||||
GNU_DIR_5 = $(WIND_BASE)/host/$(WIND_HOST_TYPE)
|
||||
GNU_DIR_6 = $(WIND_BASE)/gnu/$(VX_GNU_VERSION)-vxworks-$(VXWORKS_VERSION)/$(WIND_HOST_TYPE)
|
||||
GNU_DIR = $(GNU_DIR_$(VXWORKS_MAJOR_VERSION))
|
||||
GNU_DIR = $(WIND_BASE)/gnu/$(VX_GNU_VERSION)-vxworks-$(VXWORKS_VERSION)/$(WIND_HOST_TYPE)
|
||||
|
||||
#--------------------------------------------------
|
||||
# This finds nm on any supported VxWorks version
|
||||
@@ -132,7 +116,7 @@ export TOOL_FAMILY = GNU
|
||||
#--------------------------------------------------
|
||||
# Operating system flags
|
||||
OP_SYS_CPPFLAGS += -DvxWorks=vxWorks
|
||||
OP_SYS_CFLAGS += -fno-builtin -fno-strict-aliasing
|
||||
OP_SYS_CFLAGS += -fno-builtin
|
||||
|
||||
# Fix for vxWorks headers that use macros defined in vxWorks.h but
|
||||
# which don't actually include vxWorks.h themselves, for example the
|
||||
@@ -149,23 +133,12 @@ OPT_CXXFLAGS_YES = -O2
|
||||
# code flags
|
||||
CODE_CFLAGS =
|
||||
#
|
||||
# For gcc versions before 3.4 we need this g++ compiler flag
|
||||
# However WindRiver says gcc 3.3 does not need it any more
|
||||
# which would allow to build vxWorks 6 without this flag.
|
||||
# Maybe we can live without it at the penalty of larger code.
|
||||
# See vxWorks 5 docs/gnu2.96+ppc/gcc.html
|
||||
# chapter 4.5 "Where's the Template?"
|
||||
CODE_CXXFLAGS_OLD = -fno-implicit-templates
|
||||
CODE_CXXFLAGS = $(CODE_CXXFLAGS_$(VX_OLD_GCC))
|
||||
|
||||
#--------------------------------------------------
|
||||
# Modules we cannot build with old compiler
|
||||
|
||||
PV_MODULES = pv% normativeTypes
|
||||
SKIP_BUILDS_5 = $(PV_MODULES)
|
||||
SKIP_BUILDS_OLD = $(PV_MODULES)
|
||||
SKIP_BUILDS_6 = $(SKIP_BUILDS_$(VX_OLD_GCC))
|
||||
SKIP_BUILDS = $(SKIP_BUILDS_$(VXWORKS_MAJOR_VERSION))
|
||||
# For vxWorks versions before 6.3 we need this g++ compiler flag
|
||||
CODE_CXXFLAGS_6.0 = -fno-implicit-templates
|
||||
CODE_CXXFLAGS_6.1 = -fno-implicit-templates
|
||||
CODE_CXXFLAGS_6.2 = -fno-implicit-templates
|
||||
CODE_CXXFLAGS_6 = $(CODE_CXXFLAGS_$(VXWORKS_VERSION))
|
||||
CODE_CXXFLAGS = $(CODE_CXXFLAGS_$(VXWORKS_MAJOR_VERSION))
|
||||
|
||||
#--------------------------------------------------
|
||||
# no shared libs for vxWorks
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
# Include definitions common to all Linux targets
|
||||
include $(CONFIG)/os/CONFIG.Common.linuxCommon
|
||||
|
||||
COMMANDLINE_LIBRARY = READLINE
|
||||
|
||||
ARCH_CLASS = arm64
|
||||
|
||||
SDK = petalinux
|
||||
|
||||
@@ -12,5 +12,5 @@ CC = $(GNU_BIN)/$(CMPLR_PREFIX)gcc44
|
||||
CCC = $(GNU_BIN)/$(CMPLR_PREFIX)g++44
|
||||
|
||||
TARGET_CPPFLAGS = -isystem /usr/lib/x86_64-redhat-linux6E/include
|
||||
TARGET_LDFLAGS = -L /usr/lib/x86_64-redhat-linux6E/lib
|
||||
TARGET_LDFLAGS = -L /usr/lib/x86_64-redhat-linux6E/lib
|
||||
LINK.cpp += --as-needed -lc -lm -lrt -lpthread -lreadline -ltinfo
|
||||
|
||||
2
configure/os/CONFIG_SITE.Common.UnixCommon
Normal file
2
configure/os/CONFIG_SITE.Common.UnixCommon
Normal file
@@ -0,0 +1,2 @@
|
||||
SHRLIB_SUFFIX = $(SHRLIB_SUFFIX_BASE)
|
||||
LOADABLE_SHRLIB_SUFFIX = $(SHRLIB_SUFFIX_BASE)
|
||||
1
configure/os/CONFIG_SITE.Common.linuxCommon
Normal file
1
configure/os/CONFIG_SITE.Common.linuxCommon
Normal file
@@ -0,0 +1 @@
|
||||
COMMANDLINE_LIBRARY = READLINE
|
||||
@@ -2,25 +2,58 @@
|
||||
#
|
||||
# Site specific definitions for vxWorks target builds.
|
||||
|
||||
# Compiler options can vary with the vxWorks version number, so we
|
||||
# need to know that. Do not include any third-level digits.
|
||||
#### Fixes for CONFIG.Common.vxWorksCommon #######
|
||||
|
||||
# Note: vxWorks 5.4.x and 5.5.x (Tornado 2.x) are not supported.
|
||||
# VxWorks 6.0 through 6.5 use older, untested versions of GCC.
|
||||
# These are needed for vxWorks 6.x; the GNU toolset version number
|
||||
# is in the path to the compiler tools:
|
||||
VX_GNU_VERSION_5 = 2.96
|
||||
VX_GNU_VERSION_6 = $(VX_GNU_VERSION_$(VXWORKS_VERSION))
|
||||
VX_GNU_VERSION = $(VX_GNU_VERSION_$(VXWORKS_MAJOR_VERSION))
|
||||
VX_GNU_MINOR_VERSION = $(basename $(patsubst $(VX_GNU_MAJOR_VERSION).%,%,$(VX_GNU_VERSION)))
|
||||
|
||||
#VXWORKS_VERSION = 6.6
|
||||
#VXWORKS_VERSION = 6.7
|
||||
#VXWORKS_VERSION = 6.8
|
||||
VXWORKS_VERSION = 6.9
|
||||
# gcc version before 3.4 are "old" and need special treatment
|
||||
VX_OLD_GCC_2 = OLD
|
||||
VX_OLD_GCC_3.3 = OLD
|
||||
VX_OLD_GCC_3 = $(VX_OLD_GCC_3.$(VX_GNU_MINOR_VERSION))
|
||||
VX_OLD_GCC = $(VX_OLD_GCC_$(VX_GNU_MAJOR_VERSION))
|
||||
|
||||
# vxWorks directory definitions
|
||||
VX_DIR_5 = $(WIND_BASE)
|
||||
VX_DIR_6 = $(WIND_BASE)/vxworks-$(VXWORKS_VERSION)
|
||||
VX_DIR = $(VX_DIR_$(VXWORKS_MAJOR_VERSION))
|
||||
|
||||
# Sites may override the following path for a particular host
|
||||
# architecture by adding it to an appropriate
|
||||
# CONFIG_SITE.$(EPICS_HOST_ARCH).vxWorksCommon file.
|
||||
VX_INCLUDE_DIRS_5 = $(VX_DIR)/target/h
|
||||
VX_INCLUDE_DIRS_6 = $(VX_DIR)/target/h $(VX_DIR)/target/h/wrn/coreip
|
||||
GNU_TARGET_INCLUDE_DIR = $(VX_INCLUDE_DIRS_$(VXWORKS_MAJOR_VERSION))
|
||||
TARGET_CPPFLAGS = -isystem $(VX_DIR)/target/h
|
||||
|
||||
# vxWorks GNU directories
|
||||
|
||||
GNU_DIR_5 = $(WIND_BASE)/host/$(WIND_HOST_TYPE)
|
||||
GNU_DIR_6 = $(WIND_BASE)/gnu/$(VX_GNU_VERSION)-vxworks-$(VXWORKS_VERSION)/$(WIND_HOST_TYPE)
|
||||
GNU_DIR = $(GNU_DIR_$(VXWORKS_MAJOR_VERSION))
|
||||
|
||||
# Operating system flags
|
||||
OP_SYS_CFLAGS += -fno-strict-aliasing
|
||||
|
||||
# For gcc versions before 3.4 we need this g++ compiler flag
|
||||
# However WindRiver says gcc 3.3 does not need it any more
|
||||
# which would allow to build vxWorks 6 without this flag.
|
||||
# Maybe we can live without it at the penalty of larger code.
|
||||
# See vxWorks 5 docs/gnu2.96+ppc/gcc.html
|
||||
# chapter 4.5 "Where's the Template?"
|
||||
CODE_CXXFLAGS_OLD = -fno-implicit-templates
|
||||
CODE_CXXFLAGS = $(CODE_CXXFLAGS_$(VX_OLD_GCC))
|
||||
|
||||
# WIND_BASE is where you installed the Wind River software.
|
||||
|
||||
#WIND_BASE = /usr/local/vw/tornado22-$(ARCH_CLASS)
|
||||
#WIND_BASE = /usr/local/vw/vxWorks-$(VXWORKS_VERSION)
|
||||
#WIND_BASE = /ade/vxWorks/$(VXWORKS_VERSION)
|
||||
WIND_BASE = /afs/psi.ch/project/vxworks/VxWorks$(VXWORKS_VERSION)
|
||||
|
||||
#--------------------------------------------------
|
||||
# Modules we cannot build with old compiler
|
||||
|
||||
PV_MODULES = pv% normativeTypes
|
||||
SKIP_BUILDS_5 = $(PV_MODULES)
|
||||
SKIP_BUILDS_OLD = $(PV_MODULES)
|
||||
SKIP_BUILDS_6 = $(SKIP_BUILDS_$(VX_OLD_GCC))
|
||||
SKIP_BUILDS = $(SKIP_BUILDS_$(VXWORKS_MAJOR_VERSION))
|
||||
|
||||
|
||||
@@ -4,17 +4,17 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
||||
<title>Known Problems in EPICS 7.0.2</title>
|
||||
<title>Known Problems in EPICS 7.0.3</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1 style="text-align: center">EPICS 7.0.2: Known Problems</h1>
|
||||
<h1 style="text-align: center">EPICS 7.0.3: Known Problems</h1>
|
||||
|
||||
<p>Any patch files linked below should be applied at the root of the
|
||||
base-7.0.2 tree. Download them, then use the GNU Patch program as
|
||||
base-7.0.3 tree. Download them, then use the GNU Patch program as
|
||||
follows:</p>
|
||||
|
||||
<blockquote><pre>% <b>cd <i>/path/to/</i>base-7.0.2</b>
|
||||
<blockquote><pre>% <b>cd <i>/path/to/</i>base-7.0.3</b>
|
||||
% <b>patch -p1 < <i>/path/to/</i>file.patch</b></pre></blockquote>
|
||||
|
||||
<p>The following problems were known by the developers at the time of this
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
Installation Instructions
|
||||
|
||||
EPICS Base Release 7.0.2
|
||||
EPICS Base Release 7.0.3
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
Table of Contents
|
||||
|
||||
* What is EPICS base?
|
||||
* What is new in this release?
|
||||
* Copyright
|
||||
* Supported platforms
|
||||
* Supported compilers
|
||||
* Software requirements
|
||||
* Host system storage requirements
|
||||
* Documentation
|
||||
* Directory Structure
|
||||
* Build related components
|
||||
* Building EPICS base (Unix and Win32)
|
||||
* Example application and extension
|
||||
* Multiple host platforms
|
||||
* What is EPICS base?
|
||||
* What is new in this release?
|
||||
* Copyright
|
||||
* Supported platforms
|
||||
* Supported compilers
|
||||
* Software requirements
|
||||
* Host system storage requirements
|
||||
* Documentation
|
||||
* Directory Structure
|
||||
* Build related components
|
||||
* Building EPICS base (Unix and Win32)
|
||||
* Example application and extension
|
||||
* Multiple host platforms
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<BODY>
|
||||
<CENTER>
|
||||
<H1>Installation Instructions</H1>
|
||||
<H2>EPICS Base Release 7.0.2</H2><BR>
|
||||
<H2>EPICS Base Release 7.0.3</H2><BR>
|
||||
</CENTER>
|
||||
<HR>
|
||||
<H3> Table of Contents</H3>
|
||||
|
||||
@@ -20,7 +20,7 @@ release.</p>
|
||||
which should also be read to understand what has changed since an earlier
|
||||
release.</p>
|
||||
|
||||
<h1 align="center">EPICS Release 7.0.2.2</h1>
|
||||
<h1 align="center">EPICS Release 7.0.3</h1>
|
||||
|
||||
<!-- Insert new items immediately below this template ...
|
||||
|
||||
@@ -30,6 +30,66 @@ release.</p>
|
||||
|
||||
-->
|
||||
|
||||
<h3>epicsTimeGetCurrent() optimization</h3>
|
||||
|
||||
<p>Add a fast path to epicsTimeGetCurrent() and related calls
|
||||
in the common case where only the default OS current time provider is
|
||||
registered. This path does not take the global mutex guarding
|
||||
the time providers list, potentially reducing lock contention.</p>
|
||||
|
||||
<h3>dbEvent tweak Queue size</h3>
|
||||
|
||||
<p>The size of the queue used by dbEvent to push monitor updates
|
||||
has been slightly increased based on DBR_TIME_DOUBLE to better fill
|
||||
an ethernet frame. This may result in slightly fewer, but larger
|
||||
frames being sent.</p>
|
||||
|
||||
<h3>mbbo/mbbiDirect number of bits as precision</h3>
|
||||
|
||||
<p>Report NOBT as "precision" through the dbAccess API.
|
||||
This is not accessible through CA, but is planned to be used through
|
||||
QSRV.</p>
|
||||
|
||||
<h1 align="center">EPICS Release 7.0.2.2</h1>
|
||||
|
||||
<h3>Build System changes</h3>
|
||||
|
||||
<ul>
|
||||
|
||||
<li>The GNUmake build targets <tt>cvsclean</tt> and <tt>depclean</tt> are now
|
||||
available from any directory; previously they were only available from
|
||||
application top directories.</li>
|
||||
|
||||
<li>The approach that EPICS Base uses for building submodules inside the parent
|
||||
module looks useful for support modules too. The rules for building submodules
|
||||
have been modified and extracted into a new <tt>RULES_MODULES</tt> file, so a
|
||||
support module will be able to use them too without having to copy them into its
|
||||
own <tt>modules/Makefile</tt>. There are some specific requirements that support
|
||||
modules and their submodules must follow, which are described as comments in the
|
||||
new <tt>base/configure/RULES_MODULES</tt> file itself.</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<h3>EPICS_BASE_VERSION Update Policy change</h3>
|
||||
|
||||
<p>In the past, a build of EPICS using sources checked out from the repository
|
||||
branch between official releases would have shown the version number of the
|
||||
previous release, followed by a <q>-DEV</q> suffix, for example
|
||||
<q>7.0.2.1-DEV</q>.</p>
|
||||
|
||||
<p>The policy that controls when the number gets updated has been changed, and
|
||||
now immediately after a release has been tagged the version number will be
|
||||
updated to the next patch release version, plus the <q>-DEV</q> suffix as
|
||||
before. Thus following <q>7.0.2.2</q> the version number will show as
|
||||
<q>7.0.2.3-DEV</q>. This does not require the next official release to be
|
||||
numbered <q>7.0.2.3</q> though, it could become <q>7.0.3</q> or even
|
||||
<q>7.1.0</q> if the changes incorporated into it are more substantial than bug
|
||||
fixes.</p>
|
||||
|
||||
<h3>Drop CLOCK_MONOTONIC_RAW from posix/osdMonotonic.c</h3>
|
||||
|
||||
<p>Turns out this is ~10x slower to query than CLOCK_MONOTONIC.</p>
|
||||
|
||||
|
||||
<h1 align="center">EPICS Release 7.0.2.1</h1>
|
||||
|
||||
@@ -977,6 +1037,15 @@ of its CALLBACK objects.</p>
|
||||
|
||||
<!-- Insert inherited items immediately below here ... -->
|
||||
|
||||
<h3>Cleaning up with Multiple CA contexts in a Process</h3>
|
||||
|
||||
<p>Bruno Martins reported a problem with the CA client library at shutdown in a
|
||||
process that uses multiple CA client contexts. The first context that triggers
|
||||
the CA client exit handler prevents any others from being able to clean up
|
||||
because it resets the ID of an internal epicsThreadPrivate variable which is
|
||||
shared by all clients. This action has been removed from the client library,
|
||||
which makes cleanup of clients like this possible.</p>
|
||||
|
||||
<h3>Perl CA bindings fixed for macOS Mojave</h3>
|
||||
|
||||
<p>Apple removed some Perl header files from macOS Mojave that were available
|
||||
|
||||
@@ -53,9 +53,10 @@ made.</p>
|
||||
|
||||
<h4>Short Process for Patch Releases</h4>
|
||||
|
||||
<p>The Patch Release date and its scope are agreed upon about four weeks
|
||||
ahead of time. If no blocking issues are raised, the release is made by the
|
||||
release manager.</p>
|
||||
<p>The Patch Release date and its scope are agreed upon a few weeks ahead of the
|
||||
release. If no blocking issues are raised, the release is made by the Release
|
||||
Manager on or as soon as possible after that date, following the steps below
|
||||
starting at <a href="#ReleaseApproval">Release Approval</a>.</p>
|
||||
|
||||
<h3>Roles</h3>
|
||||
|
||||
@@ -72,6 +73,7 @@ release manager.</p>
|
||||
<dd>Responsible for the EPICS website</dd>
|
||||
</dl>
|
||||
|
||||
<form>
|
||||
<table border="1" width="100%">
|
||||
<tbody>
|
||||
<tr>
|
||||
@@ -124,80 +126,81 @@ release manager.</p>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td>Website Manager</td>
|
||||
<td>Create a release milestone on Launchpad if necessary and set the
|
||||
expected release date. Note that pre-release and release-candidate
|
||||
versions do not appear on Launchpad, only the final release.</td>
|
||||
<td>Create a release milestone on Launchpad. If a target release date is
|
||||
known set "Date Targeted" to the expected release date. Note that
|
||||
pre-release and release-candidate versions should not get Launchpad
|
||||
milestones, only the final release.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th colspan="3">Creating pre-release and release-candidate versions</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td><input type="checkbox"></td>
|
||||
<td>Release Manager</td>
|
||||
<!-- Submodules... -->
|
||||
<td>Edit and commit changes to the EPICS version number file
|
||||
configure/CONFIG_BASE_VERSION.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td><input type="checkbox"></td>
|
||||
<td>Release Manager</td>
|
||||
<td>Tag the module in Git, using these tag conventions:
|
||||
<ul>
|
||||
<li>
|
||||
<tt>R7.0.2-pre<i>n</i></tt>
|
||||
<tt>R7.0.3-pre<i>n</i></tt>
|
||||
— pre-release tag
|
||||
</li>
|
||||
<li>
|
||||
<tt>R7.0.2-rc<i>n</i></tt>
|
||||
<tt>R7.0.3-rc<i>n</i></tt>
|
||||
— release candidate tag
|
||||
</li>
|
||||
</ul>
|
||||
<blockquote><tt>
|
||||
cd base-7.0<br />
|
||||
git tag -m 'ANJ: Tagged for 7.0.2-rc1' R7.0.2-rc1
|
||||
git tag -m 'ANJ: Tagged for 7.0.3-rc1' R7.0.3-rc1
|
||||
</tt></blockquote>
|
||||
Note that submodules must <em>not</em> be tagged with the version used
|
||||
for the top-level, they each have their own separate version numbers
|
||||
that are only tagged at the final release.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td><input type="checkbox"></td>
|
||||
<td>Release Manager</td>
|
||||
<td>Export the tagged version into a tarfile. The <tt>make-tar.sh</tt>
|
||||
script generates a gzipped tarfile directly from the tag, excluding the
|
||||
files and directories that are only used for continuous integration:
|
||||
<blockquote><tt>
|
||||
cd base-7.0<br />
|
||||
./.tools/make-tar.sh R7.0.2-rc1 base-7.0.2-rc1.tar.gz base-7.0.2-rc1/
|
||||
./.tools/make-tar.sh R7.0.3-rc1 base-7.0.3-rc1.tar.gz base-7.0.3-rc1/
|
||||
</tt></blockquote>
|
||||
Create a GPG signature file of the tarfile as follows:
|
||||
<blockquote><tt>
|
||||
gpg --armor --sign --detach-sig base-7.0.2-rc1.tar.gz
|
||||
gpg --armor --sign --detach-sig base-7.0.3-rc1.tar.gz
|
||||
</tt></blockquote>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td><input type="checkbox"></td>
|
||||
<td>Release Manager</td>
|
||||
<td>Test the tarfile by extracting its contents and building it on at
|
||||
least one supported platform.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td><input type="checkbox"></td>
|
||||
<td>Website Manager</td>
|
||||
<td>Copy the tarfile and its signature to the Base download area of the
|
||||
website and add the new files to the website Base download index
|
||||
page.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td><input type="checkbox"></td>
|
||||
<td>Website Manager</td>
|
||||
<td>Create or update a website subdirectory to hold the release
|
||||
documentation, and copy in selected files from the base/documentation
|
||||
and base/html directories of the tarfile.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td><input type="checkbox"></td>
|
||||
<td>Website Manager</td>
|
||||
<td>Create or modify the webpage for the new release with links to the
|
||||
release documents and tar file. Pre-release and release-candidate
|
||||
@@ -257,10 +260,11 @@ release manager.</p>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th colspan="3">Release Approval</th>
|
||||
<th colspan="3" id="ReleaseApproval">
|
||||
Release Approval</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td><input type="checkbox"></td>
|
||||
<td>Release Manager</td>
|
||||
<td>Obtain a positive <q>Ok to release</q> from all platform developers
|
||||
once a release candidate version has gone for 2 weeks without any major
|
||||
@@ -270,7 +274,7 @@ release manager.</p>
|
||||
<th colspan="3">Creating the final release version</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td><input type="checkbox"></td>
|
||||
<td>Release Manager</td>
|
||||
<td>
|
||||
<p>For each external submodule, check if the module's release version
|
||||
@@ -282,7 +286,7 @@ release manager.</p>
|
||||
commit.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td><input type="checkbox"></td>
|
||||
<td>Release Manager</td>
|
||||
<td>Edit and commit changes to the EPICS Base version number file and
|
||||
the embedded module version files:
|
||||
@@ -294,33 +298,33 @@ release manager.</p>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td><input type="checkbox"></td>
|
||||
<td>Release Manager</td>
|
||||
<td>Tag the epics-base module in Git:
|
||||
<blockquote><tt>
|
||||
cd base-7.0<br />
|
||||
git tag -m 'ANJ: Tagged for 7.0.2' R7.0.2</i>
|
||||
git tag -m 'ANJ: Tagged for 7.0.3' R7.0.3</i>
|
||||
</tt></blockquote>
|
||||
Don't push the new tag to the Launchpad repository yet.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td><input type="checkbox"></td>
|
||||
<td>Release Manager</td>
|
||||
<td>Export the tagged version into a tarfile. The <tt>make-tar.sh</tt>
|
||||
script generates a gzipped tarfile directly from the tag, excluding the
|
||||
files and directories that are only used for continuous integration:
|
||||
<blockquote><tt>
|
||||
cd base-7.0<br />
|
||||
./.tools/make-tar.sh R7.0.2 base-7.0.2.tar.gz base-7.0.2/
|
||||
./.tools/make-tar.sh R7.0.3 base-7.0.3.tar.gz base-7.0.3/
|
||||
</tt></blockquote>
|
||||
Create a GPG signature file of the tarfile as follows:
|
||||
<blockquote><tt>
|
||||
gpg --armor --sign --detach-sig base-7.0.2.tar.gz
|
||||
gpg --armor --sign --detach-sig base-7.0.3.tar.gz
|
||||
</tt></blockquote>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td><input type="checkbox"></td>
|
||||
<td>Release Manager</td>
|
||||
<td>Test the tar file by extracting its contents and building it on at
|
||||
least one supported platform. When this succeeds the new git tag can be
|
||||
@@ -331,7 +335,7 @@ release manager.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td><input type="checkbox"></td>
|
||||
<td>Release Manager</td>
|
||||
<td>Edit and commit changes to the EPICS Base version number file and
|
||||
the embedded module version files:
|
||||
@@ -345,64 +349,95 @@ release manager.</p>
|
||||
with a "-DEV" tag added (where applicable).
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> </td>
|
||||
<th colspan="3">Publish to epics.anl.gov</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input type="checkbox"></td>
|
||||
<td>Release Manager</td>
|
||||
<td>Copy the tarfile and its signature to the Base download area of the
|
||||
website.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td>Release Manager</td>
|
||||
<td>Find all Launchpad bug reports with the status Fix Committed which
|
||||
have been fixed in this release and mark them Fix Released.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th colspan="3">Publish and Announce it</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td>Website Manager</td>
|
||||
<td>Upload the tar file and its <tt>.asc</tt> signature file to the
|
||||
Launchpad milestone for this release version.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td><input type="checkbox"></td>
|
||||
<td>Website Manager</td>
|
||||
<td>Update the website subdirectory that holds the release
|
||||
documentation, and copy in the files from the base/documentation
|
||||
directory of the tarfile.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td><input type="checkbox"></td>
|
||||
<td>Website Manager</td>
|
||||
<td>Update the webpage for the new release with links to the release
|
||||
documents and tar file.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td><input type="checkbox"></td>
|
||||
<td>Website Manager</td>
|
||||
<td>Add the new release tar file to the website Base download index
|
||||
page.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td><input type="checkbox"></td>
|
||||
<td>Website Manager</td>
|
||||
<td>Link to the release webpage from other relevent areas of the
|
||||
website - update front page and sidebars.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td><input type="checkbox"></td>
|
||||
<td>Website Manager</td>
|
||||
<td>Add an entry to the website News page, linking to the new version
|
||||
webpage.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> </td>
|
||||
<th colspan="3">Publish to epics-controls</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input type="checkbox"></td>
|
||||
<td>Website Manager</td>
|
||||
<td>Upload the tar file and its <tt>.asc</tt> signature file to the
|
||||
epics-controls web-server [ToDo: ssh-key, location]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input type="checkbox"></td>
|
||||
<td>Website Manager</td>
|
||||
<td>Follow instructions on
|
||||
<a href="https://epics-controls.org/resources-and-support/documents/epics-website-documentation/adding-a-page-for-a-new-release/">
|
||||
Add a page for a new release</a> to create a new release webpage (not
|
||||
required for a patch release though, just edit the existing page).</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th colspan="3">Publish to Launchpad</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input type="checkbox"></td>
|
||||
<td>Website Manager</td>
|
||||
<td>Go to the Launchpad milestone for this release. Click the Create
|
||||
release button and add the release date. Put a URL for the release page
|
||||
in the Release notes box, and click the Create release button. Upload
|
||||
the tar file and its <tt>.asc</tt> signature file to the new Launchpad
|
||||
release page.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input type="checkbox"></td>
|
||||
<td>Release Manager</td>
|
||||
<td>Find all Launchpad bug reports with the status Fix Committed which
|
||||
have been fixed in this release and mark them Fix Released.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th colspan="3">Make Announcement</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input type="checkbox"></td>
|
||||
<td>Release Manager</td>
|
||||
<td>Announce the release on the tech-talk mailing list.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -3,8 +3,11 @@
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
|
||||
# When building submodules, this should always be true:
|
||||
INSTALL_LOCATION = $(EPICS_BASE)
|
||||
# The name our submodules know us by:
|
||||
PARENT_MODULE = EPICS_BASE
|
||||
|
||||
# Stop submodules from installing their configuration files:
|
||||
# When building submodules, this should always be true:
|
||||
INSTALL_LOCATION := $($(PARENT_MODULE))
|
||||
|
||||
# Stop submodules installing their configure/ files into our area
|
||||
CONFIG_INSTALLS =
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
TOP = ..
|
||||
include $(TOP)/configure/CONFIG
|
||||
include CONFIG_SITE.local
|
||||
|
||||
# Submodules for bundle build
|
||||
SUBMODULES += libcom
|
||||
@@ -42,20 +43,4 @@ pcas_DEPEND_DIRS = ca
|
||||
# Allow sites to add extra submodules
|
||||
-include Makefile.local
|
||||
|
||||
# Add only checked-out submodules to DIRS
|
||||
DIRS += $(subst /Makefile,,$(wildcard $(addsuffix /Makefile, $(SUBMODULES))))
|
||||
|
||||
include $(TOP)/configure/RULES_DIRS
|
||||
|
||||
INSTALL_LOCATION_ABS := $(abspath $(INSTALL_LOCATION))
|
||||
RELEASE_LOCAL := RELEASE.$(EPICS_HOST_ARCH).local
|
||||
|
||||
# Ensure that RELEASE.<host>.local exists before doing anything else
|
||||
all host $(DIRS) $(ARCHS) $(ACTIONS) $(dirActionTargets) $(dirArchTargets) \
|
||||
$(dirActionArchTargets) $(actionArchTargets): | $(RELEASE_LOCAL)
|
||||
|
||||
$(RELEASE_LOCAL):
|
||||
$(ECHO) Creating $@, EPICS_BASE = $(INSTALL_LOCATION_ABS)
|
||||
@echo EPICS_BASE = $(INSTALL_LOCATION_ABS)> $@
|
||||
realclean:
|
||||
$(RM) $(wildcard RELEASE.*.local)
|
||||
include $(TOP)/configure/RULES_MODULES
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
EPICS_CA_MAJOR_VERSION = 4
|
||||
EPICS_CA_MINOR_VERSION = 13
|
||||
EPICS_CA_MAINTENANCE_VERSION = 3
|
||||
EPICS_CA_MAINTENANCE_VERSION = 4
|
||||
EPICS_CA_DEVELOPMENT_FLAG = 0
|
||||
|
||||
@@ -3143,7 +3143,8 @@ indicating the current state of the channel.</p>
|
||||
<dl>
|
||||
<dt><code>COUNT</code></dt>
|
||||
<dd>The element count to be read from the specified channel. A count of
|
||||
zero means use the current element count from the server.</dd>
|
||||
zero means use the current element count from the server, effectively
|
||||
resulting in a variable size array subscription.</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt><code>CHID</code></dt>
|
||||
|
||||
@@ -45,20 +45,12 @@ static epicsThreadOnceId cacOnce = EPICS_THREAD_ONCE_INIT;
|
||||
|
||||
const unsigned ca_client_context :: flushBlockThreshold = 0x58000;
|
||||
|
||||
extern "C" void cacExitHandler ( void *)
|
||||
{
|
||||
epicsThreadPrivateDelete ( caClientCallbackThreadId );
|
||||
caClientCallbackThreadId = 0;
|
||||
delete ca_client_context::pDefaultServiceInstallMutex;
|
||||
}
|
||||
|
||||
// runs once only for each process
|
||||
extern "C" void cacOnceFunc ( void * )
|
||||
{
|
||||
caClientCallbackThreadId = epicsThreadPrivateCreate ();
|
||||
assert ( caClientCallbackThreadId );
|
||||
ca_client_context::pDefaultServiceInstallMutex = newEpicsMutex;
|
||||
epicsAtExit ( cacExitHandler,0 );
|
||||
}
|
||||
|
||||
extern epicsThreadPrivateId caClientContextId;
|
||||
@@ -67,6 +59,8 @@ cacService * ca_client_context::pDefaultService = 0;
|
||||
epicsMutex * ca_client_context::pDefaultServiceInstallMutex;
|
||||
|
||||
ca_client_context::ca_client_context ( bool enablePreemptiveCallback ) :
|
||||
mutex(__FILE__, __LINE__),
|
||||
cbMutex(__FILE__, __LINE__),
|
||||
createdByThread ( epicsThreadGetIdSelf () ),
|
||||
ca_exception_func ( 0 ), ca_exception_arg ( 0 ),
|
||||
pVPrintfFunc ( errlogVprintf ), fdRegFunc ( 0 ), fdRegArg ( 0 ),
|
||||
|
||||
@@ -289,7 +289,6 @@ private:
|
||||
};
|
||||
|
||||
extern "C" void cacOnceFunc ( void * );
|
||||
extern "C" void cacExitHandler ( void *);
|
||||
|
||||
struct ca_client_context : public cacContextNotify
|
||||
{
|
||||
@@ -429,7 +428,6 @@ private:
|
||||
ca_client_context & operator = ( const ca_client_context & );
|
||||
|
||||
friend void cacOnceFunc ( void * );
|
||||
friend void cacExitHandler ( void *);
|
||||
static cacService * pDefaultService;
|
||||
static epicsMutex * pDefaultServiceInstallMutex;
|
||||
static const unsigned flushBlockThreshold;
|
||||
|
||||
@@ -37,6 +37,7 @@ repeaterSubscribeTimer::repeaterSubscribeTimer (
|
||||
epicsMutex & cbMutexIn, cacContextNotify & ctxNotifyIn ) :
|
||||
timer ( queueIn.createTimer () ), iiu ( iiuIn ),
|
||||
cbMutex ( cbMutexIn ),ctxNotify ( ctxNotifyIn ),
|
||||
stateMutex(__FILE__, __LINE__),
|
||||
attempts ( 0 ), registered ( false ), once ( false )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
EPICS_DATABASE_MAJOR_VERSION = 3
|
||||
EPICS_DATABASE_MINOR_VERSION = 17
|
||||
EPICS_DATABASE_MAINTENANCE_VERSION = 3
|
||||
EPICS_DATABASE_MAINTENANCE_VERSION = 4
|
||||
EPICS_DATABASE_DEVELOPMENT_FLAG = 0
|
||||
|
||||
@@ -240,6 +240,10 @@ int astac(const char *pname,const char *user,const char *location)
|
||||
char *puser;
|
||||
char *plocation;
|
||||
|
||||
if (!pname || !user || !location){
|
||||
printf("Usage: astac \"record name\", \"user\", \"host\"\n");
|
||||
return(1);
|
||||
}
|
||||
paddr = dbCalloc(1,sizeof(DBADDR) + sizeof(ASCLIENTPVT));
|
||||
pasclientpvt = (ASCLIENTPVT *)(paddr + 1);
|
||||
status=dbNameToAddr(pname,paddr);
|
||||
|
||||
@@ -55,7 +55,7 @@ typedef struct cbQueueSet {
|
||||
epicsRingPointerId queue;
|
||||
int queueOverflow;
|
||||
int queueOverflows;
|
||||
int shutdown;
|
||||
int shutdown; // use atomic
|
||||
int threadsConfigured;
|
||||
int threadsRunning;
|
||||
} cbQueueSet;
|
||||
@@ -71,12 +71,15 @@ epicsExportAddress(int,callbackParallelThreadsDefault);
|
||||
/* Timer for Delayed Requests */
|
||||
static epicsTimerQueueId timerQueue;
|
||||
|
||||
/* Shutdown handling */
|
||||
enum ctl {ctlInit, ctlRun, ctlPause, ctlExit};
|
||||
static volatile enum ctl cbCtl;
|
||||
static epicsEventId startStopEvent;
|
||||
enum cbState_t {
|
||||
cbInit, /* before callbackInit() and after callbackCleanup() */
|
||||
cbRun, /* after callbackInit() and before callbackStop() */
|
||||
cbStop, /* after callbackStop() and before callbackCleanup() */
|
||||
};
|
||||
|
||||
static int callbackIsInit;
|
||||
static int cbState; // holdscbState_t, use atomic ops
|
||||
|
||||
static epicsEventId startStopEvent;
|
||||
|
||||
/* Static data */
|
||||
static char *threadNamePrefix[NUM_CALLBACK_PRIORITIES] = {
|
||||
@@ -96,7 +99,7 @@ static int priorityValue[NUM_CALLBACK_PRIORITIES] = {0, 1, 2};
|
||||
|
||||
int callbackSetQueueSize(int size)
|
||||
{
|
||||
if (callbackIsInit) {
|
||||
if (epicsAtomicGetIntT(&cbState)!=cbInit) {
|
||||
fprintf(stderr, "Callback system already initialized\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -107,7 +110,7 @@ int callbackSetQueueSize(int size)
|
||||
int callbackQueueStatus(const int reset, callbackQueueStats *result)
|
||||
{
|
||||
int ret;
|
||||
if (!callbackIsInit) return -1;
|
||||
if (epicsAtomicGetIntT(&cbState)==cbInit) return -1;
|
||||
if (result) {
|
||||
int prio;
|
||||
result->size = callbackQueueSize;
|
||||
@@ -151,7 +154,7 @@ void callbackQueueShow(const int reset)
|
||||
|
||||
int callbackParallelThreads(int count, const char *prio)
|
||||
{
|
||||
if (callbackIsInit) {
|
||||
if (epicsAtomicGetIntT(&cbState)!=cbInit) {
|
||||
fprintf(stderr, "Callback system already initialized\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -207,7 +210,7 @@ static void callbackTask(void *arg)
|
||||
taskwdInsert(0, NULL, NULL);
|
||||
epicsEventSignal(startStopEvent);
|
||||
|
||||
while(!mySet->shutdown) {
|
||||
while(!epicsAtomicGetIntT(&mySet->shutdown)) {
|
||||
void *ptr;
|
||||
if (epicsRingPointerIsEmpty(mySet->queue))
|
||||
epicsEventMustWait(mySet->semWakeUp);
|
||||
@@ -230,11 +233,10 @@ void callbackStop(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (cbCtl == ctlExit) return;
|
||||
cbCtl = ctlExit;
|
||||
if (epicsAtomicCmpAndSwapIntT(&cbState, cbRun, cbStop)!=cbRun) return;
|
||||
|
||||
for (i = 0; i < NUM_CALLBACK_PRIORITIES; i++) {
|
||||
callbackQueue[i].shutdown = 1;
|
||||
epicsAtomicSetIntT(&callbackQueue[i].shutdown, 1);
|
||||
epicsEventSignal(callbackQueue[i].semWakeUp);
|
||||
}
|
||||
|
||||
@@ -252,6 +254,10 @@ void callbackCleanup(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(epicsAtomicCmpAndSwapIntT(&cbState, cbStop, cbInit)!=cbStop) {
|
||||
fprintf(stderr, "callbackCleanup() but not stopped\n");
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_CALLBACK_PRIORITIES; i++) {
|
||||
cbQueueSet *mySet = &callbackQueue[i];
|
||||
|
||||
@@ -261,7 +267,6 @@ void callbackCleanup(void)
|
||||
}
|
||||
|
||||
epicsTimerQueueRelease(timerQueue);
|
||||
callbackIsInit = 0;
|
||||
memset(callbackQueue, 0, sizeof(callbackQueue));
|
||||
}
|
||||
|
||||
@@ -271,15 +276,14 @@ void callbackInit(void)
|
||||
int j;
|
||||
char threadName[32];
|
||||
|
||||
if (callbackIsInit) {
|
||||
errlogMessage("Warning: callbackInit called again before callbackCleanup\n");
|
||||
if (epicsAtomicCmpAndSwapIntT(&cbState, cbInit, cbRun)!=cbInit) {
|
||||
fprintf(stderr, "Warning: callbackInit called again before callbackCleanup\n");
|
||||
return;
|
||||
}
|
||||
callbackIsInit = 1;
|
||||
|
||||
if(!startStopEvent)
|
||||
startStopEvent = epicsEventMustCreate(epicsEventEmpty);
|
||||
cbCtl = ctlRun;
|
||||
|
||||
timerQueue = epicsTimerQueueAllocate(0, epicsThreadPriorityScanHigh);
|
||||
|
||||
for (i = 0; i < NUM_CALLBACK_PRIORITIES; i++) {
|
||||
|
||||
@@ -49,7 +49,13 @@
|
||||
#include "link.h"
|
||||
#include "special.h"
|
||||
|
||||
#define EVENTSPERQUE 32
|
||||
/* Queue size based on Ethernet MTU of 1500 bytes.
|
||||
* Assume <=66 bytes of ethernet+IP+TCP overhead
|
||||
* and 40 byte CA messages (DBF_TIME_DOUBLE).
|
||||
*
|
||||
* (1500-66)/40 -> 35
|
||||
*/
|
||||
#define EVENTSPERQUE 36
|
||||
#define EVENTENTRIES 4 /* the number of que entries for each event */
|
||||
#define EVENTQUESIZE (EVENTENTRIES * EVENTSPERQUE)
|
||||
#define EVENTQEMPTY ((struct evSubscrip *)NULL)
|
||||
|
||||
@@ -13,7 +13,7 @@ SRC_DIRS += $(IOCDIR)/dbtemplate
|
||||
|
||||
PROD_HOST += msi
|
||||
|
||||
msi_SRCS = msi.c
|
||||
msi_SRCS = msi.cpp
|
||||
msi_LIBS += Com
|
||||
HTMLS += msi.html
|
||||
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
|
||||
/* msi - macro substitutions and include */
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
@@ -18,7 +21,6 @@
|
||||
|
||||
#include <dbDefs.h>
|
||||
#include <macLib.h>
|
||||
#include <ellLib.h>
|
||||
#include <errlog.h>
|
||||
#include <epicsString.h>
|
||||
#include <osiFileName.h>
|
||||
@@ -56,32 +58,35 @@ int din = 0;
|
||||
typedef struct inputData inputData;
|
||||
|
||||
static void inputConstruct(inputData **ppvt);
|
||||
static void inputDestruct(inputData *pvt);
|
||||
static void inputAddPath(inputData *pvt, char *pval);
|
||||
static void inputBegin(inputData *pvt, char *fileName);
|
||||
static char *inputNextLine(inputData *pvt);
|
||||
static void inputNewIncludeFile(inputData *pvt, char *name);
|
||||
static void inputErrPrint(inputData *pvt);
|
||||
static void inputDestruct(inputData * const pvt);
|
||||
static void inputAddPath(inputData * const pvt, const char * const pval);
|
||||
static void inputBegin(inputData * const pvt, const char * const fileName);
|
||||
static char *inputNextLine(inputData * const pvt);
|
||||
static void inputNewIncludeFile(inputData * const pvt, const char * const name);
|
||||
static void inputErrPrint(const inputData * const pvt);
|
||||
|
||||
/* Module to read the substitution file */
|
||||
typedef struct subInfo subInfo;
|
||||
|
||||
static void substituteOpen(subInfo **ppvt, char *substitutionName);
|
||||
static void substituteDestruct(subInfo *pvt);
|
||||
static int substituteGetNextSet(subInfo *pvt, char **filename);
|
||||
static int substituteGetGlobalSet(subInfo *pvt);
|
||||
static char *substituteGetReplacements(subInfo *pvt);
|
||||
static char *substituteGetGlobalReplacements(subInfo *pvt);
|
||||
static void substituteOpen(subInfo **ppvt, const std::string& substitutionName);
|
||||
static void substituteDestruct(subInfo * const pvt);
|
||||
static bool substituteGetNextSet(subInfo * const pvt, char **filename);
|
||||
static bool substituteGetGlobalSet(subInfo * const pvt);
|
||||
static const char *substituteGetReplacements(subInfo * const pvt);
|
||||
static const char *substituteGetGlobalReplacements(subInfo * const pvt);
|
||||
|
||||
/* Forward references to local routines */
|
||||
static void usageExit(int status);
|
||||
static void abortExit(int status);
|
||||
static void addMacroReplacements(MAC_HANDLE *macPvt, char *pval);
|
||||
static void makeSubstitutions(inputData *inputPvt, MAC_HANDLE *macPvt, char *templateName);
|
||||
static void usageExit(const int status);
|
||||
static void abortExit(const int status);
|
||||
static void addMacroReplacements(MAC_HANDLE * const macPvt,
|
||||
const char * const pval);
|
||||
static void makeSubstitutions(inputData * const inputPvt,
|
||||
MAC_HANDLE * const macPvt,
|
||||
const char * const templateName);
|
||||
|
||||
/*Global variables */
|
||||
static int opt_V = 0;
|
||||
static int opt_D = 0;
|
||||
static bool opt_D = false;
|
||||
|
||||
static char *outFile = 0;
|
||||
static int numDeps = 0, depHashes[MAX_DEPS];
|
||||
@@ -92,23 +97,21 @@ int main(int argc,char **argv)
|
||||
inputData *inputPvt;
|
||||
MAC_HANDLE *macPvt;
|
||||
char *pval;
|
||||
int narg;
|
||||
char *substitutionName = 0;
|
||||
std::string substitutionName;
|
||||
char *templateName = 0;
|
||||
int i;
|
||||
int localScope = 1;
|
||||
bool localScope = true;
|
||||
|
||||
inputConstruct(&inputPvt);
|
||||
macCreateHandle(&macPvt, 0);
|
||||
while ((argc > 1) && (argv[1][0] == '-')) {
|
||||
narg = (strlen(argv[1]) == 2) ? 2 : 1;
|
||||
int narg = (strlen(argv[1]) == 2) ? 2 : 1;
|
||||
pval = (narg == 1) ? (argv[1] + 2) : argv[2];
|
||||
|
||||
if (strncmp(argv[1], "-I", 2) == 0) {
|
||||
inputAddPath(inputPvt, pval);
|
||||
}
|
||||
else if (strcmp(argv[1], "-D") == 0) {
|
||||
opt_D = 1;
|
||||
opt_D = true;
|
||||
narg = 1; /* no argument for this option */
|
||||
}
|
||||
else if(strncmp(argv[1], "-o", 2) == 0) {
|
||||
@@ -118,14 +121,14 @@ int main(int argc,char **argv)
|
||||
addMacroReplacements(macPvt, pval);
|
||||
}
|
||||
else if(strncmp(argv[1], "-S", 2) == 0) {
|
||||
substitutionName = epicsStrDup(pval);
|
||||
substitutionName = pval;
|
||||
}
|
||||
else if (strcmp(argv[1], "-V") == 0) {
|
||||
opt_V = 1;
|
||||
narg = 1; /* no argument for this option */
|
||||
}
|
||||
else if (strcmp(argv[1], "-g") == 0) {
|
||||
localScope = 0;
|
||||
localScope = false;
|
||||
narg = 1; /* no argument for this option */
|
||||
}
|
||||
else if (strcmp(argv[1], "-h") == 0) {
|
||||
@@ -137,7 +140,7 @@ int main(int argc,char **argv)
|
||||
}
|
||||
|
||||
argc -= narg;
|
||||
for (i = 1; i < argc; i++)
|
||||
for (int i = 1; i < argc; i++)
|
||||
argv[i] = argv[i + narg];
|
||||
}
|
||||
|
||||
@@ -165,24 +168,24 @@ int main(int argc,char **argv)
|
||||
if (argc == 2)
|
||||
templateName = epicsStrDup(argv[1]);
|
||||
|
||||
if (!substitutionName) {
|
||||
if (substitutionName.empty()) {
|
||||
STEP("Single template+substitutions file");
|
||||
makeSubstitutions(inputPvt, macPvt, templateName);
|
||||
}
|
||||
else {
|
||||
subInfo *substitutePvt;
|
||||
char *filename = 0;
|
||||
int isGlobal, isFile;
|
||||
bool isGlobal, isFile;
|
||||
|
||||
STEPS("Substitutions from file", substitutionName);
|
||||
STEPS("Substitutions from file", substitutionName.c_str());
|
||||
substituteOpen(&substitutePvt, substitutionName);
|
||||
do {
|
||||
isGlobal = substituteGetGlobalSet(substitutePvt);
|
||||
if (isGlobal) {
|
||||
STEP("Handling global macros");
|
||||
pval = substituteGetGlobalReplacements(substitutePvt);
|
||||
if (pval)
|
||||
addMacroReplacements(macPvt, pval);
|
||||
const char *macStr = substituteGetGlobalReplacements(substitutePvt);
|
||||
if (macStr)
|
||||
addMacroReplacements(macPvt, macStr);
|
||||
}
|
||||
else if ((isFile = substituteGetNextSet(substitutePvt, &filename))) {
|
||||
if (templateName)
|
||||
@@ -193,11 +196,12 @@ int main(int argc,char **argv)
|
||||
}
|
||||
|
||||
STEPS("Handling template file", filename);
|
||||
while ((pval = substituteGetReplacements(substitutePvt))) {
|
||||
const char *macStr;
|
||||
while ((macStr = substituteGetReplacements(substitutePvt))) {
|
||||
if (localScope)
|
||||
macPushScope(macPvt);
|
||||
|
||||
addMacroReplacements(macPvt, pval);
|
||||
addMacroReplacements(macPvt, macStr);
|
||||
makeSubstitutions(inputPvt, macPvt, filename);
|
||||
|
||||
if (localScope)
|
||||
@@ -207,18 +211,18 @@ int main(int argc,char **argv)
|
||||
} while (isGlobal || isFile);
|
||||
substituteDestruct(substitutePvt);
|
||||
}
|
||||
errlogFlush();
|
||||
macDeleteHandle(macPvt);
|
||||
errlogFlush(); // macLib calls errlogPrintf()
|
||||
inputDestruct(inputPvt);
|
||||
if (opt_D) {
|
||||
printf("\n");
|
||||
}
|
||||
fflush(stdout);
|
||||
free(templateName);
|
||||
free(substitutionName);
|
||||
return opt_V & 2;
|
||||
}
|
||||
|
||||
void usageExit(int status)
|
||||
void usageExit(const int status)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: msi [options] [template]\n"
|
||||
@@ -236,7 +240,7 @@ void usageExit(int status)
|
||||
exit(status);
|
||||
}
|
||||
|
||||
void abortExit(int status)
|
||||
void abortExit(const int status)
|
||||
{
|
||||
if (outFile) {
|
||||
fclose(stdout);
|
||||
@@ -245,7 +249,8 @@ void abortExit(int status)
|
||||
exit(status);
|
||||
}
|
||||
|
||||
static void addMacroReplacements(MAC_HANDLE *macPvt, char *pval)
|
||||
static void addMacroReplacements(MAC_HANDLE * const macPvt,
|
||||
const char * const pval)
|
||||
{
|
||||
char **pairs;
|
||||
long status;
|
||||
@@ -268,7 +273,9 @@ static void addMacroReplacements(MAC_HANDLE *macPvt, char *pval)
|
||||
typedef enum {cmdInclude,cmdSubstitute} cmdType;
|
||||
static const char *cmdNames[] = {"include","substitute"};
|
||||
|
||||
static void makeSubstitutions(inputData *inputPvt, MAC_HANDLE *macPvt, char *templateName)
|
||||
static void makeSubstitutions(inputData * const inputPvt,
|
||||
MAC_HANDLE * const macPvt,
|
||||
const char * const templateName)
|
||||
{
|
||||
char *input;
|
||||
static char buffer[MAX_BUFFER_SIZE];
|
||||
@@ -292,7 +299,6 @@ static void makeSubstitutions(inputData *inputPvt, MAC_HANDLE *macPvt, char *tem
|
||||
if (command) {
|
||||
char *pstart;
|
||||
char *pend;
|
||||
char *copy;
|
||||
int cmdind=-1;
|
||||
int i;
|
||||
|
||||
@@ -325,16 +331,15 @@ static void makeSubstitutions(inputData *inputPvt, MAC_HANDLE *macPvt, char *tem
|
||||
/*skip quote and any trailing blanks*/
|
||||
while (*++p == ' ') ;
|
||||
if (*p != '\n' && *p != 0) goto endcmd;
|
||||
copy = calloc(pend-pstart + 1, sizeof(char));
|
||||
strncpy(copy, pstart, pend-pstart);
|
||||
std::string copy = std::string(pstart, pend);
|
||||
|
||||
switch(cmdind) {
|
||||
case cmdInclude:
|
||||
inputNewIncludeFile(inputPvt,copy);
|
||||
inputNewIncludeFile(inputPvt, copy.c_str());
|
||||
break;
|
||||
|
||||
case cmdSubstitute:
|
||||
addMacroReplacements(macPvt,copy);
|
||||
addMacroReplacements(macPvt, copy.c_str());
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -342,7 +347,6 @@ static void makeSubstitutions(inputData *inputPvt, MAC_HANDLE *macPvt, char *tem
|
||||
inputErrPrint(inputPvt);
|
||||
abortExit(1);
|
||||
}
|
||||
free(copy);
|
||||
expand = 0;
|
||||
}
|
||||
|
||||
@@ -361,94 +365,72 @@ endcmd:
|
||||
}
|
||||
|
||||
typedef struct inputFile {
|
||||
ELLNODE node;
|
||||
char *filename;
|
||||
std::string filename;
|
||||
FILE *fp;
|
||||
int lineNum;
|
||||
} inputFile;
|
||||
|
||||
typedef struct pathNode {
|
||||
ELLNODE node;
|
||||
char *directory;
|
||||
} pathNode;
|
||||
|
||||
struct inputData {
|
||||
ELLLIST inputFileList;
|
||||
ELLLIST pathList;
|
||||
std::list<inputFile> inputFileList;
|
||||
std::list<std::string> pathList;
|
||||
char inputBuffer[MAX_BUFFER_SIZE];
|
||||
inputData() { memset(inputBuffer, 0, sizeof(inputBuffer) * sizeof(inputBuffer[0])); };
|
||||
};
|
||||
|
||||
static void inputOpenFile(inputData *pinputData, char *filename);
|
||||
static void inputOpenFile(inputData *pinputData, const char * const filename);
|
||||
static void inputCloseFile(inputData *pinputData);
|
||||
static void inputCloseAllFiles(inputData *pinputData);
|
||||
|
||||
static void inputConstruct(inputData **ppvt)
|
||||
{
|
||||
inputData *pinputData;
|
||||
|
||||
pinputData = calloc(1, sizeof(inputData));
|
||||
ellInit(&pinputData->inputFileList);
|
||||
ellInit(&pinputData->pathList);
|
||||
*ppvt = pinputData;
|
||||
*ppvt = new inputData;
|
||||
}
|
||||
|
||||
static void inputDestruct(inputData *pinputData)
|
||||
static void inputDestruct(inputData * const pinputData)
|
||||
{
|
||||
pathNode *ppathNode;
|
||||
|
||||
inputCloseAllFiles(pinputData);
|
||||
while ((ppathNode = (pathNode *) ellFirst(&pinputData->pathList))) {
|
||||
ellDelete(&pinputData->pathList, &ppathNode->node);
|
||||
free(ppathNode->directory);
|
||||
free(ppathNode);
|
||||
}
|
||||
free(pinputData);
|
||||
delete(pinputData);
|
||||
}
|
||||
|
||||
static void inputAddPath(inputData *pinputData, char *path)
|
||||
static void inputAddPath(inputData * const pinputData, const char * const path)
|
||||
{
|
||||
ELLLIST *ppathList = &pinputData->pathList;
|
||||
pathNode *ppathNode;
|
||||
const char *pcolon;
|
||||
const char *pdir;
|
||||
size_t len;
|
||||
int emptyName;
|
||||
const char sep = *OSI_PATH_LIST_SEPARATOR;
|
||||
|
||||
ENTER;
|
||||
pdir = path;
|
||||
/*an empty name at beginning, middle, or end means current directory*/
|
||||
while (pdir && *pdir) {
|
||||
emptyName = ((*pdir == sep) ? 1 : 0);
|
||||
bool emptyName = (*pdir == sep);
|
||||
if (emptyName) ++pdir;
|
||||
|
||||
ppathNode = (pathNode *) calloc(1, sizeof(pathNode));
|
||||
ellAdd(ppathList, &ppathNode->node);
|
||||
|
||||
std::string directory;
|
||||
if (!emptyName) {
|
||||
pcolon = strchr(pdir, sep);
|
||||
len = (pcolon ? (pcolon - pdir) : strlen(pdir));
|
||||
if (len > 0) {
|
||||
ppathNode->directory = (char *) calloc(len + 1, sizeof(char));
|
||||
strncpy(ppathNode->directory, pdir, len);
|
||||
directory = std::string(pdir, len);
|
||||
pdir = pcolon;
|
||||
/*unless at end skip past first colon*/
|
||||
if (pdir && *(pdir + 1) != 0) ++pdir;
|
||||
}
|
||||
else { /*must have been trailing : */
|
||||
emptyName = 1;
|
||||
emptyName = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (emptyName) {
|
||||
ppathNode->directory = (char *) calloc(2, sizeof(char));
|
||||
strcpy(ppathNode->directory, ".");
|
||||
directory = ".";
|
||||
}
|
||||
|
||||
pinputData->pathList.push_back(directory);
|
||||
}
|
||||
EXIT;
|
||||
}
|
||||
|
||||
static void inputBegin(inputData *pinputData, char *fileName)
|
||||
static void inputBegin(inputData * const pinputData, const char * const fileName)
|
||||
{
|
||||
ENTER;
|
||||
inputCloseAllFiles(pinputData);
|
||||
@@ -456,16 +438,16 @@ static void inputBegin(inputData *pinputData, char *fileName)
|
||||
EXIT;
|
||||
}
|
||||
|
||||
static char *inputNextLine(inputData *pinputData)
|
||||
static char *inputNextLine(inputData * const pinputData)
|
||||
{
|
||||
inputFile *pinputFile;
|
||||
char *pline;
|
||||
std::list<inputFile>& inFileList = pinputData->inputFileList;
|
||||
|
||||
ENTER;
|
||||
while ((pinputFile = (inputFile *) ellFirst(&pinputData->inputFileList))) {
|
||||
pline = fgets(pinputData->inputBuffer, MAX_BUFFER_SIZE, pinputFile->fp);
|
||||
while (!inFileList.empty()) {
|
||||
inputFile& inFile = inFileList.front();
|
||||
char *pline = fgets(pinputData->inputBuffer, MAX_BUFFER_SIZE, inFile.fp);
|
||||
if (pline) {
|
||||
++pinputFile->lineNum;
|
||||
++inFile.lineNum;
|
||||
EXITS(pline);
|
||||
return pline;
|
||||
}
|
||||
@@ -475,32 +457,31 @@ static char *inputNextLine(inputData *pinputData)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void inputNewIncludeFile(inputData *pinputData, char *name)
|
||||
static void inputNewIncludeFile(inputData * const pinputData,
|
||||
const char * const name)
|
||||
{
|
||||
ENTER;
|
||||
inputOpenFile(pinputData,name);
|
||||
EXIT;
|
||||
}
|
||||
|
||||
static void inputErrPrint(inputData *pinputData)
|
||||
static void inputErrPrint(const inputData *const pinputData)
|
||||
{
|
||||
inputFile *pinputFile;
|
||||
|
||||
ENTER;
|
||||
fprintf(stderr, "input: '%s' at ", pinputData->inputBuffer);
|
||||
pinputFile = (inputFile *) ellFirst(&pinputData->inputFileList);
|
||||
while (pinputFile) {
|
||||
fprintf(stderr, "line %d of ", pinputFile->lineNum);
|
||||
const std::list<inputFile>& inFileList = pinputData->inputFileList;
|
||||
std::list<inputFile>::const_iterator inFileIt = inFileList.begin();
|
||||
while (inFileIt != inFileList.end()) {
|
||||
fprintf(stderr, "line %d of ", inFileIt->lineNum);
|
||||
|
||||
if (pinputFile->filename) {
|
||||
fprintf(stderr, " file %s\n", pinputFile->filename);
|
||||
if (!inFileIt->filename.empty()) {
|
||||
fprintf(stderr, " file %s\n", inFileIt->filename.c_str());
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "stdin:\n");
|
||||
}
|
||||
|
||||
pinputFile = (inputFile *) ellNext(&pinputFile->node);
|
||||
if (pinputFile) {
|
||||
if (++inFileIt != inFileList.end()) {
|
||||
fprintf(stderr, " included from ");
|
||||
}
|
||||
else {
|
||||
@@ -511,12 +492,11 @@ static void inputErrPrint(inputData *pinputData)
|
||||
EXIT;
|
||||
}
|
||||
|
||||
static void inputOpenFile(inputData *pinputData,char *filename)
|
||||
static void inputOpenFile(inputData *pinputData, const char * const filename)
|
||||
{
|
||||
ELLLIST *ppathList = &pinputData->pathList;
|
||||
pathNode *ppathNode = 0;
|
||||
inputFile *pinputFile;
|
||||
char *fullname = 0;
|
||||
std::list<std::string>& pathList = pinputData->pathList;
|
||||
std::list<std::string>::iterator pathIt = pathList.end();
|
||||
std::string fullname;
|
||||
FILE *fp = 0;
|
||||
|
||||
ENTER;
|
||||
@@ -524,24 +504,19 @@ static void inputOpenFile(inputData *pinputData,char *filename)
|
||||
STEP("Using stdin");
|
||||
fp = stdin;
|
||||
}
|
||||
else if ((ellCount(ppathList) == 0) || strchr(filename, '/')){
|
||||
else if (pathList.empty() || strchr(filename, '/')){
|
||||
STEPS("Opening ", filename);
|
||||
fp = fopen(filename, "r");
|
||||
}
|
||||
else {
|
||||
ppathNode = (pathNode *) ellFirst(ppathList);
|
||||
while (ppathNode) {
|
||||
fullname = calloc(strlen(filename) + strlen(ppathNode->directory) + 2,
|
||||
sizeof(char));
|
||||
strcpy(fullname, ppathNode->directory);
|
||||
strcat(fullname, "/");
|
||||
strcat(fullname, filename);
|
||||
pathIt = pathList.begin();
|
||||
while(pathIt != pathList.end()) {
|
||||
fullname = *pathIt + "/" + filename;
|
||||
STEPS("Trying", filename);
|
||||
fp = fopen(fullname, "r");
|
||||
fp = fopen(fullname.c_str(), "r");
|
||||
if (fp)
|
||||
break;
|
||||
free(fullname);
|
||||
ppathNode = (pathNode *) ellNext(&ppathNode->node);
|
||||
++pathIt;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -552,20 +527,20 @@ static void inputOpenFile(inputData *pinputData,char *filename)
|
||||
}
|
||||
|
||||
STEP("File opened");
|
||||
pinputFile = calloc(1, sizeof(inputFile));
|
||||
inputFile inFile = inputFile();
|
||||
|
||||
if (ppathNode) {
|
||||
pinputFile->filename = fullname;
|
||||
if (pathIt != pathList.end()) {
|
||||
inFile.filename = fullname;
|
||||
}
|
||||
else if (filename) {
|
||||
pinputFile->filename = epicsStrDup(filename);
|
||||
inFile.filename = filename;
|
||||
}
|
||||
else {
|
||||
pinputFile->filename = epicsStrDup("stdin");
|
||||
inFile.filename = "stdin";
|
||||
}
|
||||
|
||||
if (opt_D) {
|
||||
int hash = epicsStrHash(pinputFile->filename, 12345);
|
||||
int hash = epicsStrHash(inFile.filename.c_str(), 12345);
|
||||
int i = 0;
|
||||
int match = 0;
|
||||
|
||||
@@ -578,7 +553,7 @@ static void inputOpenFile(inputData *pinputData,char *filename)
|
||||
if (!match) {
|
||||
const char *wrap = numDeps ? " \\\n" : "";
|
||||
|
||||
printf("%s %s", wrap, pinputFile->filename);
|
||||
printf("%s %s", wrap, inFile.filename.c_str());
|
||||
if (numDeps < MAX_DEPS) {
|
||||
depHashes[numDeps++] = hash;
|
||||
}
|
||||
@@ -589,33 +564,29 @@ static void inputOpenFile(inputData *pinputData,char *filename)
|
||||
}
|
||||
}
|
||||
|
||||
pinputFile->fp = fp;
|
||||
ellInsert(&pinputData->inputFileList, 0, &pinputFile->node);
|
||||
inFile.fp = fp;
|
||||
pinputData->inputFileList.push_front(inFile);
|
||||
EXIT;
|
||||
}
|
||||
|
||||
static void inputCloseFile(inputData *pinputData)
|
||||
{
|
||||
inputFile *pinputFile;
|
||||
|
||||
std::list<inputFile>& inFileList = pinputData->inputFileList;
|
||||
ENTER;
|
||||
pinputFile = (inputFile *) ellFirst(&pinputData->inputFileList);
|
||||
if (pinputFile) {
|
||||
ellDelete(&pinputData->inputFileList, &pinputFile->node);
|
||||
if (fclose(pinputFile->fp))
|
||||
fprintf(stderr, "msi: Can't close input file '%s'\n", pinputFile->filename);
|
||||
free(pinputFile->filename);
|
||||
free(pinputFile);
|
||||
if(!inFileList.empty()) {
|
||||
inputFile& inFile = inFileList.front();
|
||||
if (fclose(inFile.fp))
|
||||
fprintf(stderr, "msi: Can't close input file '%s'\n", inFile.filename.c_str());
|
||||
inFileList.erase(inFileList.begin());
|
||||
}
|
||||
EXIT;
|
||||
}
|
||||
|
||||
static void inputCloseAllFiles(inputData *pinputData)
|
||||
{
|
||||
inputFile *pinputFile;
|
||||
|
||||
ENTER;
|
||||
while ((pinputFile = (inputFile *) ellFirst(&pinputData->inputFileList))) {
|
||||
const std::list<inputFile>& inFileList = pinputData->inputFileList;
|
||||
while(!inFileList.empty()) {
|
||||
inputCloseFile(pinputData);
|
||||
}
|
||||
EXIT;
|
||||
@@ -627,7 +598,7 @@ typedef enum {
|
||||
} tokenType;
|
||||
|
||||
typedef struct subFile {
|
||||
char *substitutionName;
|
||||
std::string substitutionName;
|
||||
FILE *fp;
|
||||
int lineNum;
|
||||
char inputBuffer[MAX_BUFFER_SIZE];
|
||||
@@ -636,25 +607,20 @@ typedef struct subFile {
|
||||
char string[MAX_BUFFER_SIZE];
|
||||
} subFile;
|
||||
|
||||
typedef struct patternNode {
|
||||
ELLNODE node;
|
||||
char *var;
|
||||
} patternNode;
|
||||
|
||||
struct subInfo {
|
||||
subFile *psubFile;
|
||||
int isFile;
|
||||
bool isFile;
|
||||
char *filename;
|
||||
int isPattern;
|
||||
ELLLIST patternList;
|
||||
size_t size;
|
||||
size_t curLength;
|
||||
char *macroReplacements;
|
||||
bool isPattern;
|
||||
std::list<std::string> patternList;
|
||||
std::string macroReplacements;
|
||||
subInfo() : psubFile(NULL), isFile(false), filename(NULL),
|
||||
isPattern(false) {};
|
||||
};
|
||||
|
||||
static char *subGetNextLine(subFile *psubFile);
|
||||
static tokenType subGetNextToken(subFile *psubFile);
|
||||
static void subFileErrPrint(subFile *psubFile,char * message);
|
||||
static void subFileErrPrint(subFile *psubFile, const char * message);
|
||||
static void freeSubFile(subInfo *psubInfo);
|
||||
static void freePattern(subInfo *psubInfo);
|
||||
static void catMacroReplacements(subInfo *psubInfo,const char *value);
|
||||
@@ -668,7 +634,7 @@ void freeSubFile(subInfo *psubInfo)
|
||||
if (fclose(psubFile->fp))
|
||||
fprintf(stderr, "msi: Can't close substitution file\n");
|
||||
}
|
||||
free(psubFile);
|
||||
delete(psubFile);
|
||||
free(psubInfo->filename);
|
||||
psubInfo->psubFile = 0;
|
||||
EXIT;
|
||||
@@ -676,43 +642,36 @@ void freeSubFile(subInfo *psubInfo)
|
||||
|
||||
void freePattern(subInfo *psubInfo)
|
||||
{
|
||||
patternNode *ppatternNode;
|
||||
|
||||
ENTER;
|
||||
while ((ppatternNode = (patternNode *) ellFirst(&psubInfo->patternList))) {
|
||||
ellDelete(&psubInfo->patternList, &ppatternNode->node);
|
||||
free(ppatternNode->var);
|
||||
free(ppatternNode);
|
||||
}
|
||||
psubInfo->isPattern = 0;
|
||||
psubInfo->patternList.clear();
|
||||
psubInfo->isPattern = false;
|
||||
EXIT;
|
||||
}
|
||||
|
||||
static void substituteDestruct(subInfo *psubInfo)
|
||||
static void substituteDestruct(subInfo * const psubInfo)
|
||||
{
|
||||
ENTER;
|
||||
freeSubFile(psubInfo);
|
||||
freePattern(psubInfo);
|
||||
free(psubInfo);
|
||||
delete(psubInfo);
|
||||
EXIT;
|
||||
}
|
||||
|
||||
static void substituteOpen(subInfo **ppvt, char *substitutionName)
|
||||
static void substituteOpen(subInfo **ppvt, const std::string& substitutionName)
|
||||
{
|
||||
subInfo *psubInfo;
|
||||
subFile *psubFile;
|
||||
FILE *fp;
|
||||
|
||||
ENTER;
|
||||
psubInfo = calloc(1, sizeof(subInfo));
|
||||
psubInfo = new subInfo;
|
||||
*ppvt = psubInfo;
|
||||
psubFile = calloc(1, sizeof(subFile));
|
||||
psubFile = new subFile;
|
||||
psubInfo->psubFile = psubFile;
|
||||
ellInit(&psubInfo->patternList);
|
||||
|
||||
fp = fopen(substitutionName, "r");
|
||||
fp = fopen(substitutionName.c_str(), "r");
|
||||
if (!fp) {
|
||||
fprintf(stderr, "msi: Can't open file '%s'\n", substitutionName);
|
||||
fprintf(stderr, "msi: Can't open file '%s'\n", substitutionName.c_str());
|
||||
abortExit(1);
|
||||
}
|
||||
|
||||
@@ -725,7 +684,7 @@ static void substituteOpen(subInfo **ppvt, char *substitutionName)
|
||||
EXIT;
|
||||
}
|
||||
|
||||
static int substituteGetGlobalSet(subInfo *psubInfo)
|
||||
static bool substituteGetGlobalSet(subInfo * const psubInfo)
|
||||
{
|
||||
subFile *psubFile = psubInfo->psubFile;
|
||||
|
||||
@@ -737,17 +696,16 @@ static int substituteGetGlobalSet(subInfo *psubInfo)
|
||||
strcmp(psubFile->string, "global") == 0) {
|
||||
subGetNextToken(psubFile);
|
||||
EXITD(1);
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
EXITD(0);
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
static int substituteGetNextSet(subInfo *psubInfo,char **filename)
|
||||
static bool substituteGetNextSet(subInfo * const psubInfo,char **filename)
|
||||
{
|
||||
subFile *psubFile = psubInfo->psubFile;
|
||||
patternNode *ppatternNode;
|
||||
|
||||
ENTER;
|
||||
*filename = 0;
|
||||
@@ -756,7 +714,7 @@ static int substituteGetNextSet(subInfo *psubInfo,char **filename)
|
||||
|
||||
if (psubFile->token == tokenEOF) {
|
||||
EXITD(0);
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (psubFile->token == tokenString &&
|
||||
@@ -764,7 +722,7 @@ static int substituteGetNextSet(subInfo *psubInfo,char **filename)
|
||||
size_t len;
|
||||
|
||||
STEP("Parsed 'file'");
|
||||
psubInfo->isFile = 1;
|
||||
psubInfo->isFile = true;
|
||||
if (subGetNextToken(psubFile) != tokenString) {
|
||||
subFileErrPrint(psubFile, "Parse error, expecting a filename");
|
||||
abortExit(1);
|
||||
@@ -799,7 +757,7 @@ static int substituteGetNextSet(subInfo *psubInfo,char **filename)
|
||||
|
||||
if (psubFile->token == tokenLBrace) {
|
||||
EXITD(1);
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (psubFile->token == tokenRBrace) {
|
||||
@@ -815,7 +773,7 @@ static int substituteGetNextSet(subInfo *psubInfo,char **filename)
|
||||
|
||||
STEP("Parsed 'pattern'");
|
||||
freePattern(psubInfo);
|
||||
psubInfo->isPattern = 1;
|
||||
psubInfo->isPattern = true;
|
||||
|
||||
while (subGetNextToken(psubFile) == tokenSeparator);
|
||||
|
||||
@@ -825,15 +783,13 @@ static int substituteGetNextSet(subInfo *psubInfo,char **filename)
|
||||
}
|
||||
STEP("Parsed '{'");
|
||||
|
||||
while (1) {
|
||||
while (true) {
|
||||
while (subGetNextToken(psubFile) == tokenSeparator);
|
||||
|
||||
if (psubFile->token != tokenString)
|
||||
break;
|
||||
|
||||
ppatternNode = calloc(1, sizeof(patternNode));
|
||||
ellAdd(&psubInfo->patternList, &ppatternNode->node);
|
||||
ppatternNode->var = epicsStrDup(psubFile->string);
|
||||
psubInfo->patternList.push_back(psubFile->string);
|
||||
}
|
||||
|
||||
if (psubFile->token != tokenRBrace) {
|
||||
@@ -843,23 +799,21 @@ static int substituteGetNextSet(subInfo *psubInfo,char **filename)
|
||||
|
||||
subGetNextToken(psubFile);
|
||||
EXITD(1);
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
static char *substituteGetGlobalReplacements(subInfo *psubInfo)
|
||||
static const char *substituteGetGlobalReplacements(subInfo * const psubInfo)
|
||||
{
|
||||
subFile *psubFile = psubInfo->psubFile;
|
||||
|
||||
ENTER;
|
||||
if (psubInfo->macroReplacements)
|
||||
psubInfo->macroReplacements[0] = 0;
|
||||
psubInfo->curLength = 0;
|
||||
psubInfo->macroReplacements.clear();
|
||||
|
||||
while (psubFile->token == tokenSeparator)
|
||||
subGetNextToken(psubFile);
|
||||
|
||||
if (psubFile->token == tokenRBrace && psubInfo->isFile) {
|
||||
psubInfo->isFile = 0;
|
||||
psubInfo->isFile = false;
|
||||
free(psubInfo->filename);
|
||||
psubInfo->filename = 0;
|
||||
freePattern(psubInfo);
|
||||
@@ -877,12 +831,12 @@ static char *substituteGetGlobalReplacements(subInfo *psubInfo)
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
while (true) {
|
||||
switch(subGetNextToken(psubFile)) {
|
||||
case tokenRBrace:
|
||||
subGetNextToken(psubFile);
|
||||
EXITS(psubInfo->macroReplacements);
|
||||
return psubInfo->macroReplacements;
|
||||
EXITS(psubInfo->macroReplacements.c_str());
|
||||
return psubInfo->macroReplacements.c_str();
|
||||
|
||||
case tokenSeparator:
|
||||
catMacroReplacements(psubInfo, ",");
|
||||
@@ -902,21 +856,18 @@ static char *substituteGetGlobalReplacements(subInfo *psubInfo)
|
||||
}
|
||||
}
|
||||
|
||||
static char *substituteGetReplacements(subInfo *psubInfo)
|
||||
static const char *substituteGetReplacements(subInfo * const psubInfo)
|
||||
{
|
||||
subFile *psubFile = psubInfo->psubFile;
|
||||
patternNode *ppatternNode;
|
||||
|
||||
ENTER;
|
||||
if (psubInfo->macroReplacements)
|
||||
psubInfo->macroReplacements[0] = 0;
|
||||
psubInfo->curLength = 0;
|
||||
psubInfo->macroReplacements.clear();
|
||||
|
||||
while (psubFile->token == tokenSeparator)
|
||||
subGetNextToken(psubFile);
|
||||
|
||||
if (psubFile->token==tokenRBrace && psubInfo->isFile) {
|
||||
psubInfo->isFile = 0;
|
||||
psubInfo->isFile = false;
|
||||
free(psubInfo->filename);
|
||||
psubInfo->filename = 0;
|
||||
freePattern(psubInfo);
|
||||
@@ -936,15 +887,16 @@ static char *substituteGetReplacements(subInfo *psubInfo)
|
||||
}
|
||||
|
||||
if (psubInfo->isPattern) {
|
||||
int gotFirstPattern = 0;
|
||||
bool gotFirstPattern = false;
|
||||
|
||||
while (subGetNextToken(psubFile) == tokenSeparator);
|
||||
ppatternNode = (patternNode *) ellFirst(&psubInfo->patternList);
|
||||
while (1) {
|
||||
std::list<std::string>& patternList = psubInfo->patternList;
|
||||
std::list<std::string>::iterator patternIt = patternList.begin();
|
||||
while (true) {
|
||||
if (psubFile->token == tokenRBrace) {
|
||||
subGetNextToken(psubFile);
|
||||
EXITS(psubInfo->macroReplacements);
|
||||
return psubInfo->macroReplacements;
|
||||
EXITS(psubInfo->macroReplacements.c_str());
|
||||
return psubInfo->macroReplacements.c_str();
|
||||
}
|
||||
|
||||
if (psubFile->token != tokenString) {
|
||||
@@ -954,13 +906,13 @@ static char *substituteGetReplacements(subInfo *psubInfo)
|
||||
|
||||
if (gotFirstPattern)
|
||||
catMacroReplacements(psubInfo, ",");
|
||||
gotFirstPattern = 1;
|
||||
gotFirstPattern = true;
|
||||
|
||||
if (ppatternNode) {
|
||||
catMacroReplacements(psubInfo, ppatternNode->var);
|
||||
if (patternIt != patternList.end()) {
|
||||
catMacroReplacements(psubInfo, patternIt->c_str());
|
||||
catMacroReplacements(psubInfo, "=");
|
||||
catMacroReplacements(psubInfo, psubFile->string);
|
||||
ppatternNode = (patternNode *) ellNext(&ppatternNode->node);
|
||||
++patternIt;
|
||||
}
|
||||
else {
|
||||
subFileErrPrint(psubFile, "Warning, too many values given");
|
||||
@@ -969,12 +921,12 @@ static char *substituteGetReplacements(subInfo *psubInfo)
|
||||
while (subGetNextToken(psubFile) == tokenSeparator);
|
||||
}
|
||||
}
|
||||
else while(1) {
|
||||
else while(true) {
|
||||
switch(subGetNextToken(psubFile)) {
|
||||
case tokenRBrace:
|
||||
subGetNextToken(psubFile);
|
||||
EXITS(psubInfo->macroReplacements);
|
||||
return psubInfo->macroReplacements;
|
||||
EXITS(psubInfo->macroReplacements.c_str());
|
||||
return psubInfo->macroReplacements.c_str();
|
||||
|
||||
case tokenSeparator:
|
||||
catMacroReplacements(psubInfo, ",");
|
||||
@@ -1017,11 +969,12 @@ static char *subGetNextLine(subFile *psubFile)
|
||||
return &psubFile->inputBuffer[0];
|
||||
}
|
||||
|
||||
static void subFileErrPrint(subFile *psubFile,char * message)
|
||||
static void subFileErrPrint(subFile *psubFile, const char * message)
|
||||
{
|
||||
fprintf(stderr, "msi: %s\n",message);
|
||||
fprintf(stderr, " in substitution file '%s' at line %d:\n %s",
|
||||
psubFile->substitutionName, psubFile->lineNum, psubFile->inputBuffer);
|
||||
psubFile->substitutionName.c_str(), psubFile->lineNum,
|
||||
psubFile->inputBuffer);
|
||||
}
|
||||
|
||||
|
||||
@@ -1107,32 +1060,8 @@ done:
|
||||
|
||||
static void catMacroReplacements(subInfo *psubInfo, const char *value)
|
||||
{
|
||||
size_t len = strlen(value);
|
||||
|
||||
ENTER;
|
||||
if (psubInfo->size <= (psubInfo->curLength + len)) {
|
||||
size_t newsize = psubInfo->size + MAX_BUFFER_SIZE;
|
||||
char *newbuf;
|
||||
|
||||
STEP("Enlarging buffer");
|
||||
if (newsize <= psubInfo->curLength + len)
|
||||
newsize = psubInfo->curLength + len + 1;
|
||||
newbuf = calloc(1, newsize);
|
||||
if (!newbuf) {
|
||||
fprintf(stderr, "calloc failed for size %lu\n",
|
||||
(unsigned long) newsize);
|
||||
abortExit(1);
|
||||
}
|
||||
if (psubInfo->macroReplacements) {
|
||||
memcpy(newbuf, psubInfo->macroReplacements, psubInfo->curLength);
|
||||
free(psubInfo->macroReplacements);
|
||||
}
|
||||
psubInfo->size = newsize;
|
||||
psubInfo->macroReplacements = newbuf;
|
||||
}
|
||||
|
||||
STEPS("Appending", value);
|
||||
strcat(psubInfo->macroReplacements, value);
|
||||
psubInfo->curLength += len;
|
||||
psubInfo->macroReplacements += value;
|
||||
EXIT;
|
||||
}
|
||||
@@ -241,7 +241,7 @@ Assuming there is a system state called "blue", that is being controlled by
|
||||
some other facility such as a timing system, updates could be restricted to
|
||||
periods only when "blue" is true by using
|
||||
|
||||
Hal$ camonitor 'test:channel' 'test:channel.{"while":"blue"}'
|
||||
Hal$ camonitor 'test:channel' 'test:channel.{"sync":{"while":"blue"}}'
|
||||
...
|
||||
|
||||
=cut
|
||||
|
||||
@@ -348,9 +348,9 @@ static long get_enum_strs(const DBADDR *paddr,struct dbr_enumStrs *pes)
|
||||
/*SETTING no_str=0 breaks channel access clients*/
|
||||
pes->no_str = 2;
|
||||
memset(pes->strs,'\0',sizeof(pes->strs));
|
||||
strncpy(pes->strs[0],prec->znam,sizeof(prec->znam));
|
||||
strncpy(pes->strs[0],prec->znam,sizeof(pes->strs[0]));
|
||||
if(*prec->znam!=0) pes->no_str=1;
|
||||
strncpy(pes->strs[1],prec->onam,sizeof(prec->onam));
|
||||
strncpy(pes->strs[1],prec->onam,sizeof(pes->strs[1]));
|
||||
if(*prec->onam!=0) pes->no_str=2;
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ static long special(DBADDR *, int);
|
||||
#define get_array_info NULL
|
||||
#define put_array_info NULL
|
||||
#define get_units NULL
|
||||
#define get_precision NULL
|
||||
static long get_precision(const DBADDR *, long *);
|
||||
#define get_enum_str NULL
|
||||
#define get_enum_strs NULL
|
||||
#define put_enum_str NULL
|
||||
@@ -204,6 +204,16 @@ static long special(DBADDR *paddr, int after)
|
||||
}
|
||||
}
|
||||
|
||||
static long get_precision(const DBADDR *paddr,long *precision)
|
||||
{
|
||||
mbbiDirectRecord *prec=(mbbiDirectRecord *)paddr->precord;
|
||||
if(dbGetFieldIndex(paddr)==mbbiDirectRecordVAL)
|
||||
*precision = prec->nobt;
|
||||
else
|
||||
recGblGetPrec(paddr,precision);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void monitor(mbbiDirectRecord *prec)
|
||||
{
|
||||
epicsUInt16 events = recGblResetAlarms(prec);
|
||||
|
||||
@@ -51,7 +51,7 @@ static long special(DBADDR *, int);
|
||||
#define get_array_info NULL
|
||||
#define put_array_info NULL
|
||||
#define get_units NULL
|
||||
#define get_precision NULL
|
||||
static long get_precision(const DBADDR *, long *);
|
||||
#define get_enum_str NULL
|
||||
#define get_enum_strs NULL
|
||||
#define put_enum_str NULL
|
||||
@@ -313,6 +313,16 @@ static long special(DBADDR *paddr, int after)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long get_precision(const DBADDR *paddr,long *precision)
|
||||
{
|
||||
mbboDirectRecord *prec=(mbboDirectRecord *)paddr->precord;
|
||||
if(dbGetFieldIndex(paddr)==mbboDirectRecordVAL)
|
||||
*precision = prec->nobt;
|
||||
else
|
||||
recGblGetPrec(paddr,precision);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void monitor(mbboDirectRecord *prec)
|
||||
{
|
||||
epicsUInt16 events = recGblResetAlarms(prec);
|
||||
|
||||
@@ -99,7 +99,7 @@ static void monitor(stateRecord *prec)
|
||||
monitor_mask = recGblResetAlarms(prec);
|
||||
if(strncmp(prec->oval,prec->val,sizeof(prec->val))) {
|
||||
db_post_events(prec,&(prec->val[0]),monitor_mask|DBE_VALUE|DBE_LOG);
|
||||
strncpy(prec->oval,prec->val,sizeof(prec->val));
|
||||
strncpy(prec->oval,prec->val,sizeof(prec->oval));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -121,8 +121,7 @@ static long init_record(struct dbCommon *pcommon, int pass)
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
strncpy(prec->oval, prec->val, sizeof(prec->val));
|
||||
strncpy(prec->oval, prec->val, sizeof(prec->oval));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -183,7 +182,7 @@ static void monitor(stringinRecord *prec)
|
||||
|
||||
if (strncmp(prec->oval, prec->val, sizeof(prec->val))) {
|
||||
monitor_mask |= DBE_VALUE | DBE_LOG;
|
||||
strncpy(prec->oval, prec->val, sizeof(prec->val));
|
||||
strncpy(prec->oval, prec->val, sizeof(prec->oval));
|
||||
}
|
||||
|
||||
if (prec->mpst == stringinPOST_Always)
|
||||
|
||||
@@ -126,8 +126,7 @@ static long init_record(struct dbCommon *pcommon, int pass)
|
||||
if(status)
|
||||
return status;
|
||||
}
|
||||
|
||||
strncpy(prec->oval, prec->val, sizeof(prec->val));
|
||||
strncpy(prec->oval, prec->val, sizeof(prec->oval));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -215,7 +214,7 @@ static void monitor(stringoutRecord *prec)
|
||||
|
||||
if (strncmp(prec->oval, prec->val, sizeof(prec->val))) {
|
||||
monitor_mask |= DBE_VALUE | DBE_LOG;
|
||||
strncpy(prec->oval, prec->val, sizeof(prec->val));
|
||||
strncpy(prec->oval, prec->val, sizeof(prec->oval));
|
||||
}
|
||||
|
||||
if (prec->mpst == stringoutPOST_Always)
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
use strict;
|
||||
use Test;
|
||||
|
||||
BEGIN {plan tests => 9}
|
||||
BEGIN {plan tests => 12}
|
||||
|
||||
# Check include/substitute command model
|
||||
ok(msi('-I .. ../t1-template.txt'), slurp('../t1-result.txt'));
|
||||
@@ -33,16 +33,9 @@ ok(msi('-S../t6-substitute.txt ../t6-template.txt'), slurp('../t6-result.txt'));
|
||||
|
||||
# Output option -o and verbose option -V
|
||||
my $out = 't7-output.txt';
|
||||
my $count = 5; # Try up to 5 times...
|
||||
my $result;
|
||||
do {
|
||||
unlink $out;
|
||||
msi("-I.. -V -o $out ../t1-template.txt");
|
||||
$result = slurp($out);
|
||||
print "# msi output file empty, retrying\n"
|
||||
if $result eq '';
|
||||
} while ($result eq '') && (--$count > 0);
|
||||
ok($result, slurp('../t7-result.txt'));
|
||||
unlink $out;
|
||||
msi("-I.. -V -o $out ../t1-template.txt");
|
||||
ok(slurp($out), slurp('../t7-result.txt'));
|
||||
|
||||
# Dependency generation, include/substitute model
|
||||
ok(msi('-I.. -D -o t8.txt ../t1-template.txt'), slurp('../t8-result.txt'));
|
||||
@@ -50,6 +43,17 @@ ok(msi('-I.. -D -o t8.txt ../t1-template.txt'), slurp('../t8-result.txt'));
|
||||
# Dependency generation, dbLoadTemplate format
|
||||
ok(msi('-I.. -D -ot9.txt -S ../t2-substitution.txt'), slurp('../t9-result.txt'));
|
||||
|
||||
# Substitution file, variable format, with 0 variable definitions
|
||||
ok(msi('-I. -I.. -S ../t10-substitute.txt'), slurp('../t10-result.txt'));
|
||||
|
||||
# Substitution file, pattern format, with 0 pattern definitions
|
||||
ok(msi('-I. -I.. -S ../t11-substitute.txt'), slurp('../t11-result.txt'));
|
||||
|
||||
# Substitution file, environment variable macros in template filename
|
||||
my %envs = (TEST_NO => 12, PREFIX => 't');
|
||||
@ENV{ keys %envs } = values %envs;
|
||||
ok(msi('-I. -I.. -S ../t12-substitute.txt'), slurp('../t12-result.txt'));
|
||||
delete @ENV{ keys %envs }; # Not really needed
|
||||
|
||||
# Test support routines
|
||||
|
||||
@@ -63,21 +67,8 @@ sub slurp {
|
||||
|
||||
sub msi {
|
||||
my ($args) = @_;
|
||||
my $nul = $^O eq 'MSWin32' ? 'NUL' : '/dev/null';
|
||||
my $msi = '@TOP@/bin/@ARCH@/msi';
|
||||
$msi .= '.exe' if ($^O eq 'MSWin32') || ($^O eq 'cygwin');
|
||||
my $result;
|
||||
if ($args =~ m/-o / && $args !~ m/-D/) {
|
||||
# An empty result is expected
|
||||
$result = `$msi $args`;
|
||||
}
|
||||
else {
|
||||
# Try up to 5 times, sometimes msi fails on Windows
|
||||
my $count = 5;
|
||||
do {
|
||||
$result = `$msi $args`;
|
||||
print "# result of '$msi $args' empty, retrying\n"
|
||||
if $result eq '';
|
||||
} while ($result eq '') && (--$count > 0);
|
||||
}
|
||||
return $result;
|
||||
$msi =~ tr(/)(\\) if $^O eq 'MSWin32';
|
||||
return `$msi $args 2>$nul`;
|
||||
}
|
||||
|
||||
4
modules/database/test/ioc/dbtemplate/t10-result.txt
Normal file
4
modules/database/test/ioc/dbtemplate/t10-result.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
# comment line
|
||||
a=$(a)
|
||||
# comment line
|
||||
a=gbl
|
||||
8
modules/database/test/ioc/dbtemplate/t10-substitute.txt
Normal file
8
modules/database/test/ioc/dbtemplate/t10-substitute.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
file t10-template.txt {
|
||||
{}
|
||||
}
|
||||
|
||||
global { a=gbl }
|
||||
file t10-template.txt {
|
||||
{}
|
||||
}
|
||||
2
modules/database/test/ioc/dbtemplate/t10-template.txt
Normal file
2
modules/database/test/ioc/dbtemplate/t10-template.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
# comment line
|
||||
a=$(a)
|
||||
4
modules/database/test/ioc/dbtemplate/t11-result.txt
Normal file
4
modules/database/test/ioc/dbtemplate/t11-result.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
# comment line
|
||||
a=$(a)
|
||||
# comment line
|
||||
a=gbl
|
||||
10
modules/database/test/ioc/dbtemplate/t11-substitute.txt
Normal file
10
modules/database/test/ioc/dbtemplate/t11-substitute.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
file t11-template.txt {
|
||||
pattern {}
|
||||
{}
|
||||
}
|
||||
|
||||
global { a=gbl }
|
||||
file t11-template.txt {
|
||||
pattern {}
|
||||
{}
|
||||
}
|
||||
2
modules/database/test/ioc/dbtemplate/t11-template.txt
Normal file
2
modules/database/test/ioc/dbtemplate/t11-template.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
# comment line
|
||||
a=$(a)
|
||||
2
modules/database/test/ioc/dbtemplate/t12-result.txt
Normal file
2
modules/database/test/ioc/dbtemplate/t12-result.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
# comment line
|
||||
a=foo
|
||||
3
modules/database/test/ioc/dbtemplate/t12-substitute.txt
Normal file
3
modules/database/test/ioc/dbtemplate/t12-substitute.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
file $(PREFIX)$(TEST_NO)-template.txt {
|
||||
{ a=foo }
|
||||
}
|
||||
2
modules/database/test/ioc/dbtemplate/t12-template.txt
Normal file
2
modules/database/test/ioc/dbtemplate/t12-template.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
# comment line
|
||||
a=$(a)
|
||||
@@ -1,4 +1,4 @@
|
||||
EPICS_LIBCOM_MAJOR_VERSION = 3
|
||||
EPICS_LIBCOM_MINOR_VERSION = 17
|
||||
EPICS_LIBCOM_MAINTENANCE_VERSION = 3
|
||||
EPICS_LIBCOM_MAINTENANCE_VERSION = 5
|
||||
EPICS_LIBCOM_DEVELOPMENT_FLAG = 0
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
static unsigned short ioc_log_port;
|
||||
static long ioc_log_file_limit;
|
||||
static char ioc_log_file_name[256];
|
||||
static char ioc_log_file_name[512];
|
||||
static char ioc_log_file_command[256];
|
||||
|
||||
|
||||
@@ -866,7 +866,12 @@ static int setupSIGHUP(struct ioc_log_server *pserver)
|
||||
*/
|
||||
static void sighupHandler(int signo)
|
||||
{
|
||||
(void) write(sighupPipe[1], "SIGHUP\n", 7);
|
||||
const char msg[] = "SIGHUP\n";
|
||||
const ssize_t bytesWritten = write(sighupPipe[1], msg, sizeof(msg));
|
||||
if (bytesWritten != sizeof(msg)) {
|
||||
fprintf(stderr, "iocLogServer: failed to write to SIGHUP pipe because "
|
||||
"`%s'\n", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -884,7 +889,10 @@ static void serviceSighupRequest(void *pParam)
|
||||
/*
|
||||
* Read and discard message from pipe.
|
||||
*/
|
||||
(void) read(sighupPipe[0], buff, sizeof buff);
|
||||
if (read(sighupPipe[0], buff, sizeof buff) <= 0) {
|
||||
fprintf(stderr, "iocLogServer: failed to read from SIGHUP pipe because "
|
||||
"`%s'\n", strerror(errno));
|
||||
};
|
||||
|
||||
/*
|
||||
* Determine new log file name.
|
||||
|
||||
@@ -171,6 +171,7 @@ ipAddrToAsciiEngine & ipAddrToAsciiEngine::allocate ()
|
||||
}
|
||||
|
||||
ipAddrToAsciiGlobal::ipAddrToAsciiGlobal () :
|
||||
mutex(__FILE__, __LINE__),
|
||||
thread ( *this, "ipToAsciiProxy",
|
||||
epicsThreadGetStackSize(epicsThreadStackBig),
|
||||
epicsThreadPriorityLow ),
|
||||
|
||||
@@ -78,6 +78,11 @@ static epicsThreadOnceId onceId = EPICS_THREAD_ONCE_INIT;
|
||||
|
||||
static const char * const tsfmt = "%Y-%m-%d %H:%M:%S.%09f";
|
||||
|
||||
/* defined in osiClockTime.c or osdTime.cpp */
|
||||
int osdTimeGetCurrent ( epicsTimeStamp *pDest );
|
||||
/* cleared if/when gtPvt.timeProviders contains more than the default osdTimeGetCurrent() */
|
||||
static int useOsdGetCurrent = 1;
|
||||
|
||||
/* Implementation */
|
||||
|
||||
static void generalTime_InitOnce(void *dummy)
|
||||
@@ -103,6 +108,9 @@ int generalTimeGetExceptPriority(epicsTimeStamp *pDest, int *pPrio, int ignore)
|
||||
gtProvider *ptp;
|
||||
int status = S_time_noProvider;
|
||||
|
||||
if(useOsdGetCurrent)
|
||||
return osdTimeGetCurrent(pDest);
|
||||
|
||||
generalTime_Init();
|
||||
|
||||
IFDEBUG(2)
|
||||
@@ -148,6 +156,9 @@ int epicsShareAPI epicsTimeGetCurrent(epicsTimeStamp *pDest)
|
||||
int status = S_time_noProvider;
|
||||
epicsTimeStamp ts;
|
||||
|
||||
if(useOsdGetCurrent)
|
||||
return osdTimeGetCurrent(pDest);
|
||||
|
||||
generalTime_Init();
|
||||
|
||||
IFDEBUG(20)
|
||||
@@ -370,6 +381,11 @@ static void insertProvider(gtProvider *ptp, ELLLIST *plist, epicsMutexId lock)
|
||||
ellAdd(plist, &ptp->node);
|
||||
}
|
||||
|
||||
/* Check to see if we have more than just the OS default time source */
|
||||
if(plist==>Pvt.timeProviders && (ellCount(plist)!=1 || ptp->get.Time!=&osdTimeGetCurrent)) {
|
||||
useOsdGetCurrent = 0;
|
||||
}
|
||||
|
||||
epicsMutexUnlock(lock);
|
||||
}
|
||||
|
||||
|
||||
@@ -205,9 +205,6 @@ epicsTime::epicsTime (const epicsTimeStamp &ts)
|
||||
epicsTime::epicsTime () :
|
||||
secPastEpoch(0u), nSec(0u) {}
|
||||
|
||||
epicsTime::epicsTime (const epicsTime &t) :
|
||||
secPastEpoch (t.secPastEpoch), nSec (t.nSec) {}
|
||||
|
||||
epicsTime epicsTime::getCurrent ()
|
||||
{
|
||||
epicsTimeStamp current;
|
||||
|
||||
@@ -82,7 +82,6 @@ public:
|
||||
class formatProblemWithStructTM {};
|
||||
|
||||
epicsTime ();
|
||||
epicsTime ( const epicsTime & t );
|
||||
|
||||
static epicsTime getEvent ( const epicsTimeEvent & );
|
||||
static epicsTime getCurrent ();
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
static clock_serv_t host_clock;
|
||||
|
||||
extern "C" {
|
||||
static int osdTimeGetCurrent (epicsTimeStamp *pDest)
|
||||
int osdTimeGetCurrent (epicsTimeStamp *pDest)
|
||||
{
|
||||
mach_timespec_t mts;
|
||||
struct timespec ts;
|
||||
|
||||
@@ -47,7 +47,8 @@
|
||||
|
||||
extern "C" void setThreadName ( DWORD dwThreadID, LPCSTR szThreadName );
|
||||
|
||||
static int osdTimeGetCurrent ( epicsTimeStamp *pDest );
|
||||
extern "C"
|
||||
int osdTimeGetCurrent ( epicsTimeStamp *pDest );
|
||||
|
||||
// for mingw
|
||||
#if !defined ( MAXLONGLONG )
|
||||
@@ -116,7 +117,7 @@ static int done = timeRegister();
|
||||
//
|
||||
// osdTimeGetCurrent ()
|
||||
//
|
||||
static int osdTimeGetCurrent ( epicsTimeStamp *pDest )
|
||||
int osdTimeGetCurrent ( epicsTimeStamp *pDest )
|
||||
{
|
||||
assert ( pCurrentTime );
|
||||
|
||||
|
||||
@@ -7,12 +7,30 @@
|
||||
* Author: Till Straumann <strauman@slac.stanford.edu>, 2011, 2014
|
||||
*/
|
||||
|
||||
// pull in libc feature test macros
|
||||
#include <stdlib.h>
|
||||
|
||||
// execinfo.h may not be present if uclibc is configured to omit backtrace()
|
||||
#if !defined(__UCLIBC_MAJOR__) || defined(__UCLIBC_HAS_EXECINFO__)
|
||||
# define HAS_EXECINFO 1
|
||||
#else
|
||||
# define HAS_EXECINFO 0
|
||||
#endif
|
||||
|
||||
#if HAS_EXECINFO
|
||||
|
||||
#include <execinfo.h>
|
||||
|
||||
#endif
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "epicsStackTracePvt.h"
|
||||
|
||||
int epicsBackTrace(void **buf, int buf_sz)
|
||||
{
|
||||
#if HAS_EXECINFO
|
||||
return backtrace(buf, buf_sz);
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -153,6 +153,10 @@ epicsMutexLockStatus epicsMutexOsdTryLock(struct epicsMutexOSD * pmutex)
|
||||
|
||||
void epicsMutexOsdShow(struct epicsMutexOSD * pmutex, unsigned int level)
|
||||
{
|
||||
/* GLIBC w/ NTPL is passing the &lock.__data.__lock as the first argument (UADDR)
|
||||
* of the futex() syscall. __lock is at offset 0 of the enclosing structures.
|
||||
*/
|
||||
printf(" pthread_mutex_t* uaddr=%p\n", &pmutex->lock);
|
||||
}
|
||||
|
||||
#else /*defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE)>=500 */
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
LAST_RESORT_PRIORITY, osdTimeGetCurrent)
|
||||
|
||||
extern "C" {
|
||||
static int osdTimeGetCurrent (epicsTimeStamp *pDest)
|
||||
int osdTimeGetCurrent (epicsTimeStamp *pDest)
|
||||
{
|
||||
struct timeval tv;
|
||||
struct timezone tz;
|
||||
|
||||
@@ -65,7 +65,7 @@ typedef int SOCKET;
|
||||
#define socket_ioctl(A,B,C) ioctl(A,B,(int)C)
|
||||
typedef int osiSockIoctl_t;
|
||||
typedef int osiSocklen_t;
|
||||
typedef int osiSockOptMcastLoop_t;
|
||||
typedef char osiSockOptMcastLoop_t;
|
||||
typedef char osiSockOptMcastTTL_t;
|
||||
|
||||
#define FD_IN_FDSET(FD) ((FD)<FD_SETSIZE&&(FD)>=0)
|
||||
|
||||
@@ -40,7 +40,7 @@ static struct {
|
||||
static epicsThreadOnceId onceId = EPICS_THREAD_ONCE_INIT;
|
||||
|
||||
|
||||
#if defined(CLOCK_REALTIME) && !defined(_WIN32)
|
||||
#if defined(CLOCK_REALTIME) && !defined(_WIN32) && !defined(__APPLE__)
|
||||
/* This code is not used on systems without Posix CLOCK_REALTIME,
|
||||
* but the only way to detect that is from the OS headers, so the
|
||||
* Makefile can't exclude compiling this file on those systems.
|
||||
@@ -48,7 +48,7 @@ static epicsThreadOnceId onceId = EPICS_THREAD_ONCE_INIT;
|
||||
|
||||
/* Forward references */
|
||||
|
||||
static int ClockTimeGetCurrent(epicsTimeStamp *pDest);
|
||||
int osdTimeGetCurrent(epicsTimeStamp *pDest);
|
||||
|
||||
#if defined(vxWorks) || defined(__rtems__)
|
||||
static void ClockTimeSync(void *dummy);
|
||||
@@ -89,7 +89,7 @@ static void ClockTime_InitOnce(void *pfirst)
|
||||
|
||||
/* Register as a time provider */
|
||||
generalTimeRegisterCurrentProvider("OS Clock", LAST_RESORT_PRIORITY,
|
||||
ClockTimeGetCurrent);
|
||||
osdTimeGetCurrent);
|
||||
}
|
||||
|
||||
void ClockTime_Init(int synchronize)
|
||||
@@ -125,7 +125,7 @@ void ClockTime_Init(int synchronize)
|
||||
else {
|
||||
/* No synchronization thread */
|
||||
if (firstTime)
|
||||
ClockTimeGetCurrent(&ClockTimePvt.startTime);
|
||||
osdTimeGetCurrent(&ClockTimePvt.startTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -191,7 +191,7 @@ static void ClockTimeSync(void *dummy)
|
||||
|
||||
/* Time Provider Routine */
|
||||
|
||||
static int ClockTimeGetCurrent(epicsTimeStamp *pDest)
|
||||
int osdTimeGetCurrent(epicsTimeStamp *pDest)
|
||||
{
|
||||
struct timespec clockNow;
|
||||
|
||||
|
||||
@@ -147,7 +147,7 @@ private:
|
||||
epicsThread thread;
|
||||
const double sleepQuantum;
|
||||
bool okToShare;
|
||||
bool exitFlag;
|
||||
int exitFlag; // use atomic ops
|
||||
bool terminateFlag;
|
||||
void run ();
|
||||
void reschedule ();
|
||||
|
||||
@@ -25,6 +25,7 @@ const double timerQueue :: exceptMsgMinPeriod = 60.0 * 5.0; // seconds
|
||||
epicsTimerQueue::~epicsTimerQueue () {}
|
||||
|
||||
timerQueue::timerQueue ( epicsTimerQueueNotify & notifyIn ) :
|
||||
mutex(__FILE__, __LINE__),
|
||||
notify ( notifyIn ),
|
||||
pExpireTmr ( 0 ),
|
||||
processThread ( 0 ),
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "epicsAtomic.h"
|
||||
#include "timerPrivate.h"
|
||||
#include "errlog.h"
|
||||
|
||||
@@ -46,7 +47,7 @@ timerQueueActive ::
|
||||
_refMgr ( refMgr ), queue ( *this ), thread ( *this, "timerQueue",
|
||||
epicsThreadGetStackSize ( epicsThreadStackMedium ), priority ),
|
||||
sleepQuantum ( epicsThreadSleepQuantum() ), okToShare ( okToShareIn ),
|
||||
exitFlag ( false ), terminateFlag ( false )
|
||||
exitFlag ( 0 ), terminateFlag ( false )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -59,7 +60,7 @@ timerQueueActive::~timerQueueActive ()
|
||||
{
|
||||
this->terminateFlag = true;
|
||||
this->rescheduleEvent.signal ();
|
||||
while ( ! this->exitFlag ) {
|
||||
while ( ! epics::atomic::get(this->exitFlag) ) {
|
||||
this->exitEvent.wait ( 1.0 );
|
||||
}
|
||||
// in case other threads are waiting here also
|
||||
@@ -87,7 +88,7 @@ void timerQueueActive :: _printLastChanceExceptionMessage (
|
||||
|
||||
void timerQueueActive :: run ()
|
||||
{
|
||||
this->exitFlag = false;
|
||||
epics::atomic::set(this->exitFlag, 0);
|
||||
while ( ! this->terminateFlag ) {
|
||||
try {
|
||||
double delay = this->queue.process ( epicsTime::getCurrent() );
|
||||
@@ -105,7 +106,7 @@ void timerQueueActive :: run ()
|
||||
epicsThreadSleep ( 10.0 );
|
||||
}
|
||||
}
|
||||
this->exitFlag = true;
|
||||
epics::atomic::set(this->exitFlag, 1);
|
||||
this->exitEvent.signal (); // no access to queue after exitEvent signal
|
||||
}
|
||||
|
||||
@@ -143,7 +144,7 @@ void timerQueueActive::show ( unsigned int level ) const
|
||||
printf ( "exit event\n" );
|
||||
this->exitEvent.show ( level - 1u );
|
||||
printf ( "exitFlag = %c, terminateFlag = %c\n",
|
||||
this->exitFlag ? 'T' : 'F',
|
||||
epics::atomic::get(this->exitFlag) ? 'T' : 'F',
|
||||
this->terminateFlag ? 'T' : 'F' );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "timerPrivate.h"
|
||||
|
||||
timerQueueActiveMgr::timerQueueActiveMgr ()
|
||||
:mutex(__FILE__, __LINE__)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -255,8 +255,8 @@ TESTSPEC_RTEMS = libComTestHarness.boot; epicsRunLibComTests
|
||||
|
||||
TESTSCRIPTS_HOST += $(TESTS:%=%.t)
|
||||
ifneq ($(filter $(T_A),$(CROSS_COMPILER_RUNTEST_ARCHS)),)
|
||||
TESTPROD_RTEMS = $(TESTPROD_HOST)
|
||||
TESTSCRIPTS_RTEMS += $(filter-out epicsUnitTestTest.t, $(TESTS:%=%.t))
|
||||
TESTPROD = $(TESTPROD_HOST)
|
||||
TESTSCRIPTS += $(filter-out epicsUnitTestTest.t, $(TESTS:%=%.t))
|
||||
endif
|
||||
|
||||
|
||||
|
||||
@@ -78,6 +78,7 @@ typedef struct {
|
||||
size_t checkLen;
|
||||
epicsEventId jammer;
|
||||
int jam;
|
||||
epicsEventId done;
|
||||
} clientPvt;
|
||||
|
||||
static void testLogPrefix(void);
|
||||
@@ -102,12 +103,13 @@ static const char prefixexpectedmsg[] = "A message without prefix"
|
||||
static char prefixmsgbuffer[1024];
|
||||
|
||||
|
||||
static
|
||||
void testEqInt_(int lhs, int rhs, const char *LHS, const char *RHS)
|
||||
static void
|
||||
testEqInt_(int line, int lhs, int rhs, const char *LHS, const char *RHS)
|
||||
{
|
||||
testOk(lhs==rhs, "%s (%d) == %s (%d)", LHS, lhs, RHS, rhs);
|
||||
testOk(lhs==rhs, "%d: %s (%d) == %s (%d)", line, LHS, lhs, RHS, rhs);
|
||||
}
|
||||
#define testEqInt(L, R) testEqInt_(L, R, #L, #R);
|
||||
#define testEqInt(L, R) testEqInt_(__LINE__, L, R, #L, #R);
|
||||
|
||||
static
|
||||
void logClient(void* raw, const char* msg)
|
||||
{
|
||||
@@ -161,6 +163,7 @@ void logClient(void* raw, const char* msg)
|
||||
}
|
||||
|
||||
pvt->count++;
|
||||
epicsEventSignal(pvt->done);
|
||||
}
|
||||
|
||||
MAIN(epicsErrlogTest)
|
||||
@@ -169,7 +172,7 @@ MAIN(epicsErrlogTest)
|
||||
char msg[256];
|
||||
clientPvt pvt, pvt2;
|
||||
|
||||
testPlan(32);
|
||||
testPlan(40);
|
||||
|
||||
strcpy(msg, truncmsg);
|
||||
|
||||
@@ -188,7 +191,9 @@ MAIN(epicsErrlogTest)
|
||||
pvt2.jam = 0;
|
||||
|
||||
pvt.jammer = epicsEventMustCreate(epicsEventEmpty);
|
||||
pvt.done = epicsEventMustCreate(epicsEventEmpty);
|
||||
pvt2.jammer = epicsEventMustCreate(epicsEventEmpty);
|
||||
pvt2.done = epicsEventMustCreate(epicsEventEmpty);
|
||||
|
||||
testDiag("Check listener registration");
|
||||
|
||||
@@ -200,6 +205,7 @@ MAIN(epicsErrlogTest)
|
||||
errlogPrintfNoConsole("%s", pvt.expect);
|
||||
errlogFlush();
|
||||
|
||||
epicsEventMustWait(pvt.done);
|
||||
testEqInt(pvt.count, 1);
|
||||
|
||||
errlogAddListener(&logClient, &pvt2);
|
||||
@@ -210,7 +216,10 @@ MAIN(epicsErrlogTest)
|
||||
errlogPrintfNoConsole("%s", pvt.expect);
|
||||
errlogFlush();
|
||||
|
||||
epicsEventMustWait(pvt.done);
|
||||
testEqInt(pvt.count, 2);
|
||||
|
||||
epicsEventMustWait(pvt2.done);
|
||||
testEqInt(pvt2.count, 1);
|
||||
|
||||
/* Removes the first listener */
|
||||
@@ -223,6 +232,10 @@ MAIN(epicsErrlogTest)
|
||||
errlogPrintfNoConsole("%s", pvt2.expect);
|
||||
errlogFlush();
|
||||
|
||||
testOk(epicsEventWaitWithTimeout(pvt.done, 0.5) == epicsEventWaitTimeout,
|
||||
"%d: Listener 1 didn't run", __LINE__);
|
||||
testOk(epicsEventTryWait(pvt2.done) == epicsEventOK,
|
||||
"%d: Listener 2 ran", __LINE__);
|
||||
testEqInt(pvt.count, 2);
|
||||
testEqInt(pvt2.count, 2);
|
||||
|
||||
@@ -234,6 +247,10 @@ MAIN(epicsErrlogTest)
|
||||
errlogPrintfNoConsole("Something different");
|
||||
errlogFlush();
|
||||
|
||||
testOk(epicsEventWaitWithTimeout(pvt.done, 0.5) == epicsEventWaitTimeout,
|
||||
"%d: Listener 1 didn't run", __LINE__);
|
||||
testOk(epicsEventTryWait(pvt2.done) == epicsEventWaitTimeout,
|
||||
"%d: Listener 2 didn't run", __LINE__);
|
||||
testEqInt(pvt.count, 2);
|
||||
testEqInt(pvt2.count, 2);
|
||||
|
||||
@@ -248,6 +265,7 @@ MAIN(epicsErrlogTest)
|
||||
errlogPrintfNoConsole("%s", longmsg);
|
||||
errlogFlush();
|
||||
|
||||
epicsEventMustWait(pvt.done);
|
||||
testEqInt(pvt.count, 3);
|
||||
|
||||
pvt.expect = NULL;
|
||||
@@ -259,13 +277,15 @@ MAIN(epicsErrlogTest)
|
||||
pvt.jam = 1;
|
||||
|
||||
errlogPrintfNoConsole("%s", longmsg);
|
||||
epicsThreadSleep(0.1);
|
||||
|
||||
testOk(epicsEventWaitWithTimeout(pvt.done, 0.5) == epicsEventWaitTimeout,
|
||||
"%d: Listener 1 didn't run", __LINE__);
|
||||
testEqInt(pvt.count, 3);
|
||||
|
||||
epicsEventSignal(pvt.jammer);
|
||||
errlogFlush();
|
||||
|
||||
epicsEventMustWait(pvt.done);
|
||||
testEqInt(pvt.count, 4);
|
||||
|
||||
testDiag("Find buffer capacity (%u theoretical)",LOGBUFSIZE);
|
||||
@@ -303,6 +323,9 @@ MAIN(epicsErrlogTest)
|
||||
errlogFlush();
|
||||
}
|
||||
|
||||
testOk(epicsEventTryWait(pvt.done) == epicsEventOK,
|
||||
"%d: Listener 1 ran", __LINE__);
|
||||
|
||||
testDiag("Checking buffer use after partial flush");
|
||||
|
||||
/* Use the numbers from the largest block size above */
|
||||
@@ -317,16 +340,18 @@ MAIN(epicsErrlogTest)
|
||||
for (i = 0; i < N; i++) {
|
||||
errlogPrintfNoConsole("%s", msg);
|
||||
}
|
||||
epicsThreadSleep(0.1); /* should really be a second Event */
|
||||
|
||||
testOk(epicsEventWaitWithTimeout(pvt.done, 0.5) == epicsEventWaitTimeout,
|
||||
"%d: Listener 1 didn't run", __LINE__);
|
||||
testEqInt(pvt.count, 0);
|
||||
|
||||
/* Extract the first 2 messages, 2*(sizeof(msgNode) + 128) bytes */
|
||||
pvt.jam = -2;
|
||||
epicsEventSignal(pvt.jammer);
|
||||
epicsThreadSleep(0.1);
|
||||
epicsThreadSleep(0.5);
|
||||
|
||||
testDiag("Drained %u messages", pvt.count);
|
||||
epicsEventMustWait(pvt.done);
|
||||
testEqInt(pvt.count, 2);
|
||||
|
||||
/* The buffer has space for 1 more message: sizeof(msgNode) + 256 bytes */
|
||||
@@ -335,12 +360,15 @@ MAIN(epicsErrlogTest)
|
||||
testDiag("Overflow the buffer");
|
||||
errlogPrintfNoConsole("%s", msg);
|
||||
|
||||
testOk(epicsEventWaitWithTimeout(pvt.done, 0.5) == epicsEventWaitTimeout,
|
||||
"%d: Listener 1 didn't run", __LINE__);
|
||||
testEqInt(pvt.count, 2);
|
||||
|
||||
epicsEventSignal(pvt.jammer); /* Empty */
|
||||
errlogFlush();
|
||||
|
||||
testDiag("Logged %u messages", pvt.count);
|
||||
epicsEventMustWait(pvt.done);
|
||||
testEqInt(pvt.count, N+1);
|
||||
|
||||
/* Clean up */
|
||||
|
||||
@@ -381,8 +381,14 @@ MAIN(epicsStdlibTest)
|
||||
|
||||
testOk(epicsParseFloat("1e-40", &f, NULL) == S_stdlib_underflow,
|
||||
"Float '1e-40' => underflow");
|
||||
#ifdef vxWorks
|
||||
testTodoBegin("Not detected on VxWorks");
|
||||
#endif
|
||||
testOk(epicsParseDouble("1e-330", &d, NULL) == S_stdlib_underflow,
|
||||
"Double '1e-330' => underflow");
|
||||
#ifdef vxWorks
|
||||
testTodoEnd();
|
||||
#endif
|
||||
|
||||
testOk(epicsScanFloat("1e30", &f) && fabs(f - 1e30) < 1e24,
|
||||
"Float '1e30'");
|
||||
|
||||
@@ -108,11 +108,11 @@ inline double delayVerify::delay () const
|
||||
|
||||
double delayVerify::checkError () const
|
||||
{
|
||||
const double messageThresh = 2.0; // percent
|
||||
const double messageThresh = 5.0; // percent
|
||||
double actualDelay = this->expireStamp - this->beginStamp;
|
||||
double measuredError = actualDelay - this->expectedDelay;
|
||||
double percentError = 100.0 * fabs ( measuredError ) / this->expectedDelay;
|
||||
if ( ! testOk1 ( percentError < messageThresh ) ) {
|
||||
if ( ! testOk ( percentError < messageThresh, "%f < %f", percentError, messageThresh ) ) {
|
||||
testDiag ( "delay = %f s, error = %f s (%.1f %%)",
|
||||
this->expectedDelay, measuredError, percentError );
|
||||
}
|
||||
|
||||
Submodule modules/normativeTypes updated: e803240fbf...c6168a7477
Submodule modules/pvAccess updated: 78410499f0...936f5d35d8
Submodule modules/pvData updated: 8c275cbc1c...6ceaa6adb0
Submodule modules/pvDatabase updated: b3f96f730f...70ee857782
Submodule modules/pva2pva updated: 521154fd52...ce39c93201
Submodule modules/pvaClient updated: b1c101578b...aba40922e6
Reference in New Issue
Block a user