Merged changes from 3.14 branch to revno 12590
This commit is contained in:
@@ -14,6 +14,14 @@
|
||||
<h2 align="center">Changes between 3.15.2 and 3.15.3</h2>
|
||||
<!-- Insert new items immediately below here ... -->
|
||||
|
||||
<h3>Clean up after GNU readline()</h3>
|
||||
|
||||
<p>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.</p>
|
||||
|
||||
<h3>Removed the last vestiges of RSET::get_value()</h3>
|
||||
|
||||
<p>The IOC has not called the get_value() routine in the RSET for a very long
|
||||
|
||||
@@ -209,6 +209,7 @@ $Date$</span></small></p>
|
||||
<li><a href="#ca_pend_event">ca_poll</a></li>
|
||||
<li><a href="#ca_puser">ca_puser</a></li>
|
||||
<li><a href="#ca_put">ca_put</a></li>
|
||||
<li><a href="#ca_put">ca_put_callback</a></li>
|
||||
<li><a href="#ca_set_puser">ca_set_puser</a></li>
|
||||
<li><a href="#ca_signal">ca_signal</a></li>
|
||||
<li><a href="#ca_sg_block">ca_sg_block</a></li>
|
||||
@@ -223,7 +224,7 @@ $Date$</span></small></p>
|
||||
<li><a href="#ca_test_io">ca_test_io</a></li>
|
||||
<li><a href="#ca_write_access">ca_write_access</a></li>
|
||||
<li><a href="#ca_state">channel_state</a></li>
|
||||
<li><a href="#dbr_size[]">dbr_size[]</a></li>
|
||||
<li><a href="#dbr_size">dbr_size[]</a></li>
|
||||
<li><a href="#dbr_size_n">dbr_size_n</a></li>
|
||||
<li><a href="#dbr_value_size">dbr_value_size[]</a></li>
|
||||
<li><a href="#dbr_type_t">dbr_type_to_text</a></li>
|
||||
@@ -3831,7 +3832,7 @@ specified channel and boolean false otherwise.</p>
|
||||
channel and boolean false otherwise</dd>
|
||||
</dl>
|
||||
|
||||
<h3><code><a name="dbr_size[]">dbr_size[]</a></code></h3>
|
||||
<h3><code><a name="dbr_size">dbr_size[]</a></code></h3>
|
||||
<pre>#include <db_access.h>
|
||||
extern unsigned dbr_size[/* TYPE */];</pre>
|
||||
|
||||
@@ -3953,11 +3954,12 @@ int ca_sg_create ( CA_SYNC_GID *PGID );</pre>
|
||||
|
||||
<p>A synchronous group can be used to guarantee that a set of channel access
|
||||
requests have completed. Once a synchronous group has been created then channel
|
||||
access get and put requests may be issued within it using <code>ca_sg_get()</code> and
|
||||
<code>ca_sg_put()</code> respectively. The routines <code>ca_sg_block()</code> and <code>ca_sg_test()</code> can be
|
||||
access get and put requests may be issued within it using
|
||||
<code>ca_sg_array_get()</code> and <code>ca_sg_array_put()</code> respectively.
|
||||
The routines <code>ca_sg_block()</code> and <code>ca_sg_test()</code> can be
|
||||
used to block for and test for completion respectively. The routine
|
||||
<code>ca_sg_reset()</code> is used to discard knowledge of old requests which have timed out
|
||||
and in all likelihood will never be satisfied.</p>
|
||||
<code>ca_sg_reset()</code> is used to discard knowledge of old requests which
|
||||
have timed out and in all likelihood will never be satisfied.</p>
|
||||
|
||||
<p>Any number of asynchronous groups can have application requested operations
|
||||
outstanding within them at any given time.</p>
|
||||
@@ -4131,16 +4133,20 @@ status = ca_sg_reset(gid);</pre>
|
||||
|
||||
<h3><code><a name="ca_sg_put">ca_sg_array_put()</a></code></h3>
|
||||
<pre>#include <cadef.h>
|
||||
int ca_sg_put ( CA_SYNC_GID GID, chtype TYPE,
|
||||
chid CHID, void *PVALUE );
|
||||
int ca_sg_array_put ( CA_SYNC_GID GID, chtype TYPE,
|
||||
unsigned long COUNT, chid CHID, void *PVALUE );</pre>
|
||||
|
||||
<p>Write a value, or array of values, to a channel and increment the
|
||||
outstanding request count of a synchronous group. The <code>ca_sg_array_put()</code>
|
||||
functionality is implemented using <code>ca_array_put_callback()</code>.</p>
|
||||
<p>Write a value, or array of values, to a channel and increment the outstanding
|
||||
request count of a synchronous group. The <code>ca_sg_put()</code> and
|
||||
<code>ca_sg_array_put()</code> functionality is implemented using
|
||||
<code>ca_array_put_callback()</code>.</p>
|
||||
|
||||
<p>All remote operation requests such as the above are accumulated (buffered)
|
||||
and not forwarded to the server until one of <code>ca_flush_io()</code>, <code>ca_pend_io()</code>,
|
||||
<code>ca_pend_event()</code>, or <code>ca_sg_block()</code> are called. This allows several requests to be
|
||||
and not forwarded to the server until one of <code>ca_flush_io()</code>,
|
||||
<code>ca_pend_io()</code>, <code>ca_pend_event()</code>, or
|
||||
<code>ca_sg_block()</code> are called. This allows several requests to be
|
||||
efficiently sent in one message.</p>
|
||||
|
||||
<p>If a connection is lost and then resumed outstanding puts are not
|
||||
@@ -4193,6 +4199,8 @@ reissued.</p>
|
||||
|
||||
<h3><code><a name="ca_sg_get">ca_sg_array_get()</a></code></h3>
|
||||
<pre>#include <cadef.h>
|
||||
int ca_sg_get ( CA_SYNC_GID GID, chtype TYPE,
|
||||
chid CHID, void *PVALUE );
|
||||
int ca_sg_array_get ( CA_SYNC_GID GID,
|
||||
chtype TYPE, unsigned long COUNT,
|
||||
chid CHID, void *PVALUE );</pre>
|
||||
@@ -4200,16 +4208,19 @@ int ca_sg_array_get ( CA_SYNC_GID GID,
|
||||
<h4>Description</h4>
|
||||
|
||||
<p>Read a value from a channel and increment the outstanding request count of a
|
||||
synchronous group. The <code>ca_sg_array_get()</code> functionality is implemented using
|
||||
synchronous group. The <code>ca_sg_get()</code> and
|
||||
<code>ca_sg_array_get()</code> functionality is implemented using
|
||||
<code>ca_array_get_callback()</code>.</p>
|
||||
|
||||
<p>The values written into your program's variables by <code>ca_sg_get()</code> should not be
|
||||
referenced by your program until ECA_NORMAL has been received from <code>ca_sg_block()</code>,
|
||||
or until <code>ca_sg_test()</code> returns ECA_IODONE.</p>
|
||||
<p>The values written into your program's variables by <code>ca_sg_get()</code>
|
||||
or <code>ca_sg_array_get()</code> should not be referenced by your program until
|
||||
ECA_NORMAL has been received from <code>ca_sg_block()</code>, or until
|
||||
<code>ca_sg_test()</code> returns ECA_IODONE.</p>
|
||||
|
||||
<p>All remote operation requests such as the above are accumulated (buffered)
|
||||
and not forwarded to the server until one of <code>ca_flush_io()</code>, <code>ca_pend_io()</code>,
|
||||
<code>ca_pend_event()</code>, or <code>ca_sg_block()</code> are called. This allows several requests to be
|
||||
and not forwarded to the server until one of <code>ca_flush_io()</code>,
|
||||
<code>ca_pend_io()</code>, <code>ca_pend_event()</code>, or
|
||||
<code>ca_sg_block()</code> are called. This allows several requests to be
|
||||
efficiently sent in one message.</p>
|
||||
|
||||
<p>If a connection is lost and then resumed outstanding gets are not
|
||||
|
||||
@@ -233,6 +233,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};
|
||||
@@ -405,6 +416,7 @@ void dbIocRegister(void)
|
||||
iocshRegister(&pftFuncDef,pftCallFunc);
|
||||
iocshRegister(&dbtpnFuncDef,dbtpnCallFunc);
|
||||
iocshRegister(&dbNotifyDumpFuncDef,dbNotifyDumpCallFunc);
|
||||
iocshRegister(&dbPutAttrFuncDef,dbPutAttrCallFunc);
|
||||
iocshRegister(&tpnFuncDef,tpnCallFunc);
|
||||
iocshRegister(&dblsrFuncDef,dblsrCallFunc);
|
||||
iocshRegister(&dbLockShowLockedFuncDef,dbLockShowLockedCallFunc);
|
||||
|
||||
@@ -132,7 +132,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];
|
||||
|
||||
@@ -309,11 +309,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:
|
||||
|
||||
@@ -1198,7 +1198,7 @@ long 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);
|
||||
@@ -1232,11 +1232,16 @@ long dbGetAttributePart(DBENTRY *pdbentry, const char **ppname)
|
||||
size_t 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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user