diff --git a/src/libCom/macLib/macCore.c b/src/libCom/macLib/macCore.c index 53b26fc80..0c43cae0e 100644 --- a/src/libCom/macLib/macCore.c +++ b/src/libCom/macLib/macCore.c @@ -45,6 +45,7 @@ #include #include #include +#include "errlog.h" #define epicsExportSharedSymbols #include "dbmf.h" @@ -66,6 +67,7 @@ static void delete( MAC_HANDLE *handle, MAC_ENTRY *entry ); static long expand( MAC_HANDLE *handle ); static void trans ( MAC_HANDLE *handle, MAC_ENTRY *entry, long level, char *term, const char **rawval, char **value, char *valend ); +static void cpy2val(const char *src, char **value, char *valend); /* * Flag bits @@ -110,7 +112,7 @@ epicsShareAPI macCreateHandle( /* allocate macro substitution context */ handle = ( MAC_HANDLE * ) dbmfMalloc( sizeof( MAC_HANDLE ) ); if ( handle == NULL ) { - macErrMessage0( -1, "macCreateHandle: failed to allocate context" ); + errlogPrintf( "macCreateHandle: failed to allocate context\n" ); return -1; } @@ -177,7 +179,7 @@ epicsShareAPI macExpandString( /* check handle */ if ( handle == NULL || handle->magic != MAC_MAGIC ) { - macErrMessage0( -1, "macExpandString: NULL or invalid handle\n" ); + errlogPrintf( "macExpandString: NULL or invalid handle\n" ); return -1; } @@ -187,10 +189,11 @@ epicsShareAPI macExpandString( /* expand raw values if necessary */ if ( expand( handle ) < 0 ) - macErrMessage0( -1, "macExpandString: failed to expand raw values" ); + errlogPrintf( "macExpandString: failed to expand raw values\n" ); - /* fill in necessary fields in fake macro entry struncture */ - entry.name = ""; + /* fill in necessary fields in fake macro entry structure */ + entry.name = (char *) src; + entry.type = "string"; entry.error = FALSE; /* expand the string */ @@ -226,12 +229,12 @@ epicsShareAPI macPutValue( /* check handle */ if ( handle == NULL || handle->magic != MAC_MAGIC ) { - macErrMessage0( -1, "macPutValue: NULL or invalid handle\n" ); + errlogPrintf( "macPutValue: NULL or invalid handle\n" ); return -1; } if ( handle->debug & 1 ) - epicsPrintf( "macPutValue( %s, %s )\n", name, value ? value : "NULL" ); + printf( "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) */ @@ -249,15 +252,17 @@ epicsShareAPI macPutValue( if ( entry == NULL || entry->level < handle->level ) { entry = create( handle, name, FALSE ); if ( entry == NULL ) { - macErrMessage2( -1, "macPutValue: failed to create macro %s = %s", + errlogPrintf( "macPutValue: failed to create macro %s = %s\n", name, value ); return -1; + } else { + entry->type = "macro"; } } /* copy raw value */ if ( rawval( handle, entry, value ) == NULL ) { - macErrMessage2( -1, "macPutValue: failed to copy macro %s = %s", + errlogPrintf( "macPutValue: failed to copy macro %s = %s\n", name, value ) ; return -1; } @@ -286,13 +291,13 @@ epicsShareAPI macGetValue( /* check handle */ if ( handle == NULL || handle->magic != MAC_MAGIC ) { - macErrMessage0( -1, "macGetValue: NULL or invalid handle\n" ); + errlogPrintf( "macGetValue: NULL or invalid handle\n" ); return -1; } /* debug output */ if ( handle->debug & 1 ) - epicsPrintf( "macGetValue( %s )\n", name ); + printf( "macGetValue( %s )\n", name ); /* look up macro name */ entry = lookup( handle, name, FALSE ); @@ -312,7 +317,7 @@ epicsShareAPI macGetValue( /* 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" ); + errlogPrintf( "macGetValue: failed to expand raw values\n" ); strncpy( value, name, maxlen ); return ( value[maxlen-1] == '\0' ) ? - (long) strlen( name ) : -maxlen; } @@ -337,7 +342,7 @@ epicsShareAPI macDeleteHandle( /* check handle */ if ( handle == NULL || handle->magic != MAC_MAGIC ) { - macErrMessage0( -1, "macDeleteHandle: NULL or invalid handle\n" ); + errlogPrintf( "macDeleteHandle: NULL or invalid handle\n" ); return -1; } @@ -369,7 +374,7 @@ epicsShareAPI macPushScope( /* check handle */ if ( handle == NULL || handle->magic != MAC_MAGIC ) { - macErrMessage0( -1, "macPushScope: NULL or invalid handle\n" ); + errlogPrintf( "macPushScope: NULL or invalid handle\n" ); return -1; } @@ -384,8 +389,10 @@ epicsShareAPI macPushScope( entry = create( handle, "", TRUE ); if ( entry == NULL ) { handle->level--; - macErrMessage0( -1, "macPushScope: failed to push scope" ); + errlogPrintf( "macPushScope: failed to push scope\n" ); return -1; + } else { + entry->type = "scope marker"; } return 0; @@ -402,7 +409,7 @@ epicsShareAPI macPopScope( /* check handle */ if ( handle == NULL || handle->magic != MAC_MAGIC ) { - macErrMessage0( -1, "macPopScope: NULL or invalid handle\n" ); + errlogPrintf( "macPopScope: NULL or invalid handle\n" ); return -1; } @@ -412,14 +419,14 @@ epicsShareAPI macPopScope( /* check scoping level isn't already zero */ if ( handle->level == 0 ) { - macErrMessage0( -1, "macPopScope: no scope to pop" ); + errlogPrintf( "macPopScope: no scope to pop\n" ); return -1; } /* look up most recent scope entry */ entry = lookup( handle, "", TRUE ); if ( entry == NULL ) { - macErrMessage0( -1, "macPopScope: no scope to pop" ); + errlogPrintf( "macPopScope: no scope to pop\n" ); return -1; } @@ -447,25 +454,25 @@ epicsShareAPI macReportMacros( /* check handle */ if ( handle == NULL || handle->magic != MAC_MAGIC ) { - macErrMessage0( -1, "macReportMacros: NULL or invalid handle\n" ); + errlogPrintf( "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" ); + errlogPrintf( "macGetValue: failed to expand raw values\n" ); /* loop through macros, reporting names and values */ - epicsPrintf( format, "e", "name", "rawval", "value" ); - epicsPrintf( format, "-", "----", "------", "-----" ); + printf( format, "e", "name", "rawval", "value" ); + printf( format, "-", "----", "------", "-----" ); for ( entry = first( handle ); entry != NULL; entry = next( entry ) ) { /* differentiate between "special" (scope marker) and ordinary entries */ if ( entry->special ) - epicsPrintf( format, "s", "----", "------", "-----" ); + printf( format, "s", "----", "------", "-----" ); else - epicsPrintf( format, entry->error ? "*" : " ", entry->name, + printf( format, entry->error ? "*" : " ", entry->name, entry->rawval ? entry->rawval : "", entry->value ? entry->value : ""); } @@ -522,6 +529,7 @@ static MAC_ENTRY *create( MAC_HANDLE *handle, const char *name, long special ) entry = NULL; } else { + entry->type = ""; entry->rawval = NULL; entry->value = NULL; entry->length = 0; @@ -551,11 +559,13 @@ static MAC_ENTRY *lookup( MAC_HANDLE *handle, const char *name, long special ) if ( strcmp( name, entry->name ) == 0 ) break; } - if ( (special == FALSE) && (entry == NULL) && (handle->flags & FLAG_USE_ENVIRONMENT) ) { + if ( (special == FALSE) && (entry == NULL) && + (handle->flags & FLAG_USE_ENVIRONMENT) ) { char *value = getenv(name); if (value) { entry = create( handle, name, FALSE ); if ( entry ) { + entry->type = "environment variable"; if ( rawval( handle, entry, value ) == NULL ) entry = NULL; } @@ -614,7 +624,7 @@ static long expand( MAC_HANDLE *handle ) for ( entry = first( handle ); entry != NULL; entry = next( entry ) ) { if ( handle->debug & 2 ) - epicsPrintf( "\nexpand %s = %s\n", entry->name, + printf( "\nexpand %s = %s\n", entry->name, entry->rawval ? entry->rawval : "" ); if ( entry->value == NULL ) { @@ -667,7 +677,7 @@ 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, " + printf( "trans-> level = %ld, maxlen = %4d, discard = %s, " "rawval = %s\n", level, valend - *value, discard ? "T" : "F", *rawval ); /* initially not in quotes */ @@ -707,7 +717,7 @@ static void trans( MAC_HANDLE *handle, MAC_ENTRY *entry, long level, } /* ensure string remains properly terminated */ - if ( v < valend ) *v = '\0'; + if ( v <= valend ) *v = '\0'; } /* macro reference */ @@ -715,7 +725,7 @@ static void trans( MAC_HANDLE *handle, MAC_ENTRY *entry, long level, /* step over '$(' or '${' */ r++; - macEnd = ( *r == '(' ) ? ")" : "}"; + macEnd = ( *r == '(' ) ? "=)" : "=}"; r++; /* translate name (may contain macro references); truncated @@ -725,30 +735,59 @@ static void trans( MAC_HANDLE *handle, MAC_ENTRY *entry, long level, 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 */ + /* look up the translated name */ 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 ); + /* not found */ + if ( *r == '=' ) { + /* there is a default value, translate that instead */ + ++r; + trans( handle, entry, level + 1, ++macEnd, &r, &v, valend ); + } else { + /* flag the warning and insert $(name) */ + if ( (handle->flags & FLAG_SUPPRESS_WARNINGS) == 0 ) { + entry->error = TRUE; + errlogPrintf( "macLib: macro %s is undefined (expanding %s %s)\n", + name2, entry->type, entry->name ); + } + if ( v < valend ) *v++ = '$'; + if ( v < valend ) *v++ = '('; + cpy2val( name2, &v, valend ); + if ( v < valend ) *v++ = ')'; } - sprintf( v, "$(%s)", name2 ); v += strlen( v ); + continue; } - /* check for recursive reference; if so, set error flag and - copy reference */ - else if ( entry2->visited ) { + /* if reference is recursive, flag an error and insert $(name) */ + if ( entry2->visited ) { entry->error = TRUE; - macErrMessage2( -1, "%s: %s referenced recursively", - entry->name, entry2->name ); - sprintf( v, "$(%s)", name2 ); v += strlen( v ); + errlogPrintf( "macLib: %s %s is recursive (expanding %s %s)\n", + entry->type, entry->name, + entry2->type, entry2->name ); + if ( v < valend ) *v++ = '$'; + if ( v < valend ) *v++ = '('; + cpy2val( name2, &v, valend ); + if ( v < valend ) *v++ = ')'; + continue; + } + + /* translate but discard any default value, supressing warnings */ + if ( *r == '=' ) { + MAC_ENTRY dflt; + int flags = handle->flags; + + ++r; + handle->flags |= FLAG_SUPPRESS_WARNINGS; + dflt.name = name2; + dflt.type = "default value"; + dflt.error = FALSE; + trans( handle, &dflt, level + 1, ++macEnd, &r, &v, v); + handle->flags = flags; } /* if all expanded values are valid (not "dirty") copy the value directly */ - else if ( !handle->dirty ) { - strcpy( v, entry2->value ); v += strlen( v ); + if ( !handle->dirty ) { + cpy2val( entry2->value, &v, valend ); } /* otherwise, translate raw value */ @@ -763,7 +802,7 @@ static void trans( MAC_HANDLE *handle, MAC_ENTRY *entry, long level, /* debug output */ if ( handle->debug & 2 ) - epicsPrintf( "<-trans level = %ld, length = %4d, value = %s\n", + printf( "<-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 @@ -775,6 +814,17 @@ static void trans( MAC_HANDLE *handle, MAC_ENTRY *entry, long level, return; } +/* + * Copy a string, honoring the 'end of destination string' pointer + */ +static void cpy2val(const char *src, char **value, char *valend) +{ + char *v = *value; + while ((v < valend) && (*v++ = *src++)) {} + *v = '\0'; + *value = v; +} + /* * strdup() implementation which uses our own memory allocator */ diff --git a/src/libCom/macLib/macEnv.c b/src/libCom/macLib/macEnv.c index c670155be..e535f5707 100644 --- a/src/libCom/macLib/macEnv.c +++ b/src/libCom/macLib/macEnv.c @@ -24,11 +24,13 @@ macEnvExpand(const char *str) { MAC_HANDLE *handle; static char *pairs[] = { "", "environ", NULL, NULL }; + long status; int destCapacity = 200; char *dest = NULL; int n; - assert(macCreateHandle(&handle, pairs) == 0); + status = macCreateHandle(&handle, pairs); + assert(status == 0); do { destCapacity *= 2; /* @@ -36,7 +38,8 @@ macEnvExpand(const char *str) * bother copying the contents if realloc needs to move the buffer */ free(dest); - assert((dest = malloc(destCapacity)) != 0); + dest = malloc(destCapacity); + assert(dest != 0); n = macExpandString(handle, str, dest, destCapacity); } while (n >= (destCapacity - 1)); if (n < 0) { @@ -48,6 +51,7 @@ macEnvExpand(const char *str) if (unused >= 20) dest = realloc(dest, n); } - assert(macDeleteHandle(handle) == 0); + status = macDeleteHandle(handle); + assert(status == 0); return dest; } diff --git a/src/libCom/macLib/macLib.h b/src/libCom/macLib/macLib.h index 5e5f2e6c9..c71d6c821 100644 --- a/src/libCom/macLib/macLib.h +++ b/src/libCom/macLib/macLib.h @@ -21,8 +21,6 @@ * EPICS include files needed by this file */ #include "ellLib.h" -#include "epicsPrint.h" -#include "errMdef.h" #include "shareLib.h" #ifdef __cplusplus @@ -50,21 +48,6 @@ extern "C" { */ #define MAC_SIZE 256 -/* - * Macros passing __FILE__ and __LINE__ to what will be macErrPrintf() - */ -#define macErrMessage0( _status, _format ) \ - errPrintf( _status, __FILE__, __LINE__, _format ) - -#define macErrMessage1( _status, _format, _arg1 ) \ - errPrintf( _status, __FILE__, __LINE__, _format, _arg1 ) - -#define macErrMessage2( _status, _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 ) - /* * Special characters */ @@ -103,7 +86,8 @@ typedef struct { */ typedef struct mac_entry { ELLNODE node; /* prev and next pointers */ - char *name; /* macro name */ + char *name; /* entry name */ + char *type; /* entry type */ char *rawval; /* raw (unexpanded) value */ char *value; /* expanded macro value */ long length; /* length of value */ diff --git a/src/libCom/macLib/macUtil.c b/src/libCom/macLib/macUtil.c index 0ecc5f5eb..e87e8ba4a 100644 --- a/src/libCom/macLib/macUtil.c +++ b/src/libCom/macLib/macUtil.c @@ -18,6 +18,7 @@ #include #include #include +#include "errlog.h" #define epicsExportSharedSymbols #include "macLib.h" @@ -239,7 +240,7 @@ epicsShareAPI macParseDefns( /* error exit */ error: - macErrMessage0( -1, "macParseDefns: failed to allocate memory" ); + errlogPrintf( "macParseDefns: failed to allocate memory\n" ); if ( ptr != NULL ) free( ptr ); if ( end != NULL ) free( end ); if ( del != NULL ) free( ( char * ) del );