- use Tcl library for splitting and merging argument lists

This commit is contained in:
zolliker
2011-08-29 14:41:23 +00:00
parent 1e23f3c7b4
commit 56523419b2
5 changed files with 85 additions and 125 deletions

View File

@ -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;
} }

View File

@ -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);
} }

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -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;
} }
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/