Merge branch 'aliases' into PSI-7.0
This commit is contained in:
@@ -145,63 +145,66 @@ long dbPutSpecial(DBADDR *paddr,int pass)
|
||||
}
|
||||
|
||||
static void get_enum_strs(DBADDR *paddr, char **ppbuffer,
|
||||
rset *prset,long *options)
|
||||
rset *prset, long *options)
|
||||
{
|
||||
short field_type=paddr->field_type;
|
||||
dbFldDes *pdbFldDes = paddr->pfldDes;
|
||||
dbMenu *pdbMenu;
|
||||
dbDeviceMenu *pdbDeviceMenu;
|
||||
char **papChoice;
|
||||
unsigned long no_str;
|
||||
char *ptemp;
|
||||
struct dbr_enumStrs *pdbr_enumStrs=(struct dbr_enumStrs*)(*ppbuffer);
|
||||
unsigned int i;
|
||||
struct dbr_enumStrs *penum=(struct dbr_enumStrs*)(*ppbuffer);
|
||||
/* advance output buffer on success or failure for next option */
|
||||
*ppbuffer = dbr_enumStrs_size + (char*)penum;
|
||||
|
||||
memset(pdbr_enumStrs,'\0',dbr_enumStrs_size);
|
||||
switch(field_type) {
|
||||
case DBF_ENUM:
|
||||
if( prset && prset->get_enum_strs ) {
|
||||
(*prset->get_enum_strs)(paddr,pdbr_enumStrs);
|
||||
} else {
|
||||
*options = (*options)^DBR_ENUM_STRS;/*Turn off option*/
|
||||
}
|
||||
break;
|
||||
case DBF_MENU:
|
||||
pdbMenu = (dbMenu *)pdbFldDes->ftPvt;
|
||||
no_str = pdbMenu->nChoice;
|
||||
papChoice= pdbMenu->papChoiceValue;
|
||||
goto choice_common;
|
||||
case DBF_DEVICE:
|
||||
pdbDeviceMenu = (dbDeviceMenu *)pdbFldDes->ftPvt;
|
||||
if(!pdbDeviceMenu) {
|
||||
*options = (*options)^DBR_ENUM_STRS;/*Turn off option*/
|
||||
break;
|
||||
}
|
||||
no_str = pdbDeviceMenu->nChoice;
|
||||
papChoice = pdbDeviceMenu->papChoice;
|
||||
goto choice_common;
|
||||
choice_common:
|
||||
i = sizeof(pdbr_enumStrs->strs)/
|
||||
sizeof(pdbr_enumStrs->strs[0]);
|
||||
if(i<no_str) no_str = i;
|
||||
pdbr_enumStrs->no_str = no_str;
|
||||
ptemp = &(pdbr_enumStrs->strs[0][0]);
|
||||
for (i=0; i<no_str; i++) {
|
||||
if(papChoice[i]==NULL) *ptemp=0;
|
||||
else {
|
||||
strncpy(ptemp,papChoice[i],
|
||||
sizeof(pdbr_enumStrs->strs[0]));
|
||||
*(ptemp+sizeof(pdbr_enumStrs->strs[0])-1) = 0;
|
||||
}
|
||||
ptemp += sizeof(pdbr_enumStrs->strs[0]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
*options = (*options)^DBR_ENUM_STRS;/*Turn off option*/
|
||||
break;
|
||||
memset(penum, 0, dbr_enumStrs_size);
|
||||
|
||||
/* from this point
|
||||
* on success, return early
|
||||
* on failure, jump or fall through to clear *options bit.
|
||||
*/
|
||||
|
||||
if(paddr->field_type == DBF_ENUM) {
|
||||
if( prset && prset->get_enum_strs ) {
|
||||
(*prset->get_enum_strs)(paddr,penum);
|
||||
return;
|
||||
}
|
||||
|
||||
} else if(paddr->field_type == DBF_MENU || paddr->field_type == DBF_DEVICE) {
|
||||
char **ppchoices;
|
||||
epicsUInt32 i, nchoices = 0;
|
||||
|
||||
if(paddr->field_type == DBF_MENU) {
|
||||
dbMenu *pmenu = paddr->pfldDes->ftPvt;
|
||||
nchoices = pmenu->nChoice;
|
||||
ppchoices= pmenu->papChoiceValue;
|
||||
|
||||
} else if(paddr->field_type == DBF_DEVICE) {
|
||||
dbDeviceMenu *pdevs = paddr->pfldDes->ftPvt;
|
||||
if(!pdevs)
|
||||
goto nostrs;
|
||||
|
||||
nchoices = pdevs->nChoice;
|
||||
ppchoices = pdevs->papChoice;
|
||||
}
|
||||
|
||||
if(nchoices > NELEMENTS(penum->strs))
|
||||
nchoices = NELEMENTS(penum->strs); /* availible > capacity, truncated list */
|
||||
|
||||
penum->no_str = nchoices;
|
||||
|
||||
for(i=0; i<nchoices; i++) {
|
||||
if(ppchoices[i]) {
|
||||
strncpy(penum->strs[i], ppchoices[i],
|
||||
sizeof(penum->strs[i]));
|
||||
/* strs[i][] allowed to omit trailing nil */
|
||||
} else {
|
||||
penum->strs[i][0] = '\0';
|
||||
}
|
||||
}
|
||||
*ppbuffer = ((char *)*ppbuffer) + dbr_enumStrs_size;
|
||||
return;
|
||||
|
||||
} else {
|
||||
/* other DBF_* fall through to error */
|
||||
}
|
||||
|
||||
nostrs:
|
||||
/* indicate option data not available. distinct from no_str==0 */
|
||||
*options = (*options)^DBR_ENUM_STRS;
|
||||
}
|
||||
|
||||
static void get_graphics(DBADDR *paddr, char **ppbuffer,
|
||||
|
||||
@@ -165,7 +165,7 @@ unsigned long dbChannelIO::nativeElementCount (
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
long elements = dbChannelElements ( this->dbch );
|
||||
if ( elements >= 0u ) {
|
||||
if ( elements >= 0 ) {
|
||||
return static_cast < unsigned long > ( elements );
|
||||
}
|
||||
return 0u;
|
||||
|
||||
@@ -15,13 +15,21 @@ typedef struct dbCommonPvt {
|
||||
/* Thread which is currently processing this record */
|
||||
struct epicsThreadOSD* procThread;
|
||||
|
||||
struct dbCommon common;
|
||||
/* actually followed by:
|
||||
* struct dbCommon common;
|
||||
*/
|
||||
} dbCommonPvt;
|
||||
|
||||
static EPICS_ALWAYS_INLINE
|
||||
dbCommonPvt* dbRec2Pvt(struct dbCommon *prec)
|
||||
{
|
||||
return CONTAINER(prec, dbCommonPvt, common);
|
||||
return (dbCommonPvt*)((char*)prec - sizeof(dbCommonPvt));
|
||||
}
|
||||
|
||||
static EPICS_ALWAYS_INLINE
|
||||
dbCommon* dbPvt2Rec(struct dbCommonPvt *pvt)
|
||||
{
|
||||
return (dbCommon*)&pvt[1];
|
||||
}
|
||||
|
||||
#endif // DBCOMMONPVT_H
|
||||
|
||||
@@ -94,7 +94,7 @@ static long cvt_st_UInt32(const char *from, void *pfield, const dbAddr *paddr)
|
||||
status = epicsParseFloat64(from, &dval, &end);
|
||||
if (!status &&
|
||||
dval >=0 &&
|
||||
dval <= ULONG_MAX)
|
||||
dval <= UINT_MAX)
|
||||
*to = dval;
|
||||
}
|
||||
return status;
|
||||
|
||||
@@ -302,7 +302,7 @@ static long getStringUlong(const dbAddr *paddr,
|
||||
epicsFloat64 dval;
|
||||
|
||||
status = epicsParseFloat64(psrc, &dval, &end);
|
||||
if (!status && 0 <= dval && dval <= ULONG_MAX)
|
||||
if (!status && 0 <= dval && dval <= UINT_MAX)
|
||||
*pdst = dval;
|
||||
}
|
||||
if (status)
|
||||
@@ -1052,7 +1052,7 @@ static long putStringUlong(dbAddr *paddr,
|
||||
epicsFloat64 dval;
|
||||
|
||||
status = epicsParseFloat64(psrc, &dval, &end);
|
||||
if (!status && 0 <= dval && dval <= ULONG_MAX)
|
||||
if (!status && 0 <= dval && dval <= UINT_MAX)
|
||||
*pdst = dval;
|
||||
}
|
||||
if (status)
|
||||
|
||||
@@ -181,7 +181,7 @@ static long cvt_st_ul(const void *f, void *t, const dbAddr *paddr)
|
||||
status = epicsParseFloat64(from, &dval, &end);
|
||||
if (!status &&
|
||||
dval >=0 &&
|
||||
dval <= ULONG_MAX)
|
||||
dval <= UINT_MAX)
|
||||
*to = dval;
|
||||
}
|
||||
return status;
|
||||
|
||||
@@ -1119,6 +1119,20 @@ static void dbRecordHead(char *recordType, char *name, int visible)
|
||||
return;
|
||||
}
|
||||
|
||||
if (recordType[0] == '#' && recordType[1] == 0) {
|
||||
status = dbFindRecord(pdbentry, name);
|
||||
if (status == 0) {
|
||||
dbDeleteRecord(pdbentry);
|
||||
} else {
|
||||
fprintf(stderr, ERL_WARNING ": Unable to delete record \"%s\". Not found.\n"
|
||||
" at file %s line %d\n",
|
||||
name, pinputFileNow->filename, pinputFileNow->line_num);
|
||||
}
|
||||
popFirstTemp();
|
||||
dbFreeEntry(pdbentry);
|
||||
duplicate = TRUE;
|
||||
return;
|
||||
}
|
||||
status = dbFindRecordType(pdbentry, recordType);
|
||||
if (status) {
|
||||
fprintf(stderr, "Record \"%s\" is of unknown type \"%s\"\n",
|
||||
@@ -1249,24 +1263,50 @@ static void dbRecordInfo(char *name, char *value)
|
||||
}
|
||||
}
|
||||
|
||||
static long createAlias(DBENTRY *pdbentry, const char *alias)
|
||||
{
|
||||
DBENTRY tempEntry;
|
||||
long status;
|
||||
dbRecordNode *precnode = pdbentry->precnode;
|
||||
|
||||
if (precnode->aliasedRecnode) precnode = precnode->aliasedRecnode;
|
||||
dbInitEntry(pdbentry->pdbbase, &tempEntry);
|
||||
status = dbFindRecord(&tempEntry, alias);
|
||||
if (status == 0) {
|
||||
if (tempEntry.precnode->aliasedRecnode != precnode) {
|
||||
if (tempEntry.precnode->aliasedRecnode)
|
||||
fprintf(stderr, ERL_ERROR ": Alias \"%s\" for \"%s\": name already used by an alias for \"%s\"\n",
|
||||
alias, dbGetRecordName(pdbentry),
|
||||
tempEntry.precnode->aliasedRecnode->recordname);
|
||||
else
|
||||
fprintf(stderr, ERL_ERROR ": Alias \"%s\" for \"%s\": name already used by a record\n",
|
||||
alias, dbGetRecordName(pdbentry));
|
||||
status = S_dbLib_recExists;
|
||||
} else if (dbRecordsOnceOnly) {
|
||||
fprintf(stderr, ERL_ERROR ": Alias \"%s\" already defined and dbRecordsOnceOnly set.\n",
|
||||
alias);
|
||||
status = S_dbLib_recExists;
|
||||
}
|
||||
} else {
|
||||
status = dbCreateAlias(pdbentry, alias);
|
||||
}
|
||||
dbFinishEntry(&tempEntry);
|
||||
return status;
|
||||
}
|
||||
|
||||
static void dbRecordAlias(char *name)
|
||||
{
|
||||
DBENTRY *pdbentry;
|
||||
tempListNode *ptempListNode;
|
||||
long status;
|
||||
|
||||
if(dbRecordNameValidate(name))
|
||||
return;
|
||||
|
||||
if (duplicate) return;
|
||||
ptempListNode = (tempListNode *)ellFirst(&tempList);
|
||||
pdbentry = ptempListNode->item;
|
||||
status = dbCreateAlias(pdbentry, name);
|
||||
if (status) {
|
||||
fprintf(stderr, "Can't create alias \"%s\" for \"%s\"\n",
|
||||
name, dbGetRecordName(pdbentry));
|
||||
|
||||
if (createAlias(pdbentry, name) != 0) {
|
||||
yyerror(NULL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1284,9 +1324,7 @@ static void dbAlias(char *name, char *alias)
|
||||
alias, name);
|
||||
yyerror(NULL);
|
||||
}
|
||||
else if (dbCreateAlias(pdbEntry, alias)) {
|
||||
fprintf(stderr, "Can't create alias \"%s\" referring to \"%s\"\n",
|
||||
alias, name);
|
||||
else if (createAlias(pdbEntry, alias) != 0) {
|
||||
yyerror(NULL);
|
||||
}
|
||||
dbFinishEntry(pdbEntry);
|
||||
|
||||
@@ -1219,7 +1219,9 @@ long dbNextRecordType(DBENTRY *pdbentry)
|
||||
|
||||
char * dbGetRecordTypeName(DBENTRY *pdbentry)
|
||||
{
|
||||
return(pdbentry->precordType->name);
|
||||
dbRecordType *pdbRecordType = pdbentry->precordType;
|
||||
if(!pdbRecordType) return NULL;
|
||||
return(pdbRecordType->name);
|
||||
}
|
||||
|
||||
int dbGetNRecordTypes(DBENTRY *pdbentry)
|
||||
@@ -1477,6 +1479,17 @@ long dbDeleteAliases(DBENTRY *pdbentry)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dbDeleteRecordLinks(dbRecordType *rtyp, struct dbCommon *prec)
|
||||
{
|
||||
short i;
|
||||
|
||||
for (i=0; i<rtyp->no_links; i++) {
|
||||
dbFldDes *pflddes = rtyp->papFldDes[rtyp->link_ind[i]];
|
||||
DBLINK *plink = (DBLINK *)(((char *)prec) + pflddes->offset);
|
||||
dbFreeLinkContents(plink);
|
||||
}
|
||||
}
|
||||
|
||||
long dbDeleteRecord(DBENTRY *pdbentry)
|
||||
{
|
||||
dbBase *pdbbase = pdbentry->pdbbase;
|
||||
@@ -1492,6 +1505,7 @@ long dbDeleteRecord(DBENTRY *pdbentry)
|
||||
preclist = &precordType->recList;
|
||||
ellDelete(preclist, &precnode->node);
|
||||
dbPvdDelete(pdbbase, precnode);
|
||||
dbDeleteRecordLinks(precordType, precnode->precord);
|
||||
while (!dbFirstInfo(pdbentry)) {
|
||||
dbDeleteInfo(pdbentry);
|
||||
}
|
||||
|
||||
@@ -66,7 +66,17 @@ void devExtend(dsxt *pdsxt)
|
||||
pthisDevSup->pdsxt = pdsxt;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Ensure that: sizeof(dbCommonPvt) + pdbRecordType->rec_size
|
||||
* accounts for necessary alignment of record type struct
|
||||
*/
|
||||
typedef struct {
|
||||
dbCommonPvt prefix;
|
||||
/* ensure no padding needed... */
|
||||
dbCommon suffix;
|
||||
} dbCommonPvtAlignmentTest;
|
||||
STATIC_ASSERT(offsetof(dbCommonPvtAlignmentTest, suffix)==sizeof(dbCommonPvt));
|
||||
|
||||
long dbAllocRecord(DBENTRY *pdbentry,const char *precordName)
|
||||
{
|
||||
dbRecordType *pdbRecordType = pdbentry->precordType;
|
||||
@@ -90,8 +100,8 @@ long dbAllocRecord(DBENTRY *pdbentry,const char *precordName)
|
||||
precordName, pdbRecordType->name, pdbRecordType->rec_size);
|
||||
return(S_dbLib_noRecSup);
|
||||
}
|
||||
ppvt = dbCalloc(1, offsetof(dbCommonPvt, common) + pdbRecordType->rec_size);
|
||||
precord = &ppvt->common;
|
||||
ppvt = dbCalloc(1, sizeof(dbCommonPvt) + pdbRecordType->rec_size);
|
||||
precord = dbPvt2Rec(ppvt);
|
||||
ppvt->recnode = precnode;
|
||||
precord->rdes = pdbRecordType;
|
||||
precnode->precord = precord;
|
||||
|
||||
@@ -378,6 +378,7 @@ static int yyerror(char *str)
|
||||
dbIncludePrint();
|
||||
yyFailed = TRUE;
|
||||
}
|
||||
fprintf(stderr, "\n %d | %s\n", pinputFileNow->line_num, my_buffer);
|
||||
return(0);
|
||||
}
|
||||
static long pvt_yy_parse(void)
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <set>
|
||||
#include <map>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user