diff --git a/README b/README
index dcf34b258..f6af2f75c 100644
--- a/README
+++ b/README
@@ -20,5 +20,5 @@ Additional information about EPICS including mailing list
archives and subscription instructions, documentation and
training materials, additional components, links to other
websites etc. is available on the EPICS home page at
- http://www.aps.anl.gov/epics/
+ https://epics.anl.gov/
diff --git a/appveyor.yml b/appveyor.yml
index e4c5010cb..dbbd7a908 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -40,11 +40,12 @@ configuration:
# Environment variables: compiler toolchain
environment:
matrix:
- - TOOLCHAIN: 9.0
- TOOLCHAIN: 10.0
- TOOLCHAIN: 11.0
- TOOLCHAIN: 12.0
- TOOLCHAIN: 14.0
+ - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
+ TOOLCHAIN: 2017
- TOOLCHAIN: cygwin
- TOOLCHAIN: mingw
@@ -57,8 +58,6 @@ platform:
matrix:
exclude:
# VS Express installs don't have the 64 bit compiler
- - platform: x64
- TOOLCHAIN: 9.0
- platform: x64
TOOLCHAIN: 10.0
diff --git a/ci/appveyor-make.bat b/ci/appveyor-make.bat
index 8ecf61dbe..a489d80ee 100644
--- a/ci/appveyor-make.bat
+++ b/ci/appveyor-make.bat
@@ -1,6 +1,6 @@
:: Universal build script for AppVeyor (https://ci.appveyor.com/)
:: Environment:
-:: TOOLCHAIN - toolchain version [9.0/10.0/11.0/12.0/14.0/cygwin/mingw]
+:: TOOLCHAIN - toolchain version [10.0/11.0/12.0/14.0/2017/cygwin/mingw]
:: CONFIGURATION - determines EPICS build [dynamic/static]
:: PLATFORM - architecture [x86/x64]
::
@@ -57,10 +57,22 @@ if "%TOOLCHAIN%"=="mingw" (
)
set "VSINSTALL=C:\Program Files (x86)\Microsoft Visual Studio %TOOLCHAIN%"
+if not exist "%VSINSTALL%\" set "VSINSTALL=C:\Program Files (x86)\Microsoft Visual Studio\%TOOLCHAIN%\Community"
+if not exist "%VSINSTALL%\" goto MSMissing
+
set "MAKE=C:\tools\make"
+echo [INFO] APPVEYOR_BUILD_WORKER_IMAGE=%APPVEYOR_BUILD_WORKER_IMAGE%
+
if "%OS%"=="64BIT" (
set EPICS_HOST_ARCH=windows-x64%ST%
+ :: VS 2017
+ if exist "%VSINSTALL%\VC\Auxiliary\Build\vcvars64.bat" (
+ call "%VSINSTALL%\VC\Auxiliary\Build\vcvars64.bat"
+ where cl
+ if !ERRORLEVEL! NEQ 0 goto MSMissing
+ goto MSFound
+ )
if exist "%VSINSTALL%\VC\vcvarsall.bat" (
call "%VSINSTALL%\VC\vcvarsall.bat" amd64
where cl
@@ -79,12 +91,19 @@ if "%OS%"=="64BIT" (
)
) else (
set EPICS_HOST_ARCH=win32-x86%ST%
+ :: VS 2017
+ if exist "%VSINSTALL%\VC\Auxiliary\Build\vcvars32.bat" (
+ call "%VSINSTALL%\VC\Auxiliary\Build\vcvars32.bat"
+ where cl
+ if !ERRORLEVEL! NEQ 0 goto MSMissing
+ goto MSFound
+ )
if exist "%VSINSTALL%\VC\vcvarsall.bat" (
call "%VSINSTALL%\VC\vcvarsall.bat" x86
where cl
if !ERRORLEVEL! NEQ 0 goto MSMissing
goto MSFound
- )
+ )
if exist "%VSINSTALL%\VC\bin\vcvars32.bat" (
call "%VSINSTALL%\VC\bin\vcvars32.bat"
where cl
diff --git a/ci/appveyor-prepare.bat b/ci/appveyor-prepare.bat
index 6edb7b52f..26ca8118a 100644
--- a/ci/appveyor-prepare.bat
+++ b/ci/appveyor-prepare.bat
@@ -65,6 +65,6 @@ if "%TOOLCHAIN%"=="mingw" (
)
echo [INFO] Installing Make 4.1
-@powershell -Command "(new-object net.webclient).DownloadFile('https://www.aps.anl.gov/epics/download/tools/make-4.1-win64.zip', 'C:\tools\make-4.1.zip')"
+curl -fsS --retry 3 -o C:\tools\make-4.1.zip https://epics.anl.gov/download/tools/make-4.1-win64.zip
cd \tools
"C:\Program Files\7-Zip\7z" e make-4.1.zip
diff --git a/configure/os/CONFIG.Common.vxWorksCommon b/configure/os/CONFIG.Common.vxWorksCommon
index e7be9fae0..50f626959 100644
--- a/configure/os/CONFIG.Common.vxWorksCommon
+++ b/configure/os/CONFIG.Common.vxWorksCommon
@@ -170,6 +170,10 @@ COMPILE.ctdt = $(CC) -c $(CPPFLAGS) $(CFLAGS_ctdt) $(INCLUDES) $(SOURCE_FLAG)
VXCPPFLAGS = $(filter-out $(OP_SYS_INCLUDE_CPPFLAGS),$(CPPFLAGS))
PREPROCESS.cpp = $(CPP) $(VXCPPFLAGS) $(INCLUDES) $< > $@
+#--------------------------------------------------
+# Use LEDLIB for command-line editing
+COMMANDLINE_LIBRARY = LEDLIB
+
#--------------------------------------------------
# Allow site overrides
-include $(CONFIG)/os/CONFIG_SITE.Common.vxWorksCommon
diff --git a/documentation/README.html b/documentation/README.html
index 8917fa2e7..868043718 100644
--- a/documentation/README.html
+++ b/documentation/README.html
@@ -98,7 +98,7 @@
base/configure/os/CONFIG_SITE.Common.vxWorksCommon file or in one of its
target-specific overrides.
-Consult the vxWorks
+Consult the vxWorks
6.x EPICS web pages and the vxWorks documentation for information
about configuring your vxWorks operating system for use with EPICS.
@@ -128,7 +128,7 @@
EPICS documentation is available through the
- EPICS website at Argonne.
+ EPICS website at Argonne.
Release specific documentation can also be found in the base/documentation
directory of the distribution.
diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html
index 3256e72a3..54968e7bd 100644
--- a/documentation/RELEASE_NOTES.html
+++ b/documentation/RELEASE_NOTES.html
@@ -53,6 +53,61 @@ than one should be ignored).
+Restore use of ledlib for VxWorks command editing
+
+The epicsReadline refactoring work described below unfortunately disabled the
+VxWorks implementation of the osdReadline.c API that uses ledlib for command
+editing and history. This functionality has now been restored, see Launchpad
+bug #1741578.
+
+Constant link types
+
+Constant links can now hold 64-bit integer values, either as scalars or
+arrays. Only base 10 is supported by the JSON parser though, the JSON standard
+doesn't allow for hexadecimal numbers.
+
+Upgraded the YAJL JSON Library
+
+The third-party YAJL library that has been included in libCom for several
+years has been upgraded to version 2.1.0 and several bugs fixed. This has an
+updated API, requiring any code that uses it to parse its own JSON files to be
+modified to match. The changes are mainly that it uses size_t instead
+unsigned int for string lengths, but it also uses long long
+instead of long for JSON integer values, which was the main motivation
+for the upgrade.
+
+The self-tests that YAJL comes with have been imported and are now run as an
+EPICS Unit Test program, and the JSON syntax accepted by the parser was extended
+to permit trailing commas in both arrays and maps. The difference between the
+old and new YAJL APIs can be detected at compile time by looking for the macro
+EPICS_YAJL_VERSION which is defined in the yajl_common.h header file
+along with a brief description of the API changes.
+
+Timestamp support for the calc link type
+
+A new optional parameter can be given when specifying a calc JSON link. The
+time parameter is a string containing a single letter A..L
+that selects one of the input links to be used for the timestamp of calculation
+if requested. The timestamp will be fetched atomically with the value from the
+chosen input link (providing that input link type supports the readLocked()
+method).
+
+Silence errors from puts to constant link types
+
+A soft channel output record with the OUT link unset uses the CONSTANT link
+type. The new link type code was causing some soft channel device supports to
+return an error status from the write method of that link type, which would
+cause a ca_put() operation to such a record to generate an exception. This has
+been silenced by giving the constant link types a dummy putValue method. A new
+test program has been added to prevent regressions of this behaviour.
+
+RSRV expanding large buffer causes crash
+
+In the 3.16.1 release a crash can occur in the IOC's RSRV server when a large
+array is made even larger; the previous array buffer was not being released
+correctly. See Launchpad
+bug
+#1706703.
Changes made between 3.16.0.1 and 3.16.1
diff --git a/src/ca/client/perl/CA.pm b/src/ca/client/perl/CA.pm
index 22944172a..d79cdd33e 100644
--- a/src/ca/client/perl/CA.pm
+++ b/src/ca/client/perl/CA.pm
@@ -652,7 +652,7 @@ not follow this pattern, but are still printable strings.
=item [1] R3.15 Channel Access Reference Manual by Jeffrey O. Hill
-L
+L
=back
diff --git a/src/ioc/db/test/callbackParallelTest.c b/src/ioc/db/test/callbackParallelTest.c
index 2ccc44375..f8d0c3981 100644
--- a/src/ioc/db/test/callbackParallelTest.c
+++ b/src/ioc/db/test/callbackParallelTest.c
@@ -34,6 +34,8 @@
*
* Two time intervals are measured. The time to queue and run each of
* the immediate callbacks, and the actual delay of the delayed callback.
+ *
+ * Slow callbacks no longer fail the test, they just emit a diagnostic.
*/
#define NCALLBACKS 169
@@ -108,7 +110,7 @@ MAIN(callbackParallelTest)
for (j = 0; j < 5; j++)
setupError[i][j] = timeError[i][j] = defaultError[j];
- testPlan(4);
+ testPlan(2);
testDiag("Starting %d parallel callback threads", noCpus);
@@ -165,7 +167,8 @@ MAIN(callbackParallelTest)
}
}
testOk(faults == 0, "%d faults during callback setup", faults);
- testOk(slowups <= 1, "%d slowups during callback setup", slowups);
+ if (slowups)
+ testDiag("%d slowups during callback setup", slowups);
slowups = 0;
for (i = 0; i < NCALLBACKS ; i++) {
@@ -182,7 +185,8 @@ MAIN(callbackParallelTest)
}
updateStats(timeError[i%NUM_CALLBACK_PRIORITIES], error);
}
- testOk(slowups < 5, "%d slowups during callbacks", slowups);
+ if (slowups)
+ testDiag("%d slowups during callback setup", slowups);
testDiag("Setup time statistics");
printStats(setupError[0], "LOW");
diff --git a/src/ioc/db/test/callbackTest.c b/src/ioc/db/test/callbackTest.c
index 7032a7cd1..3ccc2c2f3 100644
--- a/src/ioc/db/test/callbackTest.c
+++ b/src/ioc/db/test/callbackTest.c
@@ -34,6 +34,8 @@
*
* Two time intervals are measured. The time to queue and run each of
* the immediate callbacks, and the actual delay of the delayed callback.
+ *
+ * Slow callbacks no longer fail the test, they just emit a diagnostic.
*/
#define NCALLBACKS 169
@@ -108,7 +110,7 @@ MAIN(callbackTest)
for (j = 0; j < 5; j++)
setupError[i][j] = timeError[i][j] = defaultError[j];
- testPlan(4);
+ testPlan(2);
callbackInit();
epicsThreadSleep(1.0);
@@ -162,7 +164,8 @@ MAIN(callbackTest)
}
}
testOk(faults == 0, "%d faults during callback setup", faults);
- testOk(slowups <= 1, "%d slowups during callback setup", slowups);
+ if (slowups)
+ testDiag("%d slowups during callback setup", slowups);
slowups = 0;
for (i = 0; i < NCALLBACKS ; i++) {
@@ -179,7 +182,8 @@ MAIN(callbackTest)
}
updateStats(timeError[i%NUM_CALLBACK_PRIORITIES], error);
}
- testOk(slowups < 5, "%d slowups during callbacks", slowups);
+ if (slowups)
+ testDiag("%d slowups during callback setup", slowups);
testDiag("Setup time statistics");
printStats(setupError[0], "LOW");
diff --git a/src/libCom/osi/epicsReadline.c b/src/libCom/osi/epicsReadline.c
index 936cbce99..0caa50fc2 100644
--- a/src/libCom/osi/epicsReadline.c
+++ b/src/libCom/osi/epicsReadline.c
@@ -1,11 +1,11 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Saskatchewan
-* Copyright (c) 2014 UChicago Argonne LLC, as Operator of Argonne
+* Copyright (c) 2015 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.
\*************************************************************************/
-/* Author: Eric Norum Date: 12DEC2001 */
+/* Author: Eric Norum */
#include
#include
@@ -15,8 +15,15 @@
#include "envDefs.h"
#include "epicsReadline.h"
+/* Basic command-line input, no editing or history: */
#define EPICS_COMMANDLINE_LIBRARY_EPICS 0
+
+/* OS-specific command-line editing and/or history: */
#define EPICS_COMMANDLINE_LIBRARY_LIBTECLA 1
+#define EPICS_COMMANDLINE_LIBRARY_LEDLIB 1
+#define EPICS_COMMANDLINE_LIBRARY_OTHER 1
+
+/* GNU readline, or Apple's libedit wrapper: */
#define EPICS_COMMANDLINE_LIBRARY_READLINE 2
#define EPICS_COMMANDLINE_LIBRARY_READLINE_CURSES 2
#define EPICS_COMMANDLINE_LIBRARY_READLINE_NCURSES 2
@@ -38,18 +45,17 @@ static void osdReadlineEnd(struct readlineContext *);
#if EPICS_COMMANDLINE_LIBRARY == EPICS_COMMANDLINE_LIBRARY_EPICS
-static void osdReadlineBegin(struct readlineContext * c) {}
-static char * osdReadline(const char *prompt, struct readlineContext * c) { return NULL; }
-static void osdReadlineEnd(struct readlineContext * c) {}
+static void osdReadlineBegin(struct readlineContext *rc) {}
+static char * osdReadline(const char *prompt, struct readlineContext *rc)
+{
+ return NULL;
+}
+static void osdReadlineEnd(struct readlineContext *rc) {}
+#elif EPICS_COMMANDLINE_LIBRARY == EPICS_COMMANDLINE_LIBRARY_READLINE
+# include "gnuReadline.c"
#else
-
-# if EPICS_COMMANDLINE_LIBRARY == EPICS_COMMANDLINE_LIBRARY_READLINE
-# include "gnuReadline.c"
-# else
-# include "osdReadline.c"
-# endif
-
+# include "osdReadline.c"
#endif
/*
@@ -58,15 +64,15 @@ static void osdReadlineEnd(struct readlineContext * c) {}
void * epicsShareAPI
epicsReadlineBegin(FILE *in)
{
- struct readlineContext *readlineContext = calloc(1, sizeof(*readlineContext));
+ struct readlineContext *rc = calloc(1, sizeof(*rc));
- if (readlineContext) {
- readlineContext->in = in;
- readlineContext->line = NULL;
+ if (rc) {
+ rc->in = in;
+ rc->line = NULL;
if (!envGetConfigParamPtr(&IOCSH_HISTEDIT_DISABLE))
- osdReadlineBegin(readlineContext);
+ osdReadlineBegin(rc);
}
- return readlineContext;
+ return rc;
}
/*
@@ -75,19 +81,19 @@ epicsReadlineBegin(FILE *in)
char * epicsShareAPI
epicsReadline (const char *prompt, void *context)
{
- struct readlineContext *readlineContext = context;
+ struct readlineContext *rc = context;
FILE *in;
char *line;
int c; /* char is unsigned on some archs, EOF is -ve */
int linelen = 0;
int linesize = 50;
- if (readlineContext->osd)
- return osdReadline(prompt, readlineContext);
+ if (rc->osd)
+ return osdReadline(prompt, rc);
- free(readlineContext->line);
- readlineContext->line = NULL;
- if ((in = readlineContext->in) == NULL) {
+ free(rc->line);
+ rc->line = NULL;
+ if ((in = rc->in) == NULL) {
in = stdin;
if (prompt) {
fputs(prompt, stdout);
@@ -125,7 +131,7 @@ epicsReadline (const char *prompt, void *context)
line[linelen++] = c;
}
line[linelen] = '\0';
- readlineContext->line = line;
+ rc->line = line;
return line;
}
@@ -136,13 +142,13 @@ void epicsShareAPI
epicsReadlineEnd (void *context)
{
if (context) {
- struct readlineContext *readlineContext = context;
+ struct readlineContext *rc = context;
- if (readlineContext->osd)
- osdReadlineEnd(readlineContext);
- else
- free(readlineContext->line);
- free(readlineContext);
+ if (rc->osd)
+ osdReadlineEnd(rc);
+ else
+ free(rc->line);
+ free(rc);
}
}
diff --git a/src/libCom/osi/os/vxWorks/osdReadline.c b/src/libCom/osi/os/vxWorks/osdReadline.c
index 9195b6b72..dee24fd64 100644
--- a/src/libCom/osi/os/vxWorks/osdReadline.c
+++ b/src/libCom/osi/os/vxWorks/osdReadline.c
@@ -33,7 +33,7 @@ struct osdContext {
static void
osdReadlineBegin(struct readlineContext *context)
{
- struct osdContext osd = malloc(sizeof *osd);
+ struct osdContext *osd = malloc(sizeof *osd);
if (osd != NULL) {
osd->ledId = (LED_ID) ERROR;
diff --git a/src/std/rec/test/softTest.c b/src/std/rec/test/softTest.c
index b81e6bfda..b29c955f9 100644
--- a/src/std/rec/test/softTest.c
+++ b/src/std/rec/test/softTest.c
@@ -11,6 +11,7 @@
#include "dbStaticLib.h"
#include "dbTest.h"
#include "dbUnitTest.h"
+#include "epicsThread.h"
#include "errlog.h"
#include "registryFunction.h"
#include "subRecord.h"
@@ -39,10 +40,10 @@ void doProcess(const char *rec)
testdbPutFieldOk(proc, DBR_CHAR, 1);
}
-/* Group 0 are all soft-channel input records with INP being a DB link
+/* Group 0 are soft-channel input records with INP being a DB or CA link
* to the PV 'source'. Their VAL fields all start out with the default
* value for the type, i.e. 0 or an empty string. Triggering record
- * processing should read the integer value from the 'source' PV.
+ * processing reads the value from the 'source' PV.
*/
static
@@ -50,14 +51,22 @@ void testGroup0(void)
{
const char ** rec;
const char * records[] = {
- "ai0", "bi0", "di0", "ii0", "li0", "lsi0", "mi0", "si0", NULL
+ "ai0", "bi0", "di0", "ii0", "li0", "lsi0", "mi0", "si0",
+ "ai0c", "bi0c", "di0c", "ii0c", "li0c", "lsi0c", "mi0c", "si0c",
+ NULL
};
testDiag("============ Starting %s ============", EPICS_FUNCTION);
testdbPutFieldOk("source", DBR_LONG, 1);
+ /* The above put sends CA monitors to all of the CA links, but
+ * doesn't trigger record processing (the links are not CP/CPP).
+ * How could we wait until all of those monitors have arrived,
+ * instead of just waiting for an arbitrary time period?
+ */
+ epicsThreadSleep(1.0); /* FIXME: Wait here? */
for (rec = records; *rec; rec++) {
- if (strcmp(*rec, "lsi0") != 0)
+ if (strncmp(*rec, "lsi0", 4) != 0)
testdbGetFieldEqual(*rec, DBR_LONG, 0);
checkDtyp(*rec);
doProcess(*rec);
@@ -65,6 +74,7 @@ void testGroup0(void)
}
testdbPutFieldOk("source", DBR_LONG, 0);
+ epicsThreadSleep(1.0); /* FIXME: Wait here as above */
for (rec = records; *rec; rec++) {
doProcess(*rec);
testdbGetFieldEqual(*rec, DBR_LONG, 0);
@@ -129,6 +139,7 @@ static
long destSubr(subRecord *prec)
{
dest = prec->val;
+ prec->val = -1;
return 0;
}
@@ -138,20 +149,25 @@ void checkOutput(const char *rec, int value)
testDiag("Checking record '%s'", rec);
testdbPutFieldOk(rec, DBR_LONG, value);
-
+ /* Even with a local CA link, the dest record gets processed in
+ * the context of this thread (i.e. immediately). TPRO confirms.
+ */
testOk(dest == value, "value %d output -> %d", value, dest);
}
-/* Group 3 are all soft-channel output records with OUT being a DB link
- * to the PV 'dest' with PP. Putting a value to the record writes that
- * value to 'dest' and processes it.
+/* Group 3 are all soft-channel output records with OUT being a DB or
+ * local CA link to the subRecord 'dest'; DB links have the PP flag,
+ * for CA links the VAL field is marked PP. Putting a value to the
+ * output record writes that value to 'dest'.
*/
static
void testGroup3(void)
{
const char ** rec;
const char * records[] = {
- "ao0", "bo0", "io0", "lo0", "lso0", "mo0", "so0", NULL,
+ "ao3", "bo3", "io3", "lo3", "lso3", "mo3", "so3",
+ "ao3c", "bo3c", "io3c", "lo3c", "lso3c", "mo3c", "so3c",
+ NULL,
};
testDiag("============ Starting %s ============", EPICS_FUNCTION);
@@ -160,13 +176,16 @@ void testGroup3(void)
checkOutput(*rec, 1);
checkDtyp(*rec);
}
- checkOutput("do0.B0", 1);
- checkDtyp("do0");
+ checkOutput("do3.B0", 1);
+ checkDtyp("do3");
+ checkOutput("do3c.B0", 1);
+ checkDtyp("do3c");
for (rec = records; *rec; rec++) {
checkOutput(*rec, 0);
}
- checkOutput("do0.B0", 0);
+ checkOutput("do3.B0", 0);
+ checkOutput("do3c.B0", 0);
}
/* Group 4 are all soft-channel output records with OUT being empty
@@ -177,7 +196,7 @@ void testGroup4(void)
{
const char ** rec;
const char * records[] = {
- "ao1", "bo1", "do1.B0", "io1", "lo1", "lso1", "mo1", "so1", NULL,
+ "ao4", "bo4", "do4.B0", "io4", "lo4", "lso4", "mo4", "so4", NULL,
};
testDiag("============ Starting %s ============", EPICS_FUNCTION);
@@ -189,9 +208,10 @@ void testGroup4(void)
void recTestIoc_registerRecordDeviceDriver(struct dbBase *);
+
MAIN(softTest)
{
- testPlan(163);
+ testPlan(266);
testdbPrepare();
testdbReadDatabase("recTestIoc.dbd", NULL, NULL);
diff --git a/src/std/rec/test/softTest.db b/src/std/rec/test/softTest.db
index 8384fe946..06dbf2b7e 100644
--- a/src/std/rec/test/softTest.db
+++ b/src/std/rec/test/softTest.db
@@ -59,6 +59,60 @@ record(stringin, "si0") {
field(INP, "source")
}
+record(ai, "ai0c") {
+ field(DTYP, "Soft Channel")
+ field(INP, "source CA")
+}
+record(bi, "bi0c") {
+ field(DTYP, "Soft Channel")
+ field(INP, "source CA")
+ field(ZNAM, "Zero")
+ field(ONAM, "One")
+}
+record(int64in, "ii0c") {
+ field(DTYP, "Soft Channel")
+ field(INP, "source CA")
+}
+record(longin, "li0c") {
+ field(DTYP, "Soft Channel")
+ field(INP, "source CA")
+}
+record(mbbiDirect, "di0c") {
+ field(DTYP, "Soft Channel")
+ field(NOBT, 4)
+ field(INP, "source CA")
+}
+record(mbbi, "mi0c") {
+ field(DTYP, "Soft Channel")
+ field(NOBT, 4)
+ field(INP, "source CA")
+ field(ZRST, "Zero")
+ field(ONST, "One")
+ field(TWST, "Two")
+ field(THST, "Three")
+ field(FRST, "Four")
+ field(FVST, "Five")
+ field(SXST, "Six")
+ field(SVST, "Seven")
+ field(EIST, "Eight")
+ field(NIST, "Nine")
+ field(TEST, "Ten")
+ field(ELST, "Eleven")
+ field(TWST, "Twelve")
+ field(TTST, "Thirteen")
+ field(FTST, "Fourteen")
+ field(FFST, "Fifteen")
+}
+record(lsi, "lsi0c") {
+ field(DTYP, "Soft Channel")
+ field(SIZV, 40)
+ field(INP, "source CA")
+}
+record(stringin, "si0c") {
+ field(DTYP, "Soft Channel")
+ field(INP, "source CA")
+}
+
# Group 1 are all soft-channel input records with INP being a non-zero
# "const" JSON-link, 9 for most records, 1 for the binary. Their VAL
@@ -171,38 +225,39 @@ record(mbbi, "mi2") {
}
-# Group 3 are all soft-channel output records with OUT being a DB link
-# to the PV 'dest' with PP. Putting a value to the record writes that
-# value to 'dest' and processes it.
+# Group 3 are all soft-channel output records with OUT being a DB or
+# CA link to the PV 'dest' with PP. Putting a value to the record
+# under test writes the value to 'dest' and processes it.
record(sub, "dest") {
field(SNAM, "destSubr")
+ field(VAL, -1)
}
-record(ao, "ao0") {
+record(ao, "ao3") {
field(DTYP, "Soft Channel")
field(OUT, "dest PP")
}
-record(bo, "bo0") {
+record(bo, "bo3") {
field(DTYP, "Soft Channel")
field(OUT, "dest PP")
field(ZNAM, "Zero")
field(ONAM, "One")
}
-record(int64out, "io0") {
+record(int64out, "io3") {
field(DTYP, "Soft Channel")
field(OUT, "dest PP")
}
-record(longout, "lo0") {
+record(longout, "lo3") {
field(DTYP, "Soft Channel")
field(OUT, "dest PP")
}
-record(mbboDirect, "do0") {
+record(mbboDirect, "do3") {
field(DTYP, "Soft Channel")
field(NOBT, 4)
field(OUT, "dest PP")
}
-record(mbbo, "mo0") {
+record(mbbo, "mo3") {
field(DTYP, "Soft Channel")
field(NOBT, 4)
field(OUT, "dest PP")
@@ -223,39 +278,93 @@ record(mbbo, "mo0") {
field(FTST, "Fourteen")
field(FFST, "Fifteen")
}
-record(lso, "lso0") {
+record(lso, "lso3") {
field(DTYP, "Soft Channel")
field(OUT, "dest PP")
field(SIZV, 40)
}
-record(stringout, "so0") {
+record(stringout, "so3") {
field(DTYP, "Soft Channel")
field(OUT, "dest PP")
}
+record(ao, "ao3c") {
+ field(DTYP, "Soft Channel")
+ field(OUT, "dest CA")
+}
+record(bo, "bo3c") {
+ field(DTYP, "Soft Channel")
+ field(OUT, "dest CA")
+ field(ZNAM, "Zero")
+ field(ONAM, "One")
+}
+record(int64out, "io3c") {
+ field(DTYP, "Soft Channel")
+ field(OUT, "dest CA")
+}
+record(longout, "lo3c") {
+ field(DTYP, "Soft Channel")
+ field(OUT, "dest CA")
+}
+record(mbboDirect, "do3c") {
+ field(DTYP, "Soft Channel")
+ field(NOBT, 4)
+ field(OUT, "dest CA")
+}
+record(mbbo, "mo3c") {
+ field(DTYP, "Soft Channel")
+ field(NOBT, 4)
+ field(OUT, "dest CA")
+ field(ZRST, "Zero")
+ field(ONST, "One")
+ field(TWST, "Two")
+ field(THST, "Three")
+ field(FRST, "Four")
+ field(FVST, "Five")
+ field(SXST, "Six")
+ field(SVST, "Seven")
+ field(EIST, "Eight")
+ field(NIST, "Nine")
+ field(TEST, "Ten")
+ field(ELST, "Eleven")
+ field(TWST, "Twelve")
+ field(TTST, "Thirteen")
+ field(FTST, "Fourteen")
+ field(FFST, "Fifteen")
+}
+record(lso, "lso3c") {
+ field(DTYP, "Soft Channel")
+ field(OUT, "dest CA")
+ field(SIZV, 40)
+}
+record(stringout, "so3c") {
+ field(DTYP, "Soft Channel")
+ field(OUT, "dest CA")
+}
+
# Group 4 are all soft-channel output records with OUT being empty
# (i.e. a CONSTANT link). Putting a value to the record must succeed.
-record(ao, "ao1") {
+record(ao, "ao4") {
field(DTYP, "Soft Channel")
}
-record(bo, "bo1") {
+record(bo, "bo4") {
field(DTYP, "Soft Channel")
field(ZNAM, "Zero")
field(ONAM, "One")
}
-record(int64out, "io1") {
+record(int64out, "io4") {
field(DTYP, "Soft Channel")
}
-record(longout, "lo1") {
+record(longout, "lo4") {
field(DTYP, "Soft Channel")
}
-record(mbboDirect, "do1") {
+record(mbboDirect, "do4") {
field(DTYP, "Soft Channel")
field(NOBT, 4)
}
-record(mbbo, "mo1") {
+record(mbbo, "mo4") {
field(DTYP, "Soft Channel")
field(NOBT, 4)
field(ZRST, "Zero")
@@ -275,10 +384,10 @@ record(mbbo, "mo1") {
field(FTST, "Fourteen")
field(FFST, "Fifteen")
}
-record(lso, "lso1") {
+record(lso, "lso4") {
field(DTYP, "Soft Channel")
field(SIZV, 40)
}
-record(stringout, "so1") {
+record(stringout, "so4") {
field(DTYP, "Soft Channel")
}
diff --git a/src/tools/genVersionHeader.pl b/src/tools/genVersionHeader.pl
index 5851ea831..c61f14c98 100644
--- a/src/tools/genVersionHeader.pl
+++ b/src/tools/genVersionHeader.pl
@@ -18,8 +18,8 @@ use POSIX qw(strftime);
use strict;
-# RFC 8601 date+time w/ zone (eg "2014-08-29T09:42:47-0700")
-my $tfmt = '%Y-%m-%dT%H:%M:%S';
+# RFC 8601 date+time w/ zone (eg "2014-08-29T09:42-0700")
+my $tfmt = '%Y-%m-%dT%H:%M';
$tfmt .= '%z' unless $^O eq 'MSWin32'; # %z returns zone name on Windows
my $now = strftime($tfmt, localtime);