/*************************************************************************\ * Copyright (c) 2009 UChicago Argonne LLC, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * EPICS BASE is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ /* Revision-Id: anj@aps.anl.gov-20101005192737-disfz3vs0f3fiixd */ /* Author: Marty Kraimer Date: 13JUL95*/ /*The routines in this module are serially reusable NOT reentrant*/ #include #include #include #include #include "dbmf.h" #include "dbDefs.h" #include "epicsPrint.h" #include "errMdef.h" #include "ellLib.h" #include "gpHash.h" #include "freeList.h" #include "guigroup.h" #include "special.h" #include "macLib.h" #include "epicsString.h" #include "epicsExport.h" #define epicsExportSharedSymbols #include "dbFldTypes.h" #include "link.h" #include "dbStaticLib.h" #include "dbStaticPvt.h" /*global declarations*/ epicsShareDef char *makeDbdDepends=0; epicsShareDef int dbRecordsOnceOnly=0; epicsExportAddress(int,dbRecordsOnceOnly); epicsShareDef int dbBptNotMonotonic=0; epicsExportAddress(int,dbBptNotMonotonic); /*private routines */ static void yyerrorAbort(char *str); static void allocTemp(void *pvoid); static void *popFirstTemp(void); static void *getLastTemp(void); static int db_yyinput(char *buf,int max_size); static void dbIncludePrint(void); static void dbPathCmd(char *path); static void dbAddPathCmd(char *path); static void dbIncludeNew(char *include_file); static void dbMenuHead(char *name); static void dbMenuChoice(char *name,char *value); static void dbMenuBody(void); static void dbRecordtypeHead(char *name); static void dbRecordtypeBody(void); static void dbRecordtypeFieldHead(char *name,char *type); static void dbRecordtypeFieldItem(char *name,char *value); static void dbDevice(char *recordtype,char *linktype, char *dsetname,char *choicestring); static void dbDriver(char *name); static void dbRegistrar(char *name); static void dbFunction(char *name); static void dbVariable(char *name, char *type); static void dbBreakHead(char *name); static void dbBreakItem(char *value); static void dbBreakBody(void); static void dbRecordHead(char *recordType,char*name,int visible); static void dbRecordField(char *name,char *value); static void dbRecordBody(void); /*private declarations*/ #define MY_BUFFER_SIZE 1024 static char *my_buffer=NULL; static char *mac_input_buffer=NULL; static char *my_buffer_ptr=NULL; static MAC_HANDLE *macHandle = NULL; typedef struct inputFile{ ELLNODE node; char *path; char *filename; FILE *fp; int line_num; }inputFile; static ELLLIST inputFileList = ELLLIST_INIT; static inputFile *pinputFileNow = NULL; static DBBASE *pdbbase = NULL; typedef struct tempListNode { ELLNODE node; void *item; }tempListNode; static ELLLIST tempList = ELLLIST_INIT; static void *freeListPvt = NULL; static int duplicate = FALSE; static void yyerrorAbort(char *str) { yyerror(str); yyAbort = TRUE; while (ellCount(&tempList)) popFirstTemp(); } static void allocTemp(void *pvoid) { tempListNode *ptempListNode; ptempListNode = freeListCalloc(freeListPvt); ptempListNode->item = pvoid; ellAdd(&tempList,&ptempListNode->node); } static void *popFirstTemp(void) { tempListNode *ptempListNode; void *ptemp; ptempListNode = (tempListNode *)ellFirst(&tempList); ptemp = ptempListNode->item; ellDelete(&tempList,(ELLNODE *)ptempListNode); freeListFree(freeListPvt,ptempListNode); return(ptemp); } static void *getLastTemp(void) { tempListNode *ptempListNode; ptempListNode = (tempListNode *)ellLast(&tempList); return(ptempListNode->item); } static char *dbOpenFile(DBBASE *pdbbase,const char *filename,FILE **fp) { ELLLIST *ppathList = (ELLLIST *)pdbbase->pathPvt; dbPathNode *pdbPathNode; char *fullfilename; *fp = 0; if (!filename) return 0; if (!ppathList || ellCount(ppathList) == 0 || strchr(filename, '/') || strchr(filename, '\\')) { *fp = fopen(filename, "r"); if (*fp && makeDbdDepends) fprintf(stdout, "%s:%s \n", makeDbdDepends, filename); return 0; } pdbPathNode = (dbPathNode *)ellFirst(ppathList); while (pdbPathNode) { fullfilename = dbMalloc(strlen(pdbPathNode->directory) + strlen(filename) + 2); strcpy(fullfilename, pdbPathNode->directory); strcat(fullfilename, "/"); strcat(fullfilename, filename); *fp = fopen(fullfilename, "r"); if (*fp && makeDbdDepends) fprintf(stdout, "%s:%s \n", makeDbdDepends, fullfilename); free((void *)fullfilename); if (*fp) return pdbPathNode->directory; pdbPathNode = (dbPathNode *)ellNext(&pdbPathNode->node); } return 0; } static void freeInputFileList(void) { inputFile *pinputFileNow; while((pinputFileNow=(inputFile *)ellFirst(&inputFileList))) { if(fclose(pinputFileNow->fp)) errPrintf(0,__FILE__, __LINE__, "Closing file %s",pinputFileNow->filename); free((void *)pinputFileNow->filename); ellDelete(&inputFileList,(ELLNODE *)pinputFileNow); free((void *)pinputFileNow); } } static long dbReadCOM(DBBASE **ppdbbase,const char *filename, FILE *fp, const char *path,const char *substitutions) { long status; inputFile *pinputFile = NULL; char *penv; char **macPairs; if(*ppdbbase == 0) *ppdbbase = dbAllocBase(); pdbbase = *ppdbbase; if(path && strlen(path)>0) { dbPath(pdbbase,path); } else { penv = getenv("EPICS_DB_INCLUDE_PATH"); if(penv) { dbPath(pdbbase,penv); } else { dbPath(pdbbase,"."); } } my_buffer = dbCalloc(MY_BUFFER_SIZE,sizeof(char)); freeListInitPvt(&freeListPvt,sizeof(tempListNode),100); if(substitutions) { if(macCreateHandle(&macHandle,NULL)) { epicsPrintf("macCreateHandle error\n"); status = -1; goto cleanup; } macParseDefns(macHandle,(char *)substitutions,&macPairs); if(macPairs ==NULL) { macDeleteHandle(macHandle); macHandle = NULL; } else { macInstallMacros(macHandle,macPairs); free((void *)macPairs); mac_input_buffer = dbCalloc(MY_BUFFER_SIZE,sizeof(char)); } } pinputFile = dbCalloc(1,sizeof(inputFile)); if(filename) { pinputFile->filename = macEnvExpand(filename); } if(!fp) { FILE *fp1; if(pinputFile->filename) pinputFile->path = dbOpenFile(pdbbase,pinputFile->filename,&fp1); if(!pinputFile->filename || !fp1) { errPrintf(0,__FILE__, __LINE__, "dbRead opening file %s",pinputFile->filename); free((void *)pinputFile->filename); free((void *)pinputFile); status = -1; goto cleanup; } pinputFile->fp = fp1; } else { pinputFile->fp = fp; } pinputFile->line_num = 0; pinputFileNow = pinputFile; my_buffer[0] = '\0'; my_buffer_ptr = my_buffer; ellAdd(&inputFileList,&pinputFile->node); status = pvt_yy_parse(); dbFreePath(pdbbase); if(!status) { /*add RTYP and VERS as an attribute */ DBENTRY dbEntry; DBENTRY *pdbEntry = &dbEntry; long localStatus; dbInitEntry(pdbbase,pdbEntry); localStatus = dbFirstRecordType(pdbEntry); while(!localStatus) { localStatus = dbPutRecordAttribute(pdbEntry,"RTYP", dbGetRecordTypeName(pdbEntry)); if(!localStatus) { localStatus = dbPutRecordAttribute(pdbEntry,"VERS", "none specified"); } if(localStatus) { fprintf(stderr,"dbPutRecordAttribute status %ld\n",status); } else { localStatus = dbNextRecordType(pdbEntry); } } dbFinishEntry(pdbEntry); } cleanup: if(macHandle) macDeleteHandle(macHandle); macHandle = NULL; if(mac_input_buffer) free((void *)mac_input_buffer); mac_input_buffer = NULL; if(freeListPvt) freeListCleanup(freeListPvt); freeListPvt = NULL; if(my_buffer) free((void *)my_buffer); my_buffer = NULL; freeInputFileList(); return(status); } long epicsShareAPI dbReadDatabase(DBBASE **ppdbbase,const char *filename, const char *path,const char *substitutions) {return (dbReadCOM(ppdbbase,filename,0,path,substitutions));} long epicsShareAPI dbReadDatabaseFP(DBBASE **ppdbbase,FILE *fp, const char *path,const char *substitutions) {return (dbReadCOM(ppdbbase,0,fp,path,substitutions));} static int db_yyinput(char *buf, int max_size) { int l,n; char *fgetsRtn; if(yyAbort) return(0); if(*my_buffer_ptr==0) { while(TRUE) { /*until we get some input*/ if(macHandle) { fgetsRtn = fgets(mac_input_buffer,MY_BUFFER_SIZE, pinputFileNow->fp); if(fgetsRtn) { n = macExpandString(macHandle,mac_input_buffer, my_buffer,MY_BUFFER_SIZE); if(n<0) { errPrintf(0,__FILE__, __LINE__, "macExpandString failed for file %s", pinputFileNow->filename); } } } else { fgetsRtn = fgets(my_buffer,MY_BUFFER_SIZE,pinputFileNow->fp); } if(fgetsRtn) break; if(fclose(pinputFileNow->fp)) errPrintf(0,__FILE__, __LINE__, "Closing file %s",pinputFileNow->filename); free((void *)pinputFileNow->filename); ellDelete(&inputFileList,(ELLNODE *)pinputFileNow); free((void *)pinputFileNow); pinputFileNow = (inputFile *)ellLast(&inputFileList); if(!pinputFileNow) return(0); } if(dbStaticDebug) fprintf(stderr,"%s",my_buffer); pinputFileNow->line_num++; my_buffer_ptr = &my_buffer[0]; } l = strlen(my_buffer_ptr); n = (l<=max_size ? l : max_size); memcpy(buf,my_buffer_ptr,n); my_buffer_ptr += n; return(n); } static void dbIncludePrint(void) { inputFile *pinputFile = pinputFileNow; while (pinputFile) { epicsPrintf(" in"); if (pinputFile->path) epicsPrintf(" path \"%s\" ",pinputFile->path); if (pinputFile->filename) { epicsPrintf(" file \"%s\"",pinputFile->filename); } else { epicsPrintf(" standard input"); } epicsPrintf(" line %d\n",pinputFile->line_num); pinputFile = (inputFile *)ellPrevious(&pinputFile->node); } return; } static void dbPathCmd(char *path) { dbPath(pdbbase,path); } static void dbAddPathCmd(char *path) { dbAddPath(pdbbase,path); } static void dbIncludeNew(char *filename) { inputFile *pinputFile; FILE *fp; pinputFile = dbCalloc(1,sizeof(inputFile)); pinputFile->filename = macEnvExpand(filename); pinputFile->path = dbOpenFile(pdbbase, pinputFile->filename, &fp); if (!fp) { epicsPrintf("Can't open include file \"%s\"\n", filename); yyerror(NULL); free((void *)pinputFile->filename); free((void *)pinputFile); return; } pinputFile->fp = fp; ellAdd(&inputFileList,&pinputFile->node); pinputFileNow = pinputFile; } static void dbMenuHead(char *name) { dbMenu *pdbMenu; GPHENTRY *pgphentry; pgphentry = gphFind(pdbbase->pgpHash,name,&pdbbase->menuList); if(pgphentry) { duplicate = TRUE; return; } if(ellCount(&tempList)) yyerrorAbort("dbMenuHead: tempList not empty"); pdbMenu = dbCalloc(1,sizeof(dbMenu)); pdbMenu->name = epicsStrDup(name); allocTemp(pdbMenu); } static void dbMenuChoice(char *name,char *value) { if(duplicate) return; allocTemp(epicsStrDup(name)); allocTemp(epicsStrDup(value)); } static void dbMenuBody(void) { dbMenu *pnewMenu; dbMenu *pMenu; int nChoice; int i; GPHENTRY *pgphentry; if(duplicate) { duplicate = FALSE; return; } pnewMenu = (dbMenu *)popFirstTemp(); pnewMenu->nChoice = nChoice = ellCount(&tempList)/2; pnewMenu->papChoiceName = dbCalloc(pnewMenu->nChoice,sizeof(char *)); pnewMenu->papChoiceValue = dbCalloc(pnewMenu->nChoice,sizeof(char *)); for(i=0; ipapChoiceName[i] = (char *)popFirstTemp(); pnewMenu->papChoiceValue[i] = (char *)popFirstTemp(); } if(ellCount(&tempList)) yyerrorAbort("dbMenuBody: tempList not empty"); /* Add menu in sorted order */ pMenu = (dbMenu *)ellFirst(&pdbbase->menuList); while(pMenu && strcmp(pMenu->name,pnewMenu->name) >0 ) pMenu = (dbMenu *)ellNext(&pMenu->node); if(pMenu) ellInsert(&pdbbase->menuList,ellPrevious(&pMenu->node),&pnewMenu->node); else ellAdd(&pdbbase->menuList,&pnewMenu->node); pgphentry = gphAdd(pdbbase->pgpHash,pnewMenu->name,&pdbbase->menuList); if(!pgphentry) { yyerrorAbort("gphAdd failed"); } else { pgphentry->userPvt = pnewMenu; } } static void dbRecordtypeHead(char *name) { dbRecordType *pdbRecordType; GPHENTRY *pgphentry; pgphentry = gphFind(pdbbase->pgpHash,name,&pdbbase->recordTypeList); if(pgphentry) { duplicate = TRUE; return; } pdbRecordType = dbCalloc(1,sizeof(dbRecordType)); pdbRecordType->name = epicsStrDup(name); if (pdbbase->loadCdefs) ellInit(&pdbRecordType->cdefList); if(ellCount(&tempList)) yyerrorAbort("dbRecordtypeHead tempList not empty"); allocTemp(pdbRecordType); } static void dbRecordtypeFieldHead(char *name,char *type) { dbFldDes *pdbFldDes; int i; if(duplicate) return; pdbFldDes = dbCalloc(1,sizeof(dbFldDes)); allocTemp(pdbFldDes); pdbFldDes->name = epicsStrDup(name); pdbFldDes->as_level = ASL1; for(i=0; ifield_type = pamapdbfType[i].value; return; } } yyerrorAbort("Illegal Field Type"); } static void dbRecordtypeFieldItem(char *name,char *value) { dbFldDes *pdbFldDes; if(duplicate) return; pdbFldDes = (dbFldDes *)getLastTemp(); if(strcmp(name,"asl")==0) { if(strcmp(value,"ASL0")==0) { pdbFldDes->as_level = ASL0; } else if(strcmp(value,"ASL1")==0) { pdbFldDes->as_level = ASL1; } else { yyerror("Illegal Access Security value: Must be ASL0 or ASL1"); } return; } if(strcmp(name,"initial")==0) { pdbFldDes->initial = epicsStrDup(value); return; } if(strcmp(name,"promptgroup")==0) { int i; for(i=0; ipromptgroup = pamapguiGroup[i].value; return; } } yyerror("Illegal promptgroup. See guigroup.h for legal values"); return; } if(strcmp(name,"prompt")==0) { pdbFldDes->prompt = epicsStrDup(value); return; } if(strcmp(name,"special")==0) { int i; for(i=0; ispecial = pamapspcType[i].value; return; } } if(sscanf(value,"%hd",&pdbFldDes->special)==1) { return; } yyerror("Illegal special value."); return; } if(strcmp(name,"pp")==0) { if((strcmp(value,"YES")==0) || (strcmp(value,"TRUE")==0)) { pdbFldDes->process_passive = TRUE; } else if((strcmp(value,"NO")==0) || (strcmp(value,"FALSE")==0)) { pdbFldDes->process_passive = FALSE; } else { yyerror("Illegal value. Must be NO or YES"); } return; } if(strcmp(name,"interest")==0) { if(sscanf(value,"%hd",&pdbFldDes->interest)!=1) yyerror("Illegal value. Must be integer"); return; } if(strcmp(name,"base")==0) { if(strcmp(value,"DECIMAL")==0) { pdbFldDes->base = CT_DECIMAL; } else if(strcmp(value,"HEX")==0) { pdbFldDes->base = CT_HEX; } else { yyerror("Illegal value. Must be CT_DECIMAL or CT_HEX"); } return; } if(strcmp(name,"size")==0) { if(sscanf(value,"%hd",&pdbFldDes->size)!=1) yyerror("Illegal value. Must be integer"); return; } if(strcmp(name,"extra")==0) { pdbFldDes->extra = epicsStrDup(value); return; } if(strcmp(name,"menu")==0) { pdbFldDes->ftPvt = (dbMenu *)dbFindMenu(pdbbase,value); if(!pdbbase->ignoreMissingMenus && !pdbFldDes->ftPvt) yyerrorAbort("menu not found"); return; } } static void dbRecordtypeCdef(char *text) { dbText *pdbCdef; tempListNode *ptempListNode; dbRecordType *pdbRecordType; if (!pdbbase->loadCdefs || duplicate) return; ptempListNode = (tempListNode *)ellFirst(&tempList); pdbRecordType = ptempListNode->item; pdbCdef = dbCalloc(1,sizeof(dbText)); if (text[0] == ' ') text++; /* strip leading space if present */ pdbCdef->text = epicsStrDup(text); ellAdd(&pdbRecordType->cdefList, &pdbCdef->node); return; } static void dbRecordtypeBody(void) { dbRecordType *pdbRecordType; dbFldDes *pdbFldDes; int i,j,ilink; GPHENTRY *pgphentry; int no_fields,no_prompt,no_links; dbfType field_type; char *psortFldNameTemp; short psortFldIndTemp; char **papsortFldName; short *sortFldInd; if(duplicate) { duplicate = FALSE; return; } pdbRecordType= (dbRecordType *)popFirstTemp(); pdbRecordType->no_fields = no_fields = ellCount(&tempList); pdbRecordType->papFldDes = dbCalloc(no_fields,sizeof(dbFldDes *)); pdbRecordType->papsortFldName = dbCalloc(no_fields,sizeof(char *)); pdbRecordType->sortFldInd = dbCalloc(no_fields,sizeof(short)); no_prompt = no_links = 0; for(i=0; ipdbRecordType = pdbRecordType; pdbFldDes->indRecordType = i; pdbRecordType->papFldDes[i] = pdbFldDes; if(pdbFldDes->promptgroup) no_prompt++; field_type = pdbFldDes->field_type; if((field_type>=DBF_INLINK) && (field_type<=DBF_FWDLINK))no_links++; if((field_type==DBF_STRING) && (pdbFldDes->size==0)) fprintf(stderr,"recordtype(%s).%s size not specified\n", pdbRecordType->name,pdbFldDes->name); if((field_type==DBF_NOACCESS) && (pdbFldDes->extra==0)) fprintf(stderr,"recordtype(%s).%s extra not specified\n", pdbRecordType->name,pdbFldDes->name); } if(ellCount(&tempList)) yyerrorAbort("dbMenuBody: tempList not empty"); pdbRecordType->no_prompt = no_prompt; pdbRecordType->no_links = no_links; pdbRecordType->link_ind = dbCalloc(no_links,sizeof(short)); ilink = 0; for(i=0; ipapFldDes[i]; /* if prompt is null make it a null string */ if(!pdbFldDes->prompt) pdbFldDes->prompt = dbCalloc(1,sizeof(char)); field_type = pdbFldDes->field_type; if((field_type>=DBF_INLINK) && (field_type<=DBF_FWDLINK)) pdbRecordType->link_ind[ilink++] = i; if(strcmp(pdbFldDes->name,"VAL")==0) { pdbRecordType->pvalFldDes = pdbRecordType->papFldDes[i]; pdbRecordType->indvalFlddes = i; } pdbRecordType->papsortFldName[i] = pdbFldDes->name; pdbRecordType->sortFldInd[i] = i; } /*Now sort fields. Sorry dumb sort algorithm */ papsortFldName = pdbRecordType->papsortFldName; sortFldInd = pdbRecordType->sortFldInd; for(i=0; iattributeList); ellInit(&pdbRecordType->recList); ellInit(&pdbRecordType->devList); pgphentry = gphAdd(pdbbase->pgpHash,pdbRecordType->name, &pdbbase->recordTypeList); if(!pgphentry) { yyerrorAbort("gphAdd failed"); } else { pgphentry->userPvt = pdbRecordType; } ellAdd(&pdbbase->recordTypeList,&pdbRecordType->node); } static void dbDevice(char *recordtype,char *linktype, char *dsetname,char *choicestring) { devSup *pdevSup; dbRecordType *pdbRecordType; GPHENTRY *pgphentry; int i,link_type; pgphentry = gphFind(pdbbase->pgpHash,recordtype,&pdbbase->recordTypeList); if(!pgphentry) { epicsPrintf("Record type \"%s\" not found for device \"%s\"\n", recordtype, choicestring); yyerror(NULL); return; } link_type=-1; for(i=0; iuserPvt; pgphentry = gphFind(pdbbase->pgpHash,choicestring,&pdbRecordType->devList); if(pgphentry) { return; } pdevSup = dbCalloc(1,sizeof(devSup)); pdevSup->name = epicsStrDup(dsetname); pdevSup->choice = epicsStrDup(choicestring); pdevSup->link_type = link_type; pgphentry = gphAdd(pdbbase->pgpHash,pdevSup->choice,&pdbRecordType->devList); if(!pgphentry) { yyerrorAbort("gphAdd failed"); } else { pgphentry->userPvt = pdevSup; } ellAdd(&pdbRecordType->devList,&pdevSup->node); } static void dbDriver(char *name) { drvSup *pdrvSup; GPHENTRY *pgphentry; pgphentry = gphFind(pdbbase->pgpHash,name,&pdbbase->drvList); if(pgphentry) { return; } pdrvSup = dbCalloc(1,sizeof(drvSup)); pdrvSup->name = epicsStrDup(name); pgphentry = gphAdd(pdbbase->pgpHash,pdrvSup->name,&pdbbase->drvList); if(!pgphentry) { yyerrorAbort("gphAdd failed"); } pgphentry->userPvt = pdrvSup; ellAdd(&pdbbase->drvList,&pdrvSup->node); } static void dbRegistrar(char *name) { dbText *ptext; GPHENTRY *pgphentry; pgphentry = gphFind(pdbbase->pgpHash,name,&pdbbase->registrarList); if(pgphentry) { return; } ptext = dbCalloc(1,sizeof(dbText)); ptext->text = epicsStrDup(name); pgphentry = gphAdd(pdbbase->pgpHash,ptext->text,&pdbbase->registrarList); if(!pgphentry) { yyerrorAbort("gphAdd failed"); } pgphentry->userPvt = ptext; ellAdd(&pdbbase->registrarList,&ptext->node); } static void dbFunction(char *name) { dbText *ptext; GPHENTRY *pgphentry; pgphentry = gphFind(pdbbase->pgpHash,name,&pdbbase->functionList); if(pgphentry) { return; } ptext = dbCalloc(1,sizeof(dbText)); ptext->text = epicsStrDup(name); pgphentry = gphAdd(pdbbase->pgpHash,ptext->text,&pdbbase->functionList); if(!pgphentry) { yyerrorAbort("gphAdd failed"); } pgphentry->userPvt = ptext; ellAdd(&pdbbase->functionList,&ptext->node); } static void dbVariable(char *name, char *type) { dbVariableDef *pvar; GPHENTRY *pgphentry; pgphentry = gphFind(pdbbase->pgpHash,name,&pdbbase->variableList); if(pgphentry) { return; } pvar = dbCalloc(1,sizeof(dbVariableDef)); pvar->name = epicsStrDup(name); pvar->type = epicsStrDup(type); pgphentry = gphAdd(pdbbase->pgpHash,pvar->name,&pdbbase->variableList); if(!pgphentry) { yyerrorAbort("gphAdd failed"); } pgphentry->userPvt = pvar; ellAdd(&pdbbase->variableList,&pvar->node); } static void dbBreakHead(char *name) { brkTable *pbrkTable; GPHENTRY *pgphentry; pgphentry = gphFind(pdbbase->pgpHash,name,&pdbbase->bptList); if(pgphentry) { duplicate = TRUE; return; } pbrkTable = dbCalloc(1,sizeof(brkTable)); pbrkTable->name = epicsStrDup(name); if(ellCount(&tempList)) yyerrorAbort("dbBreakHead:tempList not empty"); allocTemp(pbrkTable); } static void dbBreakItem(char *value) { double dummy; if (duplicate) return; if (epicsScanDouble(value, &dummy) != 1) { yyerrorAbort("Non-numeric value in breaktable"); } allocTemp(epicsStrDup(value)); } static void dbBreakBody(void) { brkTable *pnewbrkTable; brkInt *paBrkInt; brkTable *pbrkTable; int number, down=0; int i; GPHENTRY *pgphentry; if (duplicate) { duplicate = FALSE; return; } pnewbrkTable = (brkTable *)popFirstTemp(); number = ellCount(&tempList); if (number % 2) { yyerrorAbort("breaktable: Raw value missing"); return; } number /= 2; if (number < 2) { yyerrorAbort("breaktable: Must have at least two points!"); return; } pnewbrkTable->number = number; pnewbrkTable->paBrkInt = paBrkInt = dbCalloc(number, sizeof(brkInt)); for (i=0; ibptList); while (pbrkTable) { if (strcmp(pbrkTable->name, pnewbrkTable->name) > 0) { ellInsert(&pdbbase->bptList, ellPrevious((ELLNODE *)pbrkTable), (ELLNODE *)pnewbrkTable); break; } pbrkTable = (brkTable *)ellNext(&pbrkTable->node); } if (!pbrkTable) ellAdd(&pdbbase->bptList, &pnewbrkTable->node); pgphentry = gphAdd(pdbbase->pgpHash,pnewbrkTable->name,&pdbbase->bptList); if (!pgphentry) { yyerrorAbort("dbBreakBody: gphAdd failed"); return; } pgphentry->userPvt = pnewbrkTable; } static void dbRecordHead(char *recordType,char *name, int visible) { DBENTRY *pdbentry; long status; pdbentry = dbAllocEntry(pdbbase); if(ellCount(&tempList)) yyerrorAbort("dbRecordHead: tempList not empty"); allocTemp(pdbentry); status = dbFindRecordType(pdbentry,recordType); if(status) { epicsPrintf("Record \"%s\" is of unknown type \"%s\" - ", name, recordType); yyerrorAbort(NULL); return; } /*Duplicate records ok if the same type */ status = dbCreateRecord(pdbentry,name); if(status==S_dbLib_recExists) { if(strcmp(recordType,dbGetRecordTypeName(pdbentry))!=0) { epicsPrintf("Record %s already defined with different type %s\n", name, dbGetRecordTypeName(pdbentry)); yyerror(NULL); duplicate = TRUE; return; } else if (dbRecordsOnceOnly) { epicsPrintf("Record \"%s\" already defined (dbRecordsOnceOnly is set)\n", name); yyerror(NULL); duplicate = TRUE; } } else if(status) { epicsPrintf("Can't create record \"%s\" of type \"%s\"\n", name, recordType); yyerrorAbort(NULL); } if(visible) dbVisibleRecord(pdbentry); } static void dbRecordField(char *name,char *value) { DBENTRY *pdbentry; tempListNode *ptempListNode; long status; if(duplicate) return; ptempListNode = (tempListNode *)ellFirst(&tempList); pdbentry = ptempListNode->item; status = dbFindField(pdbentry,name); if(status) { epicsPrintf("Record \"%s\" does not have a field \"%s\"\n", dbGetRecordName(pdbentry), name); yyerror(NULL); return; } dbTranslateEscape(value, value); /* yuck: in-place, but safe */ status = dbPutString(pdbentry,value); if(status) { epicsPrintf("Can't set \"%s.%s\" to \"%s\"\n", dbGetRecordName(pdbentry), name, value); yyerror(NULL); return; } } static void dbRecordInfo(char *name, char *value) { DBENTRY *pdbentry; tempListNode *ptempListNode; long status; if(duplicate) return; ptempListNode = (tempListNode *)ellFirst(&tempList); pdbentry = ptempListNode->item; status = dbPutInfo(pdbentry,name,value); if(status) { epicsPrintf("Can't set \"%s\" info \"%s\" to \"%s\"\n", dbGetRecordName(pdbentry), name, value); yyerror(NULL); return; } } static void dbRecordAlias(char *name) { DBENTRY *pdbentry; tempListNode *ptempListNode; long status; if(duplicate) return; ptempListNode = (tempListNode *)ellFirst(&tempList); pdbentry = ptempListNode->item; status = dbCreateAlias(pdbentry, name); if(status) { epicsPrintf("Can't create alias \"%s\" for \"%s\"\n", name, dbGetRecordName(pdbentry)); yyerror(NULL); return; } } static void dbAlias(char *name, char *alias) { DBENTRY dbEntry; DBENTRY *pdbEntry = &dbEntry; dbInitEntry(pdbbase, pdbEntry); if (dbFindRecord(pdbEntry, name)) { epicsPrintf("Alias \"%s\" refers to unknown record \"%s\"\n", alias, name); yyerror(NULL); } else if (dbCreateAlias(pdbEntry, alias)) { epicsPrintf("Can't create alias \"%s\" referring to \"%s\"\n", alias, name); yyerror(NULL); } dbFinishEntry(pdbEntry); } static void dbRecordBody(void) { DBENTRY *pdbentry; if(duplicate) { duplicate = FALSE; return; } pdbentry = (DBENTRY *)popFirstTemp(); if(ellCount(&tempList)) yyerrorAbort("dbRecordBody: tempList not empty"); dbFreeEntry(pdbentry); }