From 5d61a512d1eb2533697b4b7e9adf71b34e36fe29 Mon Sep 17 00:00:00 2001 From: "J. Lewis Muir" Date: Thu, 14 May 2015 16:23:23 -0500 Subject: [PATCH 1/6] doc: add ca_put_callback to CA ref man func call interface index The ca_put_callback function is not listed in the CA Reference Manual's function call interface index; add it. --- src/ca/CAref.html | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ca/CAref.html b/src/ca/CAref.html index 4432eaaca..afca14e41 100644 --- a/src/ca/CAref.html +++ b/src/ca/CAref.html @@ -209,6 +209,7 @@ $Date$

  • ca_poll
  • ca_puser
  • ca_put
  • +
  • ca_put_callback
  • ca_set_puser
  • ca_signal
  • ca_sg_block
  • From 65e781d58ab7bbac0836f94686e4b12556b78f53 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Tue, 23 Jun 2015 14:46:29 -0500 Subject: [PATCH 2/6] db: Fix off-by-one error in initHookName() Thanks to Lawrence T. Prevatte III for noticing that. --- src/db/initHooks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/db/initHooks.c b/src/db/initHooks.c index 5dc7f88e7..06925cacd 100644 --- a/src/db/initHooks.c +++ b/src/db/initHooks.c @@ -123,7 +123,7 @@ const char *initHookName(int state) "initHookAfterInterruptAccept", "initHookAtEnd" }; - if (state < 0 || state > NELEMENTS(stateName)) { + if (state < 0 || state >= NELEMENTS(stateName)) { return "Not an initHookState"; } return stateName[state]; From 84c3ec7c64d254c7fac27a466200cba28c6c5b73 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Tue, 23 Jun 2015 15:51:00 -0500 Subject: [PATCH 3/6] db: Correct DBF_CHAR range in recGbl.c Seems invisible, but spotted by Lawrence T. Prevatte III. --- src/db/recGbl.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/db/recGbl.c b/src/db/recGbl.c index e0d2480df..1337811a7 100644 --- a/src/db/recGbl.c +++ b/src/db/recGbl.c @@ -313,11 +313,11 @@ static void getMaxRangeValues(short field_type, double *pupper_limit, { switch(field_type){ case DBF_CHAR: - *pupper_limit = -128.0; - *plower_limit = 127.0; + *pupper_limit = (double) CHAR_MAX; + *plower_limit = (double) CHAR_MIN; break; case DBF_UCHAR: - *pupper_limit = 255.0; + *pupper_limit = (double) UCHAR_MAX; *plower_limit = 0.0; break; case DBF_SHORT: From c0e2a4436568bd4bdf28b429d6675dc797dd4a56 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Tue, 23 Jun 2015 17:04:37 -0500 Subject: [PATCH 4/6] Register dbPutAttribute with iocsh --- src/db/dbIocRegister.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/db/dbIocRegister.c b/src/db/dbIocRegister.c index a82337f03..df93dbd0e 100644 --- a/src/db/dbIocRegister.c +++ b/src/db/dbIocRegister.c @@ -223,6 +223,17 @@ static void dbtpnCallFunc(const iocshArgBuf *args) static const iocshFuncDef dbNotifyDumpFuncDef = {"dbNotifyDump",0,0}; static void dbNotifyDumpCallFunc(const iocshArgBuf *args) { dbNotifyDump();} +/* dbPutAttribute */ +static const iocshArg dbPutAttrArg0 = { "record type",iocshArgString}; +static const iocshArg dbPutAttrArg1 = { "attribute name",iocshArgString}; +static const iocshArg dbPutAttrArg2 = { "value",iocshArgString}; +static const iocshArg * const dbPutAttrArgs[] = + {&dbPutAttrArg0, &dbPutAttrArg1, &dbPutAttrArg2}; +static const iocshFuncDef dbPutAttrFuncDef = + {"dbPutAttribute",3,dbPutAttrArgs}; +static void dbPutAttrCallFunc(const iocshArgBuf *args) +{ dbPutAttribute(args[0].sval,args[1].sval,args[2].sval);} + /* tpn */ static const iocshArg tpnArg0 = { "record name",iocshArgString}; static const iocshArg tpnArg1 = { "value",iocshArgString}; @@ -321,6 +332,7 @@ void epicsShareAPI dbIocRegister(void) iocshRegister(&pftFuncDef,pftCallFunc); iocshRegister(&dbtpnFuncDef,dbtpnCallFunc); iocshRegister(&dbNotifyDumpFuncDef,dbNotifyDumpCallFunc); + iocshRegister(&dbPutAttrFuncDef,dbPutAttrCallFunc); iocshRegister(&tpnFuncDef,tpnCallFunc); iocshRegister(&dblsrFuncDef,dblsrCallFunc); iocshRegister(&dbLockShowLockedFuncDef,dbLockShowLockedCallFunc); From ca46bf70b7f6c6bf35e3babd6c94589628042a2d Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Tue, 23 Jun 2015 17:06:54 -0500 Subject: [PATCH 5/6] Fixes to attribute handling in dbStaticLib From Peter Leban of i-tech (Libera) --- src/dbStatic/dbStaticLib.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/dbStatic/dbStaticLib.c b/src/dbStatic/dbStaticLib.c index 08ec137e1..a3648f3bf 100644 --- a/src/dbStatic/dbStaticLib.c +++ b/src/dbStatic/dbStaticLib.c @@ -1347,7 +1347,7 @@ long epicsShareAPI dbPutRecordAttribute( pnew = dbCalloc(1,sizeof(dbRecordAttribute)); if(pattribute) { - ellInsert(&precordType->attributeList,&pattribute->node, + ellInsert(&precordType->attributeList,pattribute->node.previous, &pnew->node); } else { ellAdd(&precordType->attributeList,&pnew->node); @@ -1381,11 +1381,16 @@ long epicsShareAPI dbGetAttributePart(DBENTRY *pdbentry, const char **ppname) int nameLen = strlen(pattribute->name); int compare = strncmp(pattribute->name, pname, nameLen); int ch = pname[nameLen]; - if (compare == 0 && !(ch == '_' || isalnum(ch))) { - pdbentry->pflddes = pattribute->pdbFldDes; - pdbentry->pfield = pattribute->value; - *ppname = &pname[nameLen]; - return 0; + if (compare == 0) { + if (!(ch == '_' || isalnum(ch))) { + pdbentry->pflddes = pattribute->pdbFldDes; + pdbentry->pfield = pattribute->value; + *ppname = &pname[nameLen]; + return 0; + } + if (strlen(pname) > nameLen) { + compare = -1; + } } if (compare >= 0) break; pattribute = (dbRecordAttribute *)ellNext(&pattribute->node); From 444b89f557b6d96562423caf7e1d51a4b93b422f Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Tue, 30 Jun 2015 14:08:32 -0500 Subject: [PATCH 6/6] libCom: Make readline support clean up on epicsExit() --- documentation/RELEASE_NOTES.html | 19 ++++++++++++++++--- src/libCom/osi/os/default/epicsReadline.c | 16 ++++++++++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html index 0b93f21af..af7c8bffe 100644 --- a/documentation/RELEASE_NOTES.html +++ b/documentation/RELEASE_NOTES.html @@ -3,16 +3,29 @@ - EPICS Base R3.14.12.5 Release Notes + EPICS Base R3.14.12.6 Release Notes +

    EPICS Base Release 3.14.12.6

    + +

    Changes between 3.14.12.5 and 3.14.12.6

    + + + +

    Clean up after GNU readline()

    + +

    If EPICS Base is built with readline support, any IOC that calls epicsExit() +from a thread other than the main thread is likely to leave the user's terminal +in a weird state, requiring the user to run something like 'stty sane' to clean +it up. This release patches the readline support code to clean up automatically +by registering an epicsAtExit() routine.

    + +

    EPICS Base Release 3.14.12.5

    Changes between 3.14.12.4 and 3.14.12.5

    - -

    aoRecord raw conversion overflows

    The ao record type now checks converted raw values and limits them to the diff --git a/src/libCom/osi/os/default/epicsReadline.c b/src/libCom/osi/os/default/epicsReadline.c index 6c442e376..1d7d9c1d5 100644 --- a/src/libCom/osi/os/default/epicsReadline.c +++ b/src/libCom/osi/os/default/epicsReadline.c @@ -14,6 +14,7 @@ #define epicsExportSharedSymbols #include "envDefs.h" +#include "epicsExit.h" #include "epicsReadline.h" #define EPICS_COMMANDLINE_LIBRARY_EPICS 0 @@ -84,6 +85,14 @@ struct readlineContext { char *line; }; +static enum {rlNone, rlIdle, rlBusy} rlState = rlNone; + +static void rlExit(void *dummy) { + if (rlState == rlBusy) + rl_cleanup_after_signal(); +} + + /* * Create a command-line context */ @@ -92,6 +101,11 @@ epicsReadlineBegin(FILE *in) { struct readlineContext *readlineContext; + if (rlState == rlNone) { + epicsAtExit(rlExit, NULL); + rlState = rlIdle; + } + readlineContext = malloc(sizeof *readlineContext); if (readlineContext != NULL) { readlineContext->in = in; @@ -124,7 +138,9 @@ epicsReadline (const char *prompt, void *context) free (readlineContext->line); readlineContext->line = NULL; if (readlineContext->in == NULL) { + rlState = rlBusy; line = readline (prompt); + rlState = rlIdle; } else { line = (char *)malloc (linesize * sizeof *line);