Date: Tue, 24 Oct 2017 11:46:09 -0500
Subject: [PATCH 032/147] add release note
---
documentation/RELEASE_NOTES.html | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html
index a4a09c7da..e172f12cd 100644
--- a/documentation/RELEASE_NOTES.html
+++ b/documentation/RELEASE_NOTES.html
@@ -17,6 +17,16 @@
-->
+Typed Device and Driver Support callbacks
+
+Two new structures (typed_dset and typed_drvet) are added
+for use instead of dset and drvet.
+The existing structures are not changed.
+See comments in devSup.h for usage information.
+
+A helper function DBLINK* dbGetDevLink(dbCommon*) is added to fetch
+a pointer to the INP or OUT field of a record.
+
Restore use of ledlib for VxWorks command editing
The epicsReadline refactoring work described below unfortunately disabled the
From 1893cb4f54264d137e7a6eb0c3a8c2193f9d2f89 Mon Sep 17 00:00:00 2001
From: Michael Davidsaver
Date: Mon, 14 May 2018 19:51:27 -0700
Subject: [PATCH 033/147] add USE_TYPED_DRVET and USE_TYPED_DSET options
---
src/ioc/dbStatic/devSup.h | 38 ++++++++++++++++++++++----------------
src/ioc/dbStatic/drvSup.h | 28 +++++++++++++++-------------
2 files changed, 37 insertions(+), 29 deletions(-)
diff --git a/src/ioc/dbStatic/devSup.h b/src/ioc/dbStatic/devSup.h
index 63ffb36ce..7520b7a71 100644
--- a/src/ioc/dbStatic/devSup.h
+++ b/src/ioc/dbStatic/devSup.h
@@ -24,22 +24,6 @@ struct devSup;
struct ioscan_head; /* aka IOSCANPVT */
struct link; /* aka DBLINK */
-#ifdef __cplusplus
-extern "C" {
- typedef long (*DEVSUPFUN)(void *); /* ptr to device support function*/
-#else
- typedef long (*DEVSUPFUN)(); /* ptr to device support function*/
-#endif
-
-typedef struct dset { /* device support entry table */
- long number; /*number of support routines*/
- DEVSUPFUN report; /*print report*/
- DEVSUPFUN init; /*init support layer*/
- DEVSUPFUN init_record; /*init device for particular record*/
- DEVSUPFUN get_ioint_info; /* get io interrupt information*/
- /*other functions are record dependent*/
-} dset;
-
/** Type safe alternative to 'struct dset'
*
* Recommended usage
@@ -113,6 +97,28 @@ typedef struct dsxt { /* device support extension table */
/* Recordtypes are *not* allowed to extend this table */
} dsxt;
+#ifdef __cplusplus
+extern "C" {
+ typedef long (*DEVSUPFUN)(void *); /* ptr to device support function*/
+#else
+ typedef long (*DEVSUPFUN)(); /* ptr to device support function*/
+#endif
+
+#ifndef USE_TYPED_DSET
+
+typedef struct dset { /* device support entry table */
+ long number; /*number of support routines*/
+ DEVSUPFUN report; /*print report*/
+ DEVSUPFUN init; /*init support layer*/
+ DEVSUPFUN init_record; /*init device for particular record*/
+ DEVSUPFUN get_ioint_info; /* get io interrupt information*/
+ /*other functions are record dependent*/
+} dset;
+
+#else
+typedef typed_dset dset;
+#endif /* USE_TYPED_DSET */
+
/** Fetch INP or OUT link (or NULL if record type has neither).
*
* Recommended for use in device support init_record()
diff --git a/src/ioc/dbStatic/drvSup.h b/src/ioc/dbStatic/drvSup.h
index 59a566938..943105f31 100644
--- a/src/ioc/dbStatic/drvSup.h
+++ b/src/ioc/dbStatic/drvSup.h
@@ -18,7 +18,19 @@
#include "errMdef.h"
-typedef long (*DRVSUPFUN) (); /* ptr to driver support function*/
+typedef struct typed_drvet {
+ /** Number of function pointers which follow. Must be >=2 */
+ long number;
+ /** Called from dbior() */
+ long (*report)(int lvl);
+ /** Called during iocInit() */
+ long (*init)(void);
+ /*other functions are device dependent*/
+} typed_drvet;
+
+typedef long (*DRVSUPFUN) (); /* ptr to driver support function for use with plain/untyped drvet */
+
+#ifndef USE_TYPED_DRVET
typedef struct drvet { /* driver entry table */
long number; /*number of support routines*/
@@ -28,19 +40,9 @@ typedef struct drvet { /* driver entry table */
}drvet;
#define DRVETNUMBER ( (sizeof(struct drvet) -sizeof(long))/sizeof(DRVSUPFUN) )
-typedef struct typed_drvet {
- /** Number of function pointers which follow. Must be >=2 */
- long number;
- /** Called from dbior() */
- long (*report)(int lvl);
- /** Called during iocInit() */
-#ifdef __cplusplus
- long (*init)();
#else
- long (*init)(void);
-#endif
- /*other functions are device dependent*/
-} typed_drvet;
+typedef typed_drvet drvet;
+#endif /* USE_TYPED_DRVET */
#define S_drv_noDrvSup (M_drvSup| 1) /*SDR_DRVSUP: Driver support missing*/
#define S_drv_noDrvet (M_drvSup| 3) /*Missing driver support entry table*/
From 3b89515664bb140f6f05089da98aabaa9d4dad1b Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Mon, 14 May 2018 23:43:13 -0500
Subject: [PATCH 034/147] dbJLink: Pass the correct dbfType to child links
API change for link types that support child links, they must now
indicate whether a child link is an input, output or forward link
by the return value from their parse_start_map() method. The original
jlif_key_child_link enumeration has been replaced by 3 new values:
jlif_key_child_inlink, jlif_key_child_outlink and jlif_key_child_fwdlink
Previously we were passing the dbfType of the record link field to all
child links within it, which was wrong.
---
src/ioc/db/dbJLink.c | 68 +++++++++++++++++++++++++-----------------
src/ioc/db/dbJLink.h | 7 +++--
src/std/link/lnkCalc.c | 8 +++--
3 files changed, 50 insertions(+), 33 deletions(-)
diff --git a/src/ioc/db/dbJLink.c b/src/ioc/db/dbJLink.c
index 10a4e62d2..a5fd2bed6 100644
--- a/src/ioc/db/dbJLink.c
+++ b/src/ioc/db/dbJLink.c
@@ -37,7 +37,6 @@ typedef struct parseContext {
jlink *product;
short dbfType;
short jsonDepth;
- unsigned key_is_link:1;
} parseContext;
#define CALL_OR_STOP(routine) !(routine) ? jlif_stop : (routine)
@@ -47,8 +46,8 @@ static int dbjl_return(parseContext *parser, jlif_result result) {
IFDEBUG(10) {
printf("dbjl_return(%s@%p, %d)\t", pjlink ? pjlink->pif->name : "", pjlink, result);
- printf(" jsonDepth=%d, parseDepth=%d, key_is_link=%d\n",
- parser->jsonDepth, pjlink ? pjlink->parseDepth : 0, parser->key_is_link);
+ printf(" jsonDepth=%d, parseDepth=%d, dbfType=%d\n",
+ parser->jsonDepth, pjlink ? pjlink->parseDepth : 0, parser->dbfType);
}
if (result == jlif_stop && pjlink) {
@@ -73,8 +72,8 @@ static int dbjl_value(parseContext *parser, jlif_result result) {
IFDEBUG(10) {
printf("dbjl_value(%s@%p, %d)\t", pjlink ? pjlink->pif->name : "", pjlink, result);
- printf(" jsonDepth=%d, parseDepth=%d, key_is_link=%d\n",
- parser->jsonDepth, pjlink ? pjlink->parseDepth : 0, parser->key_is_link);
+ printf(" jsonDepth=%d, parseDepth=%d, dbfType=%d\n",
+ parser->jsonDepth, pjlink ? pjlink->parseDepth : 0, parser->dbfType);
}
if (result == jlif_stop || pjlink->parseDepth > 0)
@@ -163,29 +162,45 @@ static int dbjl_start_map(void *ctx) {
if (!pjlink) {
IFDEBUG(10) {
printf("dbjl_start_map(NULL)\t");
- printf(" jsonDepth=%d, parseDepth=00, key_is_link=%d\n",
- parser->jsonDepth, parser->key_is_link);
+ printf(" jsonDepth=%d, parseDepth=00, dbfType=%d\n",
+ parser->jsonDepth, parser->dbfType);
}
assert(parser->jsonDepth == 0);
parser->jsonDepth++;
- parser->key_is_link = 1;
return jlif_continue; /* Opening '{' */
}
IFDEBUG(10) {
printf("dbjl_start_map(%s@%p)\t", pjlink ? pjlink->pif->name : "", pjlink);
- printf(" jsonDepth=%d, parseDepth=%d, key_is_link=%d\n",
- parser->jsonDepth, pjlink ? pjlink->parseDepth : 0, parser->key_is_link);
+ printf(" jsonDepth=%d, parseDepth=%d, dbfType=%d\n",
+ parser->jsonDepth, pjlink ? pjlink->parseDepth : 0, parser->dbfType);
}
pjlink->parseDepth++;
parser->jsonDepth++;
result = CALL_OR_STOP(pjlink->pif->parse_start_map)(pjlink);
- if (result == jlif_key_child_link) {
- parser->key_is_link = 1;
+ switch (result) {
+ case jlif_key_child_inlink:
+ parser->dbfType = DBF_INLINK;
result = jlif_continue;
+ break;
+ case jlif_key_child_outlink:
+ parser->dbfType = DBF_OUTLINK;
+ result = jlif_continue;
+ break;
+ case jlif_key_child_fwdlink:
+ parser->dbfType = DBF_FWDLINK;
+ result = jlif_continue;
+ break;
+ case jlif_continue:
+ break;
+ default:
+ errlogPrintf("dbJLinkInit: Bad return %d from '%s'::parse_start_map()\n",
+ result, pjlink->pif->name);
+ result = jlif_stop;
+ break;
}
IFDEBUG(10)
@@ -201,7 +216,7 @@ static int dbjl_map_key(void *ctx, const unsigned char *key, size_t len) {
linkSup *linkSup;
jlif *pjlif;
- if (!parser->key_is_link) {
+ if (parser->dbfType == 0) {
if (!pjlink) {
errlogPrintf("dbJLinkInit: Illegal second link key '%.*s'\n",
(int) len, key);
@@ -211,8 +226,8 @@ static int dbjl_map_key(void *ctx, const unsigned char *key, size_t len) {
IFDEBUG(10) {
printf("dbjl_map_key(%s@%p, \"%.*s\")\t",
pjlink->pif->name, pjlink, (int) len, key);
- printf(" jsonDepth=%d, parseDepth=%d, key_is_link=%d\n",
- parser->jsonDepth, pjlink ? pjlink->parseDepth : 0, parser->key_is_link);
+ printf(" jsonDepth=%d, parseDepth=%d, dbfType=%d\n",
+ parser->jsonDepth, pjlink ? pjlink->parseDepth : 0, parser->dbfType);
}
assert(pjlink->parseDepth > 0);
@@ -223,8 +238,8 @@ static int dbjl_map_key(void *ctx, const unsigned char *key, size_t len) {
IFDEBUG(10) {
printf("dbjl_map_key(NULL, \"%.*s\")\t", (int) len, key);
- printf(" jsonDepth=%d, parseDepth=00, key_is_link=%d\n",
- parser->jsonDepth, parser->key_is_link);
+ printf(" jsonDepth=%d, parseDepth=00, dbfType=%d\n",
+ parser->jsonDepth, parser->dbfType);
}
link_name = dbmfStrndup((const char *) key, len);
@@ -264,7 +279,7 @@ static int dbjl_map_key(void *ctx, const unsigned char *key, size_t len) {
pjlink->parent = NULL;
parser->pjlink = pjlink;
- parser->key_is_link = 0;
+ parser->dbfType = 0;
dbmfFree(link_name);
@@ -282,9 +297,9 @@ static int dbjl_end_map(void *ctx) {
IFDEBUG(10) {
printf("dbjl_end_map(%s@%p)\t",
pjlink ? pjlink->pif->name : "NULL", pjlink);
- printf(" jsonDepth=%d, parseDepth=%d, key_is_link=%d\n",
+ printf(" jsonDepth=%d, parseDepth=%d, dbfType=%d\n",
parser->jsonDepth, pjlink ? pjlink->parseDepth : 0,
- parser->key_is_link);
+ parser->dbfType);
}
parser->jsonDepth--;
@@ -306,8 +321,8 @@ static int dbjl_start_array(void *ctx) {
IFDEBUG(10) {
printf("dbjl_start_array(%s@%p)\t", pjlink ? pjlink->pif->name : "", pjlink);
- printf(" jsonDepth=%d, parseDepth=%d, key_is_link=%d\n",
- parser->jsonDepth, pjlink ? pjlink->parseDepth : 0, parser->key_is_link);
+ printf(" jsonDepth=%d, parseDepth=%d, dbfType=%d\n",
+ parser->jsonDepth, pjlink ? pjlink->parseDepth : 0, parser->dbfType);
}
assert(pjlink);
@@ -324,8 +339,8 @@ static int dbjl_end_array(void *ctx) {
IFDEBUG(10) {
printf("dbjl_end_array(%s@%p)\t", pjlink ? pjlink->pif->name : "", pjlink);
- printf(" jsonDepth=%d, parseDepth=%d, key_is_link=%d\n",
- parser->jsonDepth, pjlink ? pjlink->parseDepth : 0, parser->key_is_link);
+ printf(" jsonDepth=%d, parseDepth=%d, dbfType=%d\n",
+ parser->jsonDepth, pjlink ? pjlink->parseDepth : 0, parser->dbfType);
}
assert(pjlink);
@@ -355,15 +370,14 @@ long dbJLinkParse(const char *json, size_t jlen, short dbfType,
parser->product = NULL;
parser->dbfType = dbfType;
parser->jsonDepth = 0;
- parser->key_is_link = 0;
IFDEBUG(10)
printf("dbJLinkInit(\"%.*s\", %d, %p)\n",
(int) jlen, json, dbfType, ppjlink);
IFDEBUG(10)
- printf("dbJLinkInit: jsonDepth=%d, key_is_link=%d\n",
- parser->jsonDepth, parser->key_is_link);
+ printf("dbJLinkInit: jsonDepth=%d, dbfType=%d\n",
+ parser->jsonDepth, parser->dbfType);
yajl_set_default_alloc_funcs(&dbjl_allocs);
yh = yajl_alloc(&dbjl_callbacks, &dbjl_allocs, parser);
diff --git a/src/ioc/db/dbJLink.h b/src/ioc/db/dbJLink.h
index 954b69be5..a94d10ab8 100644
--- a/src/ioc/db/dbJLink.h
+++ b/src/ioc/db/dbJLink.h
@@ -24,7 +24,7 @@ typedef enum {
typedef enum {
jlif_key_stop = jlif_stop,
jlif_key_continue = jlif_continue,
- jlif_key_child_link
+ jlif_key_child_inlink, jlif_key_child_outlink, jlif_key_child_fwdlink
} jlif_key_result;
struct link;
@@ -71,8 +71,9 @@ typedef struct jlif {
/* Optional, parser saw a string value */
jlif_key_result (*parse_start_map)(jlink *);
- /* Optional, parser saw an open-brace '{'. Return jlif_key_child_link
- * to expect a child link next (extra key/value pairs may follow).
+ /* Optional, parser saw an open-brace '{'. Return jlif_key_child_inlink,
+ * jlif_key_child_outlink, or jlif_key_child_fwdlink to expect a child
+ * link next (extra key/value pairs may follow)
*/
jlif_result (*parse_map_key)(jlink *, const char *key, size_t len);
diff --git a/src/std/link/lnkCalc.c b/src/std/link/lnkCalc.c
index de76948a9..987d3bd06 100644
--- a/src/std/link/lnkCalc.c
+++ b/src/std/link/lnkCalc.c
@@ -254,8 +254,10 @@ static jlif_key_result lnkCalc_start_map(jlink *pjlink)
IFDEBUG(10)
printf("lnkCalc_start_map(calc@%p)\n", clink);
- if (clink->pstate == ps_args || clink->pstate == ps_out)
- return jlif_key_child_link;
+ if (clink->pstate == ps_args)
+ return jlif_key_child_inlink;
+ if (clink->pstate == ps_out)
+ return jlif_key_child_outlink;
if (clink->pstate != ps_init) {
errlogPrintf("lnkCalc: Unexpected map\n");
@@ -463,7 +465,7 @@ static void lnkCalc_report(const jlink *pjlink, int level, int indent)
}
}
-long lnkCalc_map_children(jlink *pjlink, jlink_map_fn rtn, void *ctx)
+static long lnkCalc_map_children(jlink *pjlink, jlink_map_fn rtn, void *ctx)
{
calc_link *clink = CONTAINER(pjlink, struct calc_link, jlink);
int i;
From fd30989f63f3afe2e773441725d44a735901a1fc Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Fri, 1 Jun 2018 23:23:54 -0500
Subject: [PATCH 035/147] Add jlif::start_child() method
---
src/ioc/db/dbJLink.c | 21 +++++++++++++--------
src/ioc/db/dbJLink.h | 9 ++++++++-
src/ioc/db/test/jlinkz.c | 3 ++-
src/ioc/db/test/xLink.c | 5 ++---
src/std/link/lnkCalc.c | 2 +-
src/std/link/lnkConst.c | 2 +-
src/std/link/lnkState.c | 2 +-
7 files changed, 28 insertions(+), 16 deletions(-)
diff --git a/src/ioc/db/dbJLink.c b/src/ioc/db/dbJLink.c
index a5fd2bed6..df0c2d822 100644
--- a/src/ioc/db/dbJLink.c
+++ b/src/ioc/db/dbJLink.c
@@ -215,6 +215,7 @@ static int dbjl_map_key(void *ctx, const unsigned char *key, size_t len) {
char *link_name;
linkSup *linkSup;
jlif *pjlif;
+ jlink *child;
if (parser->dbfType == 0) {
if (!pjlink) {
@@ -260,31 +261,35 @@ static int dbjl_map_key(void *ctx, const unsigned char *key, size_t len) {
return dbjl_return(parser, jlif_stop);
}
- pjlink = pjlif->alloc_jlink(parser->dbfType);
- if (!pjlink) {
+ child = pjlif->alloc_jlink(parser->dbfType);
+ if (!child) {
errlogPrintf("dbJLinkInit: Link type '%s' allocation failed. \n",
link_name);
dbmfFree(link_name);
return dbjl_return(parser, jlif_stop);
}
- pjlink->pif = pjlif;
- pjlink->parseDepth = 0;
+ child->pif = pjlif;
+ child->parseDepth = 0;
+ child->debug = 0;
if (parser->pjlink) {
/* We're starting a child link, save its parent */
- pjlink->parent = parser->pjlink;
+ child->parent = pjlink;
+
+ if (pjlink->pif->start_child)
+ pjlink->pif->start_child(pjlink, child);
}
else
- pjlink->parent = NULL;
+ child->parent = NULL;
- parser->pjlink = pjlink;
+ parser->pjlink = child;
parser->dbfType = 0;
dbmfFree(link_name);
IFDEBUG(8)
- printf("dbjl_map_key: New %s@%p\n", pjlink ? pjlink->pif->name : "", pjlink);
+ printf("dbjl_map_key: New %s@%p\n", child ? child->pif->name : "", child);
return jlif_continue;
}
diff --git a/src/ioc/db/dbJLink.h b/src/ioc/db/dbJLink.h
index a94d10ab8..54c793175 100644
--- a/src/ioc/db/dbJLink.h
+++ b/src/ioc/db/dbJLink.h
@@ -90,7 +90,8 @@ typedef struct jlif {
void (*end_child)(jlink *parent, jlink *child);
/* Optional, called with pointer to the new child link after
- * parse_start_map() returned jlif_key_child_link */
+ * the child link has finished parsing successfully
+ */
struct lset* (*get_lset)(const jlink *);
/* Required, return lset for this link instance */
@@ -107,6 +108,12 @@ typedef struct jlif {
* Stop immediately and return status if non-zero.
*/
+ void (*start_child)(jlink *parent, jlink *child);
+ /* Optional, called with pointer to the new child link after
+ * parse_start_map() returned a jlif_key_child_link value and
+ * the child link has been allocated (but not parsed yet)
+ */
+
/* Link types must NOT extend this table with their own routines,
* this space is reserved for extensions to the jlink interface.
*/
diff --git a/src/ioc/db/test/jlinkz.c b/src/ioc/db/test/jlinkz.c
index dd6919ffb..fc98ff3b3 100644
--- a/src/ioc/db/test/jlinkz.c
+++ b/src/ioc/db/test/jlinkz.c
@@ -246,7 +246,8 @@ static jlif jlifZ = {
NULL, /* end child */
&z_lset,
NULL, /* report */
- NULL /* map child */
+ NULL, /* map child */
+ NULL /* start child */
};
epicsExportAddress(jlif, jlifZ);
diff --git a/src/ioc/db/test/xLink.c b/src/ioc/db/test/xLink.c
index 12175f44e..2d7c3c043 100644
--- a/src/ioc/db/test/xLink.c
+++ b/src/ioc/db/test/xLink.c
@@ -2,7 +2,7 @@
* Copyright (c) 2016 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.
+* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* xLink.c */
@@ -82,7 +82,6 @@ static jlif xlinkIf = {
NULL, NULL, NULL,
NULL, NULL,
NULL, xlink_get_lset,
- NULL, NULL
+ NULL, NULL, NULL
};
epicsExportAddress(jlif, xlinkIf);
-
diff --git a/src/std/link/lnkCalc.c b/src/std/link/lnkCalc.c
index 987d3bd06..6b68ac990 100644
--- a/src/std/link/lnkCalc.c
+++ b/src/std/link/lnkCalc.c
@@ -847,6 +847,6 @@ static jlif lnkCalcIf = {
lnkCalc_start_map, lnkCalc_map_key, lnkCalc_end_map,
lnkCalc_start_array, lnkCalc_end_array,
lnkCalc_end_child, lnkCalc_get_lset,
- lnkCalc_report, lnkCalc_map_children
+ lnkCalc_report, lnkCalc_map_children, NULL
};
epicsExportAddress(jlif, lnkCalcIf);
diff --git a/src/std/link/lnkConst.c b/src/std/link/lnkConst.c
index ee93830ff..3b9392cfa 100644
--- a/src/std/link/lnkConst.c
+++ b/src/std/link/lnkConst.c
@@ -631,6 +631,6 @@ static jlif lnkConstIf = {
NULL, NULL, NULL,
lnkConst_start_array, lnkConst_end_array,
NULL, lnkConst_get_lset,
- lnkConst_report, NULL
+ lnkConst_report, NULL, NULL
};
epicsExportAddress(jlif, lnkConstIf);
diff --git a/src/std/link/lnkState.c b/src/std/link/lnkState.c
index 8792a1f64..518a37029 100644
--- a/src/std/link/lnkState.c
+++ b/src/std/link/lnkState.c
@@ -280,6 +280,6 @@ static jlif lnkStateIf = {
NULL, NULL, NULL,
NULL, NULL,
NULL, lnkState_get_lset,
- lnkState_report, NULL
+ lnkState_report, NULL, NULL
};
epicsExportAddress(jlif, lnkStateIf);
From f2ceb3bbbf51ffb84d76021dfa1005381c97301f Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Fri, 1 Jun 2018 23:26:53 -0500
Subject: [PATCH 036/147] dbJLink: Add jlif result enum state name strings
---
src/ioc/db/dbJLink.c | 18 ++++++++++++++++++
src/ioc/db/dbJLink.h | 4 ++++
2 files changed, 22 insertions(+)
diff --git a/src/ioc/db/dbJLink.c b/src/ioc/db/dbJLink.c
index df0c2d822..1c448dd4d 100644
--- a/src/ioc/db/dbJLink.c
+++ b/src/ioc/db/dbJLink.c
@@ -39,6 +39,19 @@ typedef struct parseContext {
short jsonDepth;
} parseContext;
+epicsShareDef const char *jlif_result_name[2] = {
+ "jlif_stop",
+ "jlif_continue",
+};
+
+epicsShareDef const char *jlif_key_result_name[5] = {
+ "jlif_key_stop",
+ "jlif_key_continue",
+ "jlif_key_child_inlink",
+ "jlif_key_child_outlink",
+ "jlif_key_child_fwdlink"
+};
+
#define CALL_OR_STOP(routine) !(routine) ? jlif_stop : (routine)
static int dbjl_return(parseContext *parser, jlif_result result) {
@@ -423,6 +436,11 @@ long dbJLinkParse(const char *json, size_t jlen, short dbfType,
}
yajl_free(yh);
+
+ IFDEBUG(10)
+ printf("dbJLinkInit: returning status=0x%lx\n\n",
+ status);
+
return status;
}
diff --git a/src/ioc/db/dbJLink.h b/src/ioc/db/dbJLink.h
index 54c793175..7080ed7cb 100644
--- a/src/ioc/db/dbJLink.h
+++ b/src/ioc/db/dbJLink.h
@@ -21,12 +21,16 @@ typedef enum {
jlif_continue = 1
} jlif_result;
+epicsShareExtern const char *jlif_result_name[2];
+
typedef enum {
jlif_key_stop = jlif_stop,
jlif_key_continue = jlif_continue,
jlif_key_child_inlink, jlif_key_child_outlink, jlif_key_child_fwdlink
} jlif_key_result;
+epicsShareExtern const char *jlif_key_result_name[5];
+
struct link;
struct lset;
struct jlif;
From 8cdcaf5a875de59f90d6e42d22b1a4ca88242ca4 Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Fri, 1 Jun 2018 23:32:48 -0500
Subject: [PATCH 037/147] dbJLink: Restore the jlink::debug flag, add debug and
trace link types
---
src/ioc/db/dbJLink.h | 1 +
src/std/link/Makefile | 1 +
src/std/link/links.dbd.pod | 36 ++
src/std/link/lnkDebug.c | 1044 ++++++++++++++++++++++++++++++++++++
4 files changed, 1082 insertions(+)
create mode 100644 src/std/link/lnkDebug.c
diff --git a/src/ioc/db/dbJLink.h b/src/ioc/db/dbJLink.h
index 7080ed7cb..bd1a6c8a2 100644
--- a/src/ioc/db/dbJLink.h
+++ b/src/ioc/db/dbJLink.h
@@ -39,6 +39,7 @@ typedef struct jlink {
struct jlif *pif; /* Link methods */
struct jlink *parent; /* NULL for top-level links */
int parseDepth; /* Used by parser, unused afterwards */
+ unsigned debug:1; /* Set to request debug output to console */
/* Link types extend or embed this structure for private storage */
} jlink;
diff --git a/src/std/link/Makefile b/src/std/link/Makefile
index 5ad9777a8..9b6abd705 100644
--- a/src/std/link/Makefile
+++ b/src/std/link/Makefile
@@ -14,5 +14,6 @@ DBD += links.dbd
dbRecStd_SRCS += lnkConst.c
dbRecStd_SRCS += lnkCalc.c
dbRecStd_SRCS += lnkState.c
+dbRecStd_SRCS += lnkDebug.c
HTMLS += links.html
diff --git a/src/std/link/links.dbd.pod b/src/std/link/links.dbd.pod
index 6b48c13fb..bf13bf7a9 100644
--- a/src/std/link/links.dbd.pod
+++ b/src/std/link/links.dbd.pod
@@ -15,6 +15,10 @@ The following additional link types are available in this release:
=item * L
+=item * L
+
+=item * L
+
=back
=head2 Using JSON Links
@@ -200,3 +204,35 @@ link is initialized if it doesn't already exist.
{state:"!simEnable"}
=cut
+
+
+link(debug, lnkDebugIf)
+variable(lnkDebug_debug, int)
+
+=head3 Debug Link C<"debug">
+
+The debug link type exists to enable debugging of other link types; it provides
+no functionality itself other than to turn on the debug flag for the child link
+that is its only parameter and pass all link operations down to that link.
+
+=head4 Example
+
+ {debug:{state:"redBeam"}}
+
+=cut
+
+
+link(trace, lnkTraceIf)
+
+=head3 Trace Link C<"trace">
+
+The trace link type is a relative of the debug link type that also traces the
+operation of its child link. At creation it turns on the debug flag of its child
+link, then it prints the method arguments and return values of all link
+operations before / after passing control down to the child link.
+
+=head4 Example
+
+ {trace:{state:"redBeam"}}
+
+=cut
diff --git a/src/std/link/lnkDebug.c b/src/std/link/lnkDebug.c
new file mode 100644
index 000000000..9ede69cb2
--- /dev/null
+++ b/src/std/link/lnkDebug.c
@@ -0,0 +1,1044 @@
+/*************************************************************************\
+* Copyright (c) 2018 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.
+\*************************************************************************/
+/* lnkDebug.c */
+
+/* Usage
+ * {debug:{...:...}}
+ */
+
+#include
+#include
+#include
+
+#include "alarm.h"
+#include "dbDefs.h"
+#include "dbAccessDefs.h"
+#include "dbLink.h"
+#include "dbJLink.h"
+#include "dbStaticLib.h"
+#include "errlog.h"
+#include "epicsTime.h"
+
+#include "epicsExport.h"
+
+/* This is for debugging the debug link-type */
+int lnkDebug_debug;
+epicsExportAddress(int, lnkDebug_debug);
+
+#define IFDEBUG(n) if (lnkDebug_debug >= (n))
+
+typedef struct debug_link {
+ jlink jlink; /* embedded object */
+ short dbfType;
+ unsigned trace:1;
+ const jlif *child_jlif;
+ const lset *child_lset;
+ jlif jlif;
+ lset lset;
+ struct link child_link;
+} debug_link;
+
+
+/********************* Delegating jlif Routines *********************/
+
+static void delegate_free(jlink *pjlink)
+{
+ debug_link *dlink = CONTAINER(pjlink->parent, struct debug_link, jlink);
+ const jlif *pif = dlink->child_jlif;
+ struct link *plink = &dlink->child_link;
+
+ if (dlink->trace)
+ printf("Link trace: Calling %s::free_jlink(%p)\n",
+ pif->name, pjlink);
+
+ pif->free_jlink(pjlink);
+ plink->type = 0;
+ plink->value.json.jlink = NULL;
+
+ if (dlink->trace)
+ printf("Link trace: %s::free_jlink(%p) returned\n",
+ pif->name, pjlink);
+}
+
+static jlif_result delegate_null(jlink *pjlink)
+{
+ debug_link *dlink = CONTAINER(pjlink->parent, struct debug_link, jlink);
+ const jlif *pif = dlink->child_jlif;
+ jlif_result res;
+
+ if (dlink->trace)
+ printf("Link trace: Calling %s::parse_null(%p)\n",
+ pif->name, pjlink);
+
+ res = pif->parse_null(pjlink);
+
+ if (dlink->trace)
+ printf("Link trace: %s::parse_null(%p) returned %s\n",
+ pif->name, pjlink, jlif_result_name[res]);
+
+ return res;
+}
+
+static jlif_result delegate_boolean(jlink *pjlink, int val)
+{
+ debug_link *dlink = CONTAINER(pjlink->parent, struct debug_link, jlink);
+ const jlif *pif = dlink->child_jlif;
+ jlif_result res;
+
+ if (dlink->trace)
+ printf("Link trace: Calling %s::parse_boolean(%p, %d)\n",
+ pif->name, pjlink, val);
+
+ res = pif->parse_boolean(pjlink, val);
+
+ if (dlink->trace)
+ printf("Link trace: %s::parse_boolean(%p) returned %s\n",
+ pif->name, pjlink, jlif_result_name[res]);
+
+ return res;
+}
+
+static jlif_result delegate_integer(jlink *pjlink, long long num)
+{
+ debug_link *dlink = CONTAINER(pjlink->parent, struct debug_link, jlink);
+ const jlif *pif = dlink->child_jlif;
+ jlif_result res;
+
+ if (dlink->trace)
+ printf("Link trace: Calling %s::parse_integer(%p, %lld)\n",
+ pif->name, pjlink, num);
+
+ res = pif->parse_integer(pjlink, num);
+
+ if (dlink->trace)
+ printf("Link trace: %s::parse_integer(%p) returned %s\n",
+ pif->name, pjlink, jlif_result_name[res]);
+
+ return res;
+}
+
+static jlif_result delegate_double(jlink *pjlink, double num)
+{
+ debug_link *dlink = CONTAINER(pjlink->parent, struct debug_link, jlink);
+ const jlif *pif = dlink->child_jlif;
+ jlif_result res;
+
+ if (dlink->trace)
+ printf("Link trace: Calling %s::parse_double(%p, %g)\n",
+ pif->name, pjlink, num);
+
+ res = pif->parse_double(pjlink, num);
+
+ if (dlink->trace)
+ printf("Link trace: %s::parse_double(%p) returned %s\n",
+ pif->name, pjlink, jlif_result_name[res]);
+
+ return res;
+}
+
+static jlif_result delegate_string(jlink *pjlink, const char *val, size_t len)
+{
+ debug_link *dlink = CONTAINER(pjlink->parent, struct debug_link, jlink);
+ const jlif *pif = dlink->child_jlif;
+ jlif_result res;
+
+ if (dlink->trace)
+ printf("Link trace: Calling %s::parse_string(%p, \"%.*s\")\n",
+ pif->name, pjlink, (int) len, val);
+
+ res = pif->parse_string(pjlink, val, len);
+
+ if (dlink->trace)
+ printf("Link trace: %s::parse_string(%p) returned %s\n",
+ pif->name, pjlink, jlif_result_name[res]);
+
+ return res;
+}
+
+static jlif_key_result delegate_start_map(jlink *pjlink)
+{
+ debug_link *dlink = CONTAINER(pjlink->parent, struct debug_link, jlink);
+ const jlif *pif = dlink->child_jlif;
+ jlif_key_result res;
+
+ if (dlink->trace)
+ printf("Link trace: Calling %s::parse_start_map(%p)\n",
+ pif->name, pjlink);
+
+ res = pif->parse_start_map(pjlink);
+
+ if (dlink->trace)
+ printf("Link trace: %s::parse_start_map(%p) returned %s\n",
+ pif->name, pjlink, jlif_key_result_name[res]);
+
+ return res;
+}
+
+static jlif_result delegate_map_key(jlink *pjlink, const char *key, size_t len)
+{
+ debug_link *dlink = CONTAINER(pjlink->parent, struct debug_link, jlink);
+ const jlif *pif = dlink->child_jlif;
+ jlif_result res;
+
+ if (dlink->trace)
+ printf("Link trace: Calling %s::parse_map_key(%p, \"%.*s\")\n",
+ pif->name, pjlink, (int) len, key);
+
+ res = pif->parse_map_key(pjlink, key, len);
+
+ if (dlink->trace)
+ printf("Link trace: %s::parse_map_key(%p) returned %s\n",
+ pif->name, pjlink, jlif_result_name[res]);
+
+ return res;
+}
+
+static jlif_result delegate_end_map(jlink *pjlink)
+{
+ debug_link *dlink = CONTAINER(pjlink->parent, struct debug_link, jlink);
+ const jlif *pif = dlink->child_jlif;
+ jlif_result res;
+
+ if (dlink->trace)
+ printf("Link trace: Calling %s::parse_end_map(%p)\n",
+ pif->name, pjlink);
+
+ res = pif->parse_end_map(pjlink);
+
+ if (dlink->trace)
+ printf("Link trace: %s::parse_end_map(%p) returned %s\n",
+ pif->name, pjlink, jlif_result_name[res]);
+
+ return res;
+}
+
+static jlif_result delegate_start_array(jlink *pjlink)
+{
+ debug_link *dlink = CONTAINER(pjlink->parent, struct debug_link, jlink);
+ const jlif *pif = dlink->child_jlif;
+ jlif_result res;
+
+ if (dlink->trace)
+ printf("Link trace: Calling %s::parse_(%p)\n",
+ pif->name, pjlink);
+
+ res = pif->parse_start_array(pjlink);
+
+ if (dlink->trace)
+ printf("Link trace: %s::parse_start_array(%p) returned %s\n",
+ pif->name, pjlink, jlif_result_name[res]);
+
+ return res;
+}
+
+static jlif_result delegate_end_array(jlink *pjlink)
+{
+ debug_link *dlink = CONTAINER(pjlink->parent, struct debug_link, jlink);
+ const jlif *pif = dlink->child_jlif;
+ jlif_result res;
+
+ if (dlink->trace)
+ printf("Link trace: Calling %s::parse_end_array(%p)\n",
+ pif->name, pjlink);
+
+ res = pif->parse_end_array(pjlink);
+
+ if (dlink->trace)
+ printf("Link trace: %s::parse_end_array(%p) returned %s\n",
+ pif->name, pjlink, jlif_result_name[res]);
+
+ return res;
+}
+
+static void delegate_start_child(jlink *pjlink, jlink *child)
+{
+ debug_link *dlink = CONTAINER(pjlink->parent, struct debug_link, jlink);
+ const jlif *pif = dlink->child_jlif;
+
+ if (dlink->trace)
+ printf("Link trace: Calling %s::start_child(%p, %p)\n",
+ pif->name, pjlink, child);
+
+ pif->start_child(pjlink, child);
+
+ if (dlink->trace)
+ printf("Link trace: %s::start_child(%p) returned\n",
+ pif->name, pjlink);
+}
+
+static void delegate_end_child(jlink *pjlink, jlink *child)
+{
+ debug_link *dlink = CONTAINER(pjlink->parent, struct debug_link, jlink);
+ const jlif *pif = dlink->child_jlif;
+
+ if (dlink->trace)
+ printf("Link trace: Calling %s::end_child(%p, %p)\n",
+ pif->name, pjlink, child);
+
+ pif->end_child(pjlink, child);
+
+ if (dlink->trace)
+ printf("Link trace: %s::end_child(%p) returned\n",
+ pif->name, pjlink);
+}
+
+static struct lset* delegate_get_lset(const jlink *pjlink)
+{
+ debug_link *dlink = CONTAINER(pjlink->parent, struct debug_link, jlink);
+
+ if (dlink->trace)
+ printf("Link trace: NOT calling %s::get_lset(%p)\n",
+ dlink->child_jlif->name, pjlink);
+
+ return &dlink->lset;
+}
+
+static void delegate_report(const jlink *pjlink, int level, int indent)
+{
+ debug_link *dlink = CONTAINER(pjlink->parent, struct debug_link, jlink);
+ const jlif *pif = dlink->child_jlif;
+
+ if (dlink->trace)
+ printf("Link trace: Calling %s::report(%p, %d, %d)\n",
+ pif->name, pjlink, level, indent);
+
+ pif->report(pjlink, level, indent);
+
+ if (dlink->trace)
+ printf("Link trace: %s::report(%p) returned\n",
+ pif->name, pjlink);
+}
+
+static long delegate_map_children(jlink *pjlink, jlink_map_fn rtn, void *ctx)
+{
+ debug_link *dlink = CONTAINER(pjlink->parent, struct debug_link, jlink);
+ const jlif *pif = dlink->child_jlif;
+ long res;
+
+ if (dlink->trace)
+ printf("Link trace: Calling %s::map_children(%p, %p, %p)\n",
+ pif->name, pjlink, rtn, ctx);
+
+ res = pif->map_children(pjlink, rtn, ctx);
+
+ if (dlink->trace)
+ printf("Link trace: %s::map_children(%p) returned %ld\n",
+ pif->name, pjlink, res);
+
+ return res;
+}
+
+
+/********************* Delegating lset Routines *********************/
+
+static void delegate_openLink(struct link *plink)
+{
+ debug_link *dlink = CONTAINER(plink->value.json.jlink,
+ struct debug_link, jlink);
+ struct link *clink = &dlink->child_link;
+ const lset *clset = dlink->child_lset;
+
+ if (dlink->trace)
+ printf("Link trace: Calling %s::openLink(%p = jlink %p)\n",
+ dlink->child_jlif->name, clink, clink->value.json.jlink);
+
+ clset->openLink(clink);
+
+ if (dlink->trace)
+ printf("Link trace: %s::openLink(%p) returned\n",
+ dlink->child_jlif->name, clink);
+}
+
+static void delegate_removeLink(struct dbLocker *locker, struct link *plink)
+{
+ debug_link *dlink = CONTAINER(plink->value.json.jlink,
+ struct debug_link, jlink);
+ struct link *clink = &dlink->child_link;
+ const lset *clset = dlink->child_lset;
+
+ if (dlink->trace)
+ printf("Link trace: Calling %s::removeLink(%p, %p)\n",
+ dlink->child_jlif->name, locker, clink);
+
+ clset->removeLink(locker, clink);
+
+ if (dlink->trace)
+ printf("Link trace: %s::removeLink(%p) returned\n",
+ dlink->child_jlif->name, clink);
+}
+
+static long delegate_loadScalar(struct link *plink, short dbrType, void *pbuffer)
+{
+ debug_link *dlink = CONTAINER(plink->value.json.jlink,
+ struct debug_link, jlink);
+ struct link *clink = &dlink->child_link;
+ const lset *clset = dlink->child_lset;
+ long res;
+
+ if (dlink->trace)
+ printf("Link trace: Calling %s::loadScalar(%p, %s, %p)\n",
+ dlink->child_jlif->name, clink,
+ dbGetFieldTypeString(dbrType), pbuffer);
+
+ res = clset->loadScalar(clink, dbrType, pbuffer);
+
+ if (dlink->trace)
+ printf("Link trace: %s::loadScalar(%p) returned %ld (0x%lx)\n",
+ dlink->child_jlif->name, clink, res, res);
+
+ return res;
+}
+
+static long delegate_loadLS(struct link *plink, char *pbuffer, epicsUInt32 size,
+ epicsUInt32 *plen)
+{
+ debug_link *dlink = CONTAINER(plink->value.json.jlink,
+ struct debug_link, jlink);
+ struct link *clink = &dlink->child_link;
+ const lset *clset = dlink->child_lset;
+ long res;
+
+ if (dlink->trace)
+ printf("Link trace: Calling %s::loadLS(%p, %p, %u)\n",
+ dlink->child_jlif->name, clink, pbuffer, size);
+
+ res = clset->loadLS(clink, pbuffer, size, plen);
+
+ if (dlink->trace) {
+ printf("Link trace: %s::loadLS(%p) returned %ld (0x%lx)\n",
+ dlink->child_jlif->name, clink, res, res);
+ if (res == 0)
+ printf(" Loaded: %u byte(s) \"%s\"\n", *plen, pbuffer);
+ }
+
+ return res;
+}
+
+static long delegate_loadArray(struct link *plink, short dbrType, void *pbuffer,
+ long *pnRequest)
+{
+ debug_link *dlink = CONTAINER(plink->value.json.jlink,
+ struct debug_link, jlink);
+ struct link *clink = &dlink->child_link;
+ const lset *clset = dlink->child_lset;
+ long res;
+
+ if (dlink->trace)
+ printf("Link trace: Calling %s::loadArray(%p, %s, %p, %ld)\n",
+ dlink->child_jlif->name, clink,
+ dbGetFieldTypeString(dbrType), pbuffer, pnRequest ? *pnRequest : 0l);
+
+ res = clset->loadArray(clink, dbrType, pbuffer, pnRequest);
+
+ if (dlink->trace) {
+ printf("Link trace: %s::loadArray(%p) returned %ld (0x%lx)\n",
+ dlink->child_jlif->name, clink, res, res);
+ if (res == 0)
+ printf(" Loaded: %ld element(s)\n", pnRequest ? *pnRequest : 1l);
+ }
+
+ return res;
+}
+
+static int delegate_isConnected(const struct link *plink)
+{
+ debug_link *dlink = CONTAINER(plink->value.json.jlink,
+ struct debug_link, jlink);
+ struct link *clink = &dlink->child_link;
+ const lset *clset = dlink->child_lset;
+ int res;
+
+ if (dlink->trace)
+ printf("Link trace: Calling %s::isConnected(%p)\n",
+ dlink->child_jlif->name, clink);
+
+ res = clset->isConnected(clink);
+
+ if (dlink->trace)
+ printf("Link trace: %s::isConnected(%p) returned %d (%s)\n",
+ dlink->child_jlif->name, clink, res,
+ res == 0 ? "No" : res == 1 ? "Yes" : "Bad value");
+
+ return res;
+}
+
+static int delegate_getDBFtype(const struct link *plink)
+{
+ debug_link *dlink = CONTAINER(plink->value.json.jlink,
+ struct debug_link, jlink);
+ struct link *clink = &dlink->child_link;
+ const lset *clset = dlink->child_lset;
+ int res;
+
+ if (dlink->trace)
+ printf("Link trace: Calling %s::getDBFtype(%p)\n",
+ dlink->child_jlif->name, clink);
+
+ res = clset->getDBFtype(clink);
+
+ if (dlink->trace)
+ printf("Link trace: %s::getDBFtype(%p) returned %d (%s)\n",
+ dlink->child_jlif->name, clink, res,
+ res == -1 ? "Link disconnected" : dbGetFieldTypeString(res));
+
+ return res;
+}
+
+static long delegate_getElements(const struct link *plink, long *pnElements)
+{
+ debug_link *dlink = CONTAINER(plink->value.json.jlink,
+ struct debug_link, jlink);
+ struct link *clink = &dlink->child_link;
+ const lset *clset = dlink->child_lset;
+ long res;
+
+ if (dlink->trace)
+ printf("Link trace: Calling %s::getElements(%p)\n",
+ dlink->child_jlif->name, clink);
+
+ res = clset->getElements(clink, pnElements);
+
+ if (dlink->trace) {
+ printf("Link trace: %s::getElements(%p) returned %ld (0x%lx)\n",
+ dlink->child_jlif->name, clink, res, res);
+ if (res == 0)
+ printf(" Result: %ld element(s)\n", *pnElements);
+ }
+
+ return res;
+}
+
+static long delegate_getValue(struct link *plink, short dbrType, void *pbuffer,
+ long *pnRequest)
+{
+ debug_link *dlink = CONTAINER(plink->value.json.jlink,
+ struct debug_link, jlink);
+ struct link *clink = &dlink->child_link;
+ const lset *clset = dlink->child_lset;
+ long res;
+
+ if (dlink->trace)
+ printf("Link trace: Calling %s::getValue(%p, %s, %p, %ld)\n",
+ dlink->child_jlif->name, clink,
+ dbGetFieldTypeString(dbrType), pbuffer, pnRequest ? *pnRequest : 0l);
+
+ res = clset->getValue(clink, dbrType, pbuffer, pnRequest);
+
+ if (dlink->trace) {
+ printf("Link trace: %s::getValue(%p) returned %ld (0x%lx)\n",
+ dlink->child_jlif->name, clink, res, res);
+ if (res == 0)
+ printf(" Got: %ld element(s)\n", pnRequest ? *pnRequest : 1l);
+ }
+
+ return res;
+}
+
+static long delegate_getControlLimits(const struct link *plink,
+ double *lo, double *hi)
+{
+ debug_link *dlink = CONTAINER(plink->value.json.jlink,
+ struct debug_link, jlink);
+ struct link *clink = &dlink->child_link;
+ const lset *clset = dlink->child_lset;
+ long res;
+
+ if (dlink->trace)
+ printf("Link trace: Calling %s::getControlLimits(%p)\n",
+ dlink->child_jlif->name, clink);
+
+ res = clset->getControlLimits(clink, lo, hi);
+
+ if (dlink->trace) {
+ printf("Link trace: %s::getControlLimits(%p) returned %ld (0x%lx)\n",
+ dlink->child_jlif->name, clink, res, res);
+ if (res == 0)
+ printf(" Got: Lo = %g, Hi = %g\n", *lo, *hi);
+ }
+
+ return res;
+}
+
+static long delegate_getGraphicLimits(const struct link *plink,
+ double *lo, double *hi)
+{
+ debug_link *dlink = CONTAINER(plink->value.json.jlink,
+ struct debug_link, jlink);
+ struct link *clink = &dlink->child_link;
+ const lset *clset = dlink->child_lset;
+ long res;
+
+ if (dlink->trace)
+ printf("Link trace: Calling %s::getGraphicLimits(%p)\n",
+ dlink->child_jlif->name, clink);
+
+ res = clset->getGraphicLimits(clink, lo, hi);
+
+ if (dlink->trace) {
+ printf("Link trace: %s::getGraphicLimits(%p) returned %ld (0x%lx)\n",
+ dlink->child_jlif->name, clink, res, res);
+ if (res == 0)
+ printf(" Got: Lo = %g, Hi = %g\n", *lo, *hi);
+ }
+
+ return res;
+}
+
+static long delegate_getAlarmLimits(const struct link *plink,
+ double *lolo, double *lo, double *hi, double *hihi)
+{
+ debug_link *dlink = CONTAINER(plink->value.json.jlink,
+ struct debug_link, jlink);
+ struct link *clink = &dlink->child_link;
+ const lset *clset = dlink->child_lset;
+ long res;
+
+ if (dlink->trace)
+ printf("Link trace: Calling %s::getAlarmLimits(%p)\n",
+ dlink->child_jlif->name, clink);
+
+ res = clset->getAlarmLimits(clink, lolo, lo, hi, hihi);
+
+ if (dlink->trace) {
+ printf("Link trace: %s::getAlarmLimits(%p) returned %ld (0x%lx)\n",
+ dlink->child_jlif->name, clink, res, res);
+ if (res == 0)
+ printf(" Got: Lolo = %g, Lo = %g, Hi = %g, Hihi = %g\n",
+ *lolo, *lo, *hi, *hihi);
+ }
+
+ return res;
+}
+
+static long delegate_getPrecision(const struct link *plink, short *precision)
+{
+ debug_link *dlink = CONTAINER(plink->value.json.jlink,
+ struct debug_link, jlink);
+ struct link *clink = &dlink->child_link;
+ const lset *clset = dlink->child_lset;
+ long res;
+
+ if (dlink->trace)
+ printf("Link trace: Calling %s::getPrecision(%p)\n",
+ dlink->child_jlif->name, clink);
+
+ res = clset->getPrecision(clink, precision);
+
+ if (dlink->trace) {
+ printf("Link trace: %s::getPrecision(%p) returned %ld (0x%lx)\n",
+ dlink->child_jlif->name, clink, res, res);
+ if (res == 0)
+ printf(" Got: prec = %d\n", *precision);
+ }
+
+ return res;
+}
+
+static long delegate_getUnits(const struct link *plink, char *units, int unitsSize)
+{
+ debug_link *dlink = CONTAINER(plink->value.json.jlink,
+ struct debug_link, jlink);
+ struct link *clink = &dlink->child_link;
+ const lset *clset = dlink->child_lset;
+ long res;
+
+ if (dlink->trace)
+ printf("Link trace: Calling %s::getUnits(%p)\n",
+ dlink->child_jlif->name, clink);
+
+ res = clset->getUnits(clink, units, unitsSize);
+
+ if (dlink->trace) {
+ printf("Link trace: %s::getUnits(%p) returned %ld (0x%lx)\n",
+ dlink->child_jlif->name, clink, res, res);
+ if (res == 0)
+ printf(" Got: Units = '%s'\n", units);
+ }
+
+ return res;
+}
+
+static long delegate_getAlarm(const struct link *plink, epicsEnum16 *stat,
+ epicsEnum16 *sevr)
+{
+ debug_link *dlink = CONTAINER(plink->value.json.jlink,
+ struct debug_link, jlink);
+ struct link *clink = &dlink->child_link;
+ const lset *clset = dlink->child_lset;
+ long res;
+
+ if (dlink->trace)
+ printf("Link trace: Calling %s::getAlarm(%p)\n",
+ dlink->child_jlif->name, clink);
+
+ res = clset->getAlarm(clink, stat, sevr);
+
+ if (dlink->trace) {
+ printf("Link trace: %s::getAlarm(%p) returned %ld (0x%lx)\n",
+ dlink->child_jlif->name, clink, res, res);
+ if (res == 0)
+ printf(" Got:%s%s%s%s\n",
+ stat ? " Status = " : "",
+ stat && (*stat < ALARM_NSEV) ?
+ epicsAlarmConditionStrings[*stat] : "Bad-status",
+ sevr ? " Severity = " : "",
+ sevr && (*sevr < ALARM_NSTATUS) ?
+ epicsAlarmSeverityStrings[*sevr] : "Bad-severity"
+ );
+ }
+
+ return res;
+}
+
+static long delegate_getTimeStamp(const struct link *plink, epicsTimeStamp *pstamp)
+{
+ debug_link *dlink = CONTAINER(plink->value.json.jlink,
+ struct debug_link, jlink);
+ struct link *clink = &dlink->child_link;
+ const lset *clset = dlink->child_lset;
+ long res;
+
+ if (dlink->trace)
+ printf("Link trace: Calling %s::getTimeStamp(%p)\n",
+ dlink->child_jlif->name, clink);
+
+ res = clset->getTimeStamp(clink, pstamp);
+
+ if (dlink->trace) {
+ printf("Link trace: %s::getTimeStamp(%p) returned %ld (0x%lx)\n",
+ dlink->child_jlif->name, clink, res, res);
+ if (res == 0) {
+ char timeStr[32];
+
+ epicsTimeToStrftime(timeStr, sizeof(timeStr),
+ "%Y-%m-%d %H:%M:%S.%09f", pstamp);
+ printf(" Got: Timestamp = '%s'\n", timeStr);
+ }
+ }
+
+ return res;
+}
+
+static long delegate_putValue(struct link *plink, short dbrType,
+ const void *pbuffer, long nRequest)
+{
+ debug_link *dlink = CONTAINER(plink->value.json.jlink,
+ struct debug_link, jlink);
+ struct link *clink = &dlink->child_link;
+ const lset *clset = dlink->child_lset;
+ long res;
+
+ if (dlink->trace)
+ printf("Link trace: Calling %s::putValue(%p, %s, %p, %ld)\n",
+ dlink->child_jlif->name, clink,
+ dbGetFieldTypeString(dbrType), pbuffer, nRequest);
+
+ res = clset->putValue(clink, dbrType, pbuffer, nRequest);
+
+ if (dlink->trace)
+ printf("Link trace: %s::putValue(%p) returned %ld (0x%lx)\n",
+ dlink->child_jlif->name, clink, res, res);
+
+ return res;
+}
+
+static long delegate_putAsync(struct link *plink, short dbrType,
+ const void *pbuffer, long nRequest)
+{
+ debug_link *dlink = CONTAINER(plink->value.json.jlink,
+ struct debug_link, jlink);
+ struct link *clink = &dlink->child_link;
+ const lset *clset = dlink->child_lset;
+ long res;
+
+ if (dlink->trace)
+ printf("Link trace: Calling %s::putAsync(%p, %s, %p, %ld)\n",
+ dlink->child_jlif->name, clink,
+ dbGetFieldTypeString(dbrType), pbuffer, nRequest);
+
+ res = clset->putAsync(clink, dbrType, pbuffer, nRequest);
+
+ if (dlink->trace)
+ printf("Link trace: %s::putAsync(%p) returned %ld (0x%lx)\n",
+ dlink->child_jlif->name, clink, res, res);
+
+ return res;
+}
+
+static void delegate_scanForward(struct link *plink)
+{
+ debug_link *dlink = CONTAINER(plink->value.json.jlink,
+ struct debug_link, jlink);
+ struct link *clink = &dlink->child_link;
+ const lset *clset = dlink->child_lset;
+
+ if (dlink->trace)
+ printf("Link trace: Calling %s::scanForward(%p)\n",
+ dlink->child_jlif->name, clink);
+
+ clset->scanForward(clink);
+
+ if (dlink->trace)
+ printf("Link trace: %s::scanForward(%p) returned\n",
+ dlink->child_jlif->name, clink);
+}
+
+static long delegate_doLocked(struct link *plink, dbLinkUserCallback rtn, void *priv)
+{
+ debug_link *dlink = CONTAINER(plink->value.json.jlink,
+ struct debug_link, jlink);
+ struct link *clink = &dlink->child_link;
+ const lset *clset = dlink->child_lset;
+ long res;
+
+ if (dlink->trace)
+ printf("Link trace: Calling %s::doLocked(%p, %p, %p)\n",
+ dlink->child_jlif->name, clink, rtn, priv);
+
+ res = clset->doLocked(clink, rtn, priv);
+
+ if (dlink->trace)
+ printf("Link trace: %s::doLocked(%p) returned %ld (0x%lx)\n",
+ dlink->child_jlif->name, clink, res, res);
+
+ return res;
+}
+
+
+/************************ Debug jlif Routines ***********************/
+
+static jlink* lnkDebug_alloc(short dbfType)
+{
+ debug_link *dlink;
+
+ IFDEBUG(10)
+ printf("lnkDebug_alloc(%s)\n", dbGetFieldTypeString(dbfType));
+
+ dlink = calloc(1, sizeof(struct debug_link));
+ if (!dlink) {
+ errlogPrintf("lnkDebug: calloc() failed.\n");
+ return NULL;
+ }
+
+ dlink->dbfType = dbfType;
+
+ IFDEBUG(10)
+ printf("lnkDebug_alloc -> debug@%p\n", dlink);
+
+ return &dlink->jlink;
+}
+
+static jlink* lnkTrace_alloc(short dbfType)
+{
+ debug_link *dlink;
+
+ IFDEBUG(10)
+ printf("lnkTrace_alloc(%s)\n", dbGetFieldTypeString(dbfType));
+
+ dlink = calloc(1, sizeof(struct debug_link));
+ if (!dlink) {
+ errlogPrintf("lnkTrace: calloc() failed.\n");
+ return NULL;
+ }
+
+ dlink->dbfType = dbfType;
+ dlink->trace = 1;
+
+ IFDEBUG(10)
+ printf("lnkTrace_alloc -> debug@%p\n", dlink);
+
+ return &dlink->jlink;
+}
+
+static void lnkDebug_free(jlink *pjlink)
+{
+ debug_link *dlink = CONTAINER(pjlink, struct debug_link, jlink);
+
+ IFDEBUG(10)
+ printf("lnkDebug_free(debug@%p)\n", dlink);
+
+ dbJLinkFree(dlink->child_link.value.json.jlink);
+
+ free(dlink);
+}
+
+static jlif_key_result lnkDebug_start_map(jlink *pjlink)
+{
+ debug_link *dlink = CONTAINER(pjlink, struct debug_link, jlink);
+
+ IFDEBUG(10)
+ printf("lnkDebug_start_map(debug@%p)\n", dlink);
+
+ switch (dlink->dbfType) {
+ case DBF_INLINK:
+ return jlif_key_child_inlink;
+ case DBF_OUTLINK:
+ return jlif_key_child_outlink;
+ case DBF_FWDLINK:
+ return jlif_key_child_outlink;
+ }
+ return jlif_stop;
+}
+
+static jlif_result lnkDebug_end_map(jlink *pjlink)
+{
+ debug_link *dlink = CONTAINER(pjlink, struct debug_link, jlink);
+
+ IFDEBUG(10)
+ printf("lnkDebug_end_map(debug@%p)\n", dlink);
+
+ return jlif_continue;
+}
+
+static void lnkDebug_start_child(jlink *parent, jlink *child)
+{
+ debug_link *dlink = CONTAINER(parent, struct debug_link, jlink);
+ const jlif *pif = child->pif;
+ const jlif delegate_jlif = {
+ pif->name,
+ pif->alloc_jlink, /* Never used */
+ delegate_free,
+ pif->parse_null ? delegate_null : NULL,
+ pif->parse_boolean ? delegate_boolean : NULL,
+ pif->parse_integer ? delegate_integer : NULL,
+ pif->parse_double ? delegate_double : NULL,
+ pif->parse_string ? delegate_string : NULL,
+ pif->parse_start_map ? delegate_start_map : NULL,
+ pif->parse_map_key ? delegate_map_key : NULL,
+ pif->parse_end_map ? delegate_end_map : NULL,
+ pif->parse_start_array ? delegate_start_array : NULL,
+ pif->parse_end_array ? delegate_end_array : NULL,
+ pif->end_child ? delegate_end_child : NULL,
+ delegate_get_lset,
+ pif->report ? delegate_report : NULL,
+ pif->map_children ? delegate_map_children : NULL,
+ pif->start_child ? delegate_start_child : NULL
+ };
+
+ IFDEBUG(10)
+ printf("lnkDebug_start_child(debug@%p, %s@%p)\n", dlink,
+ child->pif->name, child);
+
+ dlink->child_jlif = pif;
+ memcpy(&dlink->jlif, &delegate_jlif, sizeof(jlif));
+
+ child->debug = 1;
+ child->pif = &dlink->jlif; /* Replace Child's interface table */
+
+ IFDEBUG(15)
+ printf("lnkDebug_start_child: pif %p => %p\n", pif, child->pif);
+
+ if (dlink->trace)
+ printf("Link trace: %s::alloc_jlink(%s) returned %p\n",
+ pif->name, dbGetFieldTypeString(dlink->dbfType), child);
+}
+
+static void lnkDebug_end_child(jlink *parent, jlink *child)
+{
+ debug_link *dlink = CONTAINER(parent, struct debug_link, jlink);
+ struct link *plink = &dlink->child_link;
+ const lset *plset = dlink->child_jlif->get_lset(child);
+ lset delegate_lset = {
+ plset->isConstant,
+ plset->isVolatile,
+ plset->openLink ? delegate_openLink : NULL,
+ plset->removeLink ? delegate_removeLink : NULL,
+ plset->loadScalar ? delegate_loadScalar : NULL,
+ plset->loadLS ? delegate_loadLS : NULL,
+ plset->loadArray ? delegate_loadArray : NULL,
+ plset->isConnected ? delegate_isConnected : NULL,
+ plset->getDBFtype ? delegate_getDBFtype : NULL,
+ plset->getElements ? delegate_getElements : NULL,
+ plset->getValue ? delegate_getValue : NULL,
+ plset->getControlLimits ? delegate_getControlLimits : NULL,
+ plset->getGraphicLimits ? delegate_getGraphicLimits : NULL,
+ plset->getAlarmLimits ? delegate_getAlarmLimits : NULL,
+ plset->getPrecision ? delegate_getPrecision : NULL,
+ plset->getUnits ? delegate_getUnits : NULL,
+ plset->getAlarm ? delegate_getAlarm : NULL,
+ plset->getTimeStamp ? delegate_getTimeStamp : NULL,
+ plset->putValue ? delegate_putValue : NULL,
+ plset->putAsync ? delegate_putAsync : NULL,
+ plset->scanForward ? delegate_scanForward : NULL,
+ plset->doLocked ? delegate_doLocked : NULL
+ };
+
+ IFDEBUG(10)
+ printf("lnkDebug_end_child(debug@%p, %s@%p)\n", dlink,
+ child->pif->name, child);
+
+ plink->type = JSON_LINK;
+ plink->value.json.string = NULL;
+ plink->value.json.jlink = child;
+
+ dlink->child_lset = plset;
+ memcpy(&dlink->lset, &delegate_lset, sizeof(lset));
+
+ IFDEBUG(15)
+ printf("lnkDebug_end_child: lset %p => %p\n", plset, &dlink->lset);
+}
+
+static struct lset* lnkDebug_get_lset(const jlink *pjlink)
+{
+ debug_link *dlink = CONTAINER(pjlink, struct debug_link, jlink);
+
+ IFDEBUG(10)
+ printf("lnkDebug_get_lset(debug@%p)\n", pjlink);
+
+ return &dlink->lset;
+}
+
+static void lnkDebug_report(const jlink *pjlink, int level, int indent)
+{
+ debug_link *dlink = CONTAINER(pjlink, struct debug_link, jlink);
+
+ IFDEBUG(10)
+ printf("lnkDebug_report(debug@%p)\n", dlink);
+
+ if (dlink->trace)
+ printf("%*s'trace':\n", indent, "");
+ else
+ printf("%*s'debug':\n", indent, "");
+
+ if (dlink->child_link.type == JSON_LINK) {
+ dbJLinkReport(dlink->child_link.value.json.jlink, level, indent + 2);
+ }
+}
+
+long lnkDebug_map_children(jlink *pjlink, jlink_map_fn rtn, void *ctx)
+{
+ debug_link *dlink = CONTAINER(pjlink, struct debug_link, jlink);
+
+ IFDEBUG(10)
+ printf("lnkDebug_map_children(debug@%p)\n", dlink);
+
+ if (dlink->child_link.type == JSON_LINK) {
+ return dbJLinkMapChildren(&dlink->child_link, rtn, ctx);
+ }
+ return 0;
+}
+
+
+/************************* Interface Tables *************************/
+
+static jlif lnkDebugIf = {
+ "debug", lnkDebug_alloc, lnkDebug_free,
+ NULL, NULL, NULL, NULL, NULL,
+ lnkDebug_start_map, NULL, lnkDebug_end_map,
+ NULL, NULL, lnkDebug_end_child, lnkDebug_get_lset,
+ lnkDebug_report, lnkDebug_map_children, lnkDebug_start_child
+};
+epicsExportAddress(jlif, lnkDebugIf);
+
+static jlif lnkTraceIf = {
+ "trace", lnkTrace_alloc, lnkDebug_free,
+ NULL, NULL, NULL, NULL, NULL,
+ lnkDebug_start_map, NULL, lnkDebug_end_map,
+ NULL, NULL, lnkDebug_end_child, lnkDebug_get_lset,
+ lnkDebug_report, lnkDebug_map_children, lnkDebug_start_child
+};
+epicsExportAddress(jlif, lnkTraceIf);
From 89b9e240b0c81938629037803bd08e5818d86884 Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Fri, 1 Jun 2018 23:43:39 -0500
Subject: [PATCH 038/147] Link types: Remove debug tracing now provided by
debug link type
---
src/std/link/links.dbd.pod | 3 --
src/std/link/lnkCalc.c | 88 -------------------------------
src/std/link/lnkConst.c | 104 +++++++------------------------------
src/std/link/lnkState.c | 59 +--------------------
4 files changed, 22 insertions(+), 232 deletions(-)
diff --git a/src/std/link/links.dbd.pod b/src/std/link/links.dbd.pod
index bf13bf7a9..b5ed582f2 100644
--- a/src/std/link/links.dbd.pod
+++ b/src/std/link/links.dbd.pod
@@ -39,7 +39,6 @@ database file syntax.
link(const, lnkConstIf)
-variable(lnkConst_debug, int)
=head3 Constant Link C<"const">
@@ -80,7 +79,6 @@ converted to the desired double value at initialization, for example:
link(calc, lnkCalcIf)
-variable(lnkCalc_debug, int)
=head3 Calculation Link C<"calc">
@@ -169,7 +167,6 @@ atomically with the value of the input argument.
link(state, lnkStateIf)
-variable(lnkState_debug, int)
=head3 dbState Link C<"state">
diff --git a/src/std/link/lnkCalc.c b/src/std/link/lnkCalc.c
index 6b68ac990..fa1a363fe 100644
--- a/src/std/link/lnkCalc.c
+++ b/src/std/link/lnkCalc.c
@@ -37,11 +37,6 @@
typedef long (*FASTCONVERT)();
-int lnkCalc_debug;
-epicsExportAddress(int, lnkCalc_debug);
-
-#define IFDEBUG(n) if (lnkCalc_debug >= (n))
-
typedef struct calc_link {
jlink jlink; /* embedded object */
int nArgs;
@@ -82,9 +77,6 @@ static jlink* lnkCalc_alloc(short dbfType)
{
calc_link *clink;
- IFDEBUG(10)
- printf("lnkCalc_alloc(%d)\n", dbfType);
-
if (dbfType == DBF_FWDLINK) {
errlogPrintf("lnkCalc: No support for forward links\n");
return NULL;
@@ -102,9 +94,6 @@ static jlink* lnkCalc_alloc(short dbfType)
clink->prec = 15; /* standard value for a double */
clink->tinp = -1;
- IFDEBUG(10)
- printf("lnkCalc_alloc -> calc@%p\n", clink);
-
return &clink->jlink;
}
@@ -113,9 +102,6 @@ static void lnkCalc_free(jlink *pjlink)
calc_link *clink = CONTAINER(pjlink, struct calc_link, jlink);
int i;
- IFDEBUG(10)
- printf("lnkCalc_free(calc@%p)\n", clink);
-
for (i = 0; i < clink->nArgs; i++)
dbJLinkFree(clink->inp[i].value.json.jlink);
@@ -135,9 +121,6 @@ static jlif_result lnkCalc_integer(jlink *pjlink, long long num)
{
calc_link *clink = CONTAINER(pjlink, struct calc_link, jlink);
- IFDEBUG(10)
- printf("lnkCalc_integer(calc@%p, %lld)\n", clink, num);
-
if (clink->pstate == ps_prec) {
clink->prec = num;
return jlif_continue;
@@ -163,9 +146,6 @@ static jlif_result lnkCalc_double(jlink *pjlink, double num)
{
calc_link *clink = CONTAINER(pjlink, struct calc_link, jlink);
- IFDEBUG(10)
- printf("lnkCalc_double(calc@%p, %g)\n", clink, num);
-
if (clink->pstate != ps_args) {
return jlif_stop;
errlogPrintf("lnkCalc: Unexpected double %g\n", num);
@@ -188,9 +168,6 @@ static jlif_result lnkCalc_string(jlink *pjlink, const char *val, size_t len)
char *inbuf, *postbuf;
short err;
- IFDEBUG(10)
- printf("lnkCalc_string(calc@%p, \"%.*s\")\n", clink, (int) len, val);
-
if (clink->pstate == ps_units) {
clink->units = epicsStrnDup(val, len);
return jlif_continue;
@@ -251,9 +228,6 @@ static jlif_key_result lnkCalc_start_map(jlink *pjlink)
{
calc_link *clink = CONTAINER(pjlink, struct calc_link, jlink);
- IFDEBUG(10)
- printf("lnkCalc_start_map(calc@%p)\n", clink);
-
if (clink->pstate == ps_args)
return jlif_key_child_inlink;
if (clink->pstate == ps_out)
@@ -271,9 +245,6 @@ static jlif_result lnkCalc_map_key(jlink *pjlink, const char *key, size_t len)
{
calc_link *clink = CONTAINER(pjlink, struct calc_link, jlink);
- IFDEBUG(10)
- printf("lnkCalc_map_key(calc@%p, \"%.*s\")\n", pjlink, (int) len, key);
-
/* FIXME: These errors messages are wrong when a key is duplicated.
* The key is known, we just don't allow it more than once.
*/
@@ -326,9 +297,6 @@ static jlif_result lnkCalc_end_map(jlink *pjlink)
{
calc_link *clink = CONTAINER(pjlink, struct calc_link, jlink);
- IFDEBUG(10)
- printf("lnkCalc_end_map(calc@%p)\n", clink);
-
if (clink->pstate == ps_error)
return jlif_stop;
else if (clink->dbfType == DBF_INLINK &&
@@ -349,9 +317,6 @@ static jlif_result lnkCalc_start_array(jlink *pjlink)
{
calc_link *clink = CONTAINER(pjlink, struct calc_link, jlink);
- IFDEBUG(10)
- printf("lnkCalc_start_array(calc@%p)\n", clink);
-
if (clink->pstate != ps_args) {
errlogPrintf("lnkCalc: Unexpected array\n");
return jlif_stop;
@@ -364,9 +329,6 @@ static jlif_result lnkCalc_end_array(jlink *pjlink)
{
calc_link *clink = CONTAINER(pjlink, struct calc_link, jlink);
- IFDEBUG(10)
- printf("lnkCalc_end_array(calc@%p)\n", clink);
-
if (clink->pstate == ps_error)
return jlif_stop;
@@ -406,9 +368,6 @@ errOut:
static struct lset* lnkCalc_get_lset(const jlink *pjlink)
{
- IFDEBUG(10)
- printf("lnkCalc_get_lset(calc@%p)\n", pjlink);
-
return &lnkCalc_lset;
}
@@ -417,9 +376,6 @@ static void lnkCalc_report(const jlink *pjlink, int level, int indent)
calc_link *clink = CONTAINER(pjlink, struct calc_link, jlink);
int i;
- IFDEBUG(10)
- printf("lnkCalc_report(calc@%p)\n", clink);
-
printf("%*s'calc': \"%s\" = %.*g %s\n", indent, "",
clink->expr, clink->prec, clink->val,
clink->units ? clink->units : "");
@@ -470,9 +426,6 @@ static long lnkCalc_map_children(jlink *pjlink, jlink_map_fn rtn, void *ctx)
calc_link *clink = CONTAINER(pjlink, struct calc_link, jlink);
int i;
- IFDEBUG(10)
- printf("lnkCalc_map_children(calc@%p)\n", clink);
-
for (i = 0; i < clink->nArgs; i++) {
struct link *child = &clink->inp[i];
long status = dbJLinkMapChildren(child, rtn, ctx);
@@ -495,9 +448,6 @@ static void lnkCalc_open(struct link *plink)
struct calc_link, jlink);
int i;
- IFDEBUG(10)
- printf("lnkCalc_open(calc@%p)\n", clink);
-
for (i = 0; i < clink->nArgs; i++) {
struct link *child = &clink->inp[i];
@@ -517,9 +467,6 @@ static void lnkCalc_remove(struct dbLocker *locker, struct link *plink)
struct calc_link, jlink);
int i;
- IFDEBUG(10)
- printf("lnkCalc_remove(calc@%p)\n", clink);
-
for (i = 0; i < clink->nArgs; i++) {
struct link *child = &clink->inp[i];
@@ -548,9 +495,6 @@ static int lnkCalc_isConn(const struct link *plink)
int connected = 1;
int i;
- IFDEBUG(10)
- printf("lnkCalc_isConn(calc@%p)\n", clink);
-
for (i = 0; i < clink->nArgs; i++) {
struct link *child = &clink->inp[i];
@@ -572,24 +516,11 @@ static int lnkCalc_isConn(const struct link *plink)
static int lnkCalc_getDBFtype(const struct link *plink)
{
- calc_link *clink = CONTAINER(plink->value.json.jlink,
- struct calc_link, jlink);
-
- IFDEBUG(10)
- printf("lnkCalc_getDBFtype(calc@%p)\n", clink);
-
return DBF_DOUBLE;
}
static long lnkCalc_getElements(const struct link *plink, long *nelements)
{
- calc_link *clink = CONTAINER(plink->value.json.jlink,
- struct calc_link, jlink);
-
- IFDEBUG(10)
- printf("lnkCalc_getElements(calc@%p, (%ld))\n",
- clink, *nelements);
-
*nelements = 1;
return 0;
}
@@ -622,10 +553,6 @@ static long lnkCalc_getValue(struct link *plink, short dbrType, void *pbuffer,
long status;
FASTCONVERT conv = dbFastPutConvertRoutine[DBR_DOUBLE][dbrType];
- IFDEBUG(10)
- printf("lnkCalc_getValue(calc@%p, %d, ...)\n",
- clink, dbrType);
-
/* Any link errors will trigger a LINK/INVALID alarm in the child link */
for (i = 0; i < clink->nArgs; i++) {
struct link *child = &clink->inp[i];
@@ -697,9 +624,6 @@ static long lnkCalc_putValue(struct link *plink, short dbrType,
long status;
FASTCONVERT conv = dbFastGetConvertRoutine[dbrType][DBR_DOUBLE];
- IFDEBUG(10)
- printf("lnkCalc_putValue(calc@%p, %d, ...)\n", clink, dbrType);
-
/* Any link errors will trigger a LINK/INVALID alarm in the child link */
for (i = 0; i < clink->nArgs; i++) {
struct link *child = &clink->inp[i];
@@ -763,9 +687,6 @@ static long lnkCalc_getPrecision(const struct link *plink, short *precision)
calc_link *clink = CONTAINER(plink->value.json.jlink,
struct calc_link, jlink);
- IFDEBUG(10)
- printf("lnkCalc_getPrecision(calc@%p)\n", clink);
-
*precision = clink->prec;
return 0;
}
@@ -775,9 +696,6 @@ static long lnkCalc_getUnits(const struct link *plink, char *units, int len)
calc_link *clink = CONTAINER(plink->value.json.jlink,
struct calc_link, jlink);
- IFDEBUG(10)
- printf("lnkCalc_getUnits(calc@%p)\n", clink);
-
if (clink->units) {
strncpy(units, clink->units, --len);
units[len] = '\0';
@@ -793,9 +711,6 @@ static long lnkCalc_getAlarm(const struct link *plink, epicsEnum16 *status,
calc_link *clink = CONTAINER(plink->value.json.jlink,
struct calc_link, jlink);
- IFDEBUG(10)
- printf("lnkCalc_getAlarm(calc@%p)\n", clink);
-
if (status)
*status = clink->stat;
if (severity)
@@ -809,9 +724,6 @@ static long lnkCalc_getTimestamp(const struct link *plink, epicsTimeStamp *pstam
calc_link *clink = CONTAINER(plink->value.json.jlink,
struct calc_link, jlink);
- IFDEBUG(10)
- printf("lnkCalc_getTimestamp(calc@%p)\n", clink);
-
if (clink->tinp >= 0) {
*pstamp = clink->time;
return 0;
diff --git a/src/std/link/lnkConst.c b/src/std/link/lnkConst.c
index 3b9392cfa..cb948fcb3 100644
--- a/src/std/link/lnkConst.c
+++ b/src/std/link/lnkConst.c
@@ -22,11 +22,6 @@
#include "epicsExport.h"
-int lnkConst_debug;
-epicsExportAddress(int, lnkConst_debug);
-
-#define IFDEBUG(n) if (lnkConst_debug >= (n))
-
typedef long (*FASTCONVERT)();
typedef struct const_link {
@@ -53,9 +48,6 @@ static jlink* lnkConst_alloc(short dbfType)
{
const_link *clink;
- IFDEBUG(10)
- printf("lnkConst_alloc(%d)\n", dbfType);
-
if (dbfType != DBF_INLINK) {
errlogPrintf("lnkConst: Only works with input links\n");
return NULL;
@@ -71,9 +63,6 @@ static jlink* lnkConst_alloc(short dbfType)
clink->nElems = 0;
clink->value.pmem = NULL;
- IFDEBUG(10)
- printf("lnkConst_alloc -> const@%p\n", clink);
-
return &clink->jlink;
}
@@ -81,9 +70,6 @@ static void lnkConst_free(jlink *pjlink)
{
const_link *clink = CONTAINER(pjlink, const_link, jlink);
- IFDEBUG(10)
- printf("lnkConst_free(const@%p) type=%d\n", pjlink, clink->type);
-
switch (clink->type) {
int i;
case ac40:
@@ -109,16 +95,13 @@ static jlif_result lnkConst_integer(jlink *pjlink, long long num)
const_link *clink = CONTAINER(pjlink, const_link, jlink);
int newElems = clink->nElems + 1;
- IFDEBUG(10)
- printf("lnkConst_integer(const@%p, %lld)\n", pjlink, num);
-
switch (clink->type) {
void *buf;
case s0:
clink->type = si64;
clink->value.scalar_integer = num;
- IFDEBUG(12)
+ if (pjlink->debug)
printf(" si64 := %lld\n", num);
break;
@@ -132,7 +115,7 @@ static jlif_result lnkConst_integer(jlink *pjlink, long long num)
clink->value.pmem = buf;
clink->value.pintegers[clink->nElems] = num;
- IFDEBUG(12)
+ if (pjlink->debug)
printf(" ai64 += %lld\n", num);
break;
@@ -143,7 +126,7 @@ static jlif_result lnkConst_integer(jlink *pjlink, long long num)
clink->value.pmem = buf;
clink->value.pdoubles[clink->nElems] = num;
- IFDEBUG(12)
+ if (pjlink->debug)
printf(" af64 += %lld\n", num);
break;
@@ -160,9 +143,6 @@ static jlif_result lnkConst_integer(jlink *pjlink, long long num)
static jlif_result lnkConst_boolean(jlink *pjlink, int val)
{
- IFDEBUG(10)
- printf("lnkConst_boolean(const@%p, %d)\n", pjlink, val);
-
return lnkConst_integer(pjlink, val);
}
@@ -171,9 +151,6 @@ static jlif_result lnkConst_double(jlink *pjlink, double num)
const_link *clink = CONTAINER(pjlink, const_link, jlink);
int newElems = clink->nElems + 1;
- IFDEBUG(10)
- printf("lnkConst_double(const@%p, %g)\n", pjlink, num);
-
switch (clink->type) {
epicsFloat64 *f64buf;
int i;
@@ -225,9 +202,6 @@ static jlif_result lnkConst_string(jlink *pjlink, const char *val, size_t len)
const_link *clink = CONTAINER(pjlink, const_link, jlink);
int newElems = clink->nElems + 1;
- IFDEBUG(10)
- printf("lnkConst_string(const@%p, \"%.*s\")\n", clink, (int) len, val);
-
switch (clink->type) {
char **vec, *str;
@@ -275,9 +249,6 @@ static jlif_result lnkConst_start_array(jlink *pjlink)
{
const_link *clink = CONTAINER(pjlink, const_link, jlink);
- IFDEBUG(10)
- printf("lnkConst_start_array(const@%p)\n", pjlink);
-
if (clink->type != s0) {
errlogPrintf("lnkConst: Embedded array value\n");
return jlif_stop;
@@ -289,17 +260,11 @@ static jlif_result lnkConst_start_array(jlink *pjlink)
static jlif_result lnkConst_end_array(jlink *pjlink)
{
- IFDEBUG(10)
- printf("lnkConst_end_array(const@%p)\n", pjlink);
-
return jlif_continue;
}
static struct lset* lnkConst_get_lset(const jlink *pjlink)
{
- IFDEBUG(10)
- printf("lnkConst_get_lset(const@%p)\n", pjlink);
-
return &lnkConst_lset;
}
@@ -327,9 +292,6 @@ static void lnkConst_report(const jlink *pjlink, int level, int indent)
};
const char * const dtype = type_names[clink->type & 3];
- IFDEBUG(10)
- printf("lnkConst_report(const@%p)\n", clink);
-
if (clink->type > a0) {
const char * const plural = clink->nElems > 1 ? "s" : "";
@@ -391,11 +353,6 @@ static void lnkConst_report(const jlink *pjlink, int level, int indent)
static void lnkConst_remove(struct dbLocker *locker, struct link *plink)
{
- const_link *clink = CONTAINER(plink->value.json.jlink, const_link, jlink);
-
- IFDEBUG(10)
- printf("lnkConst_remove(const@%p)\n", clink);
-
lnkConst_free(plink->value.json.jlink);
}
@@ -404,55 +361,51 @@ static long lnkConst_loadScalar(struct link *plink, short dbrType, void *pbuffer
const_link *clink = CONTAINER(plink->value.json.jlink, const_link, jlink);
long status;
- IFDEBUG(10)
- printf("lnkConst_loadScalar(const@%p, %d, %p)\n",
- clink, dbrType, pbuffer);
-
switch (clink->type) {
case si64:
- IFDEBUG(12)
+ if (clink->jlink.debug)
printf(" si64 %lld\n", clink->value.scalar_integer);
status = dbFastPutConvertRoutine[DBF_INT64][dbrType]
(&clink->value.scalar_integer, pbuffer, NULL);
break;
case sf64:
- IFDEBUG(12)
+ if (clink->jlink.debug)
printf(" sf64 %g\n", clink->value.scalar_double);
status = dbFastPutConvertRoutine[DBF_DOUBLE][dbrType]
(&clink->value.scalar_double, pbuffer, NULL);
break;
case sc40:
- IFDEBUG(12)
+ if (clink->jlink.debug)
printf(" sc40 '%s'\n", clink->value.scalar_string);
status = dbFastPutConvertRoutine[DBF_STRING][dbrType]
(clink->value.scalar_string, pbuffer, NULL);
break;
case ai64:
- IFDEBUG(12)
+ if (clink->jlink.debug)
printf(" ai64 [%lld, ...]\n", clink->value.pintegers[0]);
status = dbFastPutConvertRoutine[DBF_INT64][dbrType]
(clink->value.pintegers, pbuffer, NULL);
break;
case af64:
- IFDEBUG(12)
+ if (clink->jlink.debug)
printf(" af64 [%g, ...]\n", clink->value.pdoubles[0]);
status = dbFastPutConvertRoutine[DBF_DOUBLE][dbrType]
(clink->value.pdoubles, pbuffer, NULL);
break;
case ac40:
- IFDEBUG(12)
+ if (clink->jlink.debug)
printf(" ac40 ['%s', ...]\n", clink->value.pstrings[0]);
status = dbFastPutConvertRoutine[DBF_STRING][dbrType]
(clink->value.pstrings[0], pbuffer, NULL);
break;
default:
- IFDEBUG(12)
+ if (clink->jlink.debug)
printf(" Bad type %d\n", clink->type);
status = S_db_badField;
break;
@@ -467,27 +420,23 @@ static long lnkConst_loadLS(struct link *plink, char *pbuffer, epicsUInt32 size,
const_link *clink = CONTAINER(plink->value.json.jlink, const_link, jlink);
const char *pstr;
- IFDEBUG(10)
- printf("lnkConst_loadLS(const@%p, %p, %d, %d)\n",
- clink, pbuffer, size, *plen);
-
if(!size) return 0;
switch (clink->type) {
case sc40:
- IFDEBUG(12)
+ if (clink->jlink.debug)
printf(" sc40 '%s'\n", clink->value.scalar_string);
pstr = clink->value.scalar_string;
break;
case ac40:
- IFDEBUG(12)
+ if (clink->jlink.debug)
printf(" ac40 ['%s', ...]\n", clink->value.pstrings[0]);
pstr = clink->value.pstrings[0];
break;
default:
- IFDEBUG(12)
+ if (clink->jlink.debug)
printf(" Bad type %d\n", clink->type);
return S_db_badField;
}
@@ -508,10 +457,6 @@ static long lnkConst_loadArray(struct link *plink, short dbrType, void *pbuffer,
FASTCONVERT conv;
long status;
- IFDEBUG(10)
- printf("lnkConst_loadArray(const@%p, %d, %p, (%ld))\n",
- clink, dbrType, pbuffer, *pnReq);
-
if (nElems > *pnReq)
nElems = *pnReq;
@@ -519,28 +464,28 @@ static long lnkConst_loadArray(struct link *plink, short dbrType, void *pbuffer,
int i;
case si64:
- IFDEBUG(12)
+ if (clink->jlink.debug)
printf(" si64 %lld\n", clink->value.scalar_integer);
status = dbFastPutConvertRoutine[DBF_INT64][dbrType]
(&clink->value.scalar_integer, pdest, NULL);
break;
case sf64:
- IFDEBUG(12)
+ if (clink->jlink.debug)
printf(" sf64 %g\n", clink->value.scalar_double);
status = dbFastPutConvertRoutine[DBF_DOUBLE][dbrType]
(&clink->value.scalar_double, pdest, NULL);
break;
case sc40:
- IFDEBUG(12)
+ if (clink->jlink.debug)
printf(" sc40 '%s'\n", clink->value.scalar_string);
status = dbFastPutConvertRoutine[DBF_STRING][dbrType]
(clink->value.scalar_string, pbuffer, NULL);
break;
case ai64:
- IFDEBUG(12)
+ if (clink->jlink.debug)
printf(" ai64 [%lld, ...]\n", clink->value.pintegers[0]);
conv = dbFastPutConvertRoutine[DBF_INT64][dbrType];
for (i = 0; i < nElems; i++) {
@@ -551,7 +496,7 @@ static long lnkConst_loadArray(struct link *plink, short dbrType, void *pbuffer,
break;
case af64:
- IFDEBUG(12)
+ if (clink->jlink.debug)
printf(" af64 [%g, ...]\n", clink->value.pdoubles[0]);
conv = dbFastPutConvertRoutine[DBF_DOUBLE][dbrType];
for (i = 0; i < nElems; i++) {
@@ -562,7 +507,7 @@ static long lnkConst_loadArray(struct link *plink, short dbrType, void *pbuffer,
break;
case ac40:
- IFDEBUG(12)
+ if (clink->jlink.debug)
printf(" ac40 ['%s', ...]\n", clink->value.pstrings[0]);
conv = dbFastPutConvertRoutine[DBF_STRING][dbrType];
for (i = 0; i < nElems; i++) {
@@ -573,7 +518,7 @@ static long lnkConst_loadArray(struct link *plink, short dbrType, void *pbuffer,
break;
default:
- IFDEBUG(12)
+ if (clink->jlink.debug)
printf(" Bad type %d\n", clink->type);
status = S_db_badField;
}
@@ -583,10 +528,6 @@ static long lnkConst_loadArray(struct link *plink, short dbrType, void *pbuffer,
static long lnkConst_getNelements(const struct link *plink, long *nelements)
{
- IFDEBUG(10)
- printf("lnkConst_getNelements(const@%p, (%ld))\n",
- plink->value.json.jlink, *nelements);
-
*nelements = 0;
return 0;
}
@@ -594,11 +535,6 @@ static long lnkConst_getNelements(const struct link *plink, long *nelements)
static long lnkConst_getValue(struct link *plink, short dbrType, void *pbuffer,
long *pnRequest)
{
- IFDEBUG(10)
- printf("lnkConst_getValue(const@%p, %d, %p, ... (%ld))\n",
- plink->value.json.jlink, dbrType, pbuffer,
- pnRequest ? *pnRequest : 0);
-
if (pnRequest)
*pnRequest = 0;
return 0;
diff --git a/src/std/link/lnkState.c b/src/std/link/lnkState.c
index 518a37029..b8791bd3b 100644
--- a/src/std/link/lnkState.c
+++ b/src/std/link/lnkState.c
@@ -35,11 +35,6 @@
typedef long (*FASTCONVERT)();
-int lnkState_debug;
-epicsExportAddress(int, lnkState_debug);
-
-#define IFDEBUG(n) if (lnkState_debug >= (n))
-
typedef struct state_link {
jlink jlink; /* embedded object */
char *name;
@@ -57,9 +52,6 @@ static jlink* lnkState_alloc(short dbfType)
{
state_link *slink;
- IFDEBUG(10)
- printf("lnkState_alloc(%d)\n", dbfType);
-
if (dbfType == DBF_FWDLINK) {
errlogPrintf("lnkState: DBF_FWDLINK not supported\n");
return NULL;
@@ -76,9 +68,6 @@ static jlink* lnkState_alloc(short dbfType)
slink->invert = 0;
slink->val = 0;
- IFDEBUG(10)
- printf("lnkState_alloc -> state@%p\n", slink);
-
return &slink->jlink;
}
@@ -86,9 +75,6 @@ static void lnkState_free(jlink *pjlink)
{
state_link *slink = CONTAINER(pjlink, struct state_link, jlink);
- IFDEBUG(10)
- printf("lnkState_free(state@%p)\n", slink);
-
free(slink->name);
free(slink);
}
@@ -97,9 +83,6 @@ static jlif_result lnkState_string(jlink *pjlink, const char *val, size_t len)
{
state_link *slink = CONTAINER(pjlink, struct state_link, jlink);
- IFDEBUG(10)
- printf("lnkState_string(state@%p, \"%.*s\")\n", slink, (int) len, val);
-
if (len > 1 && val[0] == '!') {
slink->invert = 1;
val++; len--;
@@ -111,9 +94,6 @@ static jlif_result lnkState_string(jlink *pjlink, const char *val, size_t len)
static struct lset* lnkState_get_lset(const jlink *pjlink)
{
- IFDEBUG(10)
- printf("lnkState_get_lset(state@%p)\n", pjlink);
-
return &lnkState_lset;
}
@@ -121,9 +101,6 @@ static void lnkState_report(const jlink *pjlink, int level, int indent)
{
state_link *slink = CONTAINER(pjlink, struct state_link, jlink);
- IFDEBUG(10)
- printf("lnkState_report(state@%p)\n", slink);
-
printf("%*s'state': \"%s\" = %s%s\n", indent, "",
slink->name, slink->invert ? "! " : "", slink->val ? "TRUE" : "FALSE");
}
@@ -135,9 +112,6 @@ static void lnkState_open(struct link *plink)
state_link *slink = CONTAINER(plink->value.json.jlink,
struct state_link, jlink);
- IFDEBUG(10)
- printf("lnkState_open(state@%p)\n", slink);
-
slink->state = dbStateCreate(slink->name);
}
@@ -146,9 +120,6 @@ static void lnkState_remove(struct dbLocker *locker, struct link *plink)
state_link *slink = CONTAINER(plink->value.json.jlink,
struct state_link, jlink);
- IFDEBUG(10)
- printf("lnkState_remove(state@%p)\n", slink);
-
free(slink->name);
free(slink);
@@ -157,24 +128,11 @@ static void lnkState_remove(struct dbLocker *locker, struct link *plink)
static int lnkState_getDBFtype(const struct link *plink)
{
- state_link *slink = CONTAINER(plink->value.json.jlink,
- struct state_link, jlink);
-
- IFDEBUG(10)
- printf("lnkState_getDBFtype(state@%p)\n", slink);
-
return DBF_SHORT;
}
static long lnkState_getElements(const struct link *plink, long *nelements)
{
- state_link *slink = CONTAINER(plink->value.json.jlink,
- struct state_link, jlink);
-
- IFDEBUG(10)
- printf("lnkState_getElements(state@%p, (%ld))\n",
- slink, *nelements);
-
*nelements = 1;
return 0;
}
@@ -184,19 +142,10 @@ static long lnkState_getValue(struct link *plink, short dbrType, void *pbuffer,
{
state_link *slink = CONTAINER(plink->value.json.jlink,
struct state_link, jlink);
- long status;
- short flag;
FASTCONVERT conv = dbFastPutConvertRoutine[DBR_SHORT][dbrType];
- IFDEBUG(10)
- printf("lnkState_getValue(state@%p, %d, ...)\n",
- slink, dbrType);
-
- flag = dbStateGet(slink->state);
- slink->val = slink->invert ^ flag;
- status = conv(&slink->val, pbuffer, NULL);
-
- return status;
+ slink->val = slink->invert ^ dbStateGet(slink->state);
+ return conv(&slink->val, pbuffer, NULL);
}
static long lnkState_putValue(struct link *plink, short dbrType,
@@ -207,10 +156,6 @@ static long lnkState_putValue(struct link *plink, short dbrType,
short val;
const char *pstr;
- IFDEBUG(10)
- printf("lnkState_putValue(state@%p, %d, ...)\n",
- slink, dbrType);
-
if (nRequest == 0)
return 0;
From 5796f717efd9c0fc35a7272a151d50c63e61b359 Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Sat, 2 Jun 2018 00:40:41 -0500
Subject: [PATCH 039/147] Update Release Notes with link-updates changes
---
documentation/RELEASE_NOTES.html | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html
index f5936bcc2..8be6a340e 100644
--- a/documentation/RELEASE_NOTES.html
+++ b/documentation/RELEASE_NOTES.html
@@ -17,6 +17,38 @@
-->
+Link type enhancements
+
+This release adds three new link types: "state", "debug" and "trace". The
+"state" link type gets and puts boolean values from/to the dbState library that
+was added in the 3.15.1 release. The "debug" link type sets the
+jlink::debug
flag in its child link, while the "trace" link type
+also causes the arguments and return values for all calls to the child link's
+jlif and lset routines to be printed on stdout. The debug flag can no longer be
+set using an info tag. The addition of the "trace" link type has allowed over
+200 lines of conditional diagnostic printf() calls to be removed from the other
+link types.
+
+The "calc" link type can now be used for output links as well as input links.
+This allows modification of the output value and even combining it with values
+from other input links. See the separate JSON Link types document for
+details.
+
+A new start_child()
method was added to the end of the jlif
+interface table.
+
+The lset
methods have now been properly documented in the
+dbLink.h header file using Doxygen annotations, although we do not run Doxygen
+on the source tree yet to generate API documentation.
+
+Link types that utilize child links must now indicate whether the child will
+be used for input, output or forward linking by the return value from its
+parse_start_map()
method. The jlif_key_result
enum now
+contains 3 values jlif_key_child_inlink
,
+jlif_key_child_outlink
and jlif_key_child_fwdlink
+instead of the single jlif_key_child_link
that was previously used
+for this.
+
Restore use of ledlib for VxWorks command editing
The epicsReadline refactoring work described below unfortunately disabled the
From c6c25ab43d7d0ffd87077b37fbacc2b4154ae5f5 Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Sat, 2 Jun 2018 23:28:20 -0500
Subject: [PATCH 040/147] New src/std/link/test directory with tests for the
state link type
---
src/Makefile | 6 +-
src/std/link/test/Makefile | 53 +++++++++++
src/std/link/test/epicsRunLinkTests.c | 28 ++++++
src/std/link/test/ioRecord.c | 22 +++++
src/std/link/test/ioRecord.db | 1 +
src/std/link/test/ioRecord.dbd | 14 +++
src/std/link/test/lnkStateTest.c | 130 ++++++++++++++++++++++++++
src/std/link/test/rtemsTestHarness.c | 14 +++
8 files changed, 266 insertions(+), 2 deletions(-)
create mode 100644 src/std/link/test/Makefile
create mode 100644 src/std/link/test/epicsRunLinkTests.c
create mode 100644 src/std/link/test/ioRecord.c
create mode 100644 src/std/link/test/ioRecord.db
create mode 100644 src/std/link/test/ioRecord.dbd
create mode 100644 src/std/link/test/lnkStateTest.c
create mode 100644 src/std/link/test/rtemsTestHarness.c
diff --git a/src/Makefile b/src/Makefile
index 257099840..482e14843 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -4,7 +4,7 @@
# 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.
#*************************************************************************
TOP = ..
@@ -72,9 +72,11 @@ std_DEPEND_DIRS = ioc libCom/RTEMS
DIRS += std/filters/test
std/filters/test_DEPEND_DIRS = std
+DIRS += std/link/test
+std/link/test_DEPEND_DIRS = std
+
DIRS += std/rec/test
std/rec/test_DEPEND_DIRS = std
include $(TOP)/configure/RULES_DIRS
-
diff --git a/src/std/link/test/Makefile b/src/std/link/test/Makefile
new file mode 100644
index 000000000..30aec6038
--- /dev/null
+++ b/src/std/link/test/Makefile
@@ -0,0 +1,53 @@
+#*************************************************************************
+# Copyright (c) 2018 UChicago Argonne LLC, as Operator of Argonne
+# National Laboratory.
+# EPICS BASE is distributed subject to a Software License Agreement found
+# in the file LICENSE that is included with this distribution.
+#*************************************************************************
+TOP=../../../..
+
+include $(TOP)/configure/CONFIG
+
+TESTLIBRARY = Recs
+
+Recs_SRCS += ioRecord.c
+Recs_LIBS += dbCore ca Com
+
+PROD_LIBS = Recs dbRecStd dbCore ca Com
+
+DBDDEPENDS_FILES += linkTest.dbd$(DEP)
+TARGETS += $(COMMON_DIR)/linkTest.dbd
+linkTest_DBD += menuGlobal.dbd
+linkTest_DBD += menuConvert.dbd
+linkTest_DBD += menuScan.dbd
+linkTest_DBD += links.dbd
+linkTest_DBD += ioRecord.dbd
+TESTFILES += $(COMMON_DIR)/linkTest.dbd
+
+testHarness_SRCS += linkTest_registerRecordDeviceDriver.cpp
+
+TESTPROD_HOST += lnkStateTest
+lnkStateTest_SRCS += lnkStateTest.c
+lnkStateTest_SRCS += linkTest_registerRecordDeviceDriver.cpp
+testHarness_SRCS += lnkStateTest.c
+TESTFILES += ../ioRecord.db
+TESTS += lnkStateTest
+
+# epicsRunLinkTests runs all the test programs in a known working order.
+testHarness_SRCS += epicsRunLinkTests.c
+
+linkTestHarness_SRCS += $(testHarness_SRCS)
+linkTestHarness_SRCS_RTEMS += rtemsTestHarness.c
+
+PROD_vxWorks = linkTestHarness
+PROD_RTEMS = linkTestHarness
+
+TESTSPEC_vxWorks = linkTestHarness.munch; epicsRunLinkTests
+TESTSPEC_RTEMS = linkTestHarness.boot; epicsRunLinkTests
+
+TESTSCRIPTS_HOST += $(TESTS:%=%.t)
+
+include $(TOP)/configure/RULES
+
+ioRecord$(DEP): $(COMMON_DIR)/ioRecord.h
+lnkStateTest$(DEP): $(COMMON_DIR)/ioRecord.h
diff --git a/src/std/link/test/epicsRunLinkTests.c b/src/std/link/test/epicsRunLinkTests.c
new file mode 100644
index 000000000..2cfc7a8a0
--- /dev/null
+++ b/src/std/link/test/epicsRunLinkTests.c
@@ -0,0 +1,28 @@
+/*************************************************************************\
+* Copyright (c) 2018 UChicago Argonne LLC, as Operator of Argonne
+* National Laboratory.
+* EPICS BASE is distributed subject to a Software License Agreement found
+* in the file LICENSE that is included with this distribution.
+\*************************************************************************/
+
+/*
+ * Run filter tests as a batch.
+ */
+
+#include "epicsUnitTest.h"
+#include "epicsExit.h"
+#include "dbmf.h"
+
+int lnkStateTest(void);
+int lnkCalcTest(void);
+
+void epicsRunLinkTests(void)
+{
+ testHarness();
+
+ runTest(lnkStateTest);
+
+ dbmfFreeChunks();
+
+ epicsExit(0); /* Trigger test harness */
+}
diff --git a/src/std/link/test/ioRecord.c b/src/std/link/test/ioRecord.c
new file mode 100644
index 000000000..1807c9171
--- /dev/null
+++ b/src/std/link/test/ioRecord.c
@@ -0,0 +1,22 @@
+/*************************************************************************\
+* Copyright (c) 2018 UChicago Argonne LLC, as Operator of Argonne
+* National Laboratory.
+* EPICS BASE is distributed subject to a Software License Agreement found
+* in the file LICENSE that is included with this distribution.
+ \*************************************************************************/
+
+/*
+ * Author: Andrew Johnson
+ */
+
+#include
+#include
+
+#define GEN_SIZE_OFFSET
+#include "ioRecord.h"
+#undef GEN_SIZE_OFFSET
+
+#include
+
+static rset ioRSET;
+epicsExportAddress(rset,ioRSET);
diff --git a/src/std/link/test/ioRecord.db b/src/std/link/test/ioRecord.db
new file mode 100644
index 000000000..7a95a1025
--- /dev/null
+++ b/src/std/link/test/ioRecord.db
@@ -0,0 +1 @@
+record(io, io) {}
diff --git a/src/std/link/test/ioRecord.dbd b/src/std/link/test/ioRecord.dbd
new file mode 100644
index 000000000..efaec10a0
--- /dev/null
+++ b/src/std/link/test/ioRecord.dbd
@@ -0,0 +1,14 @@
+# This is a soft record type with both input and output links
+
+recordtype(io) {
+ include "dbCommon.dbd"
+ field(VAL, DBF_LONG) {
+ prompt("Value")
+ }
+ field(INPUT, DBF_INLINK) {
+ prompt("Input Link")
+ }
+ field(OUTPUT, DBF_OUTLINK) {
+ prompt("Output Link")
+ }
+}
diff --git a/src/std/link/test/lnkStateTest.c b/src/std/link/test/lnkStateTest.c
new file mode 100644
index 000000000..a2d514e6b
--- /dev/null
+++ b/src/std/link/test/lnkStateTest.c
@@ -0,0 +1,130 @@
+/*************************************************************************\
+* Copyright (c) 2018 Andrew Johnson
+* EPICS BASE is distributed subject to a Software License Agreement found
+* in the file LICENSE that is included with this distribution.
+\*************************************************************************/
+
+#include
+
+#include "dbAccess.h"
+#include "alarm.h"
+#include "dbUnitTest.h"
+#include "errlog.h"
+#include "epicsThread.h"
+#include "dbLink.h"
+#include "dbState.h"
+#include "ioRecord.h"
+
+#include "testMain.h"
+
+void linkTest_registerRecordDeviceDriver(struct dbBase *);
+
+static void startTestIoc(const char *dbfile)
+{
+ testdbPrepare();
+ testdbReadDatabase("linkTest.dbd", NULL, NULL);
+ linkTest_registerRecordDeviceDriver(pdbbase);
+ testdbReadDatabase(dbfile, NULL, NULL);
+
+ eltc(0);
+ testIocInitOk();
+ eltc(1);
+}
+
+static void testState()
+{
+ dbStateId red;
+ ioRecord *pio;
+ DBLINK *pinp, *pout;
+ long status;
+
+ testDiag("testing lnkState");
+
+ startTestIoc("ioRecord.db");
+
+ pio = (ioRecord *) testdbRecordPtr("io");
+ pinp = &pio->input;
+ pout = &pio->output;
+
+ red = dbStateFind("red");
+ testOk(!red, "No state red exists");
+
+ testdbPutFieldOk("io.INPUT", DBF_STRING, "{\"state\":\"red\"}");
+ if (testOk1(pinp->type == JSON_LINK))
+ testDiag("Link was set to '%s'", pinp->value.json.string);
+ red = dbStateFind("red");
+ testOk(!!red, "state red exists");
+
+ {
+ epicsInt16 i16;
+
+ dbStateSet(red);
+ status = dbGetLink(pinp, DBF_SHORT, &i16, NULL, NULL);
+ testOk(!status, "dbGetLink succeeded");
+ testOk(i16, "Got TRUE");
+
+ testdbPutFieldOk("io.INPUT", DBF_STRING, "{\"state\":\"!red\"}");
+ if (testOk1(pinp->type == JSON_LINK))
+ testDiag("Link was set to '%s'", pinp->value.json.string);
+
+ status = dbGetLink(pinp, DBF_SHORT, &i16, NULL, NULL);
+ testOk(!status, "dbGetLink succeeded");
+ testOk(!i16, "Got FALSE");
+
+ testdbPutFieldOk("io.OUTPUT", DBF_STRING, "{\"state\":\"red\"}");
+ if (testOk1(pout->type == JSON_LINK))
+ testDiag("Link was set to '%s'", pout->value.json.string);
+
+ i16 = 0;
+ status = dbPutLink(pout, DBF_SHORT, &i16, 1);
+ testOk(!status, "dbPutLink %d succeeded", i16);
+ testOk(!dbStateGet(red), "state was cleared");
+
+ i16 = 0x8000;
+ status = dbPutLink(pout, DBF_SHORT, &i16, 1);
+ testOk(!status, "dbPutLink 0x%hx succeeded", i16);
+ testOk(dbStateGet(red), "state was set");
+ }
+
+ status = dbPutLink(pout, DBF_STRING, "", 1);
+ testOk(!status, "dbPutLink '' succeeded");
+ testOk(!dbStateGet(red), "state was cleared");
+
+ status = dbPutLink(pout, DBF_STRING, "FALSE", 1); /* Not really... */
+ testOk(!status, "dbPutLink 'FALSE' succeeded");
+ testOk(dbStateGet(red), "state was set");
+
+ status = dbPutLink(pout, DBF_STRING, "0", 1);
+ testOk(!status, "dbPutLink '0' succeeded");
+ testOk(!dbStateGet(red), "state was cleared");
+
+ {
+ epicsFloat64 f64 = 0.1;
+
+ status = dbPutLink(pout, DBF_DOUBLE, &f64, 1);
+ testOk(!status, "dbPutLink %g succeeded", f64);
+ testOk(dbStateGet(red), "state was set");
+
+ testdbPutFieldOk("io.OUTPUT", DBF_STRING, "{\"state\":\"!red\"}");
+ if (testOk1(pout->type == JSON_LINK))
+ testDiag("Link was set to '%s'", pout->value.json.string);
+
+ status = dbPutLink(pout, DBF_DOUBLE, &f64, 1);
+ testOk(!status, "dbPutLink %g succeeded", f64);
+ testOk(!dbStateGet(red), "state was cleared");
+ }
+
+ testIocShutdownOk();
+
+ testdbCleanup();
+}
+
+
+MAIN(lnkStateTest)
+{
+ testPlan(0);
+
+ testState();
+
+ return testDone();
+}
diff --git a/src/std/link/test/rtemsTestHarness.c b/src/std/link/test/rtemsTestHarness.c
new file mode 100644
index 000000000..7397f74d6
--- /dev/null
+++ b/src/std/link/test/rtemsTestHarness.c
@@ -0,0 +1,14 @@
+/*************************************************************************\
+* Copyright (c) 2018 UChicago Argonne LLC, as Operator of Argonne
+* National Laboratory.
+* EPICS BASE is distributed subject to a Software License Agreement found
+* in the file LICENSE that is included with this distribution.
+\*************************************************************************/
+
+extern void epicsRunLinkTests(void);
+
+int main(int argc, char **argv)
+{
+ epicsRunLinkTests(); /* calls epicsExit(0) */
+ return 0;
+}
From bcfdc8d3688e92cc4e99a7d9afc956c687eee49c Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Sat, 2 Jun 2018 23:59:14 -0500
Subject: [PATCH 041/147] lnkStateTest: set testPlan
---
src/std/link/test/lnkStateTest.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/std/link/test/lnkStateTest.c b/src/std/link/test/lnkStateTest.c
index a2d514e6b..ba686d9e4 100644
--- a/src/std/link/test/lnkStateTest.c
+++ b/src/std/link/test/lnkStateTest.c
@@ -122,7 +122,7 @@ static void testState()
MAIN(lnkStateTest)
{
- testPlan(0);
+ testPlan(28);
testState();
From ffe6fceffaa24f8cefdae05bb91a8ba36bd4cce8 Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Sun, 3 Jun 2018 10:01:33 -0500
Subject: [PATCH 042/147] dbJLink: Some extra checks at parse/init time
---
src/ioc/db/dbJLink.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/src/ioc/db/dbJLink.c b/src/ioc/db/dbJLink.c
index 1c448dd4d..3acf75660 100644
--- a/src/ioc/db/dbJLink.c
+++ b/src/ioc/db/dbJLink.c
@@ -207,7 +207,8 @@ static int dbjl_start_map(void *ctx) {
parser->dbfType = DBF_FWDLINK;
result = jlif_continue;
break;
- case jlif_continue:
+ case jlif_key_stop:
+ case jlif_key_continue:
break;
default:
errlogPrintf("dbJLinkInit: Bad return %d from '%s'::parse_start_map()\n",
@@ -446,13 +447,14 @@ long dbJLinkParse(const char *json, size_t jlen, short dbfType,
long dbJLinkInit(struct link *plink)
{
- jlink *pjlink;
-
assert(plink);
- pjlink = plink->value.json.jlink;
- if (pjlink)
- plink->lset = pjlink->pif->get_lset(pjlink);
+ if (plink->type == JSON_LINK) {
+ jlink *pjlink = plink->value.json.jlink;
+
+ if (pjlink)
+ plink->lset = pjlink->pif->get_lset(pjlink);
+ }
dbLinkOpen(plink);
return 0;
From 36f23f3aece56990faa6cf43cbb8f15eccdd8417 Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Sun, 3 Jun 2018 10:46:29 -0500
Subject: [PATCH 043/147] lnkDebug fix: Initialize child link's precord pointer
---
src/std/link/lnkDebug.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/std/link/lnkDebug.c b/src/std/link/lnkDebug.c
index 9ede69cb2..96ce5e5c1 100644
--- a/src/std/link/lnkDebug.c
+++ b/src/std/link/lnkDebug.c
@@ -346,6 +346,7 @@ static void delegate_openLink(struct link *plink)
printf("Link trace: Calling %s::openLink(%p = jlink %p)\n",
dlink->child_jlif->name, clink, clink->value.json.jlink);
+ clink->precord = plink->precord;
clset->openLink(clink);
if (dlink->trace)
From 2fb46fc541bd07835c5820fe09bd3cd5ff8e78b6 Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Sun, 3 Jun 2018 11:03:20 -0500
Subject: [PATCH 044/147] lnkDebug: Fix typo in getAlarm range checks
---
src/std/link/lnkDebug.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/std/link/lnkDebug.c b/src/std/link/lnkDebug.c
index 96ce5e5c1..3238a0b62 100644
--- a/src/std/link/lnkDebug.c
+++ b/src/std/link/lnkDebug.c
@@ -684,10 +684,10 @@ static long delegate_getAlarm(const struct link *plink, epicsEnum16 *stat,
if (res == 0)
printf(" Got:%s%s%s%s\n",
stat ? " Status = " : "",
- stat && (*stat < ALARM_NSEV) ?
+ stat && (*stat < ALARM_NSTATUS) ?
epicsAlarmConditionStrings[*stat] : "Bad-status",
sevr ? " Severity = " : "",
- sevr && (*sevr < ALARM_NSTATUS) ?
+ sevr && (*sevr < ALARM_NSEV) ?
epicsAlarmSeverityStrings[*sevr] : "Bad-severity"
);
}
From 6e3aa77c42bd8f4b764b30d8a055ece6aeeb745d Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Sun, 3 Jun 2018 11:18:40 -0500
Subject: [PATCH 045/147] lnkCalc fix: Don't evaluate minor expression when
major returned true
---
src/std/link/lnkCalc.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/std/link/lnkCalc.c b/src/std/link/lnkCalc.c
index fa1a363fe..2ac568840 100644
--- a/src/std/link/lnkCalc.c
+++ b/src/std/link/lnkCalc.c
@@ -600,7 +600,7 @@ static long lnkCalc_getValue(struct link *plink, short dbrType, void *pbuffer,
}
}
- if (!status && clink->post_minor) {
+ if (!status && !clink->sevr && clink->post_minor) {
double alval = clink->val;
status = calcPerform(clink->arg, &alval, clink->post_minor);
@@ -664,7 +664,7 @@ static long lnkCalc_putValue(struct link *plink, short dbrType,
}
}
- if (!status && clink->post_minor) {
+ if (!status && !clink->sevr && clink->post_minor) {
double alval = clink->val;
status = calcPerform(clink->arg, &alval, clink->post_minor);
From 3b77d9be8cb3cf7e5e26339302b098155abcee16 Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Sun, 3 Jun 2018 12:34:19 -0500
Subject: [PATCH 046/147] lnkStateTest: Show status value in test output
---
src/std/link/test/lnkStateTest.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/src/std/link/test/lnkStateTest.c b/src/std/link/test/lnkStateTest.c
index ba686d9e4..d3da06f5c 100644
--- a/src/std/link/test/lnkStateTest.c
+++ b/src/std/link/test/lnkStateTest.c
@@ -60,7 +60,7 @@ static void testState()
dbStateSet(red);
status = dbGetLink(pinp, DBF_SHORT, &i16, NULL, NULL);
- testOk(!status, "dbGetLink succeeded");
+ testOk(!status, "dbGetLink succeeded (status = %ld)", status);
testOk(i16, "Got TRUE");
testdbPutFieldOk("io.INPUT", DBF_STRING, "{\"state\":\"!red\"}");
@@ -68,7 +68,7 @@ static void testState()
testDiag("Link was set to '%s'", pinp->value.json.string);
status = dbGetLink(pinp, DBF_SHORT, &i16, NULL, NULL);
- testOk(!status, "dbGetLink succeeded");
+ testOk(!status, "dbGetLink succeeded (status = %ld)", status);
testOk(!i16, "Got FALSE");
testdbPutFieldOk("io.OUTPUT", DBF_STRING, "{\"state\":\"red\"}");
@@ -77,32 +77,32 @@ static void testState()
i16 = 0;
status = dbPutLink(pout, DBF_SHORT, &i16, 1);
- testOk(!status, "dbPutLink %d succeeded", i16);
+ testOk(!status, "dbPutLink %d succeeded (status = %ld)", i16, status);
testOk(!dbStateGet(red), "state was cleared");
i16 = 0x8000;
status = dbPutLink(pout, DBF_SHORT, &i16, 1);
- testOk(!status, "dbPutLink 0x%hx succeeded", i16);
+ testOk(!status, "dbPutLink 0x%hx succeeded (status = %ld)", i16, status);
testOk(dbStateGet(red), "state was set");
}
status = dbPutLink(pout, DBF_STRING, "", 1);
- testOk(!status, "dbPutLink '' succeeded");
+ testOk(!status, "dbPutLink '' succeeded (status = %ld)", status);
testOk(!dbStateGet(red), "state was cleared");
status = dbPutLink(pout, DBF_STRING, "FALSE", 1); /* Not really... */
- testOk(!status, "dbPutLink 'FALSE' succeeded");
+ testOk(!status, "dbPutLink 'FALSE' succeeded (status = %ld)", status);
testOk(dbStateGet(red), "state was set");
status = dbPutLink(pout, DBF_STRING, "0", 1);
- testOk(!status, "dbPutLink '0' succeeded");
+ testOk(!status, "dbPutLink '0' succeeded (status = %ld)", status);
testOk(!dbStateGet(red), "state was cleared");
{
epicsFloat64 f64 = 0.1;
status = dbPutLink(pout, DBF_DOUBLE, &f64, 1);
- testOk(!status, "dbPutLink %g succeeded", f64);
+ testOk(!status, "dbPutLink %g succeeded (status = %ld)", f64, status);
testOk(dbStateGet(red), "state was set");
testdbPutFieldOk("io.OUTPUT", DBF_STRING, "{\"state\":\"!red\"}");
@@ -110,7 +110,7 @@ static void testState()
testDiag("Link was set to '%s'", pout->value.json.string);
status = dbPutLink(pout, DBF_DOUBLE, &f64, 1);
- testOk(!status, "dbPutLink %g succeeded", f64);
+ testOk(!status, "dbPutLink %g succeeded (status = %ld)", f64, status);
testOk(!dbStateGet(red), "state was cleared");
}
From b02944805996fa8dcf7856cae420a334d95b8beb Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Sun, 3 Jun 2018 12:35:56 -0500
Subject: [PATCH 047/147] Added lnkCalcTest
---
src/std/link/test/Makefile | 8 +-
src/std/link/test/epicsRunLinkTests.c | 1 +
src/std/link/test/lnkCalcTest.c | 164 ++++++++++++++++++++++++++
3 files changed, 172 insertions(+), 1 deletion(-)
create mode 100644 src/std/link/test/lnkCalcTest.c
diff --git a/src/std/link/test/Makefile b/src/std/link/test/Makefile
index 30aec6038..2a6507e07 100644
--- a/src/std/link/test/Makefile
+++ b/src/std/link/test/Makefile
@@ -23,6 +23,7 @@ linkTest_DBD += menuScan.dbd
linkTest_DBD += links.dbd
linkTest_DBD += ioRecord.dbd
TESTFILES += $(COMMON_DIR)/linkTest.dbd
+TESTFILES += ../ioRecord.db
testHarness_SRCS += linkTest_registerRecordDeviceDriver.cpp
@@ -30,9 +31,14 @@ TESTPROD_HOST += lnkStateTest
lnkStateTest_SRCS += lnkStateTest.c
lnkStateTest_SRCS += linkTest_registerRecordDeviceDriver.cpp
testHarness_SRCS += lnkStateTest.c
-TESTFILES += ../ioRecord.db
TESTS += lnkStateTest
+TESTPROD_HOST += lnkCalcTest
+lnkCalcTest_SRCS += lnkCalcTest.c
+lnkCalcTest_SRCS += linkTest_registerRecordDeviceDriver.cpp
+testHarness_SRCS += lnkCalcTest.c
+TESTS += lnkCalcTest
+
# epicsRunLinkTests runs all the test programs in a known working order.
testHarness_SRCS += epicsRunLinkTests.c
diff --git a/src/std/link/test/epicsRunLinkTests.c b/src/std/link/test/epicsRunLinkTests.c
index 2cfc7a8a0..a0f3b7c72 100644
--- a/src/std/link/test/epicsRunLinkTests.c
+++ b/src/std/link/test/epicsRunLinkTests.c
@@ -21,6 +21,7 @@ void epicsRunLinkTests(void)
testHarness();
runTest(lnkStateTest);
+ runTest(lnkCalcTest);
dbmfFreeChunks();
diff --git a/src/std/link/test/lnkCalcTest.c b/src/std/link/test/lnkCalcTest.c
new file mode 100644
index 000000000..c0d76dda3
--- /dev/null
+++ b/src/std/link/test/lnkCalcTest.c
@@ -0,0 +1,164 @@
+/*************************************************************************\
+* Copyright (c) 2018 Andrew Johnson
+* EPICS BASE is distributed subject to a Software License Agreement found
+* in the file LICENSE that is included with this distribution.
+\*************************************************************************/
+
+#include
+
+#include "dbAccess.h"
+#include "alarm.h"
+#include "dbUnitTest.h"
+#include "errlog.h"
+#include "epicsThread.h"
+#include "dbLink.h"
+#include "dbState.h"
+#include "recGbl.h"
+#include "testMain.h"
+#include "ioRecord.h"
+
+#define testPutLongStr(PV, VAL) \
+ testdbPutArrFieldOk(PV, DBF_CHAR, sizeof(VAL), VAL);
+
+void linkTest_registerRecordDeviceDriver(struct dbBase *);
+
+static void startTestIoc(const char *dbfile)
+{
+ testdbPrepare();
+ testdbReadDatabase("linkTest.dbd", NULL, NULL);
+ linkTest_registerRecordDeviceDriver(pdbbase);
+ testdbReadDatabase(dbfile, NULL, NULL);
+
+ eltc(0);
+ testIocInitOk();
+ eltc(1);
+}
+
+static void testCalc()
+{
+ ioRecord *pio;
+ DBLINK *pinp, *pout;
+ long status;
+ epicsFloat64 f64;
+
+ startTestIoc("ioRecord.db");
+
+ pio = (ioRecord *) testdbRecordPtr("io");
+ pinp = &pio->input;
+ pout = &pio->output;
+
+ testDiag("testing lnkCalc input");
+
+ {
+ dbStateId red;
+
+ testPutLongStr("io.INPUT", "{\"calc\":{"
+ "\"expr\":\"a\","
+ "\"args\":[{\"state\":\"red\"}]"
+ "}}");
+ if (testOk1(pinp->type == JSON_LINK))
+ testDiag("Link was set to '%s'", pinp->value.json.string);
+ red = dbStateFind("red");
+ testOk(!!red, "State red was created");
+
+ dbStateSet(red);
+ status = dbGetLink(pinp, DBF_DOUBLE, &f64, NULL, NULL);
+ testOk(!status, "dbGetLink succeeded (status = %ld)", status);
+ testOk(f64, "Got TRUE (%g)", f64);
+
+ dbStateClear(red);
+ status = dbGetLink(pinp, DBF_DOUBLE, &f64, NULL, NULL);
+ testOk(!status, "dbGetLink succeeded (status = %ld)", status);
+ testOk(!f64, "Got FALSE (%g)", f64);
+ }
+
+ {
+ dbStateId major = dbStateCreate("major");
+ dbStateId minor = dbStateCreate("minor");
+ epicsEnum16 stat, sevr;
+
+ testPutLongStr("io.INPUT", "{\"calc\":{"
+ "\"expr\":\"0\","
+ "\"major\":\"A\","
+ "\"minor\":\"B\","
+ "\"args\":[{\"state\":\"major\"},{\"state\":\"minor\"}]"
+ "}}");
+ if (testOk1(pinp->type == JSON_LINK))
+ testDiag("Link was set to '%s'", pinp->value.json.string);
+
+ dbStateSet(major);
+ dbStateSet(minor);
+ status = dbGetLink(pinp, DBF_DOUBLE, &f64, NULL, NULL);
+ testOk(!status, "dbGetLink succeeded (status = %ld)", status);
+ testOk(f64 == 0.0, "Got zero (%g)", f64);
+ testOk(recGblResetAlarms(pio) && DBE_ALARM, "Record alarm was raised");
+ status = dbGetAlarm(pinp, &stat, &sevr);
+ testOk(!status, "dbGetAlarm succeeded (status = %ld)", status);
+ testOk(stat == LINK_ALARM, "Alarm status = LINK (%d)", stat);
+ testOk(sevr == MAJOR_ALARM, "Alarm severity = MAJOR (%d)", sevr);
+
+ dbStateClear(major);
+ status = dbGetLink(pinp, DBF_DOUBLE, &f64, NULL, NULL);
+ testOk(!status, "dbGetLink succeeded (status = %ld)", status);
+ testOk(recGblResetAlarms(pio) && DBE_ALARM, "Record alarm was raised");
+ status = dbGetAlarm(pinp, &stat, &sevr);
+ testOk(!status, "dbGetAlarm succeeded (status = %ld)", status);
+ testOk(stat == LINK_ALARM, "Alarm status = LINK (%d)", stat);
+ testOk(sevr == MINOR_ALARM, "Alarm severity = MINOR (%d)", sevr);
+ }
+
+ testDiag("testing lnkCalc output");
+
+ {
+ dbStateId red = dbStateFind("red");
+ dbStateId out = dbStateCreate("out");
+
+ testPutLongStr("io.OUTPUT", "{\"calc\":{"
+ "\"expr\":\"!a\","
+ "\"out\":{\"state\":\"out\"},"
+ "\"args\":[{\"state\":\"red\"}],"
+ "\"units\":\"things\","
+ "\"prec\":3"
+ "}}");
+ if (testOk1(pout->type == JSON_LINK))
+ testDiag("Link was set to '%s'", pout->value.json.string);
+
+ dbStateSet(red);
+ f64 = 1.0;
+ status = dbPutLink(pout, DBF_DOUBLE, &f64, 1);
+ testOk(!status, "dbPutLink succeeded (status = %ld)", status);
+ testOk(!dbStateGet(out), "output was cleared");
+
+ dbStateClear(red);
+ status = dbPutLink(pout, DBF_DOUBLE, &f64, 1);
+ testOk(!status, "dbGetLink succeeded (status = %ld)", status);
+ testOk(dbStateGet(out), "output was set");
+ }
+
+ {
+ char units[20] = {0};
+ short prec = 0;
+
+ status = dbGetUnits(pout, units, sizeof(units));
+ testOk(!status, "dbGetUnits succeeded (status = %ld)", status);
+ testOk(!strcmp(units, "things"), "Units string correct (%s)", units);
+
+ status = dbGetPrecision(pout, &prec);
+ testOk(!status, "dbGetPrecision succeeded (status = %ld)", status);
+ testOk(prec == 3, "Precision correct (%d)", prec);
+ }
+
+ testIocShutdownOk();
+
+ testdbCleanup();
+}
+
+
+MAIN(lnkCalcTest)
+{
+ testPlan(0);
+
+ testCalc();
+
+ return testDone();
+}
From c0a7ab976c49e39f35919f639082ab00a49728c8 Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Mon, 4 Jun 2018 15:27:01 -0500
Subject: [PATCH 048/147] Fix warnings from clang
---
src/std/link/lnkDebug.c | 2 +-
src/std/link/test/lnkCalcTest.c | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/std/link/lnkDebug.c b/src/std/link/lnkDebug.c
index 3238a0b62..bd8f84e5a 100644
--- a/src/std/link/lnkDebug.c
+++ b/src/std/link/lnkDebug.c
@@ -882,7 +882,7 @@ static jlif_key_result lnkDebug_start_map(jlink *pjlink)
case DBF_FWDLINK:
return jlif_key_child_outlink;
}
- return jlif_stop;
+ return jlif_key_stop;
}
static jlif_result lnkDebug_end_map(jlink *pjlink)
diff --git a/src/std/link/test/lnkCalcTest.c b/src/std/link/test/lnkCalcTest.c
index c0d76dda3..3fe8382d4 100644
--- a/src/std/link/test/lnkCalcTest.c
+++ b/src/std/link/test/lnkCalcTest.c
@@ -91,7 +91,7 @@ static void testCalc()
status = dbGetLink(pinp, DBF_DOUBLE, &f64, NULL, NULL);
testOk(!status, "dbGetLink succeeded (status = %ld)", status);
testOk(f64 == 0.0, "Got zero (%g)", f64);
- testOk(recGblResetAlarms(pio) && DBE_ALARM, "Record alarm was raised");
+ testOk(recGblResetAlarms(pio) & DBE_ALARM, "Record alarm was raised");
status = dbGetAlarm(pinp, &stat, &sevr);
testOk(!status, "dbGetAlarm succeeded (status = %ld)", status);
testOk(stat == LINK_ALARM, "Alarm status = LINK (%d)", stat);
@@ -100,7 +100,7 @@ static void testCalc()
dbStateClear(major);
status = dbGetLink(pinp, DBF_DOUBLE, &f64, NULL, NULL);
testOk(!status, "dbGetLink succeeded (status = %ld)", status);
- testOk(recGblResetAlarms(pio) && DBE_ALARM, "Record alarm was raised");
+ testOk(recGblResetAlarms(pio) & DBE_ALARM, "Record alarm was raised");
status = dbGetAlarm(pinp, &stat, &sevr);
testOk(!status, "dbGetAlarm succeeded (status = %ld)", status);
testOk(stat == LINK_ALARM, "Alarm status = LINK (%d)", stat);
From 8f55a1307d93bc72681053b1ede5270dd9bdbf7e Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Fri, 22 Jun 2018 14:54:06 -0500
Subject: [PATCH 049/147] startup: Update win*.bat files
---
startup/win32.bat | 128 ++++++++++----------------------------------
startup/windows.bat | 73 +++++++++++++++++++++++++
2 files changed, 100 insertions(+), 101 deletions(-)
create mode 100755 startup/windows.bat
diff --git a/startup/win32.bat b/startup/win32.bat
index af9155dd7..575b06f42 100644
--- a/startup/win32.bat
+++ b/startup/win32.bat
@@ -1,147 +1,73 @@
@ECHO OFF
REM *************************************************************************
-REM Copyright (c) 2002 The University of Chicago, as Operator of Argonne
+REM Copyright (c) 2017 UChicago Argonne LLC, as Operator of Argonne
REM National Laboratory.
REM Copyright (c) 2002 The Regents of the University of California, as
REM Operator of Los Alamos National Laboratory.
-REM EPICS BASE Versions 3.13.7
-REM and higher are distributed subject to a Software License Agreement found
+REM EPICS BASE is distributed subject to a Software License Agreement found
REM in file LICENSE that is included with this distribution.
REM *************************************************************************
REM
-REM Site-specific EPICS environment settings
-REM
-REM sites should modify these definitions
+REM EPICS build configuration environment settings
+REM
+REM Installers should modify these definitions as appropriate.
+REM This file configures the PATH variable from scratch.
REM ======================================================
REM ====== REQUIRED ENVIRONMENT VARIABLES FOLLOW ======
REM ======================================================
REM ======================================================
-REM ---------------- WINDOWS ---------------------------
+REM ---------------- WINDOWS -------------------------
REM ======================================================
-REM ----- WIN95 -----
-REM set PATH=C:\WINDOWS;C:\WINDOWS\COMMAND
-REM ----- WINNT, WIN2000 -----
-REM set PATH=C:\WINNT;C:\WINNT\SYSTEM32
REM ----- WINXP, Vista, Windows 7 -----
-set PATH=C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\SYSTEM32\Wbem
+set PATH=C:\Windows\System32;C:\Windows;C:\Windows\System32\Wbem
REM ======================================================
-REM ---------------- make and perl ---------------------
+REM --------------- Strawberry Perl ------------------
REM ======================================================
-REM --------------- ActiveState perl -------------------
-set PATH=C:\Perl\bin;%PATH%
-
-REM --------------- mingw make ------------------------
-REM set PATH=C:\mingw-make\bin;%PATH%
-REM set PATH=C:\mingw-make82-3\bin;%PATH%
-
-REM --------------- gnuwin32 make ----------------------
-set PATH=C:\gnuwin32\bin;%PATH%
+set PATH=C:\Strawberry\perl\bin;%PATH%
+set PATH=C:\Strawberry\perl\site\bin;%PATH%
+set PATH=C:\Strawberry\c\bin;%PATH%
REM ======================================================
-REM ---------------- cygwin tools ------------------------
+REM --------------- Visual C++ -----------------------
REM ======================================================
-REM (make & perl if above perl and make are REMs)
-REM Dont use cygwin GNU make and Perl!
-REM cygwin contains tk/tcl, vim, perl, and many unix tools
-REM need grep from here NOT from cvs directory
-REM set PATH=%PATH%;.;..
-REM set PATH=%PATH%;c:\cygwin\bin
-
-REM ======================================================
-REM --------------- Visual c++ -------------------------
-REM ======================================================
-
-REM ------ Microsoft Visual Studio 2005 ------
-REM call "C:\Program files\Microsoft Visual Studio 8\VC\vcvarsall.bat" x86_amd64
-REM set PATH=%PATH%;C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin
-REM set INCLUDE=%INCLUDE%;C:\Program Files\Microsoft SDKs\Windows\v6.0A\include
-REM REM set LIBPATH=%LIBPATH%;C:\Program Files\Microsoft SDKs\Windows\v6.0A\lib
-REM set LIB=%LIB%;C:\Program Files\Microsoft SDKs\Windows\v6.0A\lib
-
-REM ------ Microsoft Visual Studio 2008 ------
-REM call "C:\Program files\Microsoft Visual Studio 9.0\VC\bin\vcvars32.bat"
-REM call "C:\Program files\Microsoft Visual Studio 9.0\VC\vcvarsall.bat" x86_amd64
-REM set PATH=C:\Program Files\Microsoft SDKs\Windows\v7.0\bin;%PATH%
-REM set INCLUDE=C:\Program Files\Microsoft SDKs\Windows\v7.0\include;%INCLUDE%
-REM set LIBPATH=C:\Program Files\Microsoft SDKs\Windows\v7.0\lib;%LIBPATH%
-REM set LIB=C:\Program Files\Microsoft SDKs\Windows\v7.0\lib;%LIB%
-
-REM ----- Visual Studion 2010 -----
-REM -- windows-x64 ---
-REM call "C:\Program files\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x64
REM -- win32-x86 ---
-call "C:\Program files\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x86
+
+REM ----- Visual Studio 2010 -----
+REM call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x86
+
+REM ----- Visual Studio 2015 -----
+call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86
REM ======================================================
-REM --------------- EPICS --------------------------------
+REM --------------- EPICS Base -----------------------
REM ======================================================
-REM set EPICS_HOST_ARCH=windows-x64
set EPICS_HOST_ARCH=win32-x86
set PATH=%PATH%;G:\epics\base\bin\%EPICS_HOST_ARCH%
-set PATH=%PATH%;G:\epics\extensions\bin\%EPICS_HOST_ARCH%
REM ======================================================
-REM ------- OPTIONAL ENVIRONMENT VARIABLES FOLLOW --------
+REM ====== OPTIONAL ENVIRONMENT VARIABLES FOLLOW =====
REM ======================================================
REM ======================================================
-REM ----------------- remote CVS -------------------------
+REM --------------------- Git ------------------------
REM ======================================================
-REM set CVS_RSH=c:/cygwin/bin/ssh.exe
-REM set CVSROOT=:ext:jba@aps.anl.gov:/usr/local/epicsmgr/cvsroot
-REM set HOME=c:/users/%USERNAME%
-REM set HOME=c:/users/jba
+set PATH=%PATH%;C:\Program files\Git
REM ======================================================
-REM ------------------- Bazaar ---------------------------
+REM --------------- EPICS Extensions -----------------
REM ======================================================
-set PATH=%PATH%;C:\Program files\Bazaar
+REM set PATH=%PATH%;G:\epics\extensions\bin\%EPICS_HOST_ARCH%
REM ======================================================
-REM ----------------- GNU make flags ---------------------
+REM --------------- Exceed ---------------------------
REM ======================================================
-set MAKEFLAGS=-w
-
-REM ======================================================
-REM -------------- vim (use cygwin vim ) -----------------
-REM ======================================================
-REM HOME needed by vim to write .viminfo file.
-REM VIM needed by vim to find _vimrc file.
-REM set VIM=c:\cygwin
-
-REM ======================================================
-REM --------------- Epics Channel Access -----------------
-REM Modify and uncomment the following lines
-REM to override the base/configure/CONFIG_ENV defaults
-REM ======================================================
-REM set EPICS_CA_ADDR_LIST=n.n.n.n n.n.n.n
-REM set EPICS_CA_AUTO_ADDR_LIST=YES
-
-REM set EPICS_CA_CONN_TMO=30.0
-REM set EPICS_CA_BEACON_PERIOD=15.0
-REM set EPICS_CA_REPEATER_PORT=5065
-REM set EPICS_CA_SERVER_PORT=5064
-REM set EPICS_TS_MIN_WEST=420
-
-REM ======================================================
-REM --------------- JAVA ---------------------------------
-REM ======================================================
-REM Needed for java extensions
-REM set CLASSPATH=G:\epics\extensions\javalib
-REM set PATH=%PATH%;C:\j2sdk1.4.1_01\bin
-REM set CLASSPATH=%CLASSPATH%;C:\j2sdk1.4.1_01\lib\tools.jar
-
-REM ======================================================
-REM --------------- Exceed -------------------------------
REM Needed for X11 extensions
-REM ======================================================
-REM set EX_VER=7.10
-REM set EX_VER=12.00
REM set EX_VER=14.00
+REM set EX_VER=15.00
REM set PATH=%PATH%;C:\Exceed%EX_VER%\XDK\
REM set PATH=%PATH%;C:\Program Files\Hummingbird\Connectivity\%EX_VER%\Exceed\
diff --git a/startup/windows.bat b/startup/windows.bat
new file mode 100755
index 000000000..1b0d32eb2
--- /dev/null
+++ b/startup/windows.bat
@@ -0,0 +1,73 @@
+@ECHO OFF
+REM *************************************************************************
+REM Copyright (c) 2017 UChicago Argonne LLC, as Operator of Argonne
+REM National Laboratory.
+REM Copyright (c) 2002 The Regents of the University of California, as
+REM Operator of Los Alamos National Laboratory.
+REM EPICS BASE is distributed subject to a Software License Agreement found
+REM in file LICENSE that is included with this distribution.
+REM *************************************************************************
+REM
+REM EPICS build configuration environment settings
+REM
+REM Installers should modify these definitions as appropriate.
+REM This file configures the PATH variable from scratch.
+
+REM ======================================================
+REM ====== REQUIRED ENVIRONMENT VARIABLES FOLLOW =====
+REM ======================================================
+
+REM ======================================================
+REM ---------------- WINDOWS -------------------------
+REM ======================================================
+REM ----- WINXP, Vista, Windows 7 -----
+set PATH=C:\Windows\System32;C:\Windows;C:\Windows\System32\Wbem
+
+REM ======================================================
+REM --------------- Strawberry Perl ------------------
+REM ======================================================
+
+set PATH=C:\Strawberry\perl\bin;%PATH%
+set PATH=C:\Strawberry\perl\site\bin;%PATH%
+set PATH=C:\Strawberry\c\bin;%PATH%
+
+REM ======================================================
+REM --------------- Visual C++ -----------------------
+REM ======================================================
+REM -- windows-x64 ---
+
+REM ----- Visual Studio 2010 -----
+REM call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x64
+
+REM ----- Visual Studio 2015 -----
+call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64
+
+REM ======================================================
+REM --------------- EPICS Base -----------------------
+REM ======================================================
+set EPICS_HOST_ARCH=windows-x64
+set PATH=%PATH%;G:\epics\base\bin\%EPICS_HOST_ARCH%
+
+REM ======================================================
+REM ====== OPTIONAL ENVIRONMENT VARIABLES FOLLOW =====
+REM ======================================================
+
+REM ======================================================
+REM --------------------- Git ------------------------
+REM ======================================================
+set PATH=%PATH%;C:\Program files\Git
+
+REM ======================================================
+REM --------------- EPICS Extensions -----------------
+REM ======================================================
+REM set PATH=%PATH%;G:\epics\extensions\bin\%EPICS_HOST_ARCH%
+
+REM ======================================================
+REM --------------- Exceed ---------------------------
+REM ======================================================
+REM Needed for X11 extensions
+REM set EX_VER=14.00
+REM set EX_VER=15.00
+REM set PATH=%PATH%;C:\Exceed%EX_VER%\XDK\
+REM set PATH=%PATH%;C:\Program Files\Hummingbird\Connectivity\%EX_VER%\Exceed\
+
From dcb494b494674b330595599d53014f50b1236dd3 Mon Sep 17 00:00:00 2001
From: Michael Davidsaver
Date: Tue, 13 Mar 2018 16:40:01 -0700
Subject: [PATCH 050/147] rtemsttest generalize condition for individual tests
---
ci/travis-build.sh | 1 +
src/ioc/db/test/Makefile | 2 +-
src/libCom/test/Makefile | 2 +-
src/std/filters/test/Makefile | 2 +-
src/std/rec/test/Makefile | 2 +-
5 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/ci/travis-build.sh b/ci/travis-build.sh
index ba752ac4a..f487fbb88 100644
--- a/ci/travis-build.sh
+++ b/ci/travis-build.sh
@@ -72,6 +72,7 @@ RTEMS_BASE=/home/travis/.cache/rtems${RTEMS}-i386
EOF
cat << EOF >> configure/CONFIG_SITE
CROSS_COMPILER_TARGET_ARCHS+=RTEMS-pc386
+CROSS_COMPILER_RUNTEST_ARCHS+=RTEMS-pc386
EOF
# find local qemu-system-i386
diff --git a/src/ioc/db/test/Makefile b/src/ioc/db/test/Makefile
index baa381534..90ca9da35 100644
--- a/src/ioc/db/test/Makefile
+++ b/src/ioc/db/test/Makefile
@@ -184,7 +184,7 @@ TESTSPEC_vxWorks = dbTestHarness.munch; epicsRunDbTests
TESTSPEC_RTEMS = dbTestHarness.boot; epicsRunDbTests
TESTSCRIPTS_HOST += $(TESTS:%=%.t)
-ifeq ($(T_A),RTEMS-pc386)
+ifneq ($(filter $(T_A),$(CROSS_COMPILER_RUNTEST_ARCHS)),)
TESTPROD_RTEMS = $(TESTPROD_HOST)
TESTSCRIPTS_RTEMS += $(TESTS:%=%.t)
endif
diff --git a/src/libCom/test/Makefile b/src/libCom/test/Makefile
index b8014a2ab..a2ceb4ea4 100755
--- a/src/libCom/test/Makefile
+++ b/src/libCom/test/Makefile
@@ -235,7 +235,7 @@ TESTSPEC_vxWorks = libComTestHarness.munch; epicsRunLibComTests
TESTSPEC_RTEMS = libComTestHarness.boot; epicsRunLibComTests
TESTSCRIPTS_HOST += $(TESTS:%=%.t)
-ifeq ($(T_A),RTEMS-pc386)
+ifneq ($(filter $(T_A),$(CROSS_COMPILER_RUNTEST_ARCHS)),)
TESTPROD_RTEMS = $(TESTPROD_HOST)
TESTSCRIPTS_RTEMS += $(filter-out epicsUnitTestTest.t, $(TESTS:%=%.t))
endif
diff --git a/src/std/filters/test/Makefile b/src/std/filters/test/Makefile
index 6442ba332..d6d9973f6 100644
--- a/src/std/filters/test/Makefile
+++ b/src/std/filters/test/Makefile
@@ -71,7 +71,7 @@ TESTSPEC_vxWorks = filterTestHarness.munch; epicsRunFilterTests
TESTSPEC_RTEMS = filterTestHarness.boot; epicsRunFilterTests
TESTSCRIPTS_HOST += $(TESTS:%=%.t)
-ifeq ($(T_A),RTEMS-pc386)
+ifneq ($(filter $(T_A),$(CROSS_COMPILER_RUNTEST_ARCHS)),)
TESTPROD_RTEMS = $(TESTPROD_HOST)
TESTSCRIPTS_RTEMS += $(TESTS:%=%.t)
endif
diff --git a/src/std/rec/test/Makefile b/src/std/rec/test/Makefile
index f5f9b4312..14e10946c 100644
--- a/src/std/rec/test/Makefile
+++ b/src/std/rec/test/Makefile
@@ -119,7 +119,7 @@ TESTSPEC_vxWorks = recordTestHarness.munch; epicsRunRecordTests
TESTSPEC_RTEMS = recordTestHarness.boot; epicsRunRecordTests
TESTSCRIPTS_HOST += $(TESTS:%=%.t)
-ifeq ($(T_A),RTEMS-pc386)
+ifneq ($(filter $(T_A),$(CROSS_COMPILER_RUNTEST_ARCHS)),)
TESTPROD_RTEMS = $(TESTPROD_HOST)
TESTSCRIPTS_RTEMS += $(TESTS:%=%.t)
endif
From 65dec97f9ed98414c230c04624458b635dc6c74f Mon Sep 17 00:00:00 2001
From: Michael Davidsaver
Date: Sun, 3 Dec 2017 10:22:19 -0600
Subject: [PATCH 051/147] use new RTEMS build
---
ci/travis-build.sh | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/ci/travis-build.sh b/ci/travis-build.sh
index f487fbb88..0b592228c 100644
--- a/ci/travis-build.sh
+++ b/ci/travis-build.sh
@@ -62,13 +62,13 @@ if [ -n "$RTEMS" ]
then
echo "Cross RTEMS${RTEMS} for pc386"
install -d /home/travis/.cache
- curl -L "https://github.com/mdavidsaver/rsb/releases/download/travis-20160306-2/rtems${RTEMS}-i386-trusty-20190306-2.tar.gz" \
- | tar -C /home/travis/.cache -xj
+ curl -L "https://github.com/mdavidsaver/rsb/releases/download/20171203-${RTEMS}/i386-rtems${RTEMS}-trusty-20171203-${RTEMS}.tar.bz2" \
+ | tar -C / -xmj
sed -i -e '/^RTEMS_VERSION/d' -e '/^RTEMS_BASE/d' configure/os/CONFIG_SITE.Common.RTEMS
cat << EOF >> configure/os/CONFIG_SITE.Common.RTEMS
RTEMS_VERSION=$RTEMS
-RTEMS_BASE=/home/travis/.cache/rtems${RTEMS}-i386
+RTEMS_BASE=/home/travis/.rtems
EOF
cat << EOF >> configure/CONFIG_SITE
CROSS_COMPILER_TARGET_ARCHS+=RTEMS-pc386
@@ -76,7 +76,6 @@ CROSS_COMPILER_RUNTEST_ARCHS+=RTEMS-pc386
EOF
# find local qemu-system-i386
- export PATH="$HOME/.cache/qemu/usr/bin:$PATH"
echo -n "Using QEMU: "
type qemu-system-i386 || echo "Missing qemu"
EXTRA=RTEMS_QEMU_FIXUPS=YES
From 83b17d5061d9f6008581a59ff189ec5eeb43e847 Mon Sep 17 00:00:00 2001
From: Michael Davidsaver
Date: Sun, 22 Oct 2017 20:00:37 -0500
Subject: [PATCH 052/147] travis-ci: remove unused
---
.travis.yml | 1 -
ci/travis-build.sh | 9 ---------
ci/travis-prepare.sh | 40 ----------------------------------------
3 files changed, 50 deletions(-)
delete mode 100644 ci/travis-prepare.sh
diff --git a/.travis.yml b/.travis.yml
index 743908764..f8b11534f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -28,5 +28,4 @@ addons:
cache:
directories:
- $HOME/.cache
-install: sh ci/travis-prepare.sh &2
- exit 1
-}
-
-CURDIR="$PWD"
-
-QDIR="$HOME/.cache/qemu"
-
-if [ -n "$RTEMS" -a "$TEST" = "YES" ]
-then
- git clone --quiet --branch vme --depth 10 https://github.com/mdavidsaver/qemu.git "$HOME/.build/qemu"
- cd "$HOME/.build/qemu"
-
- HEAD=`git log -n1 --pretty=format:%H`
- echo "HEAD revision $HEAD"
-
- [ -e "$HOME/.cache/qemu/built" ] && BUILT=`cat "$HOME/.cache/qemu/built"`
- echo "Cached revision $BUILT"
-
- if [ "$HEAD" != "$BUILT" ]
- then
- echo "Building QEMU"
- git submodule --quiet update --init
-
- install -d "$HOME/.build/qemu/build"
- cd "$HOME/.build/qemu/build"
-
- "$HOME/.build/qemu/configure" --prefix="$HOME/.cache/qemu/usr" --target-list=i386-softmmu --disable-werror
- make -j2
- make install
-
- echo "$HEAD" > "$HOME/.cache/qemu/built"
- fi
-fi
-
-cd "$CURDIR"
From 220e404203e51624fb7e90f8fe5bcde2ba2767c4 Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Tue, 26 Jun 2018 11:23:15 -0500
Subject: [PATCH 053/147] Move EpicsHostArch.pl into src/tools, install to
lib/perl
---
configure/CONFIG | 5 ++++-
{startup => src/tools}/EpicsHostArch.pl | 0
src/tools/Makefile | 3 +++
3 files changed, 7 insertions(+), 1 deletion(-)
rename {startup => src/tools}/EpicsHostArch.pl (100%)
diff --git a/configure/CONFIG b/configure/CONFIG
index 6fe6b9b55..9d8d7e04b 100644
--- a/configure/CONFIG
+++ b/configure/CONFIG
@@ -21,8 +21,11 @@ endif
# Provide a default if the user hasn't set EPICS_HOST_ARCH
ifeq ($(origin EPICS_HOST_ARCH), undefined)
+ # Bootstrapping ...
+ EHA = $(firstword $(wildcard $(EPICS_BASE)/lib/perl/EpicsHostArch.pl \
+ $(TOP)/src/tools/EpicsHostArch.pl))
# NB: We use a simply expanded variable here for performance:
- EPICS_HOST_ARCH := $(shell $(CONFIG)/../startup/EpicsHostArch.pl)
+ export EPICS_HOST_ARCH := $(shell perl $(EHA))
endif
#
diff --git a/startup/EpicsHostArch.pl b/src/tools/EpicsHostArch.pl
similarity index 100%
rename from startup/EpicsHostArch.pl
rename to src/tools/EpicsHostArch.pl
diff --git a/src/tools/Makefile b/src/tools/Makefile
index bcf12700d..c54470364 100644
--- a/src/tools/Makefile
+++ b/src/tools/Makefile
@@ -16,6 +16,9 @@ PERL_MODULES += EPICS/Path.pm
PERL_MODULES += EPICS/Release.pm
PERL_MODULES += EPICS/Getopts.pm
+# This goes into lib/perl, not bin/
+PERL_MODULES += EpicsHostArch.pl
+
PERL_SCRIPTS += convertRelease.pl
PERL_SCRIPTS += cvsclean.pl
PERL_SCRIPTS += dos2unix.pl
From b32629c3bf4e718afd42acffd3f5e100d0f17a94 Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Tue, 26 Jun 2018 11:23:35 -0500
Subject: [PATCH 054/147] Start release notes for tidy-startup branch.
---
documentation/RELEASE_NOTES.html | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html
index b454da0d6..a1c80695b 100644
--- a/documentation/RELEASE_NOTES.html
+++ b/documentation/RELEASE_NOTES.html
@@ -13,6 +13,27 @@
+Cleanup of startup directory
+
+The files in the startup directory have not been maintained in recent years
+and have grown crufty (technical term). This release includes the following
+updates to these files:
+
+
+- The EpicsHostArch.pl script has been moved into src/tools
+from where it gets installed into lib/perl. The build system has been
+adjusted to look for it in both places if the EPICS_HOST_ARCH
+environment variable has not been set at build-time. Sites that may have used
+this to set EPICS_HOST_ARCH as part of their standard environment may
+need to adjust their scripts when they upgrade to this release.
+
+- The existing win32.bat file has been cleaned up and a new
+windows.bat file added for 64-bit targets. The contents of these files
+should be seen as examples, don't uncomment or install parts for software that
+you don't explicitly know that you need.
+
+
+
Fixes for Launchpad bugs
The following launchpad bugs have fixes included:
From eae59183cc0d2675496425c4b3017dddef383800 Mon Sep 17 00:00:00 2001
From: "J. Lewis Muir"
Date: Tue, 26 Jun 2018 15:41:27 -0500
Subject: [PATCH 055/147] Rename Site.{cshrc,profile} to unix.{csh,sh}
---
documentation/README.1st | 4 ++--
documentation/README.darwin.html | 2 +-
documentation/README.html | 4 ++--
documentation/RELEASE_NOTES.html | 3 +++
startup/{Site.cshrc => unix.csh} | 0
startup/{Site.profile => unix.sh} | 0
6 files changed, 8 insertions(+), 5 deletions(-)
rename startup/{Site.cshrc => unix.csh} (100%)
rename startup/{Site.profile => unix.sh} (100%)
diff --git a/documentation/README.1st b/documentation/README.1st
index 462ac460a..4ddad2772 100644
--- a/documentation/README.1st
+++ b/documentation/README.1st
@@ -223,10 +223,10 @@
EpicsHostArch C shell script to set EPICS_HOST_ARCH env variable
EpicsHostArch.pl Perl script to set EPICS_HOST_ARCH env variable
- Site.profile bourne shell script to set path and env variables
- Site.cshrc c shell script to set path and env variables
borland.bat WIN32 bat file to set borland path and env variables
cygwin.bat WIN32 bat file to set cygwin path and env variables
+ unix.csh C shell script to set path and env variables
+ unix.sh Bourne shell script to set path and env variables
win32.bat WIN32 bat file to set path and env variables
win32-debug.bat WIN32 debug bat file to set debug path and env variables
diff --git a/documentation/README.darwin.html b/documentation/README.darwin.html
index cbc290178..dd11ce857 100644
--- a/documentation/README.darwin.html
+++ b/documentation/README.darwin.html
@@ -21,7 +21,7 @@ of my Bash login script (~/.bash_login):
#
EPICS_BASE="${HOME}/src/EPICS/base"
EPICS_EXTENSIONS="${HOME}/src/EPICS/extensions"
-. "${EPICS_BASE}"/startup/Site.profile
+. "${EPICS_BASE}"/startup/unix.sh
diff --git a/documentation/README.html b/documentation/README.html
index a8a572372..ad67cdfcb 100644
--- a/documentation/README.html
+++ b/documentation/README.html
@@ -232,10 +232,10 @@
EpicsHostArch C shell script to set EPICS_HOST_ARCH env variable
EpicsHostArch.pl Perl script to set EPICS_HOST_ARCH env variable
- Site.profile bourne shell script to set path and env variables
- Site.cshrc c shell script to set path and env variables
borland.bat WIN32 bat file to set borland path and env variables
cygwin.bat WIN32 bat file to set cygwin path and env variables
+ unix.csh C shell script to set path and env variables
+ unix.sh Bourne shell script to set path and env variables
win32.bat WIN32 bat file to set path and env variables
win32-debug.bat WIN32 debug bat file to set debug path and env variables
diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html
index a1c80695b..85dc54a7b 100644
--- a/documentation/RELEASE_NOTES.html
+++ b/documentation/RELEASE_NOTES.html
@@ -27,6 +27,9 @@ environment variable has not been set at build-time. Sites that may have used
this to set EPICS_HOST_ARCH as part of their standard environment may
need to adjust their scripts when they upgrade to this release.
+The Site.cshrc and Site.profile files have been renamed to
+unix.csh and unix.sh, respectively.
+
The existing win32.bat file has been cleaned up and a new
windows.bat file added for 64-bit targets. The contents of these files
should be seen as examples, don't uncomment or install parts for software that
diff --git a/startup/Site.cshrc b/startup/unix.csh
similarity index 100%
rename from startup/Site.cshrc
rename to startup/unix.csh
diff --git a/startup/Site.profile b/startup/unix.sh
similarity index 100%
rename from startup/Site.profile
rename to startup/unix.sh
From 7a5ff269846aa8c09ab972294f193299e21c1537 Mon Sep 17 00:00:00 2001
From: "J. Lewis Muir"
Date: Tue, 26 Jun 2018 16:20:07 -0500
Subject: [PATCH 056/147] Remove EpicsHostArch
---
ci/travis-build.sh | 2 +-
documentation/README.1st | 1 -
documentation/README.html | 1 -
documentation/RELEASE_NOTES.html | 3 ++
startup/EpicsHostArch | 84 --------------------------------
5 files changed, 4 insertions(+), 87 deletions(-)
delete mode 100755 startup/EpicsHostArch
diff --git a/ci/travis-build.sh b/ci/travis-build.sh
index a3ca3fd16..2ee5d652f 100644
--- a/ci/travis-build.sh
+++ b/ci/travis-build.sh
@@ -17,7 +17,7 @@ ticker() {
CACHEKEY=1
-EPICS_HOST_ARCH=`sh startup/EpicsHostArch`
+EPICS_HOST_ARCH=`perl src/tools/EpicsHostArch.pl`
[ -e configure/os/CONFIG_SITE.Common.linux-x86 ] || die "Wrong location: $PWD"
diff --git a/documentation/README.1st b/documentation/README.1st
index 4ddad2772..f5f209dd1 100644
--- a/documentation/README.1st
+++ b/documentation/README.1st
@@ -221,7 +221,6 @@
base/startup directory - contains scripts to set environment and path
- EpicsHostArch C shell script to set EPICS_HOST_ARCH env variable
EpicsHostArch.pl Perl script to set EPICS_HOST_ARCH env variable
borland.bat WIN32 bat file to set borland path and env variables
cygwin.bat WIN32 bat file to set cygwin path and env variables
diff --git a/documentation/README.html b/documentation/README.html
index ad67cdfcb..c803ab767 100644
--- a/documentation/README.html
+++ b/documentation/README.html
@@ -230,7 +230,6 @@
base/startup directory - contains scripts to set environment and path
- EpicsHostArch C shell script to set EPICS_HOST_ARCH env variable
EpicsHostArch.pl Perl script to set EPICS_HOST_ARCH env variable
borland.bat WIN32 bat file to set borland path and env variables
cygwin.bat WIN32 bat file to set cygwin path and env variables
diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html
index 85dc54a7b..a419bcabc 100644
--- a/documentation/RELEASE_NOTES.html
+++ b/documentation/RELEASE_NOTES.html
@@ -20,6 +20,9 @@ and have grown crufty (technical term). This release includes the following
updates to these files:
+- The EpicsHostArch script has been removed.
+EpicsHostArch.pl should be used instead.
+
- The EpicsHostArch.pl script has been moved into src/tools
from where it gets installed into lib/perl. The build system has been
adjusted to look for it in both places if the EPICS_HOST_ARCH
diff --git a/startup/EpicsHostArch b/startup/EpicsHostArch
deleted file mode 100755
index 8861ac56c..000000000
--- a/startup/EpicsHostArch
+++ /dev/null
@@ -1,84 +0,0 @@
-#!/bin/sh
-#*************************************************************************
-# Copyright (c) 2011 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.
-#*************************************************************************
-#
-# EpicsHostArch - returns the Epics host architecture suitable
-# for assigning to the EPICS_HOST_ARCH variable
-
-if [ "x${1}" != "x" ]
-then
- suffix="-"${1}
-else
- suffix=""
-fi
-
-sysname=`uname`
-
-case $sysname in
- Linux )
- os=linux
- cpu=`uname -m`
- case $cpu in
- i386 | i486 | i586 | i686 )
- cpu=x86 ;;
- x86_64 )
- ;; # $cpu is correct
- armv6l | armv7l )
- cpu=arm ;;
- esac
- echo ${os}-${cpu}${suffix}
- ;;
- Darwin )
- os=darwin
- cpu=`uname -m`
- case $cpu in
- "Power Macintosh")
- cpu=ppc ;;
- i386 | x86_64 )
- cpu=x86 ;;
- esac
- echo ${os}-${cpu}${suffix}
- ;;
- SunOS )
- version=`uname -r | sed '1s/^\([0-9]*\).*$/\1/'`
- if [ ${version} -ge 5 ]; then
- os=solaris
- else
- os=sun4
- fi
- cpu=`uname -m`
- case $cpu in
- sun4*)
- cpu=sparc
- ;;
- i86pc)
- cpu=x86
- ;;
- esac
- echo ${os}-${cpu}${suffix}
- ;;
- * )
- sysname=`uname -o`
- case $sysname in
- Cygwin )
- os=cygwin
- cpu=`uname -m`
- case $cpu in i386 | i486 | i586 | i686 )
- cpu=x86
- ;;
- esac
- echo ${os}-${cpu}${suffix}
- ;;
- * )
- echo unsupported
- ;;
- esac
- ;;
-esac
-
From 68779943ebd2da19d6840660a01c79a2a6623e1f Mon Sep 17 00:00:00 2001
From: "J. Lewis Muir"
Date: Tue, 26 Jun 2018 16:34:04 -0500
Subject: [PATCH 057/147] Remove execute file mode bit
---
startup/cygwin.bat | 0
startup/unix.csh | 0
startup/unix.sh | 0
startup/windows.bat | 0
4 files changed, 0 insertions(+), 0 deletions(-)
mode change 100755 => 100644 startup/cygwin.bat
mode change 100755 => 100644 startup/unix.csh
mode change 100755 => 100644 startup/unix.sh
mode change 100755 => 100644 startup/windows.bat
diff --git a/startup/cygwin.bat b/startup/cygwin.bat
old mode 100755
new mode 100644
diff --git a/startup/unix.csh b/startup/unix.csh
old mode 100755
new mode 100644
diff --git a/startup/unix.sh b/startup/unix.sh
old mode 100755
new mode 100644
diff --git a/startup/windows.bat b/startup/windows.bat
old mode 100755
new mode 100644
From ab493264b2d08e45bb9f9359390689b3ff14c6c2 Mon Sep 17 00:00:00 2001
From: "J. Lewis Muir"
Date: Tue, 26 Jun 2018 17:56:58 -0500
Subject: [PATCH 058/147] Make EpicsHostArch.pl print newline
Print a newline after the EPICS host architecture spec. This is typical
for a UNIX-like program (e.g., date).
---
src/tools/EpicsHostArch.pl | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/tools/EpicsHostArch.pl b/src/tools/EpicsHostArch.pl
index 09f7ffddd..5f5dad453 100755
--- a/src/tools/EpicsHostArch.pl
+++ b/src/tools/EpicsHostArch.pl
@@ -19,7 +19,7 @@ $suffix="";
$suffix="-".$ARGV[0] if ($ARGV[0] ne "");
$EpicsHostArch = GetEpicsHostArch();
-print "$EpicsHostArch$suffix";
+print "$EpicsHostArch$suffix\n";
sub GetEpicsHostArch { # no args
$arch=$Config{'archname'};
From 860ce156a2e85878b341821d5153f989c6f0904d Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Thu, 19 Jul 2018 12:20:41 -0500
Subject: [PATCH 059/147] Documentation updates for 3.14.12.8
---
documentation/KnownProblems.html | 23 ++++++-----------------
documentation/RELEASE_NOTES.html | 5 +++++
2 files changed, 11 insertions(+), 17 deletions(-)
diff --git a/documentation/KnownProblems.html b/documentation/KnownProblems.html
index eadac0179..1dc944e3a 100644
--- a/documentation/KnownProblems.html
+++ b/documentation/KnownProblems.html
@@ -4,27 +4,16 @@
- Known Problems in R3.14.12.1
+ Known Problems in R3.14.12.8
-
EPICS Base R3.14.12.1: Known Problems
+EPICS Base R3.14.12.8: Known Problems
-Any patch files linked below should be applied at the root of the
-base-3.14.12.1 tree. Download them, then use the GNU Patch program as
-follows:
-
-% cd /path/to/base-3.14.12.1
-% patch -p0 < /path/to/file.patch
-
-The following significant problems have been reported with this
-version of EPICS Base:
-
-
+This was the last release in the Base-3.14 series, so we are no longer
+tracking bugs in this branch. Please upgrade to one of the newer releases which
+have incorporated many bug fixes and new features since they branched off the
+Base-3.14 release series.
diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html
index b454da0d6..b327e2430 100644
--- a/documentation/RELEASE_NOTES.html
+++ b/documentation/RELEASE_NOTES.html
@@ -9,6 +9,9 @@
EPICS Base Release 3.14.12.8
+This is the final release in the Base-3.14 series, please upgrade to the
+Base-3.15 series or to EPICS 7.
+
Changes between 3.14.12.7 and 3.14.12.8
@@ -18,6 +21,8 @@
The following launchpad bugs have fixes included:
+-
+ lp: #541221, 'assert (pca->pgetNative)' failed in ../dbCa.c
-
lp: #1747091, epicsTimeGetEvent() / generalTime bug
-
From 20d2cff501b22cfa51bd6154b5e1fba5d42dda46 Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Thu, 19 Jul 2018 12:31:52 -0500
Subject: [PATCH 060/147] Update version number to 3.14.12.8-rc1
---
configure/CONFIG_BASE_VERSION | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)
diff --git a/configure/CONFIG_BASE_VERSION b/configure/CONFIG_BASE_VERSION
index 1a4f925a2..3c2e0d868 100644
--- a/configure/CONFIG_BASE_VERSION
+++ b/configure/CONFIG_BASE_VERSION
@@ -28,15 +28,10 @@ EPICS_MODIFICATION = 12
# EPICS_PATCH_LEVEL must be a number (win32 resource file requirement)
# Not included if zero
-EPICS_PATCH_LEVEL = 7
+EPICS_PATCH_LEVEL = 8
# This will end in -DEV between official releases
-EPICS_DEV_SNAPSHOT=-DEV
-#EPICS_DEV_SNAPSHOT=-pre1
-#EPICS_DEV_SNAPSHOT=-pre1-DEV
-#EPICS_DEV_SNAPSHOT=-pre2
-#EPICS_DEV_SNAPSHOT=-pre2-DEV
-#EPICS_DEV_SNAPSHOT=-rc1
+EPICS_DEV_SNAPSHOT=-rc1
#EPICS_DEV_SNAPSHOT=-rc1-DEV
#EPICS_DEV_SNAPSHOT=-rc2
#EPICS_DEV_SNAPSHOT=-rc2-DEV
From 2a2a1e54ac7849db6ff6940503152c1ae42a4e14 Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Thu, 19 Jul 2018 12:35:40 -0500
Subject: [PATCH 061/147] Post-tag version number update
---
configure/CONFIG_BASE_VERSION | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/configure/CONFIG_BASE_VERSION b/configure/CONFIG_BASE_VERSION
index 3c2e0d868..895b5add4 100644
--- a/configure/CONFIG_BASE_VERSION
+++ b/configure/CONFIG_BASE_VERSION
@@ -31,8 +31,7 @@ EPICS_MODIFICATION = 12
EPICS_PATCH_LEVEL = 8
# This will end in -DEV between official releases
-EPICS_DEV_SNAPSHOT=-rc1
-#EPICS_DEV_SNAPSHOT=-rc1-DEV
+EPICS_DEV_SNAPSHOT=-rc1-DEV
#EPICS_DEV_SNAPSHOT=-rc2
#EPICS_DEV_SNAPSHOT=-rc2-DEV
#EPICS_DEV_SNAPSHOT=
From e0399478adf8e5d7b19df9db5e3afeb0e6155c68 Mon Sep 17 00:00:00 2001
From: "J. Lewis Muir"
Date: Fri, 20 Jul 2018 17:14:43 -0500
Subject: [PATCH 062/147] Remove startup/cygwin.bat
Cygwin is no longer supported for Microsoft API builds, so remove it.
---
startup/cygwin.bat | 122 ---------------------------------------------
1 file changed, 122 deletions(-)
delete mode 100644 startup/cygwin.bat
diff --git a/startup/cygwin.bat b/startup/cygwin.bat
deleted file mode 100644
index ff75b5335..000000000
--- a/startup/cygwin.bat
+++ /dev/null
@@ -1,122 +0,0 @@
-@ECHO OFF
-REM *************************************************************************
-REM Copyright (c) 2002 The University of Chicago, as Operator of Argonne
-REM National Laboratory.
-REM Copyright (c) 2002 The Regents of the University of California, as
-REM Operator of Los Alamos National Laboratory.
-REM EPICS BASE Versions 3.13.7
-REM and higher are distributed subject to a Software License Agreement found
-REM in file LICENSE that is included with this distribution.
-REM *************************************************************************
-REM
-REM Site-specific EPICS environment settings
-REM
-REM sites should modify these definitions
-
-REM ======================================================
-REM ====== REQUIRED ENVIRONMENT VARIABLES FOLLOW ======
-REM ======================================================
-
-REM ======================================================
-REM ---------------- WINDOWS ---------------------------
-REM ======================================================
-REM ----- WIN95 -----
-REM set PATH=C:\WINDOWS;C:\WINDOWS\COMMAND
-REM ----- WINNT, WIN2000 -----
-REM set PATH=C:\WINNT;C:\WINNT\SYSTEM32
-REM ----- WINXP, Vista, Windows 7 -----
-set PATH=C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\SYSTEM32\Wbem
-
-REM ======================================================
-REM ---------------- make and perl ---------------------
-REM ======================================================
-
-REM --------------- ActiveState perl -------------------
-set PATH=C:\Perl\bin;%PATH%
-
-REM --------------- mingw make ------------------------
-REM set PATH=C:\mingw-make\bin;%PATH%
-REM set PATH=C:\mingw-make82-3\bin;%PATH%
-
-REM --------------- gnuwin32 make ----------------------
-set PATH=C:\gnuwin32\bin;%PATH%
-
-REM ======================================================
-REM ---------------- cygwin tools ------------------------
-REM ======================================================
-REM (make & perl if above perl and make are REMs)
-REM Dont use cygwin GNU make and Perl!
-REM cygwin contains tk/tcl, vim, perl, and many unix tools
-REM need grep from here NOT from cvs directory
-set PATH=%PATH%;.;..
-set PATH=%PATH%;c:\cygwin\bin
-
-REM ======================================================
-REM --------------- EPICS --------------------------------
-REM ======================================================
-set EPICS_HOST_ARCH=cygwin-x86
-set PATH=%PATH%;G:\epics\base\bin\%EPICS_HOST_ARCH%
-set PATH=%PATH%;G:\epics\extensions\bin\%EPICS_HOST_ARCH%
-
-REM ======================================================
-REM ------- OPTIONAL ENVIRONMENT VARIABLES FOLLOW --------
-REM ======================================================
-
-REM ======================================================
-REM ----------------- remote CVS -------------------------
-REM ======================================================
-REM set CVS_RSH=c:/cygwin/bin/ssh.exe
-REM set CVSROOT=:ext:jba@aps.anl.gov:/usr/local/epicsmgr/cvsroot
-REM set HOME=c:/users/%USERNAME%
-REM set HOME=c:/users/jba
-
-REM ======================================================
-REM ------------------- Bazaar ---------------------------
-REM ======================================================
-set PATH=%PATH%;C:\Program files\Bazaar
-
-REM ======================================================
-REM ----------------- GNU make flags ---------------------
-REM ======================================================
-set MAKEFLAGS=-w
-
-REM ======================================================
-REM -------------- vim (use cygwin vim ) -----------------
-REM ======================================================
-REM HOME needed by vim to write .viminfo file.
-REM VIM needed by vim to find _vimrc file.
-REM set VIM=c:\cygwin
-
-REM ======================================================
-REM --------------- Epics Channel Access -----------------
-REM Modify and uncomment the following lines
-REM to override the base/configure/CONFIG_ENV defaults
-REM ======================================================
-REM set EPICS_CA_ADDR_LIST=n.n.n.n n.n.n.n
-REM set EPICS_CA_AUTO_ADDR_LIST=YES
-
-REM set EPICS_CA_CONN_TMO=30.0
-REM set EPICS_CA_BEACON_PERIOD=15.0
-REM set EPICS_CA_REPEATER_PORT=5065
-REM set EPICS_CA_SERVER_PORT=5064
-REM set EPICS_TS_MIN_WEST=420
-
-REM ======================================================
-REM --------------- JAVA ---------------------------------
-REM ======================================================
-REM Needed for java extensions
-REM set CLASSPATH=G:\epics\extensions\javalib
-REM set PATH=%PATH%;C:\j2sdk1.4.1_01\bin
-REM set CLASSPATH=%CLASSPATH%;C:\j2sdk1.4.1_01\lib\tools.jar
-
-REM ======================================================
-REM --------------- Exceed -------------------------------
-REM Needed for X11 extensions
-REM ======================================================
-REM set EX_VER=7.10
-REM set EX_VER=12.00
-REM set EX_VER=14.00
-REM set PATH=%PATH%;C:\Exceed%EX_VER%\XDK\
-REM set PATH=%PATH%;C:\Program Files\Hummingbird\Connectivity\%EX_VER%\Exceed\
-
-
From 8f161f9463f1605d9a6ba907890c9ac58cd6318f Mon Sep 17 00:00:00 2001
From: "J. Lewis Muir"
Date: Fri, 20 Jul 2018 17:18:22 -0500
Subject: [PATCH 063/147] Rewrite startup/unix.sh
Remove extraneous things unrelated to EPICS Base.
Make it behave consistently with the other startup scripts.
Make it easy to configure both for a human and a program.
---
startup/unix.sh | 184 ++++++++++++++++++++++--------------------------
1 file changed, 83 insertions(+), 101 deletions(-)
diff --git a/startup/unix.sh b/startup/unix.sh
index 5cb9b0273..8f45629ee 100644
--- a/startup/unix.sh
+++ b/startup/unix.sh
@@ -1,4 +1,3 @@
-#!/bin/sh
#*************************************************************************
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
# National Laboratory.
@@ -8,111 +7,94 @@
# and higher are distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
-# Site-specific EPICS environment settings
#
-# sites should modify these definitions
+# Site-specific EPICS environment settings
+#
+# Attempts to set EPICS_HOST_ARCH. Optionally, adds the EPICS Base
+# install host architecture bin directory to PATH.
+#
-# Location of epics base
-if [ -z "${MY_EPICS_BASE}" ] ; then
- MY_EPICS_BASE=/usr/local/epics/base
+#-----------------------------------------------------------------------
+# Site serviceable parts (These definitions may be modified)
+#-----------------------------------------------------------------------
+
+# Automatically set up the environment when possible ("yes" or "no").
+# If set to yes, as much of the environment will be set up as possible.
+# If set to no, just the minimum environment will be set up. More
+# specific _auto_* definitions take precedence over this definition.
+_auto=no
+
+# Automatically append to PATH ("yes" or "no"). If set to yes, the
+# EPICS Base install host architecture bin directory will be added to
+# PATH if possible. If set to no, the bin directory will not be added
+# to PATH.
+_auto_path_append=$_auto
+
+# The program used to run Perl scripts (pathname).
+_perl_prog=perl
+
+# The EPICS host architecture specification for EPICS_HOST_ARCH
+# (-[-] as defined in configure/CONFIG_SITE). If
+# nonempty, the value will be used as the value of EPICS_HOST_ARCH. If
+# empty, an attempt will be made to automatically determine the value
+# with EpicsHostArch.pl.
+_epics_host_arch=
+
+# The install location of EPICS Base (pathname). If nonempty, the
+# EpicsHostArch.pl script from it, if it exists, will be used to
+# determine EPICS_HOST_ARCH. If nonempty and EPICS_HOST_ARCH was
+# determined successfully, it will be used to add the host architecture
+# bin directory to PATH if _auto_path_append is yes.
+_epics_base=
+
+# The source location of EPICS Base (pathname). If nonempty, the
+# EpicsHostArch.pl script from it, if it exists and _epics_base is empty
+# or it did not exist in the _epics_base location, will be used to
+# determine EPICS_HOST_ARCH.
+_epics_base_src=
+
+#-----------------------------------------------------------------------
+# Internal parts (There is typically no need to modify these)
+#-----------------------------------------------------------------------
+
+# Define the possible locations of EpicsHostArch.pl
+_epics_host_arch_pl=
+_src_epics_host_arch_pl=
+if [ -n "$_epics_base" ]; then
+ _epics_host_arch_pl="$_epics_base/lib/perl/EpicsHostArch.pl"
+fi
+if [ -n "$_epics_base_src" ]; then
+ _src_epics_host_arch_pl="$_epics_base_src/src/tools/EpicsHostArch.pl"
fi
-# Location of epics extensions (medm, msi, etc.)
-if [ -z "${EPICS_EXTENSIONS}" ] ; then
- EPICS_EXTENSIONS=/usr/local/epics/extensions
+# Set the EPICS host architecture specification
+if [ -n "$_epics_host_arch" ]; then
+ EPICS_HOST_ARCH=$_epics_host_arch
+ export EPICS_HOST_ARCH
+elif [ -e "$_epics_host_arch_pl" ]; then
+ _epics_host_arch=$("$_perl_prog" "$_epics_host_arch_pl")
+ EPICS_HOST_ARCH=$_epics_host_arch
+ export EPICS_HOST_ARCH
+elif [ -e "$_src_epics_host_arch_pl" ]; then
+ _epics_host_arch=$("$_perl_prog" "$_src_epics_host_arch_pl")
+ EPICS_HOST_ARCH=$_epics_host_arch
+ export EPICS_HOST_ARCH
fi
-# Postscript printer definition needed by some extensions (eg medm, dp, dm, ...)
-if [ -z "${PSPRINTER}" ] ; then
- export PSPRINTER=lp
+# Add the EPICS Base host architecture bin directory to PATH
+if [ "$_auto_path_append" = yes ]; then
+ if [ -n "$_epics_base" ] && [ -n "$_epics_host_arch" ]; then
+ PATH="$PATH:$_epics_base/bin/$_epics_host_arch"
+ export PATH
+ fi
fi
-#Needed only by the idl and ezcaIDL extensions.
-#export EPICS_EXTENSIONS
-
-# Needed only by medm extension
-#export EPICS_DISPLAY_PATH=/path/to/adl/files
-export BROWSER=firefox
-
-# Needed only by orbitscreen extension
-#if [ -z "${ORBITSCREENHOME}" ] ; then
-# export "ORBITSCREENHOME=${EPICS_EXTENSIONS/src/orbitscreen}"
-#fi
-
-# Needed only by adt extension
-#if [ -z "${ADTHOME}" ] ; then
-# ADTHOME=
-# export ADTHOME
-#fi
-
-# Needed only by ar extension (archiver)
-#EPICS_AR_PORT=7002
-#export EPICS_AR_PORT
-
-# Needed for java extensions
-if [ -z "${CLASSPATH}" ] ; then
- CLASSPATH="${EPICS_EXTENSIONS}/javalib"
-else
- CLASSPATH="${CLASSPATH}:${EPICS_EXTENSIONS}/javalib"
-fi
-export CLASSPATH
-
-# Allow private versions of extensions without a bin subdir
-if [ -n "${EPICS_EXTENSIONS_PVT}" ] ; then
- PATH="${PATH}:${EPICS_EXTENSIONS_PVT}"
-fi
-
-#---------------------------------------------------------------
-# Start of set R3.14 environment variables
-#
-EPICS_HOST_ARCH=`"${MY_EPICS_BASE}"/startup/EpicsHostArch.pl`
-export EPICS_HOST_ARCH
-
-# Allow private versions of base
-if [ -n "${EPICS_BASE_PVT}" ] ; then
- if [ -d "${EPICS_BASE_PVT}/bin/${EPICS_HOST_ARCH}" ]; then
- PATH="${PATH}:${EPICS_BASE_PVT}/bin/${EPICS_HOST_ARCH}"
- fi
-fi
-
-# Allow private versions of extensions
-if [ -n "${EPICS_EXTENSIONS_PVT}" ] ; then
- if [ -d "${EPICS_EXTENSIONS_PVT}/bin/${EPICS_HOST_ARCH}" ]; then
- PATH="${PATH}:${EPICS_EXTENSIONS_PVT}/bin/${EPICS_HOST_ARCH}"
- fi
-fi
-PATH="${PATH}:${EPICS_EXTENSIONS}/bin/${EPICS_HOST_ARCH}"
-
-# End of set R3.14 environment variables
-
-#---------------------------------------------------------------
-#
-## Start of set pre R3.14 environment variables
-#
-## Time service:
-## EPICS_TS_MIN_WEST the local time difference from GMT.
-#EPICS_TS_MIN_WEST=360
-#export EPICS_TS_MIN_WEST
-#
-#HOST_ARCH=`"${MY_EPICS_BASE}"/startup/HostArch`
-#export HOST_ARCH
-#
-## Allow private versions of base
-#if [ -n "${EPICS_BASE_PVT}" ] ; then
-# if [ -d "${EPICS_BASE_PVT}/bin/${HOST_ARCH}" ]; then
-# PATH="${PATH}:${EPICS_BASE_PVT}/bin/${HOST_ARCH}"
-# fi
-#fi
-#
-## Allow private versions of extensions
-#if [ -n "${EPICS_EXTENSIONS_PVT}" ] ; then
-# if [ -d "${EPICS_EXTENSIONS_PVT}/bin/${HOST_ARCH}" ]; then
-# PATH="${PATH}:${EPICS_EXTENSIONS_PVT}/bin/${HOST_ARCH}"
-# fi
-#fi
-#
-#PATH="${PATH}:${EPICS_EXTENSIONS}/lib/${HOST_ARCH}"
-#
-# End of set pre R3.14 environment variables
-
-#---------------------------------------------------------------
+# Don't leak variables into the environment
+unset _auto
+unset _auto_path_append
+unset _perl_prog
+unset _epics_host_arch
+unset _epics_base
+unset _epics_base_src
+unset _epics_host_arch_pl
+unset _src_epics_host_arch_pl
From 31844af88e440052e98ab3419803fee683e594b6 Mon Sep 17 00:00:00 2001
From: "J. Lewis Muir"
Date: Fri, 20 Jul 2018 17:29:47 -0500
Subject: [PATCH 064/147] Rewrite startup/unix.csh
Remove extraneous things unrelated to EPICS Base.
Make it behave consistently with the other startup scripts.
Make it easy to configure both for a human and a program.
---
startup/unix.csh | 188 +++++++++++++++++++++--------------------------
1 file changed, 83 insertions(+), 105 deletions(-)
diff --git a/startup/unix.csh b/startup/unix.csh
index 23453cb91..dce441ea8 100644
--- a/startup/unix.csh
+++ b/startup/unix.csh
@@ -1,4 +1,3 @@
-#!/bin/csh -f
#*************************************************************************
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
# National Laboratory.
@@ -8,111 +7,90 @@
# and higher are distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
-# Site-specific EPICS environment settings
#
-# sites should modify these definitions
-
-# Location of epics base
-if ( ! $?EPICS_BASE ) then
- set EPICS_BASE=/usr/local/epics/base
-endif
-
-# Location of epics extensions
-if ( ! $?EPICS_EXTENSIONS ) then
- setenv EPICS_EXTENSIONS /usr/local/epics/extensions
-endif
-
-# Postscript printer definition needed by some extensions (eg medm, dp, dm, ...)
-if ( ! $?PSPRINTTER ) then
- setenv PSPRINTER lp
-endif
-
-# Needed only by medm extension
-#setenv EPICS_DISPLAY_PATH
-# Needed only by medm extension
-setenv BROWSER firefox
-
-# Needed only by orbitscreen extension
-if ( ! $?ORBITSCREENHOME ) then
- setenv ORBITSCREENHOME $EPICS_EXTENSIONS/src/orbitscreen
-endif
-
-# Needed only by adt extension
-if ( ! $?ADTHOME ) then
- setenv ADTHOME /usr/local/oag/apps/src/appconfig/adt
- echo $ADTHOME
-endif
-
-# Needed only by ar extension (archiver)
-setenv EPICS_AR_PORT 7002
-
-# Needed for java extensions
-if ( $?CLASSPATH ) then
- setenv CLASSPATH "${CLASSPATH}:${EPICS_EXTENSIONS}/javalib"
-else
- setenv CLASSPATH "${EPICS_EXTENSIONS}/javalib"
-endif
-
-# Allow private versions of extensions without a bin subdir
-if ( $?EPICS_EXTENSIONS_PVT ) then
- set path = ( $path $EPICS_EXTENSIONS_PVT)
-endif
-
-##################################################################
-
-# Start of set R3.14 environment variables
-
-setenv EPICS_HOST_ARCH `$EPICS_BASE/startup/EpicsHostArch.pl`
-
-# Allow private versions of base
-if ( $?EPICS_BASE_PVT ) then
- if ( -e $EPICS_BASE_PVT/bin/$EPICS_HOST_ARCH ) then
- set path = ( $path $EPICS_BASE_PVT/bin/$EPICS_HOST_ARCH)
- endif
-endif
-
-# Allow private versions of extensions
-if ( $?EPICS_EXTENSIONS_PVT ) then
- if ( -e $EPICS_EXTENSIONS_PVT/bin/$EPICS_HOST_ARCH ) then
- set path = ( $path $EPICS_EXTENSIONS_PVT/bin/$EPICS_HOST_ARCH)
- endif
-endif
-set path = ( $path $EPICS_EXTENSIONS/bin/$EPICS_HOST_ARCH )
-
-# End of set R3.14 environment variables
-##################################################################
-
-
-## Start of set pre R3.14 environment variables
+# Site-specific EPICS environment settings
#
-## Time service:
-## EPICS_TS_MIN_WEST the local time difference from GMT.
-#setenv EPICS_TS_MIN_WEST 360
+# Attempts to set EPICS_HOST_ARCH. Optionally, adds the EPICS Base
+# install host architecture bin directory to PATH.
#
-#if ( -e /usr/local/etc/setup/HostArch.pl ) then
-# setenv HOST_ARCH `/usr/local/etc/setup/HostArch.pl`
-#else
-# setenv HOST_ARCH `/usr/local/epics/startup/HostArch.pl`
-#endif
-#
-## Allow private versions of extensions
-#if ( $?EPICS_EXTENSIONS_PVT ) then
-# if ( -e $EPICS_EXTENSIONS_PVT/bin/$HOST_ARCH ) then
-# set path = ( $path $EPICS_EXTENSIONS_PVT/bin/$HOST_ARCH)
-# endif
-# # Needed if shared extension libraries are built
-# if ( -e $EPICS_EXTENSIONS_PVT/lib/$HOST_ARCH ) then
-# if ( $?LD_LIBRARY_PATH ) then
-# setenv LD_LIBRARY_PATH "${LD_LIBRARY_PATH}:${EPICS_EXTENSIONS_PVT}/lib/${HOST_ARCH}"
-# else
-# setenv LD_LIBRARY_PATH "${EPICS_EXTENSIONS_PVT}/lib/${HOST_ARCH}"
-# endif
-# endif
-#endif
-#
-#set path = ( $path $EPICS_EXTENSIONS/bin/$HOST_ARCH )
-## Needed if shared extension libraries are built
-#setenv LD_LIBRARY_PATH "${LD_LIBRARY_PATH}:${EPICS_EXTENSIONS}/lib/${HOST_ARCH}"
-# End of set pre R3.14 environment variables
-##################################################################
+#-----------------------------------------------------------------------
+# Site serviceable parts (These definitions may be modified)
+#-----------------------------------------------------------------------
+
+# Automatically set up the environment when possible ("yes" or "no").
+# If set to yes, as much of the environment will be set up as possible.
+# If set to no, just the minimum environment will be set up. More
+# specific _auto_* definitions take precedence over this definition.
+set _auto=no
+
+# Automatically append to PATH ("yes" or "no"). If set to yes, the
+# EPICS Base install host architecture bin directory will be added to
+# PATH if possible. If set to no, the bin directory will not be added
+# to PATH.
+set _auto_path_append=$_auto
+
+# The program used to run Perl scripts (pathname).
+set _perl_prog=perl
+
+# The EPICS host architecture specification for EPICS_HOST_ARCH
+# (-[-] as defined in configure/CONFIG_SITE). If
+# nonempty, the value will be used as the value of EPICS_HOST_ARCH. If
+# empty, an attempt will be made to automatically determine the value
+# with EpicsHostArch.pl.
+set _epics_host_arch=
+
+# The install location of EPICS Base (pathname). If nonempty, the
+# EpicsHostArch.pl script from it, if it exists, will be used to
+# determine EPICS_HOST_ARCH. If nonempty and EPICS_HOST_ARCH was
+# determined successfully, it will be used to add the host architecture
+# bin directory to PATH if _auto_path_append is yes.
+set _epics_base=
+
+# The source location of EPICS Base (pathname). If nonempty, the
+# EpicsHostArch.pl script from it, if it exists and _epics_base is empty
+# or it did not exist in the _epics_base location, will be used to
+# determine EPICS_HOST_ARCH.
+set _epics_base_src=
+
+#-----------------------------------------------------------------------
+# Internal parts (There is typically no need to modify these)
+#-----------------------------------------------------------------------
+
+# Define the possible locations of EpicsHostArch.pl
+set _epics_host_arch_pl=
+set _src_epics_host_arch_pl=
+if ("$_epics_base" != '') then
+ set _epics_host_arch_pl="$_epics_base/lib/perl/EpicsHostArch.pl"
+endif
+if ("$_epics_base_src" != '') then
+ set _src_epics_host_arch_pl="$_epics_base_src/src/tools/EpicsHostArch.pl"
+endif
+
+# Set the EPICS host architecture specification
+if ("$_epics_host_arch" != '') then
+ setenv EPICS_HOST_ARCH "$_epics_host_arch"
+else if (-e "$_epics_host_arch_pl") then
+ set _epics_host_arch=`"$_perl_prog" "$_epics_host_arch_pl"`
+ setenv EPICS_HOST_ARCH "$_epics_host_arch"
+else if (-e "$_src_epics_host_arch_pl") then
+ set _epics_host_arch=`"$_perl_prog" "$_src_epics_host_arch_pl"`
+ setenv EPICS_HOST_ARCH "$_epics_host_arch"
+endif
+
+# Add the EPICS Base host architecture bin directory to PATH
+if ("$_auto_path_append" == yes) then
+ if ("$_epics_base" != '' && "$_epics_host_arch" != '') then
+ setenv PATH "${PATH}:$_epics_base/bin/$_epics_host_arch"
+ endif
+endif
+
+# Don't leak variables into the environment
+unset _auto
+unset _auto_path_append
+unset _perl_prog
+unset _epics_host_arch
+unset _epics_base
+unset _epics_base_src
+unset _epics_host_arch_pl
+unset _src_epics_host_arch_pl
From 998fa984babf11735df9cca8f18b6b7d6349bd16 Mon Sep 17 00:00:00 2001
From: "J. Lewis Muir"
Date: Fri, 20 Jul 2018 17:30:30 -0500
Subject: [PATCH 065/147] Rewrite startup/win32.bat
Remove extraneous things unrelated to EPICS Base.
Make it behave consistently with the other startup scripts.
Make it easy to configure both for a human and a program.
---
startup/win32.bat | 178 +++++++++++++++++++++++++++-------------------
1 file changed, 105 insertions(+), 73 deletions(-)
diff --git a/startup/win32.bat b/startup/win32.bat
index 575b06f42..6652fc97c 100644
--- a/startup/win32.bat
+++ b/startup/win32.bat
@@ -1,73 +1,105 @@
-@ECHO OFF
-REM *************************************************************************
-REM Copyright (c) 2017 UChicago Argonne LLC, as Operator of Argonne
-REM National Laboratory.
-REM Copyright (c) 2002 The Regents of the University of California, as
-REM Operator of Los Alamos National Laboratory.
-REM EPICS BASE is distributed subject to a Software License Agreement found
-REM in file LICENSE that is included with this distribution.
-REM *************************************************************************
-REM
-REM EPICS build configuration environment settings
-REM
-REM Installers should modify these definitions as appropriate.
-REM This file configures the PATH variable from scratch.
-
-REM ======================================================
-REM ====== REQUIRED ENVIRONMENT VARIABLES FOLLOW ======
-REM ======================================================
-
-REM ======================================================
-REM ---------------- WINDOWS -------------------------
-REM ======================================================
-REM ----- WINXP, Vista, Windows 7 -----
-set PATH=C:\Windows\System32;C:\Windows;C:\Windows\System32\Wbem
-
-REM ======================================================
-REM --------------- Strawberry Perl ------------------
-REM ======================================================
-
-set PATH=C:\Strawberry\perl\bin;%PATH%
-set PATH=C:\Strawberry\perl\site\bin;%PATH%
-set PATH=C:\Strawberry\c\bin;%PATH%
-
-REM ======================================================
-REM --------------- Visual C++ -----------------------
-REM ======================================================
-REM -- win32-x86 ---
-
-REM ----- Visual Studio 2010 -----
-REM call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x86
-
-REM ----- Visual Studio 2015 -----
-call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86
-
-REM ======================================================
-REM --------------- EPICS Base -----------------------
-REM ======================================================
-set EPICS_HOST_ARCH=win32-x86
-set PATH=%PATH%;G:\epics\base\bin\%EPICS_HOST_ARCH%
-
-REM ======================================================
-REM ====== OPTIONAL ENVIRONMENT VARIABLES FOLLOW =====
-REM ======================================================
-
-REM ======================================================
-REM --------------------- Git ------------------------
-REM ======================================================
-set PATH=%PATH%;C:\Program files\Git
-
-REM ======================================================
-REM --------------- EPICS Extensions -----------------
-REM ======================================================
-REM set PATH=%PATH%;G:\epics\extensions\bin\%EPICS_HOST_ARCH%
-
-REM ======================================================
-REM --------------- Exceed ---------------------------
-REM ======================================================
-REM Needed for X11 extensions
-REM set EX_VER=14.00
-REM set EX_VER=15.00
-REM set PATH=%PATH%;C:\Exceed%EX_VER%\XDK\
-REM set PATH=%PATH%;C:\Program Files\Hummingbird\Connectivity\%EX_VER%\Exceed\
-
+@echo off
+rem *************************************************************************
+rem Copyright (c) 2017 UChicago Argonne LLC, as Operator of Argonne
+rem National Laboratory.
+rem Copyright (c) 2002 The Regents of the University of California, as
+rem Operator of Los Alamos National Laboratory.
+rem EPICS BASE is distributed subject to a Software License Agreement found
+rem in file LICENSE that is included with this distribution.
+rem *************************************************************************
+rem
+rem Site-specific EPICS environment settings
+rem
+rem Sets EPICS_HOST_ARCH and the environment for Microsoft Visual Studio.
+rem Optionally, resets PATH, adds Strawberry Perl to PATH, and adds the
+rem EPICS Base install host architecture bin directory to PATH.
+rem
+
+rem ----------------------------------------------------------------------
+rem Site serviceable parts (These definitions may be modified)
+rem ----------------------------------------------------------------------
+
+rem The values of the definitions in this section must not contain
+rem double-quotes.
+rem
+rem * Right: set _foo=C:\foo
+rem * Right: set "_foo=C:\foo"
+rem * Wrong: set _foo="C:\foo"
+
+rem Automatically set up the environment when possible ("yes" or "no").
+rem If set to yes, as much of the environment will be set up as possible.
+rem If set to no, just the minimum environment will be set up. More
+rem specific _auto_* definitions take precedence over this definition.
+set _auto=no
+
+rem Automatically reset PATH ("yes" or "no"). If set to yes, PATH will
+rem be reset to the value of _path_new. If set to no, PATH will not be
+rem reset.
+set _auto_path_reset=%_auto%
+
+rem Automatically append to PATH ("yes" or "no"). If set to yes, the
+rem EPICS Base install host architecture bin directory will be added to
+rem PATH if possible. If set to no, the bin directory will not be added
+rem to PATH.
+set _auto_path_append=%_auto%
+
+rem The new value for PATH. If _auto_path_reset is yes, PATH will be set
+rem to it.
+set _path_new=C:\Windows\System32;C:\Windows;C:\Windows\System32\wbem
+
+rem The location of Strawberry Perl (pathname). If empty, Strawberry Perl
+rem is assumed to already be in PATH and will not be added. If nonempty,
+rem Strawberry Perl will be added to PATH.
+set _strawberry_perl_home=C:\Strawberry
+
+rem The location of Microsoft Visual Studio (pathname).
+set _visual_studio_home=C:\Program Files (x86)\Microsoft Visual Studio 14.0
+
+rem The EPICS host architecture specification for EPICS_HOST_ARCH
+rem (-[-] as defined in configure/CONFIG_SITE).
+set _epics_host_arch=win32-x86
+
+rem The install location of EPICS Base (pathname). If nonempty and
+rem _auto_path_append is yes, it will be used to add the host architecture
+rem bin directory to PATH.
+set _epics_base=
+
+rem ----------------------------------------------------------------------
+rem Internal parts (There is typically no need to modify these)
+rem ----------------------------------------------------------------------
+
+rem Reset PATH
+if "%_auto_path_reset%" == "yes" (
+ set "PATH=%_path_new%"
+)
+
+rem Add Strawberry Perl to PATH
+if "%_strawberry_perl_home%" == "" goto after_add_strawberry_perl
+rem Can't do this inside parentheses because PATH would be read only once
+set "PATH=%PATH%;%_strawberry_perl_home%\c\bin"
+set "PATH=%PATH%;%_strawberry_perl_home%\perl\site\bin"
+set "PATH=%PATH%;%_strawberry_perl_home%\perl\bin"
+:after_add_strawberry_perl
+
+rem Set the environment for Microsoft Visual Studio
+call "%_visual_studio_home%\VC\vcvarsall.bat" x86
+
+rem Set the EPICS host architecture specification
+set "EPICS_HOST_ARCH=%_epics_host_arch%"
+
+rem Add the EPICS Base host architecture bin directory to PATH
+if "%_auto_path_append%" == "yes" (
+ if not "%_epics_base%" == "" (
+ set "PATH=%PATH%;%_epics_base%\bin\%_epics_host_arch%"
+ )
+)
+
+rem Don't leak variables into the environment
+set _auto=
+set _auto_path_reset=
+set _auto_path_append=
+set _path_new=
+set _strawberry_perl_home=
+set _visual_studio_home=
+set _epics_host_arch=
+set _epics_base=
From 80869a0868aebfc9b3576793ad62d33d13967b12 Mon Sep 17 00:00:00 2001
From: "J. Lewis Muir"
Date: Fri, 20 Jul 2018 17:43:01 -0500
Subject: [PATCH 066/147] Rewrite startup/windows.bat
Remove extraneous things unrelated to EPICS Base.
Make it behave consistently with the other startup scripts.
Make it easy to configure both for a human and a program.
---
startup/windows.bat | 178 ++++++++++++++++++++++++++------------------
1 file changed, 105 insertions(+), 73 deletions(-)
diff --git a/startup/windows.bat b/startup/windows.bat
index 1b0d32eb2..877c0d5a9 100644
--- a/startup/windows.bat
+++ b/startup/windows.bat
@@ -1,73 +1,105 @@
-@ECHO OFF
-REM *************************************************************************
-REM Copyright (c) 2017 UChicago Argonne LLC, as Operator of Argonne
-REM National Laboratory.
-REM Copyright (c) 2002 The Regents of the University of California, as
-REM Operator of Los Alamos National Laboratory.
-REM EPICS BASE is distributed subject to a Software License Agreement found
-REM in file LICENSE that is included with this distribution.
-REM *************************************************************************
-REM
-REM EPICS build configuration environment settings
-REM
-REM Installers should modify these definitions as appropriate.
-REM This file configures the PATH variable from scratch.
-
-REM ======================================================
-REM ====== REQUIRED ENVIRONMENT VARIABLES FOLLOW =====
-REM ======================================================
-
-REM ======================================================
-REM ---------------- WINDOWS -------------------------
-REM ======================================================
-REM ----- WINXP, Vista, Windows 7 -----
-set PATH=C:\Windows\System32;C:\Windows;C:\Windows\System32\Wbem
-
-REM ======================================================
-REM --------------- Strawberry Perl ------------------
-REM ======================================================
-
-set PATH=C:\Strawberry\perl\bin;%PATH%
-set PATH=C:\Strawberry\perl\site\bin;%PATH%
-set PATH=C:\Strawberry\c\bin;%PATH%
-
-REM ======================================================
-REM --------------- Visual C++ -----------------------
-REM ======================================================
-REM -- windows-x64 ---
-
-REM ----- Visual Studio 2010 -----
-REM call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x64
-
-REM ----- Visual Studio 2015 -----
-call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64
-
-REM ======================================================
-REM --------------- EPICS Base -----------------------
-REM ======================================================
-set EPICS_HOST_ARCH=windows-x64
-set PATH=%PATH%;G:\epics\base\bin\%EPICS_HOST_ARCH%
-
-REM ======================================================
-REM ====== OPTIONAL ENVIRONMENT VARIABLES FOLLOW =====
-REM ======================================================
-
-REM ======================================================
-REM --------------------- Git ------------------------
-REM ======================================================
-set PATH=%PATH%;C:\Program files\Git
-
-REM ======================================================
-REM --------------- EPICS Extensions -----------------
-REM ======================================================
-REM set PATH=%PATH%;G:\epics\extensions\bin\%EPICS_HOST_ARCH%
-
-REM ======================================================
-REM --------------- Exceed ---------------------------
-REM ======================================================
-REM Needed for X11 extensions
-REM set EX_VER=14.00
-REM set EX_VER=15.00
-REM set PATH=%PATH%;C:\Exceed%EX_VER%\XDK\
-REM set PATH=%PATH%;C:\Program Files\Hummingbird\Connectivity\%EX_VER%\Exceed\
-
+@echo off
+rem *************************************************************************
+rem Copyright (c) 2017 UChicago Argonne LLC, as Operator of Argonne
+rem National Laboratory.
+rem Copyright (c) 2002 The Regents of the University of California, as
+rem Operator of Los Alamos National Laboratory.
+rem EPICS BASE is distributed subject to a Software License Agreement found
+rem in file LICENSE that is included with this distribution.
+rem *************************************************************************
+rem
+rem Site-specific EPICS environment settings
+rem
+rem Sets EPICS_HOST_ARCH and the environment for Microsoft Visual Studio.
+rem Optionally, resets PATH, adds Strawberry Perl to PATH, and adds the
+rem EPICS Base install host architecture bin directory to PATH.
+rem
+
+rem ----------------------------------------------------------------------
+rem Site serviceable parts (These definitions may be modified)
+rem ----------------------------------------------------------------------
+
+rem The values of the definitions in this section must not contain
+rem double-quotes.
+rem
+rem * Right: set _foo=C:\foo
+rem * Right: set "_foo=C:\foo"
+rem * Wrong: set _foo="C:\foo"
+
+rem Automatically set up the environment when possible ("yes" or "no").
+rem If set to yes, as much of the environment will be set up as possible.
+rem If set to no, just the minimum environment will be set up. More
+rem specific _auto_* definitions take precedence over this definition.
+set _auto=no
+
+rem Automatically reset PATH ("yes" or "no"). If set to yes, PATH will
+rem be reset to the value of _path_new. If set to no, PATH will not be
+rem reset.
+set _auto_path_reset=%_auto%
+
+rem Automatically append to PATH ("yes" or "no"). If set to yes, the
+rem EPICS Base install host architecture bin directory will be added to
+rem PATH if possible. If set to no, the bin directory will not be added
+rem to PATH.
+set _auto_path_append=%_auto%
+
+rem The new value for PATH. If _auto_path_reset is yes, PATH will be set
+rem to it.
+set _path_new=C:\Windows\System32;C:\Windows;C:\Windows\System32\wbem
+
+rem The location of Strawberry Perl (pathname). If empty, Strawberry Perl
+rem is assumed to already be in PATH and will not be added. If nonempty,
+rem Strawberry Perl will be added to PATH.
+set _strawberry_perl_home=C:\Strawberry
+
+rem The location of Microsoft Visual Studio (pathname).
+set _visual_studio_home=C:\Program Files (x86)\Microsoft Visual Studio 14.0
+
+rem The EPICS host architecture specification for EPICS_HOST_ARCH
+rem (-[-] as defined in configure/CONFIG_SITE).
+set _epics_host_arch=windows-x64
+
+rem The install location of EPICS Base (pathname). If nonempty and
+rem _auto_path_append is yes, it will be used to add the host architecture
+rem bin directory to PATH.
+set _epics_base=
+
+rem ----------------------------------------------------------------------
+rem Internal parts (There is typically no need to modify these)
+rem ----------------------------------------------------------------------
+
+rem Reset PATH
+if "%_auto_path_reset%" == "yes" (
+ set "PATH=%_path_new%"
+)
+
+rem Add Strawberry Perl to PATH
+if "%_strawberry_perl_home%" == "" goto after_add_strawberry_perl
+rem Can't do this inside parentheses because PATH would be read only once
+set "PATH=%PATH%;%_strawberry_perl_home%\c\bin"
+set "PATH=%PATH%;%_strawberry_perl_home%\perl\site\bin"
+set "PATH=%PATH%;%_strawberry_perl_home%\perl\bin"
+:after_add_strawberry_perl
+
+rem Set the environment for Microsoft Visual Studio
+call "%_visual_studio_home%\VC\vcvarsall.bat" x64
+
+rem Set the EPICS host architecture specification
+set "EPICS_HOST_ARCH=%_epics_host_arch%"
+
+rem Add the EPICS Base host architecture bin directory to PATH
+if "%_auto_path_append%" == "yes" (
+ if not "%_epics_base%" == "" (
+ set "PATH=%PATH%;%_epics_base%\bin\%_epics_host_arch%"
+ )
+)
+
+rem Don't leak variables into the environment
+set _auto=
+set _auto_path_reset=
+set _auto_path_append=
+set _path_new=
+set _strawberry_perl_home=
+set _visual_studio_home=
+set _epics_host_arch=
+set _epics_base=
From 4e9cf72d712a96df2dd48158d27ab9a9896004f0 Mon Sep 17 00:00:00 2001
From: "J. Lewis Muir"
Date: Fri, 20 Jul 2018 17:45:47 -0500
Subject: [PATCH 067/147] Remove execute file mode bit on EpicsHostArch.pl
---
src/tools/EpicsHostArch.pl | 0
1 file changed, 0 insertions(+), 0 deletions(-)
mode change 100755 => 100644 src/tools/EpicsHostArch.pl
diff --git a/src/tools/EpicsHostArch.pl b/src/tools/EpicsHostArch.pl
old mode 100755
new mode 100644
From 89870e28179552cb256edadd672fbe6d0777aa32 Mon Sep 17 00:00:00 2001
From: "J. Lewis Muir"
Date: Fri, 20 Jul 2018 17:47:39 -0500
Subject: [PATCH 068/147] Remove trailing space in license of startup/unix.*
---
startup/unix.csh | 2 +-
startup/unix.sh | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/startup/unix.csh b/startup/unix.csh
index dce441ea8..788a639e6 100644
--- a/startup/unix.csh
+++ b/startup/unix.csh
@@ -5,7 +5,7 @@
# 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.
+# in file LICENSE that is included with this distribution.
#*************************************************************************
#
# Site-specific EPICS environment settings
diff --git a/startup/unix.sh b/startup/unix.sh
index 8f45629ee..a8d8328ec 100644
--- a/startup/unix.sh
+++ b/startup/unix.sh
@@ -5,7 +5,7 @@
# 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.
+# in file LICENSE that is included with this distribution.
#*************************************************************************
#
# Site-specific EPICS environment settings
From ec351c5e2f995770b3fc6788b63cf76990fbb2f3 Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Fri, 20 Jul 2018 23:10:34 -0500
Subject: [PATCH 069/147] Fix for lp: #1730727
Post monitors on all array-length record fields (often NORD)
when their values get changed.
---
documentation/RELEASE_NOTES.html | 8 +++++++
src/std/dev/devAaiSoft.c | 9 ++++++--
src/std/dev/devSASoft.c | 5 ++++-
src/std/dev/devWfSoft.c | 7 ++++++-
src/std/rec/aaiRecord.c | 36 +++++++++++++++++++++-----------
src/std/rec/aaoRecord.c | 11 ++++++----
src/std/rec/compressRecord.c | 8 +++++--
src/std/rec/subArrayRecord.c | 18 +++++++++-------
src/std/rec/waveformRecord.c | 26 ++++++++++++-----------
9 files changed, 86 insertions(+), 42 deletions(-)
diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html
index 59cd4ce18..8e902238b 100644
--- a/documentation/RELEASE_NOTES.html
+++ b/documentation/RELEASE_NOTES.html
@@ -16,6 +16,14 @@
+
All array records now post monitors on their array-length fields
+
+The waveform record has been posting monitors on its NORD field since Base
+3.15.0.1; we finally got around to doing the equivalent in all the other
+built-in record types, which even required modifying device support in some
+cases. This fixes
+Launchpad bug #1730727.
+
HOWTO: Converting Wiki Record Reference to POD
Some documentation has been added to the dbdToHtml.pl script
diff --git a/src/std/dev/devAaiSoft.c b/src/std/dev/devAaiSoft.c
index 586483c92..4aa1f4cc3 100644
--- a/src/std/dev/devAaiSoft.c
+++ b/src/std/dev/devAaiSoft.c
@@ -4,7 +4,7 @@
* 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 file LICENSE that is included with this distribution.
\*************************************************************************/
/*
@@ -71,13 +71,18 @@ static long init_record(aaiRecord *prec)
static long read_aai(aaiRecord *prec)
{
+ epicsUInt32 nord = prec->nord;
long nRequest = prec->nelm;
dbGetLink(prec->simm == menuYesNoYES ? &prec->siol : &prec->inp,
prec->ftvl, prec->bptr, 0, &nRequest);
+
if (nRequest > 0) {
prec->nord = nRequest;
- prec->udf=FALSE;
+ if (nord != prec->nord)
+ db_post_events(prec, &prec->nord, DBE_VALUE | DBE_LOG);
+
+ prec->udf = FALSE;
if (prec->tsel.type == CONSTANT &&
prec->tse == epicsTimeEventDeviceTime)
dbGetTimeStamp(&prec->inp, &prec->time);
diff --git a/src/std/dev/devSASoft.c b/src/std/dev/devSASoft.c
index 6c0c876f0..5f5d8189f 100644
--- a/src/std/dev/devSASoft.c
+++ b/src/std/dev/devSASoft.c
@@ -4,7 +4,7 @@
* Copyright (c) 2002 Lawrence Berkeley Laboratory,The Control Systems
* Group, Systems Engineering Department
* EPICS BASE is distributed subject to a Software License Agreement found
-* in file LICENSE that is included with this distribution.
+* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
@@ -67,6 +67,7 @@ static long init_record(subArrayRecord *prec)
static long read_sa(subArrayRecord *prec)
{
long nRequest = prec->indx + prec->nelm;
+ epicsUInt32 nord = prec->nord;
long ecount;
if (nRequest > prec->malm)
@@ -89,6 +90,8 @@ static long read_sa(subArrayRecord *prec)
ecount = 0;
prec->nord = ecount;
+ if (nord != prec->nord)
+ db_post_events(prec, &prec->nord, DBE_VALUE | DBE_LOG);
if (nRequest > 0 &&
prec->tsel.type == CONSTANT &&
diff --git a/src/std/dev/devWfSoft.c b/src/std/dev/devWfSoft.c
index f1754f78e..0d58c5f52 100644
--- a/src/std/dev/devWfSoft.c
+++ b/src/std/dev/devWfSoft.c
@@ -4,7 +4,7 @@
* 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 file LICENSE that is included with this distribution.
\*************************************************************************/
/*
@@ -67,11 +67,16 @@ static long init_record(waveformRecord *prec)
static long read_wf(waveformRecord *prec)
{
+ epicsUInt32 nord = prec->nord;
long nRequest = prec->nelm;
dbGetLink(&prec->inp, prec->ftvl, prec->bptr, 0, &nRequest);
+
if (nRequest > 0) {
prec->nord = nRequest;
+ if (nord != prec->nord)
+ db_post_events(prec, &prec->nord, DBE_VALUE | DBE_LOG);
+
if (prec->tsel.type == CONSTANT &&
prec->tse == epicsTimeEventDeviceTime)
dbGetTimeStamp(&prec->inp, &prec->time);
diff --git a/src/std/rec/aaiRecord.c b/src/std/rec/aaiRecord.c
index 5b370fe4c..088777b30 100644
--- a/src/std/rec/aaiRecord.c
+++ b/src/std/rec/aaiRecord.c
@@ -2,7 +2,7 @@
* Copyright (c) 2002 Southeastern Universities Research Association, as
* Operator of Thomas Jefferson National Accelerator Facility.
* EPICS BASE is distributed subject to a Software License Agreement found
-* in file LICENSE that is included with this distribution.
+* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* recAai.c */
@@ -11,7 +11,7 @@
* Original Author: Dave Barker
*
* C E B A F
- *
+ *
* Continuous Electron Beam Accelerator Facility
* Newport News, Virginia, USA.
*
@@ -139,12 +139,12 @@ static long init_record(aaiRecord *prec, int pass)
}
return 0;
}
-
+
/* SIML must be a CONSTANT or a PV_LINK or a DB_LINK */
if (prec->siml.type == CONSTANT) {
recGblInitConstantLink(&prec->siml,DBF_USHORT,&prec->simm);
}
-
+
/* must have read_aai function defined */
if (pdset->number < 5 || pdset->read_aai == NULL) {
recGblRecordError(S_dev_missingSup, prec, "aai: init_record");
@@ -204,10 +204,14 @@ static long get_array_info(DBADDR *paddr, long *no_elements, long *offset)
static long put_array_info(DBADDR *paddr, long nNew)
{
aaiRecord *prec = (aaiRecord *)paddr->precord;
+ epicsUInt32 nord = prec->nord;
prec->nord = nNew;
if (prec->nord > prec->nelm)
prec->nord = prec->nelm;
+
+ if (nord != prec->nord)
+ db_post_events(prec, &prec->nord, DBE_VALUE | DBE_LOG);
return 0;
}
@@ -220,7 +224,7 @@ static long get_units(DBADDR *paddr, char *units)
switch (dbGetFieldIndex(paddr)) {
case indexof(VAL):
if (prec->ftvl == DBF_STRING || prec->ftvl == DBF_ENUM)
- break;
+ break;
case indexof(HOPR):
case indexof(LOPR):
strncpy(units,prec->egu,DB_UNITS_SIZE);
@@ -314,12 +318,11 @@ static void monitor(aaiRecord *prec)
static long readValue(aaiRecord *prec)
{
- long status;
struct aaidset *pdset = (struct aaidset *)prec->dset;
+ long status;
if (prec->pact == TRUE){
- status = pdset->read_aai(prec);
- return status;
+ return pdset->read_aai(prec);
}
status = dbGetLink(&prec->siml, DBR_ENUM, &prec->simm, 0, 0);
@@ -327,10 +330,16 @@ static long readValue(aaiRecord *prec)
return status;
if (prec->simm == menuYesNoNO){
- return pdset->read_aai(prec);
+ epicsUInt32 nord = prec->nord;
+
+ status = pdset->read_aai(prec);
+ if (nord != prec->nord)
+ db_post_events(prec, &prec->nord, DBE_VALUE | DBE_LOG);
+ return status;
}
-
+
if (prec->simm == menuYesNoYES){
+ epicsUInt32 nord = prec->nord;
/* Device suport is responsible for buffer
which might be read-only so we may not be
allowed to call dbGetLink on it.
@@ -339,10 +348,13 @@ static long readValue(aaiRecord *prec)
Thus call device now.
*/
recGblSetSevr(prec, SIMM_ALARM, prec->sims);
- return pdset->read_aai(prec);
+
+ status = pdset->read_aai(prec);
+ if (nord != prec->nord)
+ db_post_events(prec, &prec->nord, DBE_VALUE | DBE_LOG);
+ return status;
}
recGblSetSevr(prec, SOFT_ALARM, INVALID_ALARM);
return -1;
}
-
diff --git a/src/std/rec/aaoRecord.c b/src/std/rec/aaoRecord.c
index 565fd2886..d2d652b5e 100644
--- a/src/std/rec/aaoRecord.c
+++ b/src/std/rec/aaoRecord.c
@@ -2,7 +2,7 @@
* Copyright (c) 2002 Southeastern Universities Research Association, as
* Operator of Thomas Jefferson National Accelerator Facility.
* EPICS BASE is distributed subject to a Software License Agreement found
-* in file LICENSE that is included with this distribution.
+* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* recAao.c */
@@ -11,7 +11,7 @@
* Original Author: Dave Barker
*
* C E B A F
- *
+ *
* Continuous Electron Beam Accelerator Facility
* Newport News, Virginia, USA.
*
@@ -204,10 +204,14 @@ static long get_array_info(DBADDR *paddr, long *no_elements, long *offset)
static long put_array_info(DBADDR *paddr, long nNew)
{
aaoRecord *prec = (aaoRecord *)paddr->precord;
+ epicsUInt32 nord = prec->nord;
prec->nord = nNew;
if (prec->nord > prec->nelm)
prec->nord = prec->nelm;
+
+ if (nord != prec->nord)
+ db_post_events(prec, &prec->nord, DBE_VALUE | DBE_LOG);
return 0;
}
@@ -220,7 +224,7 @@ static long get_units(DBADDR *paddr, char *units)
switch (dbGetFieldIndex(paddr)) {
case indexof(VAL):
if (prec->ftvl == DBF_STRING || prec->ftvl == DBF_ENUM)
- break;
+ break;
case indexof(HOPR):
case indexof(LOPR):
strncpy(units,prec->egu,DB_UNITS_SIZE);
@@ -343,4 +347,3 @@ static long writeValue(aaoRecord *prec)
recGblSetSevr(prec, SOFT_ALARM, INVALID_ALARM);
return -1;
}
-
diff --git a/src/std/rec/compressRecord.c b/src/std/rec/compressRecord.c
index fd99412e5..244f6f399 100644
--- a/src/std/rec/compressRecord.c
+++ b/src/std/rec/compressRecord.c
@@ -4,12 +4,12 @@
* 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 file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Original Author: Bob Dalesio
- * Date: 7-14-89
+ * Date: 7-14-89
*/
#include
@@ -405,11 +405,15 @@ static long get_array_info(DBADDR *paddr, long *no_elements, long *offset)
static long put_array_info(DBADDR *paddr, long nNew)
{
compressRecord *prec = (compressRecord *) paddr->precord;
+ epicsUInt32 nuse = prec->nuse;
prec->off = (prec->off + nNew) % prec->nsam;
prec->nuse += nNew;
if (prec->nuse > prec->nsam)
prec->nuse = prec->nsam;
+
+ if (nuse != prec->nuse)
+ db_post_events(prec, &prec->nuse, DBE_VALUE | DBE_LOG);
return 0;
}
diff --git a/src/std/rec/subArrayRecord.c b/src/std/rec/subArrayRecord.c
index 197750b81..e480e9184 100644
--- a/src/std/rec/subArrayRecord.c
+++ b/src/std/rec/subArrayRecord.c
@@ -2,17 +2,17 @@
* Copyright (c) 2002 Lawrence Berkeley Laboratory,The Control Systems
* Group, Systems Engineering Department
* EPICS BASE is distributed subject to a Software License Agreement found
-* in file LICENSE that is included with this distribution.
+* in file LICENSE that is included with this distribution.
\*************************************************************************/
-/* recSubArray.c - Record Support Routines for SubArray records
+/* recSubArray.c - Record Support Routines for SubArray records
*
*
* Author: Carl Lionberger
* Date: 090293
*
* NOTES:
- * Derived from waveform record.
+ * Derived from waveform record.
* Modification Log:
* -----------------
*/
@@ -124,7 +124,7 @@ static long init_record(subArrayRecord *prec, int pass)
}
if (pdset->init_record)
- return (*pdset->init_record)(prec);
+ return pdset->init_record(prec);
return 0;
}
@@ -191,11 +191,14 @@ static long get_array_info(DBADDR *paddr, long *no_elements, long *offset)
static long put_array_info(DBADDR *paddr, long nNew)
{
subArrayRecord *prec = (subArrayRecord *) paddr->precord;
+ epicsUInt32 nord = prec->nord;
- if (nNew > prec->malm)
- nNew = prec->malm;
prec->nord = nNew;
+ if (prec->nord > prec->malm)
+ prec->nord = prec->malm;
+ if (nord != prec->nord)
+ db_post_events(prec, &prec->nord, DBE_VALUE | DBE_LOG);
return 0;
}
@@ -208,7 +211,7 @@ static long get_units(DBADDR *paddr, char *units)
switch (dbGetFieldIndex(paddr)) {
case indexof(VAL):
if (prec->ftvl == DBF_STRING || prec->ftvl == DBF_ENUM)
- break;
+ break;
case indexof(HOPR):
case indexof(LOPR):
strncpy(units,prec->egu,DB_UNITS_SIZE);
@@ -318,4 +321,3 @@ static long readValue(subArrayRecord *prec)
return status;
}
-
diff --git a/src/std/rec/waveformRecord.c b/src/std/rec/waveformRecord.c
index ab00a39fd..c65d07964 100644
--- a/src/std/rec/waveformRecord.c
+++ b/src/std/rec/waveformRecord.c
@@ -4,7 +4,7 @@
* 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 file LICENSE that is included with this distribution.
\*************************************************************************/
/* recWaveform.c - Record Support Routines for Waveform records */
@@ -184,12 +184,14 @@ static long get_array_info(DBADDR *paddr, long *no_elements, long *offset)
static long put_array_info(DBADDR *paddr, long nNew)
{
waveformRecord *prec = (waveformRecord *) paddr->precord;
+ epicsUInt32 nord = prec->nord;
prec->nord = nNew;
if (prec->nord > prec->nelm)
prec->nord = prec->nelm;
- db_post_events(prec, &prec->nord, DBE_VALUE | DBE_LOG);
+ if (nord != prec->nord)
+ db_post_events(prec, &prec->nord, DBE_VALUE | DBE_LOG);
return 0;
}
@@ -202,7 +204,7 @@ static long get_units(DBADDR *paddr, char *units)
switch (dbGetFieldIndex(paddr)) {
case indexof(VAL):
if (prec->ftvl == DBF_STRING || prec->ftvl == DBF_ENUM)
- break;
+ break;
case indexof(HOPR):
case indexof(LOPR):
strncpy(units,prec->egu,DB_UNITS_SIZE);
@@ -305,36 +307,37 @@ static void monitor(waveformRecord *prec)
static long readValue(waveformRecord *prec)
{
- long status;
struct wfdset *pdset = (struct wfdset *) prec->dset;
+ long status;
if (prec->pact == TRUE){
- return (*pdset->read_wf)(prec);
+ return pdset->read_wf(prec);
}
- status = dbGetLink(&(prec->siml), DBR_ENUM, &(prec->simm),0,0);
+ status = dbGetLink(&prec->siml, DBR_ENUM, &prec->simm, 0, 0);
if (status)
return status;
if (prec->simm == menuYesNoNO){
epicsUInt32 nord = prec->nord;
- status = (*pdset->read_wf)(prec);
+ status = pdset->read_wf(prec);
if (nord != prec->nord)
db_post_events(prec, &prec->nord, DBE_VALUE | DBE_LOG);
return status;
}
if (prec->simm == menuYesNoYES){
+ epicsUInt32 nord = prec->nord;
long nRequest = prec->nelm;
- status = dbGetLink(&(prec->siol), prec->ftvl, prec->bptr, 0, &nRequest);
- /* nord set only for db links: needed for old db_access */
+ status = dbGetLink(&prec->siol, prec->ftvl, prec->bptr, 0, &nRequest);
if (prec->siol.type != CONSTANT) {
prec->nord = nRequest;
- db_post_events(prec, &prec->nord, DBE_VALUE | DBE_LOG);
+ if (nord != prec->nord)
+ db_post_events(prec, &prec->nord, DBE_VALUE | DBE_LOG);
if (status == 0)
- prec->udf=FALSE;
+ prec->udf = FALSE;
}
} else {
recGblSetSevr(prec, SOFT_ALARM, INVALID_ALARM);
@@ -344,4 +347,3 @@ static long readValue(waveformRecord *prec)
return status;
}
-
From 45be2306bdf6d09fdc4c2af6ac0ad2e2d8f74d4a Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Sat, 21 Jul 2018 01:04:05 -0500
Subject: [PATCH 070/147] Add missing includes for db_post_events()
---
src/std/dev/devAaiSoft.c | 1 +
src/std/dev/devSASoft.c | 1 +
2 files changed, 2 insertions(+)
diff --git a/src/std/dev/devAaiSoft.c b/src/std/dev/devAaiSoft.c
index 4aa1f4cc3..7a8ca9832 100644
--- a/src/std/dev/devAaiSoft.c
+++ b/src/std/dev/devAaiSoft.c
@@ -22,6 +22,7 @@
#include "alarm.h"
#include "dbDefs.h"
#include "dbAccess.h"
+#include "dbEvent.h"
#include "recGbl.h"
#include "devSup.h"
#include "cantProceed.h"
diff --git a/src/std/dev/devSASoft.c b/src/std/dev/devSASoft.c
index 5f5d8189f..a49b1bc49 100644
--- a/src/std/dev/devSASoft.c
+++ b/src/std/dev/devSASoft.c
@@ -19,6 +19,7 @@
#include "alarm.h"
#include "dbDefs.h"
#include "dbAccess.h"
+#include "dbEvent.h"
#include "recGbl.h"
#include "devSup.h"
#include "subArrayRecord.h"
From c09b6e2f1b34ea1925e8ff2678811b40bc23f5ca Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Sat, 21 Jul 2018 01:47:33 -0500
Subject: [PATCH 071/147] libCom: Add and use a -o option to e_flex
Note that like the -S option the filename must follow immediately in
the same command-line argument with no space.
---
configure/RULES_BUILD | 6 ++----
src/libCom/flex/flex.c | 11 +++++++++--
2 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/configure/RULES_BUILD b/configure/RULES_BUILD
index cec33eca7..1c38eef4c 100644
--- a/configure/RULES_BUILD
+++ b/configure/RULES_BUILD
@@ -256,15 +256,13 @@ YACCOPT ?= $($*_YACCOPT)
$(MV) $*.tab.c $*.c
$(if $(findstring -d, $(YACCOPT)),$(MV) $*.tab.h $*.h,)
-# must be a seperate rule since when not using '-d' the
+# must be a separate rule since when not using '-d' the
# prefix for .h will be different then .c
%.h : %.c %.y
%.c: %.l
- @$(RM) $*.yy.c
- $(LEX) $(LEXOPT) -t $< > $*.yy.c
@$(RM) $@
- $(MV) $*.yy.c $@
+ $(LEX) $(LEXOPT) -o$@ $<
#---------------------------------------------------------------
# Libraries, shared/DLL and stubs
diff --git a/src/libCom/flex/flex.c b/src/libCom/flex/flex.c
index 196f4e4cc..8d0400c2b 100644
--- a/src/libCom/flex/flex.c
+++ b/src/libCom/flex/flex.c
@@ -4,7 +4,7 @@
* 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 file LICENSE that is included with this distribution.
\*************************************************************************/
/* flex - tool to generate fast lexical analyzers */
@@ -14,7 +14,7 @@
*
* This code is derived from software contributed to Berkeley by
* Vern Paxson.
- *
+ *
* The United States Government has rights in this work pursuant
* to contract no. DE-AC03-76SF00098 between the United States
* Department of Energy and the University of California.
@@ -495,6 +495,13 @@ void flexinit(int argc, char **argv)
/* stupid do-nothing deprecated option */
break;
+ case 'o':
+ if ( i != 1 )
+ flexerror( "-o flag must be given separately" );
+
+ outfile = arg + i + 1;
+ goto get_next_arg;
+
case 'p':
performance_report = true;
break;
From 67e2b74758982fd46be5529e28fcb93fd7eb59ad Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Wed, 25 Jul 2018 00:31:48 -0500
Subject: [PATCH 072/147] Fix for lp: #1503661
Delete output file if parse errors found in substitution file
---
src/ioc/dbtemplate/msi.c | 67 +++++++++++++++++++++++++++-------------
1 file changed, 45 insertions(+), 22 deletions(-)
diff --git a/src/ioc/dbtemplate/msi.c b/src/ioc/dbtemplate/msi.c
index 5a5023163..a29bb5fc0 100644
--- a/src/ioc/dbtemplate/msi.c
+++ b/src/ioc/dbtemplate/msi.c
@@ -22,6 +22,7 @@
#include
#include
#include
+#include
#define MAX_BUFFER_SIZE 4096
#define MAX_DEPS 1024
@@ -49,6 +50,7 @@ static char *substituteGetGlobalReplacements(subInfo *pvt);
/* Forward references to local routines */
static void usageExit(int status);
+static void abortExit(int status);
static void addMacroReplacements(MAC_HANDLE *macPvt, char *pval);
static void makeSubstitutions(inputData *inputPvt, MAC_HANDLE *macPvt, char *templateName);
@@ -182,7 +184,16 @@ void usageExit(int status)
exit(status);
}
-static void addMacroReplacements(MAC_HANDLE *macPvt,char *pval)
+void abortExit(int status)
+{
+ if (outFile) {
+ fclose(stdout);
+ unlink(outFile);
+ }
+ exit(status);
+}
+
+static void addMacroReplacements(MAC_HANDLE *macPvt, char *pval)
{
char **pairs;
long status;
@@ -268,7 +279,7 @@ static void makeSubstitutions(inputData *inputPvt, MAC_HANDLE *macPvt, char *tem
default:
fprintf(stderr,"msi: Logic error in makeSubstitutions\n");
inputErrPrint(inputPvt);
- exit(1);
+ abortExit(1);
}
free(copy);
expand = 0;
@@ -447,7 +458,7 @@ static void inputOpenFile(inputData *pinputData,char *filename)
if(!fp) {
fprintf(stderr,"msi: Can't open file '%s'\n",filename);
inputErrPrint(pinputData);
- exit(1);
+ abortExit(1);
}
pinputFile = calloc(1,sizeof(inputFile));
if(ppathNode) {
@@ -592,7 +603,7 @@ static void substituteOpen(subInfo **ppvt,char *substitutionName)
fp = fopen(substitutionName,"r");
if(!fp) {
fprintf(stderr,"msi: Can't open file '%s'\n",substitutionName);
- exit(1);
+ abortExit(1);
}
psubFile->substitutionName = substitutionName;
psubFile->fp = fp;
@@ -627,7 +638,7 @@ static int substituteGetNextSet(subInfo *psubInfo,char **filename)
psubInfo->isFile = 1;
if(subGetNextToken(psubFile)!=tokenString) {
subFileErrPrint(psubFile,"Parse error, expecting filename");
- exit(1);
+ abortExit(1);
}
freePattern(psubInfo);
free(psubInfo->filename);
@@ -641,25 +652,29 @@ static int substituteGetNextSet(subInfo *psubInfo,char **filename)
while(subGetNextToken(psubFile)==tokenSeparater);
if(psubFile->token!=tokenLBrace) {
subFileErrPrint(psubFile,"Parse error, expecting {");
- exit(1);
+ abortExit(1);
}
subGetNextToken(psubFile);
}
*filename = psubInfo->filename;
while(psubFile->token==tokenSeparater) subGetNextToken(psubFile);
if(psubFile->token==tokenLBrace) return(1);
- if(psubFile->token==tokenRBrace) return(1);
- if(psubFile->token!=tokenString
- || strcmp(psubFile->string,"pattern")!=0) {
- subFileErrPrint(psubFile,"Parse error, expecting pattern");
- exit(1);
+ if (psubFile->token == tokenRBrace) {
+ subFileErrPrint(psubFile, "Parse error, unexpected '}'");
+ abortExit(1);
+ }
+
+ if (psubFile->token != tokenString ||
+ strcmp(psubFile->string, "pattern") != 0) {
+ subFileErrPrint(psubFile, "Parse error, expecting 'pattern'");
+ abortExit(1);
}
freePattern(psubInfo);
psubInfo->isPattern = 1;
while(subGetNextToken(psubFile)==tokenSeparater);
if(psubFile->token!=tokenLBrace) {
subFileErrPrint(psubFile,"Parse error, expecting {");
- exit(1);
+ abortExit(1);
}
while(1) {
while(subGetNextToken(psubFile)==tokenSeparater);
@@ -670,7 +685,7 @@ static int substituteGetNextSet(subInfo *psubInfo,char **filename)
}
if(psubFile->token!=tokenRBrace) {
subFileErrPrint(psubFile,"Parse error, expecting }");
- exit(1);
+ abortExit(1);
}
subGetNextToken(psubFile);
return(1);
@@ -707,9 +722,13 @@ static char *substituteGetGlobalReplacements(subInfo *psubInfo)
case tokenString:
catMacroReplacements(psubInfo,psubFile->string);
break;
- default:
- subFileErrPrint(psubFile,"Parse error, illegal token");
- exit(1);
+
+ case tokenLBrace:
+ subFileErrPrint(psubFile, "Parse error, unexpected '{'");
+ abortExit(1);
+ case tokenEOF:
+ subFileErrPrint(psubFile, "Parse error, incomplete file?");
+ abortExit(1);
}
}
}
@@ -744,7 +763,7 @@ static char *substituteGetReplacements(subInfo *psubInfo)
}
if(psubFile->token!=tokenString) {
subFileErrPrint(psubFile,"Parse error, illegal token");
- exit(-1);
+ abortExit(1);
}
if(gotFirstPattern) catMacroReplacements(psubInfo,",");
gotFirstPattern = 1;
@@ -772,9 +791,13 @@ static char *substituteGetReplacements(subInfo *psubInfo)
case tokenString:
catMacroReplacements(psubInfo,psubFile->string);
break;
- default:
- subFileErrPrint(psubFile,"Parse error, illegal token");
- exit(1);
+
+ case tokenLBrace:
+ subFileErrPrint(psubFile, "Parse error, unexpected '{'");
+ abortExit(1);
+ case tokenEOF:
+ subFileErrPrint(psubFile, "Parse error, incomplete file?");
+ abortExit(1);
}
}
}
@@ -842,7 +865,7 @@ static tokenType subGetNextToken(subFile *psubFile)
while(*p!='"') {
if(*p==0 || *p=='\n') {
subFileErrPrint(psubFile,"Strings must be on single line\n");
- exit(1);
+ abortExit(1);
}
/*allow escape for imbeded quote*/
if((*p=='\\') && *(p+1)=='"') {
@@ -881,7 +904,7 @@ static void catMacroReplacements(subInfo *psubInfo,const char *value)
if(!newbuf) {
fprintf(stderr,"calloc failed for size %lu\n",
(unsigned long) newsize);
- exit(1);
+ abortExit(1);
}
if(psubInfo->macroReplacements) {
memcpy(newbuf,psubInfo->macroReplacements,psubInfo->curLength);
From fe7260e263da2e7df0e0d463a51ecd9b738ae78d Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Wed, 25 Jul 2018 00:47:18 -0500
Subject: [PATCH 073/147] msi: Source code reformatting, typo fixes, unify
messages
Added lots of debug tracing macros.
Release notes.
---
documentation/RELEASE_NOTES.html | 8 +
src/ioc/dbtemplate/msi.c | 784 ++++++++++++++++++++-----------
2 files changed, 510 insertions(+), 282 deletions(-)
diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html
index 571a1b3a0..57baf3db1 100644
--- a/documentation/RELEASE_NOTES.html
+++ b/documentation/RELEASE_NOTES.html
@@ -16,6 +16,14 @@
+Improvements to msi
+
+In addition to fixing its response to discovering parsing errors in its
+ substitution input file (reported as Launchpad
+ bug #1503661)
+ so it now deletes the incomplete output file, the msi program has been cleaned
+ up a little bit internally.
+
All array records now post monitors on their array-length fields
The waveform record has been posting monitors on its NORD field since Base
diff --git a/src/ioc/dbtemplate/msi.c b/src/ioc/dbtemplate/msi.c
index a29bb5fc0..69680e17e 100644
--- a/src/ioc/dbtemplate/msi.c
+++ b/src/ioc/dbtemplate/msi.c
@@ -4,7 +4,7 @@
* 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.
\*************************************************************************/
/* msi - macro substitutions and include */
@@ -27,6 +27,31 @@
#define MAX_BUFFER_SIZE 4096
#define MAX_DEPS 1024
+#if 0
+/* Debug Tracing */
+int din = 0;
+#define ENTER fprintf(stderr, "%*sEntering %s\n", 2*din++, "", __FUNCTION__)
+
+#define STEP(s) fprintf(stderr, "%*s%s: %s\n", 2*din, "", __FUNCTION__, s)
+#define STEPS(s, v) fprintf(stderr, "%*s%s: %s '%s'\n", 2*din, "", __FUNCTION__, s, v)
+#define STEPD(s, v) fprintf(stderr, "%*s%s: %s %d\n", 2*din, "", __FUNCTION__, s, v)
+
+#define EXIT fprintf(stderr, "%*s%s: Returning\n", 2*din--, "", __FUNCTION__)
+#define EXITD(r) fprintf(stderr, "%*s%s: Returning %d\n", 2*din--, "", __FUNCTION__, r)
+#define EXITS(r) fprintf(stderr, "%*s%s: Returning '%s'\n", 2*din--, "", __FUNCTION__, r)
+#else
+#define ENTER
+
+#define STEP(s)
+#define STEPS(s, v)
+#define STEPD(s, v)
+
+#define EXIT
+#define EXITD(r)
+#define EXITS(r)
+#endif
+
+
/* Module to read the template files */
typedef struct inputData inputData;
@@ -68,48 +93,62 @@ int main(int argc,char **argv)
MAC_HANDLE *macPvt;
char *pval;
int narg;
- char *substitutionName=0;
- char *templateName=0;
+ char *substitutionName = 0;
+ char *templateName = 0;
int i;
int localScope = 1;
inputConstruct(&inputPvt);
- macCreateHandle(&macPvt,0);
- while((argc>1) && (argv[1][0] == '-')) {
- narg = (strlen(argv[1])==2) ? 2 : 1;
- pval = (narg==1) ? (argv[1]+2) : argv[2];
- if(strncmp(argv[1],"-I",2)==0) {
- inputAddPath(inputPvt,pval);
- } else if (strcmp(argv[1], "-D") == 0) {
+ macCreateHandle(&macPvt, 0);
+ while ((argc > 1) && (argv[1][0] == '-')) {
+ narg = (strlen(argv[1]) == 2) ? 2 : 1;
+ pval = (narg == 1) ? (argv[1] + 2) : argv[2];
+
+ if (strncmp(argv[1], "-I", 2) == 0) {
+ inputAddPath(inputPvt, pval);
+ }
+ else if (strcmp(argv[1], "-D") == 0) {
opt_D = 1;
narg = 1; /* no argument for this option */
- } else if(strncmp(argv[1],"-o",2)==0) {
+ }
+ else if(strncmp(argv[1], "-o", 2) == 0) {
outFile = epicsStrDup(pval);
- } else if(strncmp(argv[1],"-M",2)==0) {
- addMacroReplacements(macPvt,pval);
- } else if(strncmp(argv[1],"-S",2)==0) {
+ }
+ else if(strncmp(argv[1], "-M", 2) == 0) {
+ addMacroReplacements(macPvt, pval);
+ }
+ else if(strncmp(argv[1], "-S", 2) == 0) {
substitutionName = epicsStrDup(pval);
- } else if (strcmp(argv[1], "-V") == 0) {
+ }
+ else if (strcmp(argv[1], "-V") == 0) {
opt_V = 1;
narg = 1; /* no argument for this option */
- } else if (strcmp(argv[1], "-g") == 0) {
+ }
+ else if (strcmp(argv[1], "-g") == 0) {
localScope = 0;
narg = 1; /* no argument for this option */
- } else if (strcmp(argv[1], "-h") == 0) {
+ }
+ else if (strcmp(argv[1], "-h") == 0) {
usageExit(0);
- } else {
+ }
+ else {
fprintf(stderr, "msi: Bad argument \"%s\"\n", argv[1]);
usageExit(1);
}
+
argc -= narg;
- for(i=1; i2) {
- fprintf(stderr,"msi: Too many arguments\n");
+ macSuppressWarning(macPvt, 1);
+
+ if (argc > 2) {
+ fprintf(stderr, "msi: Too many arguments\n");
usageExit(1);
}
+
if (opt_D) {
if (!outFile) {
fprintf(stderr, "msi: Option -D requires -o for Makefile target\n");
@@ -122,34 +161,47 @@ int main(int argc,char **argv)
outFile, strerror(errno));
exit(1);
}
- if(argc==2) {
+
+ if (argc == 2)
templateName = epicsStrDup(argv[1]);
+
+ if (!substitutionName) {
+ STEP("Single template+substitutions file");
+ makeSubstitutions(inputPvt, macPvt, templateName);
}
- if(!substitutionName) {
- makeSubstitutions(inputPvt,macPvt,templateName);
- } else {
+ else {
subInfo *substitutePvt;
char *filename = 0;
int isGlobal, isFile;
- substituteOpen(&substitutePvt,substitutionName);
+ STEPS("Substitutions from file", substitutionName);
+ substituteOpen(&substitutePvt, substitutionName);
do {
- if ((isGlobal = substituteGetGlobalSet(substitutePvt))) {
+ isGlobal = substituteGetGlobalSet(substitutePvt);
+ if (isGlobal) {
+ STEP("Handling global macros");
pval = substituteGetGlobalReplacements(substitutePvt);
- if(pval) {
- addMacroReplacements(macPvt,pval);
- }
- } else if ((isFile = substituteGetNextSet(substitutePvt,&filename))) {
- if(templateName) filename = templateName;
- if(!filename) {
- fprintf(stderr,"msi: No template file\n");
+ if (pval)
+ addMacroReplacements(macPvt, pval);
+ }
+ else if ((isFile = substituteGetNextSet(substitutePvt, &filename))) {
+ if (templateName)
+ filename = templateName;
+ if (!filename) {
+ fprintf(stderr, "msi: No template file\n");
usageExit(1);
}
- while((pval = substituteGetReplacements(substitutePvt))){
- if (localScope) macPushScope(macPvt);
- addMacroReplacements(macPvt,pval);
- makeSubstitutions(inputPvt,macPvt,filename);
- if (localScope) macPopScope(macPvt);
+
+ STEPS("Handling template file", filename);
+ while ((pval = substituteGetReplacements(substitutePvt))) {
+ if (localScope)
+ macPushScope(macPvt);
+
+ addMacroReplacements(macPvt, pval);
+ makeSubstitutions(inputPvt, macPvt, filename);
+
+ if (localScope)
+ macPopScope(macPvt);
}
}
} while (isGlobal || isFile);
@@ -198,15 +250,15 @@ static void addMacroReplacements(MAC_HANDLE *macPvt, char *pval)
char **pairs;
long status;
- status = macParseDefns(macPvt,pval,&pairs);
- if(status==-1) {
- fprintf(stderr,"msi: Error from macParseDefns\n");
+ status = macParseDefns(macPvt, pval, &pairs);
+ if (status == -1) {
+ fprintf(stderr, "msi: Error from macParseDefns\n");
usageExit(1);
}
- if(status) {
- status = macInstallMacros(macPvt,pairs);
- if(!status) {
- fprintf(stderr,"Error from macInstallMacros\n");
+ if (status) {
+ status = macInstallMacros(macPvt, pairs);
+ if (!status) {
+ fprintf(stderr, "Error from macInstallMacros\n");
usageExit(1);
}
free(pairs);
@@ -222,86 +274,98 @@ static void makeSubstitutions(inputData *inputPvt, MAC_HANDLE *macPvt, char *tem
static char buffer[MAX_BUFFER_SIZE];
int n;
- inputBegin(inputPvt,templateName);
- while((input = inputNextLine(inputPvt))) {
+ ENTER;
+ inputBegin(inputPvt, templateName);
+ while ((input = inputNextLine(inputPvt))) {
int expand=1;
char *p;
char *command = 0;
- p = input;
+ p = input;
/*skip whitespace at beginning of line*/
- while(*p && (isspace((int) *p))) ++p;
+ while (*p && (isspace((int) *p))) ++p;
+
/*Look for i or s */
- if(*p && (*p=='i' || *p=='s')) command = p;
- if(command) {
+ if (*p && (*p=='i' || *p=='s'))
+ command = p;
+
+ if (command) {
char *pstart;
char *pend;
char *copy;
int cmdind=-1;
int i;
-
- for(i=0; i< NELEMENTS(cmdNames); i++) {
- if(strstr(command,cmdNames[i])) {
+
+ for (i = 0; i < NELEMENTS(cmdNames); i++) {
+ if (strstr(command, cmdNames[i])) {
cmdind = i;
}
}
- if(cmdind<0) goto endif;
+ if (cmdind < 0) goto endcmd;
p = command + strlen(cmdNames[cmdind]);
/*skip whitespace after command*/
- while(*p && (isspace((int) *p))) ++p;
+ while (*p && (isspace((int) *p))) ++p;
/*Next character must be quote*/
- if((*p==0) || (*p!='"')) goto endif;
+ if ((*p == 0) || (*p != '"')) goto endcmd;
pstart = ++p;
/*Look for end quote*/
- while(*p && (*p!='"')) {
- /*allow escape for imbeded quote*/
- if((*p=='\\') && *(p+1)=='"') {
- p += 2; continue;
- } else {
- if(*p=='"') break;
+ while (*p && (*p != '"')) {
+ /*allow escape for embeded quote*/
+ if ((p[0] == '\\') && p[1] == '"') {
+ p += 2;
+ continue;
+ }
+ else {
+ if (*p == '"') break;
}
++p;
}
pend = p;
- if(*p==0) goto endif;
+ if (*p == 0) goto endcmd;
/*skip quote and any trailing blanks*/
- while(*++p==' ') ;
- if(*p != '\n' && *p !=0) goto endif;
- copy = calloc(pend-pstart+1,sizeof(char));
- strncpy(copy,pstart,pend-pstart);
+ while (*++p == ' ') ;
+ if (*p != '\n' && *p != 0) goto endcmd;
+ copy = calloc(pend-pstart + 1, sizeof(char));
+ strncpy(copy, pstart, pend-pstart);
+
switch(cmdind) {
case cmdInclude:
inputNewIncludeFile(inputPvt,copy);
break;
+
case cmdSubstitute:
addMacroReplacements(macPvt,copy);
break;
+
default:
- fprintf(stderr,"msi: Logic error in makeSubstitutions\n");
+ fprintf(stderr, "msi: Logic error in makeSubstitutions\n");
inputErrPrint(inputPvt);
abortExit(1);
}
free(copy);
expand = 0;
}
-endif:
+
+endcmd:
if (expand && !opt_D) {
- n = macExpandString(macPvt,input,buffer,MAX_BUFFER_SIZE-1);
- fputs(buffer,stdout);
+ STEP("Expanding to output stream");
+ n = macExpandString(macPvt, input, buffer, MAX_BUFFER_SIZE - 1);
+ fputs(buffer, stdout);
if (opt_V == 1 && n < 0) {
- fprintf(stderr,"msi: Error - undefined macros present\n");
+ fprintf(stderr, "msi: Error - undefined macros present\n");
opt_V++;
}
}
}
+ EXIT;
}
-typedef struct inputFile{
+typedef struct inputFile {
ELLNODE node;
char *filename;
FILE *fp;
int lineNum;
-}inputFile;
+} inputFile;
typedef struct pathNode {
ELLNODE node;
@@ -314,15 +378,15 @@ struct inputData {
char inputBuffer[MAX_BUFFER_SIZE];
};
-static void inputOpenFile(inputData *pinputData,char *filename);
+static void inputOpenFile(inputData *pinputData, char *filename);
static void inputCloseFile(inputData *pinputData);
static void inputCloseAllFiles(inputData *pinputData);
static void inputConstruct(inputData **ppvt)
{
- inputData *pinputData;
+ inputData *pinputData;
- pinputData = calloc(1,sizeof(inputData));
+ pinputData = calloc(1, sizeof(inputData));
ellInit(&pinputData->inputFileList);
ellInit(&pinputData->pathList);
*ppvt = pinputData;
@@ -330,11 +394,11 @@ static void inputConstruct(inputData **ppvt)
static void inputDestruct(inputData *pinputData)
{
- pathNode *ppathNode;
+ pathNode *ppathNode;
inputCloseAllFiles(pinputData);
- while((ppathNode = (pathNode *)ellFirst(&pinputData->pathList))) {
- ellDelete(&pinputData->pathList,&ppathNode->node);
+ while ((ppathNode = (pathNode *) ellFirst(&pinputData->pathList))) {
+ ellDelete(&pinputData->pathList, &ppathNode->node);
free(ppathNode->directory);
free(ppathNode);
}
@@ -351,38 +415,45 @@ static void inputAddPath(inputData *pinputData, char *path)
int emptyName;
const char sep = *OSI_PATH_LIST_SEPARATOR;
+ ENTER;
pdir = path;
/*an empty name at beginning, middle, or end means current directory*/
- while(pdir && *pdir) {
+ while (pdir && *pdir) {
emptyName = ((*pdir == sep) ? 1 : 0);
- if(emptyName) ++pdir;
- ppathNode = (pathNode *)calloc(1,sizeof(pathNode));
- ellAdd(ppathList,&ppathNode->node);
- if(!emptyName) {
- pcolon = strchr(pdir,sep);
+ if (emptyName) ++pdir;
+
+ ppathNode = (pathNode *) calloc(1, sizeof(pathNode));
+ ellAdd(ppathList, &ppathNode->node);
+
+ if (!emptyName) {
+ pcolon = strchr(pdir, sep);
len = (pcolon ? (pcolon - pdir) : strlen(pdir));
- if(len>0) {
- ppathNode->directory = (char *)calloc(len+1,sizeof(char));
- strncpy(ppathNode->directory,pdir,len);
+ if (len > 0) {
+ ppathNode->directory = (char *) calloc(len + 1, sizeof(char));
+ strncpy(ppathNode->directory, pdir, len);
pdir = pcolon;
/*unless at end skip past first colon*/
- if(pdir && *(pdir+1)!=0) ++pdir;
- } else { /*must have been trailing : */
- emptyName=1;
+ if (pdir && *(pdir + 1) != 0) ++pdir;
+ }
+ else { /*must have been trailing : */
+ emptyName = 1;
}
}
- if(emptyName) {
- ppathNode->directory = (char *)calloc(2,sizeof(char));
- strcpy(ppathNode->directory,".");
+
+ if (emptyName) {
+ ppathNode->directory = (char *) calloc(2, sizeof(char));
+ strcpy(ppathNode->directory, ".");
}
}
- return;
+ EXIT;
}
static void inputBegin(inputData *pinputData, char *fileName)
{
+ ENTER;
inputCloseAllFiles(pinputData);
- inputOpenFile(pinputData,fileName);
+ inputOpenFile(pinputData, fileName);
+ EXIT;
}
static char *inputNextLine(inputData *pinputData)
@@ -390,43 +461,54 @@ static char *inputNextLine(inputData *pinputData)
inputFile *pinputFile;
char *pline;
- while((pinputFile = (inputFile *)ellFirst(&pinputData->inputFileList))) {
- pline = fgets(pinputData->inputBuffer,MAX_BUFFER_SIZE,pinputFile->fp);
- if(pline) {
+ ENTER;
+ while ((pinputFile = (inputFile *) ellFirst(&pinputData->inputFileList))) {
+ pline = fgets(pinputData->inputBuffer, MAX_BUFFER_SIZE, pinputFile->fp);
+ if (pline) {
++pinputFile->lineNum;
- return(pline);
+ EXITS(pline);
+ return pline;
}
inputCloseFile(pinputData);
}
- return(0);
+ EXITD(0);
+ return 0;
}
static void inputNewIncludeFile(inputData *pinputData, char *name)
{
+ ENTER;
inputOpenFile(pinputData,name);
+ EXIT;
}
static void inputErrPrint(inputData *pinputData)
{
inputFile *pinputFile;
- fprintf(stderr,"input: '%s' at ",pinputData->inputBuffer);
- pinputFile = (inputFile *)ellFirst(&pinputData->inputFileList);
- while(pinputFile) {
- fprintf(stderr,"line %d of ",pinputFile->lineNum);
- if(pinputFile->filename) {
- fprintf(stderr," file %s\n",pinputFile->filename);
- } else {
- fprintf(stderr,"stdin:\n");
+ ENTER;
+ fprintf(stderr, "input: '%s' at ", pinputData->inputBuffer);
+ pinputFile = (inputFile *) ellFirst(&pinputData->inputFileList);
+ while (pinputFile) {
+ fprintf(stderr, "line %d of ", pinputFile->lineNum);
+
+ if (pinputFile->filename) {
+ fprintf(stderr, " file %s\n", pinputFile->filename);
}
- pinputFile = (inputFile *)ellNext(&pinputFile->node);
- if(pinputFile) {
- fprintf(stderr," included from ");
- } else {
+ else {
+ fprintf(stderr, "stdin:\n");
+ }
+
+ pinputFile = (inputFile *) ellNext(&pinputFile->node);
+ if (pinputFile) {
+ fprintf(stderr, " included from ");
+ }
+ else {
fprintf(stderr,"\n");
}
}
fprintf(stderr,"\n");
+ EXIT;
}
static void inputOpenFile(inputData *pinputData,char *filename)
@@ -437,35 +519,48 @@ static void inputOpenFile(inputData *pinputData,char *filename)
char *fullname = 0;
FILE *fp = 0;
- if(!filename) {
+ ENTER;
+ if (!filename) {
+ STEP("Using stdin");
fp = stdin;
- } else if((ellCount(ppathList)==0) || strchr(filename,'/')){
- fp = fopen(filename,"r");
- } else {
- ppathNode = (pathNode *)ellFirst(ppathList);
- while(ppathNode) {
- fullname = calloc(strlen(filename)+strlen(ppathNode->directory) +2,
+ }
+ else if ((ellCount(ppathList) == 0) || strchr(filename, '/')){
+ STEPS("Opening ", filename);
+ fp = fopen(filename, "r");
+ }
+ else {
+ ppathNode = (pathNode *) ellFirst(ppathList);
+ while (ppathNode) {
+ fullname = calloc(strlen(filename) + strlen(ppathNode->directory) + 2,
sizeof(char));
- strcpy(fullname,ppathNode->directory);
- strcat(fullname,"/");
- strcat(fullname,filename);
- fp = fopen(fullname,"r");
- if(fp) break;
+ strcpy(fullname, ppathNode->directory);
+ strcat(fullname, "/");
+ strcat(fullname, filename);
+ STEPS("Trying", filename);
+ fp = fopen(fullname, "r");
+ if (fp)
+ break;
free(fullname);
- ppathNode = (pathNode *)ellNext(&ppathNode->node);
+ ppathNode = (pathNode *) ellNext(&ppathNode->node);
}
}
- if(!fp) {
- fprintf(stderr,"msi: Can't open file '%s'\n",filename);
+
+ if (!fp) {
+ fprintf(stderr, "msi: Can't open file '%s'\n", filename);
inputErrPrint(pinputData);
abortExit(1);
}
- pinputFile = calloc(1,sizeof(inputFile));
- if(ppathNode) {
+
+ STEP("File opened");
+ pinputFile = calloc(1, sizeof(inputFile));
+
+ if (ppathNode) {
pinputFile->filename = fullname;
- } else if(filename) {
+ }
+ else if (filename) {
pinputFile->filename = epicsStrDup(filename);
- } else {
+ }
+ else {
pinputFile->filename = epicsStrDup("stdin");
}
@@ -495,35 +590,41 @@ static void inputOpenFile(inputData *pinputData,char *filename)
}
pinputFile->fp = fp;
- ellInsert(&pinputData->inputFileList,0,&pinputFile->node);
+ ellInsert(&pinputData->inputFileList, 0, &pinputFile->node);
+ EXIT;
}
static void inputCloseFile(inputData *pinputData)
{
inputFile *pinputFile;
- pinputFile = (inputFile *)ellFirst(&pinputData->inputFileList);
- if(!pinputFile) return;
- ellDelete(&pinputData->inputFileList,&pinputFile->node);
- if(fclose(pinputFile->fp))
- fprintf(stderr,"msi: Can't close input file '%s'\n",pinputFile->filename);
- free(pinputFile->filename);
- free(pinputFile);
+ ENTER;
+ pinputFile = (inputFile *) ellFirst(&pinputData->inputFileList);
+ if (pinputFile) {
+ ellDelete(&pinputData->inputFileList, &pinputFile->node);
+ if (fclose(pinputFile->fp))
+ fprintf(stderr, "msi: Can't close input file '%s'\n", pinputFile->filename);
+ free(pinputFile->filename);
+ free(pinputFile);
+ }
+ EXIT;
}
static void inputCloseAllFiles(inputData *pinputData)
{
inputFile *pinputFile;
- while((pinputFile=(inputFile *)ellFirst(&pinputData->inputFileList))){
+ ENTER;
+ while ((pinputFile = (inputFile *) ellFirst(&pinputData->inputFileList))) {
inputCloseFile(pinputData);
}
+ EXIT;
}
/*start of code that handles substitution file*/
typedef enum {
- tokenLBrace,tokenRBrace,tokenSeparater,tokenString,tokenEOF
-}tokenType;
+ tokenLBrace, tokenRBrace, tokenSeparator, tokenString, tokenEOF
+} tokenType;
typedef struct subFile {
char *substitutionName;
@@ -560,70 +661,87 @@ static void catMacroReplacements(subInfo *psubInfo,const char *value);
void freeSubFile(subInfo *psubInfo)
{
- subFile *psubFile = psubInfo->psubFile;
- if(psubFile->fp) {
- if(fclose(psubFile->fp))
- fprintf(stderr,"msi: Can't close substitution file\n");
+ subFile *psubFile = psubInfo->psubFile;
+
+ ENTER;
+ if (psubFile->fp) {
+ if (fclose(psubFile->fp))
+ fprintf(stderr, "msi: Can't close substitution file\n");
}
free(psubFile);
free(psubInfo->filename);
psubInfo->psubFile = 0;
+ EXIT;
}
void freePattern(subInfo *psubInfo)
{
patternNode *ppatternNode;
- while((ppatternNode = (patternNode *)ellFirst(&psubInfo->patternList))) {
- ellDelete(&psubInfo->patternList,&ppatternNode->node);
+
+ ENTER;
+ while ((ppatternNode = (patternNode *) ellFirst(&psubInfo->patternList))) {
+ ellDelete(&psubInfo->patternList, &ppatternNode->node);
free(ppatternNode->var);
free(ppatternNode);
}
psubInfo->isPattern = 0;
+ EXIT;
}
static void substituteDestruct(subInfo *psubInfo)
{
+ ENTER;
freeSubFile(psubInfo);
freePattern(psubInfo);
free(psubInfo);
- return;
+ EXIT;
}
-static void substituteOpen(subInfo **ppvt,char *substitutionName)
+static void substituteOpen(subInfo **ppvt, char *substitutionName)
{
subInfo *psubInfo;
subFile *psubFile;
FILE *fp;
- psubInfo = calloc(1,sizeof(subInfo));
+ ENTER;
+ psubInfo = calloc(1, sizeof(subInfo));
*ppvt = psubInfo;
- psubFile = calloc(1,sizeof(subFile));
+ psubFile = calloc(1, sizeof(subFile));
psubInfo->psubFile = psubFile;
ellInit(&psubInfo->patternList);
- fp = fopen(substitutionName,"r");
- if(!fp) {
- fprintf(stderr,"msi: Can't open file '%s'\n",substitutionName);
+
+ fp = fopen(substitutionName, "r");
+ if (!fp) {
+ fprintf(stderr, "msi: Can't open file '%s'\n", substitutionName);
abortExit(1);
}
+
psubFile->substitutionName = substitutionName;
psubFile->fp = fp;
psubFile->lineNum = 1;
psubFile->inputBuffer[0] = 0;
psubFile->pnextChar = &psubFile->inputBuffer[0];
subGetNextToken(psubFile);
- return;
+ EXIT;
}
static int substituteGetGlobalSet(subInfo *psubInfo)
{
- subFile *psubFile = psubInfo->psubFile;
+ subFile *psubFile = psubInfo->psubFile;
- while(psubFile->token==tokenSeparater) subGetNextToken(psubFile);
- if(psubFile->token==tokenString && strcmp(psubFile->string,"global")==0) {
+ ENTER;
+ while (psubFile->token == tokenSeparator)
subGetNextToken(psubFile);
- return(1);
+
+ if (psubFile->token == tokenString &&
+ strcmp(psubFile->string, "global") == 0) {
+ subGetNextToken(psubFile);
+ EXITD(1);
+ return 1;
}
- return(0);
+
+ EXITD(0);
+ return 0;
}
static int substituteGetNextSet(subInfo *psubInfo,char **filename)
@@ -631,34 +749,59 @@ static int substituteGetNextSet(subInfo *psubInfo,char **filename)
subFile *psubFile = psubInfo->psubFile;
patternNode *ppatternNode;
+ ENTER;
*filename = 0;
- while(psubFile->token==tokenSeparater) subGetNextToken(psubFile);
- if(psubFile->token==tokenEOF) return(0);
- if(psubFile->token==tokenString && strcmp(psubFile->string,"file")==0) {
+ while (psubFile->token == tokenSeparator)
+ subGetNextToken(psubFile);
+
+ if (psubFile->token == tokenEOF) {
+ EXITD(0);
+ return 0;
+ }
+
+ if (psubFile->token == tokenString &&
+ strcmp(psubFile->string, "file") == 0) {
+ size_t len;
+
+ STEP("Parsed 'file'");
psubInfo->isFile = 1;
- if(subGetNextToken(psubFile)!=tokenString) {
- subFileErrPrint(psubFile,"Parse error, expecting filename");
+ if (subGetNextToken(psubFile) != tokenString) {
+ subFileErrPrint(psubFile, "Parse error, expecting a filename");
abortExit(1);
}
+
freePattern(psubInfo);
free(psubInfo->filename);
- if(psubFile->string[0]=='"'&&psubFile->string[strlen(psubFile->string)-1]=='"') {
- psubFile->string[strlen(psubFile->string)-1]='\0';
- psubInfo->filename = macEnvExpand(psubFile->string+1);
+
+ len = strlen(psubFile->string);
+ if (psubFile->string[0] == '"' &&
+ psubFile->string[len - 1] == '"') {
+ psubFile->string[len - 1] = '\0';
+ psubInfo->filename = macEnvExpand(psubFile->string + 1);
}
- else {
+ else
psubInfo->filename = macEnvExpand(psubFile->string);
- }
- while(subGetNextToken(psubFile)==tokenSeparater);
- if(psubFile->token!=tokenLBrace) {
- subFileErrPrint(psubFile,"Parse error, expecting {");
+ STEPS("Parsed filename", psubInfo->filename);
+
+ while (subGetNextToken(psubFile) == tokenSeparator);
+
+ if (psubFile->token != tokenLBrace) {
+ subFileErrPrint(psubFile, "Parse error, expecting '{'");
abortExit(1);
}
+ STEP("Parsed '{'");
subGetNextToken(psubFile);
}
*filename = psubInfo->filename;
- while(psubFile->token==tokenSeparater) subGetNextToken(psubFile);
- if(psubFile->token==tokenLBrace) return(1);
+
+ while (psubFile->token == tokenSeparator)
+ subGetNextToken(psubFile);
+
+ if (psubFile->token == tokenLBrace) {
+ EXITD(1);
+ return 1;
+ }
+
if (psubFile->token == tokenRBrace) {
subFileErrPrint(psubFile, "Parse error, unexpected '}'");
abortExit(1);
@@ -669,58 +812,84 @@ static int substituteGetNextSet(subInfo *psubInfo,char **filename)
subFileErrPrint(psubFile, "Parse error, expecting 'pattern'");
abortExit(1);
}
+
+ STEP("Parsed 'pattern'");
freePattern(psubInfo);
psubInfo->isPattern = 1;
- while(subGetNextToken(psubFile)==tokenSeparater);
- if(psubFile->token!=tokenLBrace) {
- subFileErrPrint(psubFile,"Parse error, expecting {");
+
+ while (subGetNextToken(psubFile) == tokenSeparator);
+
+ if (psubFile->token != tokenLBrace) {
+ subFileErrPrint(psubFile, "Parse error, expecting '{'");
abortExit(1);
}
- while(1) {
- while(subGetNextToken(psubFile)==tokenSeparater);
- if(psubFile->token!=tokenString) break;
- ppatternNode = calloc(1,sizeof(patternNode));
- ellAdd(&psubInfo->patternList,&ppatternNode->node);
+ STEP("Parsed '{'");
+
+ while (1) {
+ while (subGetNextToken(psubFile) == tokenSeparator);
+
+ if (psubFile->token != tokenString)
+ break;
+
+ ppatternNode = calloc(1, sizeof(patternNode));
+ ellAdd(&psubInfo->patternList, &ppatternNode->node);
ppatternNode->var = epicsStrDup(psubFile->string);
}
- if(psubFile->token!=tokenRBrace) {
- subFileErrPrint(psubFile,"Parse error, expecting }");
+
+ if (psubFile->token != tokenRBrace) {
+ subFileErrPrint(psubFile, "Parse error, expecting '}'");
abortExit(1);
}
+
subGetNextToken(psubFile);
- return(1);
+ EXITD(1);
+ return 1;
}
static char *substituteGetGlobalReplacements(subInfo *psubInfo)
{
subFile *psubFile = psubInfo->psubFile;
- if(psubInfo->macroReplacements) psubInfo->macroReplacements[0] = 0;
+ ENTER;
+ if (psubInfo->macroReplacements)
+ psubInfo->macroReplacements[0] = 0;
psubInfo->curLength = 0;
- while(psubFile->token==tokenSeparater) subGetNextToken(psubFile);
- if(psubFile->token==tokenRBrace && psubInfo->isFile) {
+
+ while (psubFile->token == tokenSeparator)
+ subGetNextToken(psubFile);
+
+ if (psubFile->token == tokenRBrace && psubInfo->isFile) {
psubInfo->isFile = 0;
free(psubInfo->filename);
psubInfo->filename = 0;
freePattern(psubInfo);
subGetNextToken(psubFile);
- return(0);
+ EXITD(0);
+ return 0;
}
- if(psubFile->token==tokenEOF) return(0);
- if(psubFile->token!=tokenLBrace) return(0);
- while(1) {
+
+ if (psubFile->token == tokenEOF) {
+ EXITD(0);
+ return 0;
+ }
+ if (psubFile->token != tokenLBrace) {
+ EXITD(0);
+ return 0;
+ }
+
+ while (1) {
switch(subGetNextToken(psubFile)) {
case tokenRBrace:
subGetNextToken(psubFile);
- if (!psubInfo->macroReplacements) {
- catMacroReplacements(psubInfo,"");
- }
- return(psubInfo->macroReplacements);
- case tokenSeparater:
- catMacroReplacements(psubInfo,",");
+ EXITS(psubInfo->macroReplacements);
+ return psubInfo->macroReplacements;
+
+ case tokenSeparator:
+ catMacroReplacements(psubInfo, ",");
break;
+
case tokenString:
- catMacroReplacements(psubInfo,psubFile->string);
+ catMacroReplacements(psubInfo, psubFile->string);
break;
case tokenLBrace:
@@ -738,58 +907,81 @@ static char *substituteGetReplacements(subInfo *psubInfo)
subFile *psubFile = psubInfo->psubFile;
patternNode *ppatternNode;
- if(psubInfo->macroReplacements) psubInfo->macroReplacements[0] = 0;
+ ENTER;
+ if (psubInfo->macroReplacements)
+ psubInfo->macroReplacements[0] = 0;
psubInfo->curLength = 0;
- while(psubFile->token==tokenSeparater) subGetNextToken(psubFile);
- if(psubFile->token==tokenRBrace && psubInfo->isFile) {
+
+ while (psubFile->token == tokenSeparator)
+ subGetNextToken(psubFile);
+
+ if (psubFile->token==tokenRBrace && psubInfo->isFile) {
psubInfo->isFile = 0;
free(psubInfo->filename);
psubInfo->filename = 0;
freePattern(psubInfo);
subGetNextToken(psubFile);
- return(0);
+ EXITD(0);
+ return 0;
}
- if(psubFile->token==tokenEOF) return(0);
- if(psubFile->token!=tokenLBrace) return(0);
- if(psubInfo->isPattern) {
+
+ if (psubFile->token == tokenEOF) {
+ EXITD(0);
+ return 0;
+ }
+
+ if (psubFile->token != tokenLBrace) {
+ EXITD(0);
+ return 0;
+ }
+
+ if (psubInfo->isPattern) {
int gotFirstPattern = 0;
- while(subGetNextToken(psubFile)==tokenSeparater);
- ppatternNode = (patternNode *)ellFirst(&psubInfo->patternList);
- while(1) {
- if(psubFile->token==tokenRBrace) {
+ while (subGetNextToken(psubFile) == tokenSeparator);
+ ppatternNode = (patternNode *) ellFirst(&psubInfo->patternList);
+ while (1) {
+ if (psubFile->token == tokenRBrace) {
subGetNextToken(psubFile);
- return(psubInfo->macroReplacements);
+ EXITS(psubInfo->macroReplacements);
+ return psubInfo->macroReplacements;
}
- if(psubFile->token!=tokenString) {
- subFileErrPrint(psubFile,"Parse error, illegal token");
+
+ if (psubFile->token != tokenString) {
+ subFileErrPrint(psubFile,"Parse error, expecting macro value");
abortExit(1);
}
- if(gotFirstPattern) catMacroReplacements(psubInfo,",");
+
+ if (gotFirstPattern)
+ catMacroReplacements(psubInfo, ",");
gotFirstPattern = 1;
- if(ppatternNode) {
- catMacroReplacements(psubInfo,ppatternNode->var);
- catMacroReplacements(psubInfo,"=");
- catMacroReplacements(psubInfo,psubFile->string);
- ppatternNode = (patternNode *)ellNext(&ppatternNode->node);
- } else {
- subFileErrPrint(psubFile,"Warning, too many values given");
+
+ if (ppatternNode) {
+ catMacroReplacements(psubInfo, ppatternNode->var);
+ catMacroReplacements(psubInfo, "=");
+ catMacroReplacements(psubInfo, psubFile->string);
+ ppatternNode = (patternNode *) ellNext(&ppatternNode->node);
}
- while(subGetNextToken(psubFile)==tokenSeparater);
+ else {
+ subFileErrPrint(psubFile, "Warning, too many values given");
+ }
+
+ while (subGetNextToken(psubFile) == tokenSeparator);
}
- } else while(1) {
+ }
+ else while(1) {
switch(subGetNextToken(psubFile)) {
case tokenRBrace:
subGetNextToken(psubFile);
- if (!psubInfo->macroReplacements) {
- catMacroReplacements(psubInfo,"");
- }
- return(psubInfo->macroReplacements);
- case tokenSeparater:
- catMacroReplacements(psubInfo,",");
+ EXITS(psubInfo->macroReplacements);
+ return psubInfo->macroReplacements;
+
+ case tokenSeparator:
+ catMacroReplacements(psubInfo, ",");
break;
+
case tokenString:
- catMacroReplacements(psubInfo,psubFile->string);
+ catMacroReplacements(psubInfo, psubFile->string);
break;
case tokenLBrace:
@@ -806,69 +998,84 @@ static char *subGetNextLine(subFile *psubFile)
{
char *pline;
+ ENTER;
do {
- pline = fgets(psubFile->inputBuffer,MAX_BUFFER_SIZE,psubFile->fp);
+ pline = fgets(psubFile->inputBuffer, MAX_BUFFER_SIZE, psubFile->fp);
++psubFile->lineNum;
- } while(pline && psubFile->inputBuffer[0]=='#');
- if(!pline) {
+ } while (pline && psubFile->inputBuffer[0] == '#');
+
+ if (!pline) {
psubFile->token = tokenEOF;
psubFile->inputBuffer[0] = 0;
psubFile->pnextChar = 0;
- return(0);
+ EXITD(0);
+ return 0;
}
+
psubFile->pnextChar = &psubFile->inputBuffer[0];
- return(&psubFile->inputBuffer[0]);
+ EXITS(&psubFile->inputBuffer[0]);
+ return &psubFile->inputBuffer[0];
}
static void subFileErrPrint(subFile *psubFile,char * message)
{
- fprintf(stderr,"msi: %s\n",message);
- fprintf(stderr," in substitution file '%s' at line %d:\n %s",
- psubFile->substitutionName,
- psubFile->lineNum,psubFile->inputBuffer);
+ fprintf(stderr, "msi: %s\n",message);
+ fprintf(stderr, " in substitution file '%s' at line %d:\n %s",
+ psubFile->substitutionName, psubFile->lineNum, psubFile->inputBuffer);
}
static tokenType subGetNextToken(subFile *psubFile)
{
- char *p;
- char *pto;
+ char *p, *pto;
+ ENTER;
p = psubFile->pnextChar;
- if(!p) { psubFile->token = tokenEOF; return(tokenEOF);}
- if(*p==0 || *p=='\n' || *p=='#') {
- p = subGetNextLine(psubFile);
- if(!p) { psubFile->token = tokenEOF; return(tokenEOF);}
- else { psubFile->token = tokenSeparater; return(tokenSeparater);}
+ if (!p) {
+ STEP("Got EOF");
+ psubFile->token = tokenEOF;
+ goto done;
}
- while(isspace((int) *p)) p++;
- if(*p=='{') {
+
+ if (*p == 0 || *p == '\n' || *p == '#') {
+ STEP("Got newline/comment");
+ p = subGetNextLine(psubFile);
+ psubFile->token = p ? tokenSeparator : tokenEOF;
+ goto done;
+ }
+
+ while (isspace((int) *p)) p++;
+ if (*p == '{') {
+ STEP("Got '{'");
psubFile->token = tokenLBrace;
psubFile->pnextChar = ++p;
- return(tokenLBrace);
+ goto done;
}
- if(*p=='}') {
+ if (*p == '}') {
+ STEP("Got '}'");
psubFile->token = tokenRBrace;
psubFile->pnextChar = ++p;
- return(tokenRBrace);
+ goto done;
}
- if(*p==0 || isspace((int) *p) || *p==',') {
- while (isspace((int) *p) || *p==',') p++;
- psubFile->token = tokenSeparater;
+ if (*p == 0 || isspace((int) *p) || *p == ',') {
+ STEP("Got space/comma");
+ while (isspace((int) *p) || *p == ',') p++;
+ psubFile->token = tokenSeparator;
psubFile->pnextChar = p;
- return(tokenSeparater);
+ goto done;
}
/*now handle quoted strings*/
- if(*p=='"') {
+ if (*p == '"') {
+ STEP("Got '\"'");
pto = &psubFile->string[0];
*pto++ = *p++;
- while(*p!='"') {
- if(*p==0 || *p=='\n') {
- subFileErrPrint(psubFile,"Strings must be on single line\n");
+ while (*p != '"') {
+ if (*p == 0 || *p == '\n') {
+ subFileErrPrint(psubFile, "Strings must be on single line\n");
abortExit(1);
}
- /*allow escape for imbeded quote*/
- if((*p=='\\') && *(p+1)=='"') {
+ /*allow escape for embeded quote*/
+ if ((p[0] == '\\') && p[1] == '"') {
*pto++ = *p++;
*pto++ = *p++;
continue;
@@ -879,40 +1086,53 @@ static tokenType subGetNextToken(subFile *psubFile)
psubFile->pnextChar = p;
*pto = 0;
psubFile->token = tokenString;
- return(tokenString);
+ goto done;
}
+
/*Now take anything up to next non String token and not space*/
pto = &psubFile->string[0];
- while(!isspace((int) *p) && (strspn(p,"\",{}")==0)) *pto++ = *p++;
+
+ while (!isspace((int) *p) && (strspn(p, "\",{}") == 0))
+ *pto++ = *p++;
*pto = 0;
+ STEPS("Got bareword", psubFile->string);
+
psubFile->pnextChar = p;
psubFile->token = tokenString;
- return(tokenString);
+
+done:
+ EXITD(psubFile->token);
+ return psubFile->token;
}
-static void catMacroReplacements(subInfo *psubInfo,const char *value)
+static void catMacroReplacements(subInfo *psubInfo, const char *value)
{
- size_t len = strlen(value);
+ size_t len = strlen(value);
- if(psubInfo->size <= (psubInfo->curLength + len)) {
+ ENTER;
+ if (psubInfo->size <= (psubInfo->curLength + len)) {
size_t newsize = psubInfo->size + MAX_BUFFER_SIZE;
char *newbuf;
- if(newsize <= psubInfo->curLength + len)
+ STEP("Enlarging buffer");
+ if (newsize <= psubInfo->curLength + len)
newsize = psubInfo->curLength + len + 1;
- newbuf = calloc(1,newsize);
- if(!newbuf) {
- fprintf(stderr,"calloc failed for size %lu\n",
- (unsigned long) newsize);
+ newbuf = calloc(1, newsize);
+ if (!newbuf) {
+ fprintf(stderr, "calloc failed for size %lu\n",
+ (unsigned long) newsize);
abortExit(1);
}
- if(psubInfo->macroReplacements) {
- memcpy(newbuf,psubInfo->macroReplacements,psubInfo->curLength);
+ if (psubInfo->macroReplacements) {
+ memcpy(newbuf, psubInfo->macroReplacements, psubInfo->curLength);
free(psubInfo->macroReplacements);
}
psubInfo->size = newsize;
psubInfo->macroReplacements = newbuf;
}
- strcat(psubInfo->macroReplacements,value);
+
+ STEPS("Appending", value);
+ strcat(psubInfo->macroReplacements, value);
psubInfo->curLength += len;
+ EXIT;
}
From fb31dd784b7dc1d21c61af167caca8da52f39d87 Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Tue, 31 Jul 2018 16:30:11 -0500
Subject: [PATCH 074/147] recGbl: Prevent record alarm severities >
INVALID_ALARM
---
documentation/RELEASE_NOTES.html | 9 +++++++++
src/db/recGbl.c | 4 ++++
2 files changed, 13 insertions(+)
diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html
index b327e2430..fb5238bd1 100644
--- a/documentation/RELEASE_NOTES.html
+++ b/documentation/RELEASE_NOTES.html
@@ -16,6 +16,15 @@ Base-3.15 series or to EPICS 7.
+Prevent illegal alarm severities
+
+A check has been added to recGblResetAlarms() that prevents records
+from getting an alarm severity higher than INVALID_ALARM. It is still possible
+for a field like HSV to get set to a value that is not a legal alarm severity,
+but the core IOC code should never copy such a value into a record's SEVR or
+ACKS fields. With this fix the record's alarm severity will be limited to
+INVALID_ALARM.
+
Fixes for Launchpad bugs
The following launchpad bugs have fixes included:
diff --git a/src/db/recGbl.c b/src/db/recGbl.c
index 6d45e7333..01b2fa544 100644
--- a/src/db/recGbl.c
+++ b/src/db/recGbl.c
@@ -19,6 +19,7 @@
#include
#include "dbDefs.h"
+#include "alarm.h"
#include "epicsMath.h"
#include "epicsTime.h"
#include "epicsPrint.h"
@@ -222,6 +223,9 @@ unsigned short epicsShareAPI recGblResetAlarms(void *precord)
epicsEnum16 val_mask = 0;
epicsEnum16 stat_mask = 0;
+ if (new_sevr > INVALID_ALARM)
+ new_sevr = INVALID_ALARM;
+
pdbc->stat = new_stat;
pdbc->sevr = new_sevr;
pdbc->nsta = 0;
From 1dc1b25aaa61bb986cb0d27711e1b21bb46603a8 Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Tue, 31 Jul 2018 17:58:38 -0500
Subject: [PATCH 075/147] caget.pl: Add missing acks and ackt metadata to
display output
---
src/cap5/caget.pl | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/cap5/caget.pl b/src/cap5/caget.pl
index 9d3df35b4..0ee407ad9 100644
--- a/src/cap5/caget.pl
+++ b/src/cap5/caget.pl
@@ -140,6 +140,10 @@ sub display {
printf " Lo ctrl limit: %g\n", $data->{lower_ctrl_limit};
printf " Hi ctrl limit: %g\n", $data->{upper_ctrl_limit};
}
+ if (exists $data->{ackt}) {
+ printf " Ack transients: %s\n", $data->{ackt} ? 'YES' : 'NO';
+ printf " Ack severity: %s\n", $data->{acks};
+ }
} else {
my $value = format_number($data, $type);
if ($opt_t) {
From 7626856a207bf865d27607139882a911807e0d86 Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Thu, 2 Aug 2018 16:57:53 -0500
Subject: [PATCH 076/147] Move dbScanPassive() into dbDbLink.c, create
processTarget()
Also adds dbAccessDebugPUTF variable, and removes the need for a
private API flag.
---
src/ioc/db/dbAccess.c | 49 +++--------
src/ioc/db/dbAccessDefs.h | 1 +
src/ioc/db/dbDbLink.c | 178 +++++++++++++++++++++-----------------
src/ioc/db/dbDbLink.h | 5 --
src/ioc/misc/dbCore.dbd | 4 +
5 files changed, 117 insertions(+), 120 deletions(-)
diff --git a/src/ioc/db/dbAccess.c b/src/ioc/db/dbAccess.c
index 716adee1e..54d20d5ce 100644
--- a/src/ioc/db/dbAccess.c
+++ b/src/ioc/db/dbAccess.c
@@ -23,8 +23,6 @@
#include
#include
-#define EPICS_PRIVATE_API
-
#include "alarm.h"
#include "cantProceed.h"
#include "cvtFast.h"
@@ -36,7 +34,7 @@
#include "errlog.h"
#include "errMdef.h"
-#define epicsExportSharedSymbols
+#include "epicsExport.h" /* #define epicsExportSharedSymbols */
#include "caeventmask.h"
#include "callback.h"
#include "dbAccessDefs.h"
@@ -51,7 +49,6 @@
#include "dbFldTypes.h"
#include "dbFldTypes.h"
#include "dbLink.h"
-#include "dbDbLink.h" /* for dbDbLinkPUTF() */
#include "dbLockPvt.h"
#include "dbNotify.h"
#include "dbScan.h"
@@ -68,6 +65,9 @@
epicsShareDef struct dbBase *pdbbase = 0;
epicsShareDef volatile int interruptAccept=FALSE;
+epicsShareDef int dbAccessDebugPUTF = 0;
+epicsExportAddress(int, dbAccessDebugPUTF);
+
/* Hook Routines */
epicsShareDef DB_LOAD_RECORDS_HOOK_ROUTINE dbLoadRecordsHook = NULL;
@@ -445,35 +445,6 @@ int dbGetFieldIndex(const struct dbAddr *paddr)
return paddr->pfldDes->indRecordType;
}
-/*
- * Process a record if its scan field is passive.
- * Will notify if processing is complete by callback.
- * (only if you are interested in completion)
- */
-long dbScanPassive(dbCommon *pfrom, dbCommon *pto)
-{
- long status;
- epicsUInt8 pact_save;
-
- /* if not passive just return success */
- if (pto->scan != 0)
- return 0;
-
- pact_save = pfrom->pact;
- pfrom->pact = 1;
-
- dbDbLinkPUTF(pfrom, pto);
-
- if (pfrom && pfrom->ppn)
- dbNotifyAdd(pfrom,pto);
-
- status = dbProcess(pto);
-
- pfrom->pact = pact_save;
-
- return status;
-}
-
/*
* Process the record.
* 1. Check for breakpoints.
@@ -539,7 +510,8 @@ long dbProcess(dbCommon *precord)
unsigned short monitor_mask;
if (*ptrace)
- printf("%s: Active%s %s\n", context, precord->rpro ? " Q" : "", precord->name);
+ printf("%s: dbProcess of Active '%s' with RPRO=%d\n",
+ context, precord->name, precord->rpro);
/* raise scan alarm after MAX_LOCK times */
if ((precord->stat == SCAN_ALARM) ||
@@ -568,7 +540,8 @@ long dbProcess(dbCommon *precord)
/* if disabled check disable alarm severity and return success */
if (precord->disa == precord->disv) {
if (*ptrace)
- printf("%s: Disabled %s\n", context, precord->name);
+ printf("%s: dbProcess of Disabled '%s'\n",
+ context, precord->name);
/*take care of caching and notifyCompletion*/
precord->rpro = FALSE;
@@ -605,7 +578,7 @@ long dbProcess(dbCommon *precord)
}
if (*ptrace)
- printf("%s: Process %s\n", context, precord->name);
+ printf("%s: dbProcess of '%s'\n", context, precord->name);
/* process record */
status = prset->process(precord);
@@ -1225,8 +1198,8 @@ long dbPutField(DBADDR *paddr, short dbrType,
precord->scan == 0 &&
dbrType < DBR_PUT_ACKT)) {
if (precord->pact) {
- if (precord->tpro)
- printf("%s: Active Q %s\n",
+ if (dbAccessDebugPUTF && precord->tpro)
+ printf("%s: dbPutField to Active '%s', setting RPRO=1\n",
epicsThreadGetNameSelf(), precord->name);
precord->rpro = TRUE;
} else {
diff --git a/src/ioc/db/dbAccessDefs.h b/src/ioc/db/dbAccessDefs.h
index cc45b17fe..5cf0b26ab 100644
--- a/src/ioc/db/dbAccessDefs.h
+++ b/src/ioc/db/dbAccessDefs.h
@@ -34,6 +34,7 @@ extern "C" {
epicsShareExtern struct dbBase *pdbbase;
epicsShareExtern volatile int interruptAccept;
+epicsShareExtern int dbAccessDebugPUTF;
/* The database field and request types are defined in dbFldTypes.h*/
/* Data Base Request Options */
diff --git a/src/ioc/db/dbDbLink.c b/src/ioc/db/dbDbLink.c
index 5a129c2d3..ce0110a64 100644
--- a/src/ioc/db/dbDbLink.c
+++ b/src/ioc/db/dbDbLink.c
@@ -12,14 +12,35 @@
* Current Author: Andrew Johnson
*/
+/* The PUTF and RPRO fields in dbCommon are flags that indicate when a record
+ * is being processed as a result of an external put (i.e. some server process
+ * calling dbPutField()), ensuring that the record and its successors will
+ * eventually get processed even if they happen to be busy at the time of the
+ * put. From Base-3.16.2 and 7.0.2 the code ensures that all records downstream
+ * from the original are processed even if a busy asynchronous device appears
+ * in the processing chain (this breaks the chain in older versions).
+ *
+ * PUTF - This field is set in dbPutField() prior to it calling dbProcess().
+ * It is normally cleared at the end of processing in recGblFwdLink().
+ * It may also be cleared in dbProcess() if DISA==DISV (scan disabled),
+ * or by the processTarget() function below.
+ *
+ * If PUTF is TRUE before a call to dbProcess(prec), then after it returns
+ * either PACT is TRUE, or PUTF will be FALSE.
+ *
+ * RPRO - This field is set by dbPutField() or by the processTarget() function
+ * below when a record to be processed is found to be busy (PACT==1).
+ * It is normally cleared in recGblFwdLink() when the record is queued
+ * for re-processing, or in dbProcess() if DISA==DISV (scan disabled).
+ */
+
+
#include
#include
#include
#include
#include
-#define EPICS_PRIVATE_API
-
#include "alarm.h"
#include "cantProceed.h"
#include "cvtFast.h"
@@ -53,72 +74,13 @@
#include "special.h"
#include "dbDbLink.h"
+
/***************************** Database Links *****************************/
-/* Forward definition */
+/* Forward definitions */
static lset dbDb_lset;
-/* call before each call of dbProcess() (also dbScanPassive())
- *
- * PUTF - This flag is set in dbPutField() prior to calling dbProcess().
- * It is normally cleared at the end of processing in recGblFwdLink().
- * It may also be cleared in dbProcess() if DISA==DISV (scan disabled),
- * or by this function.
- * If PUTF==1 before a call to dbProcess(prec), then afterwards
- * PACT | !PUTF must be true.
- *
- * RPRO - Set by dbPutField() or this function when the record to be processed
- * is found to be busy (PACT==1).
- * Cleared in recGblFwdLink() when a record is scheduled for re-processing,
- * or DISA==DISV.
- */
-static
-void propPUTF(struct link *plink)
-{
- struct pv_link *ppv_link = &plink->value.pv_link;
- DBADDR *paddr = ppv_link->pvt;
- dbCommon *psrc = plink->precord,
- *pdst = paddr->precord;
-
- dbDbLinkPUTF(psrc, pdst);
-}
-
-void dbDbLinkPUTF(dbCommon *psrc, dbCommon *pdst)
-{
- char context[40] = "";
- int trace = *dbLockSetAddrTrace(psrc);
-
- if (trace && dbServerClient(context, sizeof(context))) {
- /* No client, use thread name */
- strncpy(context, epicsThreadGetNameSelf(), sizeof(context));
- context[sizeof(context) - 1] = 0;
- }
-
- if(!pdst->pact) {
- /* normal propagation of PUTF from src to target */
- if(trace)
- printf("%s: %s -> %s prop PUTF=%u\n", context, psrc->name, pdst->name, psrc->putf);
-
- assert(!pdst->putf);
- pdst->putf = psrc->putf;
- } else if(psrc->putf) {
- /* found a busy async record,
- * we were originally triggered by a dbPutField()
- * so queue for reprocessing on completion,
- * but only this one time.
- */
- if(trace)
- printf("%s: %s -> %s prop RPRO=1\n", context, psrc->name, pdst->name);
- pdst->putf = FALSE;
- pdst->rpro = TRUE;
- } else {
- /* busy async record, but not originally triggered
- * by dbPutField(). Do nothing.
- */
- if(trace)
- printf("%s: %s -> %s prop DROP\n", context, psrc->name, pdst->name);
- }
-}
+static long processTarget(dbCommon *psrc, dbCommon *pdst);
long dbDbInitLink(struct link *plink, short dbfType)
{
@@ -373,20 +335,10 @@ static long dbDbPutValue(struct link *plink, short dbrType,
return status;
if (paddr->pfield == (void *) &pdest->proc ||
- (ppv_link->pvlMask & pvlOptPP && pdest->scan == 0)) {
- epicsUInt8 pact_save = psrce->pact;
-
- psrce->pact = 1;
-
- if (psrce && psrce->ppn)
- dbNotifyAdd(psrce, pdest);
-
- propPUTF(plink);
-
- status = dbProcess(pdest);
-
- psrce->pact = pact_save;
+ (ppv_link->pvlMask & pvlOptPP && pdest->scan == 0)) {
+ status = processTarget(psrce, pdest);
}
+
return status;
}
@@ -416,3 +368,75 @@ static lset dbDb_lset = {
dbDbPutValue, NULL,
dbDbScanFwdLink, doLocked
};
+
+
+/*
+ * Process a record if its scan field is passive.
+ */
+long dbScanPassive(dbCommon *pfrom, dbCommon *pto)
+{
+ /* if not passive we're done */
+ if (pto->scan != 0)
+ return 0;
+
+ return processTarget(pfrom, pto);
+}
+
+static long processTarget(dbCommon *psrc, dbCommon *pdst)
+{
+ char context[40] = "";
+ int trace = dbAccessDebugPUTF && *dbLockSetAddrTrace(psrc);
+ long status;
+ epicsUInt8 pact = psrc->pact;
+
+ psrc->pact = TRUE;
+
+ if (psrc && psrc->ppn)
+ dbNotifyAdd(psrc, pdst);
+
+ if (trace && dbServerClient(context, sizeof(context))) {
+ /* No client, use thread name */
+ strncpy(context, epicsThreadGetNameSelf(), sizeof(context));
+ context[sizeof(context) - 1] = 0;
+ }
+
+ if (!pdst->pact) {
+ /* Normal propagation of PUTF from src to dst */
+ if (trace)
+ printf("%s: '%s' -> '%s' with PUTF=%u\n",
+ context, psrc->name, pdst->name, psrc->putf);
+
+ if (pdst->putf)
+ errlogPrintf("Warning: '%s.PUTF' found true with PACT false\n",
+ pdst->name);
+
+ pdst->putf = psrc->putf;
+ }
+ else if (psrc->putf) {
+ /* The dst record is busy (awaiting async reprocessing) and
+ * we were originally triggered by a call to dbPutField(),
+ * so we mark the dst record for reprocessing once the async
+ * completion is over.
+ */
+ if (trace)
+ printf("%s: '%s' -> Active '%s', setting RPRO=1\n",
+ context, psrc->name, pdst->name);
+
+ pdst->putf = FALSE;
+ pdst->rpro = TRUE;
+ }
+ else {
+ /* The dst record is busy, but we weren't triggered by a call
+ * to dbPutField(). Do nothing.
+ */
+ if (trace)
+ printf("%s: '%s' -> Active '%s', done\n",
+ context, psrc->name, pdst->name);
+ }
+
+ status = dbProcess(pdst);
+
+ psrc->pact = pact;
+
+ return status;
+}
diff --git a/src/ioc/db/dbDbLink.h b/src/ioc/db/dbDbLink.h
index e19685427..c36772004 100644
--- a/src/ioc/db/dbDbLink.h
+++ b/src/ioc/db/dbDbLink.h
@@ -23,16 +23,11 @@ extern "C" {
struct link;
struct dbLocker;
-struct dbCommon;
epicsShareFunc long dbDbInitLink(struct link *plink, short dbfType);
epicsShareFunc void dbDbAddLink(struct dbLocker *locker, struct link *plink,
short dbfType, DBADDR *ptarget);
-#ifdef EPICS_PRIVATE_API
-void dbDbLinkPUTF(dbCommon *psrc, dbCommon *pdst);
-#endif
-
#ifdef __cplusplus
}
#endif
diff --git a/src/ioc/misc/dbCore.dbd b/src/ioc/misc/dbCore.dbd
index 921b3818e..5f970f12d 100644
--- a/src/ioc/misc/dbCore.dbd
+++ b/src/ioc/misc/dbCore.dbd
@@ -19,8 +19,12 @@ variable(dbBptNotMonotonic,int)
variable(dbQuietMacroWarnings,int)
variable(dbConvertStrict,int)
+# PUTF/RPRO tracing; set TPRO on records to trace
+variable(dbAccessDebugPUTF,int)
+
# dbLoadTemplate settings
variable(dbTemplateMaxVars,int)
+
# Default number of parallel callback threads
variable(callbackParallelThreadsDefault,int)
From 76a4a20698807317e765152f7d37ae4332db5e89 Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Thu, 2 Aug 2018 17:00:27 -0500
Subject: [PATCH 077/147] Improved and extended the PUTF/RPRO tests
Added as a unit test, although we might need additional work if we see
the race conditions that are still possible in the code.
---
src/std/rec/test/Makefile | 2 +-
src/std/rec/test/asyncproctest.c | 49 +++++++++++++++++++++++++++----
src/std/rec/test/asyncproctest.db | 28 ++++++++++++++++--
3 files changed, 70 insertions(+), 9 deletions(-)
diff --git a/src/std/rec/test/Makefile b/src/std/rec/test/Makefile
index 91443a2b0..70c5cc224 100644
--- a/src/std/rec/test/Makefile
+++ b/src/std/rec/test/Makefile
@@ -112,7 +112,7 @@ TESTPROD_HOST += asyncproctest
asyncproctest_SRCS += asyncproctest.c
asyncproctest_SRCS += asyncproctest_registerRecordDeviceDriver.cpp
TESTFILES += $(COMMON_DIR)/asyncproctest.dbd ../asyncproctest.db
-#TESTS += asyncproctest # full of races...
+TESTS += asyncproctest
# epicsRunRecordTests runs all the test programs in a known working order.
testHarness_SRCS += epicsRunRecordTests.c
diff --git a/src/std/rec/test/asyncproctest.c b/src/std/rec/test/asyncproctest.c
index 1987c05f4..bd2ffc41f 100644
--- a/src/std/rec/test/asyncproctest.c
+++ b/src/std/rec/test/asyncproctest.c
@@ -13,48 +13,87 @@
#include
#include
#include
+#include "registryFunction.h"
+#include
+
+epicsEventId done;
+static int waitFor;
+
+static
+long doneSubr(subRecord *prec)
+{
+ if (--waitFor <= 0)
+ epicsEventMustTrigger(done);
+ return 0;
+}
void asyncproctest_registerRecordDeviceDriver(struct dbBase *);
MAIN(asyncproctest)
{
- testPlan(0);
+ testPlan(21);
+
+ done = epicsEventMustCreate(epicsEventEmpty);
testdbPrepare();
testdbReadDatabase("asyncproctest.dbd", NULL, NULL);
asyncproctest_registerRecordDeviceDriver(pdbbase);
- testdbReadDatabase("asyncproctest.db", NULL, "TPRO=1");
+ registryFunctionAdd("doneSubr", (REGISTRYFUNCTION) doneSubr);
+ testdbReadDatabase("asyncproctest.db", NULL, "TPRO=0");
+
+ dbAccessDebugPUTF = 1;
testIocInitOk();
testDiag("===== Chain 1 ======");
+ waitFor = 2;
testdbPutFieldOk("chain1.B", DBF_LONG, 6);
testdbPutFieldOk("chain1.B", DBF_LONG, 7);
- epicsThreadSleep(1.0);
+ if (epicsEventWaitWithTimeout(done, 10.0) != epicsEventOK)
+ testAbort("Processing timed out");
testdbGetFieldEqual("chain1", DBF_LONG, 7);
testdbGetFieldEqual("chain1.A", DBF_LONG, 2);
testDiag("===== Chain 2 ======");
+ waitFor = 2;
testdbPutFieldOk("chain2:1.B", DBF_LONG, 6);
testdbPutFieldOk("chain2:1.B", DBF_LONG, 7);
- epicsThreadSleep(1.0);
+ if (epicsEventWaitWithTimeout(done, 10.0) != epicsEventOK)
+ testAbort("Processing timed out");
testdbGetFieldEqual("chain2:1", DBF_LONG, 7);
testdbGetFieldEqual("chain2:2", DBF_LONG, 7);
testdbGetFieldEqual("chain2:1.A", DBF_LONG, 2);
testdbGetFieldEqual("chain2:2.A", DBF_LONG, 2);
+ testDiag("===== Chain 2 again ======");
+
+ waitFor = 2;
+ testdbPutFieldOk("chain2:1.B", DBF_LONG, 6);
+ testdbPutFieldOk("chain2:1.B", DBF_LONG, 7);
+ testdbPutFieldOk("chain2:1.B", DBF_LONG, 8);
+
+ if (epicsEventWaitWithTimeout(done, 10.0) != epicsEventOK)
+ testAbort("Processing timed out");
+
+ testdbGetFieldEqual("chain2:1", DBF_LONG, 8);
+ testdbGetFieldEqual("chain2:2", DBF_LONG, 8);
+ testdbGetFieldEqual("chain2:1.A", DBF_LONG, 5);
+ testdbGetFieldEqual("chain2:2.A", DBF_LONG, 4);
+
testDiag("===== Chain 3 ======");
+ waitFor = 2;
testdbPutFieldOk("chain3.B", DBF_LONG, 6);
testdbPutFieldOk("chain3.B", DBF_LONG, 7);
- epicsThreadSleep(1.0);
+ if (epicsEventWaitWithTimeout(done, 10.0) != epicsEventOK)
+ testAbort("Processing timed out");
testdbGetFieldEqual("chain3", DBF_LONG, 7);
testdbGetFieldEqual("chain3.A", DBF_LONG, 2);
diff --git a/src/std/rec/test/asyncproctest.db b/src/std/rec/test/asyncproctest.db
index e2fc946d8..352b6ca56 100644
--- a/src/std/rec/test/asyncproctest.db
+++ b/src/std/rec/test/asyncproctest.db
@@ -5,6 +5,11 @@ record(calcout, "chain1") {
field(CALC, "A:=A+1;B")
field(ODLY, "0.1")
field(TPRO, "$(TPRO=)")
+ field(FLNK, "done1")
+}
+record(sub, "done1") {
+ field(SNAM, "doneSubr")
+ field(TPRO, "$(TPRO=)")
}
@@ -12,22 +17,39 @@ record(calcout, "chain1") {
# async record chained after syncronous record
record(calcout, "chain2:1") {
field(CALC, "A:=A+1;B")
- # DOLY=0 synchronous
+ # ODLY=0 synchronous
field(OUT , "chain2:2.B PP")
field(TPRO, "$(TPRO=)")
}
+record(ai, "chain2:3") {
+ field(INP, "chain2:1 CPP")
+ field(FLNK, "chain2:2")
+ field(TPRO, "$(TPRO=)")
+}
+
record(calcout, "chain2:2") {
field(CALC, "A:=A+1;B")
- field(ODLY, "0.1")
+ field(ODLY, "0.5")
+ field(TPRO, "$(TPRO=)")
+ field(FLNK, "done2")
+}
+record(sub, "done2") {
+ field(SNAM, "doneSubr")
field(TPRO, "$(TPRO=)")
}
+
# ANJ's error case
-# async record FLNK's to itself
+# async record FLNK's to itself (via done3)
record(calcout, "chain3") {
field(CALC, "A:=A+1;B")
field(ODLY, "0.1")
+ field(FLNK, "done3")
+ field(TPRO, "$(TPRO=)")
+}
+record(sub, "done3") {
+ field(SNAM, "doneSubr")
field(FLNK, "chain3")
field(TPRO, "$(TPRO=)")
}
From 6e85a407da522adb631980001f12ba8abc7f8b20 Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Thu, 2 Aug 2018 17:00:57 -0500
Subject: [PATCH 078/147] Release notes for PUTF/RPRO update
---
documentation/RELEASE_NOTES.html | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html
index f5936bcc2..fdfad15a7 100644
--- a/documentation/RELEASE_NOTES.html
+++ b/documentation/RELEASE_NOTES.html
@@ -17,6 +17,21 @@
-->
+Propagate PUTF across Asynchronous record processing
+
+The IOC contains a mechanism involving the PUTF and RPRO fields of each
+record to ensure that if a record is busy when it receives a put to one of its
+fields, the record will be processed again to ensure that the new field value
+has been correctly acted on. Until now that mechanism only worked if the put was
+to the asynchronous record itself, so puts that were chained from some other
+record via a DB link did not cause reprocessing.
+
+In this release the mechanism has been extended to propagate the PUTF state
+across DB links until all downstream records have been reprocessed. Some
+additional information about the record state can be shown by setting the TPRO
+field of an upstream record, and even more trace data is displayed if the
+debugging variable dbAccessDebugPUTF is set in addition to TPRO.
+
Restore use of ledlib for VxWorks command editing
The epicsReadline refactoring work described below unfortunately disabled the
From 592a83385d8ef11720fa160cef2b1931208166dd Mon Sep 17 00:00:00 2001
From: Martin Konrad
Date: Tue, 7 Aug 2018 12:06:20 -0400
Subject: [PATCH 079/147] Add missing incude in dbLock.h
Fixes lp:1784631.
---
src/ioc/db/dbLock.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/ioc/db/dbLock.h b/src/ioc/db/dbLock.h
index 1d6388ed3..e15ddd0e9 100644
--- a/src/ioc/db/dbLock.h
+++ b/src/ioc/db/dbLock.h
@@ -13,6 +13,8 @@
#ifndef INCdbLockh
#define INCdbLockh
+#include
+
#include "ellLib.h"
#include "shareLib.h"
From 2548a372672367b2662dac5a484b634acb8b7f65 Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Wed, 8 Aug 2018 16:53:32 -0500
Subject: [PATCH 080/147] Update/clean up EpicsHostArch.pl
---
src/tools/EpicsHostArch.pl | 76 +++++++++++++++++++++-----------------
1 file changed, 42 insertions(+), 34 deletions(-)
diff --git a/src/tools/EpicsHostArch.pl b/src/tools/EpicsHostArch.pl
index 5f5dad453..e8e49bc5e 100644
--- a/src/tools/EpicsHostArch.pl
+++ b/src/tools/EpicsHostArch.pl
@@ -1,47 +1,55 @@
-eval 'exec perl -S $0 ${1+"$@"}' # -*- Mode: perl -*-
- if $running_under_some_shell; # EpicsHostArch.pl
+#!/usr/bin/env perl
#*************************************************************************
-# Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne
+# Copyright (c) 2018 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.
#*************************************************************************
-# Returns the Epics host architecture suitable
-# for assigning to the EPICS_HOST_ARCH variable
+# Returns an architecture name for EPICS_HOST_ARCH that should be
+# appropriate for the CPU that this version of Perl was built for.
+# Any arguments to the program will be appended with separator '-'
+# to allow flags like -gnu -debug and/or -static to be added.
+
+# Before Base has been built, use a command like this:
+# bash$ export EPICS_HOST_ARCH=`perl src/tools/EpicsHostArch.pl`
+#
+# If Base is already built, use
+# tcsh% setenv EPICS_HOST_ARCH `perl base/lib/perl/EpicsHostArch.pl`
+
+# If your architecture is not recognized by this script, please send
+# the output from running 'perl --version' to the EPICS tech-talk
+# mailing list to have it added.
+
+use strict;
use Config;
use POSIX;
-$suffix="";
-$suffix="-".$ARGV[0] if ($ARGV[0] ne "");
+print join('-', HostArch(), @ARGV), "\n";
-$EpicsHostArch = GetEpicsHostArch();
-print "$EpicsHostArch$suffix\n";
+sub HostArch {
+ my $arch = $Config{archname};
+ for ($arch) {
+ return 'linux-x86_64' if m/^x86_64-linux/;
+ return 'linux-x86' if m/^i[3-6]86-linux/;
+ return 'linux-arm' if m/^arm-linux/;
+ return 'windows-x64' if m/^MSWin32-x64/;
+ return 'win32-x86' if m/^MSWin32-x86/;
+ return "cygwin-x86_64" if m/^x86_64-cygwin/;
+ return "cygwin-x86" if m/^i[3-6]86-cygwin/;
+ return 'solaris-sparc' if m/^sun4-solaris/;
+ return 'solaris-x86' if m/^i86pc-solaris/;
-sub GetEpicsHostArch { # no args
- $arch=$Config{'archname'};
- if ($arch =~ /sun4-solaris/) { return "solaris-sparc";
- } elsif ($arch =~ m/i86pc-solaris/) { return "solaris-x86";
- } elsif ($arch =~ m/i[3-6]86-linux/){ return "linux-x86";
- } elsif ($arch =~ m/x86_64-linux/) { return "linux-x86_64";
- } 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/) {
- 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"; }
- elsif ($cpu =~ m/i386/) { return "darwin-x86"; }
- elsif ($cpu =~ m/x86_64/) { return "darwin-x86"; }
- else { return "unsupported"; }
- } else { return "unsupported"; }
+ my ($kernel, $hostname, $release, $version, $cpu) = uname;
+ if (m/^darwin/) {
+ for ($cpu) {
+ return 'darwin-x86' if m/^(i386|x86_64)/;
+ return 'darwin-ppc' if m/Power Macintosh/;
+ }
+ die "$0: macOS CPU type '$cpu' not recognized\n";
+ }
+
+ die "$0: Architecture '$arch' not recognized\n";
+ }
}
-
-#EOF EpicsHostArch.pl
-
From 8ffea9de2700d41fe526f0e151a0ad30f1787510 Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Fri, 10 Aug 2018 14:12:19 -0500
Subject: [PATCH 081/147] Remove macLib warning indicators
Only add ',undefined' tags to macLib output when we aren't
suppressing warnings, e.g. using msi's -V flag.
---
documentation/RELEASE_NOTES.html | 19 +++++++--
src/ioc/dbtemplate/msi.html | 8 ++--
src/ioc/dbtemplate/test/msi.plt | 6 +--
src/ioc/dbtemplate/test/t1-result.txt | 2 +-
src/ioc/dbtemplate/test/t2-result.txt | 12 +++---
src/ioc/dbtemplate/test/t3-result.txt | 56 +++++++++++++--------------
src/ioc/dbtemplate/test/t4-result.txt | 12 +++---
src/ioc/dbtemplate/test/t5-result.txt | 8 ++--
src/ioc/dbtemplate/test/t6-result.txt | 8 ++--
src/ioc/dbtemplate/test/t7-result.txt | 21 ++++++++++
src/libCom/macLib/macCore.c | 9 ++++-
src/libCom/test/macLibTest.c | 8 +++-
12 files changed, 105 insertions(+), 64 deletions(-)
create mode 100644 src/ioc/dbtemplate/test/t7-result.txt
diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html
index 57baf3db1..9c6c43a90 100644
--- a/documentation/RELEASE_NOTES.html
+++ b/documentation/RELEASE_NOTES.html
@@ -16,13 +16,24 @@
+Warning indicators in msi (and macLib) output
+
+The libCom macro expansion library has been modified so that when the
+SUPPRESS_WARNINGS flag is set it will no longer include any ,undefined
+or ,recursive indicators in its output when undefined or recursive
+macros are encountered. These indicators were harmless when the output was fed
+into an IOC along with a definition for the macro, but when the msi
+tool was used to generate other kinds of files they caused problems. If the
+msi -V flag is used the markers will still be present in the output
+whenever the appropriate condition is seen.
+
Improvements to msi
In addition to fixing its response to discovering parsing errors in its
- substitution input file (reported as Launchpad
- bug #1503661)
- so it now deletes the incomplete output file, the msi program has been cleaned
- up a little bit internally.
+substitution input file (reported as Launchpad
+bug #1503661)
+so it now deletes the incomplete output file, the msi program has been cleaned
+up a little bit internally.
All array records now post monitors on their array-length fields
diff --git a/src/ioc/dbtemplate/msi.html b/src/ioc/dbtemplate/msi.html
index ff4341ead..b5929fc79 100644
--- a/src/ioc/dbtemplate/msi.html
+++ b/src/ioc/dbtemplate/msi.html
@@ -34,10 +34,10 @@ be written to stdout unless the -o option is given.
- -V
- - Verbose warnings; if this parameter is specified then any undefined
- macro discovered in the template file which does not have an associated
- default value is considered an error. An error message is generated, and
- when msi terminates it will do so with an exit status of 2.
+ - Verbose warnings; if this parameter is specified then any undefined or
+ recursive macros discovered in the template will be considered an error and
+ will be marked in the output file. An error message will be shown, and when
+ msi terminates it will do so with an exit status of 2.
- -g
- When this flag is given all macros defined in a substitution file will
diff --git a/src/ioc/dbtemplate/test/msi.plt b/src/ioc/dbtemplate/test/msi.plt
index bd663070f..414912583 100644
--- a/src/ioc/dbtemplate/test/msi.plt
+++ b/src/ioc/dbtemplate/test/msi.plt
@@ -31,18 +31,18 @@ ok(msi('-S ../t5-substitute.txt ../t5-template.txt'), slurp('../t5-result.txt'))
# Substitution file, pattern format
ok(msi('-S../t6-substitute.txt ../t6-template.txt'), slurp('../t6-result.txt'));
-# Output option -o
+# Output option -o and verbose option -V
my $out = 't7-output.txt';
my $count = 5; # Try up to 5 times...
my $result;
do {
unlink $out;
- msi("-I.. -o $out ../t1-template.txt");
+ msi("-I.. -V -o $out ../t1-template.txt");
$result = slurp($out);
print "# msi output file empty, retrying\n"
if $result eq '';
} while ($result eq '') && (--$count > 0);
-ok($result, slurp('../t1-result.txt'));
+ok($result, slurp('../t7-result.txt'));
# Dependency generation, include/substitute model
ok(msi('-I.. -D -o t8.txt ../t1-template.txt'), slurp('../t8-result.txt'));
diff --git a/src/ioc/dbtemplate/test/t1-result.txt b/src/ioc/dbtemplate/test/t1-result.txt
index fcd065585..abe94ebf7 100644
--- a/src/ioc/dbtemplate/test/t1-result.txt
+++ b/src/ioc/dbtemplate/test/t1-result.txt
@@ -1,6 +1,6 @@
This is t1-template.txt
-With $(a,undefined) & $(b,undefined):
+With $(a) & $(b):
This is t1-include.txt
a = default value used when a is undefined
b = default value used when b is undefined
diff --git a/src/ioc/dbtemplate/test/t2-result.txt b/src/ioc/dbtemplate/test/t2-result.txt
index 5239e6a05..123d2d92f 100644
--- a/src/ioc/dbtemplate/test/t2-result.txt
+++ b/src/ioc/dbtemplate/test/t2-result.txt
@@ -1,6 +1,6 @@
-a = va1-a b = def-b c = def-c d = $(d,undefined)
-a = va2-a b = va2-b c = def-c d = $(d,undefined)
-a = va3-a b = va3-b c = va3-c d = $(d,undefined)
-a = va4-a b = va4-b c = def-c d = $(d,undefined)
-a = va5-a b = def-b c = def-c d = $(d,undefined)
-a = pt3-a b = pt3-b c = pt3-c d = $(d,undefined)
+a = va1-a b = def-b c = def-c d = $(d)
+a = va2-a b = va2-b c = def-c d = $(d)
+a = va3-a b = va3-b c = va3-c d = $(d)
+a = va4-a b = va4-b c = def-c d = $(d)
+a = va5-a b = def-b c = def-c d = $(d)
+a = pt3-a b = pt3-b c = pt3-c d = $(d)
diff --git a/src/ioc/dbtemplate/test/t3-result.txt b/src/ioc/dbtemplate/test/t3-result.txt
index c6961507f..d7823e541 100644
--- a/src/ioc/dbtemplate/test/t3-result.txt
+++ b/src/ioc/dbtemplate/test/t3-result.txt
@@ -1,28 +1,28 @@
-a = gb1-a b = gb1-b c = def-c d = $(d,undefined)
-a = va1-a b = gb1-b c = def-c d = $(d,undefined)
-a = va2-a b = va2-b c = def-c d = $(d,undefined)
-a = va3-a b = va3-b c = va3-c d = $(d,undefined)
-a = va4-a b = va4-b c = def-c d = $(d,undefined)
-a = va5-a b = gb1-b c = def-c d = $(d,undefined)
-a = gb1-a b = gb1-b c = def-c d = $(d,undefined)
-a = gb2-a b = gb2-b c = def-c d = $(d,undefined)
-a = va1-a b = gb2-b c = def-c d = $(d,undefined)
-a = va2-a b = va2-b c = def-c d = $(d,undefined)
-a = va3-a b = va3-b c = va3-c d = $(d,undefined)
-a = va4-a b = va4-b c = def-c d = $(d,undefined)
-a = va5-a b = gb2-b c = def-c d = $(d,undefined)
-a = gb2-a b = gb2-b c = def-c d = $(d,undefined)
-a = gb3-a b = gb3-b c = def-c d = $(d,undefined)
-a = pt1-a b = gb3-b c = def-c d = $(d,undefined)
-a = pt2-a b = pt2-b c = def-c d = $(d,undefined)
-a = pt3-a b = pt3-b c = pt3-c d = $(d,undefined)
-a = pt4-a b = pt4-b c = def-c d = $(d,undefined)
-a = pt5-a b = gb3-b c = def-c d = $(d,undefined)
-a = gb3-a b = gb3-b c = def-c d = $(d,undefined)
-a = gb4-a b = gb4-b c = def-c d = $(d,undefined)
-a = pt1-a b = gb4-b c = def-c d = $(d,undefined)
-a = pt2-a b = pt2-b c = def-c d = $(d,undefined)
-a = pt3-a b = pt3-b c = pt3-c d = $(d,undefined)
-a = pt4-a b = pt4-b c = def-c d = $(d,undefined)
-a = pt5-a b = gb4-b c = def-c d = $(d,undefined)
-a = gb4-a b = gb4-b c = def-c d = $(d,undefined)
+a = gb1-a b = gb1-b c = def-c d = $(d)
+a = va1-a b = gb1-b c = def-c d = $(d)
+a = va2-a b = va2-b c = def-c d = $(d)
+a = va3-a b = va3-b c = va3-c d = $(d)
+a = va4-a b = va4-b c = def-c d = $(d)
+a = va5-a b = gb1-b c = def-c d = $(d)
+a = gb1-a b = gb1-b c = def-c d = $(d)
+a = gb2-a b = gb2-b c = def-c d = $(d)
+a = va1-a b = gb2-b c = def-c d = $(d)
+a = va2-a b = va2-b c = def-c d = $(d)
+a = va3-a b = va3-b c = va3-c d = $(d)
+a = va4-a b = va4-b c = def-c d = $(d)
+a = va5-a b = gb2-b c = def-c d = $(d)
+a = gb2-a b = gb2-b c = def-c d = $(d)
+a = gb3-a b = gb3-b c = def-c d = $(d)
+a = pt1-a b = gb3-b c = def-c d = $(d)
+a = pt2-a b = pt2-b c = def-c d = $(d)
+a = pt3-a b = pt3-b c = pt3-c d = $(d)
+a = pt4-a b = pt4-b c = def-c d = $(d)
+a = pt5-a b = gb3-b c = def-c d = $(d)
+a = gb3-a b = gb3-b c = def-c d = $(d)
+a = gb4-a b = gb4-b c = def-c d = $(d)
+a = pt1-a b = gb4-b c = def-c d = $(d)
+a = pt2-a b = pt2-b c = def-c d = $(d)
+a = pt3-a b = pt3-b c = pt3-c d = $(d)
+a = pt4-a b = pt4-b c = def-c d = $(d)
+a = pt5-a b = gb4-b c = def-c d = $(d)
+a = gb4-a b = gb4-b c = def-c d = $(d)
diff --git a/src/ioc/dbtemplate/test/t4-result.txt b/src/ioc/dbtemplate/test/t4-result.txt
index 664872013..6ee8aa0f3 100644
--- a/src/ioc/dbtemplate/test/t4-result.txt
+++ b/src/ioc/dbtemplate/test/t4-result.txt
@@ -1,6 +1,6 @@
-a = va1-a b = def-b c = def-c d = $(d,undefined)
-a = va2-a b = va2-b c = def-c d = $(d,undefined)
-a = va3-a b = va3-b c = va3-c d = $(d,undefined)
-a = va4-a b = va4-b c = va3-c d = $(d,undefined)
-a = va5-a b = va4-b c = va3-c d = $(d,undefined)
-a = pt3-a b = pt3-b c = pt3-c d = $(d,undefined)
+a = va1-a b = def-b c = def-c d = $(d)
+a = va2-a b = va2-b c = def-c d = $(d)
+a = va3-a b = va3-b c = va3-c d = $(d)
+a = va4-a b = va4-b c = va3-c d = $(d)
+a = va5-a b = va4-b c = va3-c d = $(d)
+a = pt3-a b = pt3-b c = pt3-c d = $(d)
diff --git a/src/ioc/dbtemplate/test/t5-result.txt b/src/ioc/dbtemplate/test/t5-result.txt
index 19a57c87c..2ae214948 100644
--- a/src/ioc/dbtemplate/test/t5-result.txt
+++ b/src/ioc/dbtemplate/test/t5-result.txt
@@ -2,19 +2,19 @@
a = 111
b = 222
c = xx
-d = $(d,undefined)
+d = $(d)
# comment line
a = aaa
b = bbb
c = ccc
-d = $(d,undefined)
+d = $(d)
# comment line
a = AA
b = BB
c = xx
-d = $(d,undefined)
+d = $(d)
# comment line
a = aaa
b = bbb
c = yy
-d = $(d,undefined)
+d = $(d)
diff --git a/src/ioc/dbtemplate/test/t6-result.txt b/src/ioc/dbtemplate/test/t6-result.txt
index 19a57c87c..2ae214948 100644
--- a/src/ioc/dbtemplate/test/t6-result.txt
+++ b/src/ioc/dbtemplate/test/t6-result.txt
@@ -2,19 +2,19 @@
a = 111
b = 222
c = xx
-d = $(d,undefined)
+d = $(d)
# comment line
a = aaa
b = bbb
c = ccc
-d = $(d,undefined)
+d = $(d)
# comment line
a = AA
b = BB
c = xx
-d = $(d,undefined)
+d = $(d)
# comment line
a = aaa
b = bbb
c = yy
-d = $(d,undefined)
+d = $(d)
diff --git a/src/ioc/dbtemplate/test/t7-result.txt b/src/ioc/dbtemplate/test/t7-result.txt
new file mode 100644
index 000000000..fcd065585
--- /dev/null
+++ b/src/ioc/dbtemplate/test/t7-result.txt
@@ -0,0 +1,21 @@
+This is t1-template.txt
+
+With $(a,undefined) & $(b,undefined):
+This is t1-include.txt
+ a = default value used when a is undefined
+ b = default value used when b is undefined
+End of t1-include.txt
+
+On defining a=aaa & b=bbb:
+This is t1-include.txt again
+ a = aaa
+ b = bbb
+End of t1-include.txt
+
+On setting a="aa":
+This is t1-include.txt again
+ a = "aa"
+ b = bbb
+End of t1-include.txt
+
+End of t1-template.txt
diff --git a/src/libCom/macLib/macCore.c b/src/libCom/macLib/macCore.c
index 55d31719e..6f84d6b84 100644
--- a/src/libCom/macLib/macCore.c
+++ b/src/libCom/macLib/macCore.c
@@ -902,11 +902,16 @@ static void refer ( MAC_HANDLE *handle, MAC_ENTRY *entry, int level,
}
}
- /* Bad reference, insert $(name,errval) */
+ /* Bad reference, insert either $(name,) or $(name) */
if ( v < valend ) *v++ = '$';
if ( v < valend ) *v++ = '(';
cpy2val( refname, &v, valend );
- cpy2val( errval, &v, valend );
+ if (handle->flags & FLAG_SUPPRESS_WARNINGS) {
+ if ( v < valend ) *v++ = ')';
+ *v = '\0';
+ }
+ else
+ cpy2val( errval, &v, valend );
cleanup:
if (pop) {
diff --git a/src/libCom/test/macLibTest.c b/src/libCom/test/macLibTest.c
index 7f1e2c544..742fc79e2 100644
--- a/src/libCom/test/macLibTest.c
+++ b/src/libCom/test/macLibTest.c
@@ -65,11 +65,11 @@ static void ovcheck(void)
MAIN(macLibTest)
{
- testPlan(91);
+ testPlan(93);
if (macCreateHandle(&h, NULL))
testAbort("macCreateHandle() failed");
- macSuppressWarning(h, TRUE);
+ eltc(0);
check("FOO", " FOO");
@@ -215,6 +215,10 @@ MAIN(macLibTest)
check("${FOO,FOO=${FOO}}", "!$(FOO,recursive)");
check("${FOO=GRIBBLE,FOO=${FOO}}", "!$(FOO,recursive)");
+ macSuppressWarning(h, TRUE);
+ check("$(CRUX)", "!$(CRUX)");
+ check("${FOO}", "!$(BAR)");
+
ovcheck();
return testDone();
From 9051cdbb34429cc03867f5ec1be990d63c3193a9 Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Fri, 10 Aug 2018 15:20:29 -0500
Subject: [PATCH 082/147] Added a simpler startup/EpicsHostArch for
backwards-compatibility
Many downstream modules seem to be using the EpicsHostArch script in
their CI build scripts and would break if we remove that. I created
a new version that finds and execs the Perl script directly.
Also reworded and expanded the Release Notes about the EpicsHostArch
scripts.
---
documentation/RELEASE_NOTES.html | 28 ++++++++++++++++++++--------
startup/EpicsHostArch | 21 +++++++++++++++++++++
2 files changed, 41 insertions(+), 8 deletions(-)
create mode 100644 startup/EpicsHostArch
diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html
index a419bcabc..d6e40de42 100644
--- a/documentation/RELEASE_NOTES.html
+++ b/documentation/RELEASE_NOTES.html
@@ -20,15 +20,27 @@ and have grown crufty (technical term). This release includes the following
updates to these files:
-- The EpicsHostArch script has been removed.
-EpicsHostArch.pl should be used instead.
-- The EpicsHostArch.pl script has been moved into src/tools
-from where it gets installed into lib/perl. The build system has been
-adjusted to look for it in both places if the EPICS_HOST_ARCH
-environment variable has not been set at build-time. Sites that may have used
-this to set EPICS_HOST_ARCH as part of their standard environment may
-need to adjust their scripts when they upgrade to this release.
+- The Perl EpicsHostArch.pl script has been rewritten, and support
+for a few previously missing host architectures has been added to it.
+
+- The EpicsHostArch.pl script has also been moved into the standard
+src/tools directory, from where it will be installed into
+lib/perl. In this new location it is no longer executable, so it must
+be run by the perl executable.
+
+- The build system has been adjusted to look for EpicsHostArch.pl in
+both places if the EPICS_HOST_ARCH environment variable has not been
+set at build-time.
+
+- Sites that used the original Perl script to set EPICS_HOST_ARCH as
+part of their standard environment will need to adjust their scripts when they
+upgrade to this release.
+
+- The EpicsHostArch shell script has been replaced with a wrapper
+routine that calls the Perl EpicsHostArch.pl script. Sites that rely on
+this script to set EPICS_HOST_ARCH should consider switching to the
+Perl script instead.
- The Site.cshrc and Site.profile files have been renamed to
unix.csh and unix.sh, respectively.
diff --git a/startup/EpicsHostArch b/startup/EpicsHostArch
new file mode 100644
index 000000000..de7f3d525
--- /dev/null
+++ b/startup/EpicsHostArch
@@ -0,0 +1,21 @@
+#!/bin/sh
+# Script to find and run the Perl EpicsHostArch.pl script.
+
+# This script is provided for backwards-compatibility only and may be
+# dropped from future releases of Base. Please adjust callers to run
+# the Perl version directly as this startup directory isn't copied to
+# INSTALL_LOCATION by the EPICS build system.
+
+EHA=EpicsHostArch.pl
+
+cd "$(dirname "$0")/.."
+
+# Perl script will be installed into lib/perl
+[[ -f lib/perl/$EHA ]] && exec perl lib/perl/$EHA $*
+
+# If Base hasn't been built yet, use the source Luke
+[[ -f src/tools/$EHA ]] && exec perl src/tools/$EHA $*
+
+# Die with an error message
+echo "$0: Can't find $EHA" >&2
+exit 1
From 8e42f516b0f6552857c7eba4171b32353f75a807 Mon Sep 17 00:00:00 2001
From: Martin Konrad
Date: Mon, 13 Aug 2018 15:50:58 -0400
Subject: [PATCH 083/147] iocLogserver: allow log file limit to be disabled
According to the Application Developer's Guide setting the environment
variable EPICS_IOC_LOG_FILE_LIMIT=0 should disable the limit on the
file size.
---
src/util/iocLogServer.c | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)
diff --git a/src/util/iocLogServer.c b/src/util/iocLogServer.c
index f5694fc0f..f42aa4563 100644
--- a/src/util/iocLogServer.c
+++ b/src/util/iocLogServer.c
@@ -347,11 +347,6 @@ static int openLogFile (struct ioc_log_server *pserver)
{
enum TF_RETURN ret;
- if (ioc_log_file_limit==0u) {
- pserver->poutfile = stderr;
- return IOCLS_ERROR;
- }
-
if (pserver->poutfile && pserver->poutfile != stderr){
fclose (pserver->poutfile);
pserver->poutfile = NULL;
@@ -627,7 +622,7 @@ static void writeMessagesToLog (struct iocLogClient *pclient)
strlen(pclient->ascii_time) + nchar + 3u;
assert (nTotChar <= INT_MAX);
ntci = (int) nTotChar;
- if ( pclient->pserver->filePos+ntci >= pclient->pserver->max_file_size ) {
+ if ( pclient->pserver->max_file_size && pclient->pserver->filePos+ntci >= pclient->pserver->max_file_size ) {
if ( pclient->pserver->max_file_size >= pclient->pserver->filePos ) {
unsigned nPadChar;
/*
@@ -771,7 +766,7 @@ static int getConfig(void)
&EPICS_IOC_LOG_FILE_LIMIT,
&ioc_log_file_limit);
if(status>=0){
- if (ioc_log_file_limit<=0) {
+ if (ioc_log_file_limit < 0) {
envFailureNotify (&EPICS_IOC_LOG_FILE_LIMIT);
return IOCLS_ERROR;
}
From 58d4242b68a25a82223265d53554977532383f06 Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Fri, 17 Aug 2018 13:09:33 -0500
Subject: [PATCH 084/147] osiClockTime: Only call clock_setting() on embedded
OSs
An update to Apple's XCode broke the iOS build because they have
added Posix CLOCK_REALTIME support since this code was written and
now if you compile a call to clock_settime() it stops the build.
---
src/libCom/osi/osiClockTime.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/libCom/osi/osiClockTime.c b/src/libCom/osi/osiClockTime.c
index 1463ee551..8d8cb2606 100644
--- a/src/libCom/osi/osiClockTime.c
+++ b/src/libCom/osi/osiClockTime.c
@@ -159,6 +159,7 @@ static int ClockTimeGetCurrent(epicsTimeStamp *pDest)
/* If a Hi-Res clock is available and works, use it */
#ifdef CLOCK_REALTIME_HR
clock_gettime(CLOCK_REALTIME_HR, &clockNow) &&
+ /* Note: Uses the lo-res clock below if the above call fails */
#endif
clock_gettime(CLOCK_REALTIME, &clockNow);
@@ -166,9 +167,15 @@ static int ClockTimeGetCurrent(epicsTimeStamp *pDest)
clockNow.tv_sec < POSIX_TIME_AT_EPICS_EPOCH) {
clockNow.tv_sec = POSIX_TIME_AT_EPICS_EPOCH + 86400;
clockNow.tv_nsec = 0;
+
+#if defined(vxWorks) || defined(__rtems__)
clock_settime(CLOCK_REALTIME, &clockNow);
errlogPrintf("WARNING: OS Clock time was read before being set.\n"
"Using 1990-01-02 00:00:00.000000 UTC\n");
+#else
+ errlogPrintf("WARNING: OS Clock pre-dates the EPICS epoch!\n"
+ "Using 1990-01-02 00:00:00.000000 UTC\n");
+#endif
}
epicsTimeFromTimespec(pDest, &clockNow);
From 13735a8088c9d842dd271ba82b773e81e260c9d5 Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Fri, 17 Aug 2018 13:18:47 -0500
Subject: [PATCH 085/147] Fix for lp: #1786320
A dbCa link that reads an enum as a string subscribes to the link target
twice, once as DBR_TIME_ENUM and again as DBR_TIME_STRING. This change
prevents ENUM updates from triggering CP/CPP record processing if there
is also a STRING subscription for this link.
---
src/db/dbCa.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/db/dbCa.c b/src/db/dbCa.c
index 610ce9d89..0b4373a24 100644
--- a/src/db/dbCa.c
+++ b/src/db/dbCa.c
@@ -648,6 +648,7 @@ static void eventCallback(struct event_handler_args arg)
struct dbr_time_double *pdbr_time_double;
dbCaCallback monitor = 0;
void *userPvt = 0;
+ int doScan = 1;
assert(pca);
epicsMutexMustLock(pca->lock);
@@ -676,10 +677,13 @@ static void eventCallback(struct event_handler_args arg)
memcpy(pca->pgetString, dbr_value_ptr(arg.dbr, arg.type), size);
pca->gotInString = TRUE;
} else switch (arg.type){
+ case DBR_TIME_ENUM:
+ /* Disable the record scan if we also have a string monitor */
+ doScan = !(plink->value.pv_link.pvlMask & pvlOptInpString);
+ /* fall through */
case DBR_TIME_STRING:
case DBR_TIME_SHORT:
case DBR_TIME_FLOAT:
- case DBR_TIME_ENUM:
case DBR_TIME_CHAR:
case DBR_TIME_LONG:
case DBR_TIME_DOUBLE:
@@ -695,7 +699,7 @@ static void eventCallback(struct event_handler_args arg)
pca->sevr = pdbr_time_double->severity;
pca->stat = pdbr_time_double->status;
memcpy(&pca->timeStamp, &pdbr_time_double->stamp, sizeof(epicsTimeStamp));
- if (precord) {
+ if (doScan && precord) {
struct pv_link *ppv_link = &plink->value.pv_link;
if ((ppv_link->pvlMask & pvlOptCP) ||
From 4247d98b08a5a4eab22c1a0c080084cd429de368 Mon Sep 17 00:00:00 2001
From: Andrew Johnson
Date: Fri, 17 Aug 2018 13:25:18 -0500
Subject: [PATCH 086/147] Add fix to Release Notes
---
documentation/RELEASE_NOTES.html | 2 ++
1 file changed, 2 insertions(+)
diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html
index fb5238bd1..9bd61ed34 100644
--- a/documentation/RELEASE_NOTES.html
+++ b/documentation/RELEASE_NOTES.html
@@ -30,6 +30,8 @@ INVALID_ALARM.