This is Unofficial EPICS BASE Doxygen Site
dbLexRoutines.c
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2009 UChicago Argonne LLC, as Operator of Argonne
3 * National Laboratory.
4 * Copyright (c) 2002 The Regents of the University of California, as
5 * Operator of Los Alamos National Laboratory.
6 * EPICS BASE is distributed subject to a Software License Agreement found
7 * in file LICENSE that is included with this distribution.
8 \*************************************************************************/
9 
10 /* Author: Marty Kraimer Date: 13JUL95*/
11 
12 /*The routines in this module are serially reusable NOT reentrant*/
13 
14 #include <ctype.h>
15 #include <epicsStdlib.h>
16 #include <stddef.h>
17 #include <stdio.h>
18 #include <string.h>
19 
20 #include "dbDefs.h"
21 #include "dbmf.h"
22 #include "ellLib.h"
23 #include "epicsPrint.h"
24 #include "epicsString.h"
25 #include "errMdef.h"
26 #include "freeList.h"
27 #include "gpHash.h"
28 #include "macLib.h"
29 
30 #define epicsExportSharedSymbols
31 #include "dbBase.h"
32 #include "dbFldTypes.h"
33 #include "dbStaticLib.h"
34 #include "dbStaticPvt.h"
35 #include "epicsExport.h"
36 #include "link.h"
37 #include "special.h"
38 #include "iocInit.h"
39 
40 
41 
42 /*global declarations*/
44 
47 
50 
53 
56 
57 /*private routines */
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);
70 
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);
77 
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);
85 
86 static void dbBreakHead(char *name);
87 static void dbBreakItem(char *value);
88 static void dbBreakBody(void);
89 
90 static void dbRecordHead(char *recordType,char*name,int visible);
91 static void dbRecordField(char *name,char *value);
92 static void dbRecordBody(void);
93 
94 /*private declarations*/
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;
99 static MAC_HANDLE *macHandle = NULL;
100 typedef struct inputFile{
102  char *path;
103  char *filename;
104  FILE *fp;
105  int line_num;
106 }inputFile;
107 static ELLLIST inputFileList = ELLLIST_INIT;
108 
109 static inputFile *pinputFileNow = NULL;
110 static DBBASE *pdbbase = NULL;
111 
112 typedef struct tempListNode {
114  void *item;
115 }tempListNode;
116 
117 static ELLLIST tempList = ELLLIST_INIT;
118 static void *freeListPvt = NULL;
119 static int duplicate = FALSE;
120 
121 static void yyerrorAbort(char *str)
122 {
123  yyerror(str);
124  yyAbort = TRUE;
125 }
126 
127 static void allocTemp(void *pvoid)
128 {
129  tempListNode *ptempListNode;
130 
131  ptempListNode = freeListCalloc(freeListPvt);
132  ptempListNode->item = pvoid;
133  ellAdd(&tempList,&ptempListNode->node);
134 }
135 
136 static void *popFirstTemp(void)
137 {
138  tempListNode *ptempListNode;
139  void *ptemp;
140 
141  ptempListNode = (tempListNode *)ellFirst(&tempList);
142  ptemp = ptempListNode->item;
143  ellDelete(&tempList,(ELLNODE *)ptempListNode);
144  freeListFree(freeListPvt,ptempListNode);
145  return(ptemp);
146 }
147 
148 static void *getLastTemp(void)
149 {
150  tempListNode *ptempListNode;
151 
152  ptempListNode = (tempListNode *)ellLast(&tempList);
153  return(ptempListNode->item);
154 }
155 
156 static char *dbOpenFile(DBBASE *pdbbase,const char *filename,FILE **fp)
157 {
158  ELLLIST *ppathList = (ELLLIST *)pdbbase->pathPvt;
159  dbPathNode *pdbPathNode;
160  char *fullfilename;
161 
162  *fp = 0;
163  if (!filename) return 0;
164  if (!ppathList || ellCount(ppathList) == 0 ||
165  strchr(filename, '/') || strchr(filename, '\\')) {
166  *fp = fopen(filename, "r");
167  if (*fp && makeDbdDepends)
168  fprintf(stdout, "%s:%s \n", makeDbdDepends, filename);
169  return 0;
170  }
171  pdbPathNode = (dbPathNode *)ellFirst(ppathList);
172  while (pdbPathNode) {
173  fullfilename = dbMalloc(strlen(pdbPathNode->directory) +
174  strlen(filename) + 2);
175  strcpy(fullfilename, pdbPathNode->directory);
176  strcat(fullfilename, "/");
177  strcat(fullfilename, filename);
178  *fp = fopen(fullfilename, "r");
179  if (*fp && makeDbdDepends)
180  fprintf(stdout, "%s:%s \n", makeDbdDepends, fullfilename);
181  free((void *)fullfilename);
182  if (*fp) return pdbPathNode->directory;
183  pdbPathNode = (dbPathNode *)ellNext(&pdbPathNode->node);
184  }
185  return 0;
186 }
187 
188 
189 static void freeInputFileList(void)
190 {
191  inputFile *pinputFileNow;
192 
193  while((pinputFileNow=(inputFile *)ellFirst(&inputFileList))) {
194  if(fclose(pinputFileNow->fp))
195  errPrintf(0,__FILE__, __LINE__,
196  "Closing file %s",pinputFileNow->filename);
197  free((void *)pinputFileNow->filename);
198  ellDelete(&inputFileList,(ELLNODE *)pinputFileNow);
199  free((void *)pinputFileNow);
200  }
201 }
202 
203 static
204 int cmp_dbRecordNode(const ELLNODE *lhs, const ELLNODE *rhs)
205 {
206  dbRecordNode *LHS = (dbRecordNode*)lhs,
207  *RHS = (dbRecordNode*)rhs;
208 
209  return strcmp(LHS->recordname, RHS->recordname);
210 }
211 
212 static long dbReadCOM(DBBASE **ppdbbase,const char *filename, FILE *fp,
213  const char *path,const char *substitutions)
214 {
215  long status;
216  inputFile *pinputFile = NULL;
217  char *penv;
218  char **macPairs;
219 
220  if (ellCount(&tempList)) {
221  epicsPrintf("dbReadCOM: Parser stack dirty %d\n", ellCount(&tempList));
222  }
223 
224  if (getIocState() != iocVoid)
225  return -2;
226 
227  if(*ppdbbase == 0) *ppdbbase = dbAllocBase();
228  pdbbase = *ppdbbase;
229  if(path && strlen(path)>0) {
230  dbPath(pdbbase,path);
231  } else {
232  penv = getenv("EPICS_DB_INCLUDE_PATH");
233  if(penv) {
234  dbPath(pdbbase,penv);
235  } else {
236  dbPath(pdbbase,".");
237  }
238  }
239  my_buffer = dbCalloc(MY_BUFFER_SIZE,sizeof(char));
240  freeListInitPvt(&freeListPvt,sizeof(tempListNode),100);
241  if(substitutions) {
242  if(macCreateHandle(&macHandle,NULL)) {
243  epicsPrintf("macCreateHandle error\n");
244  status = -1;
245  goto cleanup;
246  }
247  macParseDefns(macHandle,(char *)substitutions,&macPairs);
248  if(macPairs ==NULL) {
249  macDeleteHandle(macHandle);
250  macHandle = NULL;
251  } else {
252  macInstallMacros(macHandle,macPairs);
253  free((void *)macPairs);
254  mac_input_buffer = dbCalloc(MY_BUFFER_SIZE,sizeof(char));
255  }
257  }
258  pinputFile = dbCalloc(1,sizeof(inputFile));
259  if (filename) {
260  pinputFile->filename = macEnvExpand(filename);
261  }
262  if (!fp) {
263  FILE *fp1 = 0;
264 
265  if (pinputFile->filename)
266  pinputFile->path = dbOpenFile(pdbbase, pinputFile->filename, &fp1);
267  if (!pinputFile->filename || !fp1) {
268  errPrintf(0, __FILE__, __LINE__,
269  "dbRead opening file %s",pinputFile->filename);
270  free(pinputFile->filename);
271  free(pinputFile);
272  status = -1;
273  goto cleanup;
274  }
275  pinputFile->fp = fp1;
276  } else {
277  pinputFile->fp = fp;
278  }
279  pinputFile->line_num = 0;
280  pinputFileNow = pinputFile;
281  my_buffer[0] = '\0';
282  my_buffer_ptr = my_buffer;
283  ellAdd(&inputFileList,&pinputFile->node);
284  status = pvt_yy_parse();
285 
286  if (ellCount(&tempList) && !yyAbort)
287  epicsPrintf("dbReadCOM: Parser stack dirty w/o error. %d\n", ellCount(&tempList));
288  while (ellCount(&tempList))
289  popFirstTemp(); /* Memory leak on parser failure */
290 
291  dbFreePath(pdbbase);
292  if(!status) { /*add RTYP and VERS as an attribute */
294  DBENTRY *pdbEntry = &dbEntry;
295  long localStatus;
296 
297  dbInitEntry(pdbbase,pdbEntry);
298  localStatus = dbFirstRecordType(pdbEntry);
299  while(!localStatus) {
300  localStatus = dbPutRecordAttribute(pdbEntry,"RTYP",
301  dbGetRecordTypeName(pdbEntry));
302  if(!localStatus) {
303  localStatus = dbPutRecordAttribute(pdbEntry,"VERS",
304  "none specified");
305  }
306  if(localStatus) {
307  fprintf(stderr,"dbPutRecordAttribute status %ld\n",status);
308  } else {
309  localStatus = dbNextRecordType(pdbEntry);
310  }
311  }
312  dbFinishEntry(pdbEntry);
313  }
314 cleanup:
315  if(dbRecordsAbcSorted) {
316  ELLNODE *cur;
317  for(cur = ellFirst(&pdbbase->recordTypeList); cur; cur=ellNext(cur))
318  {
319  dbRecordType *rtype = CONTAINER(cur, dbRecordType, node);
320 
321  ellSortStable(&rtype->recList, &cmp_dbRecordNode);
322  }
323  }
324  if(macHandle) macDeleteHandle(macHandle);
325  macHandle = NULL;
326  if(mac_input_buffer) free((void *)mac_input_buffer);
327  mac_input_buffer = NULL;
328  if(freeListPvt) freeListCleanup(freeListPvt);
329  freeListPvt = NULL;
330  if(my_buffer) free((void *)my_buffer);
331  my_buffer = NULL;
332  freeInputFileList();
333  return(status);
334 }
335 
336 long dbReadDatabase(DBBASE **ppdbbase,const char *filename,
337  const char *path,const char *substitutions)
338 {return (dbReadCOM(ppdbbase,filename,0,path,substitutions));}
339 
340 long dbReadDatabaseFP(DBBASE **ppdbbase,FILE *fp,
341  const char *path,const char *substitutions)
342 {return (dbReadCOM(ppdbbase,0,fp,path,substitutions));}
343 
344 static int db_yyinput(char *buf, int max_size)
345 {
346  size_t l,n;
347  char *fgetsRtn;
348 
349  if(yyAbort) return(0);
350  if(*my_buffer_ptr==0) {
351  while(TRUE) { /*until we get some input*/
352  if(macHandle) {
353  fgetsRtn = fgets(mac_input_buffer,MY_BUFFER_SIZE,
354  pinputFileNow->fp);
355  if(fgetsRtn) {
356  int exp = macExpandString(macHandle,mac_input_buffer,
357  my_buffer,MY_BUFFER_SIZE);
358  if (exp < 0) {
359  fprintf(stderr, "Warning: '%s' line %d has undefined macros\n",
360  pinputFileNow->filename, pinputFileNow->line_num+1);
361  }
362  }
363  } else {
364  fgetsRtn = fgets(my_buffer,MY_BUFFER_SIZE,pinputFileNow->fp);
365  }
366  if(fgetsRtn) break;
367  if(fclose(pinputFileNow->fp))
368  errPrintf(0,__FILE__, __LINE__,
369  "Closing file %s",pinputFileNow->filename);
370  free((void *)pinputFileNow->filename);
371  ellDelete(&inputFileList,(ELLNODE *)pinputFileNow);
372  free((void *)pinputFileNow);
373  pinputFileNow = (inputFile *)ellLast(&inputFileList);
374  if(!pinputFileNow) return(0);
375  }
376  if(dbStaticDebug) fprintf(stderr,"%s",my_buffer);
377  pinputFileNow->line_num++;
378  my_buffer_ptr = &my_buffer[0];
379  }
380  l = strlen(my_buffer_ptr);
381  n = (l<=max_size ? l : max_size);
382  memcpy(buf,my_buffer_ptr,n);
383  my_buffer_ptr += n;
384  return (int)n;
385 }
386 
387 static void dbIncludePrint(void)
388 {
389  inputFile *pinputFile = pinputFileNow;
390 
391  while (pinputFile) {
392  epicsPrintf(" in");
393  if (pinputFile->path)
394  epicsPrintf(" path \"%s\" ",pinputFile->path);
395  if (pinputFile->filename) {
396  epicsPrintf(" file \"%s\"",pinputFile->filename);
397  } else {
398  epicsPrintf(" standard input");
399  }
400  epicsPrintf(" line %d\n",pinputFile->line_num);
401  pinputFile = (inputFile *)ellPrevious(&pinputFile->node);
402  }
403  return;
404 }
405 
406 static void dbPathCmd(char *path)
407 {
408  dbPath(pdbbase,path);
409 }
410 
411 static void dbAddPathCmd(char *path)
412 {
413  dbAddPath(pdbbase,path);
414 }
415 
416 static void dbIncludeNew(char *filename)
417 {
418  inputFile *pinputFile;
419  FILE *fp;
420 
421  pinputFile = dbCalloc(1,sizeof(inputFile));
422  pinputFile->filename = macEnvExpand(filename);
423  pinputFile->path = dbOpenFile(pdbbase, pinputFile->filename, &fp);
424  if (!fp) {
425  epicsPrintf("Can't open include file \"%s\"\n", filename);
426  yyerror(NULL);
427  free((void *)pinputFile->filename);
428  free((void *)pinputFile);
429  return;
430  }
431  pinputFile->fp = fp;
432  ellAdd(&inputFileList,&pinputFile->node);
433  pinputFileNow = pinputFile;
434 }
435 
436 static void dbMenuHead(char *name)
437 {
438  dbMenu *pdbMenu;
439  GPHENTRY *pgphentry;
440 
441  if (!*name) {
442  yyerrorAbort("dbMenuHead: Menu name can't be empty");
443  return;
444  }
445  pgphentry = gphFind(pdbbase->pgpHash,name,&pdbbase->menuList);
446  if(pgphentry) {
447  duplicate = TRUE;
448  return;
449  }
450  if(ellCount(&tempList)) yyerrorAbort("dbMenuHead: tempList not empty");
451  pdbMenu = dbCalloc(1,sizeof(dbMenu));
452  pdbMenu->name = epicsStrDup(name);
453  allocTemp(pdbMenu);
454 }
455 
456 static void dbMenuChoice(char *name,char *value)
457 {
458  if (!*name) {
459  yyerror("dbMenuChoice: Menu choice name can't be empty");
460  return;
461  }
462  if(duplicate) return;
463  allocTemp(epicsStrDup(name));
464  allocTemp(epicsStrDup(value));
465 }
466 
467 static void dbMenuBody(void)
468 {
469  dbMenu *pnewMenu;
470  dbMenu *pMenu;
471  int nChoice;
472  int i;
473  GPHENTRY *pgphentry;
474 
475  if(duplicate) {
476  duplicate = FALSE;
477  return;
478  }
479  pnewMenu = (dbMenu *)popFirstTemp();
480  pnewMenu->nChoice = nChoice = ellCount(&tempList)/2;
481  pnewMenu->papChoiceName = dbCalloc(pnewMenu->nChoice,sizeof(char *));
482  pnewMenu->papChoiceValue = dbCalloc(pnewMenu->nChoice,sizeof(char *));
483  for(i=0; i<nChoice; i++) {
484  pnewMenu->papChoiceName[i] = (char *)popFirstTemp();
485  pnewMenu->papChoiceValue[i] = (char *)popFirstTemp();
486  }
487  if(ellCount(&tempList)) yyerrorAbort("dbMenuBody: tempList not empty");
488  /* Add menu in sorted order */
489  pMenu = (dbMenu *)ellFirst(&pdbbase->menuList);
490  while(pMenu && strcmp(pMenu->name,pnewMenu->name) >0 )
491  pMenu = (dbMenu *)ellNext(&pMenu->node);
492  if(pMenu)
493  ellInsert(&pdbbase->menuList,ellPrevious(&pMenu->node),&pnewMenu->node);
494  else
495  ellAdd(&pdbbase->menuList,&pnewMenu->node);
496  pgphentry = gphAdd(pdbbase->pgpHash,pnewMenu->name,&pdbbase->menuList);
497  if(!pgphentry) {
498  yyerrorAbort("gphAdd failed");
499  } else {
500  pgphentry->userPvt = pnewMenu;
501  }
502 }
503 
504 static void dbRecordtypeHead(char *name)
505 {
506  dbRecordType *pdbRecordType;
507  GPHENTRY *pgphentry;
508 
509  if (!*name) {
510  yyerrorAbort("dbRecordtypeHead: Recordtype name can't be empty");
511  return;
512  }
513  pgphentry = gphFind(pdbbase->pgpHash,name,&pdbbase->recordTypeList);
514  if(pgphentry) {
515  duplicate = TRUE;
516  return;
517  }
518  pdbRecordType = dbCalloc(1,sizeof(dbRecordType));
519  pdbRecordType->name = epicsStrDup(name);
520  if (pdbbase->loadCdefs) ellInit(&pdbRecordType->cdefList);
521  if(ellCount(&tempList))
522  yyerrorAbort("dbRecordtypeHead tempList not empty");
523  allocTemp(pdbRecordType);
524 }
525 
526 static void dbRecordtypeFieldHead(char *name,char *type)
527 {
528  dbFldDes *pdbFldDes;
529  int i;
530 
531  if (!*name) {
532  yyerrorAbort("dbRecordtypeFieldHead: Field name can't be empty");
533  return;
534  }
535  if(duplicate) return;
536  pdbFldDes = dbCalloc(1,sizeof(dbFldDes));
537  allocTemp(pdbFldDes);
538  pdbFldDes->name = epicsStrDup(name);
539  pdbFldDes->as_level = ASL1;
540  pdbFldDes->isDevLink = strcmp(pdbFldDes->name, "INP")==0 ||
541  strcmp(pdbFldDes->name, "OUT")==0;
542  i = dbFindFieldType(type);
543  if (i < 0)
544  yyerrorAbort("Illegal Field Type");
545  pdbFldDes->field_type = i;
546 }
547 
548 static short findOrAddGuiGroup(const char *name)
549 {
550  dbGuiGroup *pdbGuiGroup;
551  GPHENTRY *pgphentry;
552  pgphentry = gphFind(pdbbase->pgpHash, name, &pdbbase->guiGroupList);
553  if (!pgphentry) {
554  pdbGuiGroup = dbCalloc(1,sizeof(dbGuiGroup));
555  pdbGuiGroup->name = epicsStrDup(name);
556  ellAdd(&pdbbase->guiGroupList, &pdbGuiGroup->node);
557  pdbGuiGroup->key = ellCount(&pdbbase->guiGroupList);
558  pgphentry = gphAdd(pdbbase->pgpHash, pdbGuiGroup->name, &pdbbase->guiGroupList);
559  pgphentry->userPvt = pdbGuiGroup;
560  }
561  return ((dbGuiGroup *)pgphentry->userPvt)->key;
562 }
563 
564 static void dbRecordtypeFieldItem(char *name,char *value)
565 {
566  dbFldDes *pdbFldDes;
567 
568  if(duplicate) return;
569  pdbFldDes = (dbFldDes *)getLastTemp();
570  if(strcmp(name,"asl")==0) {
571  if(strcmp(value,"ASL0")==0) {
572  pdbFldDes->as_level = ASL0;
573  } else if(strcmp(value,"ASL1")==0) {
574  pdbFldDes->as_level = ASL1;
575  } else {
576  yyerror("Illegal Access Security value: Must be ASL0 or ASL1");
577  }
578  return;
579  }
580  if(strcmp(name,"initial")==0) {
581  pdbFldDes->initial = epicsStrDup(value);
582  return;
583  }
584  if(strcmp(name,"promptgroup")==0) {
585  pdbFldDes->promptgroup = findOrAddGuiGroup(value);
586  return;
587  }
588  if(strcmp(name,"prompt")==0) {
589  pdbFldDes->prompt = epicsStrDup(value);
590  return;
591  }
592  if(strcmp(name,"special")==0) {
593  int i;
594  for(i=0; i<SPC_NTYPES; i++) {
595  if(strcmp(value,pamapspcType[i].strvalue)==0) {
596  pdbFldDes->special = pamapspcType[i].value;
597  return;
598  }
599  }
600  if(sscanf(value,"%hd",&pdbFldDes->special)==1) {
601  return;
602  }
603  yyerror("Illegal 'special' value.");
604  return;
605  }
606  if(strcmp(name,"pp")==0) {
607  if((strcmp(value,"YES")==0) || (strcmp(value,"TRUE")==0)) {
608  pdbFldDes->process_passive = TRUE;
609  } else if((strcmp(value,"NO")==0) || (strcmp(value,"FALSE")==0)) {
610  pdbFldDes->process_passive = FALSE;
611  } else {
612  yyerror("Illegal 'pp' value, must be YES/NO/TRUE/FALSE");
613  }
614  return;
615  }
616  if(strcmp(name,"interest")==0) {
617  if(sscanf(value,"%hd",&pdbFldDes->interest)!=1)
618  yyerror("Illegal 'interest' value, must be integer");
619  return;
620  }
621  if(strcmp(name,"base")==0) {
622  if(strcmp(value,"DECIMAL")==0) {
623  pdbFldDes->base = CT_DECIMAL;
624  } else if(strcmp(value,"HEX")==0) {
625  pdbFldDes->base = CT_HEX;
626  } else {
627  yyerror("Illegal 'base' value, must be DECIMAL/HEX");
628  }
629  return;
630  }
631  if(strcmp(name,"size")==0) {
632  if(sscanf(value,"%hd",&pdbFldDes->size)!=1)
633  yyerror("Illegal 'size' value, must be integer");
634  return;
635  }
636  if(strcmp(name,"extra")==0) {
637  pdbFldDes->extra = epicsStrDup(value);
638  return;
639  }
640  if(strcmp(name,"menu")==0) {
641  pdbFldDes->ftPvt = (dbMenu *)dbFindMenu(pdbbase,value);
642  if(!pdbbase->ignoreMissingMenus && !pdbFldDes->ftPvt)
643  yyerrorAbort("menu not found");
644  return;
645  }
646  if(strcmp(name,"prop")==0) {
647  if(strcmp(value, "YES")==0)
648  pdbFldDes->prop = 1;
649  else
650  pdbFldDes->prop = 0;
651  return;
652  }
653 }
654 
655 static void dbRecordtypeCdef(char *text) {
656  dbText *pdbCdef;
657  tempListNode *ptempListNode;
658  dbRecordType *pdbRecordType;
659 
660  if (!pdbbase->loadCdefs || duplicate) return;
661  ptempListNode = (tempListNode *)ellFirst(&tempList);
662  pdbRecordType = ptempListNode->item;
663 
664  pdbCdef = dbCalloc(1,sizeof(dbText));
665  if (text[0] == ' ') text++; /* strip leading space if present */
666  pdbCdef->text = epicsStrDup(text);
667  ellAdd(&pdbRecordType->cdefList, &pdbCdef->node);
668  return;
669 }
670 
671 static void dbRecordtypeEmpty(void)
672 {
673  tempListNode *ptempListNode;
674  dbRecordType *pdbRecordType;
675 
676  if (duplicate) {
677  duplicate = FALSE;
678  return;
679  }
680 
681  ptempListNode = (tempListNode *)ellFirst(&tempList);
682  pdbRecordType = ptempListNode->item;
683  epicsPrintf("Declaration of recordtype(%s) preceeded full definition.\n",
684  pdbRecordType->name);
685  yyerrorAbort(NULL);
686 }
687 
688 static void dbRecordtypeBody(void)
689 {
690  dbRecordType *pdbRecordType;
691  dbFldDes *pdbFldDes;
692  int i,j,ilink;
693  GPHENTRY *pgphentry;
694  int no_fields,no_prompt,no_links;
695  dbfType field_type;
696  char *psortFldNameTemp;
697  short psortFldIndTemp;
698  char **papsortFldName;
699  short *sortFldInd;
700 
701  if(duplicate) {
702  duplicate = FALSE;
703  return;
704  }
705  pdbRecordType= (dbRecordType *)popFirstTemp();
706  pdbRecordType->no_fields = no_fields = ellCount(&tempList);
707  pdbRecordType->papFldDes = dbCalloc(no_fields,sizeof(dbFldDes *));
708  pdbRecordType->papsortFldName = dbCalloc(no_fields,sizeof(char *));
709  pdbRecordType->sortFldInd = dbCalloc(no_fields,sizeof(short));
710  no_prompt = no_links = 0;
711  for(i=0; i<no_fields; i++) {
712  pdbFldDes = (dbFldDes *)popFirstTemp();
713  pdbFldDes->pdbRecordType = pdbRecordType;
714  pdbFldDes->indRecordType = i;
715  pdbRecordType->papFldDes[i] = pdbFldDes;
716  if(pdbFldDes->promptgroup) no_prompt++;
717  field_type = pdbFldDes->field_type;
718  if((field_type>=DBF_INLINK) && (field_type<=DBF_FWDLINK))no_links++;
719  if((field_type==DBF_STRING) && (pdbFldDes->size==0))
720  fprintf(stderr,"recordtype(%s).%s size not specified\n",
721  pdbRecordType->name,pdbFldDes->name);
722  if((field_type==DBF_NOACCESS) && (pdbFldDes->extra==0))
723  fprintf(stderr,"recordtype(%s).%s extra not specified\n",
724  pdbRecordType->name,pdbFldDes->name);
725  }
726  if (ellCount(&tempList))
727  yyerrorAbort("dbRecordtypeBody: tempList not empty");
728  pdbRecordType->no_prompt = no_prompt;
729  pdbRecordType->no_links = no_links;
730  pdbRecordType->link_ind = dbCalloc(no_links,sizeof(short));
731  ilink = 0;
732  for(i=0; i<no_fields; i++) {
733  pdbFldDes = pdbRecordType->papFldDes[i];
734  /* if prompt is null make it a null string */
735  if(!pdbFldDes->prompt) pdbFldDes->prompt = dbCalloc(1,sizeof(char));
736  field_type = pdbFldDes->field_type;
737  if((field_type>=DBF_INLINK) && (field_type<=DBF_FWDLINK))
738  pdbRecordType->link_ind[ilink++] = i;
739  if(strcmp(pdbFldDes->name,"VAL")==0) {
740  pdbRecordType->pvalFldDes = pdbRecordType->papFldDes[i];
741  pdbRecordType->indvalFlddes = i;
742  }
743  pdbRecordType->papsortFldName[i] = pdbFldDes->name;
744  pdbRecordType->sortFldInd[i] = i;
745  }
746  /*Now sort fields. Sorry dumb sort algorithm */
747  papsortFldName = pdbRecordType->papsortFldName;
748  sortFldInd = pdbRecordType->sortFldInd;
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;
758  }
759  }
760  }
761  /*Initialize lists*/
762  ellInit(&pdbRecordType->attributeList);
763  ellInit(&pdbRecordType->recList);
764  ellInit(&pdbRecordType->devList);
765  pgphentry = gphAdd(pdbbase->pgpHash,pdbRecordType->name,
766  &pdbbase->recordTypeList);
767  if(!pgphentry) {
768  yyerrorAbort("gphAdd failed");
769  } else {
770  pgphentry->userPvt = pdbRecordType;
771  }
772  ellAdd(&pdbbase->recordTypeList,&pdbRecordType->node);
773 }
774 
775 static void dbDevice(char *recordtype,char *linktype,
776  char *dsetname,char *choicestring)
777 {
778  devSup *pdevSup;
779  dbRecordType *pdbRecordType;
780  GPHENTRY *pgphentry;
781  int i,link_type;
782  pgphentry = gphFind(pdbbase->pgpHash,recordtype,&pdbbase->recordTypeList);
783  if(!pgphentry) {
784  epicsPrintf("Record type \"%s\" not found for device \"%s\"\n",
785  recordtype, choicestring);
786  yyerror(NULL);
787  return;
788  }
789  link_type=-1;
790  for(i=0; i<LINK_NTYPES; i++) {
791  if(strcmp(pamaplinkType[i].strvalue,linktype)==0) {
792  link_type = pamaplinkType[i].value;
793  break;
794  }
795  }
796  if(link_type==-1) {
797  epicsPrintf("Bad link type \"%s\" for device \"%s\"\n",
798  linktype, choicestring);
799  yyerror(NULL);
800  return;
801  }
802  pdbRecordType = (dbRecordType *)pgphentry->userPvt;
803  pgphentry = gphFind(pdbbase->pgpHash,choicestring,&pdbRecordType->devList);
804  if(pgphentry) {
805  return;
806  }
807  pdevSup = dbCalloc(1,sizeof(devSup));
808  pdevSup->name = epicsStrDup(dsetname);
809  pdevSup->choice = epicsStrDup(choicestring);
810  pdevSup->link_type = link_type;
811  pgphentry = gphAdd(pdbbase->pgpHash,pdevSup->choice,&pdbRecordType->devList);
812  if(!pgphentry) {
813  yyerrorAbort("gphAdd failed");
814  } else {
815  pgphentry->userPvt = pdevSup;
816  }
817  ellAdd(&pdbRecordType->devList,&pdevSup->node);
818 }
819 
820 static void dbDriver(char *name)
821 {
822  drvSup *pdrvSup;
823  GPHENTRY *pgphentry;
824 
825  if (!*name) {
826  yyerrorAbort("dbDriver: Driver name can't be empty");
827  return;
828  }
829  pgphentry = gphFind(pdbbase->pgpHash,name,&pdbbase->drvList);
830  if(pgphentry) {
831  return;
832  }
833  pdrvSup = dbCalloc(1,sizeof(drvSup));
834  pdrvSup->name = epicsStrDup(name);
835  pgphentry = gphAdd(pdbbase->pgpHash,pdrvSup->name,&pdbbase->drvList);
836  if(!pgphentry) {
837  yyerrorAbort("gphAdd failed");
838  }
839  pgphentry->userPvt = pdrvSup;
840  ellAdd(&pdbbase->drvList,&pdrvSup->node);
841 }
842 
843 static void dbLinkType(char *name, char *jlif_name)
844 {
845  linkSup *pLinkSup;
846  GPHENTRY *pgphentry;
847 
848  pgphentry = gphFind(pdbbase->pgpHash, name, &pdbbase->linkList);
849  if (pgphentry) {
850  return;
851  }
852  pLinkSup = dbCalloc(1,sizeof(linkSup));
853  pLinkSup->name = epicsStrDup(name);
854  pLinkSup->jlif_name = epicsStrDup(jlif_name);
855  pgphentry = gphAdd(pdbbase->pgpHash, pLinkSup->name, &pdbbase->linkList);
856  if (!pgphentry) {
857  yyerrorAbort("gphAdd failed");
858  }
859  pgphentry->userPvt = pLinkSup;
860  ellAdd(&pdbbase->linkList, &pLinkSup->node);
861 }
862 
863 static void dbRegistrar(char *name)
864 {
865  dbText *ptext;
866  GPHENTRY *pgphentry;
867 
868  if (!*name) {
869  yyerrorAbort("dbRegistrar: Registrar name can't be empty");
870  return;
871  }
872  pgphentry = gphFind(pdbbase->pgpHash,name,&pdbbase->registrarList);
873  if(pgphentry) {
874  return;
875  }
876  ptext = dbCalloc(1,sizeof(dbText));
877  ptext->text = epicsStrDup(name);
878  pgphentry = gphAdd(pdbbase->pgpHash,ptext->text,&pdbbase->registrarList);
879  if(!pgphentry) {
880  yyerrorAbort("gphAdd failed");
881  }
882  pgphentry->userPvt = ptext;
883  ellAdd(&pdbbase->registrarList,&ptext->node);
884 }
885 
886 static void dbFunction(char *name)
887 {
888  dbText *ptext;
889  GPHENTRY *pgphentry;
890 
891  if (!*name) {
892  yyerrorAbort("dbFunction: Function name can't be empty");
893  return;
894  }
895  pgphentry = gphFind(pdbbase->pgpHash,name,&pdbbase->functionList);
896  if(pgphentry) {
897  return;
898  }
899  ptext = dbCalloc(1,sizeof(dbText));
900  ptext->text = epicsStrDup(name);
901  pgphentry = gphAdd(pdbbase->pgpHash,ptext->text,&pdbbase->functionList);
902  if(!pgphentry) {
903  yyerrorAbort("gphAdd failed");
904  }
905  pgphentry->userPvt = ptext;
906  ellAdd(&pdbbase->functionList,&ptext->node);
907 }
908 
909 static void dbVariable(char *name, char *type)
910 {
911  dbVariableDef *pvar;
912  GPHENTRY *pgphentry;
913 
914  if (!*name) {
915  yyerrorAbort("dbVariable: Variable name can't be empty");
916  return;
917  }
918  pgphentry = gphFind(pdbbase->pgpHash,name,&pdbbase->variableList);
919  if(pgphentry) {
920  return;
921  }
922  pvar = dbCalloc(1,sizeof(dbVariableDef));
923  pvar->name = epicsStrDup(name);
924  pvar->type = epicsStrDup(type);
925  pgphentry = gphAdd(pdbbase->pgpHash,pvar->name,&pdbbase->variableList);
926  if(!pgphentry) {
927  yyerrorAbort("gphAdd failed");
928  }
929  pgphentry->userPvt = pvar;
930  ellAdd(&pdbbase->variableList,&pvar->node);
931 }
932 
933 static void dbBreakHead(char *name)
934 {
935  brkTable *pbrkTable;
936  GPHENTRY *pgphentry;
937 
938  if (!*name) {
939  yyerrorAbort("dbBreakHead: Breaktable name can't be empty");
940  return;
941  }
942  pgphentry = gphFind(pdbbase->pgpHash,name,&pdbbase->bptList);
943  if(pgphentry) {
944  duplicate = TRUE;
945  return;
946  }
947  pbrkTable = dbCalloc(1,sizeof(brkTable));
948  pbrkTable->name = epicsStrDup(name);
949  if(ellCount(&tempList)) yyerrorAbort("dbBreakHead:tempList not empty");
950  allocTemp(pbrkTable);
951 }
952 
953 static void dbBreakItem(char *value)
954 {
955  double dummy;
956  if (duplicate) return;
957  if (epicsScanDouble(value, &dummy) != 1) {
958  yyerrorAbort("Non-numeric value in breaktable");
959  }
960  allocTemp(epicsStrDup(value));
961 }
962 
963 static void dbBreakBody(void)
964 {
965  brkTable *pnewbrkTable;
966  brkInt *paBrkInt;
967  brkTable *pbrkTable;
968  int number, down=0;
969  int i;
970  GPHENTRY *pgphentry;
971 
972  if (duplicate) {
973  duplicate = FALSE;
974  return;
975  }
976  pnewbrkTable = (brkTable *)popFirstTemp();
977  number = ellCount(&tempList);
978  if (number % 2) {
979  yyerrorAbort("breaktable: Raw value missing");
980  return;
981  }
982  number /= 2;
983  if (number < 2) {
984  yyerrorAbort("breaktable: Must have at least two points!");
985  return;
986  }
987  pnewbrkTable->number = number;
988  pnewbrkTable->paBrkInt = paBrkInt = dbCalloc(number, sizeof(brkInt));
989  for (i=0; i<number; i++) {
990  char *str;
991 
992  str = (char *)popFirstTemp();
993  (void) epicsScanDouble(str, &paBrkInt[i].raw);
994  free(str);
995 
996  str = (char *)popFirstTemp();
997  (void) epicsScanDouble(str, &paBrkInt[i].eng);
998  free(str);
999  }
1000  /* Compute slopes */
1001  for (i=0; i<number-1; i++) {
1002  double slope =
1003  (paBrkInt[i+1].eng - paBrkInt[i].eng)/
1004  (paBrkInt[i+1].raw - paBrkInt[i].raw);
1005  if (!dbBptNotMonotonic && slope == 0) {
1006  yyerrorAbort("breaktable slope is zero");
1007  return;
1008  }
1009  if (i == 0) {
1010  down = (slope < 0);
1011  } else if (!dbBptNotMonotonic && down != (slope < 0)) {
1012  yyerrorAbort("breaktable slope changes sign");
1013  return;
1014  }
1015  paBrkInt[i].slope = slope;
1016  }
1017  /* Continue with last slope beyond the final point */
1018  paBrkInt[number-1].slope = paBrkInt[number-2].slope;
1019  /* Add brkTable in sorted order */
1020  pbrkTable = (brkTable *)ellFirst(&pdbbase->bptList);
1021  while (pbrkTable) {
1022  if (strcmp(pbrkTable->name, pnewbrkTable->name) > 0) {
1023  ellInsert(&pdbbase->bptList, ellPrevious((ELLNODE *)pbrkTable),
1024  (ELLNODE *)pnewbrkTable);
1025  break;
1026  }
1027  pbrkTable = (brkTable *)ellNext(&pbrkTable->node);
1028  }
1029  if (!pbrkTable) ellAdd(&pdbbase->bptList, &pnewbrkTable->node);
1030  pgphentry = gphAdd(pdbbase->pgpHash,pnewbrkTable->name,&pdbbase->bptList);
1031  if (!pgphentry) {
1032  yyerrorAbort("dbBreakBody: gphAdd failed");
1033  return;
1034  }
1035  pgphentry->userPvt = pnewbrkTable;
1036 }
1037 
1038 static void dbRecordHead(char *recordType, char *name, int visible)
1039 {
1040  char *badch;
1041  DBENTRY *pdbentry;
1042  long status;
1043 
1044  if (!*name) {
1045  yyerrorAbort("dbRecordHead: Record name can't be empty");
1046  return;
1047  }
1048  badch = strpbrk(name, " \"'.$");
1049  if (badch) {
1050  epicsPrintf("Bad character '%c' in record name \"%s\"\n",
1051  *badch, name);
1052  }
1053 
1054  pdbentry = dbAllocEntry(pdbbase);
1055  if (ellCount(&tempList))
1056  yyerrorAbort("dbRecordHead: tempList not empty");
1057  allocTemp(pdbentry);
1058 
1059  if (recordType[0] == '*' && recordType[1] == 0) {
1060  if (dbRecordsOnceOnly)
1061  epicsPrintf("Record-type \"*\" not valid with dbRecordsOnceOnly\n");
1062  else {
1063  status = dbFindRecord(pdbentry, name);
1064  if (status == 0)
1065  return; /* done */
1066  epicsPrintf("Record \"%s\" not found\n", name);
1067  }
1068  yyerror(NULL);
1069  duplicate = TRUE;
1070  return;
1071  }
1072 
1073  status = dbFindRecordType(pdbentry, recordType);
1074  if (status) {
1075  epicsPrintf("Record \"%s\" is of unknown type \"%s\"\n",
1076  name, recordType);
1077  yyerrorAbort(NULL);
1078  return;
1079  }
1080 
1081  /*Duplicate records are ok if the same type */
1082 
1083  status = dbCreateRecord(pdbentry,name);
1084  if (status == S_dbLib_recExists) {
1085  if (strcmp(recordType, dbGetRecordTypeName(pdbentry)) != 0) {
1086  epicsPrintf("Record \"%s\" of type \"%s\" redefined with new type "
1087  "\"%s\"\n", name, dbGetRecordTypeName(pdbentry), recordType);
1088  yyerror(NULL);
1089  duplicate = TRUE;
1090  return;
1091  }
1092  else if (dbRecordsOnceOnly) {
1093  epicsPrintf("Record \"%s\" already defined (dbRecordsOnceOnly is "
1094  "set)\n", name);
1095  yyerror(NULL);
1096  duplicate = TRUE;
1097  }
1098  }
1099  else if (status) {
1100  epicsPrintf("Can't create record \"%s\" of type \"%s\"\n",
1101  name, recordType);
1102  yyerrorAbort(NULL);
1103  }
1104 
1105  if (visible)
1106  dbVisibleRecord(pdbentry);
1107 }
1108 
1109 static void dbRecordField(char *name,char *value)
1110 {
1111  DBENTRY *pdbentry;
1112  tempListNode *ptempListNode;
1113  long status;
1114 
1115  if (duplicate) return;
1116  ptempListNode = (tempListNode *)ellFirst(&tempList);
1117  pdbentry = ptempListNode->item;
1118  status = dbFindField(pdbentry,name);
1119  if (status) {
1120  epicsPrintf("Record \"%s\" does not have a field \"%s\"\n",
1121  dbGetRecordName(pdbentry), name);
1122  yyerror(NULL);
1123  return;
1124  }
1125  if (pdbentry->indfield == 0) {
1126  epicsPrintf("Can't set \"NAME\" field of record \"%s\"\n",
1127  dbGetRecordName(pdbentry));
1128  yyerror(NULL);
1129  return;
1130  }
1131  if (*value == '"') {
1132  /* jsonSTRING values still have their quotes */
1133  value++;
1134  value[strlen(value) - 1] = 0;
1135  }
1136  dbTranslateEscape(value, value); /* in-place; safe & legal */
1137  status = dbPutString(pdbentry,value);
1138  if (status) {
1139  char msg[128];
1140 
1141  errSymLookup(status, msg, sizeof(msg));
1142  epicsPrintf("Can't set \"%s.%s\" to \"%s\" %s\n",
1143  dbGetRecordName(pdbentry), name, value, msg);
1144  yyerror(NULL);
1145  return;
1146  }
1147 }
1148 
1149 static void dbRecordInfo(char *name, char *value)
1150 {
1151  DBENTRY *pdbentry;
1152  tempListNode *ptempListNode;
1153  long status;
1154 
1155  if (!*name) {
1156  yyerrorAbort("dbRecordInfo: Info item name can't be empty");
1157  return;
1158  }
1159  if (duplicate) return;
1160  ptempListNode = (tempListNode *)ellFirst(&tempList);
1161  pdbentry = ptempListNode->item;
1162  if (*value == '"') {
1163  /* jsonSTRING values still have their quotes */
1164  value++;
1165  value[strlen(value) - 1] = 0;
1166  }
1167  dbTranslateEscape(value, value); /* yuck: in-place, but safe */
1168  status = dbPutInfo(pdbentry,name,value);
1169  if (status) {
1170  epicsPrintf("Can't set \"%s\" info \"%s\" to \"%s\"\n",
1171  dbGetRecordName(pdbentry), name, value);
1172  yyerror(NULL);
1173  return;
1174  }
1175 }
1176 
1177 static void dbRecordAlias(char *name)
1178 {
1179  DBENTRY *pdbentry;
1180  tempListNode *ptempListNode;
1181  long status;
1182 
1183  if (!*name) {
1184  yyerrorAbort("dbRecordAlias: Alias name can't be empty");
1185  return;
1186  }
1187  if (duplicate) return;
1188  ptempListNode = (tempListNode *)ellFirst(&tempList);
1189  pdbentry = ptempListNode->item;
1190  status = dbCreateAlias(pdbentry, name);
1191  if (status) {
1192  epicsPrintf("Can't create alias \"%s\" for \"%s\"\n",
1193  name, dbGetRecordName(pdbentry));
1194  yyerror(NULL);
1195  return;
1196  }
1197 }
1198 
1199 static void dbAlias(char *name, char *alias)
1200 {
1201  DBENTRY dbEntry;
1202  DBENTRY *pdbEntry = &dbEntry;
1203 
1204  if (!*alias) {
1205  yyerrorAbort("dbAlias: Alias name can't be empty");
1206  return;
1207  }
1208  dbInitEntry(pdbbase, pdbEntry);
1209  if (dbFindRecord(pdbEntry, name)) {
1210  epicsPrintf("Alias \"%s\" refers to unknown record \"%s\"\n",
1211  alias, name);
1212  yyerror(NULL);
1213  }
1214  else if (dbCreateAlias(pdbEntry, alias)) {
1215  epicsPrintf("Can't create alias \"%s\" referring to \"%s\"\n",
1216  alias, name);
1217  yyerror(NULL);
1218  }
1219  dbFinishEntry(pdbEntry);
1220 }
1221 
1222 static void dbRecordBody(void)
1223 {
1224  DBENTRY *pdbentry;
1225 
1226  if (duplicate) {
1227  duplicate = FALSE;
1228  return;
1229  }
1230  pdbentry = (DBENTRY *)popFirstTemp();
1231  if (ellCount(&tempList))
1232  yyerrorAbort("dbRecordBody: tempList not empty");
1233  dbFreeEntry(pdbentry);
1234 }
LIBCOM_API void *epicsStdCall freeListCalloc(void *pvt)
Definition: freeListLib.c:60
ELLLIST cdefList
Definition: dbBase.h:150
long dbCreateAlias(DBENTRY *pdbentry, const char *alias)
Definition: dbStaticLib.c:1648
long dbPath(DBBASE *pdbbase, const char *path)
Definition: dbStaticLib.c:657
char ** papChoiceName
Definition: dbBase.h:28
void dbInitEntry(dbBase *pdbbase, DBENTRY *pdbentry)
Definition: dbStaticLib.c:626
#define SPC_NTYPES
Definition: special.h:42
struct inputFile inputFile
struct tempListNode tempListNode
char * name
Definition: dbBase.h:140
ELLNODE node
Definition: dbBase.h:134
Definition: link.h:174
char * filename
short promptgroup
Definition: dbBase.h:91
long dbFirstRecordType(DBENTRY *pdbentry)
Definition: dbStaticLib.c:1198
ELLLIST drvList
Definition: dbBase.h:173
LIBCOM_API long epicsStdCall macParseDefns(MAC_HANDLE *handle, const char *defns, char **pairs[])
Parse macro definitions into an array of {name, value} pairs.
Definition: macUtil.c:32
char * choice
Definition: dbBase.h:41
void * pathPvt
Definition: dbBase.h:181
#define FALSE
Definition: dbDefs.h:32
char * jlif_name
Definition: dbBase.h:51
#define ellCount(PLIST)
Report the number of nodes in a list.
Definition: ellLib.h:84
Definition: dbBase.h:32
int dbRecordsOnceOnly
Definition: dbLexRoutines.c:45
short special
Definition: dbBase.h:85
long dbPutRecordAttribute(DBENTRY *pdbentry, const char *name, const char *value)
Definition: dbStaticLib.c:1230
ELLLIST linkList
Definition: dbBase.h:174
pvd::Status status
int dbFindFieldType(const char *type)
Definition: dbStaticLib.c:3000
int dbBptNotMonotonic
Definition: dbLexRoutines.c:48
#define CONTAINER(ptr, structure, member)
Find parent object from a member pointer.
Definition: dbDefs.h:66
int i
Definition: scan.c:967
short key
Definition: dbStaticPvt.h:89
void dbFreeEntry(DBENTRY *pdbentry)
Definition: dbStaticLib.c:617
int dbStaticDebug
Definition: dbStaticLib.c:49
ELLNODE node
Definition: dbBase.h:63
DBENTRY * dbAllocEntry(dbBase *pdbbase)
Definition: dbStaticLib.c:607
long dbFindRecordType(DBENTRY *pdbentry, const char *recordType)
Definition: dbStaticLib.c:1186
ELLLIST recordTypeList
Definition: dbBase.h:172
short loadCdefs
Definition: dbBase.h:185
void dbFinishEntry(DBENTRY *pdbentry)
Definition: dbStaticLib.c:632
pvd::StructureConstPtr type
short * link_ind
Definition: dbBase.h:156
#define S_dbLib_recExists
Definition: dbStaticLib.h:237
void dbFreePath(DBBASE *pdbbase)
Definition: dbStaticLib.c:140
ELLNODE node
Definition: dbStaticPvt.h:88
#define NULL
Definition: catime.c:38
long number
Definition: dbBase.h:75
int value
Definition: link.h:46
ELLLIST functionList
Definition: dbBase.h:176
LIBCOM_API void ellSortStable(ELLLIST *pList, pListCmp pListCmp)
Stable (MergeSort) of a given list.
Definition: ellSort.c:30
LIBCOM_API void epicsStdCall freeListInitPvt(void **ppvt, int size, int nmalloc)
Definition: freeListLib.c:44
int dbQuietMacroWarnings
Definition: dbLexRoutines.c:51
int dbRecordsAbcSorted
Definition: dbLexRoutines.c:54
#define str(v)
long dbNextRecordType(DBENTRY *pdbentry)
Definition: dbStaticLib.c:1209
#define ELLLIST_INIT
Value of an empty list.
Definition: ellLib.h:63
dbfType
Definition: dbFldTypes.h:24
ELLLIST bptList
Definition: dbBase.h:178
char * name
Definition: dbBase.h:26
long dbFindRecord(DBENTRY *pdbentry, const char *pname)
Definition: dbStaticLib.c:1559
Miscellaneous macro definitions.
#define epicsScanDouble(str, to)
Definition: epicsStdlib.h:78
char * name
Definition: dbBase.h:40
A library to manage storage that is allocated and quickly freed.
ELLNODE node
Definition: dbBase.h:146
ELLNODE node
Definition: dbBase.h:39
#define ellPrevious(PNODE)
Find the previous node in list.
Definition: ellLib.h:104
long epicsStdCall macExpandString(MAC_HANDLE *handle, const char *src, char *dest, long capacity)
Expand a string which may contain macro references.
Definition: macCore.c:174
char *epicsStdCall macEnvExpand(const char *str)
Expand environment variables in a string.
Definition: macEnv.c:20
dbBase * dbAllocBase(void)
Definition: dbStaticLib.c:401
void * userPvt
Definition: gpHash.h:25
int dbTranslateEscape(char *dst, const char *src)
Definition: epicsString.c:30
A doubly-linked list library.
void ellAdd(ELLLIST *pList, ELLNODE *pNode)
Adds a node to the end of a list.
Definition: ellLib.c:24
LIBCOM_API GPHENTRY *epicsStdCall gphFind(struct gphPvt *pvt, const char *name, void *pvtid)
Definition: gpHashLib.c:92
#define ellNext(PNODE)
Find the next node in list.
Definition: ellLib.h:99
short interest
Definition: dbBase.h:92
struct dbRecordType * pdbRecordType
Definition: dbBase.h:83
LIBCOM_API void epicsStdCall freeListCleanup(void *pvt)
Definition: freeListLib.c:152
ELLNODE node
Definition: dbBase.h:73
ELLNODE node
Definition: dbBase.h:139
maplinkType pamaplinkType[LINK_NTYPES]
Definition: dbStaticLib.c:63
void errPrintf(long status, const char *pFileName, int lineno, const char *pformat,...)
Definition: errlog.c:383
enum iocStateEnum getIocState(void)
Definition: iocInit.c:100
short indfield
Definition: dbStaticLib.h:41
short size
Definition: dbBase.h:98
unsigned int process_passive
Definition: dbBase.h:87
LIBCOM_API void errSymLookup(long status, char *pBuf, size_t bufLength)
Definition: errSymLib.c:190
short indvalFlddes
Definition: dbBase.h:160
Macro substitution context, for use by macLib routines only.
Definition: macLib.h:42
void epicsStdCall macSuppressWarning(MAC_HANDLE *handle, int suppress)
Disable or enable warning messages.
Definition: macCore.c:154
LIBCOM_API void epicsStdCall freeListFree(void *pvt, void *pmem)
Definition: freeListLib.c:131
char ** papsortFldName
Definition: dbBase.h:157
ctType base
Definition: dbBase.h:90
#define epicsPrintf
Definition: errlog.h:51
char * text
Definition: dbBase.h:135
Definition: dbBase.h:48
#define dbMalloc(size)
Definition: dbStaticLib.h:229
char ** papChoiceValue
Definition: dbBase.h:29
ELLNODE node
Definition: dbBase.h:49
ELLLIST devList
Definition: dbBase.h:149
long dbCreateRecord(DBENTRY *pdbentry, const char *precordName)
Definition: dbStaticLib.c:1416
short no_fields
Definition: dbBase.h:152
Definition: dbBase.h:38
char * dbGetRecordName(DBENTRY *pdbentry)
Definition: dbStaticLib.c:1612
ELLLIST guiGroupList
Definition: dbBase.h:180
#define ellLast(PLIST)
Find the last node in list.
Definition: ellLib.h:94
double eng
Definition: makeBpt.c:46
#define stdout
Definition: epicsStdio.h:30
char * name
Definition: dbStaticPvt.h:90
char * name
Definition: dbBase.h:151
List node type.
Definition: ellLib.h:45
short * sortFldInd
Definition: dbBase.h:158
char * epicsStrDup(const char *s)
Definition: epicsString.c:233
epics::pvData::PVStructurePtr dummy
Definition: pvAccess.cpp:72
mapspcType pamapspcType[]
ELLLIST menuList
Definition: dbBase.h:171
Definition: dbBase.h:24
asLevel as_level
Definition: dbBase.h:93
short no_links
Definition: dbBase.h:154
Definition: makeBpt.c:43
long epicsStdCall macDeleteHandle(MAC_HANDLE *handle)
Marks a handle invalid, and frees all storage associated with it.
Definition: macCore.c:360
int value
Definition: special.h:45
unsigned int prop
Definition: dbBase.h:88
Definition: dbBase.h:63
char * makeDbdDepends
Definition: dbLexRoutines.c:43
short no_prompt
Definition: dbBase.h:153
ELLNODE node
Definition: dbBase.h:33
long epicsStdCall macCreateHandle(MAC_HANDLE **pHandle, const char *pairs[])
Creates a new macro substitution context.
Definition: macCore.c:100
int nChoice
Definition: dbBase.h:27
ELLLIST recList
Definition: dbBase.h:148
#define TRUE
Definition: dbDefs.h:27
#define dbCalloc(nobj, size)
Definition: dbStaticLib.h:228
#define ellInit(PLIST)
Initialize a list type.
Definition: ellLib.h:76
unsigned int isDevLink
Definition: dbBase.h:89
void ellInsert(ELLLIST *plist, ELLNODE *pPrev, ELLNODE *pNode)
Inserts a node into a list immediately after a specific node.
Definition: ellLib.c:178
void * ftPvt
Definition: dbBase.h:96
long dbReadDatabase(DBBASE **ppdbbase, const char *filename, const char *path, const char *substitutions)
Definition: dbBase.h:170
dbFldDes * pvalFldDes
Definition: dbBase.h:159
Text macro substitution routines.
dbFldDes ** papFldDes
Definition: dbBase.h:161
if(yy_init)
Definition: scan.c:972
char * path
long dbFindField(DBENTRY *pdbentry, const char *pname)
Definition: dbStaticLib.c:1828
char * extra
Definition: dbBase.h:82
struct brkInt * paBrkInt
Definition: dbBase.h:76
char * recordname
Definition: dbBase.h:117
char * initial
Definition: dbBase.h:94
#define stderr
Definition: epicsStdio.h:32
short ignoreMissingMenus
Definition: dbBase.h:184
char * prompt
Definition: dbBase.h:80
char * name
Definition: dbBase.h:81
long dbPutString(DBENTRY *pdbentry, const char *pstring)
Definition: dbStaticLib.c:2545
long dbVisibleRecord(DBENTRY *pdbentry)
Definition: dbStaticLib.c:1622
long dbAddPath(DBBASE *pdbbase, const char *path)
Definition: dbStaticLib.c:665
char * type
Definition: dbBase.h:141
dbMenu * dbFindMenu(dbBase *pdbbase, const char *name)
Definition: dbStaticLib.c:3012
List header type.
Definition: ellLib.h:56
ELLLIST registrarList
Definition: dbBase.h:175
LIBCOM_API long epicsStdCall macInstallMacros(MAC_HANDLE *handle, char *pairs[])
Install set of {name, value} pairs as definitions.
Definition: macUtil.c:253
ELLNODE node
Definition: dbBase.h:25
ELLLIST attributeList
Definition: dbBase.h:147
void ellDelete(ELLLIST *pList, ELLNODE *pNode)
Deletes a node from a list.
Definition: ellLib.c:75
Definition: dbBase.h:133
long dbReadDatabaseFP(DBBASE **ppdbbase, FILE *fp, const char *path, const char *substitutions)
#define MY_BUFFER_SIZE
Definition: dbLexRoutines.c:95
Definition: dbBase.h:61
long dbPutInfo(DBENTRY *pdbentry, const char *name, const char *string)
Definition: dbStaticLib.c:2948
struct gphPvt * pgpHash
Definition: dbBase.h:183
dbfType field_type
Definition: dbBase.h:86
char * name
Definition: dbBase.h:34
epicsExportAddress(int, dbRecordsOnceOnly)
LIBCOM_API GPHENTRY *epicsStdCall gphAdd(struct gphPvt *pvt, const char *name, void *pvtid)
Definition: gpHashLib.c:97
char * dbGetRecordTypeName(DBENTRY *pdbentry)
Definition: dbStaticLib.c:1220
char * name
Definition: dbBase.h:50
ELLLIST variableList
Definition: dbBase.h:177
char * name
Definition: dbBase.h:74
short indRecordType
Definition: dbBase.h:84
double slope
Definition: makeBpt.c:45
int link_type
Definition: dbBase.h:42
Exporting IOC objects.
#define ellFirst(PLIST)
Find the first node in list.
Definition: ellLib.h:89