diff --git a/configure/CONFIG b/configure/CONFIG index 305c6e3de..52f0a2ee5 100644 --- a/configure/CONFIG +++ b/configure/CONFIG @@ -1,13 +1,14 @@ #************************************************************************* -# Copyright (c) 2010 UChicago Argonne LLC, as Operator of Argonne +# Copyright (c) 2013 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 is distributed subject to a Software License Agreement found -# in file LICENSE that is included with this distribution. +# in the file LICENSE that is included with this distribution. #************************************************************************* # # $Revision-Id$ + # # Common build definitions # @@ -82,8 +83,6 @@ endif -include $(CONFIG)/os/CONFIG_SITE.Common.$(T_A) -include $(CONFIG)/os/CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A) -endif - # Include /cfg/CONFIG* definitions from tops defined in RELEASE* files # ifneq ($(CONFIG),$(TOP)/configure) @@ -96,12 +95,12 @@ endif # Include $(INSTALL_CFG)/CONFIG* definitions # -ifndef T_A TOP_CFG_CONFIGS = $(wildcard $(INSTALL_CFG)/CONFIG*) ifneq ($(TOP_CFG_CONFIGS),) include $(TOP_CFG_CONFIGS) endif -endif + +endif # ifdef T_A # User specific definitions # @@ -111,3 +110,4 @@ ifdef T_A -include $(HOME)/configure/CONFIG_USER.Common.$(T_A) -include $(HOME)/configure/CONFIG_USER.$(EPICS_HOST_ARCH).$(T_A) endif + diff --git a/configure/CONFIG_FILE_TYPE b/configure/CONFIG_FILE_TYPE index 3fc6a9d93..0501e1949 100644 --- a/configure/CONFIG_FILE_TYPE +++ b/configure/CONFIG_FILE_TYPE @@ -1,10 +1,10 @@ #************************************************************************* -# Copyright (c) 2006 UChicago Argonne LLC, as Operator of Argonne +# Copyright (c) 2013 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 is distributed subject to a Software License Agreement found -# in the file LICENSE that is included with this distribution. +# in the file LICENSE that is included with this distribution. #************************************************************************* # $Revision-Id$ # @@ -12,7 +12,7 @@ # # -------------------------------------------------------------- -# Module developers can now define a new type of file, e.g. ABC, +# Module developers can now define a new type of file, e.g. ABC, # so that files of type ABC will be installed into a directory # defined by INSTALL_ABC. This is done by creating a new CONFIG # file, e.g. CONFIG_ABC, with the following lines: @@ -24,8 +24,14 @@ # $(INSTALL_LOCATION). The file type ABC should be target # architecture independent (alh files, medm files, edm files). # -# Optional rules necessary for files of type ABC should be put in -# a RULES_ABC file. +# Files of type ABC are then installed into the INSTALL_ABC +# directory by adding a line like the following to a Makefile. +# +# ABC += +# +# Rules necessary to create files of type ABC should be put in +# a RULES_ABC file. Variables used by those rules should appear +# in a CONFIG_ABC file. # # The module developer installs new CONFIG* or RULES* files # into the directory $(INSTALL_LOCATION)/cfg by including the @@ -33,16 +39,11 @@ # # CFG += CONFIG_ABC RULES_ABC # -# Files of type ABC are installed into INSTALL_ABC directory -# by adding a line like the following to a Makefile. -# -# ABC += -# -# Files in $(INSTALL_LOCATION)/cfg directory are now included by -# the base config files so the definitions and rules are available -# for use by later src directory Makefiles in the same module or -# by other modules with a RELEASE line pointing to the TOP of -# the module with RULES_ABC. +# CONFIG and RULES files in the $(INSTALL_LOCATION)/cfg directory +# are included by the Base config files so their definitions and +# rules are available for use by later src directory Makefiles in +# the same module, or by other modules with a RELEASE line that +# points to the TOP of the module providing these files. FILE_TYPE += ADL INSTALL_ADL = $(INSTALL_LOCATION)/adl @@ -59,6 +60,6 @@ INSTALL_EDL = $(INSTALL_LOCATION)/edl FILE_TYPE += PERL_MODULES INSTALL_PERL_MODULES = $(INSTALL_LOCATION_LIB)/perl -INSTALLS_CFG= $(CFG:%= $(INSTALL_CFG)/%) +INSTALLS_CFG = $(CFG:%= $(INSTALL_CFG)/%) DIRECTORY_TARGETS += $(foreach type, $(FILE_TYPE),$(INSTALL_$(type))) diff --git a/configure/CONFIG_SITE b/configure/CONFIG_SITE index ea3fd9ee7..9eedc6b7a 100644 --- a/configure/CONFIG_SITE +++ b/configure/CONFIG_SITE @@ -17,6 +17,7 @@ # # Currently Supporting: # cygwin-x86 (cygwin compiler used for host builds) +# cygwin-x86_64 (cygwin compiler used for host builds) # darwin-ppc (PowerPC based Apple running OSX) # darwin-ppcx86 (Universal binaries for both CPUs) # darwin-x86 (Intel based Apple running OSX) @@ -37,6 +38,7 @@ # win32-x86 (MS Visual C++ compiler used for host builds) # win32-x86-mingw (MinGW compiler used for host builds) # windows-x64 (MS Visual C++ compiler used for host builds) +# windows-x64-mingw (MinGW compiler used for host builds) # Debugging builds: # linux-x86-debug (GNU compiler with -g option for host builds) diff --git a/configure/RULES_FILE_TYPE b/configure/RULES_FILE_TYPE index 1af5c5415..c559f7032 100644 --- a/configure/RULES_FILE_TYPE +++ b/configure/RULES_FILE_TYPE @@ -1,10 +1,10 @@ #************************************************************************* -# Copyright (c) 2006 UChicago Argonne LLC, as Operator of Argonne +# Copyright (c) 2013 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 is distributed subject to a Software License Agreement found -# in the file LICENSE that is included with this distribution. +# in the file LICENSE that is included with this distribution. #************************************************************************* # $Revision-Id$ # @@ -36,13 +36,11 @@ endif endif #--------------------------------------------- -# Include existing and new $(INSTALL_CFG)/* definitions +# Include our own $(INSTALL_CFG)/RULES* definitions # -TOP_CFG_FILES = $(sort $(wildcard $(INSTALL_CFG)/RULES*) \ - $(wildcard $(INSTALL_CFG)/CONFIG*) \ - $(addprefix $(INSTALL_CFG)/,$(CFG))) -ifneq ($(TOP_CFG_FILES),) - include $(TOP_CFG_FILES) +TOP_CFG_RULES = $(wildcard $(INSTALL_CFG)/RULES*) +ifneq ($(TOP_CFG_RULES),) + include $(TOP_CFG_RULES) endif #--------------------------------------------------------------- diff --git a/configure/Sample.Makefile b/configure/Sample.Makefile old mode 100755 new mode 100644 diff --git a/configure/os/CONFIG.Common.cygwin-x86_64 b/configure/os/CONFIG.Common.cygwin-x86_64 new file mode 100644 index 000000000..380e686be --- /dev/null +++ b/configure/os/CONFIG.Common.cygwin-x86_64 @@ -0,0 +1,14 @@ +# CONFIG.Common.cygwin-x86_64 +# +# $Revision-Id$ +# This file is maintained by the build community. +# +# Definitions for cygwin-x86_64 target builds +# Sites may override these definitions in CONFIG_SITE.Common.cygwin-x86_64 +#------------------------------------------------------- + +include $(CONFIG)/os/CONFIG.Common.cygwin-x86 + +ARCH_DEP_CFLAGS = -m64 +ARCH_DEP_LDFLAGS = -m64 + diff --git a/configure/os/CONFIG.Common.windows-x64-mingw b/configure/os/CONFIG.Common.windows-x64-mingw new file mode 100644 index 000000000..b2943af16 --- /dev/null +++ b/configure/os/CONFIG.Common.windows-x64-mingw @@ -0,0 +1,15 @@ +# CONFIG.Common.windows-x64-mingw +# +# $Revision-Id$ +# This file is maintained by the build community. +# +# Definitions for windows-x64-mingw target builds +# Sites may override these definitions in CONFIG_SITE.Common.windows-x64-mingw +#------------------------------------------------------- + +include $(CONFIG)/os/CONFIG.Common.win32-x86-mingw + +ARCH_CLASS = x64 + +ARCH_DEP_CFLAGS = -m64 +ARCH_DEP_LDFLAGS = -m64 diff --git a/configure/os/CONFIG.cygwin-x86_64.Common b/configure/os/CONFIG.cygwin-x86_64.Common new file mode 100644 index 000000000..ff6c3e2c8 --- /dev/null +++ b/configure/os/CONFIG.cygwin-x86_64.Common @@ -0,0 +1,10 @@ +# CONFIG.cygwin-x86_64.Common +# +# $Revision-Id$ +# This file is maintained by the build community. +# +# Definitions for cygwin-x86_64 host archs +# Sites may override these definitions in CONFIG_SITE.cygwin-x86_64.Common +#------------------------------------------------------- + +include $(CONFIG)/os/CONFIG.cygwin-x86.Common diff --git a/configure/os/CONFIG.cygwin-x86_64.cygwin-x86_64 b/configure/os/CONFIG.cygwin-x86_64.cygwin-x86_64 new file mode 100644 index 000000000..20a52a6d8 --- /dev/null +++ b/configure/os/CONFIG.cygwin-x86_64.cygwin-x86_64 @@ -0,0 +1,11 @@ +# CONFIG.cygwin-x86_64.cygwin-x86_64 +# +# $Revision-Id$ +# +# Definitions for cygwin-x86_64 host - cygwin-x86_64 target builds +# Sites may override these definitions in CONFIG_SITE.cygwin-x86_64.cygwin-x86_64 +#------------------------------------------------------- + +# Include common gnu compiler definitions +include $(CONFIG)/os/CONFIG.cygwin-x86.cygwin-x86 + diff --git a/configure/os/CONFIG.darwinCommon.darwinCommon b/configure/os/CONFIG.darwinCommon.darwinCommon index 57a5553f0..918278cc2 100644 --- a/configure/os/CONFIG.darwinCommon.darwinCommon +++ b/configure/os/CONFIG.darwinCommon.darwinCommon @@ -59,8 +59,10 @@ COMMANDLINE_LIBRARY=READLINE GNU_DIR = /usr -CC = $(GNU_BIN)/cc -CCC = $(GNU_BIN)/c++ +# Apple soft-links these compilers to clang/clang++ +CC = cc +CCC = c++ +GNU = NO # # Darwin shared libraries diff --git a/configure/os/CONFIG.win32-x86-mingw.win32-x86-mingw b/configure/os/CONFIG.win32-x86-mingw.win32-x86-mingw index 0389a4043..1983a6b42 100644 --- a/configure/os/CONFIG.win32-x86-mingw.win32-x86-mingw +++ b/configure/os/CONFIG.win32-x86-mingw.win32-x86-mingw @@ -9,14 +9,15 @@ # Include common gnu compiler definitions include $(CONFIG)/CONFIG.gnuCommon -# gcc, g++, ar, ld, and ranlib must be in user's path -CC = gcc -CCC = g++ -AR = ar -rc -LD = ld -r -RANLIB = ranlib -RES=.coff -RCCMD = windres $(INCLUDES) $< $@ +CMPLR_PREFIX = + +CC = $(CMPLR_PREFIX)gcc +CCC = $(CMPLR_PREFIX)g++ +AR = $(CMPLR_PREFIX)ar -rc +LD = $(CMPLR_PREFIX)ld -r +RANLIB = $(CMPLR_PREFIX)ranlib +RES = .coff +RCCMD = $(CMPLR_PREFIX)windres $(INCLUDES) $< $@ # No -fPIC avoids "-fPIC ignored for target (all code is position independent)" SHRLIB_CFLAGS = @@ -28,4 +29,4 @@ LOADABLE_SHRLIB_LDFLAGS = -shared \ # Override linking with gcc library from CONFIG.gnuCommon GNU_LDLIBS_YES = -OP_SYS_LDLIBS = -lws2_32 +OP_SYS_LDLIBS = -lws2_32 diff --git a/configure/os/CONFIG.windows-x64-mingw.Common b/configure/os/CONFIG.windows-x64-mingw.Common new file mode 100644 index 000000000..c467a3a51 --- /dev/null +++ b/configure/os/CONFIG.windows-x64-mingw.Common @@ -0,0 +1,11 @@ +# CONFIG.windows-x64-mingw.Common +# +# $Revision-Id$ +# This file is maintained by the build community. +# +# Definitions for windows-x64-mingw host archs +# Sites may override these definitions in CONFIG_SITE.windows-x64-mingw.Common +#------------------------------------------------------- + +include $(CONFIG)/os/CONFIG.win32-x86-mingw.Common + diff --git a/configure/os/CONFIG.windows-x64-mingw.windows-x64-mingw b/configure/os/CONFIG.windows-x64-mingw.windows-x64-mingw new file mode 100644 index 000000000..9e42784aa --- /dev/null +++ b/configure/os/CONFIG.windows-x64-mingw.windows-x64-mingw @@ -0,0 +1,11 @@ +# CONFIG.windows-x64-mingw.windows-x64-mingw +# +# $Revision-Id$ +# This file is maintained by the build community. +# +# Definitions for windows-x64-mingw target archs +# Sites may override these definitions in CONFIG_SITE.windows-x64-mingw.windows-x64-mingw +#------------------------------------------------------- + +# Include common gnu compiler definitions +include $(CONFIG)/os/CONFIG.win32-x86-mingw.win32-x86-mingw diff --git a/configure/os/CONFIG_SITE.Common.cygwin-x86_64 b/configure/os/CONFIG_SITE.Common.cygwin-x86_64 new file mode 100644 index 000000000..3950526d1 --- /dev/null +++ b/configure/os/CONFIG_SITE.Common.cygwin-x86_64 @@ -0,0 +1,14 @@ +# CONFIG_SITE.Common.cygwin-x86_64 +# +# $Revision-Id$ +# +# Site Specific definitions for cygwin-x86_64 target +# Only the local epics system manager should modify this file + +# If readline is installed uncomment the following line +# to add command-line editing and history support +#COMMANDLINE_LIBRARY = READLINE + +# Uncomment the following line if readline has problems +#LDLIBS_READLINE = -lreadline -lcurses + diff --git a/configure/os/CONFIG_SITE.Common.darwin-x86 b/configure/os/CONFIG_SITE.Common.darwin-x86 index ae2d8bfa6..e8f36c4bc 100644 --- a/configure/os/CONFIG_SITE.Common.darwin-x86 +++ b/configure/os/CONFIG_SITE.Common.darwin-x86 @@ -14,20 +14,21 @@ ARCH_CLASS = x86_64 #ARCH_CLASS = i386 x86_64 # -# Comment out the following lines to build with Apple's GCC instead of CLANG. +# Uncomment the following 3 lines to build with Apple's GCC instead of CLANG. # -CMPLR_CLASS = clang -CC = clang -CCC = clang++ -GNU = NO +#CMPLR_CLASS = gcc +#CC = gcc +#CCC = g++ +#GNU = YES -# To use MacPorts GCC, comment out ALL the settings above this line, -# then uncomment (and modify if necessary) the following instead: +# To use MacPorts GCC uncomment (and modify if necessary) the following: #GNU_DIR = /opt/local +#CMPLR_CLASS = gcc #CC = $(GNU_BIN)/gcc -m64 #CCC = $(GNU_BIN)/g++ -m64 +#GNU = YES # If you see this or similar errors while building in the src/cap5 directory # gcc: error: unrecognized option '-no-cpp-precomp' diff --git a/configure/os/CONFIG_SITE.Common.ios-arm b/configure/os/CONFIG_SITE.Common.ios-arm index e6ae3fcc1..3e20f58f6 100644 --- a/configure/os/CONFIG_SITE.Common.ios-arm +++ b/configure/os/CONFIG_SITE.Common.ios-arm @@ -16,11 +16,16 @@ # # Xcode 4.5 dropped support for the ARMv6. # -# ARMv7s devices: iPhone 5 +# ARMv8 (arm64) devices: iPhone 5S +# ARMv7s devices: iPhone 5 and 5C, iPad Gen 4 +# ARMv7 devices: iPhone 3GS, 4 and 4S, iPod Touch Gen 3 to 5 +# iPad Gen 1 to 3, iPad Mini, Apple TV Gen 2 and 3 # ARMv6 devices: iPhone 1 and 3G, iPod Touch Gen 1 and 2 -# All other devices are ARMv7 -ARCH_CLASS = armv7 armv7s +#ARCH_CLASS = arm64 +#ARCH_CLASS = armv7s arm64 +ARCH_CLASS = armv7 armv7s arm64 +#ARCH_CLASS = armv7 armv7s #ARCH_CLASS = armv7 #ARCH_CLASS = armv6 armv7 #ARCH_CLASS = armv6 diff --git a/configure/os/CONFIG_SITE.Common.iosCommon b/configure/os/CONFIG_SITE.Common.iosCommon index fa7b599e9..7c4b528aa 100644 --- a/configure/os/CONFIG_SITE.Common.iosCommon +++ b/configure/os/CONFIG_SITE.Common.iosCommon @@ -14,11 +14,12 @@ #IOS_VERSION = 5.0 #IOS_VERSION = 5.1 #IOS_VERSION = 6.0 -IOS_VERSION = 6.1 +#IOS_VERSION = 6.1 +IOS_VERSION = 7.0 # Which compiler to use: -# CLANG is preferred for recent versions of Xcode +# CLANG is required for Xcode 5.0 and later # LLVM_GNU uses the llvm-gcc and llvm-g++ compilers # GNU is needed for older versions of Xcode diff --git a/configure/os/CONFIG_SITE.windows-x64-mingw.windows-x64-mingw b/configure/os/CONFIG_SITE.windows-x64-mingw.windows-x64-mingw new file mode 100644 index 000000000..bdb8c995e --- /dev/null +++ b/configure/os/CONFIG_SITE.windows-x64-mingw.windows-x64-mingw @@ -0,0 +1,9 @@ +# CONFIG_SITE.windows-x64-mingw.windows-x64-mingw +# +# $Revision-Id$ +# +# Site Specific definitions for windows-x64-mingw target +# Only the local epics system manager should modify this file + +# Prefix for mingw compiler from cygwin +#CMPLR_PREFIX = x86_64-w64-mingw32- diff --git a/src/ca/client/CAref.html b/src/ca/client/CAref.html index bd63bc018..9753a151d 100644 --- a/src/ca/client/CAref.html +++ b/src/ca/client/CAref.html @@ -165,7 +165,8 @@ $Date$

  • block for certain requests to complete
  • test to see if certain requests have completed
  • -
  • process CA client library background activities
  • +
  • process CA client library background + activities
  • flush outstanding requests to the server
  • replace the default exception handler
  • @@ -454,26 +455,20 @@ Environment below.

    Firewalls

    -

    If you want channel access clients on a machine to be able to see -beacons and replies to broadcast PV search requests, you need to permit -inbound UDP packets with source port EPICS_CA_SERVER_PORT (default is 5064) -or destination port EPICS_CA_REPEATER_PORT (default is 5065). On systems -using iptables this can be accomplished by rules like

    - -
    -     -A INPUT -s 192.168.0.0/22 -p udp --sport 5064 -j ACCEPT
    -     -A INPUT -s 192.168.0.0/22 -p udp --dport 5065 -j ACCEPT
    -
    +

    If you want channel access clients on a machine to be able to see beacons +and replies to broadcast PV search requests, you need to permit inbound UDP +packets with source port EPICS_CA_SERVER_PORT (default is 5064) or destination +port EPICS_CA_REPEATER_PORT (default is 5065). On systems using iptables this +can be accomplished by rules like

    +
         -A INPUT -s 192.168.0.0/22 -p udp --sport 5064 -j ACCEPT
    +     -A INPUT -s 192.168.0.0/22 -p udp --dport 5065 -j ACCEPT

    If you want channel access servers (e.g. "soft IOCs") on a machine to be able to be seen by clients, you need to permit inbound TCP or UDP packets with -destination port EPICS_CA_SERVER_PORT (default is 5064). -On systems using iptables this can be accomplished by rules like

    - -
    -     -A INPUT -s 192.168.0.0/22 -p udp --dport 5064 -j ACCEPT
    -     -A INPUT -s 192.168.0.0/22 -p tcp --dport 5064 -j ACCEPT
    -
    +destination port EPICS_CA_SERVER_PORT (default is 5064). On systems using +iptables this can be accomplished by rules like

    +
         -A INPUT -s 192.168.0.0/22 -p udp --dport 5064 -j ACCEPT
    +     -A INPUT -s 192.168.0.0/22 -p tcp --dport 5064 -j ACCEPT

    In all cases the "-s 192.168.0.0/22" specifies the range of addresses from which you wish to accept packets.

    @@ -498,9 +493,8 @@ broadcast address of that subnet is added to the list. For each point to point interface found, the destination address of that link is added to the list. This automatic server address list initialization can be disabled if the EPICS environment variable EPICS_CA_AUTO_ADDR_LIST exists and its value is either -of "no" or "NO". The typical default is to enable network interface -introspection driven initialization with EPICS_CA_AUTO_ADDR_LIST set to "YES" -or "yes".

    +"no" or "NO". The typical default is to enable network interface introspection +driven initialization with EPICS_CA_AUTO_ADDR_LIST set to "YES" or "yes".

    Following network interface introspection, any IP addresses specified in the EPICS environment variable EPICS_CA_ADDR_LIST are added to the list of @@ -511,8 +505,8 @@ CA servers unless a CA proxy (gateway) is installed. The addresses in EPICS_CA_ADDR_LIST may be dotted IP addresses or host names if the local OS has support for host name to IP address translation. When multiple names are added to EPICS_CA_ADDR_LIST they must be separated by white space. There is no -requirement that the addresses specified in the EPICS_CA_ADDR_LIST be -broadcast addresses, but this will often be the most convenient choice.

    +requirement that the addresses specified in the EPICS_CA_ADDR_LIST be broadcast +addresses, but this will often be the most convenient choice.

    For any IP addresses specified in the EPICS environment variable EPICS_CA_NAME_SERVERS, TCP connections are opened and used for CA client name @@ -560,7 +554,7 @@ default to EPICS_CA_SERVER_PORT.

    Frequently vxWorks systems boot by default with routes limiting access only to the local subnet. If a EPICS system is operating in a WAN environment it may be necessary to configure routes into the vxWorks system which enable a vxWorks -based CA server to respond to requests originating outside it's subnet. These +based CA server to respond to requests originating outside its subnet. These routing restrictions can also apply to vxWorks base CA clients communicating with off subnet servers. An EPICS system manager can implement an rudimentary, but robust, form of access control for a particular host by not providing @@ -865,8 +859,8 @@ the contents of EPICS_CA_ADDR_LIST is used to augment the list. Otherwise, the list is not augmented.

    The EPICS_CAS_BEACON_PORT parameter specifies the destination port for -server beacons. The only exception to this occurs when ports are specified -in EPICS_CAS_BEACON_ADDR_LIST or possibly in EPICS_CA_ADDR_LIST. If +server beacons. The only exception to this occurs when ports are specified in +EPICS_CAS_BEACON_ADDR_LIST or possibly in EPICS_CA_ADDR_LIST. If EPICS_CAS_BEACON_PORT is not specified then beacons are sent to the port specified in EPICS_CA_REPEATER_PORT.

    @@ -874,7 +868,7 @@ specified in EPICS_CA_REPEATER_PORT.

    The parameter EPICS_CAS_INTF_ADDR_LIST allows a ca server to bind itself to, and therefore accept messages only over, a limited set of the local host's -network interfaces (each specified by it's IP address). On UNIX systems type +network interfaces (each specified by its IP address). On UNIX systems type "netstat -i" (type "ipconfig" on windows) to see a list of the local host's network interfaces. Specifically, UDP search messages addressed to both the IP addresses in EPICS_CAS_INTF_ADDR_LIST and also to the broadcast addresses of @@ -1885,7 +1879,7 @@ order to connect to this new beacon-out-of-range server. The typical situation where a client would not see the server's beacon might be when the client isnt on the same IP subnet as the server, and the client's EPICS_CA_ADDR_LIST was modified to include a destination address for the server, but the server's -beacon address list was not modified so that it's beacons are received by the +beacon address list was not modified so that its beacons are received by the client.

    A Server's IP Address Was Changed

    @@ -2017,8 +2011,8 @@ OS and even between different versions of the same OS.

    If the subscription update producer in the server produces subscription updates faster than the subscription update consumer in the client consumes them, then events have to be discarded if the buffering in the server -isn't allowed to grow to an infinite size. This is a law of nature -- based on queuing theory of course.

    +isn't allowed to grow to an infinite size. This is a law of nature – +based on queuing theory of course.

    What is done depends on the version of the CA server. All server versions place quotas on the maximum number of subscription updates allowed on the @@ -2040,10 +2034,10 @@ server to resume with subscription updates. This prevents slow clients from getting time warped, but also guarantees that intervening events are discarded until the slow client catches up.

    -

    There is currently no message on the IOC's console when a -particular client is slow on the uptake. A message of this type used to exist -many years ago, but it was a source of confusion (and what we will call -message noise) so it was removed.

    +

    There is currently no message on the IOC's console when a particular client +is slow on the uptake. A message of this type used to exist many years ago, but +it was a source of confusion (and what we will call message noise) so it was +removed.

    There is unfortunately no field in the protocol allowing the server to indicate that an intervening subscription update was discarded. We should @@ -2320,7 +2314,7 @@ int main ( int argc, char ** argv )

    Certain CA client initiated requests asynchronously execute an application supplied call back in the client process when a response arrives. The functions -ca_put_callback, ca_get_callback, and ca_add_event all request notification of +ca_put_callback, ca_get_callback, and ca_create_subscription all request notification of asynchronous completion via this mechanism. The event_handler_args structure is passed by value to the application supplied callback. In this structure the dbr field is a void pointer to any @@ -2355,8 +2349,8 @@ void myCallback ( struct event_handler_args args )

    Channel Access Exceptions

    When the server detects a failure, and there is no client call back function -attached to the request, an exception handler is executed in the client. -The default exception handler prints a message on the console and exits if the +attached to the request, an exception handler is executed in the client. The +default exception handler prints a message on the console and exits if the exception condition is severe. Certain internal exceptions within the CA client library, and failures detected by the SEVCHK macro may also cause the exception handler to be invoked. To modify this behavior see all OS (in past releases the library was thread safe only on vxWorks). When the client library is initialized the programmer may specify if preemptive callback is to be enabled. Preemptive callback is disabled by default. If preemptive -callback is enabled, then the user's callback functions might be called by -CA's auxiliary threads when the main initiating channel access thread is not -inside of a function in the channel access client library. Otherwise, the -user's callback functions will be called only when the main initiating channel -access thread is executing inside of the CA client library. When the CA client -library invokes a user's callback function, it will always wait for the current +callback is enabled, then the user's callback functions might be called by CA's +auxiliary threads when the main initiating channel access thread is not inside +of a function in the channel access client library. Otherwise, the user's +callback functions will be called only when the main initiating channel access +thread is executing inside of the CA client library. When the CA client library +invokes a user's callback function, it will always wait for the current callback to complete prior to executing another callback function. Programmers enabling preemptive callback should be familiar with using mutex locks to create a reliable multi-threaded program.

    @@ -2457,10 +2451,10 @@ address space (process) to be independent of each other. For example, the database CA links and the sequencer are designed to not use the same CA client library threads, network circuits, and data structures. Each thread that calls ca_context_create() for the first time either -directly or implicitly when calling any CA library function for the first -time, creates a CA client library context. A CA client library context contains -all of the threads, network circuits, and data structures required to connect -and communicate with the channels that a CA client application has created. The +directly or implicitly when calling any CA library function for the first time, +creates a CA client library context. A CA client library context contains all +of the threads, network circuits, and data structures required to connect and +communicate with the channels that a CA client application has created. The priority of auxiliary threads spawned by the CA client library are at fixed offsets from the priority of the thread that called ca_context_create(). An application specific @@ -2530,9 +2524,9 @@ questionable practice for the following reasons.

    • The vxWorks shell thread runs at the very highest priority in the system and therefore socket calls are made at a priority that is above the - priority of tNetTask - a practice that has caused the WRS IP kernel - to get sick in the past. That symptom was observed some time ago, but we - don't know if WRS has fixed the problem.
    • + priority of tNetTask. This has caused problems with the WRS IP kernel in + the past. That symptom was observed some time ago, but we don't know if + WRS has fixed the problem.
    • The vxWorks shell thread runs at the very highest priority in the system @@ -2679,7 +2673,7 @@ on a channel.

      The circuit may be initially connected or disconnected depending on the state of the network and the location of the channel. A channel will only enter -a connected state after server's address is determined, and only if channel +a connected state after the server's address is determined, and only if channel access successfully establishes a virtual circuit through the network to the server. Channel access routines that send a request to a server will return ECA_DISCONNCHID if the channel is currently disconnected.

      @@ -2689,7 +2683,7 @@ a connected state.

      • The first and simplest method requires that you call ca_pend_io(), and wait for successful completion, prior to using a channel that was created - specifying a nil connection call back function pointer.
      • + specifying a nill connection call back function pointer.
      • The second method requires that you register a connection handler by supplying a valid connection callback function pointer. This connection handler is called whenever the connection state of the channel changes. If @@ -2725,10 +2719,10 @@ time.

        USERFUNC
        Optional address of the user's call back function to be run when the connection state changes. Casual users of channel access may decide to - set this field to nil or 0 if they do not need to have a call back + set this field to nill or 0 if they do not need to have a call back function run in response to each connection state change event.

        The following structure is passed by value to the user's - connection connection callback function. The op field will + connection callback function. The op field will be set by the CA client library to CA_OP_CONN_UP when the channel connects, and to CA_OP_CONN_DOWN when the channel disconnects. See ca_puser if the @@ -2745,7 +2739,7 @@ time.

        The value of this void pointer argument is retained in storage associated with the specified channel. See the MACROS manual page for reading and writing this field. Casual users of channel access may - wish to set this field to nil or 0.
        + wish to set this field to nill or 0.
        PRIORITY
        @@ -2853,7 +2847,7 @@ This allows several requests to be efficiently combined into one message.

        Description (IOC Database Specific)

        A CA put request causes the record to process if the record's SCAN field is -set to passive, and the field being written has it's process passive attribute +set to passive, and the field being written has its process passive attribute set to true. If such a record is already processing when a put request is initiated the specified field is written immediately, and the record is scheduled to process again as soon as it finishes processing. Earlier instances @@ -2861,20 +2855,19 @@ of multiple put requests initiated while the record is being processing may be discarded, but the last put request initiated is always written and processed.

        -

        A CA put callback request causes -the record to process if the record's SCAN field is set to passive, and the -field being written has it's process passive attribute set to true. For such a -record, the user's put callback function is not called until after the record, -and any records that the record links to, finish processing. If such a record -is already processing when a put callback request is initiated the put callback request is postponed until the -record, and any records it links to, finish processing.

        +

        A CA put callback request causes the record to process if the +record's SCAN field is set to passive, and the field being written has its +process passive attribute set to true. For such a record, the user's put +callback function is not called until after the record, and any records that +the record links to, finish processing. If such a record is already processing +when a put callback request is initiated the put callback +request is postponed until the record, and any records it links to, finish +processing.

        If the record's SCAN field is not set to passive, or the field being written -has it's process passive attribute set to false then the CA put or CA put -callback request cause the specified field to be immediately written, but they -do not cause the record to be processed.

        +has its process passive attribute set to false then the CA put or CA put +callback request cause the specified field to be immediately written, +but they do not cause the record to be processed.

        Arguments

        @@ -3056,10 +3049,10 @@ int ca_create_subscription ( chtype TYPE, unsigned long COUNT, invoked whenever the process variable undergoes significant state changes. A significant change can be a change in the process variable's value, alarm status, or alarm severity. In the process control function block database the -deadband field determines the magnitude of a significant change for for the +deadband field determines the magnitude of a significant change for the process variable's value. Each call to this function consumes resources in the client library and potentially a CA server until one of ca_clear_channel or -ca_clear_event is called.

        +ca_clear_subscription is called.

        Subscriptions may be installed or canceled against both connected and disconnected channels. The specified USERFUNC is called once immediately after @@ -3067,7 +3060,7 @@ the subscription is installed with the process variable's current state if the process variable is connected. Otherwise, the specified USERFUNC is called immediately after establishing a connection (or reconnection) with the process variable. The specified USERFUNC is called immediately with the process -variable's current state from within ca_add_event() if the client and the +variable's current state from within ca_create_subscription() if the client and the process variable share the same address space.

        If a subscription is installed on a channel in a disconnected state then the @@ -3124,8 +3117,8 @@ indicating the current state of the channel.

        PEVID
        This is a pointer to user supplied event id which is overwritten if - successful. This event id can later be used to clear a specific - event. This option may may be omitted by passing a nil pointer.
        + successful. This event id can later be used to clear a specific event. + This option may be omitted by passing a nill pointer.
        MASK
        @@ -3173,7 +3166,7 @@ int ca_clear_subscription ( evid EVID );

        Cancel a subscription.

        -

        All ca_clear_event() requests such as the above are accumulated (buffered) +

        All cancel-subscription requests such as the above are accumulated (buffered) and not forwarded to the server until one of ca_flush_io, ca_pend_io, ca_pend_event, or ca_sg_pend are called. This allows several requests to be efficiently sent together in one message.

        @@ -3181,7 +3174,7 @@ efficiently sent together in one message.

        Arguments

        EVID
        -
        event id returned by ca_add_event()
        +
        event id returned by ca_create_subscription()

        Returns

        @@ -3232,9 +3225,9 @@ activities.

        network delays such as Ethernet collision exponential back off until retransmission delays which can be quite long on overloaded networks.

        -

        Unlike ca_pend_event, this routine will -not process CA's background activities if none of the selected IO requests are -pending.

        +

        Unlike ca_pend_event, this routine +will not process CA's background activities if none of the selected IO requests +are pending.

        Arguments

        @@ -3297,7 +3290,7 @@ activity is processed for TIMEOUT seconds.

        background activity is processed.

        The ca_pend_event function will not return before the specified -time-out expires and all unfinished channel access labor has been processed, +timeout expires and all unfinished channel access labor has been processed, and unlike ca_pend_io returning from the function does not indicate anything about the status of pending IO requests.

        @@ -3409,7 +3402,7 @@ field should not be used.

        USERFUNC
        Address of user callback function to be executed when an exceptions - occur. Passing a nil value causes the default exception handler to be + occur. Passing a nill value causes the default exception handler to be reinstalled. The following structure is passed by value to the user's callback function. Currently, the op field can be one of CA_OP_GET, CA_OP_PUT, CA_OP_CREATE_CHANNEL, CA_OP_ADD_EVENT, @@ -3544,7 +3537,7 @@ default handler uses fprintf to send messages to 'stderr'.

        PFUNC
        The address of a user supplied call back handler to be invoked when CA - prints diagnostic messages. Installing a nil pointer will cause the + prints diagnostic messages. Installing a nill pointer will cause the default call back handler to be reinstalled.
        @@ -3591,7 +3584,7 @@ specified channel.

        PFUNC
        -
        Address of user supplied call back function. A nil pointer uninstalls +
        Address of user supplied call back function. A nill pointer uninstalls the current handler. The following arguments are passed by value to the supplied callback handler.
        typedef struct ca_access_rights {
        @@ -3934,12 +3927,12 @@ prints diagnostics to standard out.

        Examples

        void ca_test_event (); 
        -status = ca_add_event ( type, chid, ca_test_event, NULL, NULL ); 
        +status = ca_create_subscription ( type, chid, ca_test_event, NULL, NULL ); 
         SEVCHK ( status, .... );

        See Also

        -

        ca_add_event()

        +

        ca_create_subscription()

        ca_sg_create()

        #include <cadef.h>
        @@ -4285,7 +4278,7 @@ ca_client_status() prints information about the calling threads CA context.

        Description

        -

        Returns a pointer to the current thread's CA context. If none then nil is +

        Returns a pointer to the current thread's CA context. If none then nill is returned.

        See Also

        @@ -4318,12 +4311,11 @@ preemptively from more than one thread.

        Returns

        -

        ECA_ISATTACHED - already attached to a CA context

        +

        ECA_NORMAL - Normal successful completion

        -

        ECA_NOTTHREADED - the specified context is non-preemptive and therefore does -not allow other threads to join

        +

        ECA_NOTTHREADED - Context is not preemptive so cannot be joined

        -

        ECA_ISATTACHED - the current thread is already attached to a CA context

        +

        ECA_ISATTACHED - Thread already attached to a CA context

        See Also

        diff --git a/src/ca/client/SearchDest.h b/src/ca/client/SearchDest.h old mode 100755 new mode 100644 diff --git a/src/ca/client/ca.rc b/src/ca/client/ca.rc old mode 100755 new mode 100644 diff --git a/src/ca/client/iocinf.cpp b/src/ca/client/iocinf.cpp index 487067c00..b3e634928 100644 --- a/src/ca/client/iocinf.cpp +++ b/src/ca/client/iocinf.cpp @@ -22,12 +22,12 @@ #include #include -#include #include #include #include "envDefs.h" #include "epicsAssert.h" +#include "epicsStdioRedirect.h" #include "errlog.h" #include "osiWireFormat.h" diff --git a/src/ca/client/test_event.cpp b/src/ca/client/test_event.cpp index 17cfe2f47..8b5a8bb54 100644 --- a/src/ca/client/test_event.cpp +++ b/src/ca/client/test_event.cpp @@ -14,7 +14,7 @@ * simple stub for testing monitors */ -#include +#include "epicsStdioRedirect.h" #define epicsExportSharedSymbols #include "cadef.h" diff --git a/src/ca/legacy/gdd/gdd.cc b/src/ca/legacy/gdd/gdd.cc index ea8e1ba5b..2ff4675fe 100644 --- a/src/ca/legacy/gdd/gdd.cc +++ b/src/ca/legacy/gdd/gdd.cc @@ -594,7 +594,7 @@ size_t gdd::describedDataSizeBytes(void) const size_t gdd::getTotalSizeBytes(void) const { size_t sz; - unsigned long tsize; + size_t tsize; const gdd* pdd; // add up size of bounds + size of this DD @@ -924,8 +924,8 @@ int gdd::flattenDDs(gddContainer* dd, void* buf, size_t size) gddStatus gdd::convertOffsetsToAddress(void) { aitUint8* pdd = (aitUint8*)this; - unsigned long bnds = (unsigned long)(bounds); - unsigned long dp = (unsigned long)(dataPointer()); + size_t bnds = (size_t)(bounds); + size_t dp = (size_t)(dataPointer()); gdd* tdd; gddContainer* cdd; gddCursor cur; @@ -943,7 +943,7 @@ gddStatus gdd::convertOffsetsToAddress(void) for(tdd=cur.first();tdd;tdd=cur.next()) { - if(tdd->next()) tdd->setNext((gdd*)(pdd+(unsigned long)tdd->next())); + if(tdd->next()) tdd->setNext((gdd*)(pdd+(size_t)tdd->next())); tdd->convertOffsetsToAddress(); } } @@ -962,7 +962,7 @@ gddStatus gdd::convertOffsetsToAddress(void) if(str[i].string()) { cstr=str[i].string(); - str[i].installBuf((char *)(pdd+(unsigned long)cstr), + str[i].installBuf((char *)(pdd+(size_t)cstr), str[i].length(), str[i].length()+1); } else @@ -982,7 +982,7 @@ gddStatus gdd::convertOffsetsToAddress(void) if(str->string()) { cstr=str->string(); - str->installBuf((char *)(pdd+(unsigned long)cstr), + str->installBuf((char *)(pdd+(size_t)cstr), str->length(), str->length()+1u); } else diff --git a/src/ca/legacy/gdd/gdd.rc b/src/ca/legacy/gdd/gdd.rc old mode 100755 new mode 100644 diff --git a/src/ca/legacy/pcas/build/cas.rc b/src/ca/legacy/pcas/build/cas.rc old mode 100755 new mode 100644 diff --git a/src/ca/legacy/pcas/generic/casStrmClient.cc b/src/ca/legacy/pcas/generic/casStrmClient.cc index 44b0ed126..849cf3cfa 100644 --- a/src/ca/legacy/pcas/generic/casStrmClient.cc +++ b/src/ca/legacy/pcas/generic/casStrmClient.cc @@ -884,7 +884,7 @@ caStatus casStrmClient::monitorResponse ( } else { ecaStatus = ECA_GETFAIL; - } + } return monitorFailureResponse ( guard, msg, ecaStatus ); } else { @@ -926,6 +926,7 @@ caStatus casStrmClient::monitorResponse ( int cacStatus = caNetConvert ( msg.m_dataType, pPayload, pPayload, true, msg.m_count ); if ( cacStatus != ECA_NORMAL ) { + pDBRDD->unreference (); return this->sendErrWithEpicsStatus ( guard, & msg, chan.getCID(), S_cas_internal, cacStatus ); } diff --git a/src/ioc/db/dbScan.c b/src/ioc/db/dbScan.c index f31e7bc37..10dc9c146 100644 --- a/src/ioc/db/dbScan.c +++ b/src/ioc/db/dbScan.c @@ -82,9 +82,12 @@ typedef struct scan_element{ /* PERIODIC */ +#define OVERRUN_REPORT_DELAY 10.0 /* Time between initial reports */ +#define OVERRUN_REPORT_MAX 3600.0 /* Maximum time between reports */ typedef struct periodic_scan_list { scan_list scan_list; double period; + const char *name; unsigned long overruns; volatile enum ctl scanCtl; epicsEventId loopEvent; @@ -351,8 +354,8 @@ int scanppl(double period) /* print periodic list */ ppsl = papPeriodic[i]; if (ppsl == NULL) continue; if (period > 0.0 && (fabs(period - ppsl->period) >.05)) continue; - sprintf(message, "Scan Period = %g seconds (%lu over-runs)", - ppsl->period, ppsl->overruns); + sprintf(message, "Records with SCAN = '%s' (%lu over-runs):", + ppsl->name, ppsl->overruns); printList(&ppsl->scan_list, message); } return 0; @@ -565,7 +568,11 @@ static void periodicTask(void *arg) periodic_scan_list *ppsl = (periodic_scan_list *)arg; epicsTimeStamp next, reported; unsigned int overruns = 0; - double report_delay = 10.0; + double report_delay = OVERRUN_REPORT_DELAY; + double overtime = 0.0; + double over_min = 0.0; + double over_max = 0.0; + const double penalty = (ppsl->period >= 2) ? 1 : (ppsl->period / 2); taskwdInsert(0, NULL, NULL); epicsEventSignal(startStopEvent); @@ -584,24 +591,40 @@ static void periodicTask(void *arg) epicsTimeGetCurrent(&now); delay = epicsTimeDiffInSeconds(&next, &now); if (delay <= 0.0) { - delay = 0.1; + if (overtime == 0.0) { + overtime = over_min = over_max = -delay; + } + else { + overtime -= delay; + if (over_min + delay > 0) + over_min = -delay; + if (over_max + delay < 0) + over_max = -delay; + } + delay = penalty; ppsl->overruns++; next = now; + epicsTimeAddSeconds(&next, delay); if (++overruns >= 10 && epicsTimeDiffInSeconds(&now, &reported) > report_delay) { - errlogPrintf("dbScan warning: %g second scan over-ran %u times\n", - ppsl->period, overruns); + errlogPrintf("\ndbScan warning from '%s' scan thread:\n" + "\tScan processing averages %.2f seconds (%.2f .. %.2f).\n" + "\tOver-runs have now happened %u times in a row.\n" + "\tTo fix this, move some records to a slower scan rate.\n", + ppsl->name, ppsl->period + overtime / overruns, + ppsl->period + over_min, ppsl->period + over_max, overruns); reported = now; - if (report_delay < 1800.0) + if (report_delay < (OVERRUN_REPORT_MAX / 2)) report_delay *= 2; else - report_delay = 3600.0; /* At most hourly */ + report_delay = OVERRUN_REPORT_MAX; } } else { overruns = 0; - report_delay = 10.0; + report_delay = OVERRUN_REPORT_DELAY; + overtime = 0.0; } epicsEventWaitWithTimeout(ppsl->loopEvent, delay); @@ -634,6 +657,7 @@ static void initPeriodic(void) ppsl->scan_list.lock = epicsMutexMustCreate(); ellInit(&ppsl->scan_list.list); + ppsl->name = choice; if (status || number == 0) { errlogPrintf("initPeriodic: Bad menuScan choice '%s'\n", choice); ppsl->period = i; diff --git a/src/ioc/db/dbTest.c b/src/ioc/db/dbTest.c index 96a805ae2..ec60c863e 100644 --- a/src/ioc/db/dbTest.c +++ b/src/ioc/db/dbTest.c @@ -8,7 +8,7 @@ \*************************************************************************/ /* $Revision-Id$ */ -/* database access test subroutines */ +/* database access test subroutines */ #include #include @@ -43,7 +43,7 @@ #include "dbTest.h" #define MAXLINE 80 -struct msgBuff { /* line output structure */ +struct msgBuff { /* line output structure */ char out_buff[MAXLINE + 1]; char *pNext; char *pLast; @@ -62,25 +62,26 @@ typedef struct msgBuff TAB_BUFFER; /* Local Routines */ static long nameToAddr(const char *pname, DBADDR *paddr); static void printDbAddr(DBADDR *paddr); -static void printBuffer( - long status,short dbr_type,void *pbuffer,long reqOptions, - long retOptions,long no_elements,TAB_BUFFER *pMsgBuff,int tab_size); -static int dbpr_report( - const char *pname,DBADDR *paddr,int interest_level, - TAB_BUFFER *pMsgBuff,int tab_size); +static void printBuffer(long status, short dbr_type, void *pbuffer, + long reqOptions, long retOptions, long no_elements, + TAB_BUFFER *pMsgBuff, int tab_size); +static int dbpr_report(const char *pname, DBADDR *paddr, int interest_level, + TAB_BUFFER *pMsgBuff, int tab_size); static void dbpr_msgOut(TAB_BUFFER *pMsgBuff,int tab_size); static void dbpr_init_msg(TAB_BUFFER *pMsgBuff,int tab_size); static void dbpr_insert_msg(TAB_BUFFER *pMsgBuff,int len,int tab_size); static void dbpr_msg_flush(TAB_BUFFER *pMsgBuff,int tab_size); -static char *dbf[DBF_NTYPES]={ - "STRING","CHAR","UCHAR","SHORT","USHORT","LONG","ULONG", - "FLOAT","DOUBLE","ENUM","MENU","DEVICE", - "INLINK","OUTLINK","FWDLINK","NOACCESS"}; +static char *dbf[DBF_NTYPES] = { + "STRING","CHAR","UCHAR","SHORT","USHORT","LONG","ULONG", + "FLOAT","DOUBLE","ENUM","MENU","DEVICE", + "INLINK","OUTLINK","FWDLINK","NOACCESS" +}; -static char *dbr[DBR_ENUM+2]={ - "STRING","CHAR","UCHAR","SHORT","USHORT","LONG","ULONG", - "FLOAT","DOUBLE","ENUM","NOACCESS"}; +static char *dbr[DBR_ENUM+2] = { + "STRING","CHAR","UCHAR","SHORT","USHORT","LONG","ULONG", + "FLOAT","DOUBLE","ENUM","NOACCESS" +}; long dba(const char*pname) { @@ -90,7 +91,10 @@ long dba(const char*pname) printf("Usage: dba \"pv name\"\n"); return 1; } - if (nameToAddr(pname, &addr)) return -1; + + if (nameToAddr(pname, &addr)) + return -1; + printDbAddr(&addr); return 0; } @@ -109,6 +113,7 @@ long dbl(const char *precordTypename, const char *fields) printf("No database loaded\n"); return 0; } + if (precordTypename && ((*precordTypename == '\0') || !strcmp(precordTypename,"*"))) precordTypename = NULL; @@ -143,6 +148,7 @@ long dbl(const char *precordTypename, const char *fields) if (status) { printf("No record type\n"); } + while (!status) { status = dbFirstRecord(pdbentry); while (!status) { @@ -153,11 +159,13 @@ long dbl(const char *precordTypename, const char *fields) if (status) { if (!strcmp(papfields[ifield], "recordType")) { pvalue = dbGetRecordTypeName(pdbentry); - } else { - printf(", "); + } + else { + printf(", "); continue; } - } else { + } + else { pvalue = dbGetString(pdbentry); } printf(", \"%s\"", pvalue ? pvalue : ""); @@ -165,7 +173,9 @@ long dbl(const char *precordTypename, const char *fields) printf("\n"); status = dbNextRecord(pdbentry); } - if (precordTypename) break; + if (precordTypename) + break; + status = dbNextRecordType(pdbentry); } if (nfields > 0) { @@ -190,12 +200,14 @@ long dbnr(int verbose) printf("No database loaded\n"); return 0; } + dbInitEntry(pdbbase, pdbentry); status = dbFirstRecordType(pdbentry); if (status) { printf("No record types loaded\n"); return 0; } + printf("Records Aliases Record Type\n"); while (!status) { naliases = dbGetNAliases(pdbentry); @@ -207,6 +219,7 @@ long dbnr(int verbose) nrecords, naliases, dbGetRecordTypeName(pdbentry)); status = dbNextRecordType(pdbentry); } + dbFinishEntry(pdbentry); printf("Total %d records, %d aliases\n", trecords, taliases); return 0; @@ -222,6 +235,7 @@ long dbla(const char *pmask) printf("No database loaded\n"); return 0; } + dbInitEntry(pdbbase, pdbentry); status = dbFirstRecordType(pdbentry); while (!status) { @@ -229,14 +243,18 @@ long dbla(const char *pmask) status = dbNextRecord(pdbentry)) { char *palias; - if (!dbIsAlias(pdbentry)) continue; + if (!dbIsAlias(pdbentry)) + continue; + palias = dbGetRecordName(pdbentry); - if (pmask && *pmask && !epicsStrGlobMatch(palias, pmask)) continue; + if (pmask && *pmask && !epicsStrGlobMatch(palias, pmask)) + continue; dbFindField(pdbentry, "NAME"); printf("%s -> %s\n", palias, dbGetString(pdbentry)); } status = dbNextRecordType(pdbentry); } + dbFinishEntry(pdbentry); return 0; } @@ -251,21 +269,25 @@ long dbgrep(const char *pmask) printf("Usage: dbgrep \"pattern\"\n"); return 1; } + if (!pdbbase) { printf("No database loaded\n"); return 0; } + dbInitEntry(pdbbase, pdbentry); status = dbFirstRecordType(pdbentry); while (!status) { status = dbFirstRecord(pdbentry); while (!status) { char *pname = dbGetRecordName(pdbentry); - if (epicsStrGlobMatch(pname, pmask)) puts(pname); + if (epicsStrGlobMatch(pname, pmask)) + puts(pname); status = dbNextRecord(pdbentry); } status = dbNextRecordType(pdbentry); } + dbFinishEntry(pdbentry); return 0; } @@ -276,64 +298,84 @@ long dbgf(const char *pname) long buffer[100]; long *pbuffer=&buffer[0]; DBADDR addr; - long status; long options = 0; long no_elements; static TAB_BUFFER msg_Buff; - int tab_size = 10; if (!pname || !*pname) { printf("Usage: dbgf \"pv name\"\n"); return 1; } - if (nameToAddr(pname, &addr)) return -1; + + if (nameToAddr(pname, &addr)) + return -1; + no_elements = MIN(addr.no_elements, sizeof(buffer)/addr.field_size); if (addr.dbr_field_type == DBR_ENUM) { - status = dbGetField(&addr, DBR_STRING, pbuffer, + long status = dbGetField(&addr, DBR_STRING, pbuffer, &options, &no_elements, NULL); + printBuffer(status, DBR_STRING, pbuffer, 0L, 0L, - no_elements, &msg_Buff, tab_size); - } else { - status = dbGetField(&addr, addr.dbr_field_type, pbuffer, - &options, &no_elements, NULL); - printBuffer(status, addr.dbr_field_type, pbuffer, 0L, 0L, - no_elements, &msg_Buff, tab_size); + no_elements, &msg_Buff, 10); } + else { + long status = dbGetField(&addr, addr.dbr_field_type, pbuffer, + &options, &no_elements, NULL); + + printBuffer(status, addr.dbr_field_type, pbuffer, 0L, 0L, + no_elements, &msg_Buff, 10); + } + msg_Buff.message[0] = '\0'; - dbpr_msgOut(&msg_Buff, tab_size); + dbpr_msgOut(&msg_Buff, 10); return 0; } long dbpf(const char *pname,const char *pvalue) { DBADDR addr; - long status = 0; + long status; + epicsUInt16 value; + short dbrType; + long n = 1; if (!pname || !*pname || !pvalue) { printf("Usage: dbpf \"pv name\", \"value\"\n"); return 1; } - if (nameToAddr(pname, &addr)) return -1; - /* For enumerated types must allow for ENUM rather than string*/ - /* If entire field is digits then use DBR_ENUM else DBR_STRING*/ + + if (nameToAddr(pname, &addr)) + return -1; + + /* For enumerated types must allow for ENUM rather than string */ + /* If entire field is digits then use DBR_ENUM else DBR_STRING */ if (addr.dbr_field_type == DBR_ENUM && *pvalue && strspn(pvalue,"0123456789") == strlen(pvalue)) { - unsigned short value; sscanf(pvalue, "%hu", &value); - status = dbPutField(&addr, DBR_ENUM, &value, 1L); - } else if (addr.dbr_field_type == DBR_CHAR && - addr.no_elements > 1) { - status = dbPutField(&addr, DBR_CHAR, pvalue, strlen(pvalue) + 1); - } else { - status = dbPutField(&addr, DBR_STRING, pvalue, 1L); + pvalue = (char *) &value; + dbrType = DBR_ENUM; } + else if (addr.no_elements > 1 && + (addr.dbr_field_type == DBR_CHAR || addr.dbr_field_type == DBR_UCHAR)) { + dbrType = addr.dbr_field_type; + n = strlen(pvalue) + 1; + } + else { + dbrType = DBR_STRING; + } + + status = dbPutField(&addr, dbrType, pvalue, n); if (status) { - errMessage(status,"- dbPutField error\n"); - return status; + if (status == -1) + printf("dbpf: Value conversion from %s to %s failed\n", + dbr[dbrType], dbf[addr.field_type]); + else + errMessage(status,"- dbPutField error\n"); + return status; } - status = dbgf(pname); - return status; + + return dbgf(pname); } long dbpr(const char *pname,int interest_level) @@ -348,11 +390,15 @@ long dbpr(const char *pname,int interest_level) printf("Usage: dbpr \"pv name\", level\n"); return 1; } - if (nameToAddr(pname, &addr)) return -1; + + if (nameToAddr(pname, &addr)) + return -1; + pmsg = pMsgBuff->message; if (dbpr_report(pname, &addr, interest_level, pMsgBuff, tab_size)) return 1; + pmsg[0] = '\0'; dbpr_msgOut(pMsgBuff, tab_size); return 0; @@ -368,17 +414,23 @@ long dbtr(const char *pname) printf("Usage: dbtr \"pv name\"\n"); return 1; } - if (nameToAddr(pname, &addr)) return -1; + + if (nameToAddr(pname, &addr)) + return -1; + precord = (struct dbCommon*)addr.precord; if (precord->pact) { printf("record active\n"); return 1; } + dbScanLock(precord); status = dbProcess(precord); dbScanUnlock(precord); + if (status) recGblRecordError(status, precord, "dbtr(dbProcess)"); + dbpr(pname, 3); return 0; } @@ -401,7 +453,9 @@ long dbtgf(const char *pname) printf("Usage: dbtgf \"pv name\"\n"); return 1; } - if (nameToAddr(pname, &addr)) return -1; + + if (nameToAddr(pname, &addr)) + return -1; /* try all options first */ req_options = 0xffffffff; @@ -485,12 +539,6 @@ long dbtpf(const char *pname, const char *pvalue) int validULong; int valid = 1; int put_type; - epicsInt8 val_i8; - epicsUInt8 val_u8; - epicsInt16 val_i16; - epicsUInt16 val_u16; - epicsInt32 val_i32; - epicsUInt32 val_u32; epicsFloat32 fvalue; epicsFloat64 dvalue; static TAB_BUFFER msg_Buff; @@ -502,7 +550,9 @@ long dbtpf(const char *pname, const char *pvalue) printf("Usage: dbtpf \"pv name\", \"value\"\n"); return 1; } - if (nameToAddr(pname, &addr)) return -1; + + if (nameToAddr(pname, &addr)) + return -1; val_long = strtol(pvalue, &pend, 10); validLong = (*pend == 0); @@ -517,37 +567,37 @@ long dbtpf(const char *pname, const char *pvalue) break; case DBR_CHAR: if ((valid = validLong)) { - val_i8 = (epicsInt8)val_long; + epicsInt8 val_i8 = (epicsInt8)val_long; status = dbPutField(&addr, put_type, &val_i8, 1L); } break; case DBR_UCHAR: if ((valid = validULong)) { - val_u8 = (epicsUInt8)val_ulong; + epicsUInt8 val_u8 = (epicsUInt8)val_ulong; status = dbPutField(&addr, put_type, &val_u8, 1L); } break; case DBR_SHORT: if ((valid = validLong)) { - val_i16 = val_long; + epicsInt16 val_i16 = val_long; status = dbPutField(&addr, put_type, &val_i16,1L); } break; case DBR_USHORT: if ((valid = validULong)) { - val_u16 = val_ulong; + epicsUInt16 val_u16 = val_ulong; status = dbPutField(&addr, put_type, &val_u16, 1L); } break; case DBR_LONG: if ((valid = validLong)) { - val_i32 = val_long; + epicsInt32 val_i32 = val_long; status = dbPutField(&addr, put_type,&val_i32,1L); } break; case DBR_ULONG: if ((valid = validULong)) { - val_u32 = val_ulong; + epicsUInt32 val_u32 = val_ulong; status = dbPutField(&addr, put_type, &val_u32, 1L); } break; @@ -561,8 +611,8 @@ long dbtpf(const char *pname, const char *pvalue) break; case DBR_ENUM: if ((valid = validULong)) { - val_u16 = val_ulong; - status = dbPutField(&addr, put_type, &val_u16, 1L); + epicsEnum16 val_e16 = val_ulong; + status = dbPutField(&addr, put_type, &val_e16, 1L); } break; } @@ -589,51 +639,65 @@ long dbtpf(const char *pname, const char *pvalue) long dbior(const char *pdrvName,int interest_level) { - char *pname; - drvSup *pdrvSup; + drvSup *pdrvSup; struct drvet *pdrvet; dbRecordType *pdbRecordType; - devSup *pdevSup; - struct dset *pdset; if (!pdbbase) { printf("No database loaded\n"); return 0; } + if (pdrvName && ((*pdrvName == '\0') || !strcmp(pdrvName,"*"))) pdrvName = NULL; + for (pdrvSup = (drvSup *)ellFirst(&pdbbase->drvList); pdrvSup; pdrvSup = (drvSup *)ellNext(&pdrvSup->node)) { - pname = pdrvSup->name; - if(pdrvName!=NULL && *pdrvName!='\0' && (strcmp(pdrvName,pname)!=0)) continue; - pdrvet = pdrvSup->pdrvet ; - if(pdrvet==NULL) { - printf("No driver entry table is present for %s\n",pname); - continue; - } - if(pdrvet->report==NULL) - printf("Driver: %s No report available\n",pname); - else { - printf("Driver: %s\n",pname); - (*pdrvet->report)(interest_level); - } + const char *pname = pdrvSup->name; + + if (pdrvName!=NULL && *pdrvName!='\0' && + (strcmp(pdrvName,pname)!=0)) + continue; + + pdrvet = pdrvSup->pdrvet ; + if (pdrvet == NULL) { + printf("No driver entry table is present for %s\n", pname); + continue; + } + + if (pdrvet->report == NULL) + printf("Driver: %s No report available\n", pname); + else { + printf("Driver: %s\n", pname); + pdrvet->report(interest_level); + } } + /* now check devSup reports */ for (pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList); pdbRecordType; pdbRecordType = (dbRecordType *)ellNext(&pdbRecordType->node)) { + devSup *pdevSup; + for (pdevSup = (devSup *)ellFirst(&pdbRecordType->devList); pdevSup; pdevSup = (devSup *)ellNext(&pdevSup->node)) { - if(!(pdset = pdevSup->pdset)) continue; - if(!(pname = pdevSup->name)) continue; - if(pdrvName!=NULL && *pdrvName!='\0' && (strcmp(pdrvName,pname)!=0)) continue; - if(pdset->report!=NULL) { - printf("Device Support: %s\n",pname); - (*pdset->report)(interest_level); - } - } + struct dset *pdset = pdevSup->pdset; + const char *pname = pdevSup->name; + + if (!pdset || !pname) + continue; + + if (pdrvName != NULL && *pdrvName != '\0' && + (strcmp(pdrvName, pname) != 0)) + continue; + + if (pdset->report != NULL) { + printf("Device Support: %s\n", pname); + pdset->report(interest_level); + } + } } return 0; } @@ -644,6 +708,7 @@ int dbhcr(void) printf("No database loaded\n"); return 0; } + dbReportDeviceConfig(pdbbase, stdout); return 0; } @@ -651,39 +716,35 @@ int dbhcr(void) static long nameToAddr(const char *pname, DBADDR *paddr) { long status = dbNameToAddr(pname, paddr); + if (status) { - printf("Record '%s' not found\n", pname); + printf("PV '%s' not found\n", pname); } return status; } static void printDbAddr(DBADDR *paddr) { - short field_type; - short dbr_field_type; - dbFldDes *pdbFldDes = paddr->pfldDes; + dbFldDes *pdbFldDes = paddr->pfldDes; + short field_type = paddr->field_type; + short dbr_field_type = paddr->dbr_field_type; - printf("Record Address: %p",(void *)paddr->precord); - printf(" Field Address: %p",paddr->pfield); - printf(" Field Description: %p\n",(void *)pdbFldDes); - printf(" No Elements: %ld\n",paddr->no_elements); - printf(" Record Type: %s\n",pdbFldDes->pdbRecordType->name); - printf(" FieldType: DBF_"); - field_type = paddr->field_type; - if(field_type<0 || field_type>DBR_NOACCESS) - printf(" Illegal = %d\n",field_type); - else - printf("%s\n",dbf[field_type]); - printf(" Field Type: %d\n",paddr->field_type); - printf(" Field Size: %d\n",paddr->field_size); - printf(" Special: %d\n",paddr->special); - printf("DBR Field Type: DBR_"); - dbr_field_type = paddr->dbr_field_type; - if(dbr_field_type==DBR_NOACCESS)dbr_field_type=DBR_ENUM + 1; - if(dbr_field_type<0 || dbr_field_type>(DBR_ENUM+1)) - printf(" Illegal = %d\n",dbr_field_type); - else - printf("%s\n",dbr[dbr_field_type]); + printf("Record Address: %p", paddr->precord); + printf(" Field Address: %p", paddr->pfield); + printf(" Field Description: %p\n", pdbFldDes); + printf(" No Elements: %ld\n", paddr->no_elements); + printf(" Record Type: %s\n", pdbFldDes->pdbRecordType->name); + printf(" Field Type: %d = DBF_%s\n", field_type, + (field_type < 0 || field_type > DBR_NOACCESS) ? "????" : + dbf[field_type]); + printf(" Field Size: %d\n", paddr->field_size); + printf(" Special: %d\n", paddr->special); + + if (dbr_field_type == DBR_NOACCESS) + dbr_field_type = DBR_ENUM + 1; + printf("DBR Field Type: %d = DBR_%s\n", paddr->dbr_field_type, + (dbr_field_type < 0 || dbr_field_type > (DBR_ENUM+1)) ? "????" : + dbr[dbr_field_type]); } @@ -703,32 +764,39 @@ static void printBuffer( printf("status = %u, severity = %u\n", pdbr_status->status, pdbr_status->severity); - } else + } + else { printf("status and severity not returned\n"); + } pbuffer = (char *)pbuffer + dbr_status_size; } + if (reqOptions & DBR_UNITS) { if (retOptions & DBR_UNITS) { struct dbr_units *pdbr_units = (void *)pbuffer; printf("units = \"%s\"\n", pdbr_units->units); - }else{ + } + else { printf("units not returned\n"); } pbuffer = (char *)pbuffer + dbr_units_size; } + if (reqOptions & DBR_PRECISION) { if (retOptions & DBR_PRECISION){ struct dbr_precision *pdbr_precision = (void *)pbuffer; printf("precision = %ld\n", pdbr_precision->precision.dp); - }else{ + } + else { printf("precision not returned\n"); } pbuffer = (char *)pbuffer + dbr_precision_size; } + if (reqOptions & DBR_TIME) { if (retOptions & DBR_TIME) { struct dbr_time *pdbr_time = (void *)pbuffer; @@ -736,11 +804,13 @@ static void printBuffer( epicsTimeToStrftime(time_buf, 40, "%Y-%m-%d %H:%M:%S.%09f", &pdbr_time->time); printf("time = %s\n", time_buf); - }else{ + } + else { printf("time not returned\n"); } pbuffer = (char *)pbuffer + dbr_time_size; } + if (reqOptions & DBR_ENUM_STRS) { if (retOptions & DBR_ENUM_STRS) { struct dbr_enumStrs *pdbr_enumStrs = (void *)pbuffer; @@ -749,10 +819,13 @@ static void printBuffer( pdbr_enumStrs->no_str); for (i = 0; i < pdbr_enumStrs->no_str; i++) printf("\t\"%s\"\n", pdbr_enumStrs->strs[i]); - } else + } + else { printf("enum strings not returned\n"); + } pbuffer = (char *)pbuffer + dbr_enumStrs_size; } + if (reqOptions & DBR_GR_LONG) { if (retOptions & DBR_GR_LONG) { struct dbr_grLong *pdbr_grLong = (void *)pbuffer; @@ -760,11 +833,13 @@ static void printBuffer( printf("grLong: %d .. %d\n", pdbr_grLong->lower_disp_limit, pdbr_grLong->upper_disp_limit); - }else{ + } + else { printf("DBRgrLong not returned\n"); } pbuffer = (char *)pbuffer + dbr_grLong_size; } + if (reqOptions & DBR_GR_DOUBLE) { if (retOptions & DBR_GR_DOUBLE) { struct dbr_grDouble *pdbr_grDouble = (void *)pbuffer; @@ -772,11 +847,13 @@ static void printBuffer( printf("grDouble: %g .. %g\n", pdbr_grDouble->lower_disp_limit, pdbr_grDouble->upper_disp_limit); - }else{ + } + else { printf("DBRgrDouble not returned\n"); } pbuffer = (char *)pbuffer + dbr_grDouble_size; } + if (reqOptions & DBR_CTRL_LONG) { if (retOptions & DBR_CTRL_LONG){ struct dbr_ctrlLong *pdbr_ctrlLong = (void *)pbuffer; @@ -784,11 +861,13 @@ static void printBuffer( printf("ctrlLong: %d .. %d\n", pdbr_ctrlLong->lower_ctrl_limit, pdbr_ctrlLong->upper_ctrl_limit); - }else{ + } + else { printf("DBRctrlLong not returned\n"); } pbuffer = (char *)pbuffer + dbr_ctrlLong_size; } + if (reqOptions & DBR_CTRL_DOUBLE) { if (retOptions & DBR_CTRL_DOUBLE) { struct dbr_ctrlDouble *pdbr_ctrlDouble = (void *)pbuffer; @@ -796,11 +875,13 @@ static void printBuffer( printf("ctrlDouble: %g .. %g\n", pdbr_ctrlDouble->lower_ctrl_limit, pdbr_ctrlDouble->upper_ctrl_limit); - }else{ + } + else { printf("DBRctrlDouble not returned\n"); } pbuffer = (char *)pbuffer + dbr_ctrlDouble_size; } + if (reqOptions & DBR_AL_LONG) { if (retOptions & DBR_AL_LONG) { struct dbr_alLong *pdbr_alLong = (void *)pbuffer; @@ -810,11 +891,13 @@ static void printBuffer( pdbr_alLong->lower_warning_limit, pdbr_alLong->upper_warning_limit, pdbr_alLong->upper_alarm_limit); - }else{ + } + else { printf("DBRalLong not returned\n"); } pbuffer = (char *)pbuffer + dbr_alLong_size; } + if (reqOptions & DBR_AL_DOUBLE) { if (retOptions & DBR_AL_DOUBLE) { struct dbr_alDouble *pdbr_alDouble = (void *)pbuffer; @@ -824,13 +907,17 @@ static void printBuffer( pdbr_alDouble->lower_warning_limit, pdbr_alDouble->upper_warning_limit, pdbr_alDouble->upper_alarm_limit); - }else{ + } + else { printf("DBRalDouble not returned\n"); } pbuffer = (char *)pbuffer + dbr_alDouble_size; } + /* Now print values */ - if (no_elements == 0) return; + if (no_elements == 0) + return; + switch (dbr_type) { case (DBR_STRING): if (no_elements == 1) @@ -843,6 +930,7 @@ static void printBuffer( dbpr_msgOut(pMsgBuff, tab_size); break; } + for(i=0; i 0) { @@ -852,6 +940,7 @@ static void printBuffer( pbuffer = (char *)pbuffer + MAX_STRING_SIZE; } break; + case (DBR_CHAR): if (no_elements == 1) sprintf(pmsg, "DBR_CHAR: "); @@ -863,11 +952,13 @@ static void printBuffer( dbpr_msgOut(pMsgBuff, tab_size); break; } + if (no_elements == 1) { val_i32 = *(epicsInt8 *) pbuffer; sprintf(pmsg, "%-9d 0x%-9x", val_i32, val_i32); dbpr_msgOut(pMsgBuff, tab_size); - } else { + } + else { for (i = 0; i < no_elements; i+= MAXLINE - 5) { sprintf(pmsg, " \"%.*s\"", MAXLINE - 5, (char *)pbuffer + i); if (i + MAXLINE - 5 < no_elements) strcat(pmsg, " +"); @@ -875,6 +966,7 @@ static void printBuffer( } } break; + case (DBR_UCHAR): if (no_elements == 1) sprintf(pmsg, "DBR_UCHAR: "); @@ -886,6 +978,7 @@ static void printBuffer( dbpr_msgOut(pMsgBuff, tab_size); break; } + for (i = 0; i < no_elements; i++) { val_u32 = *(epicsUInt8 *) pbuffer; sprintf(pmsg, "%-9u 0x%-9x", val_u32, val_u32); @@ -893,6 +986,7 @@ static void printBuffer( pbuffer = (char *)pbuffer + sizeof(epicsUInt8); } break; + case (DBR_SHORT): if (no_elements == 1) sprintf(pmsg, "DBR_SHORT: "); @@ -904,6 +998,7 @@ static void printBuffer( dbpr_msgOut(pMsgBuff, tab_size); break; } + for (i = 0; i < no_elements; i++) { val_i32 = *(epicsInt16 *) pbuffer; sprintf(pmsg, "%-9d 0x%-9x", val_i32, val_i32); @@ -911,6 +1006,7 @@ static void printBuffer( pbuffer = (char *)pbuffer + sizeof(epicsInt16); } break; + case (DBR_USHORT): if (no_elements == 1) sprintf(pmsg, "DBR_USHORT: "); @@ -922,6 +1018,7 @@ static void printBuffer( dbpr_msgOut(pMsgBuff, tab_size); break; } + for (i = 0; i < no_elements; i++) { val_u32 = *(epicsUInt16 *) pbuffer; sprintf(pmsg, "%-9u 0x%-9x", val_u32, val_u32); @@ -929,6 +1026,7 @@ static void printBuffer( pbuffer = (char *)pbuffer + sizeof(epicsUInt16); } break; + case (DBR_LONG): if (no_elements == 1) sprintf(pmsg, "DBR_LONG: "); @@ -940,6 +1038,7 @@ static void printBuffer( dbpr_msgOut(pMsgBuff, tab_size); break; } + for (i = 0; i < no_elements; i++) { val_i32 = *(epicsInt32 *) pbuffer; sprintf(pmsg, "%-9d 0x%-9x", val_i32, val_i32); @@ -947,6 +1046,7 @@ static void printBuffer( pbuffer = (char *)pbuffer + sizeof(epicsInt32); } break; + case (DBR_ULONG): if (no_elements == 1) sprintf(pmsg, "DBR_ULONG: "); @@ -958,6 +1058,7 @@ static void printBuffer( dbpr_msgOut(pMsgBuff, tab_size); break; } + for (i = 0; i < no_elements; i++) { val_u32 = *(epicsUInt32 *) pbuffer; sprintf(pmsg, "%-9u 0x%-9x", val_u32, val_u32); @@ -965,6 +1066,7 @@ static void printBuffer( pbuffer = (char *)pbuffer + sizeof(epicsUInt32); } break; + case (DBR_FLOAT): if (no_elements == 1) sprintf(pmsg, "DBR_FLOAT: "); @@ -976,12 +1078,14 @@ static void printBuffer( dbpr_msgOut(pMsgBuff, tab_size); break; } + for (i = 0; i < no_elements; i++) { sprintf(pmsg, "%-13.6g", *((epicsFloat32 *) pbuffer)); dbpr_msgOut(pMsgBuff, tab_size); pbuffer = (char *)pbuffer + sizeof(epicsFloat32); } break; + case (DBR_DOUBLE): if (no_elements == 1) sprintf(pmsg, "DBR_DOUBLE: "); @@ -993,12 +1097,14 @@ static void printBuffer( dbpr_msgOut(pMsgBuff, tab_size); break; } + for (i = 0; i < no_elements; i++) { sprintf(pmsg, "%-13.6g", *((epicsFloat64 *) pbuffer)); dbpr_msgOut(pMsgBuff, tab_size); pbuffer = (char *)pbuffer + sizeof(epicsFloat64); } break; + case (DBR_ENUM): if (no_elements == 1) sprintf(pmsg, "DBR_ENUM: "); @@ -1010,122 +1116,133 @@ static void printBuffer( dbpr_msgOut(pMsgBuff, tab_size); break; } + for (i = 0; i < no_elements; i++) { sprintf(pmsg, "%-9u", *((epicsEnum16 *) pbuffer)); dbpr_msgOut(pMsgBuff, tab_size); pbuffer = (char *)pbuffer + sizeof(epicsEnum16); } break; + default: printf(" illegal request type."); break; } + dbpr_msg_flush(pMsgBuff, tab_size); return; } static int dbpr_report( - const char *pname,DBADDR *paddr,int interest_level, - TAB_BUFFER *pMsgBuff,int tab_size) + const char *pname, DBADDR *paddr, int interest_level, + TAB_BUFFER *pMsgBuff, int tab_size) { - - char *pmsg; - dbFldDes *pdbFldDes = paddr->pfldDes; - dbRecordType *pdbRecordType = pdbFldDes->pdbRecordType; - short n2; - void *pfield; - char *pfield_name; - char *pfield_value; - DBENTRY dbentry; - DBENTRY *pdbentry = &dbentry; - long status; + char *pmsg; + dbFldDes *pdbFldDes = paddr->pfldDes; + dbRecordType *pdbRecordType = pdbFldDes->pdbRecordType; + short n2; + void *pfield; + char *pfield_name; + char *pfield_value; + DBENTRY dbentry; + DBENTRY *pdbentry = &dbentry; + long status; dbInitEntry(pdbbase,pdbentry); status = dbFindRecord(pdbentry,pname); - if(status) { - errMessage(status,pname); - return(-1); + if (status) { + errMessage(status,pname); + return -1; } + pmsg = pMsgBuff->message; for (n2 = 0; n2 <= pdbRecordType->no_fields - 1; n2++) { - pdbFldDes = pdbRecordType->papFldDes[pdbRecordType->sortFldInd[n2]]; - pfield_name = pdbFldDes->name; - pfield = ((char *)paddr->precord) + pdbFldDes->offset; - if (pdbFldDes->interest > interest_level ) - continue; - switch (pdbFldDes->field_type) { - case DBF_STRING: - case DBF_USHORT: - case DBF_ENUM: - case DBF_FLOAT: - case DBF_CHAR: - case DBF_UCHAR: - case DBF_SHORT: - case DBF_LONG: - case DBF_ULONG: - case DBF_DOUBLE: - case DBF_MENU: - case DBF_DEVICE: - status = dbFindField(pdbentry,pfield_name); - pfield_value = dbGetString(pdbentry); - sprintf(pmsg, "%s: %s", pfield_name, - (pfield_value ? pfield_value : "")); - dbpr_msgOut(pMsgBuff, tab_size); - break; - case DBF_INLINK: - case DBF_OUTLINK: - case DBF_FWDLINK: { - DBLINK *plink = (DBLINK *)pfield; - int ind; + pdbFldDes = pdbRecordType->papFldDes[pdbRecordType->sortFldInd[n2]]; + pfield_name = pdbFldDes->name; + pfield = ((char *)paddr->precord) + pdbFldDes->offset; + if (pdbFldDes->interest > interest_level ) + continue; - status = dbFindField(pdbentry,pfield_name); - for(ind=0; indtype) break; - } - if(ind>=LINK_NTYPES) { - sprintf(pmsg,"%s: Illegal Link Type", pfield_name); - } else { - sprintf(pmsg,"%s:%s %s", pfield_name, - pamaplinkType[ind].strvalue,dbGetString(pdbentry)); - } - dbpr_msgOut(pMsgBuff, tab_size); - } - break; - case DBF_NOACCESS: - if (pfield == (void *)&paddr->precord->time) { - /* Special for the TIME field, make it human-readable */ - char time_buf[40]; - epicsTimeToStrftime(time_buf, 40, "%Y-%m-%d %H:%M:%S.%09f", - &paddr->precord->time); - sprintf(pmsg, "%s: %s", pfield_name, time_buf); - dbpr_msgOut(pMsgBuff, tab_size); - } else if (pdbFldDes->size == sizeof(void *) && + switch (pdbFldDes->field_type) { + case DBF_STRING: + case DBF_USHORT: + case DBF_ENUM: + case DBF_FLOAT: + case DBF_CHAR: + case DBF_UCHAR: + case DBF_SHORT: + case DBF_LONG: + case DBF_ULONG: + case DBF_DOUBLE: + case DBF_MENU: + case DBF_DEVICE: + status = dbFindField(pdbentry,pfield_name); + pfield_value = dbGetString(pdbentry); + sprintf(pmsg, "%s: %s", pfield_name, + (pfield_value ? pfield_value : "")); + dbpr_msgOut(pMsgBuff, tab_size); + break; + + case DBF_INLINK: + case DBF_OUTLINK: + case DBF_FWDLINK: { + DBLINK *plink = (DBLINK *)pfield; + int ind; + + status = dbFindField(pdbentry,pfield_name); + for (ind=0; indtype) + break; + } + if (ind>=LINK_NTYPES) { + sprintf(pmsg,"%s: Illegal Link Type", pfield_name); + } + else { + sprintf(pmsg,"%s:%s %s", pfield_name, + pamaplinkType[ind].strvalue,dbGetString(pdbentry)); + } + dbpr_msgOut(pMsgBuff, tab_size); + } + break; + + case DBF_NOACCESS: + if (pfield == (void *)&paddr->precord->time) { + /* Special for the TIME field, make it human-readable */ + char time_buf[40]; + epicsTimeToStrftime(time_buf, 40, "%Y-%m-%d %H:%M:%S.%09f", + &paddr->precord->time); + sprintf(pmsg, "%s: %s", pfield_name, time_buf); + dbpr_msgOut(pMsgBuff, tab_size); + } + else if (pdbFldDes->size == sizeof(void *) && strchr(pdbFldDes->extra, '*')) { /* Special for pointers, needed on little-endian CPUs */ sprintf(pmsg, "%s: %p", pfield_name, *(void **)pfield); dbpr_msgOut(pMsgBuff, tab_size); - } else { /* just print field as hex bytes */ - unsigned char *pchar = (unsigned char *)pfield; - char temp_buf[61]; - char *ptemp_buf = &temp_buf[0]; - short n = pdbFldDes->size; - short i; + } + else { /* just print field as hex bytes */ + unsigned char *pchar = (unsigned char *)pfield; + char temp_buf[61]; + char *ptemp_buf = &temp_buf[0]; + short n = pdbFldDes->size; + short i; unsigned int value; - if (n > sizeof(temp_buf)/3) n = sizeof(temp_buf)/3; - for (i=0; i sizeof(temp_buf)/3) n = sizeof(temp_buf)/3; + for (i=0; imessage; - static int last_tabsize; + int len; + int err = 0; + char *pmsg = pMsgBuff->message; + static int last_tabsize; if (!((tab_size == 10) || (tab_size == 20))) { - printf("tab_size not 10 or 20 - dbpr_msgOut()\n"); - return; + printf("tab_size not 10 or 20 - dbpr_msgOut()\n"); + return; } /* init if first time */ if (!(pMsgBuff->pNext)) - dbpr_init_msg(pMsgBuff, tab_size); + dbpr_init_msg(pMsgBuff, tab_size); if (tab_size != last_tabsize) - pMsgBuff->pNexTab = pMsgBuff->out_buff + tab_size; + pMsgBuff->pNexTab = pMsgBuff->out_buff + tab_size; last_tabsize = tab_size; /* flush output if NULL string command */ if (*pmsg == 0) { - dbpr_msg_flush(pMsgBuff, tab_size); - return; + dbpr_msg_flush(pMsgBuff, tab_size); + return; } /* truncate if too long */ len = strlen(pmsg); @@ -1167,15 +1284,11 @@ static void dbpr_msgOut(TAB_BUFFER *pMsgBuff,int tab_size) /* warn if msg gt 80 */ if (err == 1) { - len = strlen(pmsg); - sprintf(pmsg, - "dbpr_msgOut: ERROR - msg length=%d limit=%d ", - len, - MAXLINE); - dbpr_insert_msg(pMsgBuff, len, tab_size); - return; + len = strlen(pmsg); + sprintf(pmsg, "dbpr_msgOut: ERROR - msg length=%d limit=%d ", + len, MAXLINE); + dbpr_insert_msg(pMsgBuff, len, tab_size); } - return; } static void dbpr_init_msg(TAB_BUFFER *pMsgBuff,int tab_size) @@ -1183,7 +1296,6 @@ static void dbpr_init_msg(TAB_BUFFER *pMsgBuff,int tab_size) pMsgBuff->pNext = pMsgBuff->out_buff; pMsgBuff->pLast = pMsgBuff->out_buff + MAXLINE; pMsgBuff->pNexTab = pMsgBuff->out_buff + tab_size; - return; } static void dbpr_insert_msg(TAB_BUFFER *pMsgBuff,int len,int tab_size) @@ -1197,35 +1309,33 @@ static void dbpr_insert_msg(TAB_BUFFER *pMsgBuff,int len,int tab_size) /* flush buffer if overflow would occor */ if (tot_line > MAXLINE) - dbpr_msg_flush(pMsgBuff, tab_size); + dbpr_msg_flush(pMsgBuff, tab_size); /* append message to buffer */ n = 0; while ((*pmsg) && (n < len)) { - *pMsgBuff->pNext++ = *pmsg++; + *pMsgBuff->pNext++ = *pmsg++; - /* position to next tab stop */ - if (*(pMsgBuff->pNexTab - 1) != '\0') - pMsgBuff->pNexTab = pMsgBuff->pNexTab + tab_size; - n++; + /* position to next tab stop */ + if (*(pMsgBuff->pNexTab - 1) != '\0') + pMsgBuff->pNexTab = pMsgBuff->pNexTab + tab_size; + n++; } /* fill spaces to next tab stop */ while (*(pMsgBuff->pNexTab - 1) != ' ' - && pMsgBuff->pNext < pMsgBuff->pLast) { - *pMsgBuff->pNext++ = ' '; + && pMsgBuff->pNext < pMsgBuff->pLast) { + *pMsgBuff->pNext++ = ' '; } - return; - } static void dbpr_msg_flush(TAB_BUFFER *pMsgBuff,int tab_size) { /* skip print if buffer empty */ if (pMsgBuff->pNext != pMsgBuff->out_buff) - printf("%s\n", pMsgBuff->out_buff); + printf("%s\n", pMsgBuff->out_buff); + memset(pMsgBuff->out_buff,'\0', (int) MAXLINE + 1); pMsgBuff->pNext = pMsgBuff->out_buff; pMsgBuff->pNexTab = pMsgBuff->out_buff + tab_size; - return; } diff --git a/src/ioc/db/recGbl.c b/src/ioc/db/recGbl.c index 2155875fe..7388d6e29 100644 --- a/src/ioc/db/recGbl.c +++ b/src/ioc/db/recGbl.c @@ -270,7 +270,7 @@ void recGblTSELwasModified(struct link *plink) /*Note that the VAL value will not be used*/ pfieldname = strstr(ppv_link->pvname, ".TIME"); if (pfieldname) { - strcpy(pfieldname, ".VAL"); + *pfieldname = 0; ppv_link->pvlMask |= pvlOptTSELisTime; } } diff --git a/src/ioc/dbCore.rc b/src/ioc/dbCore.rc old mode 100755 new mode 100644 diff --git a/src/ioc/dbStatic/dbLexRoutines.c b/src/ioc/dbStatic/dbLexRoutines.c index 801a27845..09d9524af 100644 --- a/src/ioc/dbStatic/dbLexRoutines.c +++ b/src/ioc/dbStatic/dbLexRoutines.c @@ -31,7 +31,6 @@ #include "epicsString.h" #include "epicsExport.h" -#define epicsExportSharedSymbols #include "dbFldTypes.h" #include "link.h" #include "dbStaticLib.h" @@ -113,8 +112,6 @@ static void yyerrorAbort(char *str) { yyerror(str); yyAbort = TRUE; - while (ellCount(&tempList)) - popFirstTemp(); } static void allocTemp(void *pvoid) @@ -257,6 +254,11 @@ static long dbReadCOM(DBBASE **ppdbbase,const char *filename, FILE *fp, my_buffer_ptr = my_buffer; ellAdd(&inputFileList,&pinputFile->node); status = pvt_yy_parse(); + + if (yyAbort) + while (ellCount(&tempList)) + popFirstTemp(); + dbFreePath(pdbbase); if(!status) { /*add RTYP and VERS as an attribute */ DBENTRY dbEntry; @@ -931,7 +933,7 @@ static void dbRecordHead(char *recordType, char *name, int visible) allocTemp(pdbentry); status = dbFindRecordType(pdbentry, recordType); if (status) { - epicsPrintf("Record \"%s\" is of unknown type \"%s\" - ", + epicsPrintf("Record \"%s\" is of unknown type \"%s\"\n", name, recordType); yyerrorAbort(NULL); return; @@ -940,8 +942,8 @@ static void dbRecordHead(char *recordType, char *name, int visible) status = dbCreateRecord(pdbentry,name); if (status==S_dbLib_recExists) { if (strcmp(recordType, dbGetRecordTypeName(pdbentry))!=0) { - epicsPrintf("Record \"%s\" already defined with different type " - "\"%s\"\n", name, dbGetRecordTypeName(pdbentry)); + epicsPrintf("Record \"%s\" of type \"%s\" redefined with new type " + "\"%s\"\n", name, dbGetRecordTypeName(pdbentry), recordType); yyerror(NULL); duplicate = TRUE; return; diff --git a/src/ioc/dbStatic/dbStaticLib.c b/src/ioc/dbStatic/dbStaticLib.c index ff1361d7e..0c2dfe55c 100644 --- a/src/ioc/dbStatic/dbStaticLib.c +++ b/src/ioc/dbStatic/dbStaticLib.c @@ -1899,9 +1899,11 @@ char * dbGetString(DBENTRY *pdbentry) else if(pvlMask&pvlOptCP) ppind=3; else if(pvlMask&pvlOptCPP) ppind=4; else ppind=0; - if(plink->value.pv_link.pvname) - strcpy(message,plink->value.pv_link.pvname); - else + if (plink->value.pv_link.pvname) { + strcpy(message, plink->value.pv_link.pvname); + if (pvlMask & pvlOptTSELisTime) + strcat(message, ".TIME"); + } else strcpy(message,""); strcat(message," "); strcat(message,ppstring[ppind]); diff --git a/src/ioc/dbtemplate/dbLoadTemplate.y b/src/ioc/dbtemplate/dbLoadTemplate.y index cc0ff7019..1a4a47caf 100644 --- a/src/ioc/dbtemplate/dbLoadTemplate.y +++ b/src/ioc/dbtemplate/dbLoadTemplate.y @@ -16,22 +16,29 @@ #include "macLib.h" #include "dbmf.h" -#define epicsExportSharedSymbols +#include "epicsExport.h" #include "dbAccess.h" #include "dbLoadTemplate.h" static int line_num; static int yyerror(char* str); -#define VAR_MAX_VAR_STRING 5000 -#define VAR_MAX_VARS 100 - -static char *sub_collect; +static char *sub_collect = NULL; static char *sub_locals; -static char** vars = NULL; -static char* db_file_name = NULL; +static char **vars = NULL; +static char *db_file_name = NULL; static int var_count, sub_count; +/* We allocate MAX_VAR_FACTOR chars in the sub_collect string for each + * "variable=value," segment, and will accept at most dbTemplateMaxVars + * template variables. The user can adjust that variable to increase + * the number of variables or the length allocated for the buffer. + */ +#define MAX_VAR_FACTOR 50 + +int dbTemplateMaxVars = 100; +epicsExportAddress(int, dbTemplateMaxVars); + %} %start substitution_file @@ -132,10 +139,18 @@ pattern_name: WORD #ifdef ERROR_STUFF fprintf(stderr, "pattern_name: [%d] = %s\n", var_count, $1); #endif - vars[var_count] = dbmfMalloc(strlen($1)+1); - strcpy(vars[var_count], $1); - var_count++; - dbmfFree($1); + if (var_count >= dbTemplateMaxVars) { + fprintf(stderr, + "More than dbTemplateMaxVars = %d macro variables used\n", + dbTemplateMaxVars); + yyerror(NULL); + } + else { + vars[var_count] = dbmfMalloc(strlen($1)+1); + strcpy(vars[var_count], $1); + var_count++; + dbmfFree($1); + } } ; @@ -319,14 +334,21 @@ int dbLoadTemplate(const char *sub_file, const char *cmd_collect) return -1; } + if (dbTemplateMaxVars < 1) + { + fprintf(stderr,"Error: dbTemplateMaxVars = %d, must be +ve\n", + dbTemplateMaxVars); + return -1; + } + fp = fopen(sub_file, "r"); if (!fp) { fprintf(stderr, "dbLoadTemplate: error opening sub file %s\n", sub_file); return -1; } - vars = (char**)malloc(VAR_MAX_VARS * sizeof(char*)); - sub_collect = malloc(VAR_MAX_VAR_STRING); + vars = malloc(dbTemplateMaxVars * sizeof(char*)); + sub_collect = malloc(dbTemplateMaxVars * MAX_VAR_FACTOR); if (!vars || !sub_collect) { free(vars); free(sub_collect); diff --git a/src/ioc/misc/dbCore.dbd b/src/ioc/misc/dbCore.dbd index eae942b18..fac0fd674 100644 --- a/src/ioc/misc/dbCore.dbd +++ b/src/ioc/misc/dbCore.dbd @@ -12,3 +12,5 @@ variable(asCaDebug,int) variable(dbRecordsOnceOnly,int) variable(dbBptNotMonotonic,int) +# dbLoadTemplate settings +variable(dbTemplateMaxVars,int) diff --git a/src/libCom/Com.rc b/src/libCom/Com.rc old mode 100755 new mode 100644 diff --git a/src/libCom/bucketLib/bucketLib.c b/src/libCom/bucketLib/bucketLib.c index 9fd887b6d..1f68e1d97 100644 --- a/src/libCom/bucketLib/bucketLib.c +++ b/src/libCom/bucketLib/bucketLib.c @@ -167,16 +167,16 @@ static BUCKETID bucketUnsignedHash (BUCKET *pb, const void *pId) static BUCKETID bucketPointerHash (BUCKET *pb, const void *pId) { void * const *ppId = (void * const *) pId; - unsigned long src; + size_t src; BUCKETID hashid; /* - * This makes the assumption that - * a pointer will fit inside of a long + * This makes the assumption that size_t + * can be used to hold a pointer value * (this assumption may not port to all * CPU architectures) */ - src = (unsigned long) *ppId; + src = (size_t) *ppId; hashid = src; src = src >> pb->hashIdNBits; while(src){ diff --git a/src/libCom/calc/postfix.c b/src/libCom/calc/postfix.c index 7baa8263a..2a7030b69 100644 --- a/src/libCom/calc/postfix.c +++ b/src/libCom/calc/postfix.c @@ -207,7 +207,7 @@ static int * convert an infix expression to a postfix expression */ epicsShareFunc long - postfix(const char *psrc, char * const ppostfix, short *perror) + postfix(const char *psrc, char *pout, short *perror) { ELEMENT stack[80]; ELEMENT *pstacktop = stack; @@ -215,7 +215,7 @@ epicsShareFunc long int operand_needed = TRUE; int runtime_depth = 0; int cond_count = 0; - char *pout = ppostfix; + char * const pdest = pout; char *pnext; if (psrc == NULL || *psrc == '\0' || @@ -251,7 +251,7 @@ epicsShareFunc long goto bad; } psrc = pnext; - lit_i = lit_d; + lit_i = (int) lit_d; if (lit_d != (double) lit_i) { *pout++ = pel->code; memcpy(pout, &lit_d, sizeof(double)); @@ -280,7 +280,7 @@ epicsShareFunc long break; case STORE_OPERATOR: - if (pout == ppostfix || pstacktop > stack || + if (pout == pdest || pstacktop > stack || *--pout < FETCH_A || *pout > FETCH_L) { *perror = CALC_ERR_BAD_ASSIGNMENT; goto bad; @@ -481,7 +481,7 @@ epicsShareFunc long return 0; bad: - *ppostfix = END_EXPRESSION; + *pdest = END_EXPRESSION; return -1; } diff --git a/src/libCom/gpHash/gpHashLib.c b/src/libCom/gpHash/gpHashLib.c index c37371fae..3b680a2fc 100644 --- a/src/libCom/gpHash/gpHashLib.c +++ b/src/libCom/gpHash/gpHashLib.c @@ -10,7 +10,6 @@ /* Author: Marty Kraimer Date: 04-07-94 */ -#include #include #include #include @@ -18,6 +17,7 @@ #define epicsExportSharedSymbols #include "cantProceed.h" #include "epicsMutex.h" +#include "epicsStdioRedirect.h" #include "epicsString.h" #include "dbDefs.h" #include "ellLib.h" @@ -35,12 +35,13 @@ typedef struct gphPvt { #define DEFAULT_SIZE 512 #define MAX_SIZE 65536 + void epicsShareAPI gphInitPvt(gphPvt **ppvt, int size) { gphPvt *pgphPvt; if (size & (size - 1)) { - printf("gphInitPvt: %d is not a power of 2\n", size); + fprintf(stderr, "gphInitPvt: %d is not a power of 2\n", size); size = DEFAULT_SIZE; } @@ -215,9 +216,10 @@ void epicsShareAPI gphDumpFP(FILE *fp, gphPvt *pgphPvt) ELLLIST **paplist; int h; - if (pgphPvt == NULL) return; + if (pgphPvt == NULL) + return; - printf("Hash table has %d buckets", pgphPvt->size); + fprintf(fp, "Hash table has %d buckets", pgphPvt->size); paplist = pgphPvt->paplist; for (h = 0; h < pgphPvt->size; h++) { diff --git a/src/libCom/iocsh/iocsh.cpp b/src/libCom/iocsh/iocsh.cpp index c140e56a9..c1d50d27e 100644 --- a/src/libCom/iocsh/iocsh.cpp +++ b/src/libCom/iocsh/iocsh.cpp @@ -3,8 +3,7 @@ * 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 +* EPICS BASE is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ /* iocsh.cpp */ @@ -68,6 +67,7 @@ struct iocshRedirect { const char *mode; FILE *fp; FILE *oldFp; + int mustRestore; }; /* @@ -101,7 +101,8 @@ iocshTableUnlock (void) /* * Register a command */ -void epicsShareAPI iocshRegister (const iocshFuncDef *piocshFuncDef, iocshCallFunc func) +void epicsShareAPI iocshRegister (const iocshFuncDef *piocshFuncDef, + iocshCallFunc func) { struct iocshCommand *l, *p, *n; int i; @@ -118,7 +119,8 @@ void epicsShareAPI iocshRegister (const iocshFuncDef *piocshFuncDef, iocshCallFu if (i < 0) break; } - n = (struct iocshCommand *)callocMustSucceed (1, sizeof *n, "iocshRegister"); + n = (struct iocshCommand *) callocMustSucceed (1, sizeof *n, + "iocshRegister"); if (!registryAdd(iocshCmdID, piocshFuncDef->name, (void *)n)) { free (n); iocshTableUnlock (); @@ -162,7 +164,8 @@ void epicsShareAPI iocshRegisterVariable (const iocshVarDef *piocshVarDef) for (l = NULL, p = iocshVariableHead ; p != NULL ; l = p, p = p->next) { i = strcmp (piocshVarDef->name, p->pVarDef->name); if (i == 0) { - errlogPrintf("Warning -- iocshRegisterVariable redefining %s.\n", piocshVarDef->name); + errlogPrintf("Warning: iocshRegisterVariable redefining %s.\n", + piocshVarDef->name); p->pVarDef = piocshVarDef; found = 1; break; @@ -171,11 +174,13 @@ void epicsShareAPI iocshRegisterVariable (const iocshVarDef *piocshVarDef) break; } if (!found) { - n = (struct iocshVariable *)callocMustSucceed(1, sizeof *n, "iocshRegisterVariable"); + n = (struct iocshVariable *) callocMustSucceed(1, sizeof *n, + "iocshRegisterVariable"); if (!registryAdd(iocshVarID, piocshVarDef->name, (void *)n)) { free(n); iocshTableUnlock(); - errlogPrintf("iocshRegisterVariable failed to add %s.\n", piocshVarDef->name); + errlogPrintf("iocshRegisterVariable failed to add %s.\n", + piocshVarDef->name); return; } if (l == NULL) { @@ -225,14 +230,15 @@ showError (const char *filename, int lineno, const char *msg, ...) va_start (ap, msg); if (filename) - fprintf (stderr, "%s -- Line %d -- ", filename, lineno); - vfprintf (stderr, msg, ap); - fputc ('\n', stderr); + fprintf(epicsGetStderr(), "%s line %d: ", filename, lineno); + vfprintf (epicsGetStderr(), msg, ap); + fputc ('\n', epicsGetStderr()); va_end (ap); } static int -cvtArg (const char *filename, int lineno, char *arg, iocshArgBuf *argBuf, const iocshArg *piocshArg) +cvtArg (const char *filename, int lineno, char *arg, iocshArgBuf *argBuf, + const iocshArg *piocshArg) { char *endp; @@ -245,12 +251,13 @@ cvtArg (const char *filename, int lineno, char *arg, iocshArgBuf *argBuf, const errno = 0; argBuf->ival = strtoul (arg, &endp, 0); if (errno == ERANGE) { - showError (filename, lineno, "Integer '%s' out of range", arg); + showError(filename, lineno, "Integer '%s' out of range", + arg); return 0; } } if (*endp) { - showError (filename, lineno, "Illegal integer '%s'", arg); + showError(filename, lineno, "Illegal integer '%s'", arg); return 0; } } @@ -263,7 +270,7 @@ cvtArg (const char *filename, int lineno, char *arg, iocshArgBuf *argBuf, const if (arg && *arg) { argBuf->dval = epicsStrtod (arg, &endp); if (*endp) { - showError (filename, lineno, "Illegal double '%s'", arg); + showError(filename, lineno, "Illegal double '%s'", arg); return 0; } } @@ -279,7 +286,7 @@ cvtArg (const char *filename, int lineno, char *arg, iocshArgBuf *argBuf, const case iocshArgPersistentString: argBuf->sval = epicsStrDup(arg); if (argBuf->sval == NULL) { - showError (filename, lineno, "Out of memory"); + showError(filename, lineno, "Out of memory"); return 0; } break; @@ -288,17 +295,18 @@ cvtArg (const char *filename, int lineno, char *arg, iocshArgBuf *argBuf, const /* Argument must be missing or 0 or pdbbase */ if(!arg || !*arg || (*arg == '0') || (strcmp(arg, "pdbbase") == 0)) { if(!iocshPpdbbase || !*iocshPpdbbase) { - showError (filename, lineno, "pdbbase not present"); + showError(filename, lineno, "pdbbase not present"); return 0; } argBuf->vval = *iocshPpdbbase; break; } - showError (filename, lineno, "Expecting 'pdbbase' got '%s'", arg); + showError(filename, lineno, "Expecting 'pdbbase' got '%s'", arg); return 0; default: - showError (filename, lineno, "Illegal argument type %d", piocshArg->type); + showError(filename, lineno, "Illegal argument type %d", + piocshArg->type); return 0; } return 1; @@ -329,6 +337,7 @@ openRedirect(const char *filename, int lineno, struct iocshRedirect *redirect) } return -1; } + redirect->mustRestore = 0; } } return 0; @@ -349,14 +358,17 @@ startRedirect(const char * /*filename*/, int /*lineno*/, case 0: redirect->oldFp = epicsGetThreadStdin(); epicsSetThreadStdin(redirect->fp); + redirect->mustRestore = 1; break; case 1: redirect->oldFp = epicsGetThreadStdout(); epicsSetThreadStdout(redirect->fp); + redirect->mustRestore = 1; break; case 2: redirect->oldFp = epicsGetThreadStderr(); epicsSetThreadStderr(redirect->fp); + redirect->mustRestore = 1; break; } } @@ -377,10 +389,12 @@ stopRedirect(const char *filename, int lineno, struct iocshRedirect *redirect) showError(filename, lineno, "Error closing \"%s\": %s.", redirect->name, strerror(errno)); redirect->fp = NULL; - switch(i) { - case 0: epicsSetThreadStdin(redirect->oldFp); break; - case 1: epicsSetThreadStdout(redirect->oldFp); break; - case 2: epicsSetThreadStderr(redirect->oldFp); break; + if (redirect->mustRestore) { + switch(i) { + case 0: epicsSetThreadStdin(redirect->oldFp); break; + case 1: epicsSetThreadStdout(redirect->oldFp); break; + case 2: epicsSetThreadStderr(redirect->oldFp); break; + } } } redirect->name = NULL; @@ -404,30 +418,31 @@ static void helpCallFunc(const iocshArgBuf *args) if (argc == 1) { int l, col = 0; - printf ("Type 'help command_name' to get more information about a particular command.\n"); + fprintf(epicsGetStdout(), + "Type 'help ' to see the arguments of .\n"); iocshTableLock (); for (pcmd = iocshCommandHead ; pcmd != NULL ; pcmd = pcmd->next) { piocshFuncDef = pcmd->pFuncDef; l = strlen (piocshFuncDef->name); if ((l + col) >= 79) { - fputc ('\n', stdout); + fputc('\n', epicsGetStdout()); col = 0; } - fputs (piocshFuncDef->name, stdout); + fputs(piocshFuncDef->name, epicsGetStdout()); col += l; if (col >= 64) { - fputc ('\n', stdout); + fputc('\n', epicsGetStdout()); col = 0; } else { do { - fputc (' ', stdout); + fputc(' ', epicsGetStdout()); col++; } while ((col % 16) != 0); } } if (col) - fputc ('\n', stdout); + fputc('\n', epicsGetStdout()); iocshTableUnlock (); } else { @@ -435,18 +450,18 @@ static void helpCallFunc(const iocshArgBuf *args) for (pcmd = iocshCommandHead ; pcmd != NULL ; pcmd = pcmd->next) { piocshFuncDef = pcmd->pFuncDef; if (epicsStrGlobMatch(piocshFuncDef->name, argv[iarg]) != 0) { - fputs (piocshFuncDef->name, stdout); + fputs(piocshFuncDef->name, epicsGetStdout()); for (int a = 0 ; a < piocshFuncDef->nargs ; a++) { const char *cp = piocshFuncDef->arg[a]->name; if ((piocshFuncDef->arg[a]->type == iocshArgArgv) || (strchr (cp, ' ') == NULL)) { - fprintf (stdout, " %s", cp); + fprintf(epicsGetStdout(), " %s", cp); } else { - fprintf (stdout, " '%s'", cp); + fprintf(epicsGetStdout(), " '%s'", cp); } } - fprintf (stdout,"\n");; + fprintf(epicsGetStdout(),"\n");; } } } @@ -478,7 +493,6 @@ iocshBody (const char *pathname, const char *commandLine) iocshArgBuf *argBuf = NULL; int argBufCapacity = 0; struct iocshCommand *found; - struct iocshFuncDef const *piocshFuncDef; void *readlineContext = NULL; int wasOkToBlock; @@ -493,7 +507,8 @@ iocshBody (const char *pathname, const char *commandLine) else { fp = fopen (pathname, "r"); if (fp == NULL) { - fprintf (stderr, "Can't open %s: %s\n", pathname, strerror (errno)); + fprintf(epicsGetStderr(), "Can't open %s: %s\n", pathname, + strerror (errno)); return -1; } if ((filename = strrchr (pathname, '/')) == NULL) @@ -507,7 +522,7 @@ iocshBody (const char *pathname, const char *commandLine) * Create a command-line input context */ if ((readlineContext = epicsReadlineBegin(fp)) == NULL) { - fprintf(stderr, "Can't allocate command-line object.\n"); + fprintf(epicsGetStderr(), "Can't allocate command-line object.\n"); if (fp) fclose(fp); return -1; @@ -519,7 +534,7 @@ iocshBody (const char *pathname, const char *commandLine) */ redirects = (struct iocshRedirect *)calloc(NREDIRECTS, sizeof *redirects); if (redirects == NULL) { - printf ("Out of memory!\n"); + fprintf(epicsGetStderr(), "Out of memory!\n"); return -1; } @@ -604,7 +619,7 @@ iocshBody (const char *pathname, const char *commandLine) argvCapacity += 50; av = (char **)realloc (argv, argvCapacity * sizeof *argv); if (av == NULL) { - printf ("Out of memory!\n"); + fprintf (epicsGetStderr(), "Out of memory!\n"); argc = -1; break; } @@ -699,17 +714,17 @@ iocshBody (const char *pathname, const char *commandLine) backslash = 0; } if (redirect != NULL) { - showError (filename, lineno, "Illegal redirection."); + showError(filename, lineno, "Illegal redirection."); continue; } if (argc < 0) break; if (quote != EOF) { - showError (filename, lineno, "Unbalanced quote."); + showError(filename, lineno, "Unbalanced quote."); continue; } if (backslash) { - showError (filename, lineno, "Trailing backslash."); + showError(filename, lineno, "Trailing backslash."); continue; } if (inword) @@ -730,73 +745,68 @@ iocshBody (const char *pathname, const char *commandLine) stopRedirect(filename, lineno, redirects); continue; } - if (openRedirect(filename, lineno, redirects) < 0) - continue; /* - * Look up command + * Special command? */ - if (argc) { - /* - * Special command? - */ - if (strncmp (argv[0], "exit", 4) == 0) - break; - if ((strcmp (argv[0], "?") == 0) - || (strncmp (argv[0], "help", 4) == 0)) { - } + if ((argc > 0) && (strcmp(argv[0], "exit") == 0)) + break; + /* + * Set up redirection + */ + if ((openRedirect(filename, lineno, redirects) == 0) && (argc > 0)) { /* * Look up command */ found = (iocshCommand *)registryFind (iocshCmdID, argv[0]); - if (!found) { - showError (filename, lineno, "Command %s not found.", argv[0]); - continue; - } - piocshFuncDef = found->pFuncDef; - - /* - * Process arguments and call function - */ - for (int iarg = 0 ; ; ) { - if (iarg == piocshFuncDef->nargs) { - startRedirect(filename, lineno, redirects); - (*found->func)(argBuf); - stopRedirect(filename, lineno, redirects); - break; - } - if (iarg >= argBufCapacity) { - void *np; - - argBufCapacity += 20; - np = realloc (argBuf, argBufCapacity * sizeof *argBuf); - if (np == NULL) { - fprintf (stderr, "Out of memory!\n"); - argBufCapacity -= 20; + if (found) { + /* + * Process arguments and call function + */ + struct iocshFuncDef const *piocshFuncDef = found->pFuncDef; + for (int iarg = 0 ; ; ) { + if (iarg == piocshFuncDef->nargs) { + startRedirect(filename, lineno, redirects); + (*found->func)(argBuf); break; } - argBuf = (iocshArgBuf *)np; + if (iarg >= argBufCapacity) { + void *np; + + argBufCapacity += 20; + np = realloc (argBuf, argBufCapacity * sizeof *argBuf); + if (np == NULL) { + fprintf (epicsGetStderr(), "Out of memory!\n"); + argBufCapacity -= 20; + break; + } + argBuf = (iocshArgBuf *)np; + } + if (piocshFuncDef->arg[iarg]->type == iocshArgArgv) { + argBuf[iarg].aval.ac = argc-iarg; + argBuf[iarg].aval.av = argv+iarg; + iarg = piocshFuncDef->nargs; + } + else { + if (!cvtArg (filename, lineno, + ((iarg < argc) ? argv[iarg+1] : NULL), + &argBuf[iarg], piocshFuncDef->arg[iarg])) + break; + iarg++; + } } - if (piocshFuncDef->arg[iarg]->type == iocshArgArgv) { - argBuf[iarg].aval.ac = argc-iarg; - argBuf[iarg].aval.av = argv+iarg; - iarg = piocshFuncDef->nargs; - } - else { - if (!cvtArg (filename, lineno, - ((iarg < argc) ? argv[iarg+1] : NULL), - &argBuf[iarg], piocshFuncDef->arg[iarg])) - break; - iarg++; + if ((prompt != NULL) && (strcmp(argv[0], "epicsEnvSet") == 0)) { + const char *newPrompt; + if ((newPrompt = envGetConfigParamPtr(&IOCSH_PS1)) != NULL) + prompt = newPrompt; } } - if((prompt != NULL) && (strcmp(argv[0], "epicsEnvSet") == 0)) { - const char *newPrompt; - if ((newPrompt = envGetConfigParamPtr(&IOCSH_PS1)) != NULL) - prompt = newPrompt; + else { + showError(filename, lineno, "Command %s not found.", argv[0]); } } + stopRedirect(filename, lineno, redirects); } if (fp && (fp != stdin)) fclose (fp); @@ -840,7 +850,8 @@ static void varHandler(const iocshVarDef *v, const char *setString) { switch(v->type) { default: - printf("Can't handle variable %s of type %d.\n", v->name, v->type); + fprintf(epicsGetStderr(), "Can't handle variable %s of type %d.\n", + v->name, v->type); return; case iocshArgInt: break; case iocshArgDouble: break; @@ -849,10 +860,10 @@ static void varHandler(const iocshVarDef *v, const char *setString) switch(v->type) { default: break; case iocshArgInt: - printf("%s = %d\n", v->name, *(int *)v->pval); + fprintf(epicsGetStdout(), "%s = %d\n", v->name, *(int *)v->pval); break; case iocshArgDouble: - printf("%s = %g\n", v->name, *(double *)v->pval); + fprintf(epicsGetStdout(), "%s = %g\n", v->name, *(double *)v->pval); break; } } @@ -866,7 +877,8 @@ static void varHandler(const iocshVarDef *v, const char *setString) if((*setString != '\0') && (*endp == '\0')) *(int *)v->pval = ltmp; else - printf("Invalid value -- value of %s not changed.\n", v->name); + fprintf(epicsGetStderr(), + "Invalid integer value. Var %s not changed.\n", v->name); break; } case iocshArgDouble: @@ -876,7 +888,8 @@ static void varHandler(const iocshVarDef *v, const char *setString) if((*setString != '\0') && (*endp == '\0')) *(double *)v->pval = dtmp; else - printf("Invalid value -- value of %s not changed.\n", v->name); + fprintf(epicsGetStderr(), + "Invalid double value. Var %s not changed.\n", v->name); break; } } @@ -893,7 +906,7 @@ static void varCallFunc(const iocshArgBuf *args) else { v = (iocshVariable *)registryFind(iocshVarID, args[0].sval); if (v == NULL) { - printf("%s -- no such variable.\n", args[0].sval); + fprintf(epicsGetStderr(), "Var %s not found.\n", args[0].sval); } else { varHandler(v->pVarDef, args[1].sval); @@ -916,7 +929,8 @@ static void iocshCmdCallFunc(const iocshArgBuf *args) */ /* comment */ -static const iocshArg commentArg0 = { "newline-terminated comment",iocshArgArgv}; +static const iocshArg commentArg0 = { "newline-terminated comment", + iocshArgArgv}; static const iocshArg *commentArgs[1] = {&commentArg0}; static const iocshFuncDef commentFuncDef = {"#",1,commentArgs}; static void commentCallFunc(const iocshArgBuf *) diff --git a/src/libCom/iocsh/libComRegister.c b/src/libCom/iocsh/libComRegister.c index f6ce30284..b3f3b2f36 100644 --- a/src/libCom/iocsh/libComRegister.c +++ b/src/libCom/iocsh/libComRegister.c @@ -9,10 +9,10 @@ \*************************************************************************/ #include -#include #define epicsExportSharedSymbols #include "iocsh.h" +#include "epicsStdioRedirect.h" #include "epicsTime.h" #include "epicsThread.h" #include "epicsMutex.h" @@ -60,7 +60,7 @@ static void chdirCallFunc(const iocshArgBuf *args) int status; status = chdir(args[0].sval); if (status) { - printf ("Invalid directory path ignored\n"); + fprintf(stderr, "Invalid directory path, ignored\n"); } } @@ -86,11 +86,11 @@ static void epicsEnvSetCallFunc(const iocshArgBuf *args) char *value = args[1].sval; if (name == NULL) { - printf ("Missing environment variable name argument.\n"); + fprintf(stderr, "Missing environment variable name argument.\n"); return; } if (value == NULL) { - printf ("Missing environment variable value argument.\n"); + fprintf(stderr, "Missing environment variable value argument.\n"); return; } epicsEnvSet (name, value); @@ -240,7 +240,7 @@ static void threadCallFunc(const iocshArgBuf *args) if (*endp) { tid = epicsThreadGetId (cp); if (!tid) { - printf ("\t'%s' is not a known thread name\n", cp); + fprintf(stderr, "\t'%s' is not a known thread name\n", cp); continue; } } @@ -308,7 +308,7 @@ static void epicsThreadResumeCallFunc(const iocshArgBuf *args) if (*endp) { tid = epicsThreadGetId(cp); if (!tid) { - printf("*** argument %d (%s) is not a valid thread name ***\n", i, cp); + fprintf(stderr, "'%s' is not a valid thread name\n", cp); continue; } } @@ -316,13 +316,13 @@ static void epicsThreadResumeCallFunc(const iocshArgBuf *args) tid =(epicsThreadId)ltmp; epicsThreadGetName(tid, nameBuf, sizeof nameBuf); if (nameBuf[0] == '\0') { - printf("*** argument %d (%s) is not a valid thread id ***\n", i, cp); + fprintf(stderr, "'%s' is not a valid thread id\n", cp); continue; } } if (!epicsThreadIsSuspended(tid)) { - printf("*** Thread %s is not suspended ***\n", cp); + fprintf(stderr, "Thread %s is not suspended\n", cp); continue; } epicsThreadResume(tid); diff --git a/src/libCom/macLib/macUtil.c b/src/libCom/macLib/macUtil.c index d47d3a131..ee7b53f7f 100644 --- a/src/libCom/macLib/macUtil.c +++ b/src/libCom/macLib/macUtil.c @@ -3,8 +3,7 @@ * 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 +* EPICS BASE is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ /* $Revision-Id$ @@ -51,11 +50,11 @@ epicsShareAPI macParseDefns( int quote; int escape; size_t nbytes; - const unsigned char **ptr; - const unsigned char **end; + const char **ptr; + const char **end; int *del; char *memCp, **memCpp; - const unsigned char *c; + const char *c; char *s, *d, **p; enum { preName, inName, preValue, inValue } state; @@ -68,8 +67,8 @@ epicsShareAPI macParseDefns( numMax = strlen( defns ); if ( numMax < altNumMax ) numMax = altNumMax; - ptr = (const unsigned char **) calloc( numMax, sizeof( char * ) ); - end = (const unsigned char **) calloc( numMax, sizeof( char * ) ); + ptr = (const char **) calloc( numMax, sizeof( char * ) ); + end = (const char **) calloc( numMax, sizeof( char * ) ); del = (int *) calloc( numMax, sizeof( int ) ); if ( ptr == NULL || end == NULL || del == NULL ) goto error; @@ -80,7 +79,7 @@ epicsShareAPI macParseDefns( del[0] = FALSE; quote = 0; state = preName; - for ( c = (const unsigned char *) defns; *c != '\0'; c++ ) { + for ( c = (const char *) defns; *c != '\0'; c++ ) { /* handle quotes */ if ( quote ) @@ -226,8 +225,8 @@ epicsShareAPI macParseDefns( } /* free workspace */ - free( ptr ); - free( end ); + free( ( void * ) ptr ); + free( ( void * ) end ); free( ( char * ) del ); /* debug output */ @@ -240,8 +239,8 @@ epicsShareAPI macParseDefns( /* error exit */ error: errlogPrintf( "macParseDefns: failed to allocate memory\n" ); - if ( ptr != NULL ) free( ptr ); - if ( end != NULL ) free( end ); + if ( ptr != NULL ) free( ( void * ) ptr ); + if ( end != NULL ) free( ( void * ) end ); if ( del != NULL ) free( ( char * ) del ); *pairs = NULL; return -1; diff --git a/src/libCom/osi/epicsGeneralTime.c b/src/libCom/osi/epicsGeneralTime.c index 819220ea7..8ef8a73cc 100644 --- a/src/libCom/osi/epicsGeneralTime.c +++ b/src/libCom/osi/epicsGeneralTime.c @@ -9,7 +9,6 @@ /* Original Authors: David H. Thompson & Sheng Peng (ORNL) */ -#include #include #include @@ -19,6 +18,7 @@ #include "epicsMutex.h" #include "epicsMessageQueue.h" #include "epicsString.h" +#include "epicsStdioRedirect.h" #include "epicsThread.h" #include "epicsTime.h" #include "epicsTimer.h" diff --git a/src/libCom/osi/os/WIN32/osdMutex.c b/src/libCom/osi/os/WIN32/osdMutex.c index 4e6c885ff..0104ac566 100644 --- a/src/libCom/osi/os/WIN32/osdMutex.c +++ b/src/libCom/osi/os/WIN32/osdMutex.c @@ -38,8 +38,9 @@ * It appears that the only entry point used here that causes * portability problems with W95\W98\WME is TryEnterCriticalSection. */ -#undef _WIN32_WINNT -#define _WIN32_WINNT 0x0400 +#ifndef _WIN32_WINNT +# define _WIN32_WINNT 0x0400 +#endif #include #define epicsExportSharedSymbols diff --git a/src/libCom/osi/os/WIN32/osdThread.c b/src/libCom/osi/os/WIN32/osdThread.c index 6246c7736..155792a30 100644 --- a/src/libCom/osi/os/WIN32/osdThread.c +++ b/src/libCom/osi/os/WIN32/osdThread.c @@ -22,8 +22,8 @@ #define VC_EXTRALEAN #define STRICT -#if _WIN64 -# define _WIN32_WINNT 0x400 /* defining this drops support for W95 */ +#ifndef _WIN32_WINNT +# define _WIN32_WINNT 0x400 /* No support for W95 */ #endif #include #include /* for _endthread() etc */ diff --git a/src/libCom/osi/os/cygwin32/systemCallIntMech.cpp b/src/libCom/osi/os/cygwin32/systemCallIntMech.cpp index 113bc738a..6a5ce4c9f 100644 --- a/src/libCom/osi/os/cygwin32/systemCallIntMech.cpp +++ b/src/libCom/osi/os/cygwin32/systemCallIntMech.cpp @@ -1,12 +1,10 @@ - /*************************************************************************\ * 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. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* $Revision-Id$ */ /* diff --git a/src/libCom/taskwd/taskwd.c b/src/libCom/taskwd/taskwd.c index c034e1828..f8a061c2c 100644 --- a/src/libCom/taskwd/taskwd.c +++ b/src/libCom/taskwd/taskwd.c @@ -22,7 +22,7 @@ #include "dbDefs.h" #include "epicsEvent.h" #include "epicsExit.h" -#include "epicsStdio.h" +#include "epicsStdioRedirect.h" #include "epicsThread.h" #include "epicsMutex.h" #include "errlog.h" diff --git a/src/libCom/test/Makefile b/src/libCom/test/Makefile index bef859a8f..870313e1c 100755 --- a/src/libCom/test/Makefile +++ b/src/libCom/test/Makefile @@ -42,6 +42,11 @@ epicsEllTest_SRCS += epicsEllTest.c testHarness_SRCS += epicsEllTest.c TESTS += epicsEllTest +TESTPROD_HOST += epicsEnvTest +epicsEnvTest_SRCS += epicsEnvTest.c +testHarness_SRCS += epicsEnvTest.c +TESTS += epicsEnvTest + TESTPROD_HOST += epicsErrlogTest epicsErrlogTest_SRCS += epicsErrlogTest.c epicsErrlogTest_SYS_LIBS_solaris = socket diff --git a/src/libCom/test/epicsEnvTest.c b/src/libCom/test/epicsEnvTest.c new file mode 100644 index 000000000..bbce4b749 --- /dev/null +++ b/src/libCom/test/epicsEnvTest.c @@ -0,0 +1,78 @@ +/*************************************************************************\ +* Copyright (c) 2013 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. +\*************************************************************************/ +/* epicsEnvTest.c */ + +/* Author: Andrew Johnson + * Date: 2013-12-13 + */ + +/* Check environment variable APIs. + * TODO: Add tests for envDefs.h routines. + * + * The thread test is needed on VxWorks 6.x, where the OS can be + * configured to maintain separate, totally independent sets + * of environment variables for each thread. This configuration + * is not supported by EPICS which expects child threads to at + * least inherit the partent thread's environment variables. + */ + +#include +#include + +#include "envDefs.h" +#include "epicsThread.h" +#include "epicsUnitTest.h" +#include "testMain.h" + +#define PARENT "Parent" +#define CHILD "Child" + +static void child(void *arg) +{ + const char *value = getenv(PARENT); + + if (!testOk(value && (strcmp(value, PARENT) == 0), + "Child thread sees parent environment values")) { +#ifdef vxWorks + testDiag("VxWorks image needs ENV_VAR_USE_HOOKS configured as FALSE"); +#else + testDiag("Check OS configuration, environment inheritance needed"); +#endif + } + + epicsEnvSet(CHILD, CHILD); +} + +MAIN(epicsEnvTest) +{ + unsigned int stackSize = epicsThreadGetStackSize(epicsThreadStackSmall); + const char *value; + + testPlan(3); + + epicsEnvSet(PARENT, PARENT); + + value = getenv(PARENT); + if (!testOk(value && (strcmp(value, PARENT) == 0), + "epicsEnvSet correctly modifies environment")) + testAbort("environment variables not working"); + + epicsThreadCreate("child", 50, stackSize, child, NULL); + epicsThreadSleep(0.1); + + value = getenv(CHILD); + if (value && (strcmp(value, CHILD) == 0)) + testDiag("Child and parent threads share a common environment"); + + value = getenv(PARENT); + testOk(value && (strcmp(value, PARENT) == 0), + "PARENT environment variable not modified"); + + testDone(); + return 0; +} + diff --git a/src/libCom/test/epicsRunLibComTests.c b/src/libCom/test/epicsRunLibComTests.c index c80f0244c..f77821199 100644 --- a/src/libCom/test/epicsRunLibComTests.c +++ b/src/libCom/test/epicsRunLibComTests.c @@ -20,6 +20,7 @@ int epicsThreadTest(void); int epicsTimerTest(void); int epicsAlgorithm(void); int epicsEllTest(void); +int epicsEnvTest(void); int epicsErrlogTest(void); int epicsCalcTest(void); int epicsEventTest(void); @@ -63,6 +64,8 @@ void epicsRunLibComTests(void) runTest(epicsEllTest); + runTest(epicsEnvTest); + runTest(epicsErrlogTest); runTest(epicsCalcTest); diff --git a/src/std/dbRecStd.rc b/src/std/dbRecStd.rc old mode 100755 new mode 100644 diff --git a/src/std/dev/devStdio.c b/src/std/dev/devStdio.c index a4ebd64e7..4801657b9 100644 --- a/src/std/dev/devStdio.c +++ b/src/std/dev/devStdio.c @@ -15,6 +15,7 @@ #include "errlog.h" #include "recGbl.h" #include "recSup.h" + #include "lsoRecord.h" #include "printfRecord.h" #include "stringoutRecord.h" diff --git a/src/std/dev/softDevIoc.rc b/src/std/dev/softDevIoc.rc old mode 100755 new mode 100644 diff --git a/src/std/rec/aaiRecord.c b/src/std/rec/aaiRecord.c index 96e0960ce..5b370fe4c 100644 --- a/src/std/rec/aaiRecord.c +++ b/src/std/rec/aaiRecord.c @@ -41,6 +41,7 @@ #include "recGbl.h" #include "cantProceed.h" #include "menuYesNo.h" + #define GEN_SIZE_OFFSET #include "aaiRecord.h" #undef GEN_SIZE_OFFSET diff --git a/src/std/rec/aaoRecord.c b/src/std/rec/aaoRecord.c index ca26aac52..565fd2886 100644 --- a/src/std/rec/aaoRecord.c +++ b/src/std/rec/aaoRecord.c @@ -41,6 +41,7 @@ #include "recGbl.h" #include "cantProceed.h" #include "menuYesNo.h" + #define GEN_SIZE_OFFSET #include "aaoRecord.h" #undef GEN_SIZE_OFFSET diff --git a/src/std/rec/aiRecord.c b/src/std/rec/aiRecord.c index 4f2211e52..c7f4d7977 100644 --- a/src/std/rec/aiRecord.c +++ b/src/std/rec/aiRecord.c @@ -36,6 +36,7 @@ #include "recGbl.h" #include "special.h" #include "menuConvert.h" + #define GEN_SIZE_OFFSET #include "aiRecord.h" #undef GEN_SIZE_OFFSET diff --git a/src/std/rec/aoRecord.c b/src/std/rec/aoRecord.c index 31bd3c12c..78febffe5 100644 --- a/src/std/rec/aoRecord.c +++ b/src/std/rec/aoRecord.c @@ -37,10 +37,11 @@ #include "menuConvert.h" #include "menuOmsl.h" #include "menuYesNo.h" +#include "menuIvoa.h" + #define GEN_SIZE_OFFSET #include "aoRecord.h" #undef GEN_SIZE_OFFSET -#include "menuIvoa.h" #include "epicsExport.h" /* Create RSET - Record Support Entry Table*/ diff --git a/src/std/rec/biRecord.c b/src/std/rec/biRecord.c index c8dda1da5..1e09ce2f7 100644 --- a/src/std/rec/biRecord.c +++ b/src/std/rec/biRecord.c @@ -34,10 +34,12 @@ #include "recSup.h" #include "recGbl.h" #include "special.h" + #define GEN_SIZE_OFFSET #include "biRecord.h" #undef GEN_SIZE_OFFSET #include "epicsExport.h" + /* Create RSET - Record Support Entry Table*/ #define report NULL #define initialize NULL diff --git a/src/std/rec/boRecord.c b/src/std/rec/boRecord.c index df8f17671..55e198220 100644 --- a/src/std/rec/boRecord.c +++ b/src/std/rec/boRecord.c @@ -33,12 +33,13 @@ #include "recSup.h" #include "recGbl.h" #include "special.h" -#define GEN_SIZE_OFFSET -#include "boRecord.h" -#undef GEN_SIZE_OFFSET #include "menuIvoa.h" #include "menuOmsl.h" #include "menuYesNo.h" + +#define GEN_SIZE_OFFSET +#include "boRecord.h" +#undef GEN_SIZE_OFFSET #include "epicsExport.h" /* Create RSET - Record Support Entry Table*/ diff --git a/src/std/rec/calcRecord.c b/src/std/rec/calcRecord.c index 1efe71de6..9a7a56e96 100644 --- a/src/std/rec/calcRecord.c +++ b/src/std/rec/calcRecord.c @@ -32,6 +32,7 @@ #include "recSup.h" #include "recGbl.h" #include "special.h" + #define GEN_SIZE_OFFSET #include "calcRecord.h" #undef GEN_SIZE_OFFSET diff --git a/src/std/rec/calcoutRecord.c b/src/std/rec/calcoutRecord.c index 580546e64..190c94c96 100644 --- a/src/std/rec/calcoutRecord.c +++ b/src/std/rec/calcoutRecord.c @@ -36,13 +36,13 @@ #include "special.h" #include "callback.h" #include "taskwd.h" +#include "menuIvoa.h" #define GEN_SIZE_OFFSET #include "calcoutRecord.h" #undef GEN_SIZE_OFFSET -#include "menuIvoa.h" #include "epicsExport.h" - + /* Create RSET - Record Support Entry Table*/ #define report NULL #define initialize NULL diff --git a/src/std/rec/compressRecord.c b/src/std/rec/compressRecord.c index 07ad06a7f..0ecfbd4e5 100644 --- a/src/std/rec/compressRecord.c +++ b/src/std/rec/compressRecord.c @@ -31,6 +31,7 @@ #include "special.h" #include "recSup.h" #include "recGbl.h" + #define GEN_SIZE_OFFSET #include "compressRecord.h" #undef GEN_SIZE_OFFSET diff --git a/src/std/rec/dfanoutRecord.c b/src/std/rec/dfanoutRecord.c index 3deba1dc6..cccc91ab4 100644 --- a/src/std/rec/dfanoutRecord.c +++ b/src/std/rec/dfanoutRecord.c @@ -38,6 +38,7 @@ #include "recGbl.h" #include "special.h" #include "menuOmsl.h" + #define GEN_SIZE_OFFSET #include "dfanoutRecord.h" #undef GEN_SIZE_OFFSET diff --git a/src/std/rec/eventRecord.c b/src/std/rec/eventRecord.c index 435666ccf..9e25f7baa 100644 --- a/src/std/rec/eventRecord.c +++ b/src/std/rec/eventRecord.c @@ -34,6 +34,7 @@ #include "recGbl.h" #include "special.h" #include "menuYesNo.h" + #define GEN_SIZE_OFFSET #include "eventRecord.h" #undef GEN_SIZE_OFFSET diff --git a/src/std/rec/fanoutRecord.c b/src/std/rec/fanoutRecord.c index c881c9760..e2bec291c 100644 --- a/src/std/rec/fanoutRecord.c +++ b/src/std/rec/fanoutRecord.c @@ -30,6 +30,7 @@ #include "recSup.h" #include "recGbl.h" #include "dbCommon.h" + #define GEN_SIZE_OFFSET #include "fanoutRecord.h" #undef GEN_SIZE_OFFSET diff --git a/src/std/rec/histogramRecord.c b/src/std/rec/histogramRecord.c index 0d57f0e29..74b2fcd17 100644 --- a/src/std/rec/histogramRecord.c +++ b/src/std/rec/histogramRecord.c @@ -37,6 +37,7 @@ #include "recSup.h" #include "recGbl.h" #include "menuYesNo.h" + #define GEN_SIZE_OFFSET #include "histogramRecord.h" #undef GEN_SIZE_OFFSET diff --git a/src/std/rec/longinRecord.c b/src/std/rec/longinRecord.c index a0f52e6b4..b4b50ebd5 100644 --- a/src/std/rec/longinRecord.c +++ b/src/std/rec/longinRecord.c @@ -33,6 +33,7 @@ #include "recSup.h" #include "recGbl.h" #include "menuYesNo.h" + #define GEN_SIZE_OFFSET #include "longinRecord.h" #undef GEN_SIZE_OFFSET diff --git a/src/std/rec/longoutRecord.c b/src/std/rec/longoutRecord.c index 6c7e8f10b..afdf90ea8 100644 --- a/src/std/rec/longoutRecord.c +++ b/src/std/rec/longoutRecord.c @@ -29,13 +29,14 @@ #include "recSup.h" #include "recGbl.h" #include "menuYesNo.h" +#include "menuIvoa.h" +#include "menuOmsl.h" + #define GEN_SIZE_OFFSET #include "longoutRecord.h" #undef GEN_SIZE_OFFSET -#include "menuIvoa.h" -#include "menuOmsl.h" #include "epicsExport.h" - + /* Create RSET - Record Support Entry Table*/ #define report NULL #define initialize NULL diff --git a/src/std/rec/mbbiDirectRecord.c b/src/std/rec/mbbiDirectRecord.c index f905db8e5..74cc3d1f9 100644 --- a/src/std/rec/mbbiDirectRecord.c +++ b/src/std/rec/mbbiDirectRecord.c @@ -35,6 +35,7 @@ #include "recSup.h" #include "recGbl.h" #include "special.h" + #define GEN_SIZE_OFFSET #include "mbbiDirectRecord.h" #undef GEN_SIZE_OFFSET diff --git a/src/std/rec/mbbiRecord.c b/src/std/rec/mbbiRecord.c index e7d3e171e..9c1ec6fd1 100644 --- a/src/std/rec/mbbiRecord.c +++ b/src/std/rec/mbbiRecord.c @@ -33,6 +33,7 @@ #include "recSup.h" #include "recGbl.h" #include "special.h" + #define GEN_SIZE_OFFSET #include "mbbiRecord.h" #undef GEN_SIZE_OFFSET diff --git a/src/std/rec/mbboDirectRecord.c b/src/std/rec/mbboDirectRecord.c index 99c043517..728f99d74 100644 --- a/src/std/rec/mbboDirectRecord.c +++ b/src/std/rec/mbboDirectRecord.c @@ -32,12 +32,13 @@ #include "recSup.h" #include "recGbl.h" #include "special.h" -#define GEN_SIZE_OFFSET -#include "mbboDirectRecord.h" -#undef GEN_SIZE_OFFSET #include "menuOmsl.h" #include "menuIvoa.h" #include "menuYesNo.h" + +#define GEN_SIZE_OFFSET +#include "mbboDirectRecord.h" +#undef GEN_SIZE_OFFSET #include "epicsExport.h" /* Create RSET - Record Support Entry Table*/ diff --git a/src/std/rec/mbboRecord.c b/src/std/rec/mbboRecord.c index 927d5eb75..4655638c4 100644 --- a/src/std/rec/mbboRecord.c +++ b/src/std/rec/mbboRecord.c @@ -33,12 +33,13 @@ #include "recSup.h" #include "recGbl.h" #include "special.h" -#define GEN_SIZE_OFFSET -#include "mbboRecord.h" -#undef GEN_SIZE_OFFSET #include "menuOmsl.h" #include "menuIvoa.h" #include "menuYesNo.h" + +#define GEN_SIZE_OFFSET +#include "mbboRecord.h" +#undef GEN_SIZE_OFFSET #include "epicsExport.h" /* Create RSET - Record Support Entry Table*/ diff --git a/src/std/rec/permissiveRecord.c b/src/std/rec/permissiveRecord.c index a1d96d151..65077253a 100644 --- a/src/std/rec/permissiveRecord.c +++ b/src/std/rec/permissiveRecord.c @@ -29,6 +29,7 @@ #include "errMdef.h" #include "recSup.h" #include "recGbl.h" + #define GEN_SIZE_OFFSET #include "permissiveRecord.h" #undef GEN_SIZE_OFFSET diff --git a/src/std/rec/selRecord.c b/src/std/rec/selRecord.c index f4dfb0cc2..eb9a04af8 100644 --- a/src/std/rec/selRecord.c +++ b/src/std/rec/selRecord.c @@ -31,6 +31,7 @@ #include "errMdef.h" #include "recSup.h" #include "recGbl.h" + #define GEN_SIZE_OFFSET #include "selRecord.h" #undef GEN_SIZE_OFFSET diff --git a/src/std/rec/stateRecord.c b/src/std/rec/stateRecord.c index 193d7ca51..b295ccbb7 100644 --- a/src/std/rec/stateRecord.c +++ b/src/std/rec/stateRecord.c @@ -30,6 +30,7 @@ #include "errMdef.h" #include "recSup.h" #include "recGbl.h" + #define GEN_SIZE_OFFSET #include "stateRecord.h" #undef GEN_SIZE_OFFSET diff --git a/src/std/rec/stringinRecord.c b/src/std/rec/stringinRecord.c index bff03b4fc..02f454788 100644 --- a/src/std/rec/stringinRecord.c +++ b/src/std/rec/stringinRecord.c @@ -33,11 +33,12 @@ #include "recSup.h" #include "recGbl.h" #include "menuYesNo.h" + #define GEN_SIZE_OFFSET #include "stringinRecord.h" #undef GEN_SIZE_OFFSET #include "epicsExport.h" - + /* Create RSET - Record Support Entry Table*/ #define report NULL #define initialize NULL diff --git a/src/std/rec/stringoutRecord.c b/src/std/rec/stringoutRecord.c index d3a8ac314..1bd376176 100644 --- a/src/std/rec/stringoutRecord.c +++ b/src/std/rec/stringoutRecord.c @@ -32,14 +32,15 @@ #include "errMdef.h" #include "recSup.h" #include "recGbl.h" -#define GEN_SIZE_OFFSET -#include "stringoutRecord.h" -#undef GEN_SIZE_OFFSET #include "menuOmsl.h" #include "menuIvoa.h" #include "menuYesNo.h" + +#define GEN_SIZE_OFFSET +#include "stringoutRecord.h" +#undef GEN_SIZE_OFFSET #include "epicsExport.h" - + /* Create RSET - Record Support Entry Table*/ #define report NULL #define initialize NULL diff --git a/src/std/rec/subArrayRecord.c b/src/std/rec/subArrayRecord.c index 1112a3057..dd6d50a9c 100644 --- a/src/std/rec/subArrayRecord.c +++ b/src/std/rec/subArrayRecord.c @@ -37,6 +37,7 @@ #include "recSup.h" #include "recGbl.h" #include "cantProceed.h" + #define GEN_SIZE_OFFSET #include "subArrayRecord.h" #undef GEN_SIZE_OFFSET diff --git a/src/std/rec/subRecord.c b/src/std/rec/subRecord.c index 6c3187dd1..d081459e4 100644 --- a/src/std/rec/subRecord.c +++ b/src/std/rec/subRecord.c @@ -35,6 +35,7 @@ #include "recSup.h" #include "recGbl.h" #include "special.h" + #define GEN_SIZE_OFFSET #include "subRecord.h" #undef GEN_SIZE_OFFSET diff --git a/src/std/rec/waveformRecord.c b/src/std/rec/waveformRecord.c index b1e450d82..293be79af 100644 --- a/src/std/rec/waveformRecord.c +++ b/src/std/rec/waveformRecord.c @@ -23,6 +23,7 @@ #include "dbDefs.h" #include "epicsPrint.h" +#include "epicsString.h" #include "alarm.h" #include "dbAccess.h" #include "dbEvent.h" @@ -34,11 +35,11 @@ #include "recGbl.h" #include "cantProceed.h" #include "menuYesNo.h" + #define GEN_SIZE_OFFSET #include "waveformRecord.h" #undef GEN_SIZE_OFFSET #include "epicsExport.h" -#include "epicsString.h" /* Create RSET - Record Support Entry Table*/ #define report NULL diff --git a/src/template/base/makeBaseApp.pl b/src/template/base/makeBaseApp.pl old mode 100755 new mode 100644 diff --git a/src/template/ext/makeBaseExt.pl b/src/template/ext/makeBaseExt.pl old mode 100755 new mode 100644 diff --git a/src/tools/registerRecordDeviceDriver.pl b/src/tools/registerRecordDeviceDriver.pl old mode 100755 new mode 100644 diff --git a/startup/EpicsHostArch.pl b/startup/EpicsHostArch.pl index 942d55940..e6babf6d3 100755 --- a/startup/EpicsHostArch.pl +++ b/startup/EpicsHostArch.pl @@ -31,7 +31,10 @@ sub GetEpicsHostArch { # no args } elsif ($arch =~ m/arm-linux/) { return "linux-arm"; } elsif ($arch =~ m/MSWin32-x86/) { return "win32-x86"; } elsif ($arch =~ m/MSWin32-x64/) { return "windows-x64"; - } elsif ($arch =~ m/cygwin/) { return "cygwin-x86"; + } elsif ($arch =~ m/cygwin/) { + my($kernel, $hostname, $release, $version, $cpu) = POSIX::uname(); + if ($cpu =~ m/x86_64/) { return "cygwin-x86_64"; } + return "cygwin-x86"; } elsif ($arch =~ m/darwin/) { my($kernel, $hostname, $release, $version, $cpu) = POSIX::uname(); if ($cpu =~ m/Power Macintosh/) { return "darwin-ppc"; }