From 2d3db2036b0bb939ded466d05d5e2b6283bce2f8 Mon Sep 17 00:00:00 2001 From: Keenan Lang Date: Wed, 27 Aug 2014 11:33:14 -0500 Subject: [PATCH] Updated iocshBody to keep track of macro context to allow scoping of macro variables from iocshRun/Load --- src/libCom/iocsh/iocsh.cpp | 63 ++++++++++++++++++++++++++++++++------ src/libCom/macLib/macEnv.c | 29 ++++++++---------- src/libCom/macLib/macLib.h | 3 +- 3 files changed, 69 insertions(+), 26 deletions(-) diff --git a/src/libCom/iocsh/iocsh.cpp b/src/libCom/iocsh/iocsh.cpp index 3a9d459cc..b239287c5 100644 --- a/src/libCom/iocsh/iocsh.cpp +++ b/src/libCom/iocsh/iocsh.cpp @@ -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 diff --git a/src/libCom/macLib/macEnv.c b/src/libCom/macLib/macEnv.c index d78769138..019a67f5d 100644 --- a/src/libCom/macLib/macEnv.c +++ b/src/libCom/macLib/macEnv.c @@ -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; } diff --git a/src/libCom/macLib/macLib.h b/src/libCom/macLib/macLib.h index 89dccf72c..84339711a 100644 --- a/src/libCom/macLib/macLib.h +++ b/src/libCom/macLib/macLib.h @@ -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