diff --git a/src/libCom/Makefile b/src/libCom/Makefile index 42a136d60..02da342a7 100644 --- a/src/libCom/Makefile +++ b/src/libCom/Makefile @@ -63,9 +63,11 @@ INC += tsFreeList.h INC += epicsSingleton.h INC += epicsGuard.h INC += epicsOnce.h +INC += epicsThrowTrace.h SRCS += resourceLib.cpp SRCS += epicsOnce.cpp SRCS += epicsSingletonMutex.cpp +SRCS += epicsThrowTrace.cpp SRC_DIRS += $(LIBCOM)/dbmf INC += dbmf.h @@ -113,6 +115,7 @@ SRCS += logClient.c SRC_DIRS += $(LIBCOM)/macLib INC += macLib.h SRCS += macCore.c +SRCS += macEnv.c SRCS += macUtil.c SRC_DIRS += $(LIBCOM)/misc @@ -157,6 +160,8 @@ INC += osiPoolStatus.h INC += osdPoolStatus.h INC += osdThread.h +osdThread_CFLAGS_AIX = -U_ALL_SOURCE + INC += epicsThread.h INC += epicsTime.h INC += osdTime.h @@ -196,6 +201,7 @@ SRCS += osdProcess.c SRCS += osdNetIntf.c SRCS += osdMessageQueue.c + SRC_DIRS += $(LIBCOM)/taskwd INC += taskwd.h SRCS += taskwd.c diff --git a/src/libCom/macLib/macCore.c b/src/libCom/macLib/macCore.c index 08e5043a0..d8c8cfd24 100644 --- a/src/libCom/macLib/macCore.c +++ b/src/libCom/macLib/macCore.c @@ -63,9 +63,15 @@ static MAC_ENTRY *create( MAC_HANDLE *handle, char *name, long special ); static MAC_ENTRY *lookup( MAC_HANDLE *handle, char *name, long special ); static char *rawval( MAC_HANDLE *handle, MAC_ENTRY *entry, char *value ); static void delete( MAC_HANDLE *handle, MAC_ENTRY *entry ); -static long expand( MAC_HANDLE *handle ); +static long expand( MAC_HANDLE *handle ); static void trans ( MAC_HANDLE *handle, MAC_ENTRY *entry, long level, - char *term, char **rawval, char **value, char *valend ); + char *term, char **rawval, char **value, char *valend ); + +/* + * Flag bits + */ +#define FLAG_SUPPRESS_WARNINGS 0x1 +#define FLAG_USE_ENVIRONMENT 0x80 static char *Strdup( char *string ); @@ -86,17 +92,17 @@ static MAC_CHARS macDefaultChars = { * associated with the new context. Also optionally load an initial set * of macro definitions */ -long /* 0 = OK; <0 = ERROR */ +long /* 0 = OK; <0 = ERROR */ epicsShareAPI macCreateHandle( - MAC_HANDLE **pHandle, /* address of variable to receive pointer */ - /* to new macro substitution context */ + MAC_HANDLE **pHandle, /* address of variable to receive pointer */ + /* to new macro substitution context */ - char *pairs[] ) /* pointer to NULL-terminated array of */ - /* {name,value} pair strings; a NULL */ - /* value implies undefined; a NULL */ - /* argument implies no macros */ + char *pairs[] ) /* pointer to NULL-terminated array of */ + /* {name,value} pair strings; a NULL */ + /* value implies undefined; a NULL */ + /* argument implies no macros */ { - MAC_HANDLE *handle; /* pointer to macro substitution context */ + MAC_HANDLE *handle; /* pointer to macro substitution context */ /* ensure NULL handle pointer is returned on error */ *pHandle = NULL; @@ -104,8 +110,8 @@ epicsShareAPI macCreateHandle( /* allocate macro substitution context */ handle = ( MAC_HANDLE * ) dbmfMalloc( sizeof( MAC_HANDLE ) ); if ( handle == NULL ) { - macErrMessage0( -1, "macCreateHandle: failed to allocate context" ); - return -1; + macErrMessage0( -1, "macCreateHandle: failed to allocate context" ); + return -1; } /* initialize context */ @@ -114,15 +120,21 @@ epicsShareAPI macCreateHandle( handle->dirty = FALSE; handle->level = 0; handle->debug = 0; - handle->suppressWarning = 0; + handle->flags = 0; ellInit( &handle->list ); - /* if supplied, load macro definitions */ - for ( ; pairs && pairs[0]; pairs += 2 ) { - if ( macPutValue( handle, pairs[0], pairs[1] ) < 0 ) { - dbmfFree( handle ); - return -1; - } + /* use environment variables if so specified */ + if (pairs && pairs[0] && !strcmp(pairs[0],"") && pairs[1] && !strcmp(pairs[1],"environ") && !pairs[3]) { + handle->flags |= FLAG_USE_ENVIRONMENT; + } + else { + /* if supplied, load macro definitions */ + for ( ; pairs && pairs[0]; pairs += 2 ) { + if ( macPutValue( handle, pairs[0], pairs[1] ) < 0 ) { + dbmfFree( handle ); + return -1; + } + } } /* set returned handle pointer */ @@ -135,7 +147,8 @@ void epicsShareAPI macSuppressWarning( int falseTrue /*0 means issue, 1 means suppress*/ ) { - if(handle) handle->suppressWarning = falseTrue; + if(handle) handle->flags = (handle->flags & ~FLAG_SUPPRESS_WARNINGS) | + (falseTrue ? FLAG_SUPPRESS_WARNINGS : 0); } /* @@ -163,17 +176,17 @@ epicsShareAPI macExpandString( /* check handle */ if ( handle == NULL || handle->magic != MAC_MAGIC ) { - macErrMessage0( -1, "macExpandString: NULL or invalid handle\n" ); - return -1; + macErrMessage0( -1, "macExpandString: NULL or invalid handle\n" ); + return -1; } /* debug output */ if ( handle->debug & 1 ) - printf( "macExpandString( %s, maxlen = %ld )\n", src, maxlen ); + printf( "macExpandString( %s, maxlen = %ld )\n", src, maxlen ); /* expand raw values if necessary */ if ( expand( handle ) < 0 ) - macErrMessage0( -1, "macExpandString: failed to expand raw values" ); + macErrMessage0( -1, "macExpandString: failed to expand raw values" ); /* fill in necessary fields in fake macro entry struncture */ entry.name = ""; @@ -191,7 +204,7 @@ epicsShareAPI macExpandString( /* debug output */ if ( handle->debug & 1 ) - printf( "macExpandString() -> %ld\n", length ); + printf( "macExpandString() -> %ld\n", length ); return length; } @@ -200,31 +213,31 @@ epicsShareAPI macExpandString( * Define the value of a macro. A NULL value deletes the macro if it * already existed */ -long /* length of value */ +long /* length of value */ epicsShareAPI macPutValue( - MAC_HANDLE *handle, /* opaque handle */ + MAC_HANDLE *handle, /* opaque handle */ - char *name, /* macro name */ + char *name, /* macro name */ - char *value ) /* macro value */ + char *value ) /* macro value */ { - MAC_ENTRY *entry; /* pointer to this macro's entry structure */ + MAC_ENTRY *entry; /* pointer to this macro's entry structure */ /* check handle */ if ( handle == NULL || handle->magic != MAC_MAGIC ) { - macErrMessage0( -1, "macPutValue: NULL or invalid handle\n" ); - return -1; + macErrMessage0( -1, "macPutValue: NULL or invalid handle\n" ); + return -1; } if ( handle->debug & 1 ) - epicsPrintf( "macPutValue( %s, %s )\n", name, value ? value : "NULL" ); + epicsPrintf( "macPutValue( %s, %s )\n", name, value ? value : "NULL" ); /* handle NULL value case: if name was found, delete entry (may be several entries at different scoping levels) */ if ( value == NULL ) { - while ( ( entry = lookup( handle, name, FALSE ) ) != NULL ) - delete( handle, entry ); - return 0; + while ( ( entry = lookup( handle, name, FALSE ) ) != NULL ) + delete( handle, entry ); + return 0; } /* look up macro name */ @@ -233,19 +246,19 @@ epicsShareAPI macPutValue( /* new entry must be created if macro doesn't exist or if it only exists at a lower scoping level */ if ( entry == NULL || entry->level < handle->level ) { - entry = create( handle, name, FALSE ); - if ( entry == NULL ) { - macErrMessage2( -1, "macPutValue: failed to create macro %s = %s", - name, value ); - return -1; - } + entry = create( handle, name, FALSE ); + if ( entry == NULL ) { + macErrMessage2( -1, "macPutValue: failed to create macro %s = %s", + name, value ); + return -1; + } } /* copy raw value */ if ( rawval( handle, entry, value ) == NULL ) { - macErrMessage2( -1, "macPutValue: failed to copy macro %s = %s", - name, value ) ; - return -1; + macErrMessage2( -1, "macPutValue: failed to copy macro %s = %s", + name, value ) ; + return -1; } /* return length of value */ @@ -255,30 +268,30 @@ epicsShareAPI macPutValue( /* * Return the value of a macro */ -long /* #chars copied (<0 if undefined) */ +long /* #chars copied (<0 if undefined) */ epicsShareAPI macGetValue( - MAC_HANDLE *handle, /* opaque handle */ + MAC_HANDLE *handle, /* opaque handle */ - char *name, /* macro name or reference */ + char *name, /* macro name or reference */ - char *value, /* string to receive macro value or name */ - /* argument if macro is undefined */ + char *value, /* string to receive macro value or name */ + /* argument if macro is undefined */ - long maxlen ) /* maximum number of characters to copy */ - /* to value */ + long maxlen ) /* maximum number of characters to copy */ + /* to value */ { - MAC_ENTRY *entry; /* pointer to this macro's entry structure */ - long length; /* number of characters returned */ + MAC_ENTRY *entry; /* pointer to this macro's entry structure */ + long length; /* number of characters returned */ /* check handle */ if ( handle == NULL || handle->magic != MAC_MAGIC ) { - macErrMessage0( -1, "macGetValue: NULL or invalid handle\n" ); - return -1; + macErrMessage0( -1, "macGetValue: NULL or invalid handle\n" ); + return -1; } /* debug output */ if ( handle->debug & 1 ) - epicsPrintf( "macGetValue( %s )\n", name ); + epicsPrintf( "macGetValue( %s )\n", name ); /* look up macro name */ entry = lookup( handle, name, FALSE ); @@ -286,21 +299,21 @@ epicsShareAPI macGetValue( /* if maxlen <= 0 or VALUE == NULL just return -1 / 0 for undefined / defined macro */ if ( maxlen <= 0 || value == NULL ) { - return ( entry == NULL ) ? -1 : 0; + return ( entry == NULL ) ? -1 : 0; } /* if not found, copy name to value and return minus #chars copied */ if ( entry == NULL ) { - strncpy( value, name, maxlen ); - return ( value[maxlen-1] == '\0' ) ? - (long) strlen( name ) : -maxlen; + strncpy( value, name, maxlen ); + return ( value[maxlen-1] == '\0' ) ? - (long) strlen( name ) : -maxlen; } /* expand raw values if necessary; if fail (can only fail because of memory allocation failure), return same as if not found */ if ( expand( handle ) < 0 ) { - macErrMessage0( -1, "macGetValue: failed to expand raw values" ); - strncpy( value, name, maxlen ); - return ( value[maxlen-1] == '\0' ) ? - (long) strlen( name ) : -maxlen; + macErrMessage0( -1, "macGetValue: failed to expand raw values" ); + strncpy( value, name, maxlen ); + return ( value[maxlen-1] == '\0' ) ? - (long) strlen( name ) : -maxlen; } /* copy value and return +/- #chars copied depending on successful @@ -315,26 +328,26 @@ epicsShareAPI macGetValue( * Free up all storage associated with and delete a macro substitution * context */ -long /* 0 = OK; <0 = ERROR */ +long /* 0 = OK; <0 = ERROR */ epicsShareAPI macDeleteHandle( - MAC_HANDLE *handle ) /* opaque handle */ + MAC_HANDLE *handle ) /* opaque handle */ { MAC_ENTRY *entry, *nextEntry; /* check handle */ if ( handle == NULL || handle->magic != MAC_MAGIC ) { - macErrMessage0( -1, "macDeleteHandle: NULL or invalid handle\n" ); - return -1; + macErrMessage0( -1, "macDeleteHandle: NULL or invalid handle\n" ); + return -1; } /* debug output */ if ( handle->debug & 1 ) - printf( "macDeleteHandle()\n" ); + printf( "macDeleteHandle()\n" ); /* delete all entries */ for ( entry = first( handle ); entry != NULL; entry = nextEntry ) { - nextEntry = next( entry ); - delete( handle, entry ); + nextEntry = next( entry ); + delete( handle, entry ); } /* clear magic field and free context structure */ @@ -347,21 +360,21 @@ epicsShareAPI macDeleteHandle( /* * Mark the start of a new scoping level */ -long /* 0 = OK; <0 = ERROR */ +long /* 0 = OK; <0 = ERROR */ epicsShareAPI macPushScope( - MAC_HANDLE *handle ) /* opaque handle */ + MAC_HANDLE *handle ) /* opaque handle */ { MAC_ENTRY *entry; /* check handle */ if ( handle == NULL || handle->magic != MAC_MAGIC ) { - macErrMessage0( -1, "macPushScope: NULL or invalid handle\n" ); - return -1; + macErrMessage0( -1, "macPushScope: NULL or invalid handle\n" ); + return -1; } /* debug output */ if ( handle->debug & 1 ) - printf( "macPushScope()\n" ); + printf( "macPushScope()\n" ); /* increment scoping level */ handle->level++; @@ -369,9 +382,9 @@ epicsShareAPI macPushScope( /* create new "special" entry of name "" */ entry = create( handle, "", TRUE ); if ( entry == NULL ) { - handle->level--; - macErrMessage0( -1, "macPushScope: failed to push scope" ); - return -1; + handle->level--; + macErrMessage0( -1, "macPushScope: failed to push scope" ); + return -1; } return 0; @@ -380,39 +393,39 @@ epicsShareAPI macPushScope( /* * Pop all macros defined since the last call to macPushScope() */ -long /* 0 = OK; <0 = ERROR */ +long /* 0 = OK; <0 = ERROR */ epicsShareAPI macPopScope( - MAC_HANDLE *handle ) /* opaque handle */ + MAC_HANDLE *handle ) /* opaque handle */ { MAC_ENTRY *entry, *nextEntry; /* check handle */ if ( handle == NULL || handle->magic != MAC_MAGIC ) { - macErrMessage0( -1, "macPopScope: NULL or invalid handle\n" ); - return -1; + macErrMessage0( -1, "macPopScope: NULL or invalid handle\n" ); + return -1; } /* debug output */ if ( handle->debug & 1 ) - printf( "macPopScope()\n" ); + printf( "macPopScope()\n" ); /* check scoping level isn't already zero */ if ( handle->level == 0 ) { - macErrMessage0( -1, "macPopScope: no scope to pop" ); - return -1; + macErrMessage0( -1, "macPopScope: no scope to pop" ); + return -1; } /* look up most recent scope entry */ entry = lookup( handle, "", TRUE ); if ( entry == NULL ) { - macErrMessage0( -1, "macPopScope: no scope to pop" ); - return -1; + macErrMessage0( -1, "macPopScope: no scope to pop" ); + return -1; } /* delete scope entry and all macros defined since it */ for ( ; entry != NULL; entry = nextEntry ) { - nextEntry = next( entry ); - delete( handle, entry ); + nextEntry = next( entry ); + delete( handle, entry ); } /* decrement scoping level */ @@ -424,36 +437,36 @@ epicsShareAPI macPopScope( /* * Report macro details to standard output */ -long /* 0 = OK; <0 = ERROR */ +long /* 0 = OK; <0 = ERROR */ epicsShareAPI macReportMacros( - MAC_HANDLE *handle ) /* opaque handle */ + MAC_HANDLE *handle ) /* opaque handle */ { char *format = "%-1s %-16s %-16s %s\n"; MAC_ENTRY *entry; /* check handle */ if ( handle == NULL || handle->magic != MAC_MAGIC ) { - macErrMessage0( -1, "macReportMacros: NULL or invalid handle\n" ); - return -1; + macErrMessage0( -1, "macReportMacros: NULL or invalid handle\n" ); + return -1; } /* expand raw values if necessary; report but ignore failure */ if ( expand( handle ) < 0 ) - macErrMessage0( -1, "macGetValue: failed to expand raw values" ); + macErrMessage0( -1, "macGetValue: failed to expand raw values" ); /* loop through macros, reporting names and values */ epicsPrintf( format, "e", "name", "rawval", "value" ); epicsPrintf( format, "-", "----", "------", "-----" ); for ( entry = first( handle ); entry != NULL; entry = next( entry ) ) { - /* differentiate between "special" (scope marker) and ordinary - entries */ - if ( entry->special ) - epicsPrintf( format, "s", "----", "------", "-----" ); - else - epicsPrintf( format, entry->error ? "*" : " ", entry->name, - entry->rawval ? entry->rawval : "", - entry->value ? entry->value : ""); + /* differentiate between "special" (scope marker) and ordinary + entries */ + if ( entry->special ) + epicsPrintf( format, "s", "----", "------", "-----" ); + else + epicsPrintf( format, entry->error ? "*" : " ", entry->name, + entry->rawval ? entry->rawval : "", + entry->value ? entry->value : ""); } return 0; @@ -502,22 +515,22 @@ static MAC_ENTRY *create( MAC_HANDLE *handle, char *name, long special ) MAC_ENTRY *entry = ( MAC_ENTRY * ) dbmfMalloc( sizeof( MAC_ENTRY ) ); if ( entry != NULL ) { - entry->name = Strdup( name ); - if ( entry->name == NULL ) { - dbmfFree( entry ); - entry = NULL; - } - else { - entry->rawval = NULL; - entry->value = NULL; - entry->length = 0; - entry->error = FALSE; - entry->visited = FALSE; - entry->special = special; - entry->level = handle->level; + entry->name = Strdup( name ); + if ( entry->name == NULL ) { + dbmfFree( entry ); + entry = NULL; + } + else { + entry->rawval = NULL; + entry->value = NULL; + entry->length = 0; + entry->error = FALSE; + entry->visited = FALSE; + entry->special = special; + entry->level = handle->level; - ellAdd( list, ( ELLNODE * ) entry ); - } + ellAdd( list, ( ELLNODE * ) entry ); + } } return entry; @@ -532,10 +545,20 @@ static MAC_ENTRY *lookup( MAC_HANDLE *handle, char *name, long special ) /* search backwards so scoping works */ for ( entry = last( handle ); entry != NULL; entry = previous( entry ) ) { - if ( entry->special != special ) - continue; - if ( strcmp( name, entry->name ) == 0 ) - break; + if ( entry->special != special ) + continue; + if ( strcmp( name, entry->name ) == 0 ) + break; + } + if ( (special == FALSE) && (entry == NULL) && (handle->flags & FLAG_USE_ENVIRONMENT) ) { + char *value = getenv(name); + if (value) { + entry = create( handle, name, FALSE ); + if ( entry ) { + if ( rawval( handle, entry, value ) == NULL ) + entry = NULL; + } + } } return entry; @@ -547,7 +570,7 @@ static MAC_ENTRY *lookup( MAC_HANDLE *handle, char *name, long special ) static char *rawval( MAC_HANDLE *handle, MAC_ENTRY *entry, char *value ) { if ( entry->rawval != NULL ) - dbmfFree( entry->rawval ); + dbmfFree( entry->rawval ); entry->rawval = Strdup( value ); handle->dirty = TRUE; @@ -567,9 +590,9 @@ static void delete( MAC_HANDLE *handle, MAC_ENTRY *entry ) dbmfFree( entry->name ); if ( entry->rawval != NULL ) - dbmfFree( entry->rawval ); + dbmfFree( entry->rawval ); if ( entry->value != NULL ) - free( entry->value ); + free( entry->value ); dbmfFree( entry ); handle->dirty = TRUE; @@ -585,29 +608,29 @@ static long expand( MAC_HANDLE *handle ) char *value; if ( !handle->dirty ) - return 0; + return 0; for ( entry = first( handle ); entry != NULL; entry = next( entry ) ) { - if ( handle->debug & 2 ) - epicsPrintf( "\nexpand %s = %s\n", entry->name, - entry->rawval ? entry->rawval : "" ); + if ( handle->debug & 2 ) + epicsPrintf( "\nexpand %s = %s\n", entry->name, + entry->rawval ? entry->rawval : "" ); - if ( entry->value == NULL ) { - if ( ( entry->value = malloc( MAC_SIZE + 1 ) ) == NULL ) { - return -1; - } - } + if ( entry->value == NULL ) { + if ( ( entry->value = malloc( MAC_SIZE + 1 ) ) == NULL ) { + return -1; + } + } - /* start at level 1 so quotes and escapes will be removed from - expanded value */ - rawval = entry->rawval; + /* start at level 1 so quotes and escapes will be removed from + expanded value */ + rawval = entry->rawval; value = entry->value; - *value = '\0'; - entry->error = FALSE; - trans( handle, entry, 1, "", &rawval, &value, entry->value + MAC_SIZE ); - entry->length = value - entry->value; - entry->value[MAC_SIZE] = '\0'; + *value = '\0'; + entry->error = FALSE; + trans( handle, entry, 1, "", &rawval, &value, entry->value + MAC_SIZE ); + entry->length = value - entry->value; + entry->value[MAC_SIZE] = '\0'; } handle->dirty = FALSE; @@ -623,7 +646,7 @@ static long expand( MAC_HANDLE *handle ) * For now, use default special characters */ static void trans( MAC_HANDLE *handle, MAC_ENTRY *entry, long level, - char *term, char **rawval, char **value, char *valend ) + char *term, char **rawval, char **value, char *valend ) { char quote; char *r, *v, *n2, *r2; @@ -642,8 +665,8 @@ static void trans( MAC_HANDLE *handle, MAC_ENTRY *entry, long level, /* debug output */ if ( handle->debug & 2 ) - epicsPrintf( "trans-> level = %ld, maxlen = %4d, discard = %s, " - "rawval = %s\n", level, valend - *value, discard ? "T" : "F", *rawval ); + epicsPrintf( "trans-> level = %ld, maxlen = %4d, discard = %s, " + "rawval = %s\n", level, valend - *value, discard ? "T" : "F", *rawval ); /* initially not in quotes */ quote = 0; @@ -651,95 +674,95 @@ static void trans( MAC_HANDLE *handle, MAC_ENTRY *entry, long level, /* scan characters until hit terminator or end of string */ for ( r = *rawval, v = *value; strchr( term, *r ) == NULL; r++ ) { - /* handle quoted characters (quotes are discarded if in name) */ - if ( quote ) { - if ( *r == quote ) { - quote = 0; - if ( discard ) continue; - } - } - else if ( *r == '"' || *r == '\'' ) { - quote = *r; - if ( discard ) continue; - } + /* handle quoted characters (quotes are discarded if in name) */ + if ( quote ) { + if ( *r == quote ) { + quote = 0; + if ( discard ) continue; + } + } + else if ( *r == '"' || *r == '\'' ) { + quote = *r; + if ( discard ) continue; + } - /* macro reference if '$' followed by '(' or '{' */ - macRef = ( *r == '$' && *( r + 1 ) != '\0' && - strchr( "({", *( r + 1 ) ) != NULL ); + /* macro reference if '$' followed by '(' or '{' */ + macRef = ( *r == '$' && *( r + 1 ) != '\0' && + strchr( "({", *( r + 1 ) ) != NULL ); - /* if not macro reference (macros are not expanded in single quotes) */ - if ( quote == '\'' || !macRef ) { + /* if not macro reference (macros are not expanded in single quotes) */ + if ( quote == '\'' || !macRef ) { - /* handle escaped characters (escape is discarded if in name) */ - if ( *r == '\\' && *( r + 1 ) != '\0' ) { - if ( v < valend && !discard ) *v++ = '\\'; - if ( v < valend ) *v++ = *++r; - } + /* handle escaped characters (escape is discarded if in name) */ + if ( *r == '\\' && *( r + 1 ) != '\0' ) { + if ( v < valend && !discard ) *v++ = '\\'; + if ( v < valend ) *v++ = *++r; + } - /* copy character to output */ - else { - if ( v < valend ) *v++ = *r; - } + /* copy character to output */ + else { + if ( v < valend ) *v++ = *r; + } - /* ensure string remains properly terminated */ - if ( v < valend ) *v = '\0'; - } + /* ensure string remains properly terminated */ + if ( v < valend ) *v = '\0'; + } - /* macro reference */ - else { + /* macro reference */ + else { - /* step over '$(' or '${' */ - r++; - macEnd = ( *r == '(' ) ? ")" : "}"; - r++; + /* step over '$(' or '${' */ + r++; + macEnd = ( *r == '(' ) ? ")" : "}"; + r++; - /* translate name (may contain macro references); truncated - quietly if too long but always guaranteed zero-terminated */ - n2 = name2; - *n2 = '\0'; - trans( handle, entry, level + 1, macEnd, &r, &n2, n2 + MAC_SIZE ); - name2[MAC_SIZE] = '\0'; + /* translate name (may contain macro references); truncated + quietly if too long but always guaranteed zero-terminated */ + n2 = name2; + *n2 = '\0'; + trans( handle, entry, level + 1, macEnd, &r, &n2, n2 + MAC_SIZE ); + name2[MAC_SIZE] = '\0'; - /* look up resultant name; if not there, set error flag and - copy reference */ - if ( ( entry2 = lookup( handle, name2, FALSE ) ) == NULL ) { - if(!handle->suppressWarning) { - entry->error = TRUE; - macErrMessage2( -1, "%s: %s referenced but undefined", - entry->name, name2 ); - } - sprintf( v, "$(%s)", name2 ); v += strlen( v ); - } + /* look up resultant name; if not there, set error flag and + copy reference */ + if ( ( entry2 = lookup( handle, name2, FALSE ) ) == NULL ) { + if ( (handle->flags & FLAG_SUPPRESS_WARNINGS) == 0 ) { + entry->error = TRUE; + macErrMessage2( -1, "%s: %s referenced but undefined", + entry->name, name2 ); + } + sprintf( v, "$(%s)", name2 ); v += strlen( v ); + } - /* check for recursive reference; if so, set error flag and - copy reference */ - else if ( entry2->visited ) { - entry->error = TRUE; - macErrMessage2( -1, "%s: %s referenced recursively", - entry->name, entry2->name ); - sprintf( v, "$(%s)", name2 ); v += strlen( v ); - } + /* check for recursive reference; if so, set error flag and + copy reference */ + else if ( entry2->visited ) { + entry->error = TRUE; + macErrMessage2( -1, "%s: %s referenced recursively", + entry->name, entry2->name ); + sprintf( v, "$(%s)", name2 ); v += strlen( v ); + } - /* if all expanded values are valid (not "dirty") copy the - value directly */ - else if ( !handle->dirty ) { - strcpy( v, entry2->value ); v += strlen( v ); - } + /* if all expanded values are valid (not "dirty") copy the + value directly */ + else if ( !handle->dirty ) { + strcpy( v, entry2->value ); v += strlen( v ); + } - /* otherwise, translate raw value */ - else { - r2 = entry2->rawval; - entry2->visited = TRUE; - trans( handle, entry, level + 1, "", &r2, &v, valend ); - entry2->visited = FALSE; - } - } + /* otherwise, translate raw value */ + else { + r2 = entry2->rawval; + entry2->visited = TRUE; + trans( handle, entry, level + 1, "", &r2, &v, valend ); + entry2->visited = FALSE; + } + } } /* debug output */ if ( handle->debug & 2 ) - epicsPrintf( "<-trans level = %ld, length = %4d, value = %s\n", - level, v - *value, *value ); + epicsPrintf( "<-trans level = %ld, length = %4d, value = %s\n", + level, v - *value, *value ); /* update pointers to next characters to scan in raw value and to fill in in output value (if at end of input, step back so terminator is @@ -758,7 +781,7 @@ static char *Strdup( char *string ) char *copy = dbmfMalloc( strlen( string ) + 1 ); if ( copy != NULL ) - strcpy( copy, string ); + strcpy( copy, string ); return copy; } diff --git a/src/libCom/macLib/macLib.h b/src/libCom/macLib/macLib.h index 55cd8827a..b71ffa89d 100644 --- a/src/libCom/macLib/macLib.h +++ b/src/libCom/macLib/macLib.h @@ -43,7 +43,7 @@ extern "C" { /* * Magic number for validating context. */ -#define MAC_MAGIC 0xbadcafe /* ...sells sub-standard coffee? */ +#define MAC_MAGIC 0xbadcafe /* ...sells sub-standard coffee? */ /* * Maximum size of macro name or value string (simpler to make fixed) @@ -54,26 +54,26 @@ extern "C" { * Macros passing __FILE__ and __LINE__ to what will be macErrPrintf() */ #define macErrMessage0( _status, _format ) \ - errPrintf( _status, __FILE__, __LINE__, _format ) + errPrintf( _status, __FILE__, __LINE__, _format ) #define macErrMessage1( _status, _format, _arg1 ) \ - errPrintf( _status, __FILE__, __LINE__, _format, _arg1 ) + errPrintf( _status, __FILE__, __LINE__, _format, _arg1 ) #define macErrMessage2( _status, _format, _arg1, _arg2 ) \ - errPrintf( _status, __FILE__, __LINE__, _format, _arg1, _arg2 ) + errPrintf( _status, __FILE__, __LINE__, _format, _arg1, _arg2 ) #define macErrMessage3( _status, _format, _arg1, _arg2, _arg3 ) \ - errPrintf( _status, __FILE__, __LINE__, _format, _arg1, _arg2, _arg3 ) + errPrintf( _status, __FILE__, __LINE__, _format, _arg1, _arg2, _arg3 ) /* * Special characters */ -#define MAC_STARTCHARS "$" /* characters that indicate macro ref */ -#define MAC_LEFTCHARS "{(" /* characters to left of macro name */ -#define MAC_RIGHTCHARS "})" /* characters to right of macro name */ -#define MAC_SEPARCHARS "," /* characters separating macro defns */ -#define MAC_ASSIGNCHARS "=" /* characters denoting values assignment */ -#define MAC_ESCAPECHARS "\\" /* characters escaping the next char */ +#define MAC_STARTCHARS "$" /* characters that indicate macro ref */ +#define MAC_LEFTCHARS "{(" /* characters to left of macro name */ +#define MAC_RIGHTCHARS "})" /* characters to right of macro name */ +#define MAC_SEPARCHARS "," /* characters separating macro defns */ +#define MAC_ASSIGNCHARS "=" /* characters denoting values assignment */ +#define MAC_ESCAPECHARS "\\" /* characters escaping the next char */ typedef struct { char *start; @@ -89,132 +89,137 @@ typedef struct { * macCreateHandle() is called */ typedef struct { - long magic; /* magic number (used for authentication) */ - MAC_CHARS chars; /* special characters */ - long dirty; /* values need expanding from raw values? */ - long level; /* scoping level */ - long debug; /* debugging level */ - ELLLIST list; /* macro name / value list */ - int suppressWarning;/*suppress warning messages*/ + long magic; /* magic number (used for authentication) */ + MAC_CHARS chars; /* special characters */ + long dirty; /* values need expanding from raw values? */ + long level; /* scoping level */ + long debug; /* debugging level */ + ELLLIST list; /* macro name / value list */ + int flags; /* operating mode flags */ } MAC_HANDLE; /* * Entry in linked list of macro definitions */ typedef struct mac_entry { - ELLNODE node; /* prev and next pointers */ - char *name; /* macro name */ - char *rawval; /* raw (unexpanded) value */ - char *value; /* expanded macro value */ - long length; /* length of value */ - long error; /* error expanding value? */ - long visited; /* ever been visited? */ - long special; /* special (internal) entry? */ - long level; /* scoping level */ + ELLNODE node; /* prev and next pointers */ + char *name; /* macro name */ + char *rawval; /* raw (unexpanded) value */ + char *value; /* expanded macro value */ + long length; /* length of value */ + long error; /* error expanding value? */ + long visited; /* ever been visited? */ + long special; /* special (internal) entry? */ + long level; /* scoping level */ } MAC_ENTRY; /* * Function prototypes (core library) */ -epicsShareFunc long /* 0 = OK; <0 = ERROR */ +epicsShareFunc long /* 0 = OK; <0 = ERROR */ epicsShareAPI macCreateHandle( - MAC_HANDLE **handle, /* address of variable to receive pointer */ - /* to new macro substitution context */ + MAC_HANDLE **handle, /* address of variable to receive pointer */ + /* to new macro substitution context */ - char *pairs[] /* pointer to NULL-terminated array of */ - /* {name,value} pair strings; a NULL */ - /* value implies undefined; a NULL */ - /* argument implies no macros */ + char *pairs[] /* pointer to NULL-terminated array of */ + /* {name,value} pair strings; a NULL */ + /* value implies undefined; a NULL */ + /* argument implies no macros */ ); epicsShareFunc void epicsShareAPI macSuppressWarning( - MAC_HANDLE *handle, /* opaque handle */ + MAC_HANDLE *handle, /* opaque handle */ - int falseTrue /*0 means ussue, 1 means suppress*/ + int falseTrue /*0 means ussue, 1 means suppress*/ ); -epicsShareFunc long /* #chars copied, <0 if any macros are */ - /* undefined */ +epicsShareFunc long /* #chars copied, <0 if any macros are */ + /* undefined */ epicsShareAPI macExpandString( - MAC_HANDLE *handle, /* opaque handle */ + MAC_HANDLE *handle, /* opaque handle */ - char *src, /* source string */ + char *src, /* source string */ - char *dest, /* destination string */ + char *dest, /* destination string */ - long maxlen /* maximum number of characters to copy */ - /* to destination string */ + long maxlen /* maximum number of characters to copy */ + /* to destination string */ ); -epicsShareFunc long /* length of value */ +epicsShareFunc long /* length of value */ epicsShareAPI macPutValue( - MAC_HANDLE *handle, /* opaque handle */ + MAC_HANDLE *handle, /* opaque handle */ - char *name, /* macro name */ + char *name, /* macro name */ - char *value /* macro value */ + char *value /* macro value */ ); -epicsShareFunc long /* #chars copied (<0 if undefined) */ +epicsShareFunc long /* #chars copied (<0 if undefined) */ epicsShareAPI macGetValue( - MAC_HANDLE *handle, /* opaque handle */ + MAC_HANDLE *handle, /* opaque handle */ - char *name, /* macro name or reference */ + char *name, /* macro name or reference */ - char *value, /* string to receive macro value or name */ - /* argument if macro is undefined */ + char *value, /* string to receive macro value or name */ + /* argument if macro is undefined */ - long maxlen /* maximum number of characters to copy */ - /* to value */ + long maxlen /* maximum number of characters to copy */ + /* to value */ ); -epicsShareFunc long /* 0 = OK; <0 = ERROR */ +epicsShareFunc long /* 0 = OK; <0 = ERROR */ epicsShareAPI macDeleteHandle( - MAC_HANDLE *handle /* opaque handle */ + MAC_HANDLE *handle /* opaque handle */ ); -epicsShareFunc long /* 0 = OK; <0 = ERROR */ +epicsShareFunc long /* 0 = OK; <0 = ERROR */ epicsShareAPI macPushScope( - MAC_HANDLE *handle /* opaque handle */ + MAC_HANDLE *handle /* opaque handle */ ); -epicsShareFunc long /* 0 = OK; <0 = ERROR */ +epicsShareFunc long /* 0 = OK; <0 = ERROR */ epicsShareAPI macPopScope( - MAC_HANDLE *handle /* opaque handle */ + MAC_HANDLE *handle /* opaque handle */ ); -epicsShareFunc long /* 0 = OK; <0 = ERROR */ +epicsShareFunc long /* 0 = OK; <0 = ERROR */ epicsShareAPI macReportMacros( - MAC_HANDLE *handle /* opaque handle */ + MAC_HANDLE *handle /* opaque handle */ ); /* * Function prototypes (utility library) */ -epicsShareFunc long /* #defns encountered; <0 = ERROR */ +epicsShareFunc long /* #defns encountered; <0 = ERROR */ epicsShareAPI macParseDefns( - MAC_HANDLE *handle, /* opaque handle; can be NULL if default */ - /* special characters are to be used */ + MAC_HANDLE *handle, /* opaque handle; can be NULL if default */ + /* special characters are to be used */ - char *defns, /* macro definitions in "a=xxx,b=yyy" */ - /* format */ + char *defns, /* macro definitions in "a=xxx,b=yyy" */ + /* format */ - char **pairs[] /* address of variable to receive pointer */ - /* to NULL-terminated array of {name, */ - /* value} pair strings; all storage is */ - /* allocated contiguously */ + char **pairs[] /* address of variable to receive pointer */ + /* to NULL-terminated array of {name, */ + /* value} pair strings; all storage is */ + /* allocated contiguously */ ); -epicsShareFunc long /* #macros defined; <0 = ERROR */ +epicsShareFunc long /* #macros defined; <0 = ERROR */ epicsShareAPI macInstallMacros( - MAC_HANDLE *handle, /* opaque handle */ + MAC_HANDLE *handle, /* opaque handle */ - char *pairs[] /* pointer to NULL-terminated array of */ - /* {name,value} pair strings; a NULL */ - /* value implies undefined; a NULL */ - /* argument implies no macros */ + char *pairs[] /* pointer to NULL-terminated array of */ + /* {name,value} pair strings; a NULL */ + /* value implies undefined; a NULL */ + /* argument implies no macros */ +); + +epicsShareFunc char * /* expanded string; NULL if any undefined macros */ +epicsShareAPI macEnvExpand( + char *str /* string to be expanded */ ); #ifdef __cplusplus diff --git a/src/libCom/test/Makefile b/src/libCom/test/Makefile index 3b9e20672..6091cc43d 100644 --- a/src/libCom/test/Makefile +++ b/src/libCom/test/Makefile @@ -74,6 +74,10 @@ epicsMessageQueueTestHost_SRCS += epicsMessageQueueTestMain.cpp epicsMessageQueu PROD_HOST += epicsMessageQueueTestHost OBJS_IOC += epicsMessageQueueTest +macEnvExpandTestHost_SRCS += macEnvExpandTestMain.cpp macEnvExpandTest.c +PROD_HOST += macEnvExpandTestHost +OBJS_IOC += macEnvExpandTest + #fdmgrTest_SRCS += fdmgrTest.c #PROD_HOST += fdmgrTest