- design improvements in scriptcontext (sct send) and ascon (AsconBaseHandler)

- bug fixes
This commit is contained in:
zolliker
2009-03-03 14:07:43 +00:00
parent 0dc196becb
commit 2e060ccf73
8 changed files with 292 additions and 172 deletions

207
ascon.c
View File

@ -15,6 +15,7 @@
#include "uselect.h"
static double lastClose = 0; /* time of last close operation */
static AsconProtocol *protocols = NULL;
/*
CreateSocketAdress stolen from Tcl. Thanks to John Ousterhout
@ -132,6 +133,10 @@ static void AsconConnect(Ascon * a)
return;
}
}
if (a->hostport == NULL) {
AsconError(a, "no host:port given", 0);
return;
}
colon = strchr(a->hostport, ':');
if (colon == NULL)
return;
@ -167,28 +172,6 @@ static void AsconConnect(Ascon * a)
return;
}
int AsconStdInit(Ascon *a, SConnection *con, int argc, char *argv[])
{
a->fd = -1;
a->state = AsconConnectStart;
a->hostport = strdup(argv[1]);
if (argc > 2) {
a->sendTerminator = strdup(argv[2]);
} else {
a->sendTerminator = strdup("\n");
}
if (argc > 3) {
a->timeout = atof(argv[3]);
} else {
a->timeout = 2.0; /* sec */
}
a->replyTerminator == NULL;
if (argc > 4 && argv[4][0] != '\0') {
a->replyTerminator = strdup(argv[4]);
}
return 1;
}
int AsconReadGarbage(int fd)
{
fd_set rmask;
@ -315,14 +298,14 @@ int AsconWriteChars(int fd, char *data, int length)
static double lastCall = 0;
int AsconStdHandler(Ascon * a)
int AsconBaseHandler(Ascon * a)
{
int ret;
int l;
char chr;
double now = DoubleTime();
if (now > lastCall + 0.5) { /* AsconStdHandler was not called since a long time (0.5 sec) */
if (now > lastCall + 0.5) { /* AsconBaseHandler was not called since a long time (0.5 sec) */
if (lastCall != 0) { /* extend timeout time (for debugging purposes) */
a->start += now - lastCall - 0.5;
}
@ -343,26 +326,13 @@ int AsconStdHandler(Ascon * a)
}
break;
case AsconWriteStart:
if (strstr(GetCharArray(a->wrBuffer), "@@NOSEND@@") != NULL) {
a->state = AsconWriteDone;
} else {
if (a->sendTerminator) {
DynStringConcat(a->wrBuffer, a->sendTerminator);
a->wrPos = 0;
a->state = AsconWriting;
}
a->wrPos = 0;
a->state = AsconWriting;
break;
case AsconWriting:
if (a->readState) { /* last char was CR */
ret = AsconReadChar(a->fd, &chr);
if (ret > 0) {
if (chr == '\n') {
/* swallow LF after CR */
a->readState = 0;
} else {
/* garbage character found */
}
}
}
AsconReadGarbage(a->fd);
l = GetDynStringLength(a->wrBuffer) - a->wrPos;
ret = AsconWriteChars(a->fd, GetCharArray(a->wrBuffer) + a->wrPos, l);
@ -382,56 +352,24 @@ int AsconStdHandler(Ascon * a)
break;
case AsconReading:
ret = AsconReadChar(a->fd, &chr);
if (ret > 0) {
a->start = DoubleTime();
if (a->replyTerminator != NULL) {
if (strchr(a->replyTerminator, chr) != NULL) {
DynStringConcatChar(a->rdBuffer, chr);
DynStringConcatChar(a->rdBuffer, '\0');
a->state = AsconReadDone;
break;
}
} else {
if (chr == '\n') {
if (a->readState) { /* last char was CR */
/* swallow LF after CR */
a->readState = 0;
chr = 0;
} else {
DynStringConcatChar(a->rdBuffer, '\0');
a->state = AsconReadDone;
break;
}
} else if (chr == '\r') {
a->readState = 1; /* set 'last char was CR' */
DynStringConcatChar(a->rdBuffer, '\0');
a->state = AsconReadDone;
break;
if (ret <= 0) {
if (ret < 0) {
AsconError(a, "ASC5", errno);
return 0;
}
if (a->timeout > 0) {
if (DoubleTime() - a->start > a->timeout) {
AsconError(a, "no response", 0);
a->state = AsconTimeout;
}
}
if (chr != 0) {
if (DynStringConcatChar(a->rdBuffer, chr) == 0) {
AsconError(a, "DynStringConcatChar failed:", ENOMEM);
break;
}
a->readState = 0;
}
return 0;
}
if (ret < 0) {
AsconError(a, "ASC5", errno);
return 1;
}
if (a->state == AsconReadDone) {
DynStringConcatChar(a->rdBuffer, '\0');
} else if (ret > 0) {
return 0; /* characater read: recycle */
}
if (a->timeout > 0) {
if (DoubleTime() - a->start > a->timeout) {
AsconError(a, "no response", 0);
a->state = AsconTimeout;
}
a->lastChar = chr;
a->start = DoubleTime();
if (DynStringConcatChar(a->rdBuffer, chr) == 0) {
AsconError(a, "ASC6", errno);
return 0;
}
break;
default:
@ -440,8 +378,6 @@ int AsconStdHandler(Ascon * a)
return 1;
}
static AsconProtocol *protocols = NULL;
void AsconInsertProtocol(AsconProtocol *protocol) {
protocol->next = protocols;
protocols = protocol;
@ -472,6 +408,88 @@ AsconHandler AsconSetHandler(Ascon *a, SConnection *con,
return NULL;
}
/* --- standard handler ---- */
int AsconStdHandler(Ascon * a)
{
int result;
char chr;
int ret;
switch (a->state) {
case AsconWriteStart:
if (strstr(GetCharArray(a->wrBuffer), "@@NOSEND@@") != NULL) {
a->state = AsconWriteDone;
return 1;
}
break; /* go to the base handler */
case AsconWriting:
if (a->readState) { /* last char was CR */
ret = AsconReadChar(a->fd, &chr);
if (ret > 0) {
if (chr == '\n') {
/* swallow LF after CR */
a->readState = 0;
} else {
/* garbage character found -> swallow */
}
}
}
break; /* go to the base handler */
case AsconReading:
result = AsconBaseHandler(a);
if (result == 0)
return 0;
chr = a->lastChar;
if (a->replyTerminator != NULL) {
if (strchr(a->replyTerminator, chr) != NULL) {
DynStringConcatChar(a->rdBuffer, '\0');
a->state = AsconReadDone;
}
} else {
if (chr == '\n') {
if (a->readState) { /* last char was CR */
/* swallow LF after CR */
a->readState = 0;
} else {
DynStringBackspace(a->rdBuffer); /* remove LF */
DynStringConcatChar(a->rdBuffer, '\0');
a->state = AsconReadDone;
}
} else if (chr == '\r') {
a->readState = 1; /* set 'last char was CR' */
DynStringBackspace(a->rdBuffer); /* remove CR */
DynStringConcatChar(a->rdBuffer, '\0');
a->state = AsconReadDone;
}
}
return 1; /* base handler was already called */
default:
break;
}
return AsconBaseHandler(a);
}
int AsconStdInit(Ascon *a, SConnection *con, int argc, char *argv[])
{
a->hostport = strdup(argv[1]);
if (argc > 2) {
a->sendTerminator = strdup(argv[2]);
} else {
a->sendTerminator = strdup("\n");
}
if (argc > 3) {
a->timeout = atof(argv[3]);
} else {
a->timeout = 2.0; /* sec */
}
a->replyTerminator = NULL;
if (argc > 4 && argv[4][0] != '\0') {
a->replyTerminator = strdup(argv[4]);
}
return 1;
}
/* --- implementation of higher level interface ---- */
char *ConcatArgs(int argc, char *argv[])
@ -489,6 +507,15 @@ Ascon *AsconMake(SConnection * con, int argc, char *argv[])
SCWrite(con, "ERROR: no memory", eError);
return NULL;
}
a->fd = -1;
a->state = AsconConnectStart;
a->timeout = 2.0; /* 2 sec default */
a->reconnectInterval = 10; /* 10 sec default */
a->replyTerminator = NULL;
a->sendTerminator = NULL;
a->hostport = NULL;
a->responseValid = 0;
a->handler = AsconSetHandler(a, con, argc, argv);
if (a->handler == NULL) {
args = ConcatArgs(argc, argv);
@ -501,7 +528,7 @@ Ascon *AsconMake(SConnection * con, int argc, char *argv[])
a->rdBuffer = CreateDynString(60, 63);
a->wrBuffer = CreateDynString(60, 63);
a->errmsg = CreateDynString(60, 63);
a->responseValid = 0;
return a;
}

65
ascon.i
View File

@ -51,25 +51,26 @@ typedef int (* AsconHandler)(Ascon *connection);
* all members are public, allowing access by handler wrappers
*/
struct Ascon {
AsconState state; /**< the current state */
int fd; /**< socket */
int readState; /**< default implementation: 'was cr' */
pDynString rdBuffer;/**< read buffer */
pDynString wrBuffer;/**< write buffer */
int wrPos; /**< write buffer position */
double timeout; /**< read timeout (sec) */
char *sendTerminator; /**< terminator for sending messages */
char *replyTerminator; /**< terminator list for reply. NULL is the special case CR, LF or CR/LF */
char *hostport; /**< host:port to connect */
pDynString errmsg; /**< error message */
double start; /**< unix time when read was started */
void *private; /**< private data of protocol */
AsconState state; /**< the current state */
int fd; /**< socket */
int readState; /**< default implementation: 'was cr' */
pDynString rdBuffer; /**< read buffer */
pDynString wrBuffer; /**< write buffer */
int wrPos; /**< write buffer position */
double timeout; /**< read timeout (sec) */
char *sendTerminator; /**< terminator for sending messages */
char *replyTerminator; /**< terminator list for reply. NULL is the special case CR, LF or CR/LF */
char *hostport; /**< host:port to connect */
pDynString errmsg; /**< error message */
double start; /**< unix time when read was started */
void *private; /**< private data of protocol */
void (*killPrivate)(void *); /** < kill function for private */
int noResponse; /**< no response expected */
int responseValid; /**< a valid response is ready */
AsconHandler handler; /**< handler function */
double reconnectInterval; /**< reconnect interval */
double lastReconnect; /**< last reconnect try */
int noResponse; /**< no response expected */
int responseValid; /**< a valid response is ready */
AsconHandler handler; /**< handler function */
double reconnectInterval; /**< reconnect interval */
double lastReconnect; /**< last reconnect try */
char lastChar; /**< last char read */
};
#define ASCON_SELECT_ERROR -1
@ -77,14 +78,25 @@ struct Ascon {
#define ASCON_SEND_ERROR -3
#define ASCON_DISCONNECTED -4
/** \brief the basic handler routine.
* \param a the connection
* \return when the state before the call was not AsconReading, the return
* value should be 1
* when the state was AsconReading, a 1 indicates that a character was read
* and the character is stored in the lastChar field. A 0 indicates
* that no charater was read.
*
*
* In most cases a custom handler may be a wrapper around AsconBaseHandler
* or around AsconStdHandler
*/
int AsconBaseHandler(Ascon *a);
/** \brief the standard handler routine.
* \param a the connection
* \return 0 when it makes sense to call the handler again immediately
* (for example while reading, after a character was read, as
* there may be more chars in the buffer)
* 1 else
* \return see AsconBaseHandler
*
* In most cases a custom handler may be a wrapper around AsconStdHandler
* features: see description of AsconStdInit
*/
int AsconStdHandler(Ascon *a);
@ -94,12 +106,13 @@ int AsconStdHandler(Ascon *a);
* \param argc number of arguments
* \param argv arguments ("<host>:<port>" [sendTerminator] [timeout] [replyTerminators])
* sendTerminator is a character or string sent at the end of a command
* timoeut is in seconds
* timeout is in seconds
* replyTerminator is a string, meant as a list of terminator characters
* if not replyTerminator is given, CR, LF or CR/LF all are detected as
* terminators
* terminators. In this case the terminator is removed from the result,
* where in the case before, the terminator stays in the result.
*
* In most cases a custom init function may be a wrapper around AsconStdInit
* In many cases a custom init function may be a wrapper around AsconStdInit
*/
int AsconStdInit(Ascon *a, SConnection *con, int argc, char *argv[]);

View File

@ -233,15 +233,13 @@ int exeBufProcess(pExeBuf self, SicsInterp * pSics,
SCPrintf(pCon, eLogError, "ERROR: Tcl reported: %s",
pTcl->result);
}
SCWrite(pCon, "ERROR: Tcl error in block:", eLogError);
SCWrite(pCon, GetCharArray(command), eError);
SCWrite(pCon, "ERROR: end of Tcl error block", eLogError);
} else {
if(strstr(pTcl->result, "ERROR") != NULL){
SCPrintf(pCon,eError,"%s occurred in %s", pTcl->result, cmd );
}
SCWrite(pCon, pTcl->result, eError);
pCon->sicsError = 0;
}
SCWrite(pCon, "ERROR: above error was in block:", eError);
SCWrite(pCon, cmd, eError);
SCWrite(pCon, "ERROR: end of Tcl error block", eError);
}
DeleteDynString(command);
if (SCGetInterrupt(pCon) >= eAbortBatch) {

2
lld.c
View File

@ -69,7 +69,7 @@ static int ListInit(int List, int ItemSize)
if (0 != ItemSize) {
/* create dummy head node
*/
Fortify_CheckAllMemory();
(void)Fortify_CheckAllMemory();
Tmp = NODE_MALLOC(List);
if (NULL == Tmp) {
return ERR_MEMORY;

View File

@ -28,6 +28,8 @@ typedef struct ScriptContext {
ObjectDescriptor *desc;
ContextItem *nodes;
ContextItem *trash;
Hdb *sendNode;
int sendCalled;
} ScriptContext;
struct SctController {
@ -152,7 +154,6 @@ int SctCommand(SConnection * con, SicsInterp * sics, void *object,
Hdb *cNode = NULL;
hdbValue v;
double dtime;
int iMacro;
assert(sct == object);
if (sct->nodes != NULL) {
@ -190,14 +191,13 @@ int SctCommand(SConnection * con, SicsInterp * sics, void *object,
* print
*/
if (strcmp(argv[1], "print") == 0) {
iMacro = con->iMacro;
if (queueData != NULL) {
queueData->answered = 1;
con->iMacro = queueData->inMacro; /* take macro flag stored at set callback */
SCsetMacro(con, queueData->inMacro); /* take macro flag stored at set callback */
}
Arg2Text(argc - 2, argv + 2, value, sizeof value);
SCWrite(con, value, eWarning);
con->iMacro = iMacro;
SCsetMacro(con, 1); /* where are always in Macro */
return 1;
}
@ -223,6 +223,19 @@ int SctCommand(SConnection * con, SicsInterp * sics, void *object,
return 1;
}
/*
* send command
*/
if (strcmp(argv[1], "send") == 0 && argc > 2) {
if (sct->sendNode != node) {
SCPrintf(con, eError, "ERROR: %s may be called only in action scripts",
argv[0]);
return 0;
}
sct->sendCalled = 1;
/* continue with property handling */
}
/*
* property handling
*/
@ -265,6 +278,13 @@ int SctCallInContext(SConnection * con, char *script, Hdb * node,
ret = Tcl_EvalEx(pTcl, script, l, 0);
result = (char *) Tcl_GetStringResult(pTcl);
if (ret != TCL_OK && result[0] != '\0') {
if (strncmp(result, "ERROR:", 6) == 0) {
/* remove "ERROR:", as it will be added later */
result += 6;
if (result[0] == ' ') {
result++;
}
}
if (verbose) {
SCPrintf(con, eLog, "error: %s", result);
}
@ -306,8 +326,10 @@ static char *SctActionHandler(void *actionData, char *lastReply,
char *emsg;
size_t l;
int cnt;
int ret;
char timeKey[50], timeVal[50];
int iMacro;
if (queueData != NULL && queueData->conCtx != NULL) {
con = queueData->conCtx;
} else {
@ -325,9 +347,6 @@ static char *SctActionHandler(void *actionData, char *lastReply,
SetProp(node, controller->node, "state", state);
}
for (i = 0; i < 10; i++) {
SetProp(node, controller->node, "sent",
GetProp(node, controller->node, "send"));
SetProp(node, controller->node, "send", NULL);
script = GetProp(node, controller->node, state);
if (script == NULL)
script = state;
@ -339,11 +358,12 @@ static char *SctActionHandler(void *actionData, char *lastReply,
commError = 0;
}
script = strdup(script);
if (!SctCallInContext(con, script, node, controller, &result)) {
sct->sendNode = node;
sct->sendCalled = 0;
ret = SctCallInContext(con, script, node, controller, &result);
sct->sendNode = NULL;
if (ret == 0) {
snprintf(eprop, sizeof eprop, "error_during_%s", data->name);
if (strncmp(result, "ERROR: ", 7) == 0) {
result += 7;
}
emsg = GetHdbProp(node, eprop);
if (emsg == NULL || con != controller->conn) {
GetHdbPath(node, path, sizeof path);
@ -366,7 +386,7 @@ static char *SctActionHandler(void *actionData, char *lastReply,
sscanf(emsg, "%d", &cnt);
}
cnt++;
snprintf(msg, sizeof msg, "%dx {%s} %s", cnt, origScript, result);
snprintf(msg, sizeof msg, "%dx {%s}: %s", cnt, origScript, result);
SetHdbProperty(node, eprop, msg);
send = NULL;
free(script);
@ -375,7 +395,12 @@ static char *SctActionHandler(void *actionData, char *lastReply,
state = result;
if (strcasecmp(state, "idle") == 0 || strcasecmp(state, "unpoll") == 0) {
if (queueData == data && !data->answered) {
SCWrite(con, "o.k.", eWarning);
if (queueData->inMacro == 0) {
iMacro = SCinMacro(con);
con->iMacro = 0;
SCWrite(con, "o.k.", eWarning);
SCsetMacro(con, iMacro);
}
}
snprintf(eprop, sizeof eprop, "error_during_%s", data->name);
emsg = GetHdbProp(node, eprop);
@ -396,8 +421,10 @@ static char *SctActionHandler(void *actionData, char *lastReply,
SetProp(node, controller->node, "state", state);
free(script);
script = NULL;
send = GetProp(node, controller->node, "send");
if (send != NULL && send[0] != '\0') {
if (sct->sendCalled) {
send = GetProp(node, controller->node, "send");
if (send == NULL)
send = "";
if (controller->verbose) {
SCPrintf(con, eLog, "send : %s", send);
}
@ -522,7 +549,9 @@ static hdbCallbackReturn SctActionCallback(Hdb * node, void *userData,
char *error;
SConnection *con;
char path[MAX_HDB_PATH];
char *sicsCommand;
int iMacro;
pm = GetKillPtrMessage(msg);
if (pm != NULL) {
if (data->controller == pm->pPtr) {
@ -554,7 +583,7 @@ static hdbCallbackReturn SctActionCallback(Hdb * node, void *userData,
if (script != NULL) {
if (SctCallInContext(con, script, node, data->controller, &error) ==
0) {
SCPrintf(con, eError, "ERROR: %s", error);
SCPrintf(con, eError, "ERROR: in {%s}: %s", script, error);
SetHdbProperty(node, "target", NULL);
return hdbAbort;
}
@ -574,16 +603,19 @@ static hdbCallbackReturn SctActionCallback(Hdb * node, void *userData,
}
if (data->conCtx != NULL) {
GetHdbPath(node, path, sizeof path);
SCPrintf(data->conCtx, eWarning,
"%s target changed to %s before completion", path,
GetCharArray(text));
if (data->inMacro == 0) {
GetHdbPath(node, path, sizeof path);
SCsetMacro(data->conCtx, 0);
SCPrintf(data->conCtx, eWarning,
"%s target changed to %s before completion", path,
GetCharArray(text));
}
SCDeleteConnection(data->conCtx);
}
DeleteDynString(text);
data->conCtx = SCCopyConnection(con);
data->answered = 0;
data->inMacro = con->iMacro;
data->inMacro = SCinMacro(con);
DevQueue(data->controller->devser, data, prio,
SctWriteHandler, SctMatch, NULL);
/* no kill function in DevQueue: data is owned by the node (callback list) */
@ -594,10 +626,20 @@ static hdbCallbackReturn SctActionCallback(Hdb * node, void *userData,
if (mm != NULL) {
if (queueData != NULL && queueData->conCtx != NULL && !data->answered) {
/* update called from a write action */
data->answered = 1;
GetHdbPath(node, path, sizeof path);
text = formatValue(*(mm->v), node);
SCPrintf(queueData->conCtx, eWarning, "OK: %s set to: %s", path, GetCharArray(text));
if (queueData->inMacro == 0 && queueData->node == node) {
data->answered = 1;
iMacro = SCinMacro(queueData->conCtx);
SCsetMacro(queueData->conCtx, 0);
sicsCommand = GetHdbProp(node, "sicscommand");
if (sicsCommand) {
SCPrintf(queueData->conCtx, eWarning, "OK: %s %s", sicsCommand, GetCharArray(text));
} else {
GetHdbPath(node, path, sizeof path);
SCPrintf(queueData->conCtx, eWarning, "OK: hset %s %s", path, GetCharArray(text));
}
SCsetMacro(queueData->conCtx, iMacro);
}
DeleteDynString(text);
}
return hdbContinue;
@ -1137,7 +1179,8 @@ static int SctMakeController(SConnection * con, SicsInterp * sics,
return 0;
SetHdbProperty(controller->node, "controllerName", objName);
SetHdbProperty(controller->node, "sicsdev", objName);
AddCommand(pServ->pSics, objName, InterInvokeSICSOBJ, KillSICSOBJ, ccmd);
RegisterSICSOBJKillCmd(ccmd, objName);
SetDescriptorKey(ccmd->pDes, "creationCommand", "0");

View File

@ -381,6 +381,7 @@ int SctMakeDriveObject(SConnection * pCon, SicsInterp * pSics,
SetDescriptorKey(pNew->pDes, "creationCommand", "0");
RegisterSICSOBJKillCmd(pNew, argv[1]);
}
SetHdbProperty(pNew->objectNode, "sicsdev", argv[1]);
status = AddCommand(pSics,
argv[1], InterInvokeSICSOBJ, KillDriveOBJ, pNew);
if (status != 1) {

View File

@ -12,13 +12,39 @@
#define MAX_HDB_PATH 1024
/*-------------------------------------------------------------------------*/
static pDynString ComposeSicsCommand(pHdb node)
{
char *sicsdev;
pDynString sicsCommand;
if (node == NULL)
return NULL;
sicsdev = GetHdbProp(node, "sicsdev");
if (sicsdev != NULL) {
sicsCommand = CreateDynString(60,63);
DynStringConcat(sicsCommand, sicsdev);
return sicsCommand;
}
sicsCommand = ComposeSicsCommand(node->mama);
if (sicsCommand) {
if (strchr(GetCharArray(sicsCommand), ' ') == NULL) {
DynStringConcatChar(sicsCommand, ' ');
} else {
DynStringConcatChar(sicsCommand, '/');
}
DynStringConcat(sicsCommand, node->name);
}
return sicsCommand;
}
/*-------------------------------------------------------------------------*/
static int MakePlainNode(pHdb parent, char *name, SConnection * pCon,
int argc, char *argv[])
{
pHdb child = NULL;
int type = 0, length = 0, priv = -1;
hdbValue val;
pDynString sicsCommand = NULL;
if (argc < 5) {
SCWrite(pCon, "ERROR: not enough arguments to create plain node",
eError);
@ -68,6 +94,13 @@ static int MakePlainNode(pHdb parent, char *name, SConnection * pCon,
}
AddHipadabaChild(parent, child, pCon);
if (type != HIPNONE) {
sicsCommand = ComposeSicsCommand(child);
if (sicsCommand) {
SetHdbProperty(child, "sicscommand", GetCharArray(sicsCommand));
DeleteDynString(sicsCommand);
}
}
SCSendOK(pCon);
return 1;
}

View File

@ -351,40 +351,45 @@ static int isNodePrintable(pHdb node)
}
/*---------------------------------------------------------------------------*/
static void objFormatNode(pHdb node, pDynString data)
static void objFormatNode(pHdb node, char separator,
char *prefix, pDynString data)
{
char par[40];
pDynString val = NULL;
snprintf(par, 40, "%-20s = ", node->name);
char par[128];
pDynString dyn = NULL;
int i;
pHdb child;
char *vis;
snprintf(par, sizeof par, "%-20s = ", prefix);
DynStringConcat(data, par);
val = formatValue(node->value, node);
if (val != NULL) {
DynStringConcat(data, GetCharArray(val));
DynStringConcatChar(data, '\n');
DeleteDynString(val);
dyn = formatValue(node->value, node);
if (dyn != NULL) {
DynStringConcat(data, GetCharArray(dyn));
} else {
dyn = CreateDynString(60, 63);
}
DynStringConcatChar(data, '\n');
for (child = node->child; child != NULL; child = child->next) {
DynStringCopy(dyn, prefix);
DynStringConcatChar(dyn, separator);
DynStringConcat(dyn, child->name);
objFormatNode(child, '/', GetCharArray(dyn), data);
}
DeleteDynString(dyn);
}
/*---------------------------------------------------------------------------*/
static int ListObj(pSICSOBJ self, SConnection * pCon, int argc,
char *argv[])
{
pHdb node = NULL;
pDynString data;
data = CreateDynString(128, 128);
if (data == NULL) {
return 0;
}
node = self->pDes->parNode;
if (node != NULL) {
objFormatNode(node, data);
node = node->child;
while (node != NULL) {
objFormatNode(node, data);
node = node->next;
}
if (self->pDes->parNode != NULL) {
objFormatNode(self->pDes->parNode, ' ', argv[0], data);
}
SCWrite(pCon, GetCharArray(data), eValue);
DeleteDynString(data);
@ -440,7 +445,7 @@ int InvokeSICSOBJ(SConnection * pCon, SicsInterp * pSics, void *pData,
} else if (strcmp(argv[1], "list") == 0) {
return ListObj(self, pCon, argc, argv);
}
SCPrintf(pCon, eError, "ERROR: %s %s not found", argv[0], argv[1]);
/* error message written by the caller */
}
return status;
@ -508,7 +513,7 @@ pSICSOBJ SetupSICSOBJ(SConnection * pCon, SicsInterp * pSics, void *pData,
SetDescriptorKey(pNew->pDes, "creationCommand", "0");
}
SetHdbProperty(pNew->objectNode, "objectName", argv[1]);
SetHdbProperty(pNew->objectNode, "sicsdev", argv[1]);
status = AddCommand(pSics,
argv[1], InterInvokeSICSOBJ, KillSICSOBJ, pNew);
if (status != 1) {