- use Tcl library for splitting and merging argument lists
This commit is contained in:
20
SCinter.c
20
SCinter.c
@ -293,7 +293,6 @@ int InterpExecute(SicsInterp * self, SConnection * pCon, char *pText)
|
|||||||
commandContext comCon;
|
commandContext comCon;
|
||||||
Statistics *old;
|
Statistics *old;
|
||||||
|
|
||||||
|
|
||||||
assert(self);
|
assert(self);
|
||||||
assert(pCon);
|
assert(pCon);
|
||||||
|
|
||||||
@ -312,9 +311,12 @@ int InterpExecute(SicsInterp * self, SConnection * pCon, char *pText)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* convert to argc, argv */
|
/* convert to argc, argv */
|
||||||
argc = 0;
|
/* use Tcl_SplitList instead of Text2Arg, is needed for complicated Tcl syntax. M.Z. 8.2011 */
|
||||||
argv = NULL;
|
iRet = Tcl_SplitList(self->pTcl, pText, &argc, (const char ***)&argv);
|
||||||
Text2Arg(pText, &argc, &argv);
|
if (iRet != TCL_OK) {
|
||||||
|
SCWrite(pCon, "ERROR: illegal tcl syntax", eError);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* the first one must be the target object. If not given an empty
|
/* the first one must be the target object. If not given an empty
|
||||||
command string was given which will be silently ignored */
|
command string was given which will be silently ignored */
|
||||||
@ -364,15 +366,7 @@ int InterpExecute(SicsInterp * self, SConnection * pCon, char *pText)
|
|||||||
|
|
||||||
|
|
||||||
deleteArgv:
|
deleteArgv:
|
||||||
if (argv) {
|
Tcl_Free((char *)argv);
|
||||||
/* delete argv */
|
|
||||||
for (i = 0; i < argc; i++) {
|
|
||||||
if (argv[i] != NULL) {
|
|
||||||
free(argv[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(argv);
|
|
||||||
}
|
|
||||||
return iRet;
|
return iRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
typedef struct ContextItem {
|
typedef struct ContextItem {
|
||||||
struct ContextItem *next;
|
struct ContextItem *next;
|
||||||
Hdb *node;
|
Hdb *node;
|
||||||
Hdb *controllerNode;
|
SctController *controller;
|
||||||
} ContextItem;
|
} ContextItem;
|
||||||
|
|
||||||
typedef struct ScriptContext {
|
typedef struct ScriptContext {
|
||||||
@ -55,7 +55,7 @@ static struct {
|
|||||||
char *name;
|
char *name;
|
||||||
} actionCallback;
|
} actionCallback;
|
||||||
|
|
||||||
void PushContext(Hdb * node, Hdb * controllerNode)
|
void PushContext(Hdb * node, SctController * controller)
|
||||||
{
|
{
|
||||||
ContextItem *new;
|
ContextItem *new;
|
||||||
|
|
||||||
@ -68,7 +68,7 @@ void PushContext(Hdb * node, Hdb * controllerNode)
|
|||||||
new->next = sct->nodes;
|
new->next = sct->nodes;
|
||||||
sct->nodes = new;
|
sct->nodes = new;
|
||||||
new->node = node;
|
new->node = node;
|
||||||
new->controllerNode = controllerNode;
|
new->controller = controller;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PopContext(void)
|
void PopContext(void)
|
||||||
@ -91,8 +91,8 @@ void CleanStack(Hdb * node)
|
|||||||
if (s->node == node) {
|
if (s->node == node) {
|
||||||
s->node = NULL;
|
s->node = NULL;
|
||||||
}
|
}
|
||||||
if (s->controllerNode == node) {
|
if (s->controller->node == node) {
|
||||||
s->controllerNode = NULL;
|
s->controller = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -163,17 +163,22 @@ int SctCommand(SConnection * con, SicsInterp * sics, void *object,
|
|||||||
Hdb *node = NULL;
|
Hdb *node = NULL;
|
||||||
Hdb *cNode = NULL;
|
Hdb *cNode = NULL;
|
||||||
hdbValue v;
|
hdbValue v;
|
||||||
|
SctController *controller;
|
||||||
|
|
||||||
assert(sct == object);
|
assert(sct == object);
|
||||||
if (sct->nodes != NULL) {
|
if (sct->nodes != NULL) {
|
||||||
node = sct->nodes->node;
|
node = sct->nodes->node;
|
||||||
cNode = sct->nodes->controllerNode;
|
controller = sct->nodes->controller;
|
||||||
}
|
}
|
||||||
if (node == NULL && cNode == NULL) {
|
if (node == NULL || controller == NULL || controller->node == NULL) {
|
||||||
SCPrintf(con, eError, "ERROR: %s may be called only in proper context",
|
SCPrintf(con, eError, "ERROR: %s may be called only in proper context",
|
||||||
argv[0]);
|
argv[0]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get path
|
||||||
|
*/
|
||||||
if (argc <= 1) {
|
if (argc <= 1) {
|
||||||
GetHdbPath(node, value, sizeof value);
|
GetHdbPath(node, value, sizeof value);
|
||||||
SCWrite(con, value, eValue);
|
SCWrite(con, value, eValue);
|
||||||
@ -214,7 +219,7 @@ int SctCommand(SConnection * con, SicsInterp * sics, void *object,
|
|||||||
* controller
|
* controller
|
||||||
*/
|
*/
|
||||||
if (strcmp(argv[1], "controller") == 0) {
|
if (strcmp(argv[1], "controller") == 0) {
|
||||||
SCWrite(con, cNode->name, eValue);
|
SCWrite(con, controller->node->name, eValue);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,11 +249,35 @@ int SctCommand(SConnection * con, SicsInterp * sics, void *object,
|
|||||||
/* continue with property handling */
|
/* continue with property handling */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* with command (execute a script in the context of an other node)
|
||||||
|
*/
|
||||||
|
if (strcmp(argv[1], "with") == 0) {
|
||||||
|
if (argc < 3) {
|
||||||
|
SCPrintf(con, eError, "ERROR: syntax must be: %s %s node script",
|
||||||
|
argv[0], argv[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
GetHdbPath(node, value, sizeof value);
|
||||||
|
node = FindHdbNode(value, argv[2], con); /* get a relative path */
|
||||||
|
if (node == NULL) {
|
||||||
|
SCPrintf(con, eError, "ERROR: %s %s: node %s not found",
|
||||||
|
argv[0], argv[1], argv[2]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (SctCallInContext(con, argv[3], node, controller, &val) == 0) {
|
||||||
|
SCPrintf(con, eError, "ERROR: in %s %s %s {%s}: %s",
|
||||||
|
argv[0], argv[1], argv[2], argv[3], val);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* property handling
|
* property handling
|
||||||
*/
|
*/
|
||||||
if (argc == 2) { /* get case */
|
if (argc == 2) { /* get case */
|
||||||
val = GetProp(node, cNode, argv[1]);
|
val = GetProp(node, controller->node, argv[1]);
|
||||||
if (val == NULL) {
|
if (val == NULL) {
|
||||||
SCPrintf(con, eError, "ERROR: %s %s not found", argv[0], argv[1]);
|
SCPrintf(con, eError, "ERROR: %s %s not found", argv[0], argv[1]);
|
||||||
return 0;
|
return 0;
|
||||||
@ -256,10 +285,10 @@ int SctCommand(SConnection * con, SicsInterp * sics, void *object,
|
|||||||
SCWrite(con, val, eValue);
|
SCWrite(con, val, eValue);
|
||||||
} else { /* set case */
|
} else { /* set case */
|
||||||
if (argc == 3) {
|
if (argc == 3) {
|
||||||
SetProp(node, cNode, argv[1], argv[2]);
|
SetProp(node, controller->node, argv[1], argv[2]);
|
||||||
} else {
|
} else {
|
||||||
val = Arg2Tcl(argc - 2, argv + 2, value, sizeof value);
|
val = Arg2Tcl(argc - 2, argv + 2, value, sizeof value);
|
||||||
SetProp(node, cNode, argv[1], val);
|
SetProp(node, controller->node, argv[1], val);
|
||||||
if (val != NULL && val != value)
|
if (val != NULL && val != value)
|
||||||
free(val);
|
free(val);
|
||||||
}
|
}
|
||||||
@ -281,7 +310,7 @@ int SctCallInContext(SConnection * con, char *script, Hdb * node,
|
|||||||
int iRet = 1;
|
int iRet = 1;
|
||||||
int verbose = controller->verbose;
|
int verbose = controller->verbose;
|
||||||
|
|
||||||
PushContext(node, controller->node);
|
PushContext(node, controller);
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
SCPrintf(con, eLog, "%6.3f script: %s", secondsOfMinute(), script);
|
SCPrintf(con, eLog, "%6.3f script: %s", secondsOfMinute(), script);
|
||||||
}
|
}
|
||||||
|
@ -3226,7 +3226,6 @@ static int SetSICSHdbProperty(SConnection * pCon, SicsInterp * pSics,
|
|||||||
void *pData, int argc, char *argv[])
|
void *pData, int argc, char *argv[])
|
||||||
{
|
{
|
||||||
pHdb targetNode = NULL;
|
pHdb targetNode = NULL;
|
||||||
char buffer[512];
|
|
||||||
char *val;
|
char *val;
|
||||||
|
|
||||||
if (argc < 4) {
|
if (argc < 4) {
|
||||||
@ -3238,12 +3237,15 @@ static int SetSICSHdbProperty(SConnection * pCon, SicsInterp * pSics,
|
|||||||
SCPrintf(pCon, eError, "ERROR: node %s not found", argv[1]);
|
SCPrintf(pCon, eError, "ERROR: node %s not found", argv[1]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
val = Arg2Tcl(argc - 3, &argv[3], buffer, sizeof buffer);
|
if (argc == 4) {
|
||||||
|
SetHdbProperty(targetNode, argv[2], argv[3]);
|
||||||
|
} else {
|
||||||
|
val = Arg2Tcl(argc - 3, &argv[3], NULL, 0);
|
||||||
if (val) {
|
if (val) {
|
||||||
SetHdbProperty(targetNode, argv[2], val);
|
SetHdbProperty(targetNode, argv[2], val);
|
||||||
if (val != buffer)
|
|
||||||
free(val);
|
free(val);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
SCSendOK(pCon);
|
SCSendOK(pCon);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,7 @@ static void saveSICSNode(pHdb node, char *prefix, FILE * fd)
|
|||||||
hdbValue v;
|
hdbValue v;
|
||||||
pDynString data = NULL;
|
pDynString data = NULL;
|
||||||
char *cmd;
|
char *cmd;
|
||||||
|
char *str, *value;
|
||||||
|
|
||||||
cmd = GetHdbProp(node, "creationCmd");
|
cmd = GetHdbProp(node, "creationCmd");
|
||||||
if (cmd != NULL) {
|
if (cmd != NULL) {
|
||||||
@ -57,8 +58,11 @@ static void saveSICSNode(pHdb node, char *prefix, FILE * fd)
|
|||||||
GetHipadabaPar(node, &v, NULL);
|
GetHipadabaPar(node, &v, NULL);
|
||||||
data = formatValue(v, node);
|
data = formatValue(v, node);
|
||||||
if (data != NULL) {
|
if (data != NULL) {
|
||||||
fprintf(fd, "%s %s\n", prefix, GetCharArray(data));
|
value = GetCharArray(data);
|
||||||
|
str = Arg2Tcl(1, &value, NULL, 0);
|
||||||
|
fprintf(fd, "%s %s\n", prefix, str);
|
||||||
DeleteDynString(data);
|
DeleteDynString(data);
|
||||||
|
free(str);
|
||||||
}
|
}
|
||||||
ReleaseHdbValue(&v);
|
ReleaseHdbValue(&v);
|
||||||
child = node->child;
|
child = node->child;
|
||||||
@ -92,6 +96,7 @@ int SaveSICSOBJ(void *data, char *name, FILE * fd)
|
|||||||
saveSICSNode(node, prefix, fd);
|
saveSICSNode(node, prefix, fd);
|
||||||
node = node->next;
|
node = node->next;
|
||||||
}
|
}
|
||||||
|
fprintf(fd, "\n");
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
114
splitter.c
114
splitter.c
@ -373,106 +373,36 @@ int isNumeric(char *pText)
|
|||||||
char *Arg2Tcl0(int argc, char *argv[], char *buffer, int buffersize,
|
char *Arg2Tcl0(int argc, char *argv[], char *buffer, int buffersize,
|
||||||
char *prepend)
|
char *prepend)
|
||||||
{
|
{
|
||||||
int i, l, firstArgToQuote, quote, prependlen;
|
int l;
|
||||||
char ch;
|
char *res, *args, *fr;
|
||||||
char *res, *arg;
|
|
||||||
|
|
||||||
|
args = Tcl_Merge(argc, (const char **)argv);
|
||||||
|
if (args == NULL)
|
||||||
|
return NULL;
|
||||||
|
fr = args;
|
||||||
|
l = strlen(args);
|
||||||
if (prepend) {
|
if (prepend) {
|
||||||
prependlen = strlen(prepend);
|
l += strlen(prepend) + 1;
|
||||||
l = prependlen + 1;
|
if (l >= buffersize) {
|
||||||
} else {
|
res = calloc(l, 1);
|
||||||
prependlen = 0;
|
if (res == NULL)
|
||||||
l = 0;
|
|
||||||
}
|
|
||||||
firstArgToQuote = argc;
|
|
||||||
quote = 0;
|
|
||||||
for (i = 0; i < argc; i++) {
|
|
||||||
arg = argv[i];
|
|
||||||
if (arg == NULL)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
ch = *arg++;
|
|
||||||
if (ch == '\0')
|
|
||||||
quote = 1;
|
|
||||||
while (ch != '\0') {
|
|
||||||
switch (ch) {
|
|
||||||
case '\\':
|
|
||||||
l += 2;
|
|
||||||
quote = 1;
|
|
||||||
break;
|
|
||||||
case '"':
|
|
||||||
l += 2;
|
|
||||||
quote = 1;
|
|
||||||
break;
|
|
||||||
case ' ':
|
|
||||||
case '\t':
|
|
||||||
case '\v':
|
|
||||||
case '\f':
|
|
||||||
case '\r':
|
|
||||||
case '\n':
|
|
||||||
l++;
|
|
||||||
quote = 1;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
l++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ch = *arg++;
|
|
||||||
}
|
|
||||||
if (quote == 0) {
|
|
||||||
firstArgToQuote = i + 1;
|
|
||||||
l += 1;
|
|
||||||
} else {
|
} else {
|
||||||
l += 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (l > buffersize) {
|
|
||||||
buffer = calloc(l, 1);
|
|
||||||
if (buffer == NULL)
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
res = buffer;
|
res = buffer;
|
||||||
if (prepend) {
|
}
|
||||||
strcpy(res, prepend);
|
strcpy(res, prepend);
|
||||||
res += prependlen;
|
strcat(res, " ");
|
||||||
*res++ = ' ';
|
strcat(res, args);
|
||||||
|
} else {
|
||||||
|
if (l >= buffersize) {
|
||||||
|
res = strdup(args);
|
||||||
|
} else {
|
||||||
|
res = buffer;
|
||||||
|
strcpy(res, args);
|
||||||
}
|
}
|
||||||
for (i = 0; i < argc; i++) {
|
|
||||||
if (i >= firstArgToQuote)
|
|
||||||
*res++ = '"';
|
|
||||||
arg = argv[i];
|
|
||||||
ch = *arg++;
|
|
||||||
while (ch != '\0') {
|
|
||||||
switch (ch) {
|
|
||||||
case '"':
|
|
||||||
*res++ = '\\';
|
|
||||||
*res++ = '"';
|
|
||||||
break;
|
|
||||||
case '\\':
|
|
||||||
*res++ = '\\';
|
|
||||||
*res++ = '\\';
|
|
||||||
break;
|
|
||||||
case '\r':
|
|
||||||
*res++ = '\\';
|
|
||||||
*res++ = 'r';
|
|
||||||
break;
|
|
||||||
case '\n':
|
|
||||||
*res++ = '\\';
|
|
||||||
*res++ = 'n';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
*res++ = ch;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
ch = *arg++;
|
Tcl_Free(fr);
|
||||||
}
|
return res;
|
||||||
if (i >= firstArgToQuote)
|
|
||||||
*res++ = '"';
|
|
||||||
*res++ = ' ';
|
|
||||||
}
|
|
||||||
if (res > buffer)
|
|
||||||
res--; /* remove trailing space */
|
|
||||||
*res = '\0';
|
|
||||||
return buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
|
Reference in New Issue
Block a user