Merge branch '7.0' release 7.4.0.1 into PSI-7.0
Conflicts: .gitmodules modules/database/src/ioc/db/Makefile modules/libcom/test/epicsAtomicTest.cpp modules/pvAccess modules/pvData modules/pvDatabase modules/pva2pva
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/*
|
||||
* Implementation of core macro substitution library (macLib)
|
||||
@@ -25,7 +25,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "dbDefs.h"
|
||||
#include "errlog.h"
|
||||
#include "dbmf.h"
|
||||
@@ -98,7 +97,7 @@ static char *Strdup( const char *string );
|
||||
* of macro definitions
|
||||
*/
|
||||
long /* 0 = OK; <0 = ERROR */
|
||||
epicsShareAPI macCreateHandle(
|
||||
epicsStdCall macCreateHandle(
|
||||
MAC_HANDLE **pHandle, /* address of variable to receive pointer */
|
||||
/* to new macro substitution context */
|
||||
|
||||
@@ -152,7 +151,7 @@ epicsShareAPI macCreateHandle(
|
||||
* for the given handle
|
||||
*/
|
||||
void
|
||||
epicsShareAPI macSuppressWarning(
|
||||
epicsStdCall macSuppressWarning(
|
||||
MAC_HANDLE *handle, /* opaque handle */
|
||||
int suppress /* 0 means issue, 1 means suppress */
|
||||
)
|
||||
@@ -172,7 +171,7 @@ epicsShareAPI macSuppressWarning(
|
||||
*/
|
||||
long /* strlen(dest), <0 if any macros are */
|
||||
/* undefined */
|
||||
epicsShareAPI macExpandString(
|
||||
epicsStdCall macExpandString(
|
||||
MAC_HANDLE *handle, /* opaque handle */
|
||||
|
||||
const char *src, /* source string */
|
||||
@@ -231,7 +230,7 @@ epicsShareAPI macExpandString(
|
||||
* already existed
|
||||
*/
|
||||
long /* strlen(value) */
|
||||
epicsShareAPI macPutValue(
|
||||
epicsStdCall macPutValue(
|
||||
MAC_HANDLE *handle, /* opaque handle */
|
||||
|
||||
const char *name, /* macro name */
|
||||
@@ -252,7 +251,7 @@ epicsShareAPI macPutValue(
|
||||
/* handle NULL value case: if name was found, delete entry (may be
|
||||
several entries at different scoping levels) */
|
||||
if ( value == NULL ) {
|
||||
/*
|
||||
/*
|
||||
* FIXME: shouldn't be able to delete entries from lower scopes
|
||||
* NOTE: when this is changed, this functionality of removing
|
||||
* a macro from all scopes will still be needed by iocshEnvClear
|
||||
@@ -260,11 +259,11 @@ epicsShareAPI macPutValue(
|
||||
while ( ( entry = lookup( handle, name, FALSE ) ) != NULL ) {
|
||||
int done = strcmp(entry->type, "environment variable") == 0;
|
||||
delete( handle, entry );
|
||||
|
||||
|
||||
if (done)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -299,7 +298,7 @@ epicsShareAPI macPutValue(
|
||||
* Return the value of a macro
|
||||
*/
|
||||
long /* strlen(value), <0 if undefined */
|
||||
epicsShareAPI macGetValue(
|
||||
epicsStdCall macGetValue(
|
||||
MAC_HANDLE *handle, /* opaque handle */
|
||||
|
||||
const char *name, /* macro name or reference */
|
||||
@@ -358,7 +357,7 @@ epicsShareAPI macGetValue(
|
||||
* context
|
||||
*/
|
||||
long /* 0 = OK; <0 = ERROR */
|
||||
epicsShareAPI macDeleteHandle(
|
||||
epicsStdCall macDeleteHandle(
|
||||
MAC_HANDLE *handle ) /* opaque handle */
|
||||
{
|
||||
MAC_ENTRY *entry, *nextEntry;
|
||||
@@ -390,7 +389,7 @@ epicsShareAPI macDeleteHandle(
|
||||
* Mark the start of a new scoping level
|
||||
*/
|
||||
long /* 0 = OK; <0 = ERROR */
|
||||
epicsShareAPI macPushScope(
|
||||
epicsStdCall macPushScope(
|
||||
MAC_HANDLE *handle ) /* opaque handle */
|
||||
{
|
||||
MAC_ENTRY *entry;
|
||||
@@ -425,7 +424,7 @@ epicsShareAPI macPushScope(
|
||||
* Pop all macros defined since the last call to macPushScope()
|
||||
*/
|
||||
long /* 0 = OK; <0 = ERROR */
|
||||
epicsShareAPI macPopScope(
|
||||
epicsStdCall macPopScope(
|
||||
MAC_HANDLE *handle ) /* opaque handle */
|
||||
{
|
||||
MAC_ENTRY *entry, *nextEntry;
|
||||
@@ -469,7 +468,7 @@ epicsShareAPI macPopScope(
|
||||
* Report macro details to standard output
|
||||
*/
|
||||
long /* 0 = OK; <0 = ERROR */
|
||||
epicsShareAPI macReportMacros(
|
||||
epicsStdCall macReportMacros(
|
||||
MAC_HANDLE *handle ) /* opaque handle */
|
||||
{
|
||||
const char *format = "%-1s %-16s %-16s %s\n";
|
||||
@@ -843,7 +842,7 @@ static long expand( MAC_HANDLE *handle )
|
||||
entry->rawval ? entry->rawval : "" );
|
||||
|
||||
if ( entry->value == NULL ) {
|
||||
if ( ( entry->value = malloc( MAC_SIZE + 1 ) ) == NULL ) {
|
||||
if ( ( entry->value = malloc( MAC_SIZE + 1 ) ) == NULL ) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (c) 2009 UChicago Argonne LLC, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/*
|
||||
* Macro expansion of environment variables
|
||||
@@ -12,18 +12,17 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "errlog.h"
|
||||
#include "epicsString.h"
|
||||
#include "macLib.h"
|
||||
|
||||
char * epicsShareAPI
|
||||
char * epicsStdCall
|
||||
macEnvExpand(const char *str)
|
||||
{
|
||||
return macDefExpand(str, NULL);
|
||||
}
|
||||
|
||||
char * epicsShareAPI
|
||||
char * epicsStdCall
|
||||
macDefExpand(const char *str, MAC_HANDLE *macros)
|
||||
{
|
||||
MAC_HANDLE *handle;
|
||||
@@ -31,7 +30,7 @@ macDefExpand(const char *str, MAC_HANDLE *macros)
|
||||
long destCapacity = 128;
|
||||
char *dest = NULL;
|
||||
int n;
|
||||
|
||||
|
||||
if (macros) {
|
||||
handle = macros;
|
||||
} else {
|
||||
|
||||
@@ -4,158 +4,302 @@
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/*
|
||||
* Definitions for macro substitution library (macLib)
|
||||
/**
|
||||
* \file macLib.h
|
||||
* \brief Text macro substitution routines
|
||||
* \author William Lupton, W. M. Keck Observatory
|
||||
*
|
||||
* William Lupton, W. M. Keck Observatory
|
||||
* This general purpose macro substitution library
|
||||
* is used for all macro substitutions in EPICS Base.
|
||||
*
|
||||
* Most routines return 0 (OK) on success, -1 (ERROR) on failure,
|
||||
* or small positive values for extra info.
|
||||
* The macGetValue() and macExpandString() routines depart from this
|
||||
* and return information both on success / failure and on value length.
|
||||
* Errors and warnings are reported using errlogPrintf().
|
||||
*/
|
||||
|
||||
#ifndef INCmacLibH
|
||||
#define INCmacLibH
|
||||
|
||||
/*
|
||||
* EPICS include files needed by this file
|
||||
*/
|
||||
#include "ellLib.h"
|
||||
#include "shareLib.h"
|
||||
#include "libComAPI.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Maximum size of macro name or value string (simpler to make fixed)
|
||||
/** \brief Maximum size of a macro name or value
|
||||
*/
|
||||
#define MAC_SIZE 256
|
||||
|
||||
/*
|
||||
* Macro substitution context. One of these contexts is allocated each time
|
||||
* macCreateHandle() is called
|
||||
/** \brief Macro substitution context, for use by macLib routines only.
|
||||
*
|
||||
* An application may have multiple active contexts if desired.
|
||||
*/
|
||||
typedef struct {
|
||||
long magic; /* magic number (used for authentication) */
|
||||
int dirty; /* values need expanding from raw values? */
|
||||
int level; /* scoping level */
|
||||
int debug; /* debugging level */
|
||||
ELLLIST list; /* macro name / value list */
|
||||
int flags; /* operating mode flags */
|
||||
long magic; /**< \brief magic number (used for authentication) */
|
||||
int dirty; /**< \brief values need expanding from raw values? */
|
||||
int level; /**< \brief scoping level */
|
||||
int debug; /**< \brief debugging level */
|
||||
ELLLIST list; /**< \brief macro name / value list */
|
||||
int flags; /**< \brief operating mode flags */
|
||||
} MAC_HANDLE;
|
||||
|
||||
/*
|
||||
* Function prototypes (core library)
|
||||
/** \name Core Library
|
||||
* The core library provides a minimal set of basic operations.
|
||||
* @{
|
||||
*/
|
||||
epicsShareFunc long /* 0 = OK; <0 = ERROR */
|
||||
epicsShareAPI macCreateHandle(
|
||||
MAC_HANDLE **handle, /* address of variable to receive pointer */
|
||||
/* to new macro substitution context */
|
||||
|
||||
const 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 */
|
||||
|
||||
int falseTrue /*0 means issue, 1 means suppress*/
|
||||
);
|
||||
|
||||
epicsShareFunc long /* strlen(dest), <0 if any macros are */
|
||||
/* undefined */
|
||||
epicsShareAPI macExpandString(
|
||||
MAC_HANDLE *handle, /* opaque handle */
|
||||
|
||||
const char *src, /* source string */
|
||||
|
||||
char *dest, /* destination string */
|
||||
|
||||
long capacity /* capacity of destination buffer (dest) */
|
||||
);
|
||||
|
||||
|
||||
epicsShareFunc long /* strlen(value) */
|
||||
epicsShareAPI macPutValue(
|
||||
MAC_HANDLE *handle, /* opaque handle */
|
||||
|
||||
const char *name, /* macro name */
|
||||
|
||||
const char *value /* macro value */
|
||||
);
|
||||
|
||||
epicsShareFunc long /* strlen(value), <0 if undefined */
|
||||
epicsShareAPI macGetValue(
|
||||
MAC_HANDLE *handle, /* opaque handle */
|
||||
|
||||
const char *name, /* macro name or reference */
|
||||
|
||||
char *value, /* string to receive macro value or name */
|
||||
/* argument if macro is undefined */
|
||||
|
||||
long capacity /* capacity of destination buffer (value) */
|
||||
);
|
||||
|
||||
epicsShareFunc long /* 0 = OK; <0 = ERROR */
|
||||
epicsShareAPI macDeleteHandle(
|
||||
MAC_HANDLE *handle /* opaque handle */
|
||||
);
|
||||
|
||||
epicsShareFunc long /* 0 = OK; <0 = ERROR */
|
||||
epicsShareAPI macPushScope(
|
||||
MAC_HANDLE *handle /* opaque handle */
|
||||
);
|
||||
|
||||
epicsShareFunc long /* 0 = OK; <0 = ERROR */
|
||||
epicsShareAPI macPopScope(
|
||||
MAC_HANDLE *handle /* opaque handle */
|
||||
);
|
||||
|
||||
epicsShareFunc long /* 0 = OK; <0 = ERROR */
|
||||
epicsShareAPI macReportMacros(
|
||||
MAC_HANDLE *handle /* opaque handle */
|
||||
);
|
||||
|
||||
/*
|
||||
* Function prototypes (utility library)
|
||||
/**
|
||||
* \brief Creates a new macro substitution context.
|
||||
* \return 0 = OK; <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 */
|
||||
LIBCOM_API long
|
||||
epicsStdCall macCreateHandle(
|
||||
MAC_HANDLE **handle, /**< pointer to variable to receive pointer
|
||||
to new macro substitution context */
|
||||
|
||||
const char *defns, /* macro definitions in "a=xxx,b=yyy" */
|
||||
/* format */
|
||||
const char * pairs[] /**< pointer to NULL-terminated array of
|
||||
{name,value} pair strings. A NULL
|
||||
value implies undefined; a NULL \c pairs
|
||||
argument implies no macros. */
|
||||
);
|
||||
/**
|
||||
* \brief Disable or enable warning messages.
|
||||
*
|
||||
* The macExpandString() routine prints warnings when it cant expand a macro.
|
||||
* This routine can be used to silence those warnings. A non zero value will
|
||||
* suppress the warning messages from subsequent library routines given the
|
||||
* same \c handle.
|
||||
*/
|
||||
LIBCOM_API void
|
||||
epicsStdCall macSuppressWarning(
|
||||
MAC_HANDLE *handle, /**< opaque handle */
|
||||
|
||||
char **pairs[] /* address of variable to receive pointer */
|
||||
/* to NULL-terminated array of {name, */
|
||||
/* value} pair strings; all storage is */
|
||||
/* allocated contiguously */
|
||||
int falseTrue /**< 0 means issue, 1 means suppress*/
|
||||
);
|
||||
|
||||
epicsShareFunc long /* #macros defined; <0 = ERROR */
|
||||
epicsShareAPI macInstallMacros(
|
||||
MAC_HANDLE *handle, /* opaque handle */
|
||||
/**
|
||||
* \brief Expand a string which may contain macro references.
|
||||
* \return Returns the length of the expanded string, <0 if any macro are
|
||||
* undefined
|
||||
*
|
||||
* This routine parses the \c src string looking for macro references and
|
||||
* passes any it finds to macGetValue() for translation.
|
||||
*
|
||||
* \note The return value is similar to that of macGetValue(). Its absolute
|
||||
* value is the number of characters copied to \c dest. If the return value
|
||||
* is negative, at least one undefined macro was left unexpanded.
|
||||
*/
|
||||
LIBCOM_API long
|
||||
epicsStdCall macExpandString(
|
||||
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 */
|
||||
const char *src, /**< source string */
|
||||
|
||||
char *dest, /**< destination string */
|
||||
|
||||
long capacity /**< capacity of destination buffer (dest) */
|
||||
);
|
||||
|
||||
epicsShareFunc char * /* expanded string; NULL if any undefined macros */
|
||||
epicsShareAPI macEnvExpand(
|
||||
const char *str /* string to be expanded */
|
||||
/**
|
||||
* \brief Sets the value of a specific macro.
|
||||
* \return Returns the length of the value string.
|
||||
* \note If \c value is NULL, all instances of \c name are undefined at
|
||||
* all scoping levels (the named macro doesn't have to exist in this case).
|
||||
* Macros referenced in \c value need not be defined at this point.
|
||||
*/
|
||||
LIBCOM_API long
|
||||
epicsStdCall macPutValue(
|
||||
MAC_HANDLE *handle, /**< opaque handle */
|
||||
|
||||
const char *name, /**< macro name */
|
||||
|
||||
const char *value /**< macro value */
|
||||
);
|
||||
|
||||
epicsShareFunc char * /* expanded string; NULL if any undefined macros */
|
||||
epicsShareAPI macDefExpand(
|
||||
const char *str, /* string to be expanded */
|
||||
MAC_HANDLE *macros /* opaque handle; can be NULL if default */
|
||||
/* special characters are to be used */
|
||||
/**
|
||||
* \brief Returns the value of a macro
|
||||
* \return Returns the length of the value string, <0 if undefined
|
||||
*
|
||||
* \c value will be zero-terminated if the length of the value is less than
|
||||
* \c capacity. The return value is the number of characters copied to
|
||||
* \c value (see below for behavior if the macro is undefined). If \c capacity
|
||||
* is zero, no characters will be copied to \c value (which may be NULL)
|
||||
* and the call can be used to check whether the macro is defined.
|
||||
*
|
||||
* \note Truncation of the value is not reported, applications should assume
|
||||
* that truncation has occurred if the return value is equal to capacity.
|
||||
*
|
||||
* If the macro is undefined, the macro reference will be returned in
|
||||
* the value string (if permitted by maxlen) and the function value will
|
||||
* be _minus_ the number of characters copied. Note that treatment of
|
||||
* \c capacity is intended to be consistent with the strncpy() routine.
|
||||
*
|
||||
* If the value contains macro references, these references will be
|
||||
* expanded recursively. This expansion will detect a direct or indirect
|
||||
* self reference.
|
||||
*
|
||||
* Macro references begin with a "$" immediately followed by either a
|
||||
* "(" or a "{" character. The macro name comes next, and may optionally
|
||||
* be succeeded by an "=" and a default value, which will be returned if
|
||||
* the named macro is undefined at the moment of expansion. A reference
|
||||
* is terminated by the matching ")" or "}" character.
|
||||
*/
|
||||
LIBCOM_API long
|
||||
epicsStdCall macGetValue(
|
||||
MAC_HANDLE *handle, /**< opaque handle */
|
||||
|
||||
const char *name, /**< macro name or reference */
|
||||
|
||||
char *value, /**< string to receive macro value or name
|
||||
argument if macro is undefined */
|
||||
|
||||
long capacity /**< capacity of destination buffer (value) */
|
||||
);
|
||||
/**
|
||||
* \brief Marks a handle invalid, and frees all storage associated with it
|
||||
* \return 0 = OK; <0 = ERROR
|
||||
* \note Note that this does not free any strings into which macro values have
|
||||
* been returned. Macro values are always returned into strings which
|
||||
* were pre-allocated by the caller.
|
||||
*/
|
||||
LIBCOM_API long
|
||||
epicsStdCall macDeleteHandle(
|
||||
MAC_HANDLE *handle /**< opaque handle */
|
||||
);
|
||||
/**
|
||||
* \brief Marks the start of a new scoping level
|
||||
* \return 0 = OK; <0 = ERROR
|
||||
*
|
||||
* Marks all macro definitions added after this call as belonging
|
||||
* to another scope. These macros will be lost on a macPopScope()
|
||||
* call and those at the current scope will be re-instated.
|
||||
*/
|
||||
LIBCOM_API long
|
||||
epicsStdCall macPushScope(
|
||||
MAC_HANDLE *handle /**< opaque handle */
|
||||
);
|
||||
/**
|
||||
* \brief Retrieve the last pushed scope (like stack operations)
|
||||
* \return 0 = OK; <0 = ERROR
|
||||
*
|
||||
* See macPushScope()
|
||||
*/
|
||||
LIBCOM_API long
|
||||
epicsStdCall macPopScope(
|
||||
MAC_HANDLE *handle /**< opaque handle */
|
||||
);
|
||||
/**
|
||||
* \brief Reports details of current definitions
|
||||
* \return 0 = OK; <0 = ERROR
|
||||
* This sends details of current definitions to standard output,
|
||||
* and is intended purely for debugging purposes.
|
||||
*/
|
||||
LIBCOM_API long
|
||||
epicsStdCall macReportMacros(
|
||||
MAC_HANDLE *handle /**< opaque handle */
|
||||
);
|
||||
/** @} */
|
||||
|
||||
/** \name Utility Library
|
||||
* These convenience functions are intended for applications to use and
|
||||
* provide a more convenient interface for some purposes.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Parse macro definitions into an array of {name, value} pairs.
|
||||
* \return Number of macros found; <0 = ERROR
|
||||
*
|
||||
* This takes a set of macro definitions in "a=xxx,b=yyy" format and
|
||||
* converts them into an array of pointers to character strings which
|
||||
* are, in order, "first name", "first value", "second name", "second
|
||||
* value" etc. The array is terminated with two NULL pointers and all
|
||||
* storage is allocated contiguously so that it can be freed with a
|
||||
* single call to free().
|
||||
*
|
||||
* This routine is independent of any handle and provides a generally
|
||||
* useful service which may be used elsewhere. Any macro references in
|
||||
* values are not expanded at this point since the referenced macros may
|
||||
* be defined or redefined before the macro actually has to be
|
||||
* translated.
|
||||
*
|
||||
* Shell-style escapes and quotes are supported, as are things like
|
||||
* "A=B,B=$(C$(A)),CA=CA,CB=CB" (sets B to "CB"). White space is
|
||||
* significant within values but ignored elsewhere (i.e. surrounding "="
|
||||
* and "," characters).
|
||||
*
|
||||
* The function returns the number of definitions encountered, or -1 if
|
||||
* the supplied string is invalid.
|
||||
*/
|
||||
LIBCOM_API long
|
||||
epicsStdCall macParseDefns(
|
||||
MAC_HANDLE *handle, /**< opaque handle; may be NULL if debug
|
||||
messages are not required. */
|
||||
|
||||
const 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 */
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Install set of {name, value} pairs as definitions
|
||||
* \return Number of macros defined; <0 = ERROR
|
||||
*
|
||||
* This takes an array of pairs as defined above and installs them as
|
||||
* definitions by calling macPutValue(). The pairs array is terminated
|
||||
* by a NULL pointer.
|
||||
*/
|
||||
LIBCOM_API long
|
||||
epicsStdCall macInstallMacros(
|
||||
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 */
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Expand environment variables in a string.
|
||||
* \return Expanded string; NULL if any undefined macros were used.
|
||||
*
|
||||
* This routine expands a string which may contain macros that are
|
||||
* environment variables. It parses the string looking for such
|
||||
* references and passes them to macGetValue() for translation. It uses
|
||||
* malloc() to allocate space for the expanded string and returns a
|
||||
* pointer to this null-terminated string. It returns NULL if the source
|
||||
* string contains any undefined references.
|
||||
*/
|
||||
LIBCOM_API char *
|
||||
epicsStdCall macEnvExpand(
|
||||
const char *str /**< string to be expanded */
|
||||
);
|
||||
|
||||
/**
|
||||
* \brief Expands macros and environment variables in a string.
|
||||
* \return Expanded string; NULL if any undefined macros were used.
|
||||
*
|
||||
* This routine is similar to macEnvExpand() but allows an optional handle
|
||||
* to be passed in that may contain additional macro definitions.
|
||||
* These macros are appended to the set of macros from environment
|
||||
* variables when expanding the string.
|
||||
*/
|
||||
LIBCOM_API char *
|
||||
epicsStdCall macDefExpand(
|
||||
const char *str, /**< string to be expanded */
|
||||
MAC_HANDLE *macros /**< opaque handle; may be NULL if only
|
||||
environment variables are to be used */
|
||||
);
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/*
|
||||
* Implementation of utility macro substitution library (macLib)
|
||||
@@ -17,7 +17,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "dbDefs.h"
|
||||
#include "errlog.h"
|
||||
#include "macLib.h"
|
||||
@@ -29,18 +28,18 @@
|
||||
* and escapes are honored but only removed from macro names (not
|
||||
* values)
|
||||
*/
|
||||
long /* #defns encountered; <0 = ERROR */
|
||||
epicsShareAPI macParseDefns(
|
||||
MAC_HANDLE *handle, /* opaque handle; can be NULL if default */
|
||||
/* special characters are to be used */
|
||||
long /* #defns encountered; <0 = ERROR */
|
||||
epicsStdCall macParseDefns(
|
||||
MAC_HANDLE *handle, /* opaque handle; can be NULL if default */
|
||||
/* special characters are to be used */
|
||||
|
||||
const char *defns, /* macro definitions in "a=xxx,b=yyy" */
|
||||
/* format */
|
||||
const 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 */
|
||||
{
|
||||
static const size_t altNumMax = 4;
|
||||
size_t numMax;
|
||||
@@ -59,7 +58,7 @@ epicsShareAPI macParseDefns(
|
||||
|
||||
/* debug output */
|
||||
if ( handle && (handle->debug & 1) )
|
||||
printf( "macParseDefns( %s )\n", defns );
|
||||
printf( "macParseDefns( %s )\n", defns );
|
||||
|
||||
/* allocate temporary pointer arrays; in worst case they need to have
|
||||
as many entries as the length of the defns string */
|
||||
@@ -80,91 +79,91 @@ epicsShareAPI macParseDefns(
|
||||
state = preName;
|
||||
for ( c = (const char *) defns; *c != '\0'; c++ ) {
|
||||
|
||||
/* handle quotes */
|
||||
if ( quote )
|
||||
quote = ( *c == quote ) ? 0 : quote;
|
||||
else if ( *c == '\'' || *c == '"' )
|
||||
quote = *c;
|
||||
/* handle quotes */
|
||||
if ( quote )
|
||||
quote = ( *c == quote ) ? 0 : quote;
|
||||
else if ( *c == '\'' || *c == '"' )
|
||||
quote = *c;
|
||||
|
||||
/* handle escapes (pointer incremented below) */
|
||||
escape = ( *c == '\\' && *( c + 1 ) != '\0' );
|
||||
/* handle escapes (pointer incremented below) */
|
||||
escape = ( *c == '\\' && *( c + 1 ) != '\0' );
|
||||
|
||||
switch ( state ) {
|
||||
case preName:
|
||||
if ( !quote && !escape && ( isspace( (int) *c ) || *c == ',' ) ) break;
|
||||
ptr[num] = c;
|
||||
state = inName;
|
||||
/* fall through (may be empty name) */
|
||||
switch ( state ) {
|
||||
case preName:
|
||||
if ( !quote && !escape && ( isspace( (int) *c ) || *c == ',' ) ) break;
|
||||
ptr[num] = c;
|
||||
state = inName;
|
||||
/* fall through (may be empty name) */
|
||||
|
||||
case inName:
|
||||
if ( quote || escape || ( *c != '=' && *c != ',' ) ) break;
|
||||
end[num] = c;
|
||||
while ( end[num] > ptr[num] && isspace( (int) *( end[num] - 1 ) ) )
|
||||
end[num]--;
|
||||
num++;
|
||||
del[num] = FALSE;
|
||||
state = preValue;
|
||||
if ( *c != ',' ) break;
|
||||
del[num] = TRUE;
|
||||
/* fall through (','; will delete) */
|
||||
case inName:
|
||||
if ( quote || escape || ( *c != '=' && *c != ',' ) ) break;
|
||||
end[num] = c;
|
||||
while ( end[num] > ptr[num] && isspace( (int) *( end[num] - 1 ) ) )
|
||||
end[num]--;
|
||||
num++;
|
||||
del[num] = FALSE;
|
||||
state = preValue;
|
||||
if ( *c != ',' ) break;
|
||||
del[num] = TRUE;
|
||||
/* fall through (','; will delete) */
|
||||
|
||||
case preValue:
|
||||
if ( !quote && !escape && isspace( (int) *c ) ) break;
|
||||
ptr[num] = c;
|
||||
state = inValue;
|
||||
/* fall through (may be empty value) */
|
||||
case preValue:
|
||||
if ( !quote && !escape && isspace( (int) *c ) ) break;
|
||||
ptr[num] = c;
|
||||
state = inValue;
|
||||
/* fall through (may be empty value) */
|
||||
|
||||
case inValue:
|
||||
if ( quote || escape || *c != ',' ) break;
|
||||
end[num] = c;
|
||||
while ( end[num] > ptr[num] && isspace( (int) *( end[num] - 1 ) ) )
|
||||
end[num]--;
|
||||
num++;
|
||||
del[num] = FALSE;
|
||||
state = preName;
|
||||
break;
|
||||
}
|
||||
case inValue:
|
||||
if ( quote || escape || *c != ',' ) break;
|
||||
end[num] = c;
|
||||
while ( end[num] > ptr[num] && isspace( (int) *( end[num] - 1 ) ) )
|
||||
end[num]--;
|
||||
num++;
|
||||
del[num] = FALSE;
|
||||
state = preName;
|
||||
break;
|
||||
}
|
||||
|
||||
/* if this was escape, increment pointer now (couldn't do
|
||||
before because could have ignored escape at start of name
|
||||
or value) */
|
||||
if ( escape ) c++;
|
||||
/* if this was escape, increment pointer now (couldn't do
|
||||
before because could have ignored escape at start of name
|
||||
or value) */
|
||||
if ( escape ) c++;
|
||||
}
|
||||
|
||||
/* tidy up from state at end of string */
|
||||
switch ( state ) {
|
||||
case preName:
|
||||
break;
|
||||
break;
|
||||
case inName:
|
||||
end[num] = c;
|
||||
while ( end[num] > ptr[num] && isspace( (int) *( end[num] - 1 ) ) )
|
||||
end[num]--;
|
||||
num++;
|
||||
del[num] = TRUE;
|
||||
end[num] = c;
|
||||
while ( end[num] > ptr[num] && isspace( (int) *( end[num] - 1 ) ) )
|
||||
end[num]--;
|
||||
num++;
|
||||
del[num] = TRUE;
|
||||
case preValue:
|
||||
ptr[num] = c;
|
||||
ptr[num] = c;
|
||||
case inValue:
|
||||
end[num] = c;
|
||||
while ( end[num] > ptr[num] && isspace( (int) *( end[num] - 1 ) ) )
|
||||
end[num]--;
|
||||
num++;
|
||||
del[num] = FALSE;
|
||||
end[num] = c;
|
||||
while ( end[num] > ptr[num] && isspace( (int) *( end[num] - 1 ) ) )
|
||||
end[num]--;
|
||||
num++;
|
||||
del[num] = FALSE;
|
||||
}
|
||||
|
||||
/* debug output */
|
||||
if ( handle != NULL && handle->debug & 4 )
|
||||
for ( i = 0; i < num; i += 2 )
|
||||
printf( "[%ld] %.*s = [%ld] %.*s (%s) (%s)\n",
|
||||
(long) (end[i+0] - ptr[i+0]), (int) (end[i+0] - ptr[i+0]), ptr[i+0],
|
||||
(long) (end[i+1] - ptr[i+1]), (int) (end[i+1] - ptr[i+1]), ptr[i+1],
|
||||
del[i+0] ? "del" : "nodel",
|
||||
del[i+1] ? "del" : "nodel" );
|
||||
for ( i = 0; i < num; i += 2 )
|
||||
printf( "[%ld] %.*s = [%ld] %.*s (%s) (%s)\n",
|
||||
(long) (end[i+0] - ptr[i+0]), (int) (end[i+0] - ptr[i+0]), ptr[i+0],
|
||||
(long) (end[i+1] - ptr[i+1]), (int) (end[i+1] - ptr[i+1]), ptr[i+1],
|
||||
del[i+0] ? "del" : "nodel",
|
||||
del[i+1] ? "del" : "nodel" );
|
||||
|
||||
/* calculate how much memory to allocate: pointers followed by
|
||||
strings */
|
||||
nbytes = ( num + 2 ) * sizeof( char * );
|
||||
for ( i = 0; i < num; i++ )
|
||||
nbytes += end[i] - ptr[i] + 1;
|
||||
nbytes += end[i] - ptr[i] + 1;
|
||||
|
||||
/* allocate memory and set returned pairs pointer */
|
||||
memCp = malloc( nbytes );
|
||||
@@ -177,16 +176,16 @@ epicsShareAPI macParseDefns(
|
||||
memCp += ( num + 2 ) * sizeof( char * );
|
||||
for ( i = 0; i < num; i++ ) {
|
||||
|
||||
/* if no '=' followed the name, macro will be deleted */
|
||||
if ( del[i] )
|
||||
*memCpp++ = NULL;
|
||||
else
|
||||
*memCpp++ = memCp;
|
||||
/* if no '=' followed the name, macro will be deleted */
|
||||
if ( del[i] )
|
||||
*memCpp++ = NULL;
|
||||
else
|
||||
*memCpp++ = memCp;
|
||||
|
||||
/* copy value regardless of the above */
|
||||
strncpy( memCp, (const char *) ptr[i], end[i] - ptr[i] );
|
||||
memCp += end[i] - ptr[i];
|
||||
*memCp++ = '\0';
|
||||
/* copy value regardless of the above */
|
||||
strncpy( memCp, (const char *) ptr[i], end[i] - ptr[i] );
|
||||
memCp += end[i] - ptr[i];
|
||||
*memCp++ = '\0';
|
||||
}
|
||||
|
||||
/* add two NULL pointers */
|
||||
@@ -196,31 +195,31 @@ epicsShareAPI macParseDefns(
|
||||
/* remove quotes and escapes from names in place (unlike values, they
|
||||
will not be re-parsed) */
|
||||
for ( p = *pairs; *p != NULL; p += 2 ) {
|
||||
quote = 0;
|
||||
for ( s = d = *p; *s != '\0'; s++ ) {
|
||||
quote = 0;
|
||||
for ( s = d = *p; *s != '\0'; s++ ) {
|
||||
|
||||
/* quotes are not copied */
|
||||
if ( quote ) {
|
||||
if ( *s == quote ) {
|
||||
quote = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if ( *s == '\'' || *s == '"' ) {
|
||||
quote = *s;
|
||||
continue;
|
||||
}
|
||||
/* quotes are not copied */
|
||||
if ( quote ) {
|
||||
if ( *s == quote ) {
|
||||
quote = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if ( *s == '\'' || *s == '"' ) {
|
||||
quote = *s;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* escapes are not copied but next character is */
|
||||
if ( *s == '\\' && *( s + 1 ) != '\0' )
|
||||
s++;
|
||||
/* escapes are not copied but next character is */
|
||||
if ( *s == '\\' && *( s + 1 ) != '\0' )
|
||||
s++;
|
||||
|
||||
/* others are copied */
|
||||
*d++ = *s;
|
||||
}
|
||||
/* others are copied */
|
||||
*d++ = *s;
|
||||
}
|
||||
|
||||
/* need to terminate destination */
|
||||
*d++ = '\0';
|
||||
/* need to terminate destination */
|
||||
*d++ = '\0';
|
||||
}
|
||||
|
||||
/* free workspace */
|
||||
@@ -230,7 +229,7 @@ epicsShareAPI macParseDefns(
|
||||
|
||||
/* debug output */
|
||||
if ( handle != NULL && handle->debug & 1 )
|
||||
printf( "macParseDefns() -> %d\n", num / 2 );
|
||||
printf( "macParseDefns() -> %d\n", num / 2 );
|
||||
|
||||
/* success exit; return number of definitions */
|
||||
return num / 2;
|
||||
@@ -248,35 +247,35 @@ error:
|
||||
/*
|
||||
* Install an array of name / value pairs as macro definitions. The
|
||||
* array should have an even number of elements followed by at least
|
||||
* one (preferably two) NULL pointers
|
||||
* one (preferably two) NULL pointers
|
||||
*/
|
||||
long /* #macros defined; <0 = ERROR */
|
||||
epicsShareAPI macInstallMacros(
|
||||
MAC_HANDLE *handle, /* opaque handle */
|
||||
long /* #macros defined; <0 = ERROR */
|
||||
epicsStdCall macInstallMacros(
|
||||
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 */
|
||||
{
|
||||
int n;
|
||||
char **p;
|
||||
|
||||
/* debug output */
|
||||
if ( handle->debug & 1 )
|
||||
printf( "macInstallMacros( %s, %s, ... )\n",
|
||||
pairs && pairs[0] ? pairs[0] : "NULL",
|
||||
pairs && pairs[1] ? pairs[1] : "NULL" );
|
||||
printf( "macInstallMacros( %s, %s, ... )\n",
|
||||
pairs && pairs[0] ? pairs[0] : "NULL",
|
||||
pairs && pairs[1] ? pairs[1] : "NULL" );
|
||||
|
||||
/* go through array defining macros */
|
||||
for ( n = 0, p = pairs; p != NULL && p[0] != NULL; n++, p += 2 ) {
|
||||
if ( macPutValue( handle, p[0], p[1] ) < 0 )
|
||||
return -1;
|
||||
if ( macPutValue( handle, p[0], p[1] ) < 0 )
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* debug output */
|
||||
if ( handle->debug & 1 )
|
||||
printf( "macInstallMacros() -> %d\n", n );
|
||||
printf( "macInstallMacros() -> %d\n", n );
|
||||
|
||||
/* return number of macros defined */
|
||||
return n;
|
||||
|
||||
Reference in New Issue
Block a user