diff --git a/SCinter.c b/SCinter.c index 24e24284..1867618f 100644 --- a/SCinter.c +++ b/SCinter.c @@ -293,7 +293,6 @@ int InterpExecute(SicsInterp * self, SConnection * pCon, char *pText) commandContext comCon; Statistics *old; - assert(self); assert(pCon); @@ -312,9 +311,12 @@ int InterpExecute(SicsInterp * self, SConnection * pCon, char *pText) } /* convert to argc, argv */ - argc = 0; - argv = NULL; - Text2Arg(pText, &argc, &argv); + /* use Tcl_SplitList instead of Text2Arg, is needed for complicated Tcl syntax. M.Z. 8.2011 */ + iRet = Tcl_SplitList(self->pTcl, pText, &argc, (const char ***)&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 command string was given which will be silently ignored */ @@ -364,15 +366,7 @@ int InterpExecute(SicsInterp * self, SConnection * pCon, char *pText) deleteArgv: - if (argv) { - /* delete argv */ - for (i = 0; i < argc; i++) { - if (argv[i] != NULL) { - free(argv[i]); - } - } - free(argv); - } + Tcl_Free((char *)argv); return iRet; } diff --git a/scriptcontext.c b/scriptcontext.c index 187aed6c..e471dc76 100644 --- a/scriptcontext.c +++ b/scriptcontext.c @@ -19,7 +19,7 @@ typedef struct ContextItem { struct ContextItem *next; Hdb *node; - Hdb *controllerNode; + SctController *controller; } ContextItem; typedef struct ScriptContext { @@ -55,7 +55,7 @@ static struct { char *name; } actionCallback; -void PushContext(Hdb * node, Hdb * controllerNode) +void PushContext(Hdb * node, SctController * controller) { ContextItem *new; @@ -68,7 +68,7 @@ void PushContext(Hdb * node, Hdb * controllerNode) new->next = sct->nodes; sct->nodes = new; new->node = node; - new->controllerNode = controllerNode; + new->controller = controller; } void PopContext(void) @@ -91,8 +91,8 @@ void CleanStack(Hdb * node) if (s->node == node) { s->node = NULL; } - if (s->controllerNode == node) { - s->controllerNode = NULL; + if (s->controller->node == node) { + s->controller = NULL; } } } @@ -163,17 +163,22 @@ int SctCommand(SConnection * con, SicsInterp * sics, void *object, Hdb *node = NULL; Hdb *cNode = NULL; hdbValue v; + SctController *controller; assert(sct == object); if (sct->nodes != NULL) { 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", argv[0]); return 0; } + + /* + * get path + */ if (argc <= 1) { GetHdbPath(node, value, sizeof value); SCWrite(con, value, eValue); @@ -214,7 +219,7 @@ int SctCommand(SConnection * con, SicsInterp * sics, void *object, * controller */ if (strcmp(argv[1], "controller") == 0) { - SCWrite(con, cNode->name, eValue); + SCWrite(con, controller->node->name, eValue); return 1; } @@ -244,11 +249,35 @@ int SctCommand(SConnection * con, SicsInterp * sics, void *object, /* 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 */ if (argc == 2) { /* get case */ - val = GetProp(node, cNode, argv[1]); + val = GetProp(node, controller->node, argv[1]); if (val == NULL) { SCPrintf(con, eError, "ERROR: %s %s not found", argv[0], argv[1]); return 0; @@ -256,10 +285,10 @@ int SctCommand(SConnection * con, SicsInterp * sics, void *object, SCWrite(con, val, eValue); } else { /* set case */ if (argc == 3) { - SetProp(node, cNode, argv[1], argv[2]); + SetProp(node, controller->node, argv[1], argv[2]); } else { 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) free(val); } @@ -281,7 +310,7 @@ int SctCallInContext(SConnection * con, char *script, Hdb * node, int iRet = 1; int verbose = controller->verbose; - PushContext(node, controller->node); + PushContext(node, controller); if (verbose) { SCPrintf(con, eLog, "%6.3f script: %s", secondsOfMinute(), script); } diff --git a/sicshipadaba.c b/sicshipadaba.c index 026008b9..93ff1a79 100644 --- a/sicshipadaba.c +++ b/sicshipadaba.c @@ -3226,7 +3226,6 @@ static int SetSICSHdbProperty(SConnection * pCon, SicsInterp * pSics, void *pData, int argc, char *argv[]) { pHdb targetNode = NULL; - char buffer[512]; char *val; if (argc < 4) { @@ -3238,11 +3237,14 @@ static int SetSICSHdbProperty(SConnection * pCon, SicsInterp * pSics, SCPrintf(pCon, eError, "ERROR: node %s not found", argv[1]); return 0; } - val = Arg2Tcl(argc - 3, &argv[3], buffer, sizeof buffer); - if (val) { - SetHdbProperty(targetNode, argv[2], val); - if (val != buffer) + if (argc == 4) { + SetHdbProperty(targetNode, argv[2], argv[3]); + } else { + val = Arg2Tcl(argc - 3, &argv[3], NULL, 0); + if (val) { + SetHdbProperty(targetNode, argv[2], val); free(val); + } } SCSendOK(pCon); return 1; diff --git a/sicsobj.c b/sicsobj.c index 161983fe..7f044686 100644 --- a/sicsobj.c +++ b/sicsobj.c @@ -46,7 +46,8 @@ static void saveSICSNode(pHdb node, char *prefix, FILE * fd) hdbValue v; pDynString data = NULL; char *cmd; - + char *str, *value; + cmd = GetHdbProp(node, "creationCmd"); if (cmd != NULL) { GetHdbPath(node, path, sizeof path); @@ -57,8 +58,11 @@ static void saveSICSNode(pHdb node, char *prefix, FILE * fd) GetHipadabaPar(node, &v, NULL); data = formatValue(v, node); 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); + free(str); } ReleaseHdbValue(&v); child = node->child; @@ -92,6 +96,7 @@ int SaveSICSOBJ(void *data, char *name, FILE * fd) saveSICSNode(node, prefix, fd); node = node->next; } + fprintf(fd, "\n"); } return 1; } diff --git a/splitter.c b/splitter.c index 9f607ad1..5253ada3 100644 --- a/splitter.c +++ b/splitter.c @@ -373,106 +373,36 @@ int isNumeric(char *pText) char *Arg2Tcl0(int argc, char *argv[], char *buffer, int buffersize, char *prepend) { - int i, l, firstArgToQuote, quote, prependlen; - char ch; - char *res, *arg; + int l; + char *res, *args, *fr; + args = Tcl_Merge(argc, (const char **)argv); + if (args == NULL) + return NULL; + fr = args; + l = strlen(args); if (prepend) { - prependlen = strlen(prepend); - l = prependlen + 1; - } else { - prependlen = 0; - l = 0; - } - firstArgToQuote = argc; - quote = 0; - for (i = 0; i < argc; i++) { - arg = argv[i]; - if (arg == 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; + l += strlen(prepend) + 1; + if (l >= buffersize) { + res = calloc(l, 1); + if (res == NULL) + return NULL; } else { - l += 3; + res = buffer; } - } - if (l > buffersize) { - buffer = calloc(l, 1); - if (buffer == NULL) - return NULL; - } - res = buffer; - if (prepend) { strcpy(res, prepend); - res += prependlen; - *res++ = ' '; - } - 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++; + strcat(res, " "); + strcat(res, args); + } else { + if (l >= buffersize) { + res = strdup(args); + } else { + res = buffer; + strcpy(res, args); } - if (i >= firstArgToQuote) - *res++ = '"'; - *res++ = ' '; } - if (res > buffer) - res--; /* remove trailing space */ - *res = '\0'; - return buffer; + Tcl_Free(fr); + return res; } /*--------------------------------------------------------------------------*/