3843 lines
107 KiB
C
3843 lines
107 KiB
C
/*dbStaticLib.c*/
|
||
/* share/src/db @(#)dbStaticLib.c 1.21 7/11/94 */
|
||
/*****************************************************************
|
||
COPYRIGHT NOTIFICATION
|
||
*****************************************************************
|
||
|
||
(C) COPYRIGHT 1993 UNIVERSITY OF CHICAGO
|
||
|
||
This software was developed under a United States Government license
|
||
described on the COPYRIGHT_UniversityOfChicago file included as part
|
||
of this distribution.
|
||
**********************************************************************/
|
||
|
||
/*
|
||
* Modification Log:
|
||
* -----------------
|
||
* .01 02-03-93 mrk Consolidated all databse defs in one place
|
||
* .02 09-10-93 mrk dbIsDefault always returns FALSE for DEVCHOICE
|
||
* .03 02-23-94 mrk dbPutString to DEV_CHOICE. Ok if no INP or OUT
|
||
*/
|
||
|
||
#include <stdlib.h>
|
||
#include <stdio.h>
|
||
#include <limits.h>
|
||
#include <string.h>
|
||
#include <math.h>
|
||
#include <ctype.h>
|
||
|
||
#include "cantProceed.h"
|
||
#define DBFLDTYPES_GBLSOURCE
|
||
#define GUIGROUPS_GBLSOURCE
|
||
#define SPECIAL_GBLSOURCE
|
||
#include "dbDefs.h"
|
||
#include "dbFldTypes.h"
|
||
#include "epicsPrint.h"
|
||
#include "errlog.h"
|
||
#include "ellLib.h"
|
||
#include "cvtFast.h"
|
||
#include "gpHash.h"
|
||
#include "dbmf.h"
|
||
#include "postfix.h"
|
||
#include "sCalcPostfix.h"
|
||
#include "osiFileName.h"
|
||
|
||
#define epicsExportSharedSymbols
|
||
#include "link.h"
|
||
#include "devSup.h"
|
||
#include "drvSup.h"
|
||
#include "special.h"
|
||
#include "guigroup.h"
|
||
#include "dbStaticLib.h"
|
||
#include "dbStaticPvt.h"
|
||
|
||
|
||
int dbStaticDebug = 0;
|
||
#define messagesize 100
|
||
#define RPCL_LEN 184
|
||
#define MAX_FIELD_NAME_LENGTH 20
|
||
|
||
static char *ppstring[5]={"NPP","PP","CA","CP","CPP"};
|
||
static char *msstring[2]={"NMS","MS"};
|
||
|
||
epicsShareDef maplinkType pamaplinkType[LINK_NTYPES] = {
|
||
{"CONSTANT",CONSTANT},
|
||
{"PV_LINK",PV_LINK},
|
||
{"VME_IO",VME_IO},
|
||
{"CAMAC_IO",CAMAC_IO},
|
||
{"AB_IO",AB_IO},
|
||
{"GPIB_IO",GPIB_IO},
|
||
{"BITBUS_IO",BITBUS_IO},
|
||
{"MACRO_LINK",MACRO_LINK},
|
||
{"DB_LINK",DB_LINK},
|
||
{"CA_LINK",CA_LINK},
|
||
{"INST_IO",INST_IO},
|
||
{"BBGPIB_IO",BBGPIB_IO},
|
||
{"RF_IO",RF_IO},
|
||
{"VXI_IO",VXI_IO}
|
||
};
|
||
|
||
static int mapDBFtoDCT[DBF_NOACCESS+1] = {
|
||
DCT_STRING,
|
||
DCT_INTEGER,DCT_INTEGER,DCT_INTEGER,DCT_INTEGER,DCT_INTEGER,DCT_INTEGER,
|
||
DCT_REAL,DCT_REAL,
|
||
DCT_INTEGER,
|
||
DCT_MENU,
|
||
DCT_MENUFORM,
|
||
DCT_INLINK,DCT_OUTLINK,DCT_FWDLINK,
|
||
DCT_NOACCESS};
|
||
|
||
struct form {
|
||
DBLINK *plink;
|
||
int linkType;
|
||
int nlines;
|
||
char **prompt;
|
||
char **value;
|
||
char **verify;
|
||
};
|
||
|
||
static char *promptCONSTANT[] = {
|
||
"Constant:"};
|
||
static char *promptINLINK[] = {
|
||
" PV Name:",
|
||
"NPP PP CA CP CPP:",
|
||
" NMS or MS:"};
|
||
static char *promptOUTLINK[] = {
|
||
" PV Name:",
|
||
"NPP PP CA:",
|
||
"NMS or MS:"};
|
||
static char *promptFWDLINK[] = {
|
||
" PV Name:",
|
||
"<null> CA:"};
|
||
static char *promptVME_IO[] = {
|
||
" card:",
|
||
"signal:",
|
||
" parm:"};
|
||
static char *promptCAMAC_IO[] = {
|
||
" branch:",
|
||
" crate:",
|
||
" station:",
|
||
"subaddress:",
|
||
" function:",
|
||
" parameter:"};
|
||
static char *promptAB_IO[] = {
|
||
" link:",
|
||
" adapter:",
|
||
" card:",
|
||
" signal:",
|
||
" parm:"};
|
||
static char *promptGPIB_IO[] = {
|
||
"link:",
|
||
"addr:",
|
||
"parm:"};
|
||
static char *promptBITBUS_IO[] = {
|
||
" link:",
|
||
" node:",
|
||
" port:",
|
||
"signal:",
|
||
" parm:"};
|
||
static char *promptINST_IO[] = {
|
||
"parm:"};
|
||
static char *promptBBGPIB_IO[] = {
|
||
" link:",
|
||
" bbaddr:",
|
||
"gpibaddr:",
|
||
" parm:"};
|
||
static char *promptRF_IO[] = {
|
||
" cryo:",
|
||
" micro:",
|
||
" dataset:",
|
||
" element:"};
|
||
static char *promptVXI_IO[] = {
|
||
" Dynamic?",
|
||
"DYN frame:",
|
||
"DYN slot:",
|
||
"STATIC la:",
|
||
" Signal:",
|
||
" parm:"};
|
||
|
||
/*Each DBF link type is separate case*/
|
||
#define FORM_CONSTANT 0
|
||
#define FORM_INLINK 1
|
||
#define FORM_OUTLINK 2
|
||
#define FORM_FWDLINK 3
|
||
#define FORM_VME_IO 4
|
||
#define FORM_CAMAC_IO 5
|
||
#define FORM_AB_IO 6
|
||
#define FORM_GPIB_IO 7
|
||
#define FORM_BITBUS_IO 8
|
||
#define FORM_INST_IO 9
|
||
#define FORM_BBGPIB_IO 10
|
||
#define FORM_RF_IO 11
|
||
#define FORM_VXI_IO 12
|
||
#define FORM_NTYPES (FORM_VXI_IO + 1)
|
||
|
||
static char **promptAddr[FORM_NTYPES] = {
|
||
promptCONSTANT,
|
||
promptINLINK,
|
||
promptOUTLINK,
|
||
promptFWDLINK,
|
||
promptVME_IO,
|
||
promptCAMAC_IO,
|
||
promptAB_IO,
|
||
promptGPIB_IO,
|
||
promptBITBUS_IO,
|
||
promptINST_IO,
|
||
promptBBGPIB_IO,
|
||
promptRF_IO,
|
||
promptVXI_IO};
|
||
|
||
static int formlines[FORM_NTYPES] = {
|
||
sizeof(promptCONSTANT)/sizeof(char *),
|
||
sizeof(promptINLINK)/sizeof(char *),
|
||
sizeof(promptOUTLINK)/sizeof(char *),
|
||
sizeof(promptFWDLINK)/sizeof(char *),
|
||
sizeof(promptVME_IO)/sizeof(char *),
|
||
sizeof(promptCAMAC_IO)/sizeof(char *),
|
||
sizeof(promptAB_IO)/sizeof(char *),
|
||
sizeof(promptGPIB_IO)/sizeof(char *),
|
||
sizeof(promptBITBUS_IO)/sizeof(char *),
|
||
sizeof(promptINST_IO)/sizeof(char *),
|
||
sizeof(promptBBGPIB_IO)/sizeof(char *),
|
||
sizeof(promptRF_IO)/sizeof(char *),
|
||
sizeof(promptVXI_IO)/sizeof(char *)};
|
||
|
||
/*forward references for private routines*/
|
||
static long putParmString(char **pparm,const char *pstring);
|
||
static long mapLINKTtoFORMT(DBLINK *plink,dbFldDes *pflddes,int *ind);
|
||
static void entryErrMessage(DBENTRY *pdbentry,long status,char *mess);
|
||
static void zeroDbentry(DBENTRY *pdbentry);
|
||
static char *getpMessage(DBENTRY *pdbentry);
|
||
static long putPvLink(DBENTRY *pdbentry,short pvlMask,const char *pvname);
|
||
static long epicsShareAPI dbAddOnePath (DBBASE *pdbbase, const char *path, unsigned length);
|
||
|
||
/*Following are obsolete. Will go away next release*/
|
||
long epicsShareAPI dbRead(DBBASE *pdbbase,FILE *fp)
|
||
{
|
||
return(dbReadDatabaseFP(&pdbbase,fp,0,0));
|
||
}
|
||
long epicsShareAPI dbWrite(DBBASE *pdbbase,FILE *fpdctsdr,FILE *fp)
|
||
{
|
||
fprintf(stderr,"dbWrite obsolete. It does NOTHING\n");
|
||
return(-1);
|
||
}
|
||
long epicsShareAPI dbFindRecdes(DBENTRY *pdbentry,const char *recdesname)
|
||
{return dbFindRecordType(pdbentry,recdesname);}
|
||
long epicsShareAPI dbFirstRecdes(DBENTRY *pdbentry)
|
||
{return dbFirstRecordType(pdbentry);}
|
||
long epicsShareAPI dbNextRecdes(DBENTRY *pdbentry)
|
||
{return dbNextRecordType(pdbentry);}
|
||
char * epicsShareAPI dbGetRecdesName(DBENTRY *pdbentry)
|
||
{return dbGetRecordTypeName(pdbentry);}
|
||
int epicsShareAPI dbGetNRecdes(DBENTRY *pdbentry)
|
||
{return dbGetNRecordTypes(pdbentry);}
|
||
long epicsShareAPI dbFirstFielddes(DBENTRY *pdbentry,int dctonly)
|
||
{return dbFirstField(pdbentry,dctonly);}
|
||
long epicsShareAPI dbNextFielddes(DBENTRY *pdbentry,int dctonly)
|
||
{return dbNextField(pdbentry,dctonly);}
|
||
char ** epicsShareAPI dbGetChoices(DBENTRY *pdbentry)
|
||
{return dbGetMenuChoices(pdbentry);}
|
||
void epicsShareAPI dbDumpRecDes(DBBASE *pdbbase,const char *recordTypeName)
|
||
{dbDumpRecordType(pdbbase,recordTypeName);}
|
||
|
||
/* internal routines*/
|
||
static int fcloseNotSTD(FILE *stream)
|
||
{
|
||
if(stream!=stdin && stream!=stdout && stream!=stderr) {
|
||
return(fclose(stream));
|
||
}
|
||
return(0);
|
||
}
|
||
|
||
static char *pNullString = "";
|
||
long setLinkType(DBENTRY *pdbentry)
|
||
{
|
||
DBENTRY dbEntry;
|
||
dbFldDes *pflddes;
|
||
dbRecordType *precordType;
|
||
devSup *pdevSup;
|
||
DBLINK *plink;
|
||
long status=0;
|
||
int link_type,ind,type;
|
||
int isSoftLink;
|
||
|
||
dbCopyEntryContents(pdbentry,&dbEntry);
|
||
status = dbFindField(&dbEntry,"DTYP");
|
||
if(status) {
|
||
epicsPrintf("field DTYP does not exist for recordtype %s\n",
|
||
dbGetRecordTypeName(&dbEntry));
|
||
status = S_dbLib_fieldNotFound;
|
||
goto done;
|
||
}
|
||
precordType = dbEntry.precordType;
|
||
if(!precordType) {
|
||
status = S_dbLib_badField;
|
||
goto done;
|
||
}
|
||
if(ellCount(&precordType->devList)==0) goto done;
|
||
ind = dbGetMenuIndex(&dbEntry);
|
||
if(ind==-1) {
|
||
char *pstring;
|
||
|
||
pstring = dbGetString(&dbEntry);
|
||
if(strstr(pstring,"$(") || strstr(pstring,"${")) {
|
||
link_type = MACRO_LINK;
|
||
} else {
|
||
status = S_dbLib_badField;
|
||
goto done;
|
||
}
|
||
} else {
|
||
pdevSup = (devSup *)ellNth(&precordType->devList,ind+1);
|
||
if(!pdevSup) {
|
||
status = S_dbLib_badField;
|
||
goto done;
|
||
}
|
||
link_type = pdevSup->link_type;
|
||
}
|
||
pflddes = pdbentry->pflddes;
|
||
plink = (DBLINK *)(pdbentry->pfield);
|
||
if(plink->type == link_type) goto done;
|
||
type = plink->type;
|
||
if(type==CONSTANT || type==PV_LINK || type==DB_LINK || type==CA_LINK)
|
||
isSoftLink = TRUE;
|
||
else
|
||
isSoftLink = FALSE;
|
||
if(isSoftLink && (link_type==CONSTANT || link_type==PV_LINK)) goto done;
|
||
dbFreeLinkContents(plink);
|
||
plink->type = link_type;
|
||
switch(plink->type) {
|
||
case VME_IO: plink->value.vmeio.parm = pNullString; break;
|
||
case CAMAC_IO: plink->value.camacio.parm = pNullString; break;
|
||
case AB_IO: plink->value.abio.parm = pNullString; break;
|
||
case GPIB_IO: plink->value.gpibio.parm = pNullString; break;
|
||
case BITBUS_IO: plink->value.bitbusio.parm = pNullString; break;
|
||
case INST_IO: plink->value.instio.string = pNullString; break;
|
||
case BBGPIB_IO: plink->value.bbgpibio.parm = pNullString; break;
|
||
case VXI_IO: plink->value.vxiio.parm = pNullString; break;
|
||
}
|
||
done:
|
||
dbFinishEntry(&dbEntry);
|
||
return(status);
|
||
}
|
||
|
||
static long putParmString(char **pparm,const char *pstring)
|
||
{
|
||
size_t size;
|
||
|
||
if(*pparm && (*pparm != pNullString)){
|
||
free((void *)(*pparm));
|
||
*pparm = pNullString;
|
||
}
|
||
if(!pstring) return(0);
|
||
if(!(pstring = strchr(pstring,'@'))) return(0);
|
||
pstring++;
|
||
size = strlen(pstring) + 1;
|
||
if(size==1) return(0);
|
||
*pparm = dbCalloc(size, sizeof(char *));
|
||
strcpy(*pparm,pstring);
|
||
return(0);
|
||
}
|
||
|
||
void dbFreeLinkContents(struct link *plink)
|
||
{
|
||
char *parm = NULL;
|
||
|
||
switch(plink->type) {
|
||
case CONSTANT: free((void *)plink->value.constantStr); break;
|
||
case MACRO_LINK: free((void *)plink->value.macro_link.macroStr); break;
|
||
case PV_LINK: free((void *)plink->value.pv_link.pvname); break;
|
||
case VME_IO: parm = plink->value.vmeio.parm; break;
|
||
case CAMAC_IO: parm = plink->value.camacio.parm; break;
|
||
case AB_IO: parm = plink->value.abio.parm; break;
|
||
case GPIB_IO: parm = plink->value.gpibio.parm; break;
|
||
case BITBUS_IO: parm = plink->value.bitbusio.parm;break;
|
||
case INST_IO: parm = plink->value.instio.string; break;
|
||
case BBGPIB_IO: parm = plink->value.bbgpibio.parm;break;
|
||
case VXI_IO: parm = plink->value.vxiio.parm; break;
|
||
default:
|
||
epicsPrintf("dbFreeLink called but link type unknown\n");
|
||
}
|
||
if(parm && (parm != pNullString)) free((void *)parm);
|
||
memset((char *)plink,0,sizeof(struct link));
|
||
}
|
||
|
||
void dbFreePath(DBBASE *pdbbase)
|
||
{
|
||
ELLLIST *ppathList;
|
||
dbPathNode *pdbPathNode;
|
||
|
||
if(!pdbbase) return;
|
||
ppathList = (ELLLIST *)pdbbase->pathPvt;
|
||
if(!ppathList) return;
|
||
while((pdbPathNode = (dbPathNode *)ellFirst(ppathList))) {
|
||
ellDelete(ppathList,&pdbPathNode->node);
|
||
free((void *)pdbPathNode->directory);
|
||
free((void *)pdbPathNode);
|
||
}
|
||
free((void *)ppathList);
|
||
pdbbase->pathPvt = 0;
|
||
return;
|
||
}
|
||
|
||
|
||
static long mapLINKTtoFORMT(DBLINK *plink,dbFldDes *pflddes,int *ind)
|
||
{
|
||
switch(plink->type) {
|
||
case CONSTANT:
|
||
*ind = FORM_CONSTANT; return(0);
|
||
case PV_LINK:
|
||
switch(pflddes->field_type) {
|
||
case DBF_INLINK:
|
||
*ind = FORM_INLINK; return(0);
|
||
case DBF_OUTLINK:
|
||
*ind = FORM_OUTLINK; return(0);
|
||
case DBF_FWDLINK:
|
||
*ind = FORM_FWDLINK; return(0);
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
case VME_IO:
|
||
*ind = FORM_VME_IO; return(0);
|
||
case CAMAC_IO:
|
||
*ind = FORM_CAMAC_IO; return(0);
|
||
case AB_IO:
|
||
*ind = FORM_AB_IO; return(0);
|
||
case GPIB_IO:
|
||
*ind = FORM_GPIB_IO; return(0);
|
||
case BITBUS_IO:
|
||
*ind = FORM_BITBUS_IO; return(0);
|
||
case INST_IO:
|
||
*ind = FORM_INST_IO; return(0);
|
||
case BBGPIB_IO:
|
||
*ind = FORM_BBGPIB_IO; return(0);
|
||
case RF_IO:
|
||
*ind = FORM_RF_IO; return(0);
|
||
case VXI_IO:
|
||
*ind = FORM_VXI_IO; return(0);
|
||
default:
|
||
break;
|
||
}
|
||
return(S_dbLib_badLink);
|
||
}
|
||
|
||
static void entryErrMessage(DBENTRY *pdbentry,long status,char *mess)
|
||
{
|
||
char message[200];
|
||
char *pmessage=&message[0];
|
||
dbRecordNode *precnode = pdbentry->precnode;
|
||
dbFldDes *pflddes = pdbentry->pflddes;
|
||
char *pname = NULL;
|
||
|
||
*pmessage=0;
|
||
if(pdbentry->precordType) pname = pdbentry->precordType->name;
|
||
if(pname) {
|
||
strcat(pmessage,"RecordType:");
|
||
strcat(pmessage,pname);
|
||
}
|
||
if(precnode){
|
||
strcat(pmessage," Record:");
|
||
strcat(pmessage,(char *)precnode->precord);
|
||
}
|
||
if(pflddes) {
|
||
char *pstr=pflddes->name;
|
||
|
||
strcat(pmessage," Field:");
|
||
strcat(pmessage,pstr);
|
||
}
|
||
strcat(pmessage,"\n");
|
||
strcat(pmessage,mess);
|
||
errMessage(status,pmessage);
|
||
}
|
||
|
||
static void zeroDbentry(DBENTRY *pdbentry)
|
||
{
|
||
/*NOTE that pdbbase, message, and formpvt MUST NOT be set to NULL*/
|
||
pdbentry->precordType=NULL;
|
||
pdbentry->pflddes=NULL;
|
||
pdbentry->precnode=NULL;
|
||
pdbentry->pfield=NULL;
|
||
pdbentry->indfield=0;
|
||
}
|
||
|
||
static char *getpMessage(DBENTRY *pdbentry)
|
||
{
|
||
if(!pdbentry->message) pdbentry->message = dbCalloc(1,messagesize);
|
||
return(pdbentry->message);
|
||
}
|
||
|
||
static long putPvLink(DBENTRY *pdbentry,short pvlMask,const char *pvname)
|
||
{
|
||
dbFldDes *pflddes;
|
||
DBLINK *plink;
|
||
char *pname;
|
||
|
||
dbGetFieldAddress(pdbentry);
|
||
pflddes = pdbentry->pflddes;
|
||
if(!pflddes) return(-1);
|
||
plink = (DBLINK *)pdbentry->pfield;
|
||
if(!plink) return(-1);
|
||
switch (pflddes->field_type) {
|
||
case DBF_INLINK:
|
||
case DBF_OUTLINK:
|
||
case DBF_FWDLINK:
|
||
if(plink->type != PV_LINK) return(S_dbLib_badLink);
|
||
pname = plink->value.pv_link.pvname;
|
||
if(pname) free((void *)pname);
|
||
pname = dbCalloc(strlen(pvname)+1,sizeof(char));
|
||
plink->value.pv_link.pvname = pname;
|
||
strcpy(pname,pvname);
|
||
plink->value.pv_link.pvlMask = pvlMask;
|
||
return(0);
|
||
default:
|
||
errPrintf(-1,__FILE__, __LINE__,"Logic Error\n");
|
||
}
|
||
return(S_dbLib_badLink);
|
||
}
|
||
|
||
/*Public only for dbStaticNoRun*/
|
||
dbDeviceMenu *dbGetDeviceMenu(DBENTRY *pdbentry)
|
||
{
|
||
dbRecordType *precordType = pdbentry->precordType;
|
||
dbFldDes *pflddes = pdbentry->pflddes;
|
||
dbDeviceMenu *pdbDeviceMenu;
|
||
devSup *pdevSup;
|
||
int ind;
|
||
int nChoice;
|
||
|
||
if(!precordType) return(NULL);
|
||
if(!pflddes) return(NULL);
|
||
if(pflddes->field_type!=DBF_DEVICE) return(NULL);
|
||
if(pflddes->ftPvt){
|
||
pdbDeviceMenu = (dbDeviceMenu *)pflddes->ftPvt;
|
||
if(pdbDeviceMenu->nChoice == ellCount(&precordType->devList))
|
||
return(pdbDeviceMenu);
|
||
free((void *)pdbDeviceMenu->papChoice);
|
||
free((void *)pdbDeviceMenu);
|
||
pflddes->ftPvt = NULL;
|
||
}
|
||
nChoice = ellCount(&precordType->devList);
|
||
if(nChoice <= 0) return(NULL);
|
||
pdbDeviceMenu = dbCalloc(1,sizeof(dbDeviceMenu));
|
||
pdbDeviceMenu->nChoice = nChoice;
|
||
pdbDeviceMenu->papChoice = dbCalloc(pdbDeviceMenu->nChoice,sizeof(char *));
|
||
pdevSup = (devSup *)ellFirst(&precordType->devList);
|
||
ind = 0;
|
||
while(pdevSup) {
|
||
pdbDeviceMenu->papChoice[ind] = pdevSup->choice;
|
||
ind++;
|
||
pdevSup = (devSup *)ellNext(&pdevSup->node);
|
||
}
|
||
pflddes->ftPvt = pdbDeviceMenu;
|
||
return(pdbDeviceMenu);
|
||
}
|
||
|
||
/* Beginning of Public Routines */
|
||
void * epicsShareAPI dbCalloc(size_t nobj,size_t size)
|
||
{
|
||
void *p;
|
||
|
||
p=callocMustSucceed(nobj,size,"dbCalloc");
|
||
return(p);
|
||
}
|
||
void * epicsShareAPI dbMalloc(size_t size)
|
||
{
|
||
void *p;
|
||
|
||
p=mallocMustSucceed(size,"dbMalloc");
|
||
return(p);
|
||
}
|
||
|
||
#define INC_SIZE 256
|
||
void epicsShareAPI dbCatString(char **string,int *stringLength,char *new,char *separator)
|
||
{
|
||
if((*string==NULL)
|
||
|| ((strlen(*string)+strlen(new)+2) > (size_t)*stringLength)) {
|
||
char *newString;
|
||
size_t size;
|
||
|
||
size = strlen(new);
|
||
if(*string) size += strlen(*string);
|
||
/*Make size multiple of INC_SIZE*/
|
||
size = ((size + 2 + INC_SIZE)/INC_SIZE) * INC_SIZE;
|
||
newString = dbCalloc(size,sizeof(char));
|
||
if(*string) {
|
||
strcpy(newString,*string);
|
||
free((void *)(*string));
|
||
}
|
||
*string = newString;
|
||
}
|
||
if(*stringLength>0) {
|
||
strcat(*string,separator);
|
||
*stringLength += strlen(separator);
|
||
}
|
||
strcat(*string,new);
|
||
*stringLength += strlen(new);
|
||
}
|
||
|
||
dbBase * epicsShareAPI dbAllocBase(void)
|
||
{
|
||
dbBase *pdbbase;
|
||
|
||
pdbbase = dbCalloc(1,sizeof(dbBase));
|
||
ellInit(&pdbbase->menuList);
|
||
ellInit(&pdbbase->recordTypeList);
|
||
ellInit(&pdbbase->drvList);
|
||
ellInit(&pdbbase->bptList);
|
||
gphInitPvt(&pdbbase->pgpHash,256);
|
||
dbPvdInitPvt(pdbbase);
|
||
return (pdbbase);
|
||
}
|
||
void epicsShareAPI dbFreeBase(dbBase *pdbbase)
|
||
{
|
||
dbMenu *pdbMenu;
|
||
dbMenu *pdbMenuNext;
|
||
dbRecordType *pdbRecordType;
|
||
dbRecordType *pdbRecordTypeNext;
|
||
dbFldDes * pdbFldDes;
|
||
dbRecordNode *pdbRecordNode;
|
||
dbRecordNode *pdbRecordNodeNext;
|
||
dbRecordAttribute *pAttribute;
|
||
dbRecordAttribute *pAttributeNext;
|
||
devSup *pdevSup;
|
||
devSup *pdevSupNext;
|
||
drvSup *pdrvSup;
|
||
drvSup *pdrvSupNext;
|
||
brkTable *pbrkTable;
|
||
brkTable *pbrkTableNext;
|
||
int i;
|
||
DBENTRY dbentry;
|
||
|
||
|
||
dbInitEntry(pdbbase,&dbentry);
|
||
pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList);
|
||
while(pdbRecordType) {
|
||
pdbRecordNode = (dbRecordNode *)ellFirst(&pdbRecordType->recList);
|
||
while(pdbRecordNode) {
|
||
pdbRecordNodeNext = (dbRecordNode *)ellNext(&pdbRecordNode->node);
|
||
if(!dbFindRecord(&dbentry,pdbRecordNode->recordname))
|
||
dbDeleteRecord(&dbentry);
|
||
pdbRecordNode = pdbRecordNodeNext;
|
||
}
|
||
pdbRecordType = (dbRecordType *)ellNext(&pdbRecordType->node);
|
||
}
|
||
dbFinishEntry(&dbentry);
|
||
pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList);
|
||
while(pdbRecordType) {
|
||
for(i=0; i<pdbRecordType->no_fields; i++) {
|
||
pdbFldDes = pdbRecordType->papFldDes[i];
|
||
free((void *)pdbFldDes->prompt);
|
||
free((void *)pdbFldDes->name);
|
||
free((void *)pdbFldDes->extra);
|
||
free((void *)pdbFldDes->initial);
|
||
if(pdbFldDes->field_type==DBF_DEVICE && pdbFldDes->ftPvt) {
|
||
dbDeviceMenu *pdbDeviceMenu;
|
||
|
||
pdbDeviceMenu = (dbDeviceMenu *)pdbFldDes->ftPvt;
|
||
free((void *)pdbDeviceMenu->papChoice);
|
||
free((void *)pdbDeviceMenu);
|
||
pdbFldDes->ftPvt=0;
|
||
}
|
||
free((void *)pdbFldDes);
|
||
}
|
||
pdevSup = (devSup *)ellFirst(&pdbRecordType->devList);
|
||
while(pdevSup) {
|
||
pdevSupNext = (devSup *)ellNext(&pdevSup->node);
|
||
ellDelete(&pdbRecordType->devList,&pdevSup->node);
|
||
free((void *)pdevSup->name);
|
||
free((void *)pdevSup->choice);
|
||
free((void *)pdevSup);
|
||
pdevSup = pdevSupNext;
|
||
}
|
||
pAttribute =
|
||
(dbRecordAttribute *)ellFirst(&pdbRecordType->attributeList);
|
||
while(pAttribute) {
|
||
pAttributeNext = (dbRecordAttribute *)ellNext(&pAttribute->node);
|
||
ellDelete(&pdbRecordType->attributeList,&pAttribute->node);
|
||
free((void *)pAttribute->name);
|
||
free((void *)pAttribute->pdbFldDes);
|
||
pAttribute = pAttributeNext;
|
||
}
|
||
pdbRecordTypeNext = (dbRecordType *)ellNext(&pdbRecordType->node);
|
||
gphDelete(pdbbase->pgpHash,pdbRecordType->name,&pdbbase->recordTypeList);
|
||
ellDelete(&pdbbase->recordTypeList,&pdbRecordType->node);
|
||
free((void *)pdbRecordType->name);
|
||
free((void *)pdbRecordType->link_ind);
|
||
free((void *)pdbRecordType->papsortFldName);
|
||
free((void *)pdbRecordType->sortFldInd);
|
||
free((void *)pdbRecordType->papFldDes);
|
||
free((void *)pdbRecordType);
|
||
pdbRecordType = pdbRecordTypeNext;
|
||
}
|
||
pdbMenu = (dbMenu *)ellFirst(&pdbbase->menuList);
|
||
while(pdbMenu) {
|
||
pdbMenuNext = (dbMenu *)ellNext(&pdbMenu->node);
|
||
gphDelete(pdbbase->pgpHash,pdbMenu->name,&pdbbase->menuList);
|
||
ellDelete(&pdbbase->menuList,&pdbMenu->node);
|
||
for(i=0; i< pdbMenu->nChoice; i++) {
|
||
free((void *)pdbMenu->papChoiceName[i]);
|
||
free((void *)pdbMenu->papChoiceValue[i]);
|
||
}
|
||
free((void *)pdbMenu->papChoiceName);
|
||
free((void *)pdbMenu->papChoiceValue);
|
||
free((void *)pdbMenu ->name);
|
||
free((void *)pdbMenu);
|
||
pdbMenu = pdbMenuNext;
|
||
}
|
||
pdrvSup = (drvSup *)ellFirst(&pdbbase->drvList);
|
||
while(pdrvSup) {
|
||
pdrvSupNext = (drvSup *)ellNext(&pdrvSup->node);
|
||
ellDelete(&pdbbase->drvList,&pdrvSup->node);
|
||
free((void *)pdrvSup->name);
|
||
free((void *)pdrvSup);
|
||
pdrvSup = pdrvSupNext;
|
||
}
|
||
pbrkTable = (brkTable *)ellFirst(&pdbbase->bptList);
|
||
while(pbrkTable) {
|
||
pbrkTableNext = (brkTable *)ellNext(&pbrkTable->node);
|
||
gphDelete(pdbbase->pgpHash,pbrkTable->name,&pdbbase->bptList);
|
||
ellDelete(&pdbbase->bptList,&pbrkTable->node);
|
||
free(pbrkTable->name);
|
||
for(i=0; i<pbrkTable->number; i++)
|
||
free((void *)(pbrkTable->papBrkInt[i]));
|
||
free((void *)pbrkTable);
|
||
pbrkTable = pbrkTableNext;
|
||
}
|
||
gphFreeMem(pdbbase->pgpHash);
|
||
dbPvdFreeMem(pdbbase);
|
||
dbFreePath(pdbbase);
|
||
free((void *)pdbbase);
|
||
return;
|
||
}
|
||
|
||
DBENTRY * epicsShareAPI dbAllocEntry(dbBase *pdbbase)
|
||
{
|
||
DBENTRY *pdbentry;
|
||
|
||
pdbentry = dbmfMalloc(sizeof(DBENTRY));
|
||
memset(pdbentry,'\0',sizeof(DBENTRY));
|
||
pdbentry->pdbbase = pdbbase;
|
||
return(pdbentry);
|
||
}
|
||
|
||
void epicsShareAPI dbFreeEntry(DBENTRY *pdbentry)
|
||
{
|
||
if(pdbentry->message) free((void *)pdbentry->message);
|
||
if(pdbentry->formpvt) dbFreeForm(pdbentry);
|
||
dbmfFree(pdbentry);
|
||
}
|
||
|
||
void epicsShareAPI dbInitEntry(dbBase *pdbbase,DBENTRY *pdbentry)
|
||
{
|
||
memset((char *)pdbentry,'\0',sizeof(DBENTRY));
|
||
pdbentry->pdbbase = pdbbase;
|
||
}
|
||
|
||
void epicsShareAPI dbFinishEntry(DBENTRY *pdbentry)
|
||
{
|
||
if(pdbentry->message) {
|
||
free((void *)pdbentry->message);
|
||
pdbentry->message = NULL;
|
||
}
|
||
if(pdbentry->formpvt) dbFreeForm(pdbentry);
|
||
}
|
||
|
||
DBENTRY * epicsShareAPI dbCopyEntry(DBENTRY *pdbentry)
|
||
{
|
||
DBENTRY *pnew;
|
||
|
||
pnew = dbAllocEntry(pdbentry->pdbbase);
|
||
*pnew = *pdbentry;
|
||
pnew->message = NULL;
|
||
pnew->formpvt = NULL;
|
||
return(pnew);
|
||
}
|
||
|
||
void epicsShareAPI dbCopyEntryContents(DBENTRY *pfrom,DBENTRY *pto)
|
||
{
|
||
*pto = *pfrom;
|
||
pto->message = NULL;
|
||
pto->formpvt = NULL;
|
||
}
|
||
|
||
|
||
long epicsShareAPI dbPath(DBBASE *pdbbase,const char *path)
|
||
{
|
||
if(!pdbbase) return(-1);
|
||
dbFreePath(pdbbase);
|
||
if(!path || strlen(path)==0) return(dbAddPath(pdbbase,"."));
|
||
return(dbAddPath(pdbbase,path));
|
||
}
|
||
|
||
long epicsShareAPI dbAddPath(DBBASE *pdbbase,const char *path)
|
||
{
|
||
ELLLIST *ppathList;
|
||
const char *pcolon;
|
||
const char *plast;
|
||
unsigned expectingPath;
|
||
unsigned sawMissingPath;
|
||
|
||
if(!pdbbase) return(-1);
|
||
ppathList = (ELLLIST *)pdbbase->pathPvt;
|
||
if(!ppathList) {
|
||
ppathList = dbCalloc(1,sizeof(ELLLIST));
|
||
ellInit(ppathList);
|
||
pdbbase->pathPvt = (void *)ppathList;
|
||
}
|
||
if (!path) return(0); /* Empty path strings are ignored */
|
||
/* care is taken to properly deal with white space
|
||
* 1) preceding and trailing white space is removed from paths
|
||
* 2) white space inbetween path separator counts as an empty name
|
||
* (see below)
|
||
*/
|
||
expectingPath = FALSE;
|
||
sawMissingPath = FALSE;
|
||
while (*path) {
|
||
int len;
|
||
|
||
/* preceding white space is removed */
|
||
if (isspace(*path)) {
|
||
path++;
|
||
continue;
|
||
}
|
||
pcolon = strstr (path, OSI_PATH_LIST_SEPARATOR);
|
||
if (pcolon==path) {
|
||
sawMissingPath = TRUE;
|
||
path += strlen (OSI_PATH_LIST_SEPARATOR);
|
||
continue;
|
||
}
|
||
if (pcolon) {
|
||
plast = pcolon - 1;
|
||
expectingPath = TRUE;
|
||
} else {
|
||
plast = strlen (path) + path - 1;
|
||
expectingPath = FALSE;
|
||
}
|
||
/* trailing white space is removed */
|
||
while (isspace(*plast)) {
|
||
plast--;
|
||
}
|
||
|
||
/*
|
||
* len is always nonzero because we found something that
|
||
* 1) isnt white space
|
||
* 2) isnt a path separator
|
||
*/
|
||
len = (plast - path) + 1;
|
||
if (dbAddOnePath (pdbbase, path, len)) return (-1);
|
||
path += len;
|
||
if (pcolon) {
|
||
path += strlen(OSI_PATH_LIST_SEPARATOR);
|
||
}
|
||
}
|
||
|
||
/*
|
||
* an empty name at beginning, middle, or end of a path string that isnt
|
||
* empty means current directory
|
||
*/
|
||
if (expectingPath||sawMissingPath) {
|
||
return dbAddOnePath (pdbbase, ".", 1);
|
||
}
|
||
return(0);
|
||
}
|
||
|
||
static long epicsShareAPI dbAddOnePath (DBBASE *pdbbase, const char *path, unsigned length)
|
||
{
|
||
ELLLIST *ppathList;
|
||
dbPathNode *pdbPathNode;
|
||
|
||
if(!pdbbase) return(-1);
|
||
ppathList = (ELLLIST *)pdbbase->pathPvt;
|
||
|
||
pdbPathNode = (dbPathNode *)dbCalloc(1, sizeof(dbPathNode));
|
||
pdbPathNode->directory = (char *)dbCalloc(length+1, sizeof(char));
|
||
strncpy(pdbPathNode->directory, path, length);
|
||
pdbPathNode->directory[length] = '\0';
|
||
ellAdd(ppathList, &pdbPathNode->node);
|
||
return 0;
|
||
}
|
||
|
||
|
||
long epicsShareAPI dbWriteRecord(DBBASE *ppdbbase,const char *filename,
|
||
const char *precordTypename,int level)
|
||
{
|
||
FILE *outFile;
|
||
|
||
outFile = fopen(filename,"w");
|
||
if(!outFile) {
|
||
errPrintf(0,__FILE__,__LINE__,"Error opening %s\n",filename);
|
||
return(-1);
|
||
}
|
||
dbWriteRecordFP(ppdbbase,outFile,precordTypename,level);
|
||
return(fcloseNotSTD(outFile));
|
||
}
|
||
|
||
long epicsShareAPI dbWriteRecordFP(
|
||
DBBASE *pdbbase,FILE *fp,const char *precordTypename,int level)
|
||
{
|
||
DBENTRY dbentry;
|
||
DBENTRY *pdbentry=&dbentry;
|
||
long status;
|
||
int dctonly;
|
||
|
||
dctonly = ((level>1) ? FALSE : TRUE);
|
||
dbInitEntry(pdbbase,pdbentry);
|
||
if(!precordTypename) {
|
||
status = dbFirstRecordType(pdbentry);
|
||
if(status) {
|
||
fprintf(stderr,"dbWriteRecordFP: No record descriptions\n");
|
||
dbFinishEntry(pdbentry);
|
||
return(status);
|
||
}
|
||
} else {
|
||
status = dbFindRecordType(pdbentry,precordTypename);
|
||
if(status) {
|
||
fprintf(stderr,"dbWriteRecordFP: No record description for %s\n",
|
||
precordTypename);
|
||
dbFinishEntry(pdbentry);
|
||
return(status);
|
||
}
|
||
}
|
||
while(!status) {
|
||
status = dbFirstRecord(pdbentry);
|
||
while(!status) {
|
||
if(dbIsVisibleRecord(pdbentry))
|
||
fprintf(fp,"grecord(%s,\"%s\") {\n",
|
||
dbGetRecordTypeName(pdbentry),dbGetRecordName(pdbentry));
|
||
else
|
||
fprintf(fp,"record(%s,\"%s\") {\n",
|
||
dbGetRecordTypeName(pdbentry),dbGetRecordName(pdbentry));
|
||
status = dbFirstField(pdbentry,dctonly);
|
||
while(!status) {
|
||
if(!dbIsDefaultValue(pdbentry) || level>0) {
|
||
char *pvalstring = dbGetString(pdbentry);
|
||
|
||
if(!pvalstring) {
|
||
fprintf(fp,"\tfield(%s,\"\")\n",
|
||
dbGetFieldName(pdbentry));
|
||
} else {
|
||
fprintf(fp,"\tfield(%s,\"%s\")\n",
|
||
dbGetFieldName(pdbentry),dbGetString(pdbentry));
|
||
}
|
||
} else if(level>0) { /*generate 0 length string*/
|
||
fprintf(fp,"\tfield(%s,\"\")\n",dbGetFieldName(pdbentry));
|
||
}
|
||
status=dbNextField(pdbentry,dctonly);
|
||
}
|
||
status = dbFirstInfo(pdbentry);
|
||
while(!status) {
|
||
fprintf(fp,"\tinfo(\"%s\",\"%s\")\n",
|
||
dbGetInfoName(pdbentry), dbGetInfoString(pdbentry));
|
||
status=dbNextInfo(pdbentry);
|
||
}
|
||
fprintf(fp,"}\n");
|
||
status = dbNextRecord(pdbentry);
|
||
}
|
||
if(precordTypename) break;
|
||
status = dbNextRecordType(pdbentry);
|
||
}
|
||
dbFinishEntry(pdbentry);
|
||
return(0);
|
||
}
|
||
|
||
long epicsShareAPI dbWriteMenu(
|
||
DBBASE *ppdbbase,const char *filename,const char *menuName)
|
||
{
|
||
FILE *outFile;
|
||
|
||
outFile = fopen(filename,"w");
|
||
if(!outFile) {
|
||
errPrintf(0,__FILE__,__LINE__,"Error opening %s\n",filename);
|
||
return(-1);
|
||
}
|
||
dbWriteMenuFP(ppdbbase,outFile,menuName);
|
||
if(fcloseNotSTD(outFile)) {
|
||
errPrintf(0,__FILE__,__LINE__,"Error closing %s\n",filename);
|
||
}
|
||
return(0);
|
||
}
|
||
|
||
long epicsShareAPI dbWriteMenuFP(DBBASE *pdbbase,FILE *fp,const char *menuName)
|
||
{
|
||
dbMenu *pdbMenu;
|
||
int gotMatch;
|
||
int i;
|
||
|
||
if(!pdbbase) {
|
||
fprintf(stderr,"pdbbase not specified\n");
|
||
return(-1);
|
||
}
|
||
pdbMenu = (dbMenu *)ellFirst(&pdbbase->menuList);
|
||
while(pdbMenu) {
|
||
if(menuName) {
|
||
gotMatch = (strcmp(menuName,pdbMenu->name)==0) ? TRUE : FALSE;
|
||
}else {
|
||
gotMatch=TRUE;
|
||
}
|
||
if(gotMatch) {
|
||
fprintf(fp,"menu(%s) {\n",pdbMenu->name);
|
||
for(i=0; i<pdbMenu->nChoice; i++) {
|
||
fprintf(fp,"\tchoice(%s,\"%s\")\n",pdbMenu->papChoiceName[i],
|
||
pdbMenu->papChoiceValue[i]);
|
||
}
|
||
fprintf(fp,"}\n");
|
||
if(menuName) break;
|
||
}
|
||
pdbMenu = (dbMenu *)ellNext(&pdbMenu->node);
|
||
}
|
||
return(0);
|
||
}
|
||
|
||
long epicsShareAPI dbWriteRecordType(
|
||
DBBASE *pdbbase,const char *filename,const char *recordTypeName)
|
||
{
|
||
FILE *outFile;
|
||
|
||
outFile = fopen(filename,"w");
|
||
if(!outFile) {
|
||
errPrintf(0,__FILE__,__LINE__,"Error opening %s\n",filename);
|
||
return(-1);
|
||
}
|
||
dbWriteRecordTypeFP(pdbbase,outFile,recordTypeName);
|
||
if(fcloseNotSTD(outFile)) {
|
||
errPrintf(0,__FILE__,__LINE__,"Error closing %s\n",filename);
|
||
}
|
||
return(0);
|
||
}
|
||
|
||
long epicsShareAPI dbWriteRecordTypeFP(
|
||
DBBASE *pdbbase,FILE *fp,const char *recordTypeName)
|
||
{
|
||
dbRecordType *pdbRecordType;
|
||
dbFldDes *pdbFldDes;
|
||
int gotMatch;
|
||
int i;
|
||
|
||
if(!pdbbase) {
|
||
fprintf(stderr,"pdbbase not specified\n");
|
||
return(-1);
|
||
}
|
||
for(pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList);
|
||
pdbRecordType; pdbRecordType = (dbRecordType *)ellNext(&pdbRecordType->node)) {
|
||
if(recordTypeName) {
|
||
gotMatch = (strcmp(recordTypeName,pdbRecordType->name)==0)
|
||
? TRUE : FALSE;
|
||
}else {
|
||
gotMatch=TRUE;
|
||
}
|
||
if(!gotMatch) continue;
|
||
fprintf(fp,"recordtype(%s) {\n",pdbRecordType->name);
|
||
for(i=0; i<pdbRecordType->no_fields; i++) {
|
||
int j;
|
||
|
||
pdbFldDes = pdbRecordType->papFldDes[i];
|
||
fprintf(fp,"\tfield(%s,",pdbFldDes->name);
|
||
for(j=0; j<DBF_NTYPES; j++) {
|
||
if(pamapdbfType[j].value == pdbFldDes->field_type) break;
|
||
}
|
||
if(j>=DBF_NTYPES)
|
||
fprintf(stderr,"\t field_type: %d\n",
|
||
pdbFldDes->field_type);
|
||
else
|
||
fprintf(fp,"%s) {\n",pamapdbfType[j].strvalue);
|
||
if(pdbFldDes->prompt)
|
||
fprintf(fp,"\t\tprompt(\"%s\")\n",pdbFldDes->prompt);
|
||
if(pdbFldDes->initial)
|
||
fprintf(fp,"\t\tinitial(\"%s\")\n",pdbFldDes->initial);
|
||
if(pdbFldDes->promptgroup) {
|
||
for(j=0; j<GUI_NTYPES; j++) {
|
||
if(pamapguiGroup[j].value == pdbFldDes->promptgroup) {
|
||
fprintf(fp,"\t\tpromptgroup(%s)\n",
|
||
pamapguiGroup[j].strvalue);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
if(pdbFldDes->special) {
|
||
if(pdbFldDes->special >= SPC_NTYPES) {
|
||
fprintf(fp,"\t\tspecial(%d)\n",pdbFldDes->special);
|
||
} else for(j=0; j<SPC_NTYPES; j++) {
|
||
if(pamapspcType[j].value == pdbFldDes->special) {
|
||
fprintf(fp,"\t\tspecial(%s)\n",
|
||
pamapspcType[j].strvalue);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
if(pdbFldDes->extra)
|
||
fprintf(fp,"\t\textra(\"%s\")\n",pdbFldDes->extra);
|
||
if(pdbFldDes->field_type==DBF_MENU) {
|
||
if(pdbFldDes->ftPvt)
|
||
fprintf(fp,"\t\tmenu(%s)\n",
|
||
((dbMenu *)pdbFldDes->ftPvt)->name);
|
||
else
|
||
fprintf(stderr,"\t\t menu: NOT FOUND\n");
|
||
}
|
||
if(pdbFldDes->field_type==DBF_STRING) {
|
||
fprintf(fp,"\t\tsize(%d)\n",
|
||
pdbFldDes->size);
|
||
}
|
||
if(pdbFldDes->process_passive) fprintf(fp,"\t\tpp(TRUE)\n");
|
||
if(pdbFldDes->base) fprintf(fp,"\t\tbase(HEX)\n");
|
||
if(pdbFldDes->interest)
|
||
fprintf(fp,"\t\tinterest(%d)\n",pdbFldDes->interest);
|
||
if(!pdbFldDes->as_level) fprintf(fp,"\t\tasl(ASL0)\n");
|
||
fprintf(fp,"\t}\n");
|
||
}
|
||
fprintf(fp,"}\n");
|
||
if(recordTypeName) break;
|
||
}
|
||
return(0);
|
||
}
|
||
|
||
long epicsShareAPI dbWriteDevice(DBBASE *pdbbase,const char *filename)
|
||
{
|
||
FILE *outFile;
|
||
|
||
outFile = fopen(filename,"w");
|
||
if(!outFile) {
|
||
errPrintf(0,__FILE__,__LINE__,"Error opening %s\n",filename);
|
||
return(-1);
|
||
}
|
||
dbWriteDeviceFP(pdbbase,outFile);
|
||
if(fcloseNotSTD(outFile)) {
|
||
errPrintf(0,__FILE__,__LINE__,"Error closing %s\n",filename);
|
||
}
|
||
return(0);
|
||
}
|
||
|
||
long epicsShareAPI dbWriteDeviceFP(DBBASE *pdbbase,FILE *fp)
|
||
{
|
||
dbRecordType *pdbRecordType;
|
||
devSup *pdevSup;
|
||
|
||
if(!pdbbase) {
|
||
fprintf(stderr,"dbWriteDeviceFP: pdbbase not specified\n");
|
||
return(-1);
|
||
}
|
||
for(pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList);
|
||
pdbRecordType; pdbRecordType = (dbRecordType *)ellNext(&pdbRecordType->node)) {
|
||
for(pdevSup = (devSup *)ellFirst(&pdbRecordType->devList);
|
||
pdevSup; pdevSup = (devSup *)ellNext(&pdevSup->node)) {
|
||
int j;
|
||
|
||
for(j=0; j< LINK_NTYPES; j++) {
|
||
if(pamaplinkType[j].value==pdevSup->link_type) break;
|
||
}
|
||
if(j>=LINK_NTYPES) {
|
||
fprintf(fp,"link_type not valid\n");
|
||
continue;
|
||
}
|
||
fprintf(fp,"device(%s,%s,%s,\"%s\")\n",
|
||
pdbRecordType->name,
|
||
pamaplinkType[j].strvalue,
|
||
pdevSup->name,pdevSup->choice);
|
||
}
|
||
}
|
||
return(0);
|
||
}
|
||
|
||
long epicsShareAPI dbWriteDriver(DBBASE *pdbbase,const char *filename)
|
||
{
|
||
FILE *outFile;
|
||
|
||
outFile = fopen(filename,"w");
|
||
if(!outFile) {
|
||
errPrintf(0,__FILE__,__LINE__,"Error opening %s\n",filename);
|
||
return(-1);
|
||
}
|
||
dbWriteDriverFP(pdbbase,outFile);
|
||
if(fcloseNotSTD(outFile)) {
|
||
errPrintf(0,__FILE__,__LINE__,"Error closing %s\n",filename);
|
||
}
|
||
return(0);
|
||
}
|
||
|
||
long epicsShareAPI dbWriteDriverFP(DBBASE *pdbbase,FILE *fp)
|
||
{
|
||
drvSup *pdrvSup;
|
||
|
||
if(!pdbbase) {
|
||
fprintf(stderr,"pdbbase not specified\n");
|
||
return(-1);
|
||
}
|
||
for(pdrvSup = (drvSup *)ellFirst(&pdbbase->drvList);
|
||
pdrvSup; pdrvSup = (drvSup *)ellNext(&pdrvSup->node)) {
|
||
fprintf(fp,"driver(%s)\n",pdrvSup->name);
|
||
}
|
||
return(0);
|
||
}
|
||
|
||
long epicsShareAPI dbWriteBreaktable(DBBASE *pdbbase,const char *filename)
|
||
{
|
||
FILE *outFile;
|
||
|
||
outFile = fopen(filename,"w");
|
||
if(!outFile) {
|
||
errPrintf(0,__FILE__,__LINE__,"Error opening %s\n",filename);
|
||
return(-1);
|
||
}
|
||
dbWriteBreaktableFP(pdbbase,outFile);
|
||
if(fcloseNotSTD(outFile)) {
|
||
errPrintf(0,__FILE__,__LINE__,"Error closing %s\n",filename);
|
||
}
|
||
return(0);
|
||
}
|
||
|
||
long epicsShareAPI dbWriteBreaktableFP(DBBASE *pdbbase,FILE *fp)
|
||
{
|
||
brkTable *pbrkTable;
|
||
brkInt *pbrkInt;
|
||
int ind;
|
||
|
||
if(!pdbbase) {
|
||
fprintf(stderr,"pdbbase not specified\n");
|
||
return(-1);
|
||
}
|
||
for(pbrkTable = (brkTable *)ellFirst(&pdbbase->bptList);
|
||
pbrkTable; pbrkTable = (brkTable *)ellNext(&pbrkTable->node)) {
|
||
fprintf(fp,"breaktable(%s) {\n",pbrkTable->name);
|
||
for(ind=0; ind<pbrkTable->number; ind++) {
|
||
pbrkInt = pbrkTable->papBrkInt[ind];
|
||
fprintf(fp,"\t%e %e\n",pbrkInt->raw,pbrkInt->eng);
|
||
}
|
||
fprintf(fp,"}\n");
|
||
}
|
||
return(0);
|
||
}
|
||
|
||
long epicsShareAPI dbFindRecordType(DBENTRY *pdbentry,const char *recordType)
|
||
{
|
||
dbBase *pdbbase = pdbentry->pdbbase;
|
||
GPHENTRY *phash;
|
||
|
||
zeroDbentry(pdbentry);
|
||
phash = gphFind(pdbbase->pgpHash,recordType,&pdbbase->recordTypeList);
|
||
if(!phash) return(S_dbLib_recordTypeNotFound);
|
||
pdbentry->precordType = phash->userPvt;
|
||
return(0);
|
||
}
|
||
|
||
long epicsShareAPI dbFirstRecordType(DBENTRY *pdbentry)
|
||
{
|
||
dbRecordType *precordType;
|
||
|
||
zeroDbentry(pdbentry);
|
||
precordType = (dbRecordType *)ellFirst(&pdbentry->pdbbase->recordTypeList);
|
||
if(!precordType) return(S_dbLib_recordTypeNotFound);
|
||
pdbentry->precordType = precordType;
|
||
return(0);
|
||
}
|
||
|
||
long epicsShareAPI dbNextRecordType(DBENTRY *pdbentry)
|
||
{
|
||
dbRecordType *precordType = pdbentry->precordType;
|
||
|
||
zeroDbentry(pdbentry);
|
||
precordType = (dbRecordType *)ellNext(&precordType->node);
|
||
if(!precordType) return(S_dbLib_recordTypeNotFound);
|
||
pdbentry->precordType = precordType;
|
||
return(0);
|
||
}
|
||
|
||
char * epicsShareAPI dbGetRecordTypeName(DBENTRY *pdbentry)
|
||
{
|
||
return(pdbentry->precordType->name);
|
||
}
|
||
|
||
int epicsShareAPI dbGetNRecordTypes(DBENTRY *pdbentry)
|
||
{
|
||
return(ellCount(&pdbentry->pdbbase->recordTypeList));
|
||
}
|
||
|
||
long epicsShareAPI dbPutRecordAttribute(
|
||
DBENTRY *pdbentry, const char *name, const char*value)
|
||
{
|
||
dbRecordType *precordType = pdbentry->precordType;
|
||
int createNew = TRUE;
|
||
int compare;
|
||
dbRecordAttribute *pattribute;
|
||
|
||
if(!precordType) return(S_dbLib_recordTypeNotFound);
|
||
pattribute = (dbRecordAttribute *)ellFirst(&precordType->attributeList);
|
||
/*put new attribute name in sort order*/
|
||
while(pattribute) {
|
||
compare = strcmp(pattribute->name,name);
|
||
if(compare==0) {
|
||
createNew = FALSE;
|
||
}
|
||
if(compare>=0) break;
|
||
pattribute = (dbRecordAttribute *)ellNext(&pattribute->node);
|
||
}
|
||
if(createNew) {
|
||
dbRecordAttribute *pnew;
|
||
dbFldDes *pdbFldDes;
|
||
|
||
pnew = dbCalloc(1,sizeof(dbRecordAttribute));
|
||
if(pattribute) {
|
||
ellInsert(&precordType->attributeList,&pattribute->node,
|
||
&pnew->node);
|
||
} else {
|
||
ellAdd(&precordType->attributeList,&pnew->node);
|
||
}
|
||
pattribute = pnew;
|
||
pattribute->name = dbCalloc(strlen(name)+1,sizeof(char));
|
||
strcpy(pattribute->name,name);
|
||
pdbFldDes = dbCalloc(1,sizeof(dbFldDes));
|
||
pdbFldDes->name = pattribute->name;
|
||
pdbFldDes->pdbRecordType = precordType;
|
||
pdbFldDes->special = SPC_ATTRIBUTE;
|
||
pdbFldDes->field_type = DBF_STRING;
|
||
pdbFldDes->as_level = ASL1;
|
||
pdbFldDes->size = MAX_STRING_SIZE;
|
||
pattribute->pdbFldDes = pdbFldDes;
|
||
}
|
||
strncpy(pattribute->value,value,MAX_STRING_SIZE);
|
||
pattribute->value[MAX_STRING_SIZE-1] = 0;
|
||
return(0);
|
||
}
|
||
|
||
long epicsShareAPI dbGetRecordAttribute(DBENTRY *pdbentry,const char *name)
|
||
{
|
||
dbRecordType *precordType = pdbentry->precordType;
|
||
int compare;
|
||
dbRecordAttribute *pattribute;
|
||
|
||
if(!precordType) return(S_dbLib_recordTypeNotFound);
|
||
pattribute = (dbRecordAttribute *)ellFirst(&precordType->attributeList);
|
||
while(pattribute) {
|
||
compare = strcmp(pattribute->name,name);
|
||
if(compare==0) {
|
||
pdbentry->pflddes = pattribute->pdbFldDes;
|
||
pdbentry->pfield = pattribute->value;
|
||
return(0);
|
||
}
|
||
if(compare>=0) break;
|
||
pattribute = (dbRecordAttribute *)ellNext(&pattribute->node);
|
||
}
|
||
return(S_dbLib_fieldNotFound);
|
||
}
|
||
|
||
long epicsShareAPI dbFirstField(DBENTRY *pdbentry,int dctonly)
|
||
{
|
||
|
||
pdbentry->indfield = -1;
|
||
return(dbNextField(pdbentry,dctonly));
|
||
}
|
||
|
||
long epicsShareAPI dbNextField(DBENTRY *pdbentry,int dctonly)
|
||
{
|
||
dbRecordType *precordType = pdbentry->precordType;
|
||
dbRecordNode *precnode = pdbentry->precnode;
|
||
dbFldDes *pflddes;
|
||
short indfield = pdbentry->indfield;
|
||
long status;
|
||
|
||
if(!precordType) return(S_dbLib_recordTypeNotFound);
|
||
indfield++;
|
||
while(TRUE) {
|
||
if(indfield>=precordType->no_fields) {
|
||
pdbentry->indfield = 0;
|
||
pdbentry->pflddes = NULL;
|
||
pdbentry->pfield = NULL;
|
||
return(S_dbLib_fieldNotFound);
|
||
}
|
||
pflddes = precordType->papFldDes[indfield];
|
||
if(!dctonly || pflddes->promptgroup) {
|
||
/*Skip field if dctonly and no device support*/
|
||
if(!dctonly || (pflddes->field_type!=DBF_DEVICE)
|
||
|| (ellCount(&precordType->devList)>0)) {
|
||
pdbentry->indfield = indfield;
|
||
pdbentry->pflddes = pflddes;
|
||
pdbentry->indfield = indfield;
|
||
if(precnode) {
|
||
status = dbGetFieldAddress(pdbentry);
|
||
}else {
|
||
pdbentry->pfield = NULL;
|
||
}
|
||
return(0);
|
||
}
|
||
}
|
||
indfield++;
|
||
}
|
||
}
|
||
|
||
int epicsShareAPI dbGetFieldType(DBENTRY *pdbentry)
|
||
{
|
||
dbFldDes *pflddes = pdbentry->pflddes;
|
||
long status;
|
||
|
||
if(!pflddes){
|
||
status = S_dbLib_flddesNotFound;
|
||
entryErrMessage(pdbentry,status,"dbGetFieldType");
|
||
return(status);
|
||
}
|
||
return(mapDBFtoDCT[pflddes->field_type]);
|
||
}
|
||
|
||
int epicsShareAPI dbGetNFields(DBENTRY *pdbentry,int dctonly)
|
||
{
|
||
dbRecordType *precordType = pdbentry->precordType;
|
||
dbFldDes *pflddes;
|
||
int indfield,n;
|
||
|
||
if(!precordType) return(S_dbLib_recordTypeNotFound);
|
||
n = 0;
|
||
for(indfield=0; indfield<precordType->no_fields; indfield++) {
|
||
pflddes = precordType->papFldDes[indfield];
|
||
if(dctonly && (pflddes->field_type==DBF_DEVICE)
|
||
&& (ellCount(&precordType->devList)==0) ) continue;
|
||
if(!dctonly || pflddes->promptgroup) n++;
|
||
}
|
||
return(n);
|
||
}
|
||
|
||
char * epicsShareAPI dbGetFieldName(DBENTRY *pdbentry)
|
||
{
|
||
dbFldDes *pflddes = pdbentry->pflddes;
|
||
|
||
if(!pflddes) return(NULL);
|
||
return(pflddes->name);
|
||
}
|
||
|
||
char * epicsShareAPI dbGetDefault(DBENTRY *pdbentry)
|
||
{
|
||
dbFldDes *pflddes = pdbentry->pflddes;
|
||
|
||
if(!pflddes) return(NULL);
|
||
return(pflddes->initial);
|
||
}
|
||
|
||
char * epicsShareAPI dbGetPrompt(DBENTRY *pdbentry)
|
||
{
|
||
dbFldDes *pflddes = pdbentry->pflddes;
|
||
|
||
if(!pflddes) return(NULL);
|
||
return(&pflddes->prompt[0]);
|
||
}
|
||
|
||
int epicsShareAPI dbGetPromptGroup(DBENTRY *pdbentry)
|
||
{
|
||
dbFldDes *pflddes = pdbentry->pflddes;
|
||
|
||
if(!pflddes) return(0);
|
||
return(pflddes->promptgroup);
|
||
}
|
||
|
||
long epicsShareAPI dbCreateRecord(DBENTRY *pdbentry,const char *precordName)
|
||
{
|
||
dbRecordType *precordType = pdbentry->precordType;
|
||
dbFldDes *pdbFldDes;
|
||
PVDENTRY *ppvd;
|
||
ELLLIST *preclist = NULL;
|
||
dbRecordNode *precnode = NULL;
|
||
dbRecordNode *pNewRecNode = NULL;
|
||
long status = 0;
|
||
|
||
if(!precordType) return(S_dbLib_recordTypeNotFound);
|
||
/*Get size of NAME field*/
|
||
pdbFldDes = precordType->papFldDes[0];
|
||
if(!pdbFldDes || (strcmp(pdbFldDes->name,"NAME")!=0))
|
||
return(S_dbLib_nameLength);
|
||
if((int)strlen(precordName)>=pdbFldDes->size) return(S_dbLib_nameLength);
|
||
/* clear callers entry */
|
||
zeroDbentry(pdbentry);
|
||
if(!dbFindRecord(pdbentry,precordName)) return (S_dbLib_recExists);
|
||
zeroDbentry(pdbentry);
|
||
pdbentry->precordType = precordType;
|
||
preclist = &precordType->recList;
|
||
/* create a recNode */
|
||
pNewRecNode = dbCalloc(1,sizeof(dbRecordNode));
|
||
/* create a new record of this record type */
|
||
pdbentry->precnode = pNewRecNode;
|
||
if((status = dbAllocRecord(pdbentry,precordName))) return(status);
|
||
pNewRecNode->recordname = dbRecordName(pdbentry);
|
||
ellInit(&pNewRecNode->infoList);
|
||
/* install record node in list in sorted postion */
|
||
status = dbFirstRecord(pdbentry);
|
||
while(status==0) {
|
||
if(strcmp(precordName,dbGetRecordName(pdbentry)) < 0) break;
|
||
status = dbNextRecord(pdbentry);
|
||
}
|
||
if(status==0) {
|
||
precnode = pdbentry->precnode;
|
||
ellInsert(preclist,ellPrevious(&precnode->node),&pNewRecNode->node);
|
||
} else {
|
||
ellAdd(preclist,&pNewRecNode->node);
|
||
}
|
||
pdbentry->precnode = pNewRecNode;
|
||
ppvd = dbPvdAdd(pdbentry->pdbbase,precordType,pNewRecNode);
|
||
if(!ppvd) {errMessage(-1,"Logic Err: Could not add to PVD");return(-1);}
|
||
return(0);
|
||
}
|
||
|
||
long epicsShareAPI dbDeleteRecord(DBENTRY *pdbentry)
|
||
{
|
||
dbBase *pdbbase = pdbentry->pdbbase;
|
||
dbRecordType *precordType = pdbentry->precordType;
|
||
dbRecordNode *precnode = pdbentry->precnode;
|
||
ELLLIST *preclist;
|
||
long status;
|
||
|
||
if (!precnode) return (S_dbLib_recNotFound);
|
||
preclist = &precordType->recList;
|
||
ellDelete(preclist,&precnode->node);
|
||
dbPvdDelete(pdbbase,precnode);
|
||
while (!dbFirstInfo(pdbentry)) {
|
||
dbDeleteInfo(pdbentry);
|
||
}
|
||
if((status = dbFreeRecord(pdbentry))) return(status);
|
||
free((void *)precnode);
|
||
pdbentry->precnode = NULL;
|
||
return (0);
|
||
}
|
||
|
||
long epicsShareAPI dbFreeRecords(DBBASE *pdbbase)
|
||
{
|
||
DBENTRY dbentry;
|
||
dbRecordType *pdbRecordType;
|
||
dbRecordNode *pdbRecordNode;
|
||
dbRecordNode *pdbRecordNodeNext;
|
||
|
||
dbInitEntry(pdbbase,&dbentry);
|
||
pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList);
|
||
while(pdbRecordType) {
|
||
pdbRecordNode = (dbRecordNode *)ellFirst(&pdbRecordType->recList);
|
||
while(pdbRecordNode) {
|
||
pdbRecordNodeNext = (dbRecordNode *)ellNext(&pdbRecordNode->node);
|
||
if(!dbFindRecord(&dbentry,pdbRecordNode->recordname))
|
||
dbDeleteRecord(&dbentry);
|
||
pdbRecordNode = pdbRecordNodeNext;
|
||
}
|
||
pdbRecordType = (dbRecordType *)ellNext(&pdbRecordType->node);
|
||
}
|
||
dbFinishEntry(&dbentry);
|
||
return(0);
|
||
}
|
||
|
||
long epicsShareAPI dbFindRecord(DBENTRY *pdbentry,const char *precordName)
|
||
{
|
||
dbBase *pdbbase = pdbentry->pdbbase;
|
||
int lenName=0;
|
||
PVDENTRY *ppvdNode;
|
||
char convName[PVNAME_SZ + 1];
|
||
char *pconvName = &convName[0];
|
||
|
||
|
||
zeroDbentry(pdbentry);
|
||
/* convert the record name */
|
||
while (*precordName && (*precordName != '.') && (lenName < PVNAME_SZ)) {
|
||
*pconvName++ = *precordName++;
|
||
lenName++;
|
||
}
|
||
*pconvName = 0;
|
||
pconvName = &convName[0];
|
||
ppvdNode = dbPvdFind(pdbbase,pconvName,lenName);
|
||
if(!ppvdNode) return(S_dbLib_recNotFound);
|
||
pdbentry->precnode = ppvdNode->precnode;
|
||
pdbentry->precordType = ppvdNode->precordType;
|
||
if(*precordName++=='.') return(dbFindField(pdbentry, precordName));
|
||
return (0);
|
||
}
|
||
|
||
long epicsShareAPI dbFirstRecord(DBENTRY *pdbentry)
|
||
{
|
||
dbRecordType *precordType = pdbentry->precordType;
|
||
dbRecordNode *precnode;
|
||
|
||
zeroDbentry(pdbentry);
|
||
if(!precordType) return(S_dbLib_recordTypeNotFound);
|
||
pdbentry->precordType = precordType;
|
||
precnode = (dbRecordNode *)ellFirst(&precordType->recList);
|
||
if(!precnode) return(S_dbLib_recNotFound);
|
||
pdbentry->precnode = precnode;
|
||
return(0);
|
||
}
|
||
|
||
long epicsShareAPI dbNextRecord(DBENTRY *pdbentry)
|
||
{
|
||
dbRecordNode *precnode=pdbentry->precnode;
|
||
long status=0;
|
||
|
||
if(!precnode) return(S_dbLib_recNotFound);
|
||
precnode = (dbRecordNode *)ellNext(&precnode->node);
|
||
if(!precnode) status = S_dbLib_recNotFound;
|
||
pdbentry->precnode = precnode;
|
||
pdbentry->pfield = NULL;
|
||
return(status);
|
||
}
|
||
|
||
int epicsShareAPI dbGetNRecords(DBENTRY *pdbentry)
|
||
{
|
||
dbRecordType *precordType = pdbentry->precordType;
|
||
|
||
if(!precordType) return(0);
|
||
return(ellCount(&precordType->recList));
|
||
}
|
||
|
||
char * epicsShareAPI dbGetRecordName(DBENTRY *pdbentry)
|
||
{
|
||
return(dbRecordName(pdbentry));
|
||
}
|
||
|
||
long epicsShareAPI dbRenameRecord(DBENTRY *pdbentry,const char *newName)
|
||
{
|
||
dbBase *pdbbase = pdbentry->pdbbase;
|
||
dbRecordType *precordType = pdbentry->precordType;
|
||
dbFldDes *pdbFldDes;
|
||
dbRecordNode *precnode = pdbentry->precnode;
|
||
PVDENTRY *ppvd;
|
||
ELLLIST *preclist;
|
||
dbRecordNode *plistnode;
|
||
long status;
|
||
DBENTRY dbentry;
|
||
|
||
if(!precordType) return(S_dbLib_recordTypeNotFound);
|
||
/*Get size of NAME field*/
|
||
pdbFldDes = precordType->papFldDes[0];
|
||
if(!pdbFldDes || (strcmp(pdbFldDes->name,"NAME")!=0))
|
||
return(S_dbLib_nameLength);
|
||
if((int)strlen(newName)>=pdbFldDes->size) return(S_dbLib_nameLength);
|
||
if(!precnode) return(S_dbLib_recNotFound);
|
||
dbInitEntry(pdbentry->pdbbase,&dbentry);
|
||
status = dbFindRecord(&dbentry,newName);
|
||
dbFinishEntry(&dbentry);
|
||
if(!status) return(S_dbLib_recExists);
|
||
dbPvdDelete(pdbbase,precnode);
|
||
pdbentry->pflddes = precordType->papFldDes[0];
|
||
if((status = dbGetFieldAddress(pdbentry))) return(status);
|
||
strcpy(pdbentry->pfield,newName);
|
||
ppvd = dbPvdAdd(pdbbase,precordType,precnode);
|
||
if(!ppvd) {errMessage(-1,"Logic Err: Could not add to PVD");return(-1);}
|
||
/*remove from record list and reinstall in sorted order*/
|
||
preclist = &precordType->recList;
|
||
ellDelete(preclist,&precnode->node);
|
||
plistnode = (dbRecordNode *)ellFirst(preclist);
|
||
while(plistnode) {
|
||
pdbentry->precnode = plistnode;
|
||
if(strcmp(newName,dbRecordName(pdbentry)) >=0) break;
|
||
plistnode = (dbRecordNode *)ellNext(&plistnode->node);
|
||
}
|
||
if(plistnode)
|
||
ellInsert(preclist,ellPrevious(&plistnode->node),&precnode->node);
|
||
else
|
||
ellAdd(preclist,&precnode->node);
|
||
/*Leave pdbentry pointing to newly renamed record*/
|
||
return(dbFindRecord(pdbentry,newName));
|
||
}
|
||
|
||
long epicsShareAPI dbVisibleRecord(DBENTRY *pdbentry)
|
||
{
|
||
dbRecordNode *precnode = pdbentry->precnode;
|
||
|
||
if(!precnode) return(S_dbLib_recNotFound);
|
||
precnode->visible=1;
|
||
return 0;
|
||
}
|
||
|
||
long epicsShareAPI dbInvisibleRecord(DBENTRY *pdbentry)
|
||
{
|
||
dbRecordNode *precnode = pdbentry->precnode;
|
||
|
||
if(!precnode) return(S_dbLib_recNotFound);
|
||
precnode->visible=0;
|
||
return 0;
|
||
}
|
||
|
||
int epicsShareAPI dbIsVisibleRecord(DBENTRY *pdbentry)
|
||
{
|
||
dbRecordNode *precnode = pdbentry->precnode;
|
||
|
||
if(!precnode) return 0;
|
||
return(precnode->visible?1:0);
|
||
}
|
||
|
||
long epicsShareAPI dbCopyRecord(DBENTRY *pdbentry,const char *newRecordName,int overWriteOK)
|
||
{
|
||
dbRecordType *precordType = pdbentry->precordType;
|
||
dbFldDes *pdbFldDes;
|
||
dbRecordNode *precnode = pdbentry->precnode;
|
||
long status;
|
||
DBENTRY dbentry;
|
||
char *pvalue;
|
||
|
||
if(!precordType) return(S_dbLib_recordTypeNotFound);
|
||
/*Get size of NAME field*/
|
||
pdbFldDes = precordType->papFldDes[0];
|
||
if(!pdbFldDes || (strcmp(pdbFldDes->name,"NAME")!=0))
|
||
return(S_dbLib_nameLength);
|
||
if((int)strlen(newRecordName)>=pdbFldDes->size) return(S_dbLib_nameLength);
|
||
if(!precnode) return(S_dbLib_recNotFound);
|
||
dbInitEntry(pdbentry->pdbbase,&dbentry);
|
||
status = dbFindRecord(&dbentry,newRecordName);
|
||
if(!status) {
|
||
if(!overWriteOK) {
|
||
dbFinishEntry(&dbentry);
|
||
return(S_dbLib_recExists);
|
||
}
|
||
status = dbDeleteRecord(&dbentry);
|
||
if(status) return(status);
|
||
}
|
||
dbFinishEntry(&dbentry);
|
||
if((status = dbFindRecordType(&dbentry,precordType->name))) return(status);
|
||
if((status = dbCreateRecord(&dbentry,newRecordName))) return(status);
|
||
if((status = dbFirstField(pdbentry,TRUE))) return(status);
|
||
if((status = dbFirstField(&dbentry,TRUE))) return(status);
|
||
while(!status) {
|
||
if(!dbIsDefaultValue(pdbentry)) {
|
||
pvalue = dbGetString(pdbentry);
|
||
if((status = dbPutString(&dbentry,pvalue))) return(status);
|
||
}
|
||
status = dbNextField(pdbentry,TRUE);
|
||
if(!status) status = dbNextField(&dbentry,TRUE);
|
||
if(!status && (pdbentry->pflddes!=dbentry.pflddes)) {
|
||
epicsPrintf("dbCopyRecord: Logic Error\n");
|
||
exit(1);
|
||
}
|
||
}
|
||
/*Copy the info strings too*/
|
||
status = dbFirstInfo(pdbentry);
|
||
while (!status) {
|
||
status = dbPutInfo(&dbentry, dbGetInfoName(pdbentry), dbGetInfoString(pdbentry));
|
||
if (status) return (status);
|
||
status = dbNextInfo(pdbentry);
|
||
}
|
||
/*Leave pdbentry pointing to newRecordName*/
|
||
return(dbFindRecord(pdbentry,newRecordName));
|
||
}
|
||
|
||
long epicsShareAPI dbFindField(DBENTRY *pdbentry,const char *pname)
|
||
{
|
||
dbRecordType *precordType = pdbentry->precordType;
|
||
dbRecordNode *precnode = pdbentry->precnode;
|
||
char *precord;
|
||
dbFldDes *pflddes;
|
||
short top, bottom, test;
|
||
char **papsortFldName;
|
||
short *sortFldInd;
|
||
int compare,ind;
|
||
char fieldName[MAX_FIELD_NAME_LENGTH];
|
||
char *pfieldName;
|
||
|
||
if(!precordType) return(S_dbLib_recordTypeNotFound);
|
||
if(!precnode) return(S_dbLib_recNotFound);
|
||
precord = precnode->precord;
|
||
papsortFldName = precordType->papsortFldName;
|
||
sortFldInd = precordType->sortFldInd;
|
||
/*copy field name. Stop at null or blank or tab*/
|
||
pfieldName = &fieldName[0];
|
||
for(ind=0; ind<MAX_FIELD_NAME_LENGTH; ind++) {
|
||
if(*pname=='\0' || *pname==' ' || *pname=='\t') break;
|
||
*pfieldName++ = *pname++;
|
||
}
|
||
*pfieldName = '\0';
|
||
pfieldName = &fieldName[0];
|
||
/* check for default field name or VAL to be supplied */
|
||
if((*pfieldName==0) || (strcmp(pfieldName,"VAL")==0) ) {
|
||
if(!(pflddes=precordType->pvalFldDes))
|
||
return(S_dbLib_recordTypeNotFound);
|
||
pdbentry->pflddes = pflddes;
|
||
pdbentry->indfield = precordType->indvalFlddes;
|
||
return(dbGetFieldAddress(pdbentry));
|
||
}
|
||
/* binary search through ordered field names */
|
||
top = precordType->no_fields - 1;
|
||
bottom = 0;
|
||
test = (top + bottom) / 2;
|
||
while (1) {
|
||
/* check the field name */
|
||
compare = strcmp(papsortFldName[test],pfieldName);
|
||
if (compare == 0) {
|
||
if(!(pflddes=precordType->papFldDes[sortFldInd[test]]))
|
||
return(S_dbLib_recordTypeNotFound);
|
||
pdbentry->pflddes = pflddes;
|
||
pdbentry->indfield = sortFldInd[test];
|
||
return(dbGetFieldAddress(pdbentry));
|
||
} else if (compare > 0) {
|
||
top = test - 1;
|
||
if (top < bottom) break;
|
||
test = (top + bottom) / 2;
|
||
} else {
|
||
bottom = test + 1;
|
||
if (top < bottom) break;
|
||
test = (top + bottom) / 2;
|
||
}
|
||
}
|
||
return(dbGetRecordAttribute(pdbentry,pfieldName));
|
||
}
|
||
|
||
int epicsShareAPI dbFoundField(DBENTRY *pdbentry)
|
||
{ return((pdbentry->pfield) ? TRUE : FALSE); }
|
||
|
||
char * epicsShareAPI dbGetString(DBENTRY *pdbentry)
|
||
{
|
||
dbFldDes *pflddes = pdbentry->pflddes;
|
||
void *pfield = pdbentry->pfield;
|
||
char *message;
|
||
unsigned char cvttype;
|
||
DBLINK *plink;
|
||
|
||
message = getpMessage(pdbentry);
|
||
*message = 0;
|
||
if(!pflddes) {strcpy(message,"fldDes not found"); return(message);}
|
||
cvttype = pflddes->base;
|
||
switch (pflddes->field_type) {
|
||
case DBF_STRING:
|
||
if(!pfield) {strcpy(message,"Field not found"); return(message);}
|
||
strcpy(message, (char *)pfield);
|
||
break;
|
||
case DBF_CHAR:
|
||
case DBF_UCHAR:
|
||
case DBF_SHORT:
|
||
case DBF_USHORT:
|
||
case DBF_ENUM:
|
||
case DBF_LONG:
|
||
case DBF_ULONG:
|
||
case DBF_FLOAT:
|
||
case DBF_DOUBLE:
|
||
case DBF_MENU:
|
||
case DBF_DEVICE:
|
||
return(dbGetStringNum(pdbentry));
|
||
case DBF_INLINK:
|
||
case DBF_OUTLINK:
|
||
if(!pfield) {strcpy(message,"Field not found"); return(message);}
|
||
plink = (DBLINK *)pfield;
|
||
switch(plink->type) {
|
||
case CONSTANT:
|
||
if(plink->value.constantStr) {
|
||
strcpy(message,plink->value.constantStr);
|
||
} else {
|
||
strcpy(message,"");
|
||
}
|
||
break;
|
||
case MACRO_LINK:
|
||
if(plink->value.macro_link.macroStr) {
|
||
strcpy(message,plink->value.macro_link.macroStr);
|
||
} else {
|
||
strcpy(message,"");
|
||
}
|
||
break;
|
||
case PV_LINK:
|
||
case CA_LINK:
|
||
case DB_LINK: {
|
||
int ppind;
|
||
short pvlMask;
|
||
|
||
pvlMask = plink->value.pv_link.pvlMask;
|
||
if(pvlMask&pvlOptPP) ppind=1;
|
||
else if(pvlMask&pvlOptCA) ppind=2;
|
||
else if(pvlMask&pvlOptCP) ppind=3;
|
||
else if(pvlMask&pvlOptCPP) ppind=4;
|
||
else ppind=0;
|
||
if(plink->value.pv_link.pvname)
|
||
strcpy(message,plink->value.pv_link.pvname);
|
||
else
|
||
strcpy(message,"");
|
||
strcat(message," ");
|
||
strcat(message,ppstring[ppind]);
|
||
strcat(message," ");
|
||
strcat(message,msstring[pvlMask&pvlOptMS]);
|
||
break;
|
||
}
|
||
case VME_IO:
|
||
sprintf(message,"#C%d S%d @%s",
|
||
plink->value.vmeio.card,plink->value.vmeio.signal,
|
||
plink->value.vmeio.parm);
|
||
break;
|
||
case CAMAC_IO:
|
||
sprintf(message,"#B%d C%d N%d A%d F%d @%s",
|
||
plink->value.camacio.b,plink->value.camacio.c,
|
||
plink->value.camacio.n,plink->value.camacio.a,
|
||
plink->value.camacio.f,plink->value.camacio.parm);
|
||
break;
|
||
case RF_IO:
|
||
sprintf(message,"#R%d M%d D%d E%d",
|
||
plink->value.rfio.cryo,
|
||
plink->value.rfio.micro,
|
||
plink->value.rfio.dataset,
|
||
plink->value.rfio.element);
|
||
break;
|
||
case AB_IO:
|
||
sprintf(message,"#L%d A%d C%d S%d @%s",
|
||
plink->value.abio.link,plink->value.abio.adapter,
|
||
plink->value.abio.card,plink->value.abio.signal,
|
||
plink->value.abio.parm);
|
||
break;
|
||
case GPIB_IO:
|
||
sprintf(message,"#L%d A%d @%s",
|
||
plink->value.gpibio.link,plink->value.gpibio.addr,
|
||
plink->value.gpibio.parm);
|
||
break;
|
||
case BITBUS_IO:
|
||
sprintf(message,"#L%u N%u P%u S%u @%s",
|
||
plink->value.bitbusio.link,plink->value.bitbusio.node,
|
||
plink->value.bitbusio.port,plink->value.bitbusio.signal,
|
||
plink->value.bitbusio.parm);
|
||
break;
|
||
case BBGPIB_IO:
|
||
sprintf(message,"#L%u B%u G%u @%s",
|
||
plink->value.bbgpibio.link,plink->value.bbgpibio.bbaddr,
|
||
plink->value.bbgpibio.gpibaddr,plink->value.bbgpibio.parm);
|
||
break;
|
||
case INST_IO:
|
||
sprintf(message,"@%s", plink->value.instio.string);
|
||
break;
|
||
case VXI_IO :
|
||
if (plink->value.vxiio.flag == VXIDYNAMIC)
|
||
sprintf(message,"#V%d C%d S%d @%s",
|
||
plink->value.vxiio.frame,plink->value.vxiio.slot,
|
||
plink->value.vxiio.signal,plink->value.vxiio.parm);
|
||
else
|
||
sprintf(message,"#V%d S%d @%s",
|
||
plink->value.vxiio.la,plink->value.vxiio.signal,
|
||
plink->value.vxiio.parm);
|
||
break;
|
||
default :
|
||
return(NULL);
|
||
}
|
||
break;
|
||
case DBF_FWDLINK: {
|
||
DBLINK *plink=(DBLINK *)pfield;
|
||
|
||
if(!pfield) {strcpy(message,"Field not found"); return(message);}
|
||
switch(plink->type) {
|
||
case CONSTANT:
|
||
strcpy(message,"0");
|
||
break;
|
||
case MACRO_LINK:
|
||
if(plink->value.macro_link.macroStr) {
|
||
strcpy(message,plink->value.macro_link.macroStr);
|
||
} else {
|
||
strcpy(message,"");
|
||
}
|
||
break;
|
||
case PV_LINK:
|
||
case CA_LINK:
|
||
case DB_LINK: {
|
||
int ppind;
|
||
short pvlMask;
|
||
|
||
pvlMask = plink->value.pv_link.pvlMask;
|
||
if(pvlMask&pvlOptCA) ppind=2;
|
||
else ppind=0;
|
||
if(plink->value.pv_link.pvname)
|
||
strcpy(message,plink->value.pv_link.pvname);
|
||
else
|
||
strcpy(message,"");
|
||
if(ppind) {
|
||
strcat(message," ");
|
||
strcat(message,ppstring[ppind]);
|
||
}
|
||
break;
|
||
}
|
||
default :
|
||
return(NULL);
|
||
}
|
||
}
|
||
break;
|
||
default:
|
||
return(NULL);
|
||
}
|
||
return (message);
|
||
}
|
||
|
||
long epicsShareAPI dbPutString(DBENTRY *pdbentry,const char *pstring)
|
||
{
|
||
dbFldDes *pflddes = pdbentry->pflddes;
|
||
void *pfield = pdbentry->pfield;
|
||
long status=0;
|
||
int macroIsOk;
|
||
int stringHasMacro=FALSE;
|
||
|
||
if(!pflddes) return(S_dbLib_flddesNotFound);
|
||
macroIsOk = dbIsMacroOk(pdbentry);
|
||
stringHasMacro = (strstr(pstring,"$(") || strstr(pstring,"${"))?TRUE:FALSE;
|
||
if(!macroIsOk && stringHasMacro) {
|
||
epicsPrintf("%s.%s Has unexpanded macro\n",
|
||
dbGetRecordName(pdbentry),dbGetFieldName(pdbentry));
|
||
return(S_dbLib_badField);
|
||
}
|
||
switch (pflddes->field_type) {
|
||
case DBF_STRING:
|
||
if(!pfield) return(S_dbLib_fieldNotFound);
|
||
strncpy((char *)pfield, pstring,pflddes->size);
|
||
if((pflddes->special == SPC_CALC) && !stringHasMacro) {
|
||
char rpcl[RPCL_LEN];
|
||
char *psCalcrpcl = 0;
|
||
short error_number;
|
||
|
||
status = postfix(pstring,rpcl,&error_number);
|
||
if(status) {
|
||
status = sCalcPostfix(pstring,&psCalcrpcl,&error_number);
|
||
free((void *)psCalcrpcl);
|
||
}
|
||
if(status) status = S_dbLib_badField;
|
||
}
|
||
if((short)strlen(pstring) >= pflddes->size) status = S_dbLib_strLen;
|
||
break;
|
||
case DBF_CHAR :
|
||
case DBF_SHORT :
|
||
case DBF_LONG:
|
||
case DBF_UCHAR:
|
||
case DBF_USHORT:
|
||
case DBF_ULONG:
|
||
case DBF_ENUM:
|
||
case DBF_FLOAT:
|
||
case DBF_DOUBLE:
|
||
case DBF_MENU:
|
||
status = dbPutStringNum(pdbentry,pstring);
|
||
break;
|
||
case DBF_DEVICE: {
|
||
DBENTRY dbEntry;
|
||
char *name;
|
||
|
||
status = dbPutStringNum(pdbentry,pstring);
|
||
if(status) return(status);
|
||
name = dbGetRelatedField(pdbentry);
|
||
if(!name) return(0);
|
||
dbCopyEntryContents(pdbentry,&dbEntry);
|
||
status = dbFindField(&dbEntry,name);
|
||
if(!status) status = setLinkType(&dbEntry);
|
||
dbFinishEntry(&dbEntry);
|
||
return(status);
|
||
}
|
||
case DBF_INLINK:
|
||
case DBF_OUTLINK:
|
||
case DBF_FWDLINK: {
|
||
DBLINK *plink;
|
||
char string[80];
|
||
char *pstr=&string[0];
|
||
int ind;
|
||
|
||
if(!pfield) return(S_dbLib_fieldNotFound);
|
||
plink = (DBLINK *)pfield;
|
||
dbFreeLinkContents(plink);
|
||
if(!stringHasMacro &&(strcmp(pflddes->name,"INP")==0
|
||
|| strcmp(pflddes->name,"OUT")==0)){
|
||
status = setLinkType(pdbentry);
|
||
if(status) {
|
||
errMessage(status,"in dbPutString from setLinkType");
|
||
return(status);
|
||
}
|
||
}
|
||
if(stringHasMacro) {
|
||
plink->type = MACRO_LINK;
|
||
plink->value.macro_link.macroStr =
|
||
dbCalloc(strlen(pstring)+1,sizeof(char));
|
||
strcpy(plink->value.macro_link.macroStr,pstring);
|
||
goto done;
|
||
}
|
||
if(strlen(pstring)>=sizeof(string)) {
|
||
status = S_dbLib_badField;
|
||
errMessage(status,
|
||
"dbPutString received a string that is too long");
|
||
return(status);
|
||
}
|
||
strcpy(pstr,pstring);
|
||
/*strip off leading blanks and tabs*/
|
||
while(*pstr && (*pstr==' ' || *pstr=='\t')) pstr++;
|
||
/*strip off trailing blanks and tabs*/
|
||
if(pstr) for(ind = strlen(pstr)-1; ind>=0; ind--) {
|
||
if(pstr[ind]!=' ' && pstr[ind]!='\t') break;
|
||
pstr[ind] = '\0';
|
||
}
|
||
if(!pstr || (int)strlen(pstr)<=0 ) {
|
||
if(plink->type==PV_LINK) dbCvtLinkToConstant(pdbentry);
|
||
if(plink->type!=CONSTANT) return(S_dbLib_badField);
|
||
free((void *)plink->value.constantStr);
|
||
plink->value.constantStr = NULL;
|
||
goto done;
|
||
}
|
||
switch(plink->type) {
|
||
case CONSTANT:
|
||
case PV_LINK: {
|
||
short ppOpt = 0;
|
||
short msOpt = 0;
|
||
char *end;
|
||
double tempval;
|
||
|
||
/* Check first to see if string is a constant*/
|
||
/*It is a double if strtod eats entire string*/
|
||
/*leading and trailing blanks have already been stripped*/
|
||
tempval = strtod(pstr,&end);
|
||
if(*end == 0) {
|
||
if(plink->type==PV_LINK) dbCvtLinkToConstant(pdbentry);
|
||
if((!plink->value.constantStr) ||
|
||
((int)strlen(plink->value.constantStr)<(int)strlen(pstr)
|
||
)) {
|
||
free(plink->value.constantStr);
|
||
plink->value.constantStr =
|
||
dbCalloc(strlen(pstr)+1,sizeof(char));
|
||
}
|
||
strcpy(plink->value.constantStr,pstr);
|
||
goto done;
|
||
}
|
||
if(plink->type==CONSTANT) dbCvtLinkToPvlink(pdbentry);
|
||
end = strchr(pstr,' ');
|
||
if(end) {
|
||
switch (pflddes->field_type) {
|
||
case DBF_INLINK: {
|
||
if(strstr(end,"NPP")) ppOpt = 0;
|
||
else if(strstr(end,"CPP")) ppOpt = pvlOptCPP;
|
||
else if(strstr(end,"PP")) ppOpt = pvlOptPP;
|
||
else if(strstr(end,"CA")) ppOpt = pvlOptCA;
|
||
else if(strstr(end,"CP")) ppOpt = pvlOptCP;
|
||
else ppOpt = 0;
|
||
if(strstr(end,"NMS")) msOpt = 0;
|
||
else if(strstr(end,"MS")) msOpt = pvlOptMS;
|
||
else msOpt = 0;
|
||
*end = 0;
|
||
}
|
||
break;
|
||
case DBF_OUTLINK: {
|
||
if(strstr(end,"NPP")) ppOpt = 0;
|
||
else if(strstr(end,"PP")) ppOpt = pvlOptPP;
|
||
else if(strstr(end,"CA")) ppOpt = pvlOptCA;
|
||
else ppOpt = 0;
|
||
if(strstr(end,"NMS")) msOpt = 0;
|
||
else if(strstr(end,"MS")) msOpt = pvlOptMS;
|
||
else msOpt = 0;
|
||
*end = 0;
|
||
}
|
||
break;
|
||
case DBF_FWDLINK: {
|
||
if(strstr(end,"NPP")) ppOpt = 0;
|
||
else if(strstr(end,"CA")) ppOpt = pvlOptCA;
|
||
else ppOpt = 0;
|
||
msOpt = 0;
|
||
*end = 0;
|
||
}
|
||
break;
|
||
default:
|
||
epicsPrintf("dbPutString: Logic Error\n");
|
||
}
|
||
}
|
||
status = putPvLink(pdbentry,ppOpt|msOpt,pstr);
|
||
goto done;
|
||
}
|
||
/*break; is unnecessary*/
|
||
case VME_IO: {
|
||
char *end;
|
||
|
||
if(!(end = strchr(pstr,'#'))) return (S_dbLib_badField);
|
||
pstr = end + 1;
|
||
if(!(end = strchr(pstr,'C'))) return (S_dbLib_badField);
|
||
pstr = end + 1;
|
||
sscanf(pstr,"%hd",&plink->value.vmeio.card);
|
||
if(!(end = strchr(pstr,'S'))) return (S_dbLib_badField);
|
||
pstr = end + 1;
|
||
sscanf(pstr,"%hd",&plink->value.vmeio.signal);
|
||
status = putParmString(&plink->value.vmeio.parm,pstr);
|
||
}
|
||
break;
|
||
case CAMAC_IO: {
|
||
char *end;
|
||
|
||
if(!(end = strchr(pstr,'#'))) return (S_dbLib_badField);
|
||
pstr = end + 1;
|
||
if(!(end = strchr(pstr,'B'))) return (S_dbLib_badField);
|
||
pstr = end + 1;
|
||
sscanf(pstr,"%hd",&plink->value.camacio.b);
|
||
if(!(end = strchr(pstr,'C'))) return (S_dbLib_badField);
|
||
pstr = end + 1;
|
||
sscanf(pstr,"%hd",&plink->value.camacio.c);
|
||
if(!(end = strchr(pstr,'N'))) return (S_dbLib_badField);
|
||
pstr = end + 1;
|
||
sscanf(pstr,"%hd",&plink->value.camacio.n);
|
||
if(!(end = strchr(pstr,'A'))) {
|
||
plink->value.camacio.a = 0;
|
||
} else {
|
||
pstr = end + 1;
|
||
sscanf(pstr,"%hd",&plink->value.camacio.a);
|
||
}
|
||
if(!(end = strchr(pstr,'F'))) {
|
||
plink->value.camacio.f = 0;
|
||
} else {
|
||
pstr = end + 1;
|
||
sscanf(pstr,"%hd",&plink->value.camacio.f);
|
||
}
|
||
status = putParmString(&plink->value.camacio.parm,pstr);
|
||
}
|
||
break;
|
||
case RF_IO: {
|
||
char *end;
|
||
|
||
if(!(end = strchr(pstr,'#'))) return (S_dbLib_badField);
|
||
pstr = end + 1;
|
||
if(!(end = strchr(pstr,'R'))) return (S_dbLib_badField);
|
||
pstr = end + 1;
|
||
sscanf(pstr,"%hd",&plink->value.rfio.cryo);
|
||
if(!(end = strchr(pstr,'M'))) return (S_dbLib_badField);
|
||
pstr = end + 1;
|
||
sscanf(pstr,"%hd",&plink->value.rfio.micro);
|
||
if(!(end = strchr(pstr,'D'))) return (S_dbLib_badField);
|
||
pstr = end + 1;
|
||
sscanf(pstr,"%hd",&plink->value.rfio.dataset);
|
||
if(!(end = strchr(pstr,'E'))) return (S_dbLib_badField);
|
||
pstr = end + 1;
|
||
sscanf(pstr,"%hd",&plink->value.rfio.element);
|
||
}
|
||
break;
|
||
case AB_IO: {
|
||
char *end;
|
||
|
||
if(!(end = strchr(pstr,'#'))) return (S_dbLib_badField);
|
||
pstr = end + 1;
|
||
if(!(end = strchr(pstr,'L'))) return (S_dbLib_badField);
|
||
pstr = end + 1;
|
||
sscanf(pstr,"%hd",&plink->value.abio.link);
|
||
if(!(end = strchr(pstr,'A'))) return (S_dbLib_badField);
|
||
pstr = end + 1;
|
||
sscanf(pstr,"%hd",&plink->value.abio.adapter);
|
||
if(!(end = strchr(pstr,'C'))) return (S_dbLib_badField);
|
||
pstr = end + 1;
|
||
sscanf(pstr,"%hd",&plink->value.abio.card);
|
||
if(!(end = strchr(pstr,'S'))) return (S_dbLib_badField);
|
||
pstr = end + 1;
|
||
sscanf(pstr,"%hd",&plink->value.abio.signal);
|
||
status = putParmString(&plink->value.abio.parm,pstr);
|
||
}
|
||
break;
|
||
case GPIB_IO: {
|
||
char *end;
|
||
|
||
if(!(end = strchr(pstr,'#'))) return (S_dbLib_badField);
|
||
pstr = end + 1;
|
||
if(!(end = strchr(pstr,'L'))) return (S_dbLib_badField);
|
||
pstr = end + 1;
|
||
sscanf(pstr,"%hd",&plink->value.gpibio.link);
|
||
if(!(end = strchr(pstr,'A'))) return (S_dbLib_badField);
|
||
pstr = end + 1;
|
||
sscanf(pstr,"%hd",&plink->value.gpibio.addr);
|
||
status = putParmString(&plink->value.gpibio.parm,pstr);
|
||
}
|
||
break;
|
||
case BITBUS_IO: {
|
||
/* jbk - the bbgpib struct uses unsigned char's instead
|
||
of short, so read values into short and then convert */
|
||
|
||
char *end;
|
||
short tmp_val;
|
||
|
||
if(!(end = strchr(pstr,'#'))) return (S_dbLib_badField);
|
||
pstr = end + 1;
|
||
if(!(end = strchr(pstr,'L'))) return (S_dbLib_badField);
|
||
pstr = end + 1;
|
||
sscanf(pstr,"%hd",&tmp_val);
|
||
plink->value.bitbusio.link=(unsigned char)tmp_val;
|
||
if(!(end = strchr(pstr,'N'))) return (S_dbLib_badField);
|
||
pstr = end + 1;
|
||
sscanf(pstr,"%hd",&tmp_val);
|
||
plink->value.bitbusio.node=(unsigned char)tmp_val;
|
||
if(!(end = strchr(pstr,'P'))) return (S_dbLib_badField);
|
||
pstr = end + 1;
|
||
sscanf(pstr,"%hd",&tmp_val);
|
||
plink->value.bitbusio.port=(unsigned char)tmp_val;
|
||
if(!(end = strchr(pstr,'S'))) return (S_dbLib_badField);
|
||
pstr = end + 1;
|
||
sscanf(pstr,"%hd",&tmp_val);
|
||
plink->value.bitbusio.signal=(unsigned char)tmp_val;
|
||
status = putParmString(&plink->value.bitbusio.parm,pstr);
|
||
}
|
||
break;
|
||
case BBGPIB_IO: {
|
||
/* jbk - the bbgpib struct uses unsigned char's instead
|
||
of short, so read values into short and then convert */
|
||
|
||
char *end;
|
||
short tmp_val;
|
||
|
||
if(!(end = strchr(pstr,'#'))) return (S_dbLib_badField);
|
||
pstr = end + 1;
|
||
if(!(end = strchr(pstr,'L'))) return (S_dbLib_badField);
|
||
pstr = end + 1;
|
||
sscanf(pstr,"%hd",&tmp_val);
|
||
plink->value.bbgpibio.link=(unsigned char)tmp_val;
|
||
if(!(end = strchr(pstr,'B'))) return (S_dbLib_badField);
|
||
pstr = end + 1;
|
||
sscanf(pstr,"%hd",&tmp_val);
|
||
plink->value.bbgpibio.bbaddr=(unsigned char)tmp_val;
|
||
if(!(end = strchr(pstr,'G'))) return (S_dbLib_badField);
|
||
pstr = end + 1;
|
||
sscanf(pstr,"%hd",&tmp_val);
|
||
plink->value.bbgpibio.gpibaddr=tmp_val;
|
||
status = putParmString(&plink->value.bbgpibio.parm,pstr);
|
||
}
|
||
break;
|
||
case VXI_IO: {
|
||
char *end;
|
||
|
||
if(!(end = strchr(pstr,'#'))) return (S_dbLib_badField);
|
||
pstr = end + 1;
|
||
memset((char *)&plink->value.vxiio,0,sizeof(struct vxiio));
|
||
plink->value.vxiio.parm = pNullString;
|
||
if(!((end = strchr(pstr,'C'))&&(end < strchr(pstr,'@')) )) {
|
||
plink->value.vxiio.flag = VXISTATIC;
|
||
if(!(end = strchr(pstr,'V'))) return (S_dbLib_badField);
|
||
pstr = end + 1;
|
||
sscanf(pstr,"%hd",&plink->value.vxiio.la);
|
||
} else {
|
||
plink->value.vxiio.flag = VXIDYNAMIC;
|
||
if(!(end = strchr(pstr,'V'))) return (S_dbLib_badField);
|
||
pstr = end + 1;
|
||
sscanf(pstr,"%hd",&plink->value.vxiio.frame);
|
||
if(!(end = strchr(pstr,'C'))) return (S_dbLib_badField);
|
||
pstr = end + 1;
|
||
sscanf(pstr,"%hd",&plink->value.vxiio.slot);
|
||
}
|
||
if((end = strchr(pstr,'S'))) {
|
||
pstr = end + 1;
|
||
sscanf(pstr,"%hd",&plink->value.vxiio.signal);
|
||
} else {
|
||
plink->value.vxiio.signal = 0;
|
||
}
|
||
status = putParmString(&plink->value.vxiio.parm,pstr);
|
||
}
|
||
break;
|
||
case INST_IO: {
|
||
status = putParmString(&plink->value.instio.string,pstr);
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
break;
|
||
default:
|
||
return (S_dbLib_badField);
|
||
}
|
||
done:
|
||
if(!status && strcmp(pflddes->name,"VAL")==0) {
|
||
DBENTRY dbentry;
|
||
|
||
dbCopyEntryContents(pdbentry,&dbentry);
|
||
if(!dbFindField(&dbentry,"UDF")) {
|
||
dbPutString(&dbentry,"0");
|
||
}
|
||
dbFinishEntry(&dbentry);
|
||
}
|
||
return(status);
|
||
}
|
||
|
||
char * epicsShareAPI dbVerify(DBENTRY *pdbentry,const char *pstring)
|
||
{
|
||
dbFldDes *pflddes = pdbentry->pflddes;
|
||
char *message;
|
||
int stringHasMacro=FALSE;
|
||
|
||
stringHasMacro = (strstr(pstring,"$(") || strstr(pstring,"${"))?TRUE:FALSE;
|
||
message = getpMessage(pdbentry);
|
||
*message = 0;
|
||
if(!pflddes) {strcpy(message,"fldDes not found"); return(message);}
|
||
if(strstr(pstring,"$(") || strstr(pstring,"${")) return(NULL);
|
||
switch (pflddes->field_type) {
|
||
case DBF_STRING: {
|
||
unsigned int length;
|
||
|
||
length=strlen(pstring);
|
||
if(length>=pflddes->size) {
|
||
sprintf(message,"string to big. max=%hd",pflddes->size);
|
||
return(message);
|
||
}
|
||
if((pflddes->special == SPC_CALC) && !stringHasMacro) {
|
||
char rpcl[RPCL_LEN];
|
||
char *psCalcrpcl = 0;
|
||
short error_number;
|
||
long status;
|
||
|
||
status = postfix(pstring,rpcl,&error_number);
|
||
if(status) {
|
||
status = sCalcPostfix(pstring,&psCalcrpcl,&error_number);
|
||
free((void *)psCalcrpcl);
|
||
}
|
||
if(status) {
|
||
sprintf(message,"Illegal Calculation String");
|
||
return(message);
|
||
}
|
||
}
|
||
}
|
||
return(NULL);
|
||
case DBF_CHAR :
|
||
case DBF_SHORT :
|
||
case DBF_LONG:{
|
||
long value;
|
||
char *endp;
|
||
|
||
value = strtol(pstring,&endp,0);
|
||
if(*endp!=0) {
|
||
strcpy(message,"not an integer number");
|
||
return(message);
|
||
}
|
||
switch (pflddes->field_type) {
|
||
case DBF_CHAR :
|
||
if(value<-128 || value>127) {
|
||
strcpy(message,"must have -128<=value<=127");
|
||
return(message);
|
||
}
|
||
return(NULL);
|
||
case DBF_SHORT :
|
||
if(value<-32768 || value>32767) {
|
||
strcpy(message,"must have -32768<=value<=32767");
|
||
return(message);
|
||
}
|
||
return(NULL);
|
||
case DBF_LONG : return(NULL);
|
||
default:
|
||
errPrintf(-1,__FILE__, __LINE__,"Logic Error\n");
|
||
return(NULL);
|
||
}
|
||
}
|
||
case DBF_UCHAR:
|
||
case DBF_USHORT:
|
||
case DBF_ULONG:
|
||
case DBF_ENUM:{
|
||
unsigned long value;
|
||
char *endp;
|
||
|
||
if(strchr(pstring,'-')) {
|
||
strcpy(message,"not an unsigned number");
|
||
return(message);
|
||
}
|
||
value = strtoul(pstring,&endp,0);
|
||
if(*endp!=0) {
|
||
strcpy(message,"not an integer number");
|
||
return(message);
|
||
}
|
||
switch (pflddes->field_type) {
|
||
case DBF_UCHAR :
|
||
if(value>255) {
|
||
strcpy(message,"must have 0<=value<=255");
|
||
return(message);
|
||
}
|
||
return(NULL);
|
||
case DBF_ENUM:
|
||
case DBF_USHORT :
|
||
if(value>65535) {
|
||
strcpy(message,"must have 0<=value<=65535");
|
||
return(message);
|
||
}
|
||
return(NULL);
|
||
case DBF_ULONG : return(NULL);
|
||
default:
|
||
errPrintf(-1,__FILE__, __LINE__,"Logic Error\n");
|
||
return(NULL);
|
||
}
|
||
}
|
||
case DBF_FLOAT:
|
||
case DBF_DOUBLE: {
|
||
double value;
|
||
char *endp;
|
||
|
||
value = strtod(pstring,&endp);
|
||
if(*endp!=0) {
|
||
strcpy(message,"not a number");
|
||
return(message);
|
||
}
|
||
return(NULL);
|
||
}
|
||
case DBF_MENU: {
|
||
dbMenu *pdbMenu = (dbMenu *)pflddes->ftPvt;
|
||
char *pchoice;
|
||
int i;
|
||
|
||
if(!pdbMenu) return(NULL);
|
||
for (i = 0; i < pdbMenu->nChoice; i++) {
|
||
if(!(pchoice = pdbMenu->papChoiceValue[i])) continue;
|
||
if(strcmp(pchoice, pstring) == 0) {
|
||
return(NULL);
|
||
}
|
||
}
|
||
}
|
||
strcpy(message,"Not a valid menu choice");
|
||
return (message);
|
||
case DBF_DEVICE: {
|
||
dbDeviceMenu *pdbDeviceMenu;
|
||
char *pchoice;
|
||
int i;
|
||
|
||
pdbDeviceMenu = dbGetDeviceMenu(pdbentry);
|
||
if(!pdbDeviceMenu) return(NULL);
|
||
if(pdbDeviceMenu->nChoice == 0) return(NULL);
|
||
for (i = 0; i < pdbDeviceMenu->nChoice; i++) {
|
||
if (!(pchoice = pdbDeviceMenu->papChoice[i]))
|
||
continue;
|
||
if (strcmp(pchoice, pstring) == 0) {
|
||
return(NULL);
|
||
}
|
||
}
|
||
}
|
||
strcpy(message,"Not a valid menu choice");
|
||
return (message);
|
||
case DBF_INLINK:
|
||
case DBF_OUTLINK:
|
||
case DBF_FWDLINK:
|
||
return(NULL);
|
||
default: break;
|
||
}
|
||
strcpy(message,"Not a valid field type");
|
||
return (message);
|
||
}
|
||
|
||
char *epicsShareAPI dbGetRange(DBENTRY *pdbentry)
|
||
{
|
||
dbFldDes *pflddes = pdbentry->pflddes;
|
||
char *message;
|
||
|
||
message = getpMessage(pdbentry);
|
||
*message = 0;
|
||
if(!pflddes) {strcpy(message,"fldDes not found"); return(message);}
|
||
switch (pflddes->field_type) {
|
||
case DBF_STRING: {strcpy(message,"STRING"); return(message);}
|
||
case DBF_CHAR : {strcpy(message,"CHAR"); return(message);}
|
||
case DBF_SHORT : {strcpy(message,"SHORT");return(message);}
|
||
case DBF_LONG: {strcpy(message,"LONG"); return(message);}
|
||
case DBF_UCHAR: {strcpy(message,"UCHAR");return(message);}
|
||
case DBF_USHORT:{strcpy(message,"USHORT");return(message);}
|
||
case DBF_ULONG:{strcpy(message,"ULONG:");return(message);}
|
||
case DBF_ENUM: {strcpy(message,"ENUM");return(message);}
|
||
case DBF_FLOAT: {strcpy(message,"FLOAT");return(message);}
|
||
case DBF_DOUBLE: {strcpy(message,"DOUBLE");return(message);}
|
||
case DBF_MENU: {strcpy(message,"MENU");return(message);}
|
||
case DBF_DEVICE: {strcpy(message,"DEVICE");return(message);}
|
||
case DBF_INLINK: {strcpy(message,"INLINK");return(message);}
|
||
case DBF_OUTLINK: {strcpy(message,"OUTLINK");return(message);}
|
||
case DBF_FWDLINK: {strcpy(message,"FWDLINK");return(message);}
|
||
default:
|
||
errPrintf(-1,__FILE__, __LINE__,"Logic Error\n");
|
||
}
|
||
strcpy(message,"Not a valid field type");
|
||
return (message);
|
||
}
|
||
|
||
long epicsShareAPI dbFirstInfo(DBENTRY *pdbentry)
|
||
{
|
||
dbRecordNode *precnode = pdbentry->precnode;
|
||
|
||
pdbentry->pinfonode = NULL;
|
||
if (!precnode) return (S_dbLib_recNotFound);
|
||
|
||
pdbentry->pinfonode = (dbInfoNode *)ellFirst(&precnode->infoList);
|
||
return (pdbentry->pinfonode ? 0 : S_dbLib_infoNotFound);
|
||
}
|
||
|
||
long epicsShareAPI dbNextInfo(DBENTRY *pdbentry)
|
||
{
|
||
dbRecordNode *precnode = pdbentry->precnode;
|
||
dbInfoNode *pinfo;
|
||
|
||
if (!precnode) return (S_dbLib_recNotFound);
|
||
pinfo = pdbentry->pinfonode;
|
||
if (!pinfo) return (S_dbLib_infoNotFound);
|
||
|
||
pinfo = (dbInfoNode *)ellNext(&pinfo->node);
|
||
pdbentry->pinfonode = pinfo;
|
||
return (pinfo ? 0 : S_dbLib_infoNotFound);
|
||
}
|
||
|
||
long epicsShareAPI dbFindInfo(DBENTRY *pdbentry,const char *name)
|
||
{
|
||
dbRecordNode *precnode = pdbentry->precnode;
|
||
dbInfoNode *pinfo;
|
||
|
||
pdbentry->pinfonode = NULL;
|
||
if (!precnode) return(S_dbLib_recNotFound);
|
||
|
||
pinfo = (dbInfoNode *)ellFirst(&precnode->infoList);
|
||
while (pinfo) {
|
||
if (!strcmp(pinfo->name, name)) {
|
||
pdbentry->pinfonode = pinfo;
|
||
return (0);
|
||
}
|
||
pinfo = (dbInfoNode *)ellNext(&pinfo->node);
|
||
}
|
||
return (S_dbLib_infoNotFound);
|
||
}
|
||
|
||
long epicsShareAPI dbDeleteInfo(DBENTRY *pdbentry)
|
||
{
|
||
dbRecordNode *precnode = pdbentry->precnode;
|
||
dbInfoNode *pinfo = pdbentry->pinfonode;
|
||
|
||
if (!precnode) return (S_dbLib_recNotFound);
|
||
if (!pinfo) return (S_dbLib_infoNotFound);
|
||
ellDelete(&precnode->infoList,&pinfo->node);
|
||
free(pinfo->name);
|
||
free(pinfo->string);
|
||
free(pinfo);
|
||
pdbentry->pinfonode = NULL;
|
||
return (0);
|
||
}
|
||
|
||
const char * epicsShareAPI dbGetInfoName(DBENTRY *pdbentry)
|
||
{
|
||
dbInfoNode *pinfo = pdbentry->pinfonode;
|
||
if (!pinfo) return (NULL);
|
||
return (pinfo->name);
|
||
}
|
||
|
||
const char * epicsShareAPI dbGetInfoString(DBENTRY *pdbentry)
|
||
{
|
||
dbInfoNode *pinfo = pdbentry->pinfonode;
|
||
if (!pinfo) return (NULL);
|
||
return (pinfo->string);
|
||
}
|
||
|
||
long epicsShareAPI dbPutInfoString(DBENTRY *pdbentry,const char *string)
|
||
{
|
||
dbInfoNode *pinfo = pdbentry->pinfonode;
|
||
char *newstring;
|
||
if (!pinfo) return (S_dbLib_infoNotFound);
|
||
newstring = realloc(pinfo->string,1+strlen(string));
|
||
if (!newstring) return (S_dbLib_outMem);
|
||
strcpy(newstring, string);
|
||
pinfo->string = newstring;
|
||
return (0);
|
||
}
|
||
|
||
long epicsShareAPI dbPutInfoPointer(DBENTRY *pdbentry, void *pointer)
|
||
{
|
||
dbInfoNode *pinfo = pdbentry->pinfonode;
|
||
if (!pinfo) return (S_dbLib_infoNotFound);
|
||
pinfo->pointer = pointer;
|
||
return (0);
|
||
}
|
||
|
||
const char * epicsShareAPI dbGetInfoPointer(DBENTRY *pdbentry)
|
||
{
|
||
dbInfoNode *pinfo = pdbentry->pinfonode;
|
||
if (!pinfo) return (NULL);
|
||
return (pinfo->pointer);
|
||
}
|
||
|
||
const char * epicsShareAPI dbGetInfo(DBENTRY *pdbentry,const char *name)
|
||
{
|
||
dbFindInfo(pdbentry, name);
|
||
return (dbGetInfoString(pdbentry));
|
||
}
|
||
|
||
long epicsShareAPI dbPutInfo(DBENTRY *pdbentry,const char *name,const char *string)
|
||
{
|
||
dbInfoNode *pinfo;
|
||
dbRecordNode *precnode = pdbentry->precnode;
|
||
if (!precnode) return (S_dbLib_recNotFound);
|
||
|
||
dbFindInfo(pdbentry, name);
|
||
pinfo = pdbentry->pinfonode;
|
||
if (pinfo) return (dbPutInfoString(pdbentry, string));
|
||
|
||
/*Create new info node*/
|
||
pinfo = calloc(1,sizeof(dbInfoNode));
|
||
if (!pinfo) return (S_dbLib_outMem);
|
||
pinfo->name = calloc(1,1+strlen(name));
|
||
if (!pinfo->name) {
|
||
free(pinfo);
|
||
return (S_dbLib_outMem);
|
||
}
|
||
strcpy(pinfo->name, name);
|
||
pinfo->string = calloc(1,1+strlen(string));
|
||
if (!pinfo->string) {
|
||
free(pinfo->name);
|
||
free(pinfo);
|
||
return (S_dbLib_outMem);
|
||
}
|
||
strcpy(pinfo->string, string);
|
||
ellAdd(&precnode->infoList,&pinfo->node);
|
||
pdbentry->pinfonode = pinfo;
|
||
return (0);
|
||
}
|
||
|
||
brkTable * epicsShareAPI dbFindBrkTable(dbBase *pdbbase,const char *name)
|
||
{
|
||
GPHENTRY *pgph;
|
||
|
||
pgph = gphFind(pdbbase->pgpHash,name,(void *)&pdbbase->bptList);
|
||
if(!pgph) return(NULL);
|
||
return((brkTable *)pgph->userPvt);
|
||
}
|
||
|
||
dbMenu * epicsShareAPI dbFindMenu(dbBase *pdbbase,const char *name)
|
||
{
|
||
GPHENTRY *pgph;
|
||
|
||
pgph = gphFind(pdbbase->pgpHash,name,(void *)&pdbbase->menuList);
|
||
if(!pgph) return(NULL);
|
||
return((dbMenu *)pgph->userPvt);
|
||
}
|
||
|
||
char ** epicsShareAPI dbGetMenuChoices(DBENTRY *pdbentry)
|
||
{
|
||
dbFldDes *pflddes = pdbentry->pflddes;
|
||
|
||
if(!pflddes) return(NULL);
|
||
switch (pflddes->field_type) {
|
||
case DBF_MENU: {
|
||
dbMenu *pdbMenu = (dbMenu *)pflddes->ftPvt;
|
||
|
||
if(!pdbMenu) return(NULL);
|
||
return(pdbMenu->papChoiceValue);
|
||
}
|
||
case DBF_DEVICE: {
|
||
dbDeviceMenu *pdbDeviceMenu;
|
||
|
||
pdbDeviceMenu = dbGetDeviceMenu(pdbentry);
|
||
if(!pdbDeviceMenu) return(NULL);
|
||
return(pdbDeviceMenu->papChoice);
|
||
}
|
||
default:
|
||
return(NULL);
|
||
}
|
||
}
|
||
|
||
int epicsShareAPI dbGetNMenuChoices(DBENTRY *pdbentry)
|
||
{
|
||
dbFldDes *pflddes = pdbentry->pflddes;
|
||
|
||
if(!pflddes) return(-1);
|
||
switch (pflddes->field_type) {
|
||
case DBF_MENU: {
|
||
dbMenu *pdbMenu = (dbMenu *)pflddes->ftPvt;
|
||
|
||
if(!pdbMenu) return(0);
|
||
return(pdbMenu->nChoice);
|
||
}
|
||
case DBF_DEVICE: {
|
||
dbDeviceMenu *pdbDeviceMenu;
|
||
|
||
pdbDeviceMenu = dbGetDeviceMenu(pdbentry);
|
||
if(!pdbDeviceMenu) return(0);
|
||
return(pdbDeviceMenu->nChoice);
|
||
}
|
||
default:
|
||
break;
|
||
}
|
||
return (-1);
|
||
}
|
||
|
||
char * epicsShareAPI dbGetMenuStringFromIndex(DBENTRY *pdbentry, int index)
|
||
{
|
||
dbFldDes *pflddes = pdbentry->pflddes;
|
||
|
||
if(!pflddes) return(NULL);
|
||
switch (pflddes->field_type) {
|
||
case DBF_MENU: {
|
||
dbMenu *pdbMenu = (dbMenu *)pflddes->ftPvt;
|
||
|
||
if(!pdbMenu) return(NULL);
|
||
if(index<0 || index>=pdbMenu->nChoice) return(NULL);
|
||
return(pdbMenu->papChoiceValue[index]);
|
||
}
|
||
case DBF_DEVICE: {
|
||
dbDeviceMenu *pdbDeviceMenu;
|
||
|
||
pdbDeviceMenu = dbGetDeviceMenu(pdbentry);
|
||
if(!pdbDeviceMenu) return(NULL);
|
||
if(index<0 || index>=pdbDeviceMenu->nChoice) return(NULL);
|
||
return(pdbDeviceMenu->papChoice[index]);
|
||
}
|
||
default:
|
||
break;
|
||
}
|
||
return (NULL);
|
||
}
|
||
|
||
int epicsShareAPI dbGetMenuIndexFromString(DBENTRY *pdbentry, const char *choice)
|
||
{
|
||
dbFldDes *pflddes = pdbentry->pflddes;
|
||
int ind;
|
||
int nChoice = 0;
|
||
char **papChoice = NULL;
|
||
|
||
if(!pflddes) return(-1);
|
||
switch (pflddes->field_type) {
|
||
case DBF_MENU: {
|
||
dbMenu *pdbMenu = (dbMenu *)pflddes->ftPvt;
|
||
|
||
if(!pdbMenu) return(-1);
|
||
papChoice = pdbMenu->papChoiceValue;
|
||
nChoice = pdbMenu->nChoice;
|
||
break;
|
||
}
|
||
case DBF_DEVICE: {
|
||
dbDeviceMenu *pdbDeviceMenu;
|
||
|
||
pdbDeviceMenu = dbGetDeviceMenu(pdbentry);
|
||
if(!pdbDeviceMenu) return(-1);
|
||
papChoice = pdbDeviceMenu->papChoice;
|
||
nChoice = pdbDeviceMenu->nChoice;
|
||
break;
|
||
}
|
||
default:
|
||
return(-1);
|
||
}
|
||
if(nChoice<=0 || !papChoice) return(-1);
|
||
for(ind=0; ind<nChoice; ind++) {
|
||
if(strcmp(choice,papChoice[ind])==0) return(ind);
|
||
}
|
||
return (-1);
|
||
}
|
||
|
||
int epicsShareAPI dbAllocForm(DBENTRY *psave)
|
||
{
|
||
DBENTRY dbEntry;
|
||
DBENTRY *pdbentry= &dbEntry;
|
||
dbFldDes *pflddes;
|
||
DBLINK *plink;
|
||
int nlines=0;
|
||
char *pstr;
|
||
struct form *pform;
|
||
int linkType;
|
||
long status = 0;
|
||
int nbytes,i;
|
||
|
||
if(psave->formpvt) {
|
||
status = dbFreeForm(psave);
|
||
if(status) return(status);
|
||
}
|
||
dbCopyEntryContents(psave,pdbentry);
|
||
pflddes = pdbentry->pflddes;
|
||
if(!pflddes) {
|
||
epicsPrintf("dbAllocForm called but no field is referenced\n");
|
||
goto done;
|
||
}
|
||
if(pflddes->field_type == DBF_DEVICE) {
|
||
status = dbFindField(pdbentry,"INP");
|
||
if(status) status = dbFindField(pdbentry,"OUT");
|
||
if(status) goto done;
|
||
pflddes = pdbentry->pflddes;
|
||
} else {
|
||
if((pflddes->field_type!=DBF_INLINK)
|
||
&& (pflddes->field_type!=DBF_OUTLINK)
|
||
&& (pflddes->field_type!=DBF_FWDLINK)) {
|
||
epicsPrintf("dbAllocForm called but not DBF_DEVICE or DBF_xxxLINK\n");
|
||
goto done;
|
||
}
|
||
plink = (DBLINK *)(pdbentry->pfield);
|
||
if(plink->type==MACRO_LINK) goto done;
|
||
if(strcmp(pflddes->name,"INP")==0 || strcmp(pflddes->name,"OUT")==0){
|
||
status = setLinkType(pdbentry);
|
||
if(status) {
|
||
errMessage(status,"in dbAllocForm from setLinkType");
|
||
return(0);
|
||
}
|
||
}
|
||
}
|
||
plink = (DBLINK *)(pdbentry->pfield);
|
||
if(plink->type==MACRO_LINK) goto done;
|
||
status = mapLINKTtoFORMT(plink,pflddes,&linkType);
|
||
if(status) goto done;
|
||
nlines = formlines[linkType];
|
||
/*Dont know how to handle string size. Just use messagesize*/
|
||
nbytes = sizeof(struct form) + 2*nlines*(sizeof(char *) + messagesize);
|
||
pform = dbCalloc(1,nbytes);
|
||
pform->nlines = nlines;
|
||
pform->linkType = linkType;
|
||
psave->formpvt = pform;
|
||
pform->plink = plink ;
|
||
pform->prompt = promptAddr[linkType];
|
||
pform->value = (char **)((char *)pform + sizeof(struct form));
|
||
pform->verify = (char **)((char *)(pform->value)+nlines*sizeof(char *));
|
||
pstr = (char *)(pform->verify) + nlines*sizeof(char *);
|
||
for(i=0; i<nlines; i++) {
|
||
pform->value[i] = pstr;
|
||
pstr += messagesize;
|
||
}
|
||
for(i=0; i<nlines; i++) {
|
||
pform->verify[i] = pstr;
|
||
pstr += messagesize;
|
||
}
|
||
done:
|
||
dbFinishEntry(pdbentry);
|
||
return(nlines);
|
||
}
|
||
|
||
long epicsShareAPI dbFreeForm(DBENTRY *pdbentry)
|
||
{
|
||
if(pdbentry->formpvt) {
|
||
free(pdbentry->formpvt);
|
||
pdbentry->formpvt = NULL;
|
||
}
|
||
return(0);
|
||
}
|
||
|
||
char ** epicsShareAPI dbGetFormPrompt(DBENTRY *pdbentry)
|
||
{
|
||
struct form *pform = pdbentry->formpvt;
|
||
|
||
if(!pform) return(NULL);
|
||
return(pform->prompt);
|
||
}
|
||
|
||
char ** epicsShareAPI dbGetFormValue(DBENTRY *pdbentry)
|
||
{
|
||
struct form *pform = pdbentry->formpvt;
|
||
DBLINK *plink;
|
||
char **value;
|
||
|
||
if(!pform) return(NULL);
|
||
plink = pform->plink;
|
||
if(!plink) return(NULL);
|
||
value = pform->value;
|
||
switch(pform->linkType) {
|
||
case FORM_CONSTANT:
|
||
if(plink->value.constantStr) {
|
||
strcpy(*value,plink->value.constantStr);
|
||
} else {
|
||
strcpy(*value,"");
|
||
}
|
||
break;
|
||
case FORM_INLINK: {
|
||
short pvlMask = plink->value.pv_link.pvlMask;
|
||
|
||
if(plink->value.pv_link.pvname)
|
||
strcpy(*value,plink->value.pv_link.pvname);
|
||
else
|
||
strcpy(*value,"");
|
||
value++;
|
||
if(pvlMask&pvlOptPP) strcpy(*value,"PP");
|
||
else if(pvlMask&pvlOptCA) strcpy(*value,"CA");
|
||
else if(pvlMask&pvlOptCP) strcpy(*value,"CP");
|
||
else if(pvlMask&pvlOptCPP) strcpy(*value,"CPP");
|
||
else strcpy(*value,"NPP");
|
||
value++;
|
||
if(pvlMask&pvlOptMS) strcpy(*value,"MS");
|
||
else strcpy(*value,"NMS");
|
||
value++;
|
||
}
|
||
break;
|
||
case FORM_OUTLINK: {
|
||
short pvlMask = plink->value.pv_link.pvlMask;
|
||
|
||
if(plink->value.pv_link.pvname)
|
||
strcpy(*value,plink->value.pv_link.pvname);
|
||
else
|
||
strcpy(*value,"");
|
||
value++;
|
||
if(pvlMask&pvlOptPP) strcpy(*value,"PP");
|
||
else if(pvlMask&pvlOptCA) strcpy(*value,"CA");
|
||
else strcpy(*value,"NPP");
|
||
value++;
|
||
if(pvlMask&pvlOptMS) strcpy(*value,"MS");
|
||
else strcpy(*value,"NMS");
|
||
value++;
|
||
}
|
||
break;
|
||
case FORM_FWDLINK: {
|
||
short pvlMask = plink->value.pv_link.pvlMask;
|
||
|
||
if(plink->value.pv_link.pvname)
|
||
strcpy(*value,plink->value.pv_link.pvname);
|
||
else
|
||
strcpy(*value,"");
|
||
value++;
|
||
if(pvlMask&pvlOptCA) strcpy(*value,"CA");
|
||
else strcpy(*value,"");
|
||
}
|
||
break;
|
||
case FORM_VME_IO:
|
||
cvtShortToString(plink->value.vmeio.card,*value);
|
||
value++;
|
||
cvtShortToString(plink->value.vmeio.signal,*value);
|
||
value++;
|
||
strcpy(*value,"@");
|
||
strcat(*value,plink->value.vmeio.parm);
|
||
break;
|
||
case FORM_CAMAC_IO:
|
||
cvtShortToString(plink->value.camacio.b,*value);
|
||
value++;
|
||
cvtShortToString(plink->value.camacio.c,*value);
|
||
value++;
|
||
cvtShortToString(plink->value.camacio.n,*value);
|
||
value++;
|
||
cvtShortToString(plink->value.camacio.a,*value);
|
||
value++;
|
||
cvtShortToString(plink->value.camacio.f,*value);
|
||
value++;
|
||
strcpy(*value,"@");
|
||
strcat(*value,plink->value.camacio.parm);
|
||
break;
|
||
case FORM_RF_IO:
|
||
cvtShortToString(plink->value.rfio.cryo,*value);
|
||
value++;
|
||
cvtShortToString(plink->value.rfio.micro,*value);
|
||
value++;
|
||
cvtShortToString(plink->value.rfio.dataset,*value);
|
||
value++;
|
||
cvtShortToString(plink->value.rfio.element,*value);
|
||
break;
|
||
case FORM_AB_IO:
|
||
cvtShortToString(plink->value.abio.link,*value);
|
||
value++;
|
||
cvtShortToString(plink->value.abio.adapter,*value);
|
||
value++;
|
||
cvtShortToString(plink->value.abio.card,*value);
|
||
value++;
|
||
cvtShortToString(plink->value.abio.signal,*value);
|
||
value++;
|
||
strcpy(*value,"@");
|
||
strcat(*value,plink->value.abio.parm);
|
||
break;
|
||
case FORM_GPIB_IO:
|
||
cvtShortToString(plink->value.gpibio.link,*value);
|
||
value++;
|
||
cvtShortToString(plink->value.gpibio.addr,*value);
|
||
value++;
|
||
strcpy(*value,"@");
|
||
strcat(*value,plink->value.gpibio.parm);
|
||
break;
|
||
case FORM_BITBUS_IO:
|
||
cvtCharToString(plink->value.bitbusio.link,*value);
|
||
value++;
|
||
cvtCharToString(plink->value.bitbusio.node,*value);
|
||
value++;
|
||
cvtCharToString(plink->value.bitbusio.port,*value);
|
||
value++;
|
||
cvtCharToString(plink->value.bitbusio.signal,*value);
|
||
value++;
|
||
strcpy(*value,"@");
|
||
strcat(*value,plink->value.bitbusio.parm);
|
||
break;
|
||
case FORM_INST_IO:
|
||
strcpy(*value,"@");
|
||
strcat(*value,plink->value.instio.string);
|
||
break;
|
||
case FORM_BBGPIB_IO:
|
||
cvtCharToString(plink->value.bbgpibio.link,*value);
|
||
value++;
|
||
cvtCharToString(plink->value.bbgpibio.bbaddr,*value);
|
||
value++;
|
||
cvtCharToString(plink->value.bbgpibio.gpibaddr,*value);
|
||
value++;
|
||
strcpy(*value,"@");
|
||
strcat(*value,plink->value.bbgpibio.parm);
|
||
break;
|
||
case FORM_VXI_IO:
|
||
strcpy(*value,(plink->value.vxiio.flag == VXIDYNAMIC ? "Yes" : "No"));
|
||
value++;
|
||
if(plink->value.vxiio.flag == VXIDYNAMIC)
|
||
cvtShortToString(plink->value.vxiio.frame,*value);
|
||
else
|
||
**value = 0;
|
||
value++;
|
||
if(plink->value.vxiio.flag == VXIDYNAMIC)
|
||
cvtShortToString(plink->value.vxiio.slot,*value);
|
||
else
|
||
**value = 0;
|
||
value++;
|
||
if(plink->value.vxiio.flag == VXISTATIC)
|
||
cvtShortToString(plink->value.vxiio.la,*value);
|
||
else
|
||
**value = 0;
|
||
value++;
|
||
cvtShortToString(plink->value.vxiio.signal,*value);
|
||
value++;
|
||
strcpy(*value,"@");
|
||
strcat(*value,plink->value.vxiio.parm);
|
||
break;
|
||
default :
|
||
return(NULL);
|
||
}
|
||
return(pform->value);
|
||
}
|
||
|
||
long epicsShareAPI dbPutForm(DBENTRY *pdbentry,char **value)
|
||
{
|
||
struct form *pform = pdbentry->formpvt;
|
||
DBLINK *plink;
|
||
char **verify;
|
||
long lvalue;
|
||
double dvalue;
|
||
char *endp;
|
||
long status = 0;
|
||
|
||
if(!pform) return(S_dbLib_badLink);
|
||
plink = pform->plink;
|
||
if(!plink) return(S_dbLib_badLink);
|
||
verify = pform->verify;
|
||
switch(pform->linkType) {
|
||
case FORM_CONSTANT:
|
||
**verify = 0; /*Initialize to no error*/
|
||
if(**value == '\0') break;
|
||
dvalue = strtod(*value,&endp);
|
||
if(*endp!=0) {
|
||
strcpy(*verify,"Illegal. Must be number");
|
||
break;
|
||
}
|
||
if((!plink->value.constantStr)
|
||
|| ((int)strlen(plink->value.constantStr)<(int)strlen(*value))) {
|
||
free(plink->value.constantStr);
|
||
plink->value.constantStr = dbCalloc(strlen(*value)+1,sizeof(char));
|
||
}
|
||
strcpy(plink->value.constantStr,*value);
|
||
break;
|
||
case FORM_INLINK: {
|
||
DBENTRY dbEntry;
|
||
DBENTRY *plinkentry = &dbEntry;
|
||
short ppOpt = 0;
|
||
short msOpt = 0;
|
||
const char *pstr;
|
||
|
||
pstr = *value;
|
||
**verify = 0;
|
||
value++; verify++;
|
||
**verify = 0; /*Initialize verify to NULL*/
|
||
if((*value==NULL) || (strcmp(*value,"")==0)) ppOpt = 0;
|
||
else if(strstr(*value,"NPP")) ppOpt = 0;
|
||
else if(strstr(*value,"CPP")) ppOpt = pvlOptCPP;
|
||
else if(strstr(*value,"PP")) ppOpt = pvlOptPP;
|
||
else if(strstr(*value,"CA")) ppOpt = pvlOptCA;
|
||
else if(strstr(*value,"CP")) ppOpt = pvlOptCP;
|
||
else strcpy(*verify,"Illegal. Chose a value");
|
||
value++; verify++;
|
||
**verify = 0; /*Initialize verify to NULL*/
|
||
if((*value==NULL) || (strcmp(*value,"")==0)) msOpt = 0;
|
||
else if(strstr(*value,"NMS")) msOpt = 0;
|
||
else if(strstr(*value,"MS")) msOpt = pvlOptMS;
|
||
else strcpy(*verify,"Illegal. Chose a value");
|
||
dbCopyEntryContents(pdbentry,plinkentry);
|
||
if(pdbentry->pflddes->field_type == DBF_DEVICE) {
|
||
status = dbFindField(plinkentry,"INP");
|
||
if(status) {
|
||
dbFinishEntry(plinkentry);
|
||
return(status);
|
||
}
|
||
}
|
||
putPvLink(plinkentry,ppOpt|msOpt,pstr);
|
||
dbFinishEntry(plinkentry);
|
||
}
|
||
break;
|
||
case FORM_OUTLINK: {
|
||
DBENTRY dbEntry;
|
||
DBENTRY *plinkentry = &dbEntry;
|
||
short ppOpt = 0;
|
||
short msOpt = 0;
|
||
const char *pstr;
|
||
|
||
pstr = *value;
|
||
**verify = 0;
|
||
value++; verify++;
|
||
**verify = 0; /*Initialize verify to NULL*/
|
||
if((*value==NULL) || (strcmp(*value,"")==0)) ppOpt = 0;
|
||
else if(strstr(*value,"NPP")) ppOpt = 0;
|
||
else if(strstr(*value,"PP")) ppOpt = pvlOptPP;
|
||
else if(strstr(*value,"CA")) ppOpt = pvlOptCA;
|
||
else strcpy(*verify,"Illegal. Chose a value");
|
||
value++; verify++;
|
||
**verify = 0; /*Initialize verify to NULL*/
|
||
if((*value==NULL) || (strcmp(*value,"")==0)) msOpt = 0;
|
||
else if(strstr(*value,"NMS")) msOpt = 0;
|
||
else if(strstr(*value,"MS")) msOpt = pvlOptMS;
|
||
else strcpy(*verify,"Illegal. Chose a value");
|
||
dbCopyEntryContents(pdbentry,plinkentry);
|
||
if(pdbentry->pflddes->field_type == DBF_DEVICE) {
|
||
status = dbFindField(plinkentry,"OUT");
|
||
if(status) {
|
||
dbFinishEntry(plinkentry);
|
||
return(status);
|
||
}
|
||
}
|
||
putPvLink(plinkentry,ppOpt|msOpt,pstr);
|
||
dbFinishEntry(plinkentry);
|
||
}
|
||
break;
|
||
case FORM_FWDLINK: {
|
||
short ppOpt = 0;
|
||
short msOpt = 0;
|
||
const char *pstr;
|
||
|
||
pstr = *value;
|
||
**verify = 0;
|
||
value++; verify++;
|
||
**verify = 0; /*Initialize verify to NULL*/
|
||
if((*value==NULL) || (strcmp(*value,"")==0)) ppOpt = 0;
|
||
else if(strstr(*value,"CA")) ppOpt = pvlOptCA;
|
||
else strcpy(*verify,"Illegal. Chose a value");
|
||
putPvLink(pdbentry,ppOpt|msOpt,pstr);
|
||
}
|
||
break;
|
||
case FORM_VME_IO:
|
||
lvalue = strtol(*value,&endp,0);
|
||
if(*endp==0) {
|
||
plink->value.vmeio.card = lvalue; **verify = 0;
|
||
} else {
|
||
strcpy(*verify,"Illegal. Must be number");
|
||
}
|
||
value++; verify++;
|
||
lvalue = strtol(*value,&endp,0);
|
||
if(*endp==0) {
|
||
plink->value.vmeio.signal = lvalue; **verify = 0;
|
||
} else {
|
||
strcpy(*verify,"Illegal. Must be number");
|
||
}
|
||
value++; verify++;
|
||
status = putParmString(&plink->value.vmeio.parm,*value);
|
||
break;
|
||
case FORM_CAMAC_IO:
|
||
lvalue = strtol(*value,&endp,0);
|
||
if(*endp==0) {
|
||
plink->value.camacio.b = lvalue; **verify = 0;
|
||
} else {
|
||
strcpy(*verify,"Illegal. Must be number");
|
||
}
|
||
value++; verify++;
|
||
lvalue = strtol(*value,&endp,0);
|
||
if(*endp==0) {
|
||
plink->value.camacio.c = lvalue; **verify = 0;
|
||
} else {
|
||
strcpy(*verify,"Illegal. Must be number");
|
||
}
|
||
value++; verify++;
|
||
lvalue = strtol(*value,&endp,0);
|
||
if(*endp==0) {
|
||
plink->value.camacio.n = lvalue; **verify = 0;
|
||
} else {
|
||
strcpy(*verify,"Illegal. Must be number");
|
||
}
|
||
value++; verify++;
|
||
lvalue = strtol(*value,&endp,0);
|
||
if(*endp==0) {
|
||
plink->value.camacio.a = lvalue; **verify = 0;
|
||
} else {
|
||
strcpy(*verify,"Illegal. Must be number");
|
||
}
|
||
value++; verify++;
|
||
lvalue = strtol(*value,&endp,0);
|
||
if(*endp==0) {
|
||
plink->value.camacio.f = lvalue; **verify = 0;
|
||
} else {
|
||
strcpy(*verify,"Illegal. Must be number");
|
||
}
|
||
value++; verify++;
|
||
status = putParmString(&plink->value.camacio.parm,*value);
|
||
break;
|
||
case FORM_RF_IO:
|
||
lvalue = strtol(*value,&endp,0);
|
||
if(*endp==0) {
|
||
plink->value.rfio.cryo = lvalue; **verify = 0;
|
||
} else {
|
||
strcpy(*verify,"Illegal. Must be number");
|
||
}
|
||
value++; verify++;
|
||
lvalue = strtol(*value,&endp,0);
|
||
if(*endp==0) {
|
||
plink->value.rfio.micro = lvalue; **verify = 0;
|
||
} else {
|
||
strcpy(*verify,"Illegal. Must be number");
|
||
}
|
||
value++; verify++;
|
||
lvalue = strtol(*value,&endp,0);
|
||
if(*endp==0) {
|
||
plink->value.rfio.dataset = lvalue; **verify = 0;
|
||
} else {
|
||
strcpy(*verify,"Illegal. Must be number");
|
||
}
|
||
value++; verify++;
|
||
lvalue = strtol(*value,&endp,0);
|
||
if(*endp==0) {
|
||
plink->value.rfio.element = lvalue; **verify = 0;
|
||
} else {
|
||
strcpy(*verify,"Illegal. Must be number");
|
||
}
|
||
break;
|
||
case FORM_AB_IO:
|
||
lvalue = strtol(*value,&endp,0);
|
||
if(*endp==0) {
|
||
plink->value.abio.link = lvalue; **verify = 0;
|
||
} else {
|
||
strcpy(*verify,"Illegal. Must be number");
|
||
}
|
||
value++; verify++;
|
||
lvalue = strtol(*value,&endp,0);
|
||
if(*endp==0) {
|
||
plink->value.abio.adapter = lvalue; **verify = 0;
|
||
} else {
|
||
strcpy(*verify,"Illegal. Must be number");
|
||
}
|
||
value++; verify++;
|
||
lvalue = strtol(*value,&endp,0);
|
||
if(*endp==0) {
|
||
plink->value.abio.card = lvalue; **verify = 0;
|
||
} else {
|
||
strcpy(*verify,"Illegal. Must be number");
|
||
}
|
||
value++; verify++;
|
||
lvalue = strtol(*value,&endp,0);
|
||
if(*endp==0) {
|
||
plink->value.abio.signal = lvalue; **verify = 0;
|
||
} else {
|
||
strcpy(*verify,"Illegal. Must be number");
|
||
}
|
||
value++; verify++;
|
||
status = putParmString(&plink->value.abio.parm,*value);
|
||
break;
|
||
case FORM_GPIB_IO:
|
||
lvalue = strtol(*value,&endp,0);
|
||
if(*endp==0) {
|
||
plink->value.gpibio.link = lvalue; **verify = 0;
|
||
} else {
|
||
strcpy(*verify,"Illegal. Must be number");
|
||
}
|
||
value++; verify++;
|
||
lvalue = strtol(*value,&endp,0);
|
||
if(*endp==0) {
|
||
plink->value.gpibio.addr = lvalue; **verify = 0;
|
||
} else {
|
||
strcpy(*verify,"Illegal. Must be number");
|
||
}
|
||
value++; verify++;
|
||
status = putParmString(&plink->value.gpibio.parm,*value);
|
||
**verify = 0;
|
||
break;
|
||
case FORM_BITBUS_IO:
|
||
lvalue = strtol(*value,&endp,0);
|
||
if(*endp==0) {
|
||
plink->value.bitbusio.link = lvalue; **verify = 0;
|
||
} else {
|
||
strcpy(*verify,"Illegal. Must be number");
|
||
}
|
||
value++; verify++;
|
||
lvalue = strtol(*value,&endp,0);
|
||
if(*endp==0) {
|
||
plink->value.bitbusio.node = lvalue; **verify = 0;
|
||
} else {
|
||
strcpy(*verify,"Illegal. Must be number");
|
||
}
|
||
value++; verify++;
|
||
lvalue = strtol(*value,&endp,0);
|
||
if(*endp==0) {
|
||
plink->value.bitbusio.port = lvalue; **verify = 0;
|
||
} else {
|
||
strcpy(*verify,"Illegal. Must be number");
|
||
}
|
||
value++; verify++;
|
||
lvalue = strtol(*value,&endp,0);
|
||
if(*endp==0) {
|
||
plink->value.bitbusio.signal = lvalue; **verify = 0;
|
||
} else {
|
||
strcpy(*verify,"Illegal. Must be number");
|
||
}
|
||
value++; verify++;
|
||
status = putParmString(&plink->value.bitbusio.parm,*value);
|
||
**verify = 0;
|
||
break;
|
||
case FORM_INST_IO:
|
||
status = putParmString(&plink->value.instio.string,*value);
|
||
**verify = 0;
|
||
break;
|
||
case FORM_BBGPIB_IO:
|
||
lvalue = strtol(*value,&endp,0);
|
||
if(*endp==0) {
|
||
plink->value.bbgpibio.link = lvalue; **verify = 0;
|
||
} else {
|
||
strcpy(*verify,"Illegal. Must be number");
|
||
}
|
||
value++; verify++;
|
||
lvalue = strtol(*value,&endp,0);
|
||
if(*endp==0) {
|
||
plink->value.bbgpibio.bbaddr = lvalue; **verify = 0;
|
||
} else {
|
||
strcpy(*verify,"Illegal. Must be number");
|
||
}
|
||
value++; verify++;
|
||
lvalue = strtol(*value,&endp,0);
|
||
if(*endp==0) {
|
||
plink->value.bbgpibio.gpibaddr = lvalue; **verify = 0;
|
||
} else {
|
||
strcpy(*verify,"Illegal. Must be number");
|
||
}
|
||
value++; verify++;
|
||
status = putParmString(&plink->value.bbgpibio.parm,*value);
|
||
**verify = 0;
|
||
break;
|
||
case FORM_VXI_IO:
|
||
plink->value.vxiio.flag =
|
||
((strchr(*value,'Y')||strchr(*value,'y') ? VXIDYNAMIC : VXISTATIC));
|
||
value++; verify++;
|
||
lvalue = strtol(*value,&endp,0);
|
||
if(*endp==0) {
|
||
plink->value.vxiio.frame = lvalue; **verify = 0;
|
||
} else {
|
||
strcpy(*verify,"Illegal. Must be number");
|
||
}
|
||
value++; verify++;
|
||
lvalue = strtol(*value,&endp,0);
|
||
if(*endp==0) {
|
||
plink->value.vxiio.slot = lvalue; **verify = 0;
|
||
} else {
|
||
strcpy(*verify,"Illegal. Must be number");
|
||
}
|
||
value++; verify++;
|
||
lvalue = strtol(*value,&endp,0);
|
||
if(*endp==0) {
|
||
plink->value.vxiio.la = lvalue; **verify = 0;
|
||
} else {
|
||
strcpy(*verify,"Illegal. Must be number");
|
||
}
|
||
value++; verify++;
|
||
lvalue = strtol(*value,&endp,0);
|
||
if(*endp==0) {
|
||
plink->value.vxiio.signal = lvalue; **verify = 0;
|
||
} else {
|
||
strcpy(*verify,"Illegal. Must be number");
|
||
}
|
||
value++; verify++;
|
||
status = putParmString(&plink->value.vxiio.parm,*value);
|
||
**verify = 0;
|
||
break;
|
||
default :
|
||
status = S_dbLib_badLink;
|
||
}
|
||
return(status);
|
||
}
|
||
|
||
char ** epicsShareAPI dbVerifyForm(DBENTRY *pdbentry,char **value)
|
||
{
|
||
struct form *pform = pdbentry->formpvt;
|
||
DBLINK *plink;
|
||
DBLINK templink;
|
||
int nlines,i;
|
||
|
||
if(!pform) return(NULL);
|
||
plink = pform->plink;
|
||
if(!plink) return(NULL);
|
||
templink = *plink;
|
||
if(plink->type==CONSTANT) templink.value.constantStr = NULL;
|
||
if(plink->type==PV_LINK) templink.value.pv_link.pvname = NULL;
|
||
pform->plink = &templink;
|
||
dbPutForm(pdbentry,value);
|
||
if(plink->type==CONSTANT) free((void *)templink.value.constantStr);
|
||
if(plink->type==PV_LINK) free((void *)templink.value.pv_link.pvname);
|
||
pform->plink = plink;
|
||
nlines = pform->nlines;
|
||
for(i=0; i<nlines; i++) {
|
||
/* If any verify string is not null then return verify */
|
||
if(*pform->verify[i]) return(pform->verify);
|
||
}
|
||
return(NULL);
|
||
}
|
||
|
||
char * epicsShareAPI dbGetRelatedField(DBENTRY *psave)
|
||
{
|
||
DBENTRY dbEntry;
|
||
DBENTRY *pdbentry= &dbEntry;
|
||
dbFldDes *pflddes;
|
||
char *rtnval = NULL;
|
||
long status;
|
||
|
||
pflddes = psave->pflddes;
|
||
if(pflddes->field_type !=DBF_DEVICE) return(NULL);
|
||
dbCopyEntryContents(psave,pdbentry);
|
||
pflddes = pdbentry->pflddes;
|
||
status = dbFindField(pdbentry,"INP");
|
||
if(status) status = dbFindField(pdbentry,"OUT");
|
||
if(!status) rtnval = pdbentry->pflddes->name;
|
||
dbFinishEntry(pdbentry);
|
||
return(rtnval);
|
||
}
|
||
|
||
int epicsShareAPI dbGetNLinks(DBENTRY *pdbentry)
|
||
{
|
||
dbRecordType *precordType = pdbentry->precordType;
|
||
|
||
if(!precordType) return(S_dbLib_recordTypeNotFound);
|
||
return((int)precordType->no_links);
|
||
}
|
||
|
||
long epicsShareAPI dbGetLinkField(DBENTRY *pdbentry,int index)
|
||
{
|
||
dbRecordType *precordType = pdbentry->precordType;
|
||
dbFldDes *pflddes;
|
||
|
||
if(!precordType) return(S_dbLib_recordTypeNotFound);
|
||
if(index<0 || index>=precordType->no_links) return(S_dbLib_badLink);
|
||
pdbentry->indfield = precordType->link_ind[index];
|
||
pdbentry->pflddes = pflddes = precordType->papFldDes[pdbentry->indfield];
|
||
dbGetFieldAddress(pdbentry);
|
||
return(0);
|
||
}
|
||
|
||
int epicsShareAPI dbGetLinkType(DBENTRY *pdbentry)
|
||
{
|
||
dbFldDes *pflddes;
|
||
DBLINK *plink;
|
||
int field_type;
|
||
|
||
dbGetFieldAddress(pdbentry);
|
||
pflddes = pdbentry->pflddes;
|
||
if(!pflddes) return(-1);
|
||
plink = (DBLINK *)pdbentry->pfield;
|
||
if(!plink) return(-1);
|
||
field_type = pflddes->field_type;
|
||
switch (field_type) {
|
||
case DBF_INLINK:
|
||
case DBF_OUTLINK:
|
||
case DBF_FWDLINK:
|
||
switch(plink->type) {
|
||
case CONSTANT:
|
||
return(DCT_LINK_CONSTANT);
|
||
case PV_LINK:
|
||
case DB_LINK:
|
||
case CA_LINK:
|
||
return(DCT_LINK_PV);
|
||
default:
|
||
return(DCT_LINK_FORM);
|
||
}
|
||
}
|
||
return(-1);
|
||
}
|
||
|
||
long epicsShareAPI dbCvtLinkToConstant(DBENTRY *pdbentry)
|
||
{
|
||
dbFldDes *pflddes;
|
||
DBLINK *plink;
|
||
|
||
dbGetFieldAddress(pdbentry);
|
||
pflddes = pdbentry->pflddes;
|
||
if(!pflddes) return(-1);
|
||
plink = (DBLINK *)pdbentry->pfield;
|
||
if(!plink) return(-1);
|
||
switch (pflddes->field_type) {
|
||
case DBF_INLINK:
|
||
case DBF_OUTLINK:
|
||
case DBF_FWDLINK:
|
||
if(plink->type == CONSTANT) return(0);
|
||
if(plink->type != PV_LINK) return(S_dbLib_badLink);
|
||
free((void *)plink->value.pv_link.pvname);
|
||
plink->value.pv_link.pvname = NULL;
|
||
dbFreeForm(pdbentry);
|
||
plink->type = CONSTANT;
|
||
if(pflddes->initial) {
|
||
plink->value.constantStr =
|
||
dbCalloc(strlen(pflddes->initial)+1,sizeof(char));
|
||
strcpy(plink->value.constantStr,pflddes->initial);
|
||
} else {
|
||
plink->value.constantStr = NULL;
|
||
}
|
||
return(0);
|
||
default:
|
||
epicsPrintf("dbCvtLinkToConstant called for non link field\n");
|
||
}
|
||
return(S_dbLib_badLink);
|
||
}
|
||
|
||
long epicsShareAPI dbCvtLinkToPvlink(DBENTRY *pdbentry)
|
||
{
|
||
dbFldDes *pflddes;
|
||
DBLINK *plink;
|
||
|
||
dbGetFieldAddress(pdbentry);
|
||
pflddes = pdbentry->pflddes;
|
||
if(!pflddes) return(-1);
|
||
if(!pdbentry->precnode || !pdbentry->precnode->precord) return(-1);
|
||
plink = (DBLINK *)pdbentry->pfield;
|
||
if(!plink) return(-1);
|
||
switch (pflddes->field_type) {
|
||
case DBF_INLINK:
|
||
case DBF_OUTLINK:
|
||
case DBF_FWDLINK:
|
||
if(plink->type == PV_LINK) return(0);
|
||
if(plink->type != CONSTANT) return(S_dbLib_badLink);
|
||
free(plink->value.constantStr);
|
||
dbFreeForm(pdbentry);
|
||
plink->type = PV_LINK;
|
||
plink->value.pv_link.pvlMask = 0;
|
||
plink->value.pv_link.pvname = 0;
|
||
plink->value.pv_link.precord = pdbentry->precnode->precord;
|
||
return(0);
|
||
default:
|
||
epicsPrintf("dbCvtLinkToPvlink called for non link field\n");
|
||
}
|
||
return(S_dbLib_badLink);
|
||
}
|
||
|
||
void epicsShareAPI dbDumpPath(DBBASE *pdbbase)
|
||
{
|
||
ELLLIST *ppathList;
|
||
dbPathNode *pdbPathNode;
|
||
|
||
if(!pdbbase) return;
|
||
ppathList = (ELLLIST *)pdbbase->pathPvt;
|
||
if(!ppathList || !(pdbPathNode = (dbPathNode *)ellFirst(ppathList))) {
|
||
printf("no path defined\n");
|
||
return;
|
||
}
|
||
while(pdbPathNode) {
|
||
printf("%s",pdbPathNode->directory);
|
||
pdbPathNode = (dbPathNode *)ellNext(&pdbPathNode->node);
|
||
if(pdbPathNode) printf("%s", OSI_PATH_LIST_SEPARATOR);
|
||
}
|
||
printf("\n");
|
||
return;
|
||
}
|
||
|
||
void epicsShareAPI dbDumpRecord(
|
||
dbBase *pdbbase,const char *precordTypename,int level)
|
||
{
|
||
if(!pdbbase) {
|
||
printf("pdbbase not specified\n");
|
||
return;
|
||
}
|
||
dbWriteRecordFP(pdbbase,stdout,precordTypename,level);
|
||
}
|
||
|
||
void epicsShareAPI dbDumpMenu(DBBASE *pdbbase,const char *menuName)
|
||
{
|
||
if(!pdbbase) {
|
||
printf("pdbbase not specified\n");
|
||
return;
|
||
}
|
||
dbWriteMenuFP(pdbbase,stdout,menuName);
|
||
}
|
||
|
||
void epicsShareAPI dbDumpRecordType(DBBASE *pdbbase,const char *recordTypeName)
|
||
{
|
||
dbRecordType *pdbRecordType;
|
||
dbFldDes *pdbFldDes;
|
||
int gotMatch;
|
||
int i;
|
||
|
||
if(!pdbbase) {
|
||
printf("pdbbase not specified\n");
|
||
return;
|
||
}
|
||
for(pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList);
|
||
pdbRecordType; pdbRecordType = (dbRecordType *)ellNext(&pdbRecordType->node)) {
|
||
if(recordTypeName) {
|
||
gotMatch = (strcmp(recordTypeName,pdbRecordType->name)==0)
|
||
? TRUE : FALSE;
|
||
}else {
|
||
gotMatch=TRUE;
|
||
}
|
||
if(!gotMatch) continue;
|
||
printf("name(%s) no_fields(%hd) no_prompt(%hd) no_links(%hd)\n",
|
||
pdbRecordType->name,pdbRecordType->no_fields,
|
||
pdbRecordType->no_prompt,pdbRecordType->no_links);
|
||
printf("index name\tsortind sortname\n");
|
||
for(i=0; i<pdbRecordType->no_fields; i++) {
|
||
pdbFldDes = pdbRecordType->papFldDes[i];
|
||
printf("%5d %s\t%7d %s\n",
|
||
i,pdbFldDes->name,
|
||
pdbRecordType->sortFldInd[i],pdbRecordType->papsortFldName[i]);
|
||
}
|
||
printf("link_ind ");
|
||
for(i=0; i<pdbRecordType->no_links; i++)
|
||
printf(" %hd",pdbRecordType->link_ind[i]);
|
||
printf("\n");
|
||
printf("indvalFlddes %d name %s\n",pdbRecordType->indvalFlddes,
|
||
pdbRecordType->pvalFldDes->name);
|
||
printf("struct rset * %p rec_size %d\n",
|
||
(void *)pdbRecordType->prset,pdbRecordType->rec_size);
|
||
if(recordTypeName) break;
|
||
}
|
||
}
|
||
|
||
void epicsShareAPI dbDumpFldDes(
|
||
DBBASE *pdbbase,const char *recordTypeName,const char *fname)
|
||
{
|
||
dbRecordType *pdbRecordType;
|
||
dbFldDes *pdbFldDes;
|
||
int gotMatch;
|
||
int i;
|
||
dbRecordAttribute *pAttribute;
|
||
|
||
if(!pdbbase) {
|
||
printf("pdbbase not specified\n");
|
||
return;
|
||
}
|
||
for(pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList);
|
||
pdbRecordType; pdbRecordType = (dbRecordType *)ellNext(&pdbRecordType->node)) {
|
||
if(recordTypeName) {
|
||
gotMatch = (strcmp(recordTypeName,pdbRecordType->name)==0)
|
||
? TRUE : FALSE;
|
||
}else {
|
||
gotMatch=TRUE;
|
||
}
|
||
if(!gotMatch) continue;
|
||
printf("recordtype(%s) \n",pdbRecordType->name);
|
||
for(i=0; i<pdbRecordType->no_fields; i++) {
|
||
int j;
|
||
|
||
pdbFldDes = pdbRecordType->papFldDes[i];
|
||
if(fname && strcmp(fname,pdbFldDes->name)!=0) continue;
|
||
printf(" %s\n", pdbFldDes->name);
|
||
printf("\t prompt: %s\n",pdbFldDes->prompt);
|
||
printf("\t extra: %s\n",pdbFldDes->extra);
|
||
printf("\t indRecordType: %hd\n",pdbFldDes->indRecordType);
|
||
printf("\t special: %hd ",pdbFldDes->special);
|
||
if(pdbFldDes->special) {
|
||
for(j=0; j<SPC_NTYPES; j++) {
|
||
if(pamapspcType[j].value == pdbFldDes->special) {
|
||
printf("%s",pamapspcType[j].strvalue);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
printf("\n");
|
||
for(j=0; j<DBF_NTYPES; j++) {
|
||
if(pamapdbfType[j].value == pdbFldDes->field_type) break;
|
||
}
|
||
if(j>=DBF_NTYPES)
|
||
printf("\t field_type: %d\n", pdbFldDes->field_type);
|
||
else
|
||
printf("\t field_type: %s\n", pamapdbfType[j].strvalue);
|
||
printf("\tprocess_passive: %hd\n",pdbFldDes->process_passive);
|
||
printf("\t base: %hd\n",pdbFldDes->base);
|
||
if(!pdbFldDes->promptgroup) {
|
||
printf("\t promptgroup: %d\n",pdbFldDes->promptgroup);
|
||
} else {
|
||
for(j=0; j<GUI_NTYPES; j++) {
|
||
if(pamapguiGroup[j].value == pdbFldDes->promptgroup) {
|
||
printf("\t promptgroup: %s\n",
|
||
pamapguiGroup[j].strvalue);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
printf("\t interest: %hd\n", pdbFldDes->interest);
|
||
printf("\t as_level: %hd\n",pdbFldDes->as_level);
|
||
printf("\t initial: %s\n",pdbFldDes->initial);
|
||
if(pdbFldDes->field_type==DBF_MENU) {
|
||
if(pdbFldDes->ftPvt)
|
||
printf("\t\t menu: %s\n",
|
||
((dbMenu *)pdbFldDes->ftPvt)->name);
|
||
else
|
||
printf("\t\t menu: NOT FOUND\n");
|
||
}
|
||
if(pdbFldDes->field_type==DBF_DEVICE) {
|
||
printf("\t ftPvt: %p\n",pdbFldDes->ftPvt);
|
||
}
|
||
printf("\t size: %hd\n",pdbFldDes->size);
|
||
printf("\t offset: %hd\n",pdbFldDes->offset);
|
||
}
|
||
pAttribute =
|
||
(dbRecordAttribute *)ellFirst(&pdbRecordType->attributeList);
|
||
while(pAttribute) {
|
||
printf("Attribute: name %s value %s\n",
|
||
pAttribute->name,pAttribute->value);
|
||
pAttribute = (dbRecordAttribute *)ellNext(&pAttribute->node);
|
||
}
|
||
if(recordTypeName) break;
|
||
}
|
||
}
|
||
|
||
void epicsShareAPI dbDumpDevice(DBBASE *pdbbase,const char *recordTypeName)
|
||
{
|
||
dbRecordType *pdbRecordType;
|
||
devSup *pdevSup;
|
||
int gotMatch;
|
||
|
||
if(!pdbbase) {
|
||
printf("pdbbase not specified\n");
|
||
return;
|
||
}
|
||
for(pdbRecordType = (dbRecordType *)ellFirst(&pdbbase->recordTypeList);
|
||
pdbRecordType; pdbRecordType = (dbRecordType *)ellNext(&pdbRecordType->node)) {
|
||
if(recordTypeName) {
|
||
gotMatch = (strcmp(recordTypeName,pdbRecordType->name)==0)
|
||
? TRUE : FALSE;
|
||
}else {
|
||
gotMatch=TRUE;
|
||
}
|
||
if(!gotMatch) continue;
|
||
printf("recordtype(%s) \n",pdbRecordType->name);
|
||
for(pdevSup = (devSup *)ellFirst(&pdbRecordType->devList);
|
||
pdevSup; pdevSup = (devSup *)ellNext(&pdevSup->node)) {
|
||
printf("\t name: %s\n",pdevSup->name);
|
||
printf("\t choice: %s\n",pdevSup->choice);
|
||
printf("\tlink_type: %d\n",pdevSup->link_type);
|
||
printf("\t pdset: %p\n",(void *)pdevSup->pdset);
|
||
}
|
||
if(recordTypeName) break;
|
||
}
|
||
}
|
||
|
||
void epicsShareAPI dbDumpDriver(DBBASE *pdbbase)
|
||
{
|
||
if(!pdbbase) {
|
||
printf("pdbbase not specified\n");
|
||
return;
|
||
}
|
||
dbWriteDriverFP(pdbbase,stdout);
|
||
}
|
||
|
||
void epicsShareAPI dbDumpBreaktable(DBBASE *pdbbase,const char *name)
|
||
{
|
||
brkTable *pbrkTable;
|
||
brkInt *pbrkInt;
|
||
int ind;
|
||
|
||
if(!pdbbase) {
|
||
fprintf(stderr,"pdbbase not specified\n");
|
||
return;
|
||
}
|
||
for(pbrkTable = (brkTable *)ellFirst(&pdbbase->bptList);
|
||
pbrkTable; pbrkTable = (brkTable *)ellNext(&pbrkTable->node)) {
|
||
if(name && strcmp(name,pbrkTable->name)!=0) continue;
|
||
printf("breaktable(%s) {\n",pbrkTable->name);
|
||
for(ind=0; ind<pbrkTable->number; ind++) {
|
||
pbrkInt = pbrkTable->papBrkInt[ind];
|
||
printf("\t%f %e %f\n",pbrkInt->raw,pbrkInt->slope,pbrkInt->eng);
|
||
}
|
||
printf("}\n");
|
||
}
|
||
return;
|
||
}
|
||
|
||
static char *bus[VXI_IO+1] = {"","","VME","CAMAC","AB",
|
||
"GPIB","BITBUS","","","","","","INST","BBGPIB","VXI"};
|
||
void epicsShareAPI dbReportDeviceConfig(dbBase *pdbbase,FILE *report)
|
||
{
|
||
DBENTRY dbentry;
|
||
DBENTRY *pdbentry=&dbentry;
|
||
long status;
|
||
char busName[40];
|
||
char linkValue[40];
|
||
char dtypValue[40];
|
||
char cvtValue[40];
|
||
int ilink,nlinks;
|
||
struct link *plink;
|
||
|
||
dbInitEntry(pdbbase,pdbentry);
|
||
status = dbFirstRecordType(pdbentry);
|
||
while(!status) {
|
||
status = dbFirstRecord(pdbentry);
|
||
while(!status) {
|
||
nlinks = dbGetNLinks(pdbentry);
|
||
for(ilink=0; ilink<nlinks; ilink++) {
|
||
status = dbGetLinkField(pdbentry,ilink);
|
||
if(status || dbGetLinkType(pdbentry)!=DCT_LINK_FORM) continue;
|
||
plink = pdbentry->pfield;
|
||
strcpy(busName,bus[plink->type]);
|
||
if(strlen(busName)==0) continue;
|
||
strcpy(linkValue,dbGetString(pdbentry));
|
||
status = dbFindField(pdbentry,"DTYP");
|
||
if(status) break;
|
||
strcpy(dtypValue,dbGetString(pdbentry));
|
||
status = dbFindField(pdbentry,"LINR");
|
||
if(status) {
|
||
cvtValue[0] = 0;
|
||
} else {
|
||
if(strcmp(dbGetString(pdbentry),"LINEAR")!=0) {
|
||
cvtValue[0] = 0;
|
||
} else {
|
||
strcpy(cvtValue,"cvt(");
|
||
status = dbFindField(pdbentry,"EGUL");
|
||
if(!status) strcat(cvtValue,dbGetString(pdbentry));
|
||
status = dbFindField(pdbentry,"EGUF");
|
||
if(!status) {
|
||
strcat(cvtValue,",");
|
||
strcat(cvtValue,dbGetString(pdbentry));
|
||
}
|
||
strcat(cvtValue,")");
|
||
}
|
||
}
|
||
fprintf(report,"%-8s %-20s %-20s %-20s %-s\n",
|
||
busName,linkValue,dtypValue,
|
||
dbGetRecordName(pdbentry),cvtValue);
|
||
break;
|
||
}
|
||
status = dbNextRecord(pdbentry);
|
||
}
|
||
status = dbNextRecordType(pdbentry);
|
||
}
|
||
dbFinishEntry(pdbentry);
|
||
return;
|
||
}
|