Compare commits

...

63 Commits

Author SHA1 Message Date
Andrew Johnson
ed37ace27e R3.15.1 2014-12-01 15:07:38 -06:00
Andrew Johnson
bc15875bfb Merge changes from 3.14 branch, revno 12507 2014-12-01 12:29:30 -06:00
Andrew Johnson
69eaaa17ba Fix xsubpp for RHEL 7 and derivatives.
It got moved. This might not be the final fix for those using an
add-on version of Perl though...
2014-12-01 12:12:09 -06:00
Andrew Johnson
30b789aa49 Fix epicsStrnEscapedFromRaw() and epicsStrnRawFromEscaped()
Major rewrites; the original epicsStrnRawFromEscaped() could read
beyond the end of the input buffer if the input count ended in the
middle of an octal or hex escape sequence. Zero termination did not
always match the return count, and hex escapes were always 2 digits,
contrary to the C standard.

New versions don't use epicsSnprintf() or sscanf() for hex and octal
conversions, so should be slightly faster.

Added 81 new tests to check the above issues.
2014-12-01 11:34:58 -06:00
Ralph Lange
1a94ea1045 libCom/osi: fix - do not set the main thread's Linux name to _main_ (linux) 2014-12-01 13:48:10 +01:00
Andrew Johnson
f1dec35c5c Update KnownProblems list 2014-11-19 16:00:31 -06:00
Andrew Johnson
6e8a3fcd6d Set version snapshot to -rc1-DEV 2014-11-19 15:35:12 -06:00
Andrew Johnson
ec35ef7136 Update version numbers for 3.15.1-rc1 2014-11-19 15:34:02 -06:00
Andrew Johnson
fce8377156 Merge change from 3.14 branch
Up to revno 12506
2014-11-19 15:18:11 -06:00
Andrew Johnson
5c4def1632 Build issues for iOS 2014-11-19 13:57:55 -06:00
Andrew Johnson
bdc57ecb2b Build issues for MinWG 2014-11-19 13:16:56 -06:00
Andrew Johnson
fd3bf215c5 Added missing tests to epicsRunDbTests.c 2014-11-19 10:22:39 -06:00
Ralph Lange
ba922d2bfa ioc/db: fix segfault in dbcaStats when disconnected CA links are present 2014-11-19 15:11:36 +01:00
Ralph Lange
cd8e08651b ioc/db/test: add a test for dbcaStats (detects bug lp:1394212) 2014-11-19 15:08:48 +01:00
Ralph Lange
0627aa5712 std/rec/test: extend arrayOpTest to cover an array of size 1 (detects bug lp:1389298) 2014-11-19 09:59:34 +01:00
Andrew Johnson
adc6219c2a scanIoTest: Extend time for callback threads to run.
Needed for VxWorks 5.5.2 on 68K
2014-11-18 18:10:19 -06:00
Andrew Johnson
a99f1d238e Cleaned up VxWorks 6.9 symLib warnings
VxWorks 6.9 deprecated several symFindBy...() routines, which
result in warning messages at build-time. I rewrote the code
that uses these to use the newer API on VxWorks 6.9.

Also deprecated the two epicsDynLink.h symFindByNameEPICS()
and symFindByNameAndTypeEPICS() routines; epicsFindSymbol() in
epicsFindSymbol.h is now available on most platforms instead.
2014-11-18 17:46:41 -06:00
Andrew Johnson
09797ee7ca Fix ringPointerTest thread priority issue on VxWorks
Picked a priority somewhere in the middle and switch to
that for the two test subroutines that care.
2014-11-18 17:30:43 -06:00
Andrew Johnson
01c0275876 Build stability fixes
Change menuGlobal.dbd and stdRecords.dbd to be generated
as a list of unexpanded include statements, not expanded
out as they have been recently on this branch. This means
any .dbd.pod files in those lists don't have to have been
filtered to remove the POD statements which significantly
simplifies the dependency graph. I had experienced build
loops at times, which this change should prevent.
2014-11-18 14:01:46 -06:00
Michael Davidsaver
d7269f9d80 Revert "dbBkpt: atexit" 2014-11-18 14:56:45 -05:00
Michael Davidsaver
58cd1d0a71 errlog: Don't free globals.
Since the pvtData.atExit flag doesn't prevent all
concurrent use of the pvtData struct we can't safely
free it.
2014-11-18 14:48:15 -05:00
Michael Davidsaver
e4954ba26a dbLock: remove dbLockExit()
No benefit to freeing global locks in unittests,
and this could cause problems with normal IOC
shutdown.
2014-11-18 14:48:15 -05:00
Andrew Johnson
60a5c476b3 Fix single-element array problem
An array field with a maximum size of 1 element would not be
treated as an array, so the record's rset::get_array_info()
routine wasn't being called. Fixed in dbAccess for both
dbGet() and dbPut() operations, and in dbEvent for monitors.

Fixes lp:1389298
2014-11-18 11:10:01 -06:00
Michael Davidsaver
9e63a51707 pcas: avoid reinterpret_cast with sockaddr
Avoid warning about breaking aliasing rules
2014-11-18 11:48:53 -05:00
Michael Davidsaver
93149071b7 dbNotify: shutdown with exitDatabase
Can't cleanup dbNotify while rsrv or scan tasks
are running as there may be operations in progress.
2014-11-18 11:25:15 -05:00
Michael Davidsaver
9c2a62ea96 dbChannel: shutdown from exitDatabase()
Can't cleanup dbChannel while rsrv or scan tasks
remain running.
2014-11-18 11:25:15 -05:00
Andrew Johnson
ae7b8c7aa3 configure: Windows-x64 architecture fixes
* Removed /favor:blend from ARCH_DEP_CPPFLAGS
  It is the default anyway, and including it stops the
  MS Express compilers from building 64-bit executables.
* Added a CONFIG_SITE.Common.windows-x64-static file.
  The MSVS 2010 linker crashes when when generating code
  for this target with HOST_OPT = YES, so make it NO.
2014-11-18 09:51:28 -06:00
Ralph Lange
ac2ff29abb libCom/log: make iocLog client unregister its listener from errlog on shutdown 2014-11-18 15:23:14 +01:00
Michael Davidsaver
f9d0fd351d libCom/test: fix ringPointerTest compile issues on vxWorks and MSVC
Remove C GNU-isms
1) mixing code/variable defs
2) arithmetic on void*
2014-11-17 18:55:47 -05:00
Michael Davidsaver
66fbbbb19a libCom/test: re-write ringPointerTest 2014-11-17 16:51:57 -05:00
Andrew Johnson
89777707c4 cap5: Minor build change on Darwin 2014-11-17 10:56:28 -06:00
Andrew Johnson
4c66f7f2d9 configure: Removed obselete 3.13 compatibility build rule 2014-11-13 17:02:10 -06:00
Michael Davidsaver
924350b362 epicsExit: add epicsExitLater() to trigger process exit without blocking 2014-11-13 11:58:35 -05:00
Michael Davidsaver
d35780888a iocInit: only teardown from iocBuildIsolated()
iocShutdown() should only stop threads and cleanup
if the IOC was started with iocBuildIsolated().
If iocBuild() is used then only close CA links
as was done previously.

This is needed as some device support calls epicsExit()
(while holding a record lock).  This make it impossible
to run the full iocShutdown without deadlocking
in scan/callback shutdown, or segfaulting
in doFreeRecord() or dbLockCleanupRecords()
2014-11-13 11:58:35 -05:00
Andrew Johnson
f7cc0e2d09 Various build system issues
* Removed broken Windows source browser rules and 'browse' targets
* Fixed parallel build issue for Make > 3.81
* Other tidying-up in RULES_ARCHS
* Fix the RTEMS override of the ECHO variable
2014-11-12 16:36:39 -06:00
Andrew Johnson
5554dfd66d Make shared library version numbers use 3 components 2014-11-11 12:57:00 -06:00
Andrew Johnson
69daab81d5 Fix tests after menuScan changes 2014-11-10 17:27:38 -06:00
Andrew Johnson
3aa5d2adee ioc/db menu fixes
* Move including menuScan.dbd from menuGlobal.dbd to base.dbd.
  Menus included in menuGlobal.dbd can't be overridden at build
  time since it gets fully expanded before installation.
* Convert .dbd.pod files before generating menuGlobal.dbd.d
* Remove menuCompress.dbd, nothing in Base uses it any more.
  The compress record has its own compressALG menu
2014-11-10 16:15:52 -06:00
Andrew Johnson
574bac67b4 CAref reformatting/prettification from 3.14 2014-11-08 10:22:03 -06:00
Andrew Johnson
3d03822043 CAref reformatting/prettification 2014-11-08 10:19:59 -06:00
Andrew Johnson
6f7fc7bf8e Merged changes from 3.14 branch
Up to revno 12504.
2014-11-07 15:57:13 -06:00
Andrew Johnson
702edbf4af Merged Lewis Muir's CAref typo fixes 2014-11-07 15:35:30 -06:00
J. Lewis Muir
0d0ac88242 doc: Fix typos in CA reference manual 2014-11-07 14:56:41 -06:00
Andrew Johnson
2ab2470317 Fix epicsStrtod() implementation to detect overflow
The VxWorks version of strtod() that we use returns Inf
instead of setting errno on overflow.
2014-11-07 13:25:16 -06:00
Andrew Johnson
53d9a07f64 Fix buffer overflow in epicsStrnRawFromEscaped
lp:1388313
2014-11-05 10:06:02 -06:00
Andrew Johnson
eae4f60e57 cap5: Fix replace_access_rights_event() channel method 2014-11-04 15:10:50 -06:00
Andrew Johnson
a05856375a Update EPICS_TIMEZONE data in CONFIG_SITE_ENV 2014-11-04 14:55:25 -06:00
Andrew Johnson
05d3bb63aa configure: Added missing menu%.h.d rule
Janet had to remove '..' from the vpaths because it was letting
the build look into the TOP/.. directory, which was causing
major issues. She added back rules for COMMON_DIR and .. but
missed this one.
2014-11-03 17:02:42 -06:00
Andrew Johnson
743e3bd387 cap5: Add replace_access_rights_event() channel method 2014-11-02 23:11:44 -06:00
Andrew Johnson
79b70d651c Flag epicsBoolean with EPICS_DEPRECATED 2014-10-31 17:26:48 -05:00
Andrew Johnson
9d5bffca94 libCom/flex: Default skeleton should be filename only 2014-10-31 16:58:03 -05:00
Andrew Johnson
64bf84169c dbStatic: Added hook routine for dbLoadRecords()
Requested by Tim Mooney for use by Autosave.
See the Release Notes for documentation.

This commit also corrects the decorations for recGblAlarmHook.
2014-10-31 16:18:25 -05:00
Andrew Johnson
647bd334ae iocsh: Protect echo and cd from NULL arguments 2014-10-31 12:19:09 -05:00
Andrew Johnson
09ff608ca9 libCom: Fix use-after-free bug in macCore.c 2014-10-30 17:55:12 -05:00
Andrew Johnson
6c14dc194c Replace the epicsBoolean type in epicsTypes.h 2014-10-30 14:40:19 -05:00
Andrew Johnson
9f163ef8d9 Merged J Lewis Muir's typo-fix branch 2014-10-28 16:20:51 -05:00
J. Lewis Muir
f0156119be cap5: Fix doc typos 2014-10-22 11:03:40 -05:00
Andrew Johnson
f808e4309d cap5 Fixes
1. Support subscribing for DBR_GR_ENUM or DBR_CTRL_ENUM
2. Fix doc example on how to combine timestamp parts
2014-10-17 15:19:00 -05:00
Andrew Johnson
f59123bd3c Added Windows-x64-debug cross-build config file 2014-10-17 11:48:18 -05:00
Ralph Lange
49a9d64946 catools: better out-of-bounds handling when printing enums as DBR_GR/DBR_CTRL 2014-10-09 14:12:39 +02:00
Andrew Johnson
c5740c0dd0 Add relPaths.sh target to convertRelease.pl
This is a /bin/sh syntax version of the dllPath.bat file,
needed to run IOCs under Cygwin when SHARED_LIBRARIES=YES.
2014-10-08 14:18:08 -05:00
Andrew Johnson
3eb6a66f3c Fix build warnings 2014-10-07 15:59:20 -05:00
Andrew Johnson
986f7abb08 Set version snapshot back to -DEV 2014-10-07 01:50:24 -05:00
86 changed files with 1623 additions and 994 deletions

View File

@@ -14,8 +14,8 @@
EPICS_BASE_HOST_BIN = $(EPICS_BASE)/bin/$(EPICS_HOST_ARCH)
EPICS_BASE_HOST_LIB = $(EPICS_BASE)/lib/$(EPICS_HOST_ARCH)
ifdef T_A
EPICS_BASE_LIB = $(EPICS_BASE)/lib/$(T_A)
EPICS_BASE_BIN = $(EPICS_BASE)/bin/$(T_A)
EPICS_BASE_LIB = $(EPICS_BASE)/lib/$(T_A)
EPICS_BASE_BIN = $(EPICS_BASE)/bin/$(T_A)
endif
#---------------------------------------------------------------
@@ -33,8 +33,10 @@ EPICS_BASE_HOST_LIBS += ca Com
# Version number for base shared libraries (and win32 products)
ifdef BASE_TOP
SHRLIB_VERSION = $(EPICS_VERSION).$(EPICS_REVISION)
PROD_VERSION = $(EPICS_VERSION).$(EPICS_REVISION)
# Unix lib.so.<v.r.m> Darwin lib.<v.r.m>.dylib
SHRLIB_VERSION = $(EPICS_VERSION).$(EPICS_REVISION).$(EPICS_MODIFICATION)
# Windows only allows 2 levels of version numbering
PROD_VERSION = $(EPICS_VERSION).$(EPICS_REVISION)
endif # BASE_TOP
#---------------------------------------------------------------
@@ -84,12 +86,15 @@ ELEX = $(call PATH_FILTER, $(TOOLS)/e_flex$(HOSTEXE)) -S$(EPICS_BASE)/include/fl
YACC = $(EYACC)
LEX = $(ELEX)
#---------------------------------------------------------------
# msi used to be an external tool
MSI ?= $(EPICS_BASE_HOST_BIN)/msi
#---------------------------------------------------------------
# External tools and tool flags - must be in path or defined in application
ifndef ADL2DL
ADL2DL = adl2dl
endif
ADL2DL ?= adl2dl
# sch2edif compiler and flags
SCH2EDIF = sch2edif
@@ -99,18 +104,11 @@ SCH2EDIF_FLAGS =
# e2db and flags
# - again there is an assumption where edb.def is installed.
ifndef E2DB
E2DB = e2db
endif
E2DB ?= e2db
E2DB_SYSFLAGS = -ate -d $(CAPFAST_TEMPLATES)/edb.def
E2DB_FLAGS =
ifndef DBST
DBST = dbst
endif
ifndef MSI
MSI = $(EPICS_BASE_HOST_BIN)/msi
endif
DBST ?= dbst

View File

@@ -29,11 +29,11 @@ EPICS_VERSION = 3
EPICS_REVISION = 15
# EPICS_MODIFICATION must be a number >=0 and <256
EPICS_MODIFICATION = 0
EPICS_MODIFICATION = 1
# EPICS_PATCH_LEVEL must be a number (win32 resource file requirement)
# EPICS_PATCH_LEVEL must be a number (win32 resource file requirement)
# Not included if zero
EPICS_PATCH_LEVEL = 2
EPICS_PATCH_LEVEL = 0
# This will end in -DEV between official releases
#EPICS_DEV_SNAPSHOT=-DEV

View File

@@ -177,7 +177,7 @@ LIBRARY_OBJS = $(addsuffix $(OBJ),$(basename $(SRCS) $(USR_SRCS) $(LIB_SRCS) $(L
LIBRARY_LD_OBJS = $(USR_OBJLIBS) $(LIB_OBJLIBS) $(TARGET_OBJS) $(LIBRARY_OBJS)
#--------------------------------------------------
# WIN95/NT resource files
# Windows resource files
TARGET_RESS = $(if $(RES),$(addsuffix $(RES),$(basename $($*_RCS))),)
@@ -187,11 +187,6 @@ PROD_LD_RESS = $(TARGET_RESS) $(PROD_RESS)
LIBRARY_RESS = $(if $(RES),$(addsuffix $(RES),$(basename $(RCS) $(LIB_RCS) $(LIBRARY_RCS))),)
LIBRARY_LD_RESS = $(TARGET_RESS) $(LIBRARY_RESS)
#--------------------------------------------------
# WIN95/NT source browser
PROD_BAF = $(addsuffix $(BAF), $(basename $(PROD)))
LIB_BAF=$(addsuffix $(BAF),$(basename $(LIBRARY)))
#--------------------------------------------------
# C preprocessor, compiler, and linker flag defaults

View File

@@ -30,23 +30,23 @@
# local timezone info for vxWorks and RTEMS IOCs. The format is
# <name>::<minutesWest>:<start daylight>:<end daylight>
# where the start and end are mmddhh - that is month,day,hour
# e.g. for ANL in 2010: EPICS_TIMEZONE=CUS::360:031402:110702
# e.g. for ANL in 2015: EPICS_TIMEZONE=CST/CDT::360:030802:110102
#
# DST for 2011 US: Mar 13 - Nov 06
# EU: Mar 27 - Oct 30
# DST for 2012 US: Mar 11 - Nov 04
# EU: Mar 25 - Oct 28
# DST for 2013 US: Mar 10 - Nov 03
# EU: Mar 31 - Oct 27
# DST for 2014 US: Mar 09 - Nov 02
# EU: Mar 30 - Oct 26
# DST for 2015 US: Mar 08 - Nov 01
# EU: Mar 29 - Oct 25
# (see: http://www.worldtimezone.org/daylight.html)
# DST for 2016 US: Mar 13 - Nov 06
# EU: Mar 27 - Oct 30
# DST for 2017 US: Mar 12 - Nov 05
# EU: Mar 26 - Oct 29
# DST for 2018 US: Mar 11 - Nov 04
# EU: Mar 25 - Oct 28
# DST for 2019 US: Mar 10 - Nov 03
# EU: Mar 31 - Oct 27
# (see: http://www.timeanddate.com/time/map/)
#
# These values are for 2011:
EPICS_TIMEZONE=CUS::360:031302:110602
#EPICS_TIMEZONE=MET::-60:032702:103002
# These values are for 2015:
EPICS_TIMEZONE=CST/CDT::360:030802:110102
#EPICS_TIMEZONE=CET/CEST::-60:032902:102502
# EPICS_TS_NTP_INET
# NTP time server ip address. Uses boot host if not set.

View File

@@ -151,7 +151,6 @@ ACTIONS = inc
ACTIONS += build
ACTIONS += install
ACTIONS += buildInstall
ACTIONS += browse
ACTIONS += runtests tapfiles
actionArchTargets = $(foreach x, $(ACTIONS),\ $(foreach arch,$(BUILD_ARCHS), $(x)$(DIVIDER)$(arch)))
@@ -233,6 +232,11 @@ menu%.h$(DEP): menu%.dbd
@$(DBTOMENUH) -D $(DBDFLAGS) -o $(COMMONDEP_TARGET) $< > $@
@echo "$(COMMONDEP_TARGET): ../Makefile" >> $@
menu%.h$(DEP): ../menu%.dbd
@$(RM) $@
@$(DBTOMENUH) -D $(DBDFLAGS) -o $(COMMONDEP_TARGET) $< > $@
@echo "$(COMMONDEP_TARGET): ../Makefile" >> $@
%.dbd$(DEP): %.dbd.pod
@$(RM) $@
@$(DBEXPAND) -D $(DBDFLAGS) -o $(COMMONDEP_TARGET) $< > $@

View File

@@ -18,16 +18,17 @@ ifeq ($(filter $(ARCH),$(BUILD_ARCHS)),$(ARCH))
buildInstall$(DIVIDER)$(ARCH) buildInstall: $(TARGETS)
clean$(DIVIDER)$(ARCH) clean:
$(RM) cdCommands envPaths dllPath.bat
$(RM) cdCommands envPaths dllPath.bat relPaths.sh
else
buildInstall$(DIVIDER)$(ARCH) buildInstall:
clean$(DIVIDER)$(ARCH) clean:
endif
cdCommands envPaths dllPath.bat: $(wildcard $(TOP)/configure/RELEASE*) \
cdCommands envPaths dllPath.bat relPaths.sh: \
$(wildcard $(TOP)/configure/RELEASE*) \
$(wildcard $(TOP)/configure/CONFIG_SITE*) $(INSTALL_BIN)
$(CONVERTRELEASE) -a $(ARCH) -t $(IOCS_APPL_TOP) $@
realclean:
$(RM) cdCommands envPaths dllPath.bat
$(RM) cdCommands envPaths dllPath.bat relPaths.sh

View File

@@ -17,48 +17,39 @@ ACTIONS = inc
ACTIONS += build
ACTIONS += install
ACTIONS += buildInstall
ACTIONS += browse
ACTIONS += runtests tapfiles
#ACTIONS += rebuild
actionPart = $(word 1, $(subst $(DIVIDER), ,$@))
archPart = $(word 2, $(subst $(DIVIDER), ,$@))
actionArchTargets = $(foreach x, $(ACTIONS),\
$(foreach arch,$(BUILD_ARCHS), $(x)$(DIVIDER)$(arch)))
actionArchTargets = $(foreach action, $(ACTIONS), \
$(addprefix $(action)$(DIVIDER), $(BUILD_ARCHS)))
cleanArchTargets = $(foreach arch,$(BUILD_ARCHS), clean$(DIVIDER)$(arch))
cleanArchTargets = $(addprefix clean$(DIVIDER), $(BUILD_ARCHS))
buildDirs = $(addprefix O.,$(BUILD_ARCHS))
buildDirs = $(addprefix O., $(BUILD_ARCHS))
#*************************************************************************
# Create epics_host_arch dependancies for GNU make -j option
# Only works with GNU make 3.81 or later (uses eval function)
# Needed in dirs where EPICS_HOST_ARCH build creates a tool used in
# Create EPICS_HOST_ARCH dependancies for GNU make -j option
# Needed in dirs where EPICS_HOST_ARCH builds a tool used by
# cross arch builds
CROSS_ARCHS += $(CROSS1) $(CROSS2)
define DEP_template
$(2): $$(EPICS_HOST_ARCH)
$(1)$$(DIVIDER)$(2): $(1)$$(DIVIDER)$$(EPICS_HOST_ARCH) O.$(2)
$(2) : $(EPICS_HOST_ARCH)
$(1)$(DIVIDER)$(2) : $(1)$(DIVIDER)$(EPICS_HOST_ARCH) O.$(2)
endef
ifeq ($(MAKE_VERSION),3.81)
$(foreach action, $(ACTIONS), $(foreach arch,\
$(CROSS_ARCHS),$(eval $(call DEP_template,$(action),$(arch)))))
else
ifeq ($(findstring j,$(MAKEFLAGS)),j)
$(foreach action, $(ACTIONS), $(foreach arch,\
$(CROSS_ARCHS),$(eval $(call DEP_template,$(action),$(arch)))))
endif
endif
$(foreach action, $(ACTIONS), $(foreach arch, $(CROSS_ARCHS), \
$(eval $(call DEP_template,$(action),$(arch)))))
#*************************************************************************
# Allows rebuild to work with parallel builds option, -j.
ifeq (rebuild,$(filter rebuild,$(MAKECMDGOALS)))
$(buildDirs) O.Common : clean
rebuild: install
$(buildDirs) O.Common : clean
rebuild : install
endif
$(actionArchTargets) : $(buildDirs) O.Common
@@ -67,7 +58,7 @@ $(actionArchTargets) : $(buildDirs) O.Common
$(BUILD_ARCHS) : % : O.% O.Common
$(MAKE) -C O.$@ -f ../Makefile TOP=$(TOP)/.. T_A=$@
$(ACTIONS):%: $(foreach arch, $(BUILD_ARCHS), %$(DIVIDER)$(arch))
$(ACTIONS) : % : $(foreach arch, $(BUILD_ARCHS), %$(DIVIDER)$(arch))
$(buildDirs):
$(PERL) $(TOOLS)/makeMakefile.pl $@ $(TOP)/..
@@ -78,21 +69,21 @@ O.Common:
#
# special clean rule
#
clean : archs_common_clean
clean: archsCommonClean
archs_common_clean :
$(RMDIR) $(addprefix O.,$(BUILD_ARCHS)) O.Common
archsCommonClean:
$(RMDIR) $(buildDirs) O.Common
archclean :
$(RMDIR) $(addprefix O.,$(BUILD_ARCHS))
archclean:
$(RMDIR) $(buildDirs)
$(cleanArchTargets) :
$(cleanArchTargets):
$(RMDIR) O.$(archPart)
realclean :
realclean:
$(RMDIR) O.*
.PHONY : $(actionArchTargets)
.PHONY : $(cleanArchTargets)
.PHONY : $(BUILD_ARCHS) rebuild arch_common_clean
.PHONY : $(BUILD_ARCHS) rebuild archsCommonClean
.PHONY : $(ACTIONS) clean realclean archclean host all

View File

@@ -166,17 +166,6 @@ build_clean:
ifdef RES
@$(RM) *$(RES)
endif
ifdef BAF
@$(RM) $(PROD_BAF) $(LIB_BAF)
endif
ifdef BOF
@$(RM) *$(BOF)
endif
# WIN95/NT source browser
#ifdef BAF
browse: $(LIB_BAF) $(PROD_BAF)
#endif
$(DIRECTORY_TARGETS) :
$(MKDIR) -p $@
@@ -238,17 +227,11 @@ $(TESTPRODNAME) $(PRODNAME): %$(EXE):
@$(RM) $@
$(COMPILE.cpp) -c $<
# WIN95/NT resource compiler
# Windows resource compiler
%$(RES): %.rc
@$(RM) $@
$(RCCMD)
# WIN95/NT source browser
%.bsc: %.sbr
$(ECHO) "building source browser archive $@"
@$(RM) $@
$(BAFCMD) $<
YACCOPT ?= $($*_YACCOPT)
#
# rename the y.tab.h file only if we
@@ -271,16 +254,6 @@ YACCOPT ?= $($*_YACCOPT)
@$(RM) $@
$(MV) $*.yy.c $@
# WIN95/NT source browser
ifdef BAF
$(LIB_BAF): $(addsuffix $(BOF),$(basename $(LIBRARY_LD_OBJS)))
$(ECHO) "Building source browser archive $@"
@$(RM) $@
$(BAFCMD) $^
endif
#---------------------------------------------------------------
# Libraries, shared/DLL and stubs
@@ -332,10 +305,6 @@ $(MUNCHNAME): %$(MUNCH_SUFFIX): $(MUNCH_DEPENDS) %$(EXE)
@$(RM) $@
$(MUNCH_CMD)
$(OBJLIB_MUNCHNAME): %.munch: %_ctdt$(OBJ) %$(OBJ)
@$(RM) $@
$(MUNCH_CMD)
#---------------------------------------------------------------
# Automated testing

View File

@@ -71,6 +71,8 @@ CPPFLAGS += $(CROSS_CPPFLAGS) $(POSIX_CPPFLAGS)\
$(BASE_CPPFLAGS) $(TARGET_CPPFLAGS) $(USR_CPPFLAGS) $(ARCH_DEP_CPPFLAGS)\
$(OP_SYS_CPPFLAGS) $(OP_SYS_INCLUDE_CPPFLAGS) $(CODE_CPPFLAGS)
ECHO = @$(if $(findstring s,$(patsubst T_A=%,,$(MAKEFLAGS))),$(NOP),echo)
#--------------------------------------------------
# Although RTEMS uses gcc, it wants to use gcc its own way
CROSS_CPPFLAGS =

View File

@@ -25,7 +25,7 @@ OS_CLASS = iOS
#--------------------------------------------------
# GNU and SDK directories
GNU_DIR = $(PLATFORM_DIR)/Developer/usr
SDK_DIR = $(PLATFORM_DIR)/Developer/SDKs/$(IOS_PLATFORM)$(IOS_VERSION).sdk
SDK_DIR = $(PLATFORM_DIR)/Developer/SDKs/$(IOS_PLATFORM).sdk
#-------------------------------------------------------
# Build architecture flags
@@ -64,7 +64,7 @@ CC_CLANG = clang
CCC_CLANG = clang++
CMPLR_CLASS_CLANG = clang
CMPLR_CLASS = $(CMPLR_CLASS_$(COMPLER))
CMPLR_CLASS = $(CMPLR_CLASS_$(COMPILER))
# Convert the iOS platform to lowercase for passing to xcrun's sdk parameter
XCRUN_SDK_BASE = $(shell echo $(IOS_PLATFORM) | tr A-Z a-z)

View File

@@ -68,13 +68,12 @@ GNU = NO
#
# Darwin shared libraries
#
SHRLIB_VERSION = $(EPICS_VERSION).$(EPICS_REVISION).$(EPICS_MODIFICATION)
SHRLIB_LDFLAGS = -dynamiclib -flat_namespace -undefined suppress \
-install_name $(shell $(FULLPATHNAME) $(INSTALL_LIB))/$@ \
-compatibility_version $(EPICS_VERSION).$(EPICS_REVISION) \
-current_version $(SHRLIB_VERSION)
-install_name $(shell $(FULLPATHNAME) $(INSTALL_LIB))/$@ \
$(addprefix -compatibility_version , $(SHRLIB_VERSION)) \
$(addprefix -current_version , $(SHRLIB_VERSION))
SHRLIB_SUFFIX_BASE = .dylib
SHRLIB_SUFFIX = .$(SHRLIB_VERSION)$(SHRLIB_SUFFIX_BASE)
SHRLIB_SUFFIX = $(addprefix ., $(SHRLIB_VERSION))$(SHRLIB_SUFFIX_BASE)
LOADABLE_SHRLIB_LDFLAGS = -bundle -flat_namespace -undefined suppress

View File

@@ -21,8 +21,6 @@ RCCMD = rc -l 0x409 $(INCLUDES) -fo $@ $<
ARCMD = lib -nologo -verbose -out:$@ $(LIB_OPT_LDFLAGS) $(LIBRARY_LD_OBJS)
BAFCMD = bscmake -nologo -o $@
#
# Configure OS vendor C compiler
CC = cl
@@ -130,6 +128,7 @@ RANLIB=
# -LTCG whole program optimization
# -incremental:no full linking
# -fixed:no generate relocatable code
# -version:<major>.<minor> - only 2 components allowed, 0-65535 each
# -debug generate debugging info
LINK_OPT_FLAGS_YES = -LTCG -incremental:no -opt:ref \
-release $(PROD_VERSION:%=-version:%)
@@ -150,8 +149,6 @@ WIN32=1
EXE=.exe
OBJ=.obj
RES=.res
BAF=.bsc
BOF=.sbr
# Problem: MS Visual C++ does not recognize *.cc as C++ source,
# so we do C++ compiles using the global flag -TP

View File

@@ -10,19 +10,9 @@
-include $(CONFIG)/os/CONFIG.Common.win32-x86
-include $(CONFIG)/os/CONFIG.win32-x86.win32-x86
ARCH_DEP_CPPFLAGS += /favor:blend
#ARCH_DEP_CPPFLAGS += /Wp64
# /favor:blend both AMD64 and INTEL64
# /favor:AMD64
# /favor:INTEL64 (new value)
# /favor:EN64T (old value)
OPT_LDFLAGS += /MACHINE:X64
# /MACHINE:X64
# /MACHINE:IA64 (Itanium)
# /MACHINE:X86
#The following option does not work
#ARCH_DEP_CPPFLAGS += /env x64

View File

@@ -9,14 +9,6 @@
-include $(CONFIG)/os/CONFIG.win32-x86.win32-x86
ARCH_DEP_CPPFLAGS += /favor:blend
#ARCH_DEP_CPPFLAGS += /Wp64
# /favor:blend both AMD64 and INTEL64
# /favor:AMD64
# /favor:INTEL64 (new value)
# /favor:EN64T (old value)
OPT_LDFLAGS += /MACHINE:X64
# /MACHINE:X64

View File

@@ -0,0 +1,12 @@
# CONFIG.windows-x64.windows-x64-debug
#
# $Revision-Id$
# This file is maintained by the build community.
#
# Definitions for windows-x64 compiler host - windows-x64 debug compiler target builds
# Sites may override these definitions in CONFIG_SITE.windows-x64.windows-x64-debug
#-------------------------------------------------------
include $(CONFIG)/os/CONFIG.windows-x64.windows-x64
HOST_OPT=NO

View File

@@ -5,17 +5,6 @@
# Site-specific settings for Apple iOS builds
#-------------------------------------------------------
# iOS SDK Version number (not the XCode version).
# We haven't tested our current build rules on the older
# versions of either XCode or the iOS SDK, be warned!
#IOS_VERSION = 5.0
#IOS_VERSION = 5.1
#IOS_VERSION = 6.0
#IOS_VERSION = 6.1
#IOS_VERSION = 7.0
IOS_VERSION = 8.0
# Minimum version of iOS the executables must run on.
# Earlier versions may work, if XCode supports them.

View File

@@ -0,0 +1,11 @@
# CONFIG_SITE.Common.windows-x64-static
#
# $Revision-Id$
#
# Site Specific definitions for windows-x64-static target
# Only the local epics system manager should modify this file
# 64-bit Visual Studio 2010 builds fail when built optimized.
# If you are using a newer version you can try removing this:
HOST_OPT = NO

View File

@@ -4,30 +4,27 @@
<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 R3.15.0.2</title>
<title>Known Problems in R3.15.1</title>
</head>
<body>
<h1 style="text-align: center">EPICS Base R3.15.0.2: Known Problems</h1>
<h1 style="text-align: center">EPICS Base R3.15.1: Known Problems</h1>
<p>Any patch files linked below should be applied at the root of the
base-3.15.0.2 tree. Download them, then use the GNU Patch program as
base-3.15.1 tree. Download them, then use the GNU Patch program as
follows:</p>
<blockquote><pre>% <b>cd <i>/path/to/</i>base-3.15.0.2</b>
<blockquote><pre>% <b>cd <i>/path/to/</i>base-3.15.1</b>
% <b>patch -p0 &lt; <i>/path/to/</i>file.patch</b></pre></blockquote>
<p>The following significant problems have been reported with this
version of EPICS Base:</p>
<ul>
<li>64-bit Windows builds may not work with some tool-sets, the code in
<tt>src/legacy/gdd</tt> is not comptible with the LLP64 model that Windows
uses for its 64-bit ABI.</li>
<li>The <tt>-x</tt> option to the softIoc program loads a standard database
that is supposed to be able to exit the running IOC. In this release that
causes an assertion failure which prints a stack trace and suspends the
program wihout exiting.</li>
<li>64-bit Windows builds of the CAS library may not work with some compilers.
The code in <tt>src/legacy/gdd</tt> is currently incompatible with the LLP64
model that Windows uses for its 64-bit ABI.</li>
</ul>

View File

@@ -1,24 +1,24 @@
Installation Instructions
EPICS Base Release 3.15.0.2
EPICS Base Release 3.15.1
--------------------------------------------------------------------------
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
--------------------------------------------------------------------------

View File

@@ -9,7 +9,7 @@
<BODY>
<CENTER>
<H1>Installation Instructions</H1>
<H2>EPICS Base Release 3.15.0.2</H2><BR>
<H2>EPICS Base Release 3.15.1</H2><BR>
</CENTER>
<HR>
<H3> Table of Contents</H3>

View File

@@ -3,17 +3,77 @@
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
<title>EPICS Base R3.15.0.1 Release Notes</title>
<title>EPICS Base R3.15.1 Release Notes</title>
</head>
<body lang="en">
<h1 align="center">EPICS Base Release 3.15.0.2</h1>
<h1 align="center">EPICS Base Release 3.15.1</h1>
<h2 align="center">Changes between 3.15.0.2 and 3.15.1</h2>
<h3>epicsStrnEscapedFromRaw() and epicsStrnRawFromEscaped()</h3>
<p>These routines have been rewritten; the previous implementations did not
always behave exactly as specified.</p>
<h3>Shared Library Versions</h3>
<p>On architectures that can support it, the shared library version number for
libraries provided with Base has had the third component of the EPICS version
number added to it, thus libCom.so.3.15.1 instead of libCom.so.3.15. Windows
can only support two components to its internal product version number, and the
Darwin bug that external shared libraries were being built using the EPICS
version number has been fixed.</p>
<h3>Hooking into dbLoadRecords</h3>
<p>A function pointer hook has been added to the dbLoadRecords() routine, to
allow external modules such as autosave to be notified when new records have
been loaded during IOC initialization. The hook is called dbLoadRecordsHook and
follows the model of the recGblAlarmHook pointer in that modules that wish to
use it must save the current value of the pointer before installing their own
function pointer, and must call the original function from their own
routine.</p>
<p>The hook is activiated from the dbLoadRecords() routine and gets called only
after a database instance file has been read in without error. Note that the
dbLoadTemplates() routine directly calls dbLoadRecords() so this hook also
provides information about instantiated database templates. It is still possible
to load record instances using dbLoadDatabase() though, and doing this will not
result in the hook routines being called.</p>
<p>Code to use this hook should look something like this:</p>
<blockquote><pre>
#include "dbAccessDefs.h"
static DB_LOAD_RECORDS_HOOK_ROUTINE previousHook;
static void myRoutine(const char* file, const char* subs) {
if (previousHook)
previousHook(file, subs);
/* Do whatever ... */
}
void myInit(void) {
static int done = 0;
if (!done) {
previousHook = dbLoadRecordsHook;
dbLoadRecordsHook = myRoutine;
done = 1;
}
}
</pre></blockquote>
<p>As with many other parts of the static database access library there is no
mutex to protect the function pointer. Initialization is expected to take place
in the context of the IOC's main thread, from either a static C++ constructor or
an EPICS registrar routine.</p>
<p>
EPICS Base 3.15.0.x releases are not intended for use in production systems.</p>
<h2 align="center">Changes between 3.15.0.1 and 3.15.0.2</h2>
<!-- Insert new items immediately below here ... -->
<h3>New iocshLoad command</h3>

File diff suppressed because it is too large Load Diff

View File

@@ -4,7 +4,7 @@
use strict;
use warnings;
my $version = '0.5';
my $version = '0.6';
package CA;
@@ -95,8 +95,8 @@ CA - Perl 5 interface to EPICS Channel Access
} else {
printf " Value: %g\n", $data->{value};
printf " Severity: %s\n", $data->{severity};
printf " Timestamp: %d.%09d\n",
$data->{stamp}, $data->{stamp_fraction};
printf " Timestamp: %.6f\n",
$data->{stamp} + $data->{stamp_fraction};
}
}
@@ -235,7 +235,7 @@ C<die> with an exception object in the callback and catch that using C<eval> in
the main thread are not likely to succeed and will probably result in a crash.
Callbacks should not perform any operations that would block for more than a
fraction of a second as this will hold up network communications with the
relevent server and could cause the Perl program and/or the Channel Access
relevant server and could cause the Perl program and/or the Channel Access
server to crash. Calling C<< CA->pend_event >> from within a callback is not
permitted by the underlying Channel Access library.
@@ -291,7 +291,7 @@ apply to the callback subroutine as described in C<get_callback> above.
=item put_acks( I<SEVR>, I<SUB> )
Applications that need to ackowledge alarms by doing a C<ca_put()> with type
Applications that need to acknowledge alarms by doing a C<ca_put()> with type
C<DBR_PUT_ACKS> can do so using the C<put_acks> method. The severity argument
may be provided as an integer from zero through three or as a string containing
one of the corresponding EPICS severity names C<NO_ALARM>, C<MINOR>, C<MAJOR> or
@@ -316,6 +316,19 @@ channel; see the C<new> constructor for details. If I<SUB> is C<undef> any
existing handler is removed, otherwise the new subroutine will be used for all
future connection events on this channel.
=item change_access_rights_event( I<SUB> )
This method replaces, adds or cancels an access rights handler subroutine for
the channel, which will be called if the client's right to read from or write
to the channel changes. If I<SUB> is C<undef> any existing handler is removed,
otherwise the new subroutine will be used for all future rights change events
on this channel.
The arguments passed to I<SUB> are the channel object and a pair of scalar
values for read and write permissions respectively, that are true when the
access is permitted, false when it is not.
=back
@@ -325,11 +338,12 @@ The data provided to a callback function registered with either C<get_callback>
or C<create_subscription> can be a scalar value or a reference to an array or a
hash, depending on the data type that was used for the data transfer. If the
request was for a single item of one of the basic data types, the data argument
will be a perl scalar that holds the value directly. If the request was for
will be a Perl scalar that holds the value directly. If the request was for
multiple items of one of the basic types, the data argument will be a reference
to an array holding the data. There is one exception though; if the data type
requested was for an array of C<DBF_CHAR> values that array will be represented
as a single Perl string contining all the characters before the first zero byte.
as a single Perl string containing all the characters before the first zero
byte.
If the request was for one of the compound data types, the data argument will be
a reference to a hash with keys as described below. Keys that are not classed
@@ -355,7 +369,7 @@ widened from the original type used to request or subscribe for the data.
The number of elements in the data returned by the server. If the data type is
C<DBF_CHAR> the value given for C<COUNT> is the number of bytes (including any
trailing zeros) returned by the server, although the value field is given as a
Perl string contining all the characters before the first zero byte.
Perl string containing all the characters before the first zero byte.
=back
@@ -417,7 +431,7 @@ Present only when I<TYPE> is C<DBR_GR_ENUM> or C<DBR_CTRL_ENUM>.
=item stamp
The process variable timestamp, converted to a local C<time_t>. This value is
suitable for passing to the perl C<localtime> or C<gmtime> functions.
suitable for passing to the Perl C<localtime> or C<gmtime> functions.
Present only when I<TYPE> is C<DBR_TIME_yyy>.
@@ -620,15 +634,15 @@ passing C<undef> as the subroutine reference.
Errors in using the library will be indicated by the module throwing an
exception, i.e. calling C<croak()> with an appropriate error message. These
exceptions can be caught using the standard Parl C<eval {}> statement and
exceptions can be caught using the standard Perl C<eval {}> statement and
testing the C<$@> variable afterwards; if not caught, they will cause the
running program to C<die> with an appropriate error message pointing to the
program line that called the C<CA> library.
Errors messages reported by the underlying CA client library all start with the
Error messages reported by the underlying CA client library all start with the
string C<ECA_> and the remainder of the symbol for the associated CA error
number, and are followed after a space-hyphen-space by a human-readable message
describing the error. Errors that are detected by the perl interface layer do
describing the error. Errors that are detected by the Perl interface layer do
not follow this pattern, but are still printable strings.
@@ -636,9 +650,9 @@ not follow this pattern, but are still printable strings.
=over
=item [1] R3.14 Channel Access Reference Manual by Jeffrey O. Hill
=item [1] R3.15 Channel Access Reference Manual by Jeffrey O. Hill
L<http://www.aps.anl.gov/epics/base/R3-14/12-docs/CAref.html>
L<http://www.aps.anl.gov/epics/base/R3-15/0-docs/CAref.html>
=back

View File

@@ -519,6 +519,46 @@ void CA_change_connection_event(SV *ca_ref, SV *sub) {
}
}
/* CA::replace_access_rights_event($ca_ref, \$sub) */
static
void rights_handler(struct access_rights_handler_args arha) {
CA_channel *pch = ca_puser(arha.chid);
PERL_SET_CONTEXT(p5_ctx);
{
dSP;
SvSetSV(ERRSV, &PL_sv_undef);
PUSHMARK(SP);
XPUSHs(pch->chan_ref);
XPUSHs(arha.ar.read_access ? &PL_sv_yes : &PL_sv_no);
XPUSHs(arha.ar.write_access ? &PL_sv_yes : &PL_sv_no);
PUTBACK;
call_sv(pch->rights_sub, G_EVAL | G_VOID | G_DISCARD | G_KEEPERR);
if (SvTRUE(ERRSV))
croak(NULL);
}
}
void CA_replace_access_rights_event(SV *ca_ref, SV *sub) {
CA_channel *pch = (CA_channel *)SvIV(SvRV(ca_ref));
caArh *handler = &rights_handler;
int status;
if (! replace_handler(sub, &pch->rights_sub, (long *)&handler))
return;
status = ca_replace_access_rights_event(pch->chan, handler);
if (status != ECA_NORMAL) {
croak("%s", get_error_msg(status));
}
}
/* CA::put($ca_ref, @values) */
@@ -914,16 +954,18 @@ SV * CA_create_subscription(SV *ca_ref, const char *mask_str, SV *sub, ...) {
dbr_text_to_type(treq, type);
if (type < 0) {
croak_msg = "Unknown data type";
croak_msg = "Unknown CA data type";
goto exit_croak;
}
if (type == DBR_PUT_ACKT ||
type == DBR_PUT_ACKS) {
croak_msg = "DBR_PUT_ACK types are write-only";
goto exit_croak;
} else if (type == DBR_CLASS_NAME ||
} else if (type == DBR_GR_ENUM ||
type == DBR_CTRL_ENUM ||
type == DBR_CLASS_NAME ||
type == DBR_STSACK_STRING)
/* These break the dbr_type_is macros */ ;
/* These above types are supported */ ;
else if (dbr_type_is_SHORT(type))
type += (DBR_LONG - DBR_SHORT);
else if (dbr_type_is_FLOAT(type))
@@ -1265,6 +1307,11 @@ CA_change_connection_event (ca_ref, sub)
SV * ca_ref
SV * sub
void
CA_replace_access_rights_event (ca_ref, sub)
SV * ca_ref
SV * sub
void
CA_put (ca_ref, val, ...)
SV * ca_ref

View File

@@ -8,18 +8,16 @@
TOP=../../../..
include $(TOP)/configure/CONFIG
# Use hdepends command (not GNU compiler flags)
# to generate header file dependancies for Darwin.
# Darwin has multiple -arch compiler flags.
# Special settings for Darwin:
ifeq ($(OS_CLASS),Darwin)
HDEPENDS_METHOD = MKMF
endif
# Use hdepends command (not GNU compiler flags)
# to generate header file dependancies for Darwin.
# Darwin has multiple -arch compiler flags.
HDEPENDS_METHOD = MKMF
ifneq ($(findstring darwin,$(T_A)),)
# Perl loadable libraries on Darwin have funny names
LOADABLE_SHRLIB_PREFIX =
LOADABLE_SHRLIB_SUFFIX = .bundle
LOADABLE_SHRLIB_SUFFIX = .$(shell $(PERL) ../perlConfig.pl dlext)
endif
PERL_VERSION = $(shell $(PERL) ../perlConfig.pl version)
@@ -56,10 +54,11 @@ include $(TOP)/configure/RULES
ifdef T_A
EXTUTILS = $(shell $(PERL) ../perlConfig.pl privlib)/ExtUtils
XSUBPP = $(firstword $(wildcard /usr/bin/xsubpp $(EXTUTILS)/xsubpp))
%.c: ../%.xs
$(RM) $@ $@_new
$(PERL) $(EXTUTILS)/xsubpp -typemap $(EXTUTILS)/typemap $< > $@_new && $(MV) $@_new $@
$(PERL) $(XSUBPP) -typemap $(EXTUTILS)/typemap $< > $@_new && $(MV) $@_new $@
$(INSTALL_PERL_MODULES)/$(PERL_ARCHPATH)/%: %
$(ECHO) "Installing loadable shared library $@"

View File

@@ -160,11 +160,21 @@ char *val2str (const void *v, unsigned type, int index)
case DBR_ENUM:
{
dbr_enum_t *val = (dbr_enum_t *)val_ptr;
if (dbr_type_is_GR(type) && !enumAsNr)
sprintf(str, "%s", ((struct dbr_gr_enum *)v)->strs[val[index]]);
else if (dbr_type_is_CTRL(type) && !enumAsNr)
sprintf(str, "%s", ((struct dbr_ctrl_enum *)v)->strs[val[index]]);
else
if (dbr_type_is_GR(type) && !enumAsNr) {
if (val[index] >= MAX_ENUM_STATES)
sprintf(str, "Illegal Value (%d)", val[index]);
else if (val[index] >= ((struct dbr_gr_enum *)v)->no_str)
sprintf(str, "Enum Index Overflow (%d)", val[index]);
else
sprintf(str, "%s", ((struct dbr_gr_enum *)v)->strs[val[index]]);
} else if (dbr_type_is_CTRL(type) && !enumAsNr) {
if (val[index] >= MAX_ENUM_STATES)
sprintf(str, "Illegal Value (%d)", val[index]);
else if (val[index] >= ((struct dbr_ctrl_enum *)v)->no_str)
sprintf(str, "Enum Index Overflow (%d)", val[index]);
else
sprintf(str, "%s", ((struct dbr_ctrl_enum *)v)->strs[val[index]]);
} else
sprintf(str, "%d", val[index]);
}
}

View File

@@ -164,10 +164,9 @@ struct sockaddr caNetAddr::getSock() const
throw std::logic_error ( "caNetAddr::getSock (): address wasnt IP" );
}
struct sockaddr sa;
struct sockaddr_in *psain = reinterpret_cast <struct sockaddr_in*> ( & sa );
*psain = this->addr.ip;
return sa;
osiSockAddr addr;
addr.ia = this->addr.ip;
return addr.sa;
}
caNetAddr::operator sockaddr_in () const

View File

@@ -40,25 +40,25 @@ INC += db_access_routines.h
INC += db_convert.h
INC += dbUnitTest.h
# Generate menuGlobal.dbd automatically
DBD += menuGlobal.dbd
# Generate menuGlobal.dbd, not really by concatenation, see RULES
DBDCAT += menuGlobal.dbd
menuGlobal_DBD += menuAlarmSevr.dbd
menuGlobal_DBD += menuAlarmStat.dbd
menuGlobal_DBD += menuCompress.dbd
menuGlobal_DBD += menuFtype.dbd
menuGlobal_DBD += menuIvoa.dbd
menuGlobal_DBD += menuOmsl.dbd
menuGlobal_DBD += menuPini.dbd
menuGlobal_DBD += menuPost.dbd
menuGlobal_DBD += menuPriority.dbd
menuGlobal_DBD += menuScan.dbd
menuGlobal_DBD += menuYesNo.dbd
menuGlobal_DBD += menuSimm.dbd
DBDINC += $(basename $(menuGlobal_DBD))
DBDINC += menuScan
DBDINC += dbCommon
HTMLS += $(patsubst %.dbd.pod,%.html,$(notdir $(wildcard ../db/menu*.dbd.pod)))
dbMenusPod = $(notdir $(wildcard ../db/menu*.dbd.pod))
HTMLS += $(patsubst %.dbd.pod,%.html,$(menusPod))
dbCore_SRCS += dbLock.c
dbCore_SRCS += dbAccess.c

View File

@@ -14,9 +14,14 @@
dbCommon.h$(DEP): $(IOCDIR)/db/dbCommonRecord.dbd $(IOCDIR)/db/RULES
@$(RM) $@
@$(DBTORECORDTYPEH) -D -I ../db -o $(COMMONDEP_TARGET) $< > $@
@echo "$(COMMONDEP_TARGET): ../Makefile" >> $@
$(COMMON_DIR)/dbCommon.h: $(IOCDIR)/db/dbCommonRecord.dbd
$(COMMON_DIR)/dbCommon.h: $(IOCDIR)/db/dbCommonRecord.dbd $(IOCDIR)/db/RULES
@$(RM) $(notdir $@)
$(DBTORECORDTYPEH) -I ../db -o $(notdir $@) $<
@$(MV) $(notdir $@) $@
$(COMMON_DIR)/menuGlobal.dbd: $(IOCDIR)/db/Makefile $(IOCDIR)/db/RULES
# This is a target-specific variable
$(COMMON_DIR)/menuGlobal.dbd: DBDCAT_COMMAND = \
$(PERL) $(TOOLS)/makeIncludeDbd.pl $(menuGlobal_DBD) $(@F)

View File

@@ -65,6 +65,10 @@
epicsShareDef struct dbBase *pdbbase = 0;
epicsShareDef volatile int interruptAccept=FALSE;
/* Hook Routines */
epicsShareDef DB_LOAD_RECORDS_HOOK_ROUTINE dbLoadRecordsHook = NULL;
static short mapDBFToDBR[DBF_NTYPES] = {
/* DBF_STRING => */ DBR_STRING,
/* DBF_CHAR => */ DBR_CHAR,
@@ -711,7 +715,11 @@ int dbLoadDatabase(const char *file, const char *path, const char *subs)
int dbLoadRecords(const char* file, const char* subs)
{
return dbReadDatabase(&pdbbase, file, 0, subs);
int status = dbReadDatabase(&pdbbase, file, 0, subs);
if (!status && dbLoadRecordsHook)
dbLoadRecordsHook(file, subs);
return status;
}
@@ -835,17 +843,15 @@ long dbGet(DBADDR *paddr, short dbrType,
return S_db_badDbrtype;
}
/* For array field, the rset function
/* For SPC_DBADDR fields, the rset function
* get_array_info() is allowed to modify
* paddr->pfield. So we store the original
* value and restore it later.
*/
pfieldsave = paddr->pfield;
/* check for array */
if ((!pfl || pfl->type == dbfl_type_rec) &&
paddr->pfldDes->special == SPC_DBADDR &&
no_elements > 1 &&
/* Update field info */
if (paddr->pfldDes->special == SPC_DBADDR &&
(prset = dbGetRset(paddr)) &&
prset->get_array_info) {
status = prset->get_array_info(paddr, &no_elements, &offset);
@@ -1171,7 +1177,9 @@ long dbPut(DBADDR *paddr, short dbrType,
long no_elements = paddr->no_elements;
long special = paddr->special;
void *pfieldsave = paddr->pfield;
struct rset *prset = dbGetRset(paddr);
long status = 0;
long offset;
dbFldDes *pfldDes;
int isValueField;
@@ -1195,31 +1203,32 @@ long dbPut(DBADDR *paddr, short dbrType,
if (status) return status;
}
if (paddr->pfldDes->special == SPC_DBADDR &&
prset && prset->get_array_info) {
long dummy;
status = prset->get_array_info(paddr, &dummy, &offset);
/* paddr->pfield may be modified */
if (status) goto done;
} else
offset = 0;
if (no_elements <= 1) {
status = dbFastPutConvertRoutine[dbrType][field_type](pbuffer,
paddr->pfield, paddr);
nRequest = 1;
} else {
struct rset *prset = dbGetRset(paddr);
long offset = 0;
if (no_elements < nRequest)
nRequest = no_elements;
status = dbPutConvertRoutine[dbrType][field_type](paddr, pbuffer,
nRequest, no_elements, offset);
}
if (status) goto done;
if (paddr->pfldDes->special == SPC_DBADDR &&
prset && prset->get_array_info) {
long dummy;
status = prset->get_array_info(paddr, &dummy, &offset);
/* paddr->pfield may be modified */
}
if (no_elements < nRequest) nRequest = no_elements;
if (!status)
status = dbPutConvertRoutine[dbrType][field_type](paddr, pbuffer,
nRequest, no_elements, offset);
/* update array info */
if (!status &&
paddr->pfldDes->special == SPC_DBADDR &&
prset && prset->put_array_info) {
status = prset->put_array_info(paddr, nRequest);
}
/* update array info */
if (paddr->pfldDes->special == SPC_DBADDR &&
prset && prset->put_array_info) {
status = prset->put_array_info(paddr, nRequest);
}
if (status) goto done;

View File

@@ -233,9 +233,14 @@ epicsShareFunc long dbBufferSize(
short dbrType,long options,long nRequest);
epicsShareFunc long dbValueSize(short dbrType);
/* Hook Routine */
typedef void (*DB_LOAD_RECORDS_HOOK_ROUTINE)(const char* filename,
const char* substitutions);
epicsShareExtern DB_LOAD_RECORDS_HOOK_ROUTINE dbLoadRecordsHook;
epicsShareFunc int dbLoadDatabase(
const char *filename, const char *path, const char *substitutions);
epicsShareFunc int dbLoadRecords(
const char* filename, const char* substitutions);

View File

@@ -48,7 +48,6 @@
#include "dbDefs.h"
#include "ellLib.h"
#include "epicsEvent.h"
#include "epicsExit.h"
#include "epicsMutex.h"
#include "epicsThread.h"
#include "epicsTime.h"
@@ -252,11 +251,6 @@ static long FIND_CONT_NODE(
return(0);
}
static void dbBkptExit(void *junk) {
epicsMutexDestroy(bkpt_stack_sem);
bkpt_stack_sem = NULL;
}
/*
* Initialise the breakpoint stack
*/
@@ -265,7 +259,6 @@ void dbBkptInit(void)
if (! bkpt_stack_sem) {
bkpt_stack_sem = epicsMutexMustCreate();
lset_stack_count = 0;
epicsAtExit(dbBkptExit, NULL);
}
}

View File

@@ -192,7 +192,7 @@ void dbcaStats(int *pchans, int *pdiscon)
caLink *pca = (caLink *)plink->value.pv_link.pvt;
ncalinks++;
if (pca && ca_state(pca->chid) == cs_conn) {
if (pca && pca->chid && ca_state(pca->chid) == cs_conn) {
nconnected++;
}
}

View File

@@ -53,7 +53,7 @@ static void *dbChannelFreeList;
static void *chFilterFreeList;
static void *dbchStringFreeList;
static void dbChannelExit(void* junk)
void dbChannelExit(void)
{
freeListCleanup(dbChannelFreeList);
freeListCleanup(chFilterFreeList);
@@ -69,7 +69,6 @@ void dbChannelInit (void)
freeListInitPvt(&dbChannelFreeList, sizeof(dbChannel), 128);
freeListInitPvt(&chFilterFreeList, sizeof(chFilter), 64);
freeListInitPvt(&dbchStringFreeList, sizeof(epicsOldString), 128);
epicsAtExit(dbChannelExit, NULL);
}
static void chf_value(parseContext *parser, parse_result *presult)
@@ -762,7 +761,7 @@ void dbChannelMakeArrayCopy(void *pvt, db_field_log *pfl, dbChannel *chan)
void *p;
struct dbCommon *prec = dbChannelRecord(chan);
if (!pfl->type == dbfl_type_rec) return;
if (pfl->type != dbfl_type_rec) return;
pfl->type = dbfl_type_ref;
pfl->stat = prec->stat;

View File

@@ -150,6 +150,7 @@ struct dbCommon;
struct dbFldDes;
epicsShareFunc void dbChannelInit (void);
epicsShareFunc void dbChannelExit(void);
epicsShareFunc long dbChannelTest(const char *name);
epicsShareFunc dbChannel * dbChannelCreate(const char *name);
epicsShareFunc long dbChannelOpen(dbChannel *chan);

View File

@@ -46,6 +46,7 @@
#include "dbFldTypes.h"
#include "dbLock.h"
#include "link.h"
#include "special.h"
#define EVENTSPERQUE 32
#define EVENTENTRIES 4 /* the number of que entries for each event */
@@ -452,7 +453,8 @@ dbEventSubscription db_add_event (
* communication (for other types they get whatever happens to be
* there upon wakeup)
*/
if( dbChannelElements(chan) == 1 &&
if (dbChannelElements(chan) == 1 &&
dbChannelSpecial(chan) != SPC_DBADDR &&
dbChannelFieldSize(chan) <= sizeof(union native_value)) {
pevent->useValque = TRUE;
}
@@ -824,7 +826,7 @@ unsigned int caEventMask
/*
* Only send event msg if they are waiting on the field which
* changed or pval==NULL and waiting on alarms and alarms changed
* changed or pval==NULL, and are waiting on matching event
*/
if ( (dbChannelField(pevent->chan) == (void *)pField || pField==NULL) &&
(caEventMask & pevent->select)) {

View File

@@ -110,15 +110,6 @@ typedef struct lockRecord {
dbCommon *precord;
} lockRecord;
static void dbLockExit(void *junk)
{
epicsMutexDestroy(globalLock);
epicsMutexDestroy(lockSetModifyLock);
globalLock = NULL;
lockSetModifyLock = NULL;
dbLockIsInitialized = FALSE;
}
/*private routines */
static void dbLockInitialize(void)
{
@@ -129,7 +120,6 @@ static void dbLockInitialize(void)
globalLock = epicsMutexMustCreate();
lockSetModifyLock = epicsMutexMustCreate();
dbLockIsInitialized = TRUE;
epicsAtExit(dbLockExit,NULL);
}
static lockSet * allocLockSet(

View File

@@ -299,7 +299,7 @@ static void notifyCallback(CALLBACK *pcallback)
callDone(precord, ppn);
}
static void dbProcessNotifyExit(void* junk)
void dbProcessNotifyExit(void)
{
assert(ellCount(&pnotifyGlobal->freeList)==0);
epicsMutexDestroy(pnotifyGlobal->lock);
@@ -314,7 +314,6 @@ void dbProcessNotifyInit(void)
pnotifyGlobal = dbCalloc(1,sizeof(notifyGlobal));
pnotifyGlobal->lock = epicsMutexMustCreate();
ellInit(&pnotifyGlobal->freeList);
epicsAtExit(dbProcessNotifyExit, NULL);
}
void dbProcessNotify(processNotify *ppn)

View File

@@ -76,6 +76,7 @@ epicsShareFunc void dbNotifyCancel(processNotify *pprocessNotify);
/* dbProcessNotifyInit called by iocInit */
epicsShareFunc void dbProcessNotifyInit(void);
epicsShareFunc void dbProcessNotifyExit(void);
/*dbNotifyAdd called by dbScanPassive and dbScanLink*/
epicsShareFunc void dbNotifyAdd(

View File

@@ -1,15 +0,0 @@
#*************************************************************************
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
# National Laboratory.
# Copyright (c) 2002 The Regents of the University of California, as
# Operator of Los Alamos National Laboratory.
# EPICS BASE Versions 3.13.7
# and higher are distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
menu(menuCompress) {
choice(menuCompressN_to_1_First_Value,"N to 1 First Value")
choice(menuCompressN_to_1_Low_Value,"N to 1 Low Value")
choice(menuCompressN_to_1_High_Value,"N to 1 High Value")
choice(menuCompressN_to_1_Average,"N to 1 Average")
}

View File

@@ -45,7 +45,7 @@
/* Hook Routines */
RECGBL_ALARM_HOOK_ROUTINE recGblAlarmHook = NULL;
epicsShareDef RECGBL_ALARM_HOOK_ROUTINE recGblAlarmHook = NULL;
/* local routines */
static void getMaxRangeValues(short field_type, double *pupper_limit,

View File

@@ -36,7 +36,7 @@ struct dbCommon;
typedef void (*RECGBL_ALARM_HOOK_ROUTINE)(struct dbCommon *prec,
epicsEnum16 prev_sevr, epicsEnum16 prev_stat);
extern RECGBL_ALARM_HOOK_ROUTINE recGblAlarmHook;
epicsShareExtern RECGBL_ALARM_HOOK_ROUTINE recGblAlarmHook;
/* Global Record Support Routines */

View File

@@ -19,6 +19,7 @@ dbTestIoc_LIBS = dbCore
TARGETS += $(COMMON_DIR)/dbTestIoc.dbd
dbTestIoc_DBD += menuGlobal.dbd
dbTestIoc_DBD += menuConvert.dbd
dbTestIoc_DBD += menuScan.dbd
dbTestIoc_DBD += xRecord.dbd
dbTestIoc_DBD += dbLinkdset.dbd
TESTFILES += $(COMMON_DIR)/dbTestIoc.dbd ../xRecord.db
@@ -67,9 +68,17 @@ dbStateTest_SRCS += dbStateTest.c
testHarness_SRCS += dbStateTest.c
TESTS += dbStateTest
TESTPROD_HOST += dbCaStatsTest
dbCaStatsTest_SRCS += dbCaStatsTest.c
dbCaStatsTest_SRCS += dbTestIoc_registerRecordDeviceDriver.cpp
testHarness_SRCS += dbCaStatsTest.c
TESTS += dbCaStatsTest
TESTFILES += ../dbCaStatsTest.db
TARGETS += $(COMMON_DIR)/scanIoTest.dbd
scanIoTest_DBD += menuGlobal.dbd
scanIoTest_DBD += menuConvert.dbd
scanIoTest_DBD += menuScan.dbd
scanIoTest_DBD += yRecord.dbd
TESTPROD_HOST += scanIoTest
scanIoTest_SRCS += scanIoTest.c

View File

@@ -12,6 +12,7 @@
*/
#include <string.h>
#include <stdio.h>
#include "chfPlugin.h"
#include "dbStaticLib.h"
@@ -540,7 +541,7 @@ MAIN(chfPluginTest)
dbChannel *pch;
db_field_log *pfl;
#ifdef WIN32
#if defined(WIN32) && (!defined(_MINGW) || __MSVCRT_VERSION__ >= 0x0800)
_set_output_format(_TWO_DIGIT_EXPONENT);
#endif

View File

@@ -0,0 +1,4 @@
record(x, "e1") {
}
record(x, "e2") {
}

View File

@@ -0,0 +1,73 @@
/*************************************************************************\
* Copyright (c) 2014 ITER Organization.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Author: Ralph Lange <ralph.lange@gmx.de>
*/
#include "dbCaTest.h"
#include "dbAccess.h"
#include "dbUnitTest.h"
#include "testMain.h"
#include "dbAccess.h"
#include "errlog.h"
void dbTestIoc_registerRecordDeviceDriver(struct dbBase *);
static
void testCaStats(void) {
int channels;
int disconnected;
testDiag("Check dbcaStats");
testdbPrepare();
testdbReadDatabase("dbTestIoc.dbd", NULL, NULL);
dbTestIoc_registerRecordDeviceDriver(pdbbase);
testdbReadDatabase("dbCaStats.db", NULL, NULL);
eltc(0);
testIocInitOk();
eltc(1);
testDiag("No CA links");
channels = disconnected = -1;
dbcaStats(&channels, &disconnected);
testOk(channels==0, "channels==0 (got %d)", channels);
testOk(disconnected==0, "disconnected==0 (got %d)", disconnected);
testDiag("One CA link, disconnected");
testdbPutFieldOk("e2.INP", DBR_STRING, "e12 CA", 1);
channels = disconnected = -1;
dbcaStats(&channels, &disconnected);
testOk(channels==1, "channels==1 (got %d)", channels);
testOk(disconnected==1, "disconnected==1 (got %d)", disconnected);
/* Connected CA links can not be tested without fully starting the IOC
which we will skip for the moment as it is not allowed inside the vxWorks/RTEMS test harness.
The above is good enough to check for bug lp:1394212 */
testIocShutdownOk();
testdbCleanup();
}
MAIN(dbCaStatsTest)
{
testPlan(0);
testCaStats();
return testDone();
}

View File

@@ -18,7 +18,9 @@
int testdbConvert(void);
int callbackTest(void);
int callbackParallelTest(void);
int dbStateTest(void);
int dbCaStatsTest(void);
int dbShutdownTest(void);
int scanIoTest(void);
int dbLockTest(void);
@@ -34,7 +36,9 @@ void epicsRunDbTests(void)
runTest(testdbConvert);
runTest(callbackTest);
runTest(callbackParallelTest);
runTest(dbStateTest);
runTest(dbCaStatsTest);
runTest(dbShutdownTest);
runTest(scanIoTest);
runTest(dbLockTest);

View File

@@ -315,7 +315,7 @@ MAIN(scanIoTest)
}
}
epicsThreadSleep(0.1);
epicsThreadSleep(1.0);
testOk((orderFail==0), "No out-of-order processing");

View File

@@ -72,6 +72,9 @@
static enum {
iocVirgin, iocBuilding, iocBuilt, iocRunning, iocPaused, iocStopped
} iocState = iocVirgin;
static enum {
buildRSRV, buildIsolated
} iocBuildMode;
/* define forward references*/
static int checkDatabase(dbBase *pdbbase);
@@ -183,6 +186,7 @@ int iocBuild(void)
rsrv_init();
status = iocBuild_3();
if (!status) iocBuildMode = buildRSRV;
return status;
}
@@ -199,6 +203,7 @@ int iocBuildIsolated(void)
if (status) return status;
status = iocBuild_3();
if (!status) iocBuildMode = buildIsolated;
return status;
}
@@ -672,13 +677,18 @@ int iocShutdown(void)
{
if (iocState == iocVirgin || iocState == iocStopped) return 0;
iterateRecords(doCloseLinks, NULL);
scanShutdown();
callbackShutdown();
iterateRecords(doFreeRecord, NULL);
dbLockCleanupRecords(pdbbase);
asShutdown();
iocshFree();
if (iocBuildMode==buildIsolated) {
scanShutdown();
callbackShutdown();
iterateRecords(doFreeRecord, NULL);
dbLockCleanupRecords(pdbbase);
asShutdown();
dbChannelExit();
dbProcessNotifyExit();
iocshFree();
}
iocState = iocStopped;
iocBuildMode = buildRSRV;
return 0;
}

View File

@@ -453,15 +453,6 @@ static void errlogExitHandler(void *pvt)
pvtData.atExit = 1;
epicsEventSignal(pvtData.waitForWork);
epicsEventMustWait(pvtData.waitForExit);
free(pvtData.pbuffer);
epicsMutexDestroy(pvtData.flushLock);
epicsEventDestroy(pvtData.flush);
epicsEventDestroy(pvtData.waitForFlush);
epicsMutexDestroy(pvtData.listenerLock);
epicsMutexDestroy(pvtData.msgQueueLock);
epicsEventDestroy(pvtData.waitForWork);
epicsEventDestroy(pvtData.waitForExit);
}
struct initArgs {

View File

@@ -13,7 +13,7 @@ SRC_DIRS += $(LIBCOM)/flex
parse_YACCOPT = -l -d
SKELETON_FILE = include/flex.skel.static
SKELETON_FILE = flex.skel.static
parse_CPPFLAGS = -DDEFAULT_SKELETON_FILE=$(SKELETON_FILE)

View File

@@ -59,7 +59,10 @@ static void echoCallFunc(const iocshArgBuf *args)
{
char *str = args[0].sval;
dbTranslateEscape(str, str); /* in-place is safe */
if (str)
dbTranslateEscape(str, str); /* in-place is safe */
else
str = "";
printf("%s\n", str);
}
@@ -69,9 +72,8 @@ static const iocshArg * const chdirArgs[1] = {&chdirArg0};
static const iocshFuncDef chdirFuncDef = {"cd",1,chdirArgs};
static void chdirCallFunc(const iocshArgBuf *args)
{
int status;
status = chdir(args[0].sval);
if (status) {
if (args[0].sval == NULL ||
chdir(args[0].sval)) {
fprintf(stderr, "Invalid directory path, ignored\n");
}
}

View File

@@ -18,7 +18,6 @@
#define epicsExportSharedSymbols
#include "envDefs.h"
#include "errlog.h"
#include "logClient.h"
#include "iocLog.h"
@@ -90,9 +89,6 @@ static logClientId iocLogClientInit (void)
return NULL;
}
id = logClientCreate (addr, port);
if (id != NULL) {
errlogAddListener ( logClientSendMessage, id );
}
return id;
}
@@ -139,13 +135,3 @@ logClientId epicsShareAPI logClientInit (void)
{
return iocLogClientInit ();
}
/*
* logClientSendMessage (); deprecated
*/
void logClientSendMessage ( logClientId id, const char * message )
{
if ( !iocLogDisable ) {
logClientSend (id, message);
}
}

View File

@@ -24,6 +24,8 @@
#define epicsExportSharedSymbols
#include "dbDefs.h"
#include "epicsEvent.h"
#include "iocLog.h"
#include "errlog.h"
#include "epicsMutex.h"
#include "epicsThread.h"
#include "epicsTime.h"
@@ -152,6 +154,8 @@ static void logClientDestroy (logClientId id)
return;
}
errlogRemoveListeners ( logClientSendMessage, (void *) pClient );
logClientClose ( pClient );
epicsMutexDestroy ( pClient->mutex );
@@ -545,6 +549,8 @@ logClientId epicsShareAPI logClientCreate (
pClient->name, LOG_SERVER_CREATE_CONNECT_SYNC_TIMEOUT );
}
errlogAddListener ( logClientSendMessage, (void *) pClient );
return (void *) pClient;
}
@@ -573,6 +579,16 @@ void epicsShareAPI logClientShow (logClientId id, unsigned level)
}
}
/*
* logClientSendMessage (); deprecated
*/
void logClientSendMessage ( logClientId id, const char * message )
{
if ( !iocLogDisable ) {
logClientSend (id, message);
}
}
/*
* iocLogPrefix()
*/

View File

@@ -259,9 +259,10 @@ epicsShareAPI macPutValue(
* a macro from all scopes will still be needed by iocshEnvClear
*/
while ( ( entry = lookup( handle, name, FALSE ) ) != NULL ) {
int done = strcmp(entry->type, "environment variable") == 0;
delete( handle, entry );
if (strcmp(entry->type, "environment variable") == 0)
if (done)
break;
}

View File

@@ -29,6 +29,7 @@
#define epicsExportSharedSymbols
#include "ellLib.h"
#include "errlog.h"
#include "epicsThread.h"
#include "epicsMutex.h"
#include "cantProceed.h"
@@ -48,10 +49,13 @@ typedef struct exitPvt {
int atExitDebug = 0;
static epicsThreadOnceId exitPvtOnce = EPICS_THREAD_ONCE_INIT;
static epicsThreadOnceId exitLaterOnce = EPICS_THREAD_ONCE_INIT;
static exitPvt * pExitPvtPerProcess = 0;
static epicsMutexId exitPvtLock = 0;
static epicsThreadPrivateId exitPvtPerThread = 0;
static int exitLaterStatus;
static void destroyExitPvt(exitPvt * pep)
{
ellFree ( &pep->list );
@@ -179,6 +183,26 @@ epicsShareFunc void epicsExit(int status)
exit(status);
}
static void exitNow(void *junk)
{
epicsExit(exitLaterStatus);
}
static void exitLaterOnceFunc(void *raw)
{
int *status = raw;
exitLaterStatus = *status;
epicsThreadMustCreate("exitLater",
epicsThreadPriorityLow,
epicsThreadGetStackSize(epicsThreadStackSmall),
&exitNow, NULL);
}
epicsShareFunc void epicsExitLater(int status)
{
epicsThreadOnce(&exitLaterOnce, &exitLaterOnceFunc, &status);
}
#include "epicsExport.h"
epicsExportAddress(int,atExitDebug);

View File

@@ -18,6 +18,7 @@ extern "C" {
typedef void (*epicsExitFunc)(void *arg);
epicsShareFunc void epicsExit(int status);
epicsShareFunc void epicsExitLater(int status);
epicsShareFunc void epicsExitCallAtExits(void);
epicsShareFunc int epicsAtExit3(epicsExitFunc func, void *arg, const char* name);
#define epicsAtExit(F,A) epicsAtExit3(F,A,#F)

View File

@@ -367,8 +367,12 @@ epicsStrtod(const char *str, char **endp)
else
return strtoul(str, endp, 16);
}
if (!isalpha((int)*cp))
return strtod(str, endp);
if (!isalpha((int)*cp)) {
res = strtod(str, endp);
if (isinf(res))
errno = ERANGE;
return res;
}
if (epicsStrnCaseCmp("NAN", cp, 3) == 0) {
res = epicsNAN;

View File

@@ -29,143 +29,165 @@
#include "epicsString.h"
/* Deprecated, use epicsStrnRawFromEscaped() instead */
int dbTranslateEscape(char *to, const char *from)
int dbTranslateEscape(char *dst, const char *src)
{
size_t big_enough = strlen(from)+1;
return epicsStrnRawFromEscaped(to, big_enough, from, big_enough);
size_t big_enough = strlen(src) + 1;
return epicsStrnRawFromEscaped(dst, big_enough, src, big_enough);
}
int epicsStrnRawFromEscaped(char *to, size_t outsize, const char *from,
size_t inlen)
int epicsStrnRawFromEscaped(char *dst, size_t dstlen, const char *src,
size_t srclen)
{
const char *pfrom = from;
char *pto = to;
char c;
size_t nto = 0, nfrom = 0;
int rem = dstlen;
int ndst = 0;
while ((c = *pfrom++) && nto < outsize && nfrom < inlen) {
nfrom++;
if (c == '\\') {
if (nfrom >= inlen || *pfrom == '\0') break;
switch (*pfrom) {
case 'a': pfrom++; nfrom++; *pto++ = '\a' ; nto++; break;
case 'b': pfrom++; nfrom++; *pto++ = '\b' ; nto++; break;
case 'f': pfrom++; nfrom++; *pto++ = '\f' ; nto++; break;
case 'n': pfrom++; nfrom++; *pto++ = '\n' ; nto++; break;
case 'r': pfrom++; nfrom++; *pto++ = '\r' ; nto++; break;
case 't': pfrom++; nfrom++; *pto++ = '\t' ; nto++; break;
case 'v': pfrom++; nfrom++; *pto++ = '\v' ; nto++; break;
case '\\': pfrom++; nfrom++; *pto++ = '\\' ; nto++; break;
case '\?': pfrom++; nfrom++; *pto++ = '\?' ; nto++; break;
case '\'': pfrom++; nfrom++; *pto++ = '\'' ; nto++; break;
case '\"': pfrom++; nfrom++; *pto++ = '\"' ; nto++; break;
case '0' :case '1' :case '2' :case '3' :
case '4' :case '5' :case '6' :case '7' :
{
int i;
char strval[4] = {0,0,0,0};
unsigned int ival;
unsigned char *pchar;
while (srclen--) {
int c = *src++;
#define OUT(chr) if (--rem > 0) ndst++, *dst++ = chr
for (i=0; i<3; i++) {
if ((*pfrom < '0') || (*pfrom > '7')) break;
strval[i] = *pfrom++; nfrom++;
}
sscanf(strval,"%o",&ival);
pchar = (unsigned char *)(pto++); nto++;
*pchar = (unsigned char)(ival);
}
break;
case 'x' :
{
int i;
char strval[3] = {0,0,0};
unsigned int ival;
unsigned char *pchar;
if (!c) break;
pfrom++; /*skip the x*/
for (i=0; i<2; i++) {
if (!isxdigit((int)*pfrom)) break;
strval[i] = *pfrom++; nfrom++;
}
sscanf(strval,"%x",&ival);
pchar = (unsigned char *)(pto++); nto++;
*pchar = (unsigned char)(ival);
}
break;
default:
*pto++ = *pfrom++; nfrom++; nto++;
}
} else {
*pto++ = c; nto++;
input:
if (c != '\\') {
OUT(c);
continue;
}
}
*pto = '\0'; /* NOTE that nto does not have to be incremented */
return nto;
}
int epicsStrnEscapedFromRaw(char *outbuf, size_t outsize, const char *inbuf,
size_t inlen)
{
int maxout = outsize;
int nout = 0;
int len;
char *outpos = outbuf;
if (!srclen-- || !(c = *src++)) break;
while (inlen--) {
char c = *inbuf++;
switch (c) {
case '\a': len = epicsSnprintf(outpos, maxout, "\\a"); break;
case '\b': len = epicsSnprintf(outpos, maxout, "\\b"); break;
case '\f': len = epicsSnprintf(outpos, maxout, "\\f"); break;
case '\n': len = epicsSnprintf(outpos, maxout, "\\n"); break;
case '\r': len = epicsSnprintf(outpos, maxout, "\\r"); break;
case '\t': len = epicsSnprintf(outpos, maxout, "\\t"); break;
case '\v': len = epicsSnprintf(outpos, maxout, "\\v"); break;
case '\\': len = epicsSnprintf(outpos, maxout, "\\\\"); ; break;
case '\'': len = epicsSnprintf(outpos, maxout, "\\'"); break;
case '\"': len = epicsSnprintf(outpos, maxout, "\\\""); break;
default:
if (isprint((int)c))
len = epicsSnprintf(outpos, maxout, "%c", c);
else
len = epicsSnprintf(outpos, maxout, "\\%03o",
(unsigned char)c);
break;
}
if (len<0) return -1;
nout += len;
if (nout < outsize) {
maxout -= len;
outpos += len;
} else {
outpos = outpos + maxout -1;
maxout = 1;
case 'a': OUT('\a'); break;
case 'b': OUT('\b'); break;
case 'f': OUT('\f'); break;
case 'n': OUT('\n'); break;
case 'r': OUT('\r'); break;
case 't': OUT('\t'); break;
case 'v': OUT('\v'); break;
case '\\': OUT('\\'); break;
case '\'': OUT('\''); break;
case '\"': OUT('\"'); break;
case '0' :case '1' :case '2' :case '3' :
case '4' :case '5' :case '6' :case '7' :
{ /* \ooo */
unsigned int u = c - '0';
if (!srclen-- || !(c = *src++)) {
OUT(u); goto done;
}
if (c < '0' || c > '7') {
OUT(u); goto input;
}
u = u << 3 | (c - '0');
if (!srclen-- || !(c = *src++)) {
OUT(u); goto done;
}
if (c < '0' || c > '7') {
OUT(u); goto input;
}
u = u << 3 | (c - '0');
if (u > 0377) {
/* Undefined behaviour! */
}
OUT(u);
}
break;
case 'x' :
{ /* \xXXX... */
unsigned int u = 0;
if (!srclen-- || !(c = *src++))
goto done;
while (isxdigit(c)) {
u = u << 4 | ((c > '9') ? toupper(c) - 'A' + 10 : c - '0');
if (u > 0xff) {
/* Undefined behaviour! */
}
if (!srclen-- || !(c = *src++)) {
OUT(u);
goto done;
}
}
OUT(u);
goto input;
}
default:
OUT(c);
}
#undef OUT
}
*outpos = '\0';
return nout;
done:
if (dstlen)
*dst = '\0';
return ndst;
}
size_t epicsStrnEscapedFromRawSize(const char *inbuf, size_t inlen)
int epicsStrnEscapedFromRaw(char *dst, size_t dstlen, const char *src,
size_t srclen)
{
size_t nout = inlen;
int rem = dstlen;
int ndst = 0;
while (inlen--) {
char c = *inbuf++;
if (dst == src)
return -1;
while (srclen--) {
int c = *src++;
#define OUT(chr) ndst++; if (--rem > 0) *dst++ = chr
switch (c) {
case '\a': OUT('\\'); OUT('a'); break;
case '\b': OUT('\\'); OUT('b'); break;
case '\f': OUT('\\'); OUT('f'); break;
case '\n': OUT('\\'); OUT('n'); break;
case '\r': OUT('\\'); OUT('r'); break;
case '\t': OUT('\\'); OUT('t'); break;
case '\v': OUT('\\'); OUT('v'); break;
case '\\': OUT('\\'); OUT('\\'); break;
case '\'': OUT('\\'); OUT('\''); break;
case '\"': OUT('\\'); OUT('\"'); break;
default:
if (isprint(c)) {
OUT(c);
break;
}
OUT('\\');
OUT('0' + ((c & 0300) >> 6));
OUT('0' + ((c & 0070) >> 3));
OUT('0' + (c & 0007));
}
#undef OUT
}
if (dstlen)
*dst = '\0';
return ndst;
}
size_t epicsStrnEscapedFromRawSize(const char *src, size_t srclen)
{
size_t ndst = srclen;
while (srclen--) {
int c = *src++;
switch (c) {
case '\a': case '\b': case '\f': case '\n':
case '\r': case '\t': case '\v': case '\\':
case '\'': case '\"':
nout++;
ndst++;
break;
default:
if (!isprint((int)c))
nout += 3;
if (!isprint(c))
ndst += 3;
}
}
return nout;
return ndst;
}
int epicsStrCaseCmp(const char *s1, const char *s2)

View File

@@ -17,6 +17,7 @@
#define INC_epicsTypes_H
#include "shareLib.h"
#include "compilerDependencies.h"
#ifndef stringOf
# if defined (__STDC__ ) || defined (__cplusplus)
@@ -26,6 +27,11 @@
# endif
#endif
typedef enum {
epicsFalse = 0,
epicsTrue = 1
} epicsBoolean EPICS_DEPRECATED;
/*
* Architecture Independent Data Types
* These are sufficient for all our current archs

View File

@@ -17,6 +17,7 @@
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/prctl.h>
@@ -57,8 +58,10 @@ static void thread_hook(epicsThreadId pthreadInfo)
/* Set the name of the thread's process. Limited to 16 characters. */
char comm[16];
snprintf(comm, sizeof(comm), "%s", pthreadInfo->name);
prctl(PR_SET_NAME, comm, 0l, 0l, 0l);
if (strcmp(pthreadInfo->name, "_main_")) {
snprintf(comm, sizeof(comm), "%s", pthreadInfo->name);
prctl(PR_SET_NAME, comm, 0l, 0l, 0l);
}
pthreadInfo->lwpId = syscall(SYS_gettid);
}

View File

@@ -55,7 +55,7 @@
# define MS_InterlockedDecrement64 InterlockedDecrement64
# define MS_InterlockedExchange64 InterlockedExchange64
# define MS_InterlockedExchangeAdd64 InterlockedExchangeAdd64
# define MS_InterlockedCompareExchange InterlockedCompareExchange64
# define MS_InterlockedCompareExchange64 InterlockedCompareExchange64
#endif
#include "epicsAtomicMS.h"

View File

@@ -14,10 +14,15 @@
int epicsBackTrace(void **buf, int buf_sz)
{
/* Docs say that (for some windows versions) the sum of
* skipped + captured frames must be less than 63
*/
if ( buf_sz >= 63 )
buf_sz = 62;
return CaptureStackBackTrace(0, buf_sz, buf, 0);
#ifdef CaptureStackBackTrace
/* Docs say that (for some windows versions) the sum of
* skipped + captured frames must be less than 63
*/
if ( buf_sz >= 63 )
buf_sz = 62;
return CaptureStackBackTrace(0, buf_sz, buf, 0);
#else
/* Older versions of MinGW */
return -1;
#endif
}

View File

@@ -23,8 +23,10 @@ epicsShareFunc double epicsStrtod(const char *str, char **endp);
* Older compilers have these equivalents though
*/
#define strtoll _strtoi64
#define strtoull _strtoui64
#ifndef _MINGW
# define strtoll _strtoi64
# define strtoull _strtoui64
#endif
#ifdef __cplusplus
}

View File

@@ -12,7 +12,7 @@
#include <stdio.h>
#include "epicsDynLink.h"
#include "epicsFindSymbol.h"
#include "epicsExit.h"
extern "C" {
@@ -21,15 +21,12 @@ typedef int (*sysAtReboot_t)(void(func)(void));
void atRebootRegister(void)
{
STATUS status;
sysAtReboot_t sysAtReboot;
SYM_TYPE type;
sysAtReboot_t sysAtReboot = (sysAtReboot_t) epicsFindSymbol("_sysAtReboot");
status = symFindByNameEPICS(sysSymTbl, "_sysAtReboot",
(char **)&sysAtReboot, &type);
if (status == OK) {
status = sysAtReboot(epicsExitCallAtExits);
if (status != OK) {
if (sysAtReboot) {
STATUS status = sysAtReboot(epicsExitCallAtExits);
if (status) {
printf("atReboot: sysAtReboot returned error %d\n", status);
}
} else {

View File

@@ -1,92 +1,95 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* Copyright (c) 2014 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* $Id $
*
* Comments from original version:
* On the MIPS processor, all symbols do not have the prepended underscore.
* Here we redefine symFindByName to look at the second character of the
* name string.
*
* On various RISC processors (at least MIPS and PPC), symbols do not have
* the prepended underscore. Here we redefine symFindByName so that, if the
* name lookup fails and if the first character of the name is "_", the
* lookup is repeated starting at the second character of the name string.
*
* 01a,08apr97,bdg created.
* 02a,03apr97,npr changed from mips.h into symFindByNameMips.c
* 03a,03jun98,wfl changed Mips -> EPICS and avoid architecture knowledge
* On 68K targets, all symbols have an underscore prepended to their name.
* This code permits both standards to work, as long as you're not looking
* for a symbol name that actually begins with an underscore.
*/
#include <string.h>
#include "epicsDynLink.h"
STATUS symFindByNameEPICS(
SYMTAB_ID symTblId,
char *name,
char **ppvalue,
SYM_TYPE *pType )
#if _WRS_VXWORKS_MAJOR < 6 || _WRS_VXWORKS_MINOR < 9
static int symNoUnderscore(SYMTAB_ID symTblId)
{
static int leadingUnderscore = 1;
static int init = 0;
STATUS status = ERROR;
static int init = 0;
static int noUnderscore = 0;
if (!init) {
char *pSymValue;
SYM_TYPE type;
status = symFindByName ( symTblId, "symFindByNameEPICS", &pSymValue, &type );
if (status==OK) {
leadingUnderscore = 0;
}
init = 1;
}
if (!init) {
char name[] = "symFindByNameEPICS";
char *pSymValue;
SYM_TYPE type;
if (name[0] != '_' || leadingUnderscore) {
status = symFindByName ( symTblId, name, ppvalue, pType );
}
else {
status = symFindByName ( symTblId, (name+1), ppvalue, pType );
}
return status;
if (symFindByName(symTblId, name, &pSymValue, &type) == OK)
noUnderscore = 1;
init = 1;
}
return noUnderscore;
}
STATUS symFindByNameAndTypeEPICS(
SYMTAB_ID symTblId,
char *name,
char **ppvalue,
SYM_TYPE *pType,
SYM_TYPE sType,
SYM_TYPE mask )
STATUS symFindByNameEPICS(SYMTAB_ID symTblId, char *name, char **ppvalue,
SYM_TYPE *pType)
{
static int leadingUnderscore = 1;
static int init = 0;
STATUS status = ERROR;
if (name[0] == '_' && symNoUnderscore(symTblId))
name++;
if (!init) {
char *pSymValue;
SYM_TYPE type;
status = symFindByName (symTblId, "symFindByNameAndTypeEPICS", &pSymValue, &type );
if (status==OK) {
leadingUnderscore = 0;
}
init = 1;
}
if (name[0] != '_' || leadingUnderscore) {
status = symFindByNameAndType ( symTblId, name, ppvalue, pType, sType, mask );
}
else if (leadingUnderscore) {
status = symFindByNameAndType ( symTblId, (name+1), ppvalue, pType, sType, mask );
}
return status;
return symFindByName(symTblId, name, ppvalue, pType);
}
STATUS symFindByNameAndTypeEPICS(SYMTAB_ID symTblId, char *name,
char **ppvalue, SYM_TYPE *pType, SYM_TYPE sType, SYM_TYPE mask)
{
if (name[0] == '_' && symNoUnderscore(symTblId))
name++;
return symFindByNameAndType(symTblId, name, ppvalue, pType, sType, mask);
}
#else /* VxWorks 6.9 deprecated the symFindBy routines */
STATUS symFindByNameEPICS(SYMTAB_ID symTblId, char *name, char **ppvalue,
SYM_TYPE *pType)
{
SYMBOL_DESC symDesc;
STATUS status;
memset(&symDesc, 0, sizeof(SYMBOL_DESC));
symDesc.mask = SYM_FIND_BY_NAME;
symDesc.name = name + (name[0] == '_');
status = symFind(sysSymTbl, &symDesc);
if (!status) {
*ppvalue = symDesc.value;
*pType = symDesc.type;
}
return status;
}
STATUS symFindByNameAndTypeEPICS(SYMTAB_ID symTblId, char *name,
char **ppvalue, SYM_TYPE *pType, SYM_TYPE sType, SYM_TYPE mask)
{
SYMBOL_DESC symDesc;
STATUS status;
memset(&symDesc, 0, sizeof(SYMBOL_DESC));
symDesc.mask = SYM_FIND_BY_NAME | SYM_FIND_BY_TYPE;
symDesc.name = name + (name[0] == '_');
symDesc.type = sType;
symDesc.typeMask = mask;
status = symFind(sysSymTbl, &symDesc);
if (!status) {
*ppvalue = symDesc.value;
*pType = symDesc.type;
}
return status;
}
#endif

View File

@@ -1,11 +1,10 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* Copyright (c) 2014 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
@@ -16,32 +15,22 @@
#ifndef epicsDynLinkh
#define epicsDynLinkh
#ifdef symFindByName
#undef symFindByName
#endif
#include "vxWorks.h"
#include "symLib.h"
#include "sysSymTbl.h"
#include "compilerDependencies.h"
#ifdef __cplusplus
extern "C" {
#endif
STATUS symFindByNameEPICS(
SYMTAB_ID symTblId,
char *name,
char **pvalue,
SYM_TYPE *pType);
/* Use epicsFindSymbol() instead of these */
STATUS symFindByNameAndTypeEPICS(
SYMTAB_ID symTblId,
char *name,
char **pvalue,
SYM_TYPE *pType,
SYM_TYPE sType,
SYM_TYPE mask);
STATUS symFindByNameEPICS(SYMTAB_ID symTblId, char *name, char **pvalue,
SYM_TYPE *pType) EPICS_DEPRECATED;
STATUS symFindByNameAndTypeEPICS(SYMTAB_ID symTblId, char *name, char **pvalue,
SYM_TYPE *pType, SYM_TYPE sType, SYM_TYPE mask) EPICS_DEPRECATED;
#ifdef __cplusplus
}

View File

@@ -56,7 +56,9 @@ epicsShareFunc void * epicsLoadLibrary(const char *name)
epicsShareFunc const char *epicsLoadError(void)
{
if (oldmsg) free(oldmsg);
if (oldmsg)
free(oldmsg);
oldmsg = errmsg;
errmsg = NULL;
return oldmsg;
@@ -65,22 +67,49 @@ epicsShareFunc const char *epicsLoadError(void)
void *epicsFindSymbol(const char *name)
{
STATUS status;
SYM_TYPE type;
#if _WRS_VXWORKS_MAJOR < 6 || _WRS_VXWORKS_MINOR < 9
char *pvalue;
status = symFindByName( sysSymTbl, (char *)name, &pvalue, &type );
if(status) {
if(name[0] == '_' ) {
status = symFindByName(sysSymTbl, (char *)(name+1), &pvalue, &type);
} else {
char *pname;
pname = dbmfMalloc(strlen(name) + 2);
strcpy(pname,"_");
strcat(pname,name);
status = symFindByName(sysSymTbl,pname, &pvalue, &type);
dbmfFree(pname);
}
SYM_TYPE type;
status = symFindByName(sysSymTbl, (char *)name, &pvalue, &type);
if (!status)
return pvalue;
if (name[0] == '_' ) {
status = symFindByName(sysSymTbl, (char *)(name+1), &pvalue, &type);
}
if(status) return(0);
return((void *)pvalue);
#if CPU_FAMILY == MC680X0
else {
char *pname = dbmfMalloc(strlen(name) + 2);
pname[0] = '_';
strcpy(pname + 1, name);
status = symFindByName(sysSymTbl, pname, &pvalue, &type);
dbmfFree(pname);
}
#endif
if (!status)
return pvalue;
#else
SYMBOL_DESC symDesc;
memset(&symDesc, 0, sizeof(SYMBOL_DESC));
symDesc.mask = SYM_FIND_BY_NAME;
symDesc.name = (char *) name;
status = symFind(sysSymTbl, &symDesc);
if (!status)
return symDesc.value;
if (name[0] == '_') {
symDesc.name++;
status = symFind(sysSymTbl, &symDesc);
if (!status)
return symDesc.value;
}
/* No need to prepend an '_'; 68K-only, no longer supported */
#endif
return 0;
}

View File

@@ -255,9 +255,9 @@ MAIN(epicsStdlibTest)
testOk(epicsScanULong("0xffffffff", &u, 0) && u == 0xffffffff,
"ULong '0xffffffff'");
testOk(epicsScanLLong("0x7fffffffffffffff", &ll, 0) &&
ll == 0x7fffffffffffffff, "LLong '0x7fffffffffffffff'");
ll == 0x7fffffffffffffffLL, "LLong '0x7fffffffffffffff'");
testOk(epicsScanULLong("0xffffffffffffffff", &ull, 0) &&
ull == 0xffffffffffffffff, "ULLong '0xffffffffffffffff'");
ull == 0xffffffffffffffffULL, "ULLong '0xffffffffffffffff'");
testOk(epicsScanFloat("0xffffff", &f) && f == 0xffffff,
"Float '0xffffff'");
testOk(epicsScanDouble("0xffffffff", &d) && d == 0xffffffff,
@@ -268,9 +268,9 @@ MAIN(epicsStdlibTest)
testOk(epicsScanULong("-0x7fffffff", &u, 0) && u == -0x7fffffff,
"ULong '-0x7fffffff'");
testOk(epicsScanLLong("-0x7fffffffffffffff", &ll, 0)
&& ll == -0x7fffffffffffffff, "LLong '-0x7fffffffffffffff'");
&& ll == -0x7fffffffffffffffLL, "LLong '-0x7fffffffffffffff'");
testOk(epicsScanULLong("-0x7fffffffffffffff", &ull, 0) &&
ull == -0x7fffffffffffffff, "ULLong '-0x7fffffffffffffff'");
ull == -0x7fffffffffffffffULL, "ULLong '-0x7fffffffffffffff'");
testOk(epicsScanFloat("-0xffffff", &f) && f == -0xffffff,
"Float '-0xffffff'");
testOk(epicsScanDouble("-0x7fffffff", &d) && d == -0x7fffffff,
@@ -328,12 +328,12 @@ MAIN(epicsStdlibTest)
"UInt32 '-0x100000000' => overflow");
testOk(!epicsParseInt64("0x7fffffffffffffff", &i64, 0, NULL) &&
i64 == 0x7fffffffffffffff, "Int64 '0x7fffffffffffffff'");
i64 == 0x7fffffffffffffffLL, "Int64 '0x7fffffffffffffff'");
testOk(!epicsParseInt64("-0x8000000000000000", &i64, 0, NULL) &&
i64 == -0x8000000000000000L, "Int64 '-0x8000000000000000'");
i64 == -0x8000000000000000LL, "Int64 '-0x8000000000000000'");
testOk(!epicsParseUInt64("0xffffffffffffffff", &u64, 0, NULL) &&
u64 == 0xffffffffffffffff, "UInt64 '0xffffffffffffffff'");
testOk(!epicsParseUInt64("-1", &u64, 0, NULL) && u64 == 0xffffffffffffffffU,
u64 == 0xffffffffffffffffULL, "UInt64 '0xffffffffffffffff'");
testOk(!epicsParseUInt64("-1", &u64, 0, NULL) && u64 == 0xffffffffffffffffULL,
"UInt64 '-1'");
testOk(epicsParseInt64("0x8000000000000000", &i64, 0, NULL) == S_stdlib_overflow,
"Int64 '0x8000000000000000' => overflow");

View File

@@ -84,9 +84,11 @@ MAIN(epicsStringTest)
const char * const a = "a";
const char * const abcd = "abcd";
const char * const abcde = "abcde";
char result[8];
char *s;
int status;
testPlan(305);
testPlan(402);
testChars();
@@ -123,5 +125,199 @@ MAIN(epicsStringTest)
testGlob();
memset(result, 'x', sizeof(result));
status = epicsStrnEscapedFromRaw(result, 0, ABCD, 4);
testOk(status == 4, "epicsStrnEscapedFromRaw(out, 0) -> %d (exp. 4)", status);
testOk(result[0] == 'x', " No output");
memset(result, 'x', sizeof(result));
status = epicsStrnRawFromEscaped(result, 0, ABCD, 4);
testOk(status == 0, "epicsStrnRawFromEscaped(out, 0) -> %d (exp. 0)", status);
testOk(result[0] == 'x', " No output");
memset(result, 'x', sizeof(result));
status = epicsStrnEscapedFromRaw(result, 1, ABCD, 4);
testOk(status == 4, "epicsStrnEscapedFromRaw(out, 1) -> %d (exp. 4)", status);
testOk(result[0] == 0, " 0-terminated");
testOk(result[1] == 'x', " No overrun");
memset(result, 'x', sizeof(result));
status = epicsStrnRawFromEscaped(result, 1, ABCD, 4);
testOk(status == 0, "epicsStrnRawFromEscaped(out, 1) -> %d (exp. 0)", status);
testOk(result[0] == 0, " 0-terminated");
testOk(result[1] == 'x', " No overrun");
testDiag("Testing size = epicsStrnEscapedFromRawSize");
status = epicsStrnEscapedFromRawSize(ABCD, 3);
testOk(status == 3, "size(\"ABCD\", 3) -> %d (exp. 3)", status);
status = epicsStrnEscapedFromRawSize(ABCD, 4);
testOk(status == 4, "size(\"ABCD\", 4) -> %d (exp. 4)", status);
status = epicsStrnEscapedFromRawSize(ABCD, 5);
testOk(status == 8, "size(\"ABCD\", 5) -> %d (exp. 8)", status);
testDiag("Testing esc = epicsStrnEscapedFromRaw(out, 4, ...)");
memset(result, 'x', sizeof(result));
status = epicsStrnEscapedFromRaw(result, 4, ABCD, 3);
testOk(status == 3, "esc(\"ABCD\", 3) -> %d (exp. 3)", status);
testOk(result[3] == 0, " 0-terminated");
testOk(result[4] == 'x', " No overrun");
memset(result, 'x', sizeof(result));
status = epicsStrnEscapedFromRaw(result, 4, ABCD, 4);
testOk(status == 4, "esc(\"ABCD\", 4) -> %d (exp. 4)", status);
testOk(result[3] == 0, " 0-terminated");
testOk(result[4] == 'x', " No overrun");
memset(result, 'x', sizeof(result));
status = epicsStrnEscapedFromRaw(result, 4, ABCD, 5);
testOk(status == 8, "esc(\"ABCD\", 5) -> %d (exp. 8)", status);
testOk(result[3] == 0, " 0-terminated");
testOk(result[4] == 'x', " No overrun");
testDiag("Testing raw = epicsStrnRawFromEscaped(out, 4, ...)");
memset(result, 'x', sizeof(result));
status = epicsStrnRawFromEscaped(result, 4, ABCD, 0);
testOk(status == 0, "raw(\"ABCD\", 0) -> %d (exp. 0)", status);
testOk(result[0] == 0, " 0-terminated");
memset(result, 'x', sizeof(result));
status = epicsStrnRawFromEscaped(result, 4, ABCD, 1);
testOk(status == 1, "raw(\"ABCD\", 1) -> %d (exp. 1)", status);
testOk(result[0] == 'A', " Char '%c' (exp. 'A')", result[0]);
testOk(result[1] == 0, " 0-terminated");
memset(result, 'x', sizeof(result));
status = epicsStrnRawFromEscaped(result, 4, ABCD, 2);
testOk(status == 2, "raw(\"ABCD\", 2) -> %d (exp. 2)", status);
testOk(result[0] == 'A', " Char '%c' (exp. 'A')", result[0]);
testOk(result[1] == 'B', " Char '%c' (exp. 'B')", result[1]);
testOk(result[2] == 0, " 0-terminated");
memset(result, 'x', sizeof(result));
status = epicsStrnRawFromEscaped(result, 4, ABCD, 3);
testOk(status == 3, "raw(\"ABCD\", 3) -> %d (exp. 3)", status);
testOk(result[0] == 'A', " Char '%c' (exp. 'A')", result[0]);
testOk(result[1] == 'B', " Char '%c' (exp. 'B')", result[1]);
testOk(result[2] == 'C', " Char '%c' (exp. 'C')", result[2]);
testOk(result[3] == 0, " 0-terminated");
testOk(result[4] == 'x', " No write outside buffer");
memset(result, 'x', sizeof(result));
status = epicsStrnRawFromEscaped(result, 4, ABCD, 4);
testOk(status == 3, "raw(\"ABCD\", 4) -> %d (exp. 3)", status);
testOk(result[0] == 'A', " Char '%c' (exp. 'A')", result[0]);
testOk(result[1] == 'B', " Char '%c' (exp. 'B')", result[1]);
testOk(result[2] == 'C', " Char '%c' (exp. 'C')", result[2]);
testOk(result[3] == 0, " 0-terminated");
testOk(result[4] == 'x', " No write outside buffer");
memset(result, 'x', sizeof(result));
status = epicsStrnRawFromEscaped(result, 4, ABCDE, 5);
testOk(status == 3, "raw(\"ABCDE\", 5) -> %d (exp. 3)", status);
testOk(result[0] == 'A', " Char '%c' (exp. 'A')", result[0]);
testOk(result[1] == 'B', " Char '%c' (exp. 'B')", result[1]);
testOk(result[2] == 'C', " Char '%c' (exp. 'C')", result[2]);
testOk(result[3] == 0, " 0-terminated");
testOk(result[4] == 'x', " No write outside buffer");
memset(result, 'x', sizeof(result));
status = epicsStrnRawFromEscaped(result, 4, "A", 2);
testOk(status == 1, "raw(\"A\", 2) -> %d (exp. 1)", status);
testOk(result[0] == 'A', " Char '%c' (exp. 'A')", result[0]);
testOk(result[status] == 0, " 0-terminated");
memset(result, 'x', sizeof(result));
status = epicsStrnRawFromEscaped(result, 4, "\\123", 1);
testOk(status == 0, "raw(\"\\123\", 1) -> %d (exp. 0)", status);
testOk(result[status] == 0, " 0-terminated");
memset(result, 'x', sizeof(result));
status = epicsStrnRawFromEscaped(result, 4, "\\123", 2);
testOk(status == 1, "raw(\"\\123\", 2) -> %d (exp. 1)", status);
testOk(result[0] == 1, " Octal escape (got \\%03o)", result[0]);
testOk(result[status] == 0, " 0-terminated");
memset(result, 'x', sizeof(result));
status = epicsStrnRawFromEscaped(result, 4, "\\123", 3);
testOk(status == 1, "raw(\"\\123\", 3) -> %d (exp. 1)", status);
testOk(result[0] == 012, " Octal escape (got \\%03o)", result[0]);
testOk(result[status] == 0, " 0-terminated");
memset(result, 'x', sizeof(result));
status = epicsStrnRawFromEscaped(result, 4, "\\123", 4);
testOk(status == 1, "raw(\"\\123\", 4) -> %d (exp. 1)", status);
testOk(result[0] == 0123, " Octal escape (got \\%03o)", result[0]);
testOk(result[status] == 0, " 0-terminated");
memset(result, 'x', sizeof(result));
status = epicsStrnRawFromEscaped(result, 4, "\\812", 2);
testOk(status == 1, "raw(\"\\812\", 2) -> %d (exp. 1)", status);
testOk(result[0] == '8', " Escaped '%c')", result[0]);
testOk(result[status] == 0, " 0-terminated");
memset(result, 'x', sizeof(result));
status = epicsStrnRawFromEscaped(result, 4, "\\182", 3);
testOk(status == 2, "raw(\"\\182\", 3) -> %d (exp. 2)", status);
testOk(result[0] == 1, " Octal escape (got \\%03o)", result[0]);
testOk(result[1] == '8', " Terminated with '%c'", result[1]);
testOk(result[status] == 0, " 0-terminated");
memset(result, 'x', sizeof(result));
status = epicsStrnRawFromEscaped(result, 4, "\\128", 4);
testOk(status == 2, "raw(\"\\128\", 4) -> %d (exp. 2)", status);
testOk(result[0] == 012, " Octal escape (got \\%03o)", result[0]);
testOk(result[1] == '8', " Terminator char got '%c'", result[1]);
testOk(result[status] == 0, " 0-terminated");
memset(result, 'x', sizeof(result));
status = epicsStrnRawFromEscaped(result, 4, "\\x12", 1);
testOk(status == 0, "raw(\"\\x12\", 1) -> %d (exp. 0)", status);
testOk(result[status] == 0, " 0-terminated");
memset(result, 'x', sizeof(result));
status = epicsStrnRawFromEscaped(result, 4, "\\x12", 2);
testOk(status == 0, "raw(\"\\x12\", 2) -> %d (exp. 0)", status);
testOk(result[status] == 0, " 0-terminated");
memset(result, 'x', sizeof(result));
status = epicsStrnRawFromEscaped(result, 4, "\\x12", 3);
testOk(status == 1, "raw(\"\\x12\", 3) -> %d (exp. 1)", status);
testOk(result[0] == 1, " Hex escape (got \\x%x)", result[0]);
testOk(result[status] == 0, " 0-terminated");
memset(result, 'x', sizeof(result));
status = epicsStrnRawFromEscaped(result, 4, "\\x12", 4);
testOk(status == 1, "raw(\"\\x12\", 4) -> %d (exp. 1)", status);
testOk(result[0] == 0x12," Hex escape (got \\x%x)", result[0]);
testOk(result[status] == 0, " 0-terminated");
memset(result, 'x', sizeof(result));
status = epicsStrnRawFromEscaped(result, 4, "\\xaF", 4);
testOk(status == 1, "raw(\"\\xaF\", 4) -> %d (exp. 1)", status);
testOk(result[0] == '\xaF'," Hex escape (got \\x%x)", result[0] & 0xFF);
testOk(result[status] == 0, " 0-terminated");
memset(result, 'x', sizeof(result));
status = epicsStrnRawFromEscaped(result, 4, "\\x012", 5);
testOk(status == 1, "raw(\"\\x012\", 5) -> %d (exp. 1)", status);
testOk(result[0] == 0x12," Hex escape (got \\x%x)", result[0]);
testOk(result[status] == 0, " 0-terminated");
memset(result, 'x', sizeof(result));
status = epicsStrnRawFromEscaped(result, 4, "\\x0012", 6);
testOk(status == 1, "raw(\"\\x0012\", 6) -> %d (exp. 1)", status);
testOk(result[0] == 0x12," Hex escape (got \\x%x)", result[0]);
testOk(result[status] == 0, " 0-terminated");
memset(result, 'x', sizeof(result));
status = epicsStrnRawFromEscaped(result, 4, "\\x1g", 4);
testOk(status == 2, "raw(\"\\x1g\", 4) -> %d (exp. 2)", status);
testOk(result[0] == 1, " Hex escape (got \\x%x)", result[0]);
testOk(result[1] == 'g', " Terminator char got '%c'", result[1]);
testOk(result[status] == 0, " 0-terminated");
return testDone();
}

View File

@@ -26,179 +26,221 @@
#include "epicsUnitTest.h"
#include "testMain.h"
#define ringSize 10
#define consumerCount 4
#define producerCount 4
static volatile int testExit = 0;
int value[ringSize*2];
typedef struct info {
epicsEventId consumerEvent;
epicsRingPointerId ring;
int checkOrder;
int value[ringSize*2];
}info;
static void consumer(void *arg)
static
void *int2ptr(size_t i)
{
info *pinfo = (info *)arg;
static int expectedValue=0;
int *newvalue;
char myname[20];
epicsThreadGetName(epicsThreadGetIdSelf(), myname, sizeof(myname));
testDiag("%s starting", myname);
while(1) {
epicsEventMustWait(pinfo->consumerEvent);
if (testExit) return;
while ((newvalue = (int *)epicsRingPointerPop(pinfo->ring))) {
if (pinfo->checkOrder) {
testOk(expectedValue == *newvalue,
"%s: (got) %d == %d (expected)", myname, *newvalue, expectedValue);
expectedValue = *newvalue + 1;
} else {
testOk(pinfo->value[*newvalue] <= producerCount, "%s: got a %d (%d times seen before)",
myname, *newvalue, pinfo->value[*newvalue]);
}
/* This must be atomic... */
pinfo->value[*newvalue]++;
epicsThreadSleep(0.05);
}
}
char *zero = 0;
i = i|(i<<16);
return zero+i;
}
static void producer(void *arg)
{
info *pinfo = (info *)arg;
char myname[20];
int i;
static int foundCorruption;
epicsThreadGetName(epicsThreadGetIdSelf(), myname, sizeof(myname));
testDiag("%s starting", myname);
for (i=0; i<ringSize*2; i++) {
while (epicsRingPointerIsFull(pinfo->ring)) {
epicsThreadSleep(0.2);
if (testExit) return;
}
testOk(epicsRingPointerPush(pinfo->ring, (void *)&value[i]),
"%s: Pushing %d, ring not full", myname, i);
epicsEventSignal(pinfo->consumerEvent);
if (testExit) return;
static
size_t ptr2int(void *p)
{
char *zero = 0, *p2 = p;
size_t i = p2-zero;
if((i&0xffff)!=((i>>16)&0xffff)) {
testDiag("Pointer value corruption %p", p);
foundCorruption = 1;
}
return i&0xffff;
}
static void testSingle(void)
{
int i;
const int rsize = 100;
void *addr = 0;
epicsRingPointerId ring = epicsRingPointerCreate(rsize);
foundCorruption = 0;
testDiag("Testing operations w/o threading");
testOk1(epicsRingPointerIsEmpty(ring));
testOk1(!epicsRingPointerIsFull(ring));
testOk1(epicsRingPointerGetFree(ring)==rsize);
testOk1(epicsRingPointerGetSize(ring)==rsize);
testOk1(epicsRingPointerGetUsed(ring)==0);
testOk1(epicsRingPointerPop(ring)==NULL);
addr = int2ptr(1);
testOk1(epicsRingPointerPush(ring, addr)==1);
testOk1(!epicsRingPointerIsEmpty(ring));
testOk1(!epicsRingPointerIsFull(ring));
testOk1(epicsRingPointerGetFree(ring)==rsize-1);
testOk1(epicsRingPointerGetSize(ring)==rsize);
testOk1(epicsRingPointerGetUsed(ring)==1);
testDiag("Fill it up");
for(i=2; i<2*rsize; i++) {
int ret;
addr = int2ptr(i);
ret = epicsRingPointerPush(ring, addr);
if(!ret)
break;
}
/* Note: +1 because we started with 1 */
testOk(i==rsize+1, "%d == %d", i, rsize+1);
testOk1(!epicsRingPointerIsEmpty(ring));
testOk1(epicsRingPointerIsFull(ring));
testOk1(epicsRingPointerGetFree(ring)==0);
testOk1(epicsRingPointerGetSize(ring)==rsize);
testOk1(epicsRingPointerGetUsed(ring)==rsize);
testDiag("Drain it out");
for(i=1; i<2*rsize; i++) {
addr = epicsRingPointerPop(ring);
if(addr==NULL || ptr2int(addr)!=i)
break;
}
testOk1(!foundCorruption);
testOk(i==rsize+1, "%d == %d", i, rsize+1);
testOk1(epicsRingPointerIsEmpty(ring));
testOk1(!epicsRingPointerIsFull(ring));
testOk1(epicsRingPointerGetFree(ring)==rsize);
testOk1(epicsRingPointerGetSize(ring)==rsize);
testOk1(epicsRingPointerGetUsed(ring)==0);
testDiag("Fill it up again");
for(i=2; i<2*rsize; i++) {
int ret;
addr = int2ptr(i);
ret = epicsRingPointerPush(ring, addr);
if(!ret)
break;
}
testDiag("flush");
testOk1(epicsRingPointerIsFull(ring));
epicsRingPointerFlush(ring);
testOk1(epicsRingPointerIsEmpty(ring));
testOk1(!epicsRingPointerIsFull(ring));
testOk1(epicsRingPointerGetFree(ring)==rsize);
testOk1(epicsRingPointerGetSize(ring)==rsize);
testOk1(epicsRingPointerGetUsed(ring)==0);
epicsRingPointerDelete(ring);
}
typedef struct {
epicsRingPointerId ring;
epicsEventId sync, wait;
int stop;
void *lastaddr;
} pairPvt;
static void pairConsumer(void *raw)
{
pairPvt *pvt = raw;
void *prev = pvt->lastaddr;
epicsEventMustTrigger(pvt->sync);
while(1) {
size_t c,p;
epicsEventMustWait(pvt->wait);
if(pvt->stop)
break;
pvt->lastaddr = epicsRingPointerPop(pvt->ring);
c = ptr2int(pvt->lastaddr);
p = ptr2int(prev);
if(p+1!=c) {
testFail("consumer skip %p %p", prev, pvt->lastaddr);
break;
}
prev = pvt->lastaddr;
}
pvt->stop = 1;
epicsEventMustTrigger(pvt->sync);
}
static void testPair(int locked)
{
unsigned int myprio = epicsThreadGetPrioritySelf(), consumerprio;
pairPvt pvt;
const int rsize = 100;
int i, expect;
epicsRingPointerId ring;
if(locked)
ring = epicsRingPointerLockedCreate(rsize);
else
ring = epicsRingPointerCreate(rsize);
pvt.ring = ring;
pvt.sync = epicsEventCreate(epicsEventEmpty);
pvt.wait = epicsEventCreate(epicsEventEmpty);
pvt.stop = 0;
pvt.lastaddr = 0;
foundCorruption = 0;
testDiag("single producer, single consumer with%s locking", locked?"":"out");
/* give the consumer thread a slightly higher priority so that
* it can preempt us on RTOS targets. On non-RTOS targets
* we expect to be preempted at some random time
*/
if(!epicsThreadLowestPriorityLevelAbove(myprio, &consumerprio))
testAbort("Can't run test from thread with highest priority");
epicsThreadMustCreate("pair", consumerprio,
epicsThreadGetStackSize(epicsThreadStackSmall),
&pairConsumer, &pvt);
/* wait for worker to start */
epicsEventMustWait(pvt.sync);
i=1;
while(i<rsize*10 && !pvt.stop) {
int full = epicsRingPointerPush(ring, int2ptr(i));
if(full || i%32==31)
epicsEventMustTrigger(pvt.wait);
if(full) {
i++;
}
}
testDiag("Everything enqueued, Stopping consumer");
pvt.stop = 1;
epicsEventMustTrigger(pvt.wait);
epicsEventMustWait(pvt.sync);
i = epicsRingPointerGetUsed(ring);
testDiag("Pushed %d, have %d remaining unconsumed", rsize*10, i);
expect = rsize*10-i;
testDiag("Expect %d consumed", expect);
testOk(pvt.lastaddr==int2ptr(expect-1), "%p == %p", pvt.lastaddr, int2ptr(expect-1));
if(pvt.lastaddr==int2ptr(expect-1))
testPass("Consumer consumed all");
testOk1(!foundCorruption);
epicsEventDestroy(pvt.sync);
epicsEventDestroy(pvt.wait);
epicsRingPointerDelete(ring);
}
MAIN(ringPointerTest)
{
int i;
info *pinfo;
epicsEventId consumerEvent;
int *pgetValue;
epicsRingPointerId ring;
epicsThreadId tid;
char threadName[20];
testPlan(256);
for (i=0; i<ringSize*2; i++) value[i] = i;
pinfo = calloc(1,sizeof(info));
if(!pinfo) testAbort("calloc failed");
pinfo->consumerEvent = consumerEvent = epicsEventMustCreate(epicsEventEmpty);
if (!consumerEvent) {
testAbort("epicsEventMustCreate failed");
}
testDiag("******************************************************");
testDiag("** Test 1: local ring pointer, check size and order **");
testDiag("******************************************************");
pinfo->ring = ring = epicsRingPointerCreate(ringSize);
if (!ring) {
testAbort("epicsRingPointerCreate failed");
}
testOk(epicsRingPointerIsEmpty(ring), "Ring empty");
for (i=0; epicsRingPointerPush(ring,(void *)&value[i]); ++i) {}
testOk(i==ringSize, "ring filled, %d values", i);
for (i=0; (pgetValue = (int *)epicsRingPointerPop(ring)); ++i) {
testOk(i==*pgetValue, "Pop test: %d == %d", i, *pgetValue);
}
testOk(epicsRingPointerIsEmpty(ring), "Ring empty");
testDiag("**************************************************************");
testDiag("** Test 2: unlocked ring pointer, one consumer, check order **");
testDiag("**************************************************************");
pinfo->checkOrder = 1;
tid=epicsThreadCreate("consumer", 50,
epicsThreadGetStackSize(epicsThreadStackSmall), consumer, pinfo);
if(!tid) testAbort("epicsThreadCreate failed");
epicsThreadSleep(0.2);
for (i=0; i<ringSize*2; i++) {
if (epicsRingPointerIsFull(ring)) {
epicsThreadSleep(0.2);
}
testOk(epicsRingPointerPush(ring, (void *)&value[i]), "Pushing %d, ring not full", i);
epicsEventSignal(consumerEvent);
}
epicsThreadSleep(1.0);
testOk(epicsRingPointerIsEmpty(ring), "Ring empty");
for (i=0; i<ringSize*2; i++) {
testOk(pinfo->value[i] == 1, "Value test: %d was processed", i);
}
testExit = 1;
epicsEventSignal(consumerEvent);
epicsThreadSleep(1.0);
epicsRingPointerDelete(pinfo->ring);
testDiag("*************************************************************************************");
testDiag("** Test 3: locked ring pointer, many consumers, many producers, check no of copies **");
testDiag("*************************************************************************************");
pinfo->ring = ring = epicsRingPointerLockedCreate(ringSize);
if (!ring) {
testAbort("epicsRingPointerLockedCreate failed");
}
testOk(epicsRingPointerIsEmpty(ring), "Ring empty");
for (i=0; i<ringSize*2; i++) pinfo->value[i] = 0;
testExit = 0;
pinfo->checkOrder = 0;
for (i=0; i<consumerCount; i++) {
sprintf(threadName, "consumer%d", i);
tid=epicsThreadCreate(threadName, 50,
epicsThreadGetStackSize(epicsThreadStackSmall), consumer, pinfo);
if(!tid) testAbort("epicsThreadCreate failed");
}
epicsThreadSleep(0.2);
for (i=0; i<producerCount; i++) {
sprintf(threadName, "producer%d", i);
tid=epicsThreadCreate(threadName, 50,
epicsThreadGetStackSize(epicsThreadStackSmall), producer, pinfo);
if(!tid) testAbort("epicsThreadCreate failed");
}
epicsThreadSleep(0.5);
epicsEventSignal(consumerEvent);
epicsThreadSleep(1.0);
testOk(epicsRingPointerIsEmpty(ring), "Ring empty");
for (i=0; i<ringSize*2; i++) {
testOk(pinfo->value[i] == producerCount, "Value test: %d was processed %d times", i, producerCount);
}
testExit = 1;
epicsEventSignal(consumerEvent);
epicsThreadSleep(1.0);
int prio = epicsThreadGetPrioritySelf();
testPlan(37);
testSingle();
epicsThreadSetPriority(epicsThreadGetIdSelf(), epicsThreadPriorityScanLow);
testPair(0);
testPair(1);
epicsThreadSetPriority(epicsThreadGetIdSelf(), prio);
return testDone();
}

View File

@@ -1,5 +1,6 @@
include "menuGlobal.dbd"
include "menuConvert.dbd"
include "menuScan.dbd"
recordtype(arr) {
include "dbCommon.dbd"
field(VAL, DBF_NOACCESS) {

View File

@@ -45,8 +45,9 @@ stdRecords += subArrayRecord
stdRecords += waveformRecord
DBDINC += $(stdRecords)
DBD += stdRecords.dbd
# Generate stdRecords.dbd, not really by concatenation, see RULES
DBDCAT += stdRecords.dbd
stdRecords_DBD = $(patsubst %,%.dbd,$(stdRecords))
dbRecStd_SRCS += $(patsubst %,%.c,$(stdRecords))

View File

@@ -1,5 +1,5 @@
##########################################################################
# Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne
# Copyright (c) 2014 UChicago Argonne LLC, as Operator of Argonne
# National Laboratory.
# EPICS BASE is distributed subject to a Software License Agreement found
# in the file LICENSE that is included with this distribution.
@@ -7,4 +7,12 @@
# This is a Makefile fragment, see src/ioc/Makefile.
$(COMMON_DIR)/stdRecords.dbd: $(STDDIR)/rec/Makefile
stdRecords.dbd$(DEP): $(STDDIR)/rec/Makefile $(STDDIR)/rec/RULES
@$(RM) $@
@echo "$(COMMON_DIR)/stdRecords.dbd:" > $@
$(COMMON_DIR)/stdRecords.dbd: $(STDDIR)/rec/Makefile $(STDDIR)/rec/RULES
# This is a target-specific variable
$(COMMON_DIR)/stdRecords.dbd: DBDCAT_COMMAND = \
$(PERL) $(TOOLS)/makeIncludeDbd.pl $(stdRecords_DBD) $(@F)

View File

@@ -26,8 +26,6 @@ static void testGetPutArray(void)
epicsInt32 *pbtr;
waveformRecord *prec;
testDiag("Test dbGet() and dbPut() of an array");
testdbReadDatabase("recTestIoc.dbd", NULL, NULL);
recTestIoc_registerRecordDeviceDriver(pdbbase);
@@ -38,6 +36,8 @@ static void testGetPutArray(void)
testIocInitOk();
eltc(1);
testDiag("Test dbGet() and dbPut() from/to an array");
prec = (waveformRecord*)testdbRecordPtr("wfrec");
if(!prec || dbNameToAddr("wfrec", &addr))
testAbort("Failed to find record wfrec");
@@ -52,7 +52,7 @@ static void testGetPutArray(void)
if(dbGet(&addr, DBF_DOUBLE, &data, NULL, &nreq, NULL))
testFail("dbGet fails");
else {
testOk1(nreq==0);
testOk(nreq==0, "nreq==0 (got %ld)", nreq);
}
dbScanUnlock(addr.precord);
@@ -69,7 +69,7 @@ static void testGetPutArray(void)
dbScanLock(addr.precord);
testOk1(dbPut(&addr, DBF_DOUBLE, &data, NELEMENTS(data))==0);
pbtr = prec->bptr;
testOk1(prec->nord==4);
testOk(prec->nord==4, "prec->nord==4 (got %u)", prec->nord);
testOk1(pbtr[0]==4 && pbtr[1]==5 && pbtr[2]==6 && pbtr[3]==7);
dbScanUnlock(addr.precord);
@@ -78,7 +78,7 @@ static void testGetPutArray(void)
memset(&data, 0, sizeof(data));
testDiag("reread the value");
testDiag("Reread the value");
dbScanLock(addr.precord);
nreq = NELEMENTS(data);
@@ -92,6 +92,62 @@ static void testGetPutArray(void)
testOk1(memcmp(&addr, &save, sizeof(save))==0);
testDiag("Test dbGet() and dbPut() from/to an array of size 1");
prec = (waveformRecord*)testdbRecordPtr("wfrec1");
if(!prec || dbNameToAddr("wfrec1", &addr))
testAbort("Failed to find record wfrec1");
memcpy(&save, &addr, sizeof(save));
testDiag("Fetch initial value");
dbScanLock(addr.precord);
testOk1(prec->nord==0);
nreq = NELEMENTS(data);
if(dbGet(&addr, DBF_DOUBLE, &data, NULL, &nreq, NULL))
testFail("dbGet fails");
else {
testOk(nreq==0, "nreq==0 (got %ld)", nreq);
}
dbScanUnlock(addr.precord);
testOk1(memcmp(&addr, &save, sizeof(save))==0);
addr=save;
testDiag("Write a new value");
data[0] = 4.0;
data[1] = 5.0;
data[2] = 6.0;
data[3] = 7.0;
dbScanLock(addr.precord);
testOk1(dbPut(&addr, DBF_DOUBLE, &data, 1)==0);
pbtr = prec->bptr;
testOk(prec->nord==1, "prec->nord==1 (got %u)", prec->nord);
testOk1(pbtr[0]==4);
dbScanUnlock(addr.precord);
testOk1(memcmp(&addr, &save, sizeof(save))==0);
addr=save;
memset(&data, 0, sizeof(data));
testDiag("Reread the value");
dbScanLock(addr.precord);
nreq = NELEMENTS(data);
if(dbGet(&addr, DBF_DOUBLE, &data, NULL, &nreq, NULL))
testFail("dbGet fails");
else {
testOk1(nreq==1);
testOk1(data[0]==4.0);
}
dbScanUnlock(addr.precord);
testOk1(memcmp(&addr, &save, sizeof(save))==0);
testIocShutdownOk();
testdbCleanup();
@@ -99,7 +155,7 @@ static void testGetPutArray(void)
MAIN(arrayOpTest)
{
testPlan(10);
testPlan(20);
testGetPutArray();
return testDone();
}

View File

@@ -2,3 +2,7 @@ record(waveform, "wfrec") {
field(NELM, "10")
field(FTVL, "LONG")
}
record(waveform, "wfrec1") {
field(NELM, "1")
field(FTVL, "LONG")
}

View File

@@ -1,11 +1,14 @@
# $Revision-Id$
#
# This file defines the standard record types and device support
# This file includes the standard record types and device support
# provided by Base and (usually) loaded into all IOCs.
# Menus
# Fixed menus
include "menuGlobal.dbd"
# Modifyable menus
include "menuConvert.dbd"
include "menuScan.dbd"
# Record types
include "stdRecords.dbd"
@@ -13,7 +16,7 @@ include "stdRecords.dbd"
# Channel filters & plugins
include "filters.dbd"
# "Soft Channel", "Raw Soft Channel", and "Async Soft Channel" device support
# Standard device support
include "devSoft.dbd"
# Access security subroutines

View File

@@ -83,7 +83,7 @@ const char *exit_db = EXIT_FILE;
static void exitSubroutine(subRecord *precord) {
epicsExit((precord->a == 0.0) ? EXIT_SUCCESS : EXIT_FAILURE);
epicsExitLater((precord->a == 0.0) ? EXIT_SUCCESS : EXIT_FAILURE);
}
static void usage(int status) {

View File

@@ -52,6 +52,8 @@ TEMPLATES += top/exampleBoot/nfsCommands@RTEMS
TEMPLATES += top/exampleBoot/ioc/Makefile@Common
TEMPLATES += top/exampleBoot/ioc/Makefile@vxWorks
TEMPLATES += top/exampleBoot/ioc/Makefile@win32
TEMPLATES += top/exampleBoot/ioc/Makefile@windows
TEMPLATES += top/exampleBoot/ioc/Makefile@cygwin
TEMPLATES += top/exampleBoot/ioc/st.cmd@Common
TEMPLATES += top/exampleBoot/ioc/st.cmd@vxWorks
TEMPLATES += top/exampleBoot/ioc/st.cmd@RTEMS
@@ -81,6 +83,8 @@ TEMPLATES += top/iocBoot/nfsCommands@RTEMS
TEMPLATES += top/iocBoot/ioc/Makefile@Common
TEMPLATES += top/iocBoot/ioc/Makefile@vxWorks
TEMPLATES += top/iocBoot/ioc/Makefile@win32
TEMPLATES += top/iocBoot/ioc/Makefile@windows
TEMPLATES += top/iocBoot/ioc/Makefile@cygwin
TEMPLATES += top/iocBoot/ioc/st.cmd@Common
TEMPLATES += top/iocBoot/ioc/st.cmd@Cross
TEMPLATES += top/iocBoot/ioc/st.cmd@vxWorks

View File

@@ -0,0 +1,5 @@
TOP = ../..
include $(TOP)/configure/CONFIG
ARCH = _ARCH_
TARGETS = envPaths relPaths.sh
include $(TOP)/configure/RULES.ioc

View File

@@ -0,0 +1,5 @@
TOP = ../..
include $(TOP)/configure/CONFIG
ARCH = _ARCH_
TARGETS = envPaths dllPath.bat
include $(TOP)/configure/RULES.ioc

View File

@@ -0,0 +1,5 @@
TOP = ../..
include $(TOP)/configure/CONFIG
ARCH = _ARCH_
TARGETS = envPaths relPaths.sh
include $(TOP)/configure/RULES.ioc

View File

@@ -0,0 +1,5 @@
TOP = ../..
include $(TOP)/configure/CONFIG
ARCH = _ARCH_
TARGETS = envPaths dllPath.bat
include $(TOP)/configure/RULES.ioc

View File

@@ -38,6 +38,7 @@ PERL_SCRIPTS += dos2unix.pl
PERL_SCRIPTS += expandVars.pl
PERL_SCRIPTS += fullPathName.pl
PERL_SCRIPTS += installEpics.pl
PERL_SCRIPTS += makeIncludeDbd.pl
PERL_SCRIPTS += makeMakefile.pl
PERL_SCRIPTS += makeTestfile.pl
PERL_SCRIPTS += mkmf.pl

View File

@@ -82,6 +82,7 @@ expandRelease(\%macros, \@apps);
for ($outfile) {
m/releaseTops/ and do { &releaseTops; last; };
m/dllPath\.bat/ and do { &dllPath; last; };
m/relPaths\.sh/ and do { &relPaths; last; };
m/cdCommands/ and do { &cdCommands; last; };
m/envPaths/ and do { &envPaths; last; };
m/checkRelease/ and do { &checkRelease; last; };
@@ -96,7 +97,8 @@ sub HELP_MESSAGE {
Usage: convertRelease.pl [-a arch] [-T top] [-t ioctop] outfile
where outfile is one of:
releaseTops - lists the module names defined in RELEASE*s
dllPath.bat - path changes for cmd.exe to find WIN32 DLLs
dllPath.bat - path changes for cmd.exe to find Windows DLLs
relPaths.sh - path changes for bash to add RELEASE bin dir's
cdCommands - generate cd path strings for vxWorks IOCs
envPaths - generate epicsEnvSet commands for other IOCs
checkRelease - checks consistency with support modules
@@ -113,13 +115,21 @@ sub releaseTops {
}
#
# Generate Path files so Windows can find our DLLs
# Generate Path files so Windows/Cygwin can find our DLLs
#
sub dllPath {
unlink $outfile;
open(OUT, ">$outfile") or die "$! creating $outfile";
print OUT "\@ECHO OFF\n";
print OUT "PATH %PATH%;", join(';', binDirs()), "\n";
print OUT "PATH \%PATH\%;", join(';', binDirs()), "\n";
close OUT;
}
sub relPaths {
unlink $outfile;
open(OUT, ">$outfile") or die "$! creating $outfile";
print OUT "export PATH=\$PATH:",
join(':', map {m/\s/ ? "\"$_\"" : $_ } binDirs()), "\n";
close OUT;
}

View File

@@ -0,0 +1,34 @@
#!/usr/bin/env perl
#*************************************************************************
# Copyright (c) 2014 UChicago Argonne LLC, as Operator of Argonne
# National Laboratory.
# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
#
# $Revision-Id$
use strict;
use File::Basename;
sub Usage {
my $txt = shift;
print "Usage: makeIncludeDbd.pl input file list ... outfile\n";
print "Error: $txt\n" if $txt;
exit 2;
}
Usage("No input files specified")
unless $#ARGV > 1;
my $target = pop @ARGV;
my @inputs = map { basename($_); } @ARGV;
open(my $OUT, '>', $target)
or die "$0: Can't create $target, $!\n";
print $OUT "# Generated file $target\n\n";
print $OUT map { "include \"$_\"\n"; } @inputs;
close $OUT;