309 lines
11 KiB
C
309 lines
11 KiB
C
/*************************************************************************\
|
|
* Copyright (c) 2007 UChicago Argonne LLC, as Operator of Argonne
|
|
* National Laboratory.
|
|
* 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.
|
|
\*************************************************************************/
|
|
/**
|
|
* \file macLib.h
|
|
* \brief Text macro substitution routines
|
|
* \author 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
|
|
|
|
#include "ellLib.h"
|
|
#include "shareLib.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/** \brief Maximum size of a macro name or value
|
|
*/
|
|
#define MAC_SIZE 256
|
|
|
|
/** \brief Macro substitution context, for use by macLib routines only.
|
|
*
|
|
* An application may have multiple active contexts if desired.
|
|
*/
|
|
typedef struct {
|
|
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;
|
|
|
|
/** \name Core Library
|
|
* The core library provides a minimal set of basic operations.
|
|
* @{
|
|
*/
|
|
|
|
/**
|
|
* \brief Creates a new macro substitution context.
|
|
* \return 0 = OK; <0 = ERROR
|
|
*/
|
|
epicsShareFunc long
|
|
epicsShareAPI macCreateHandle(
|
|
MAC_HANDLE **handle, /**< pointer to 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 \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.
|
|
*/
|
|
epicsShareFunc void
|
|
epicsShareAPI macSuppressWarning(
|
|
MAC_HANDLE *handle, /**< opaque handle */
|
|
|
|
int falseTrue /**< 0 means issue, 1 means suppress*/
|
|
);
|
|
|
|
/**
|
|
* \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.
|
|
*/
|
|
epicsShareFunc long
|
|
epicsShareAPI macExpandString(
|
|
MAC_HANDLE *handle, /**< opaque handle */
|
|
|
|
const char *src, /**< source string */
|
|
|
|
char *dest, /**< destination string */
|
|
|
|
long capacity /**< capacity of destination buffer (dest) */
|
|
);
|
|
|
|
/**
|
|
* \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.
|
|
*/
|
|
epicsShareFunc long
|
|
epicsShareAPI macPutValue(
|
|
MAC_HANDLE *handle, /**< opaque handle */
|
|
|
|
const char *name, /**< macro name */
|
|
|
|
const char *value /**< macro value */
|
|
);
|
|
|
|
/**
|
|
* \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.
|
|
*/
|
|
epicsShareFunc long
|
|
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) */
|
|
);
|
|
/**
|
|
* \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.
|
|
*/
|
|
epicsShareFunc long
|
|
epicsShareAPI 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.
|
|
*/
|
|
epicsShareFunc long
|
|
epicsShareAPI macPushScope(
|
|
MAC_HANDLE *handle /**< opaque handle */
|
|
);
|
|
/**
|
|
* \brief Retrieve the last pushed scope (like stack operations)
|
|
* \return 0 = OK; <0 = ERROR
|
|
*
|
|
* See macPushScope()
|
|
*/
|
|
epicsShareFunc long
|
|
epicsShareAPI 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.
|
|
*/
|
|
epicsShareFunc long
|
|
epicsShareAPI 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.
|
|
*/
|
|
epicsShareFunc long
|
|
epicsShareAPI 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.
|
|
*/
|
|
epicsShareFunc long
|
|
epicsShareAPI 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.
|
|
*/
|
|
epicsShareFunc char *
|
|
epicsShareAPI 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.
|
|
*/
|
|
epicsShareFunc char *
|
|
epicsShareAPI 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
|
|
}
|
|
#endif
|
|
|
|
#endif /*INCmacLibH*/
|