30 #define epicsExportSharedSymbols 58 static void yyerrorAbort(
char *
str);
59 static void allocTemp(
void *pvoid);
60 static void *popFirstTemp(
void);
61 static void *getLastTemp(
void);
62 static int db_yyinput(
char *buf,
int max_size);
63 static void dbIncludePrint(
void);
64 static void dbPathCmd(
char *path);
65 static void dbAddPathCmd(
char *path);
66 static void dbIncludeNew(
char *include_file);
67 static void dbMenuHead(
char *name);
68 static void dbMenuChoice(
char *name,
char *
value);
69 static void dbMenuBody(
void);
71 static void dbRecordtypeHead(
char *name);
72 static void dbRecordtypeEmpty(
void);
73 static void dbRecordtypeBody(
void);
74 static void dbRecordtypeFieldHead(
char *name,
char *
type);
75 static void dbRecordtypeFieldItem(
char *name,
char *
value);
76 static short findOrAddGuiGroup(
const char *name);
78 static void dbDevice(
char *recordtype,
char *linktype,
79 char *dsetname,
char *choicestring);
80 static void dbDriver(
char *name);
81 static void dbLinkType(
char *name,
char *jlif_name);
82 static void dbRegistrar(
char *name);
83 static void dbFunction(
char *name);
84 static void dbVariable(
char *name,
char *
type);
86 static void dbBreakHead(
char *name);
87 static void dbBreakItem(
char *
value);
88 static void dbBreakBody(
void);
90 static void dbRecordHead(
char *recordType,
char*name,
int visible);
91 static void dbRecordField(
char *name,
char *
value);
92 static void dbRecordBody(
void);
95 #define MY_BUFFER_SIZE 1024 96 static char *my_buffer=
NULL;
97 static char *mac_input_buffer=
NULL;
98 static char *my_buffer_ptr=
NULL;
118 static void *freeListPvt =
NULL;
119 static int duplicate =
FALSE;
121 static void yyerrorAbort(
char *
str)
127 static void allocTemp(
void *pvoid)
132 ptempListNode->
item = pvoid;
136 static void *popFirstTemp(
void)
142 ptemp = ptempListNode->
item;
148 static void *getLastTemp(
void)
153 return(ptempListNode->
item);
164 if (!ppathList ||
ellCount(ppathList) == 0 ||
172 while (pdbPathNode) {
173 fullfilename =
dbMalloc(strlen(pdbPathNode->directory) +
175 strcpy(fullfilename, pdbPathNode->directory);
176 strcat(fullfilename,
"/");
178 *fp = fopen(fullfilename,
"r");
181 free((
void *)fullfilename);
182 if (*fp)
return pdbPathNode->directory;
189 static void freeInputFileList(
void)
194 if(fclose(pinputFileNow->
fp))
196 "Closing file %s",pinputFileNow->
filename);
197 free((
void *)pinputFileNow->
filename);
199 free((
void *)pinputFileNow);
209 return strcmp(LHS->
recordname, RHS->recordname);
213 const char *
path,
const char *substitutions)
232 penv = getenv(
"EPICS_DB_INCLUDE_PATH");
248 if(macPairs ==
NULL) {
253 free((
void *)macPairs);
266 pinputFile->
path = dbOpenFile(pdbbase, pinputFile->
filename, &fp1);
267 if (!pinputFile->
filename || !fp1) {
269 "dbRead opening file %s",pinputFile->
filename);
275 pinputFile->
fp = fp1;
280 pinputFileNow = pinputFile;
282 my_buffer_ptr = my_buffer;
284 status = pvt_yy_parse();
286 if (
ellCount(&tempList) && !yyAbort)
299 while(!localStatus) {
307 fprintf(
stderr,
"dbPutRecordAttribute status %ld\n",status);
326 if(mac_input_buffer) free((
void *)mac_input_buffer);
327 mac_input_buffer =
NULL;
330 if(my_buffer) free((
void *)my_buffer);
337 const char *
path,
const char *substitutions)
338 {
return (dbReadCOM(ppdbbase,filename,0,path,substitutions));}
341 const char *
path,
const char *substitutions)
342 {
return (dbReadCOM(ppdbbase,0,fp,path,substitutions));}
344 static int db_yyinput(
char *buf,
int max_size)
349 if(yyAbort)
return(0);
350 if(*my_buffer_ptr==0) {
359 fprintf(
stderr,
"Warning: '%s' line %d has undefined macros\n",
367 if(fclose(pinputFileNow->
fp))
369 "Closing file %s",pinputFileNow->
filename);
370 free((
void *)pinputFileNow->
filename);
372 free((
void *)pinputFileNow);
374 if(!pinputFileNow)
return(0);
378 my_buffer_ptr = &my_buffer[0];
380 l = strlen(my_buffer_ptr);
381 n = (l<=max_size ? l : max_size);
382 memcpy(buf,my_buffer_ptr,n);
387 static void dbIncludePrint(
void)
393 if (pinputFile->
path)
406 static void dbPathCmd(
char *
path)
411 static void dbAddPathCmd(
char *
path)
416 static void dbIncludeNew(
char *
filename)
423 pinputFile->
path = dbOpenFile(pdbbase, pinputFile->
filename, &fp);
425 epicsPrintf(
"Can't open include file \"%s\"\n", filename);
428 free((
void *)pinputFile);
433 pinputFileNow = pinputFile;
436 static void dbMenuHead(
char *name)
442 yyerrorAbort(
"dbMenuHead: Menu name can't be empty");
450 if(
ellCount(&tempList)) yyerrorAbort(
"dbMenuHead: tempList not empty");
456 static void dbMenuChoice(
char *name,
char *
value)
459 yyerror(
"dbMenuChoice: Menu choice name can't be empty");
462 if(duplicate)
return;
467 static void dbMenuBody(
void)
479 pnewMenu = (
dbMenu *)popFirstTemp();
483 for(i=0; i<nChoice; i++) {
487 if(
ellCount(&tempList)) yyerrorAbort(
"dbMenuBody: tempList not empty");
490 while(pMenu && strcmp(pMenu->
name,pnewMenu->
name) >0 )
498 yyerrorAbort(
"gphAdd failed");
504 static void dbRecordtypeHead(
char *name)
510 yyerrorAbort(
"dbRecordtypeHead: Recordtype name can't be empty");
522 yyerrorAbort(
"dbRecordtypeHead tempList not empty");
523 allocTemp(pdbRecordType);
526 static void dbRecordtypeFieldHead(
char *name,
char *
type)
532 yyerrorAbort(
"dbRecordtypeFieldHead: Field name can't be empty");
535 if(duplicate)
return;
537 allocTemp(pdbFldDes);
541 strcmp(pdbFldDes->
name,
"OUT")==0;
544 yyerrorAbort(
"Illegal Field Type");
548 static short findOrAddGuiGroup(
const char *name)
559 pgphentry->
userPvt = pdbGuiGroup;
564 static void dbRecordtypeFieldItem(
char *name,
char *
value)
568 if(duplicate)
return;
569 pdbFldDes = (
dbFldDes *)getLastTemp();
570 if(strcmp(name,
"asl")==0) {
571 if(strcmp(value,
"ASL0")==0) {
573 }
else if(strcmp(value,
"ASL1")==0) {
576 yyerror(
"Illegal Access Security value: Must be ASL0 or ASL1");
580 if(strcmp(name,
"initial")==0) {
584 if(strcmp(name,
"promptgroup")==0) {
588 if(strcmp(name,
"prompt")==0) {
592 if(strcmp(name,
"special")==0) {
600 if(sscanf(value,
"%hd",&pdbFldDes->
special)==1) {
603 yyerror(
"Illegal 'special' value.");
606 if(strcmp(name,
"pp")==0) {
607 if((strcmp(value,
"YES")==0) || (strcmp(value,
"TRUE")==0)) {
609 }
else if((strcmp(value,
"NO")==0) || (strcmp(value,
"FALSE")==0)) {
612 yyerror(
"Illegal 'pp' value, must be YES/NO/TRUE/FALSE");
616 if(strcmp(name,
"interest")==0) {
617 if(sscanf(value,
"%hd",&pdbFldDes->
interest)!=1)
618 yyerror(
"Illegal 'interest' value, must be integer");
621 if(strcmp(name,
"base")==0) {
622 if(strcmp(value,
"DECIMAL")==0) {
624 }
else if(strcmp(value,
"HEX")==0) {
627 yyerror(
"Illegal 'base' value, must be DECIMAL/HEX");
631 if(strcmp(name,
"size")==0) {
632 if(sscanf(value,
"%hd",&pdbFldDes->
size)!=1)
633 yyerror(
"Illegal 'size' value, must be integer");
636 if(strcmp(name,
"extra")==0) {
640 if(strcmp(name,
"menu")==0) {
643 yyerrorAbort(
"menu not found");
646 if(strcmp(name,
"prop")==0) {
647 if(strcmp(value,
"YES")==0)
655 static void dbRecordtypeCdef(
char *text) {
660 if (!pdbbase->
loadCdefs || duplicate)
return;
662 pdbRecordType = ptempListNode->
item;
665 if (text[0] ==
' ') text++;
671 static void dbRecordtypeEmpty(
void)
682 pdbRecordType = ptempListNode->
item;
683 epicsPrintf(
"Declaration of recordtype(%s) preceeded full definition.\n",
684 pdbRecordType->
name);
688 static void dbRecordtypeBody(
void)
694 int no_fields,no_prompt,no_links;
696 char *psortFldNameTemp;
697 short psortFldIndTemp;
698 char **papsortFldName;
710 no_prompt = no_links = 0;
711 for(i=0; i<no_fields; i++) {
712 pdbFldDes = (
dbFldDes *)popFirstTemp();
720 fprintf(
stderr,
"recordtype(%s).%s size not specified\n",
721 pdbRecordType->
name,pdbFldDes->
name);
723 fprintf(
stderr,
"recordtype(%s).%s extra not specified\n",
724 pdbRecordType->
name,pdbFldDes->
name);
727 yyerrorAbort(
"dbRecordtypeBody: tempList not empty");
732 for(i=0; i<no_fields; i++) {
739 if(strcmp(pdbFldDes->
name,
"VAL")==0) {
749 for(i=0; i<no_fields; i++) {
750 for(j=i+1; j<no_fields; j++) {
751 if(strcmp(papsortFldName[j],papsortFldName[i])<0 ) {
752 psortFldNameTemp = papsortFldName[j];
753 psortFldIndTemp = sortFldInd[j];
754 papsortFldName[j] = papsortFldName[
i];
755 sortFldInd[j] = sortFldInd[
i];
756 papsortFldName[
i] = psortFldNameTemp;
757 sortFldInd[
i] = psortFldIndTemp;
768 yyerrorAbort(
"gphAdd failed");
770 pgphentry->
userPvt = pdbRecordType;
775 static void dbDevice(
char *recordtype,
char *linktype,
776 char *dsetname,
char *choicestring)
784 epicsPrintf(
"Record type \"%s\" not found for device \"%s\"\n",
785 recordtype, choicestring);
797 epicsPrintf(
"Bad link type \"%s\" for device \"%s\"\n",
798 linktype, choicestring);
813 yyerrorAbort(
"gphAdd failed");
820 static void dbDriver(
char *name)
826 yyerrorAbort(
"dbDriver: Driver name can't be empty");
837 yyerrorAbort(
"gphAdd failed");
843 static void dbLinkType(
char *name,
char *jlif_name)
857 yyerrorAbort(
"gphAdd failed");
863 static void dbRegistrar(
char *name)
869 yyerrorAbort(
"dbRegistrar: Registrar name can't be empty");
880 yyerrorAbort(
"gphAdd failed");
886 static void dbFunction(
char *name)
892 yyerrorAbort(
"dbFunction: Function name can't be empty");
903 yyerrorAbort(
"gphAdd failed");
909 static void dbVariable(
char *name,
char *
type)
915 yyerrorAbort(
"dbVariable: Variable name can't be empty");
927 yyerrorAbort(
"gphAdd failed");
933 static void dbBreakHead(
char *name)
939 yyerrorAbort(
"dbBreakHead: Breaktable name can't be empty");
949 if(
ellCount(&tempList)) yyerrorAbort(
"dbBreakHead:tempList not empty");
950 allocTemp(pbrkTable);
953 static void dbBreakItem(
char *
value)
956 if (duplicate)
return;
958 yyerrorAbort(
"Non-numeric value in breaktable");
963 static void dbBreakBody(
void)
976 pnewbrkTable = (
brkTable *)popFirstTemp();
979 yyerrorAbort(
"breaktable: Raw value missing");
984 yyerrorAbort(
"breaktable: Must have at least two points!");
987 pnewbrkTable->
number = number;
989 for (i=0; i<number; i++) {
992 str = (
char *)popFirstTemp();
996 str = (
char *)popFirstTemp();
1001 for (i=0; i<number-1; i++) {
1003 (paBrkInt[i+1].
eng - paBrkInt[
i].
eng)/
1004 (paBrkInt[i+1].raw - paBrkInt[i].raw);
1006 yyerrorAbort(
"breaktable slope is zero");
1012 yyerrorAbort(
"breaktable slope changes sign");
1015 paBrkInt[
i].
slope = slope;
1018 paBrkInt[number-1].
slope = paBrkInt[number-2].
slope;
1022 if (strcmp(pbrkTable->
name, pnewbrkTable->
name) > 0) {
1032 yyerrorAbort(
"dbBreakBody: gphAdd failed");
1035 pgphentry->
userPvt = pnewbrkTable;
1038 static void dbRecordHead(
char *recordType,
char *name,
int visible)
1045 yyerrorAbort(
"dbRecordHead: Record name can't be empty");
1048 badch = strpbrk(name,
" \"'.$");
1050 epicsPrintf(
"Bad character '%c' in record name \"%s\"\n",
1056 yyerrorAbort(
"dbRecordHead: tempList not empty");
1057 allocTemp(pdbentry);
1059 if (recordType[0] ==
'*' && recordType[1] == 0) {
1061 epicsPrintf(
"Record-type \"*\" not valid with dbRecordsOnceOnly\n");
1075 epicsPrintf(
"Record \"%s\" is of unknown type \"%s\"\n",
1086 epicsPrintf(
"Record \"%s\" of type \"%s\" redefined with new type " 1093 epicsPrintf(
"Record \"%s\" already defined (dbRecordsOnceOnly is " 1100 epicsPrintf(
"Can't create record \"%s\" of type \"%s\"\n",
1109 static void dbRecordField(
char *name,
char *
value)
1115 if (duplicate)
return;
1117 pdbentry = ptempListNode->
item;
1120 epicsPrintf(
"Record \"%s\" does not have a field \"%s\"\n",
1126 epicsPrintf(
"Can't set \"NAME\" field of record \"%s\"\n",
1131 if (*value ==
'"') {
1134 value[strlen(value) - 1] = 0;
1149 static void dbRecordInfo(
char *name,
char *
value)
1156 yyerrorAbort(
"dbRecordInfo: Info item name can't be empty");
1159 if (duplicate)
return;
1161 pdbentry = ptempListNode->
item;
1162 if (*value ==
'"') {
1165 value[strlen(value) - 1] = 0;
1168 status =
dbPutInfo(pdbentry,name,value);
1170 epicsPrintf(
"Can't set \"%s\" info \"%s\" to \"%s\"\n",
1177 static void dbRecordAlias(
char *name)
1184 yyerrorAbort(
"dbRecordAlias: Alias name can't be empty");
1187 if (duplicate)
return;
1189 pdbentry = ptempListNode->
item;
1192 epicsPrintf(
"Can't create alias \"%s\" for \"%s\"\n",
1199 static void dbAlias(
char *name,
char *alias)
1205 yyerrorAbort(
"dbAlias: Alias name can't be empty");
1210 epicsPrintf(
"Alias \"%s\" refers to unknown record \"%s\"\n",
1215 epicsPrintf(
"Can't create alias \"%s\" referring to \"%s\"\n",
1222 static void dbRecordBody(
void)
1230 pdbentry = (
DBENTRY *)popFirstTemp();
1232 yyerrorAbort(
"dbRecordBody: tempList not empty");
LIBCOM_API void *epicsStdCall freeListCalloc(void *pvt)
long dbCreateAlias(DBENTRY *pdbentry, const char *alias)
long dbPath(DBBASE *pdbbase, const char *path)
void dbInitEntry(dbBase *pdbbase, DBENTRY *pdbentry)
struct inputFile inputFile
struct tempListNode tempListNode
long dbFirstRecordType(DBENTRY *pdbentry)
LIBCOM_API long epicsStdCall macParseDefns(MAC_HANDLE *handle, const char *defns, char **pairs[])
Parse macro definitions into an array of {name, value} pairs.
#define ellCount(PLIST)
Report the number of nodes in a list.
long dbPutRecordAttribute(DBENTRY *pdbentry, const char *name, const char *value)
int dbFindFieldType(const char *type)
#define CONTAINER(ptr, structure, member)
Find parent object from a member pointer.
void dbFreeEntry(DBENTRY *pdbentry)
DBENTRY * dbAllocEntry(dbBase *pdbbase)
long dbFindRecordType(DBENTRY *pdbentry, const char *recordType)
void dbFinishEntry(DBENTRY *pdbentry)
pvd::StructureConstPtr type
#define S_dbLib_recExists
void dbFreePath(DBBASE *pdbbase)
LIBCOM_API void ellSortStable(ELLLIST *pList, pListCmp pListCmp)
Stable (MergeSort) of a given list.
LIBCOM_API void epicsStdCall freeListInitPvt(void **ppvt, int size, int nmalloc)
long dbNextRecordType(DBENTRY *pdbentry)
#define ELLLIST_INIT
Value of an empty list.
long dbFindRecord(DBENTRY *pdbentry, const char *pname)
Miscellaneous macro definitions.
#define epicsScanDouble(str, to)
A library to manage storage that is allocated and quickly freed.
#define ellPrevious(PNODE)
Find the previous node in list.
long epicsStdCall macExpandString(MAC_HANDLE *handle, const char *src, char *dest, long capacity)
Expand a string which may contain macro references.
char *epicsStdCall macEnvExpand(const char *str)
Expand environment variables in a string.
dbBase * dbAllocBase(void)
int dbTranslateEscape(char *dst, const char *src)
A doubly-linked list library.
void ellAdd(ELLLIST *pList, ELLNODE *pNode)
Adds a node to the end of a list.
LIBCOM_API GPHENTRY *epicsStdCall gphFind(struct gphPvt *pvt, const char *name, void *pvtid)
#define ellNext(PNODE)
Find the next node in list.
struct dbRecordType * pdbRecordType
LIBCOM_API void epicsStdCall freeListCleanup(void *pvt)
maplinkType pamaplinkType[LINK_NTYPES]
void errPrintf(long status, const char *pFileName, int lineno, const char *pformat,...)
enum iocStateEnum getIocState(void)
unsigned int process_passive
LIBCOM_API void errSymLookup(long status, char *pBuf, size_t bufLength)
Macro substitution context, for use by macLib routines only.
void epicsStdCall macSuppressWarning(MAC_HANDLE *handle, int suppress)
Disable or enable warning messages.
LIBCOM_API void epicsStdCall freeListFree(void *pvt, void *pmem)
long dbCreateRecord(DBENTRY *pdbentry, const char *precordName)
char * dbGetRecordName(DBENTRY *pdbentry)
#define ellLast(PLIST)
Find the last node in list.
char * epicsStrDup(const char *s)
epics::pvData::PVStructurePtr dummy
mapspcType pamapspcType[]
long epicsStdCall macDeleteHandle(MAC_HANDLE *handle)
Marks a handle invalid, and frees all storage associated with it.
long epicsStdCall macCreateHandle(MAC_HANDLE **pHandle, const char *pairs[])
Creates a new macro substitution context.
#define dbCalloc(nobj, size)
#define ellInit(PLIST)
Initialize a list type.
void ellInsert(ELLLIST *plist, ELLNODE *pPrev, ELLNODE *pNode)
Inserts a node into a list immediately after a specific node.
long dbReadDatabase(DBBASE **ppdbbase, const char *filename, const char *path, const char *substitutions)
Text macro substitution routines.
long dbFindField(DBENTRY *pdbentry, const char *pname)
long dbPutString(DBENTRY *pdbentry, const char *pstring)
long dbVisibleRecord(DBENTRY *pdbentry)
long dbAddPath(DBBASE *pdbbase, const char *path)
dbMenu * dbFindMenu(dbBase *pdbbase, const char *name)
LIBCOM_API long epicsStdCall macInstallMacros(MAC_HANDLE *handle, char *pairs[])
Install set of {name, value} pairs as definitions.
void ellDelete(ELLLIST *pList, ELLNODE *pNode)
Deletes a node from a list.
long dbReadDatabaseFP(DBBASE **ppdbbase, FILE *fp, const char *path, const char *substitutions)
long dbPutInfo(DBENTRY *pdbentry, const char *name, const char *string)
epicsExportAddress(int, dbRecordsOnceOnly)
LIBCOM_API GPHENTRY *epicsStdCall gphAdd(struct gphPvt *pvt, const char *name, void *pvtid)
char * dbGetRecordTypeName(DBENTRY *pdbentry)
#define ellFirst(PLIST)
Find the first node in list.