diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html index dbb23e66a..f056d3b16 100644 --- a/documentation/RELEASE_NOTES.html +++ b/documentation/RELEASE_NOTES.html @@ -955,6 +955,15 @@ of its CALLBACK objects.

+

Perl CA bindings fixed for macOS Mojave

+ +

Apple removed some Perl header files from macOS Mojave that were available +in their SDK, requiring a change to the include paths used when compiling the +CA bindings. The new version should build on new and older macOS versions, and +these changes may also help other targets that have an incomplete installation +of Perl (the build will continue after printing a warning that the Perl CA +bindings could not be built).

+

Routine epicsTempName() removed from libCom

This routine was a simple wrapper around the C89 function tmpnam() diff --git a/modules/ca/src/perl/Makefile b/modules/ca/src/perl/Makefile index 5b2bd5920..7890f34e4 100644 --- a/modules/ca/src/perl/Makefile +++ b/modules/ca/src/perl/Makefile @@ -8,6 +8,18 @@ TOP = ../.. include $(TOP)/configure/CONFIG +ifdef T_A + PERL_VERSION = $(shell $(PERL) ../perlConfig.pl version) + PERL_ARCHNAME = $(shell $(PERL) ../perlConfig.pl archname) + PERL_ARCHPATH := $(PERL_VERSION)/$(PERL_ARCHNAME) + + PERL_ARCHLIB := $(shell $(PERL) ../perlConfig.pl archlib) + PERL_h = $(PERL_ARCHLIB)/CORE/perl.h + + EXTUTILS := $(shell $(PERL) ../perlConfig.pl privlib)/ExtUtils + PERLBIN := $(shell $(PERL) ../perlConfig.pl bin) + XSUBPP := $(firstword $(wildcard $(PERLBIN)/xsubpp $(EXTUTILS)/xsubpp)) + # Special settings for Darwin: ifeq ($(OS_CLASS),Darwin) # Use hdepends command (not GNU compiler flags) @@ -18,22 +30,23 @@ ifeq ($(OS_CLASS),Darwin) # Perl loadable libraries on Darwin have funny names LOADABLE_SHRLIB_PREFIX = LOADABLE_SHRLIB_SUFFIX = .$(shell $(PERL) ../perlConfig.pl dlext) + +ifeq ($(wildcard $(PERL_h)),) + # Perl's headers moved in Mojave + SDK_PATH := $(shell xcodebuild -version -sdk macosx Path) + PERL_ARCHLIB := $(SDK_PATH)/$(PERL_ARCHLIB) +endif endif -ifdef T_A - PERL_VERSION = $(shell $(PERL) ../perlConfig.pl version) - PERL_ARCHNAME = $(shell $(PERL) ../perlConfig.pl archname) - PERL_ARCHPATH := $(PERL_VERSION)/$(PERL_ARCHNAME) - - EXTUTILS := $(shell $(PERL) ../perlConfig.pl privlib)/ExtUtils - PERLBIN := $(shell $(PERL) ../perlConfig.pl bin) - XSUBPP := $(firstword $(wildcard $(PERLBIN)/xsubpp $(EXTUTILS)/xsubpp)) - +ifeq ($(T_A),$(EPICS_HOST_ARCH)) # No cross-builds (wrong Perl!) ifeq ($(strip $(XSUBPP)),) $(warning Perl's xsubpp program was not found.) $(warning The Perl CA module will not be built.) else -ifeq ($(T_A),$(EPICS_HOST_ARCH)) # No cross-builds (wrong Perl!) +ifeq ($(wildcard $(PERL_h)),) + $(warning Perl's C header files were not found.) + $(warning The Perl CA module will not be built.) +else ifeq ($(findstring $(OS_CLASS),WIN32 cygwin32),) # Doesn't build on WIN32 LOADABLE_LIBRARY_HOST = Cap5 @@ -50,10 +63,11 @@ endif endif endif endif +endif Cap5_SRCS = Cap5.xs Cap5_LIBS = ca Com -Cap5_INCLUDES = -I$(shell $(PERL) ../perlConfig.pl archlib)/CORE +Cap5_INCLUDES = -I$(PERL_ARCHLIB)/CORE Cap5_CFLAGS = $(shell $(PERL) ../perlConfig.pl ccflags) CLEANS += Cap5.c diff --git a/modules/database/src/ioc/dbStatic/dbLexRoutines.c b/modules/database/src/ioc/dbStatic/dbLexRoutines.c index 59eb345f3..9281246d6 100644 --- a/modules/database/src/ioc/dbStatic/dbLexRoutines.c +++ b/modules/database/src/ioc/dbStatic/dbLexRoutines.c @@ -434,6 +434,10 @@ static void dbMenuHead(char *name) dbMenu *pdbMenu; GPHENTRY *pgphentry; + if (!*name) { + yyerrorAbort("dbMenuHead: Menu name can't be empty"); + return; + } pgphentry = gphFind(pdbbase->pgpHash,name,&pdbbase->menuList); if(pgphentry) { duplicate = TRUE; @@ -447,6 +451,10 @@ static void dbMenuHead(char *name) static void dbMenuChoice(char *name,char *value) { + if (!*name) { + yyerror("dbMenuChoice: Menu choice name can't be empty"); + return; + } if(duplicate) return; allocTemp(epicsStrDup(name)); allocTemp(epicsStrDup(value)); @@ -494,6 +502,10 @@ static void dbRecordtypeHead(char *name) dbRecordType *pdbRecordType; GPHENTRY *pgphentry; + if (!*name) { + yyerrorAbort("dbRecordtypeHead: Recordtype name can't be empty"); + return; + } pgphentry = gphFind(pdbbase->pgpHash,name,&pdbbase->recordTypeList); if(pgphentry) { duplicate = TRUE; @@ -512,6 +524,10 @@ static void dbRecordtypeFieldHead(char *name,char *type) dbFldDes *pdbFldDes; int i; + if (!*name) { + yyerrorAbort("dbRecordtypeFieldHead: Field name can't be empty"); + return; + } if(duplicate) return; pdbFldDes = dbCalloc(1,sizeof(dbFldDes)); allocTemp(pdbFldDes); @@ -580,7 +596,7 @@ static void dbRecordtypeFieldItem(char *name,char *value) if(sscanf(value,"%hd",&pdbFldDes->special)==1) { return; } - yyerror("Illegal special value."); + yyerror("Illegal 'special' value."); return; } if(strcmp(name,"pp")==0) { @@ -589,13 +605,13 @@ static void dbRecordtypeFieldItem(char *name,char *value) } else if((strcmp(value,"NO")==0) || (strcmp(value,"FALSE")==0)) { pdbFldDes->process_passive = FALSE; } else { - yyerror("Illegal value. Must be NO or YES"); + yyerror("Illegal 'pp' value, must be YES/NO/TRUE/FALSE"); } return; } if(strcmp(name,"interest")==0) { if(sscanf(value,"%hd",&pdbFldDes->interest)!=1) - yyerror("Illegal value. Must be integer"); + yyerror("Illegal 'interest' value, must be integer"); return; } if(strcmp(name,"base")==0) { @@ -604,13 +620,13 @@ static void dbRecordtypeFieldItem(char *name,char *value) } else if(strcmp(value,"HEX")==0) { pdbFldDes->base = CT_HEX; } else { - yyerror("Illegal value. Must be CT_DECIMAL or CT_HEX"); + yyerror("Illegal 'base' value, must be DECIMAL/HEX"); } return; } if(strcmp(name,"size")==0) { if(sscanf(value,"%hd",&pdbFldDes->size)!=1) - yyerror("Illegal value. Must be integer"); + yyerror("Illegal 'size' value, must be integer"); return; } if(strcmp(name,"extra")==0) { @@ -802,6 +818,10 @@ static void dbDriver(char *name) drvSup *pdrvSup; GPHENTRY *pgphentry; + if (!*name) { + yyerrorAbort("dbDriver: Driver name can't be empty"); + return; + } pgphentry = gphFind(pdbbase->pgpHash,name,&pdbbase->drvList); if(pgphentry) { return; @@ -841,6 +861,10 @@ static void dbRegistrar(char *name) dbText *ptext; GPHENTRY *pgphentry; + if (!*name) { + yyerrorAbort("dbRegistrar: Registrar name can't be empty"); + return; + } pgphentry = gphFind(pdbbase->pgpHash,name,&pdbbase->registrarList); if(pgphentry) { return; @@ -860,6 +884,10 @@ static void dbFunction(char *name) dbText *ptext; GPHENTRY *pgphentry; + if (!*name) { + yyerrorAbort("dbFunction: Function name can't be empty"); + return; + } pgphentry = gphFind(pdbbase->pgpHash,name,&pdbbase->functionList); if(pgphentry) { return; @@ -879,6 +907,10 @@ static void dbVariable(char *name, char *type) dbVariableDef *pvar; GPHENTRY *pgphentry; + if (!*name) { + yyerrorAbort("dbVariable: Variable name can't be empty"); + return; + } pgphentry = gphFind(pdbbase->pgpHash,name,&pdbbase->variableList); if(pgphentry) { return; @@ -899,6 +931,10 @@ static void dbBreakHead(char *name) brkTable *pbrkTable; GPHENTRY *pgphentry; + if (!*name) { + yyerrorAbort("dbBreakHead: Breaktable name can't be empty"); + return; + } pgphentry = gphFind(pdbbase->pgpHash,name,&pdbbase->bptList); if(pgphentry) { duplicate = TRUE; @@ -1001,6 +1037,10 @@ static void dbRecordHead(char *recordType, char *name, int visible) DBENTRY *pdbentry; long status; + if (!*name) { + yyerrorAbort("dbRecordHead: Record name can't be empty"); + return; + } badch = strpbrk(name, " \"'.$"); if (badch) { epicsPrintf("Bad character '%c' in record name \"%s\"\n", @@ -1108,6 +1148,10 @@ static void dbRecordInfo(char *name, char *value) tempListNode *ptempListNode; long status; + if (!*name) { + yyerrorAbort("dbRecordInfo: Info item name can't be empty"); + return; + } if (duplicate) return; ptempListNode = (tempListNode *)ellFirst(&tempList); pdbentry = ptempListNode->item; @@ -1132,6 +1176,10 @@ static void dbRecordAlias(char *name) tempListNode *ptempListNode; long status; + if (!*name) { + yyerrorAbort("dbRecordAlias: Alias name can't be empty"); + return; + } if (duplicate) return; ptempListNode = (tempListNode *)ellFirst(&tempList); pdbentry = ptempListNode->item; @@ -1149,6 +1197,10 @@ static void dbAlias(char *name, char *alias) DBENTRY dbEntry; DBENTRY *pdbEntry = &dbEntry; + if (!*alias) { + yyerrorAbort("dbAlias: Alias name can't be empty"); + return; + } dbInitEntry(pdbbase, pdbEntry); if (dbFindRecord(pdbEntry, name)) { epicsPrintf("Alias \"%s\" refers to unknown record \"%s\"\n",