ISIS Logo
UTILITIES
EPICS Utilities
iocshCmdFuncs.cpp
Go to the documentation of this file.
1 #include <stdlib.h>
6 #include <string.h>
7 #include <stdio.h>
8 #include <errno.h>
9 #include <math.h>
10 #include <exception>
11 #include <algorithm>
12 #include <stdexcept>
13 #include <iostream>
14 #include <map>
15 #include <list>
16 #include <string>
17 #include <time.h>
18 #include <sstream>
19 #include <fstream>
20 #ifndef _WIN32
21 #include <unistd.h>
22 #endif
23 
24 #include "epicsStdlib.h"
25 #include "epicsString.h"
26 #include "epicsStdio.h"
27 #include "dbDefs.h"
28 #include "epicsMutex.h"
29 #include "dbBase.h"
30 #include "dbStaticLib.h"
31 #include "dbFldTypes.h"
32 #include "dbCommon.h"
33 #include "dbAccessDefs.h"
34 #include <epicsTypes.h>
35 #include <epicsTime.h>
36 #include <epicsThread.h>
37 #include <epicsString.h>
38 #include <epicsTimer.h>
39 #include <epicsMutex.h>
40 #include <iocsh.h>
41 #include "envDefs.h"
42 #include "macLib.h"
43 #include "errlog.h"
44 
45 #include <string.h>
46 #include <registryFunction.h>
47 
48 #include <epicsExport.h>
49 
50 #include "utilities.h"
51 
52 static char* ioc_getenv(const char* var)
53 {
54  char* val = getenv(var);
55  if (val == NULL)
56  {
57  return strdup("");
58  }
59  else
60  {
61  return strdup(val);
62  }
63 }
64 
65 static void loadMacEnviron(MAC_HANDLE* pmh)
66 {
67  for(char** cp = environ; *cp != NULL; ++cp)
68  {
69  char* str_tmp = strdup(*cp);
70  char* equals_loc = strchr(str_tmp, '='); // split name=value string
71  if (equals_loc != NULL)
72  {
73  *equals_loc = '\0';
74  macPutValue(pmh, str_tmp, equals_loc + 1);
75  }
76  free(str_tmp);
77  }
78 }
79 
81 static void subMacros(std::string& new_macros, const char* macros, const char* loopVar)
82 {
83  char loopSubFrom[32], loopSubTo[32];
84  epicsSnprintf(loopSubFrom, sizeof(loopSubFrom), "\\$(%s)", loopVar);
85  epicsSnprintf(loopSubTo, sizeof(loopSubTo), "$(%s)", loopVar);
86  new_macros = macros;
87  size_t start_pos = 0, lf = strlen(loopSubFrom), lt = strlen(loopSubTo);
88  while( (start_pos = new_macros.find(loopSubFrom, start_pos)) != std::string::npos )
89  {
90  new_macros.replace(start_pos, lf, loopSubTo);
91  start_pos += lt;
92  }
93  epicsSnprintf(loopSubFrom, sizeof(loopSubFrom), "\\${%s}", loopVar);
94  epicsSnprintf(loopSubTo, sizeof(loopSubTo), "${%s}", loopVar);
95  start_pos = 0;
96  while( (start_pos = new_macros.find(loopSubFrom, start_pos)) != std::string::npos )
97  {
98  new_macros.replace(start_pos, lf, loopSubTo);
99  start_pos += lt;
100  }
101 }
102 
123 epicsShareFunc void iocshCmdLoop(const char* command, const char* macros, const char* loopVar, int start, int stop, int step)
124 {
125  char loopVal[32];
126  if (loopVar == NULL)
127  {
128  iocshCmd(command);
129  return;
130  }
131  if (step <= 0)
132  {
133  step = 1;
134  }
135  std::string macros_s, command_s;
136  subMacros(command_s, command, loopVar);
137  subMacros(macros_s, macros, loopVar);
138  MAC_HANDLE* mh = NULL;
139  char** pairs;
140  char macros_exp[1024], command_exp[1024];
141  for(int i = start; i <= stop; i += step)
142  {
143  std::map<std::string,char*> old_values;
144  macCreateHandle(&mh, NULL);
145  loadMacEnviron(mh);
146  epicsSnprintf(loopVal, sizeof(loopVal), "%d", i);
147  macPutValue(mh, loopVar, loopVal);
148  macExpandString(mh, command_s.c_str(), command_exp, sizeof(command_exp));
149  macExpandString(mh, macros_s.c_str(), macros_exp, sizeof(macros_exp));
150  pairs = NULL;
151  macParseDefns(mh, macros_exp, &pairs);
152  // save old environment and set new values for command
153  for(int j=0; pairs[j] != NULL; j += 2)
154  {
155  old_values[pairs[j]] = ioc_getenv(pairs[j]);
156  epicsEnvSet(pairs[j], pairs[j+1]);
157  }
158  free(pairs);
159  old_values[loopVar] = ioc_getenv(loopVar);
160  epicsEnvSet(loopVar, loopVal);
161  std::ostringstream new_macros;
162  new_macros << macros_exp << (strlen(macros_exp) > 0 ? "," : "") << loopVar << "=" << loopVal;
163  std::cout << "--> (" << i << ") iocshCmd(\"" << command_exp << "\") with: " << new_macros.str() << std::endl;
164  iocshCmd(command_exp);
165  // restore old environment
166  for(std::map<std::string,char*>::iterator it = old_values.begin(); it != old_values.end(); ++it)
167  {
168  epicsEnvSet(it->first.c_str(), it->second);
169  free(it->second);
170  }
171  macDeleteHandle(mh);
172  }
173 }
174 
194 epicsShareFunc void iocshCmdList(const char* command, const char* macros, const char* loopVar, const char* list, const char* sep)
195 {
196  static const char* default_sep = ";";
197  if (loopVar == NULL || list == NULL)
198  {
199  iocshCmd(command);
200  return;
201  }
202  if (sep == NULL)
203  {
204  sep = default_sep;
205  }
206  std::string macros_s, command_s;
207  subMacros(command_s, command, loopVar);
208  subMacros(macros_s, macros, loopVar);
209  char* saveptr = NULL;
210  char* list_tmp = strdup(list);
211  char* list_item = epicsStrtok_r(list_tmp, sep, &saveptr);
212  MAC_HANDLE* mh = NULL;
213  char** pairs;
214  char macros_exp[1024], command_exp[1024];
215  while(list_item != NULL)
216  {
217  std::map<std::string,char*> old_values;
218  macCreateHandle(&mh, NULL);
219  loadMacEnviron(mh);
220  macPutValue(mh, loopVar, list_item);
221  macExpandString(mh, command_s.c_str(), command_exp, sizeof(command_exp));
222  macExpandString(mh, macros_s.c_str(), macros_exp, sizeof(macros_exp));
223  pairs = NULL;
224  macParseDefns(mh, macros_exp, &pairs);
225  for(int j=0; pairs[j] != NULL; j += 2)
226  {
227  old_values[pairs[j]] = ioc_getenv(pairs[j]);
228  epicsEnvSet(pairs[j], pairs[j+1]);
229  }
230  free(pairs);
231  old_values[loopVar] = ioc_getenv(loopVar);
232  epicsEnvSet(loopVar, list_item);
233  std::ostringstream new_macros;
234  new_macros << macros_exp << (strlen(macros_exp) > 0 ? "," : "") << loopVar << "=" << list_item;
235  std::cout << "--> (" << list_item << ") iocshCmd(\"" << command_exp << "\") with: " << new_macros.str() << std::endl;
236  iocshCmd(command_exp);
237  for(std::map<std::string,char*>::iterator it = old_values.begin(); it != old_values.end(); ++it)
238  {
239  epicsEnvSet(it->first.c_str(), it->second);
240  free(it->second);
241  }
242  macDeleteHandle(mh);
243  list_item = epicsStrtok_r(NULL, sep, &saveptr);
244  }
245  free(list_tmp);
246 }
247 
248 extern "C" {
249 
250 // EPICS iocsh shell commands
251 
252 static const iocshArg iocshCmdLoopInitArg0 = { "command", iocshArgString };
253 static const iocshArg iocshCmdLoopInitArg1 = { "macros", iocshArgString };
254 static const iocshArg iocshCmdLoopInitArg2 = { "loopVar", iocshArgString };
255 static const iocshArg iocshCmdLoopInitArg3 = { "start", iocshArgInt };
256 static const iocshArg iocshCmdLoopInitArg4 = { "stop", iocshArgInt };
257 static const iocshArg iocshCmdLoopInitArg5 = { "step", iocshArgInt };
258 static const iocshArg * const iocshCmdLoopInitArgs[] = { &iocshCmdLoopInitArg0, &iocshCmdLoopInitArg1,
259  &iocshCmdLoopInitArg2, &iocshCmdLoopInitArg3, &iocshCmdLoopInitArg4, &iocshCmdLoopInitArg5 };
260 
261 static const iocshArg iocshCmdListInitArg0 = { "command", iocshArgString };
262 static const iocshArg iocshCmdListInitArg1 = { "macros", iocshArgString };
263 static const iocshArg iocshCmdListInitArg2 = { "loopVar", iocshArgString };
264 static const iocshArg iocshCmdListInitArg3 = { "list", iocshArgString };
265 static const iocshArg iocshCmdListInitArg4 = { "sep", iocshArgString };
266 static const iocshArg * const iocshCmdListInitArgs[] = { &iocshCmdListInitArg0, &iocshCmdListInitArg1,
267  &iocshCmdListInitArg2, &iocshCmdListInitArg3, &iocshCmdListInitArg4 };
268 
269 static const iocshFuncDef iocshCmdLoopDef = {"iocshCmdLoop", sizeof(iocshCmdLoopInitArgs) / sizeof(iocshArg*), iocshCmdLoopInitArgs};
270 
271 static const iocshFuncDef iocshCmdListDef = {"iocshCmdList", sizeof(iocshCmdListInitArgs) / sizeof(iocshArg*), iocshCmdListInitArgs};
272 
273 static void iocshCmdLoopInitCallFunc(const iocshArgBuf *args)
274 {
275  iocshCmdLoop(args[0].sval, args[1].sval, args[2].sval, args[3].ival, args[4].ival, args[5].ival);
276 }
277 
278 static void iocshCmdListInitCallFunc(const iocshArgBuf *args)
279 {
280  iocshCmdList(args[0].sval, args[1].sval, args[2].sval, args[3].sval, args[4].sval);
281 }
282 
283 static void iocshCmdFuncsRegister(void)
284 {
285  iocshRegister(&iocshCmdLoopDef, iocshCmdLoopInitCallFunc);
286  iocshRegister(&iocshCmdListDef, iocshCmdListInitCallFunc);
287 }
288 
289 epicsExportRegistrar(iocshCmdFuncsRegister); // need to be declared via registrar() in utilities.dbd too
290 
291 }
static const iocshFuncDef iocshCmdLoopDef
static void iocshCmdLoopInitCallFunc(const iocshArgBuf *args)
static const iocshArg iocshCmdLoopInitArg0
command string
static const iocshArg iocshCmdLoopInitArg1
macros to pass to command
static const iocshArg iocshCmdLoopInitArg2
loop macro variable name
static const iocshArg *const iocshCmdLoopInitArgs[]
static void iocshCmdFuncsRegister(void)
static void iocshCmdListInitCallFunc(const iocshArgBuf *args)
static const iocshArg iocshCmdListInitArg2
list macro variable name
static const iocshArg *const iocshCmdListInitArgs[]
static char * ioc_getenv(const char *var)
static const iocshArg iocshCmdLoopInitArg4
Loop end value.
static void loadMacEnviron(MAC_HANDLE *pmh)
static const iocshArg iocshCmdListInitArg4
list value separator character
epicsShareFunc void iocshCmdList(const char *command, const char *macros, const char *loopVar, const char *list, const char *sep)
Execute a command multiple times according to a list of items separated by known separator(s).
static const iocshArg iocshCmdLoopInitArg3
Loop start value.
static const iocshArg iocshCmdListInitArg0
command string
static const iocshArg iocshCmdLoopInitArg5
Loop step (default: 1)
static const iocshArg iocshCmdListInitArg1
macros to pass to command
static const iocshArg iocshCmdListInitArg3
list of values to substitute
static const iocshFuncDef iocshCmdListDef
epicsExportRegistrar(dbLoadRecordsFuncsRegister)
static void subMacros(std::string &new_macros, const char *macros, const char *loopVar)
look for e.g. $(I) and replace with so we can substitute later with macEnvExpand() ...
epicsShareFunc void iocshCmdLoop(const char *command, const char *macros, const char *loopVar, int start, int stop, int step)
Execute command multiple times substituting a specified macro according to a number range...
Copyright © 2013 Science and Technology Facilities Council | Generated by   doxygen 1.8.5