Updated iocshBody to keep track of macro context to allow scoping of macro variables from iocshRun/Load
This commit is contained in:
@@ -57,6 +57,9 @@ static char iocshVarID[] = "iocshVar";
|
||||
extern "C" { static void varCallFunc(const iocshArgBuf *); }
|
||||
static epicsMutexId iocshTableMutex;
|
||||
static epicsThreadOnceId iocshTableOnceId = EPICS_THREAD_ONCE_INIT;
|
||||
static epicsThreadOnceId iocshMacroOnceId = EPICS_THREAD_ONCE_INIT;
|
||||
|
||||
static epicsThreadPrivateId iocshMacroHandleId;
|
||||
|
||||
/*
|
||||
* I/O redirection
|
||||
@@ -78,6 +81,14 @@ static void iocshTableOnce (void *)
|
||||
iocshTableMutex = epicsMutexMustCreate ();
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up iocsh MAC_HANDLE for scoped macros
|
||||
*/
|
||||
static void iocshMacroOnce (void *)
|
||||
{
|
||||
iocshMacroHandleId = epicsThreadPrivateCreate();
|
||||
}
|
||||
|
||||
/*
|
||||
* Lock the table mutex
|
||||
*/
|
||||
@@ -475,7 +486,7 @@ static void helpCallFunc(const iocshArgBuf *args)
|
||||
* The body of the command interpreter
|
||||
*/
|
||||
static int
|
||||
iocshBody (const char *pathname, const char *commandLine, const char* macros)
|
||||
iocshBody (const char *pathname, const char *commandLine, const char *macros)
|
||||
{
|
||||
FILE *fp = NULL;
|
||||
const char *filename = NULL;
|
||||
@@ -498,6 +509,9 @@ iocshBody (const char *pathname, const char *commandLine, const char* macros)
|
||||
struct iocshCommand *found;
|
||||
void *readlineContext = NULL;
|
||||
int wasOkToBlock;
|
||||
static char *pairs[] = {NULL, NULL};
|
||||
MAC_HANDLE *handle;
|
||||
char ** defines = NULL;
|
||||
|
||||
/*
|
||||
* See if command interpreter is interactive
|
||||
@@ -540,7 +554,36 @@ iocshBody (const char *pathname, const char *commandLine, const char* macros)
|
||||
fprintf(epicsGetStderr(), "Out of memory!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Parse macro definitions, this check occurs before creating the
|
||||
* macro handle to simplify cleanup.
|
||||
*/
|
||||
|
||||
if (macros) {
|
||||
if (macParseDefns(NULL, macros, &defines) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for existing macro context or construct a new one.
|
||||
*/
|
||||
epicsThreadOnce (&iocshMacroOnceId, iocshMacroOnce, NULL);
|
||||
handle = (MAC_HANDLE *) epicsThreadPrivateGet(iocshMacroHandleId);
|
||||
|
||||
if (handle == NULL) {
|
||||
if (macCreateHandle(&handle, pairs)) {
|
||||
errlogMessage("iocsh: macCreateHandle failed.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
epicsThreadPrivateSet(iocshMacroHandleId, (void *) handle);
|
||||
}
|
||||
|
||||
macPushScope(handle);
|
||||
macInstallMacros(handle, defines);
|
||||
|
||||
/*
|
||||
* Read commands till EOF or exit
|
||||
*/
|
||||
@@ -585,7 +628,7 @@ iocshBody (const char *pathname, const char *commandLine, const char* macros)
|
||||
* Expand macros
|
||||
*/
|
||||
free(line);
|
||||
if ((line = macDefExpand(raw, macros)) == NULL)
|
||||
if ((line = macDefExpand(raw, handle)) == NULL)
|
||||
continue;
|
||||
|
||||
/*
|
||||
@@ -811,6 +854,12 @@ iocshBody (const char *pathname, const char *commandLine, const char* macros)
|
||||
}
|
||||
stopRedirect(filename, lineno, redirects);
|
||||
}
|
||||
macPopScope(handle);
|
||||
|
||||
if (handle->level == 0) {
|
||||
macDeleteHandle(handle);
|
||||
epicsThreadPrivateSet(iocshMacroHandleId, NULL);
|
||||
}
|
||||
if (fp && (fp != stdin))
|
||||
fclose (fp);
|
||||
if (redirects != NULL) {
|
||||
@@ -833,17 +882,13 @@ iocshBody (const char *pathname, const char *commandLine, const char* macros)
|
||||
int epicsShareAPI
|
||||
iocsh (const char *pathname)
|
||||
{
|
||||
if (pathname)
|
||||
epicsEnvSet("IOCSH_STARTUP_SCRIPT", pathname);
|
||||
return iocshBody(pathname, NULL, NULL);
|
||||
return iocshLoad(pathname, NULL);
|
||||
}
|
||||
|
||||
int epicsShareAPI
|
||||
iocshCmd (const char *cmd)
|
||||
{
|
||||
if (cmd == NULL)
|
||||
return 0;
|
||||
return iocshBody(NULL, cmd, NULL);
|
||||
return iocshRun(cmd, NULL);
|
||||
}
|
||||
|
||||
int epicsShareAPI
|
||||
|
||||
@@ -25,29 +25,23 @@ macEnvExpand(const char *str)
|
||||
}
|
||||
|
||||
char * epicsShareAPI
|
||||
macDefExpand(const char *str, const char *macros)
|
||||
macDefExpand(const char *str, MAC_HANDLE *macros)
|
||||
{
|
||||
MAC_HANDLE *handle;
|
||||
static char *pairs[] = { "", "environ", NULL, NULL };
|
||||
char** defines;
|
||||
long destCapacity = 128;
|
||||
char *dest = NULL;
|
||||
int n;
|
||||
|
||||
if (macCreateHandle(&handle, pairs)){
|
||||
errlogMessage("macDefExpand: macCreateHandle failed.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
if (macros) {
|
||||
if (macParseDefns(handle, macros, &defines) < 0) {
|
||||
cantProceed("macDefExpand: invalid macro string");
|
||||
}
|
||||
else {
|
||||
macInstallMacros(handle, defines);
|
||||
handle = macros;
|
||||
} else {
|
||||
if (macCreateHandle(&handle, pairs)){
|
||||
errlogMessage("macDefExpand: macCreateHandle failed.");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
do {
|
||||
destCapacity *= 2;
|
||||
/*
|
||||
@@ -73,7 +67,10 @@ macDefExpand(const char *str, const char *macros)
|
||||
}
|
||||
|
||||
done:
|
||||
if (macDeleteHandle(handle))
|
||||
errlogMessage("macDefExpand: macDeleteHandle failed.");
|
||||
if (macros == NULL) {
|
||||
if (macDeleteHandle(handle)) {
|
||||
errlogMessage("macDefExpand: macDeleteHandle failed.");
|
||||
}
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
@@ -154,7 +154,8 @@ epicsShareAPI macEnvExpand(
|
||||
epicsShareFunc char * /* expanded string; NULL if any undefined macros */
|
||||
epicsShareAPI macDefExpand(
|
||||
const char *str, /* string to be expanded */
|
||||
const char *macros /* macro definitions in "a=xxx, b=yyy" */
|
||||
MAC_HANDLE *macros /* opaque handle; can be NULL if default */
|
||||
/* special characters are to be used */
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
Reference in New Issue
Block a user