751 lines
18 KiB
C
751 lines
18 KiB
C
#include <strings.h>
|
|
#include <tcl.h>
|
|
#include <time.h>
|
|
#include <math.h>
|
|
#include "sics.h"
|
|
#include "sicsobj.h"
|
|
#include "splitter.h"
|
|
#include "initializer.h"
|
|
#include "commandlog.h"
|
|
#include "hipadaba.h"
|
|
#include "sicshipadaba.h"
|
|
#include "dynstring.h"
|
|
#include "devser.h"
|
|
|
|
#define MAX_HDB_PATH 1024
|
|
|
|
typedef struct ContextItem {
|
|
struct ContextItem *next;
|
|
Hdb *node;
|
|
Hdb *controllerNode;
|
|
} ContextItem;
|
|
|
|
typedef struct ScriptContext {
|
|
ObjectDescriptor *desc;
|
|
ContextItem *nodes;
|
|
ContextItem *trash;
|
|
ContextItem *base;
|
|
} ScriptContext;
|
|
|
|
typedef struct SctController {
|
|
DevSer *devser;
|
|
Hdb *node; /* the controller node */
|
|
SCStore *conn;
|
|
int verbose;
|
|
} SctController;
|
|
|
|
typedef struct SctData {
|
|
int writable;
|
|
char *name;
|
|
SctController *controller;
|
|
SCStore *conCtx;
|
|
int answered;
|
|
Hdb *node; /* back link used by SctMatchWrite/SctMatchPoll */
|
|
} SctData;
|
|
|
|
static ScriptContext *sct = NULL;
|
|
static SCStore *currentCon = NULL;
|
|
|
|
static struct {
|
|
char *name;
|
|
} actionCallback;
|
|
|
|
static char *mainCallback = "main callback";
|
|
|
|
void PushContext(Hdb *node, Hdb *controllerNode) {
|
|
ContextItem *new;
|
|
|
|
if (sct->trash == NULL) {
|
|
new = calloc(1, sizeof(*new));
|
|
} else {
|
|
new = sct->trash;
|
|
sct->trash = sct->trash->next;
|
|
}
|
|
new->next = sct->nodes;
|
|
sct->nodes = new;
|
|
new->node = node;
|
|
new->controllerNode = controllerNode;
|
|
}
|
|
|
|
void PopContext(void) {
|
|
ContextItem *c;
|
|
|
|
c = sct->nodes;
|
|
assert(c);
|
|
sct->nodes = c->next;
|
|
c->next = sct->trash;
|
|
sct->trash = c;
|
|
}
|
|
|
|
void CleanStack(Hdb *node) {
|
|
ContextItem *s;
|
|
|
|
/* clean context from killed nodes */
|
|
for (s = sct->nodes; s != NULL; s = s->next) {
|
|
if (s->node == node) {
|
|
s->node = NULL;
|
|
}
|
|
if (s->controllerNode == node) {
|
|
s->controllerNode = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void SetProp(Hdb *node, Hdb *cNode, char *key, char *value) {
|
|
char *val;
|
|
|
|
if (node == NULL) {
|
|
if (cNode == NULL) return;
|
|
node = cNode;
|
|
} else {
|
|
val = GetHdbProp(node, key);
|
|
if (val == NULL && cNode != NULL) {
|
|
val = GetHdbProp(cNode, key);
|
|
if (val != NULL) {
|
|
node = cNode;
|
|
}
|
|
}
|
|
}
|
|
if (value == NULL) {
|
|
if (GetHdbProperty(node, key, NULL, 0) > 0) {
|
|
SetHdbProperty(node, key, "");
|
|
}
|
|
} else {
|
|
SetHdbProperty(node, key, value);
|
|
}
|
|
}
|
|
|
|
static char *GetProp(Hdb *node, Hdb *cNode, char *key) {
|
|
char *val;
|
|
|
|
if (node != NULL) {
|
|
val = GetHdbProp(node, key);
|
|
if (val != NULL) return val;
|
|
}
|
|
if (cNode != NULL) {
|
|
val = GetHdbProp(node, key);
|
|
}
|
|
return val;
|
|
}
|
|
|
|
int SctCommand(SConnection *con, SicsInterp *sics, void *object,
|
|
int argc, char *argv[]) {
|
|
static char value[1024];
|
|
char *val;
|
|
Hdb *node = sct->nodes->node;
|
|
Hdb *cNode = sct->nodes->controllerNode;
|
|
|
|
assert(sct == object);
|
|
if (node == NULL && cNode == NULL) {
|
|
SCPrintf(con, eError, "ERROR: %s may be called only in proper context",
|
|
argv[0]);
|
|
return 0;
|
|
}
|
|
if (argc <= 1) {
|
|
GetHdbPath(node, value, sizeof value);
|
|
SCWrite(con, value, eValue);
|
|
return 1;
|
|
}
|
|
if (argc == 2) { /* get case */
|
|
val = GetProp(node, cNode, argv[1]);
|
|
if (val == NULL) {
|
|
SCPrintf(con, eError, "ERROR: %s %s not found", argv[0], argv[1]);
|
|
return 0;
|
|
}
|
|
SCWrite(con, val, eValue);
|
|
} else { /* set case */
|
|
val = Arg2Tcl(argc-2, argv+2, value, sizeof value);
|
|
SetProp(node, cNode, argv[1], val);
|
|
if (val != NULL && val != value) free(val);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int SctCallInContext(SConnection *con, char *script, Hdb *node,
|
|
SctController *controller, char **resPtr) {
|
|
Tcl_Interp *pTcl = InterpGetTcl(pServ->pSics);
|
|
int ret, l;
|
|
char *result = NULL;
|
|
int iRet = 1;
|
|
int verbose = controller->verbose;
|
|
|
|
PushContext(node, controller->node);
|
|
if (verbose) {
|
|
SCPrintf(con, eInError, "\nscript: %s\n", script);
|
|
}
|
|
|
|
l = strlen(script);
|
|
ret = Tcl_EvalEx(pTcl, script, l, 0);
|
|
result = (char *)Tcl_GetStringResult(pTcl);
|
|
if (ret != TCL_OK && result[0]!='\0') {
|
|
if (verbose) {
|
|
SCPrintf(con, eInError, "\nerror: %s\n", result);
|
|
}
|
|
iRet = 0;
|
|
}
|
|
*resPtr = result;
|
|
|
|
PopContext();
|
|
PopContext();
|
|
return iRet;
|
|
}
|
|
|
|
static int SctMatch(void *data1, void *data2) {
|
|
SctData *a = data1;
|
|
SctData *b = data2;
|
|
|
|
return a->node == b->node && strcasecmp(a->name, b->name) == 0;
|
|
}
|
|
|
|
static char *SctActionHandler(void *actionData, char *lastReply) {
|
|
SctData *data = actionData;
|
|
Hdb *node = data->node;
|
|
SctController *controller = data->controller;
|
|
char *state;
|
|
char *result;
|
|
char *script;
|
|
char *send = NULL;
|
|
int i;
|
|
SConnection *con;
|
|
|
|
if (currentCon) {
|
|
con = SCStorePush(currentCon);
|
|
} else {
|
|
con = SCStorePush(controller->conn);
|
|
}
|
|
SetProp(node, controller->node, "result", lastReply);
|
|
if (controller->verbose && lastReply != NULL && *lastReply != '\0') {
|
|
SCPrintf(con, eWarning, "reply : %s", lastReply);
|
|
}
|
|
state = GetProp(node, controller->node, "state");
|
|
if (state == NULL || strcasecmp(state, "idle") == 0) {
|
|
state = data->name;
|
|
SetProp(node, controller->node, "state", state);
|
|
}
|
|
for (i = 0; i < 10; i++) {
|
|
SetProp(node, controller->node, "send", NULL);
|
|
script = GetProp(node, controller->node, state);
|
|
if (script == NULL) script = state;
|
|
|
|
if (! SctCallInContext(con, script, node, data->controller, &result)) {
|
|
SCPrintf(con, eError, "ERROR: %s", result);
|
|
goto finish;
|
|
}
|
|
state = result;
|
|
if (strcasecmp(state, "idle") == 0) {
|
|
if (currentCon && ! data->answered) {
|
|
SCWrite(con, "o.k.", eValue);
|
|
}
|
|
if (data->conCtx != NULL) {
|
|
SCStoreFree(data->conCtx);
|
|
data->conCtx = NULL;
|
|
}
|
|
goto finish;
|
|
}
|
|
SetProp(node, controller->node, "state", state);
|
|
send = GetProp(node, controller->node, "send");
|
|
if (send != NULL && send[0] != '\0') {
|
|
if (controller->verbose) {
|
|
SCPrintf(con, eWarning, "send : %s", send);
|
|
}
|
|
goto quit;
|
|
}
|
|
}
|
|
SCPrintf(con, eError, "ERROR: too many quick scripts chained");
|
|
finish:
|
|
SetProp(node, controller->node, "state", "idle");
|
|
quit:
|
|
if (currentCon) {
|
|
SCStorePop(currentCon);
|
|
} else {
|
|
SCStorePop(controller->conn);
|
|
}
|
|
return send;
|
|
}
|
|
|
|
static char *SctWriteHandler(void *actionData, char *lastReply) {
|
|
SctData *data = actionData;
|
|
SCStore *old;
|
|
char *result;
|
|
|
|
old = currentCon;
|
|
currentCon = data->conCtx;
|
|
result = SctActionHandler(data, lastReply);
|
|
currentCon = old;
|
|
return result;
|
|
}
|
|
|
|
static hdbCallbackReturn SctMainCallback(Hdb *node, void *userData,
|
|
hdbMessage *msg) {
|
|
SctController *controller = userData;
|
|
hdbDataSearch *dsm;
|
|
hdbDataMessage *mm;
|
|
hdbPtrMessage *pm;
|
|
hdbMessage *km;
|
|
ContextItem *s;
|
|
SConnection *con;
|
|
char *geterror;
|
|
|
|
pm = GetKillPtrMessage(msg);
|
|
if (pm != NULL) {
|
|
if (controller == pm->pPtr) {
|
|
return hdbKill;
|
|
}
|
|
return hdbContinue;
|
|
}
|
|
dsm = GetHdbDataSearchMessage(msg);
|
|
if (dsm != NULL) {
|
|
if (dsm->testPtr == controller) {
|
|
dsm->result = controller;
|
|
return hdbAbort;
|
|
}
|
|
return hdbContinue;
|
|
}
|
|
km = GetHdbKillNodeMessage(msg);
|
|
if (km != NULL) {
|
|
CleanStack(node);
|
|
return hdbContinue;
|
|
}
|
|
mm = GetHdbGetMessage(msg);
|
|
if (mm != NULL) {
|
|
con = mm->callData;
|
|
geterror = GetHdbProp(node, "geterror");
|
|
if (geterror != NULL) {
|
|
SCPrintf(con, eError, "ERROR: %s", geterror);
|
|
return hdbAbort;
|
|
}
|
|
return hdbContinue;
|
|
}
|
|
|
|
return hdbContinue;
|
|
}
|
|
|
|
static hdbCallbackReturn SctActionCallback(Hdb *node, void *userData,
|
|
hdbMessage *msg) {
|
|
hdbDataSearch *dsm;
|
|
hdbDataMessage *mm;
|
|
hdbPtrMessage *pm;
|
|
SctData *data = userData;
|
|
Hdb *target;
|
|
char *script;
|
|
int l;
|
|
int iRet;
|
|
pDynString text;
|
|
DevPrio prio;
|
|
char *writeprio;
|
|
char *error;
|
|
SConnection *con;
|
|
SConnection *con2;
|
|
char path[MAX_HDB_PATH];
|
|
|
|
pm = GetKillPtrMessage(msg);
|
|
if (pm != NULL) {
|
|
if (data->controller == pm->pPtr) {
|
|
return hdbKill;
|
|
}
|
|
return hdbContinue;
|
|
}
|
|
dsm = GetHdbDataSearchMessage(msg);
|
|
if (dsm != NULL) {
|
|
if (dsm->testPtr == &actionCallback) {
|
|
if (strcasecmp(data->name, actionCallback.name) == 0) {
|
|
dsm->result = data;
|
|
}
|
|
return hdbAbort;
|
|
}
|
|
return hdbContinue;
|
|
}
|
|
|
|
mm = GetHdbSetMessage(msg);
|
|
if (mm != NULL && data->writable) {
|
|
con = mm->callData;
|
|
|
|
/* call check script, if available */
|
|
script = GetProp(node, data->controller->node, "check");
|
|
if (script != NULL) {
|
|
if (SctCallInContext(con, script, node, data->controller, &error) == 0) {
|
|
SCPrintf(con, eError, "ERROR: %s", error);
|
|
return hdbAbort;
|
|
}
|
|
}
|
|
|
|
/* set target value */
|
|
text = formatValue(*(mm->v), node);
|
|
SetHdbProperty(node, "target", GetCharArray(text));
|
|
|
|
/* enqueue write action */
|
|
writeprio = GetProp(node, data->controller->node, "writeprio");
|
|
if (writeprio != NULL) {
|
|
prio = DevText2Prio(writeprio);
|
|
if (prio < 0) prio = WritePRIO;
|
|
} else {
|
|
prio = WritePRIO;
|
|
}
|
|
|
|
if (data->conCtx != NULL) {
|
|
con2 = SCStorePush(data->conCtx);
|
|
GetHdbPath(node, path, sizeof path);
|
|
SCPrintf(con2, eValue, "%s target changed to %s before completion",
|
|
path, GetCharArray(text));
|
|
SCStorePop(data->conCtx);
|
|
}
|
|
DeleteDynString(text);
|
|
data->conCtx = SCSave(con, data->conCtx);
|
|
data->answered = 0;
|
|
DevQueue(data->controller->devser, data, prio,
|
|
SctWriteHandler, SctMatch, NULL);
|
|
return hdbContinue;
|
|
}
|
|
|
|
mm = GetHdbUpdateMessage(msg);
|
|
if (mm != NULL) {
|
|
if (currentCon) { /* update called from a write action */
|
|
data->answered = 1;
|
|
GetHdbPath(node, path, sizeof path);
|
|
con = SCStorePush(currentCon);
|
|
text = formatValue(*(mm->v), node);
|
|
SCPrintf(con, eStatus, "%s = %s", path,
|
|
GetCharArray(text));
|
|
DeleteDynString(text);
|
|
SCStorePop(currentCon);
|
|
}
|
|
return hdbContinue;
|
|
}
|
|
return hdbContinue;
|
|
}
|
|
|
|
static char *ParText(Hdb *cmdNode, char *name) {
|
|
Hdb *par;
|
|
|
|
par = GetHipadabaNode(cmdNode, name);
|
|
if (par && par->value.dataType == HIPTEXT) {
|
|
return par->value.v.text;
|
|
}
|
|
return "<undefined>";
|
|
}
|
|
|
|
static double ParValue(Hdb *cmdNode, char *name) {
|
|
Hdb *par;
|
|
|
|
par = GetHipadabaNode(cmdNode, name);
|
|
if (par) {
|
|
switch (par->value.dataType) {
|
|
case HIPINT: return par->value.v.intValue;
|
|
case HIPFLOAT: return par->value.v.doubleValue;
|
|
}
|
|
}
|
|
return -999;
|
|
}
|
|
|
|
void SctKillData(void *d) {
|
|
SctData *data = d;
|
|
if (data->name) free(data->name);
|
|
if (data->conCtx) SCStoreFree(data->conCtx);
|
|
free(data);
|
|
}
|
|
|
|
void SctAddPollNode(SctController *controller, Hdb *node, double interval,
|
|
DevPrio prio, char *action) {
|
|
SctData *data;
|
|
hdbCallback *cb;
|
|
|
|
if (! FindHdbCallbackData(node, controller)) {
|
|
cb = MakeHipadabaCallback(SctMainCallback, controller, NULL);
|
|
assert(cb);
|
|
AppendHipadabaCallback(node, cb);
|
|
}
|
|
|
|
actionCallback.name = action;
|
|
data = FindHdbCallbackData(node, &actionCallback);
|
|
if (data == NULL) {
|
|
data = calloc(1, sizeof(*data));
|
|
assert(data);
|
|
data->controller = controller;
|
|
data->node = node;
|
|
data->writable = 0;
|
|
data->conCtx = NULL;
|
|
data->name = strdup(action);
|
|
}
|
|
|
|
DevSchedule(controller->devser, data, prio, interval,
|
|
SctActionHandler, SctMatch, NULL);
|
|
|
|
}
|
|
|
|
static int SctPollCmd(pSICSOBJ ccmd, SConnection *con,
|
|
Hdb *cmdNode, Hdb *par[], int nPar) {
|
|
Hdb *node;
|
|
SctController *controller;
|
|
double interval;
|
|
char *path;
|
|
DevPrio prio;
|
|
char *action;
|
|
|
|
if(nPar < 1){
|
|
SCPrintf(con,eError,
|
|
"ERROR: should be: %s poll <node> (<interval> <prio> <action>)",
|
|
ccmd->objectNode->name);
|
|
return 0;
|
|
}
|
|
controller = ccmd->pPrivate;
|
|
path = ParText(cmdNode, "node");
|
|
node = FindHdbNode(NULL, path, con);
|
|
if (node == NULL) {
|
|
SCPrintf(con, eError, "ERROR: %s not found", path);
|
|
return 0;
|
|
}
|
|
interval = ParValue(cmdNode, "interval");
|
|
prio = DevText2Prio(ParText(cmdNode, "prio"));
|
|
action = ParText(cmdNode, "action");
|
|
|
|
SctAddPollNode(controller, node, interval, prio, action);
|
|
|
|
sct->base->node = node;
|
|
|
|
return 1;
|
|
}
|
|
|
|
int SctAddWriteNode(SctController *controller, Hdb *node) {
|
|
hdbCallback *cb;
|
|
SctData *data;
|
|
|
|
if (! FindHdbCallbackData(node, controller)) {
|
|
cb = MakeHipadabaCallback(SctMainCallback, controller, NULL);
|
|
assert(cb);
|
|
AppendHipadabaCallback(node, cb);
|
|
}
|
|
|
|
actionCallback.name = strdup("write");
|
|
data = FindHdbCallbackData(node, &actionCallback);
|
|
if (data != NULL) {
|
|
return 0;
|
|
}
|
|
data = calloc(1, sizeof(*data));
|
|
assert(data);
|
|
data->controller = controller;
|
|
data->node = node;
|
|
data->writable = 1;
|
|
data->conCtx = NULL;
|
|
data->name = strdup("write");
|
|
|
|
cb = MakeHipadabaCallback(SctActionCallback, data, SctKillData);
|
|
assert(cb);
|
|
data->node = node;
|
|
AppendHipadabaCallback(node, cb);
|
|
RemoveSetUpdateCallback(node);
|
|
return 1;
|
|
}
|
|
|
|
static int SctWriteCmd(pSICSOBJ ccmd, SConnection *con,
|
|
Hdb *cmdNode, Hdb *par[], int nPar) {
|
|
Hdb *node;
|
|
SctController *controller;
|
|
double interval;
|
|
char *path;
|
|
|
|
if(nPar < 1){
|
|
SCPrintf(con, eError, "ERROR: should be: %s write <node>",
|
|
ccmd->objectNode->name);
|
|
return 0;
|
|
}
|
|
controller = ccmd->pPrivate;
|
|
path = ParText(cmdNode, "node");
|
|
node = FindHdbNode(NULL, path, con);
|
|
if (node == NULL) {
|
|
SCPrintf(con, eError, "ERROR: %s not found", path);
|
|
return 0;
|
|
}
|
|
if (SctAddWriteNode(controller, node) == 0) {
|
|
SCPrintf(con, eError,
|
|
"ERROR: %s has already a write action", path);
|
|
return 0;
|
|
}
|
|
|
|
sct->base->node = node;
|
|
return 1;
|
|
}
|
|
|
|
SctData *SctQueueNode(SctController *controller, Hdb *node,
|
|
DevPrio prio, char *action) {
|
|
SctData *data;
|
|
hdbCallback *cb;
|
|
|
|
if (! FindHdbCallbackData(node, controller)) {
|
|
cb = MakeHipadabaCallback(SctMainCallback, controller, NULL);
|
|
assert(cb);
|
|
AppendHipadabaCallback(node, cb);
|
|
}
|
|
|
|
data = calloc(1, sizeof(*data));
|
|
assert(data);
|
|
data->controller = controller;
|
|
data->node = node;
|
|
data->writable = 0;
|
|
data->name = strdup(action);
|
|
data->conCtx = NULL;
|
|
|
|
DevQueue(data->controller->devser, data, prio,
|
|
SctWriteHandler, SctMatch, SctKillData);
|
|
return data;
|
|
}
|
|
|
|
static int SctQueueCmd(pSICSOBJ ccmd, SConnection *con,
|
|
Hdb *cmdNode, Hdb *par[], int nPar) {
|
|
Hdb *node;
|
|
SctController *controller;
|
|
double interval;
|
|
char *path;
|
|
char *action;
|
|
DevPrio prio;
|
|
SctData *data;
|
|
|
|
if(nPar < 2){
|
|
SCPrintf(con,eError, "ERROR: should be: %s queue <node> <prio> <action>",
|
|
ccmd->objectNode->name);
|
|
return 0;
|
|
}
|
|
controller = ccmd->pPrivate;
|
|
path = ParText(cmdNode, "node");
|
|
node = FindHdbNode(NULL, path, con);
|
|
if (node == NULL) {
|
|
SCPrintf(con, eError, "ERROR: %s not found", path);
|
|
return 0;
|
|
}
|
|
prio = DevText2Prio(ParText(cmdNode, "prio"));
|
|
action = ParText(cmdNode, "action");
|
|
|
|
data = SctQueueNode(controller, node, prio, action);
|
|
data->conCtx = SCSave(con, NULL);
|
|
return 1;
|
|
}
|
|
|
|
static hdbCallbackReturn SctDebugCallback(Hdb *node, void *userData,
|
|
hdbMessage *msg) {
|
|
hdbDataMessage *mm;
|
|
SctController *controller = userData;
|
|
SConnection *con;
|
|
int i;
|
|
|
|
mm = GetHdbSetMessage(msg);
|
|
if (mm != NULL) {
|
|
i = mm->v->v.intValue;
|
|
if (i < 0) {
|
|
controller->verbose = 0;
|
|
DevDebugMode(controller->devser, -1);
|
|
} else if (i == 0) {
|
|
controller->verbose = 1;
|
|
DevDebugMode(controller->devser, -1);
|
|
} else {
|
|
controller->verbose = 1;
|
|
DevDebugMode(controller->devser, i);
|
|
}
|
|
}
|
|
return hdbContinue;
|
|
}
|
|
|
|
static void SctKillController(void *c) {
|
|
SctController *controller = c;
|
|
|
|
CleanStack(controller->node);
|
|
RemoveSICSInternalCallback(controller);
|
|
DevKill(controller->devser);
|
|
}
|
|
|
|
static int SctMakeController(SConnection *con, SicsInterp *sics,
|
|
void *object, int argc, char *argv[]) {
|
|
SICSOBJ *ccmd;
|
|
Hdb *parent, *par, *cmd;
|
|
char *nodeName;
|
|
hdbCallback *cb;
|
|
SctController *controller;
|
|
|
|
if (argc < 2) {
|
|
SCPrintf(con, eError,
|
|
"ERROR: should be %s <path> <protocol args> ...",
|
|
argv[0]);
|
|
return 0;
|
|
}
|
|
|
|
parent = FindHdbParent(NULL, argv[1], &nodeName, con);
|
|
if (parent == NULL) return 0; /* error message already written */
|
|
|
|
controller = calloc(1, sizeof(*controller));
|
|
assert(controller);
|
|
controller->verbose = 0;
|
|
|
|
ccmd = MakeSICSOBJv(nodeName, "SctController", HIPNONE, usSpy);
|
|
controller->node = ccmd->objectNode;
|
|
controller->conn = SCSave(SCCreateDummyConnection(pServ->pSics), NULL);
|
|
|
|
assert(ccmd);
|
|
assert(controller->node->mama == NULL);
|
|
ccmd->pPrivate = controller;
|
|
ccmd->KillPrivate = SctKillController;
|
|
|
|
AddCommand(pServ->pSics, nodeName, InvokeSICSOBJ, KillSICSOBJ, ccmd);
|
|
SetDescriptorKey(ccmd->pDes, "creationCommand", "0");
|
|
|
|
AddHipadabaChild(parent, controller->node, con);
|
|
|
|
controller->devser = DevMake(con, argc - 2, argv + 2);
|
|
if (!controller->devser) return 0;
|
|
|
|
cmd = AddSICSHdbPar(controller->node,
|
|
"poll", usMugger, MakeSICSFunc(SctPollCmd));
|
|
AddSICSHdbPar(cmd, "node", usMugger, MakeHdbText(""));
|
|
AddSICSHdbPar(cmd, "interval", usMugger, MakeHdbFloat(5.0));
|
|
AddSICSHdbPar(cmd, "prio", usMugger, MakeHdbText("read"));
|
|
AddSICSHdbPar(cmd, "action", usMugger, MakeHdbText("read"));
|
|
|
|
cmd = AddSICSHdbPar(controller->node,
|
|
"write", usMugger, MakeSICSFunc(SctWriteCmd));
|
|
AddSICSHdbPar(cmd, "node", usMugger, MakeHdbText(""));
|
|
|
|
|
|
cmd = AddSICSHdbPar(controller->node,
|
|
"queue", usMugger, MakeSICSFunc(SctQueueCmd));
|
|
AddSICSHdbPar(cmd, "node", usMugger, MakeHdbText(""));
|
|
AddSICSHdbPar(cmd, "prio", usMugger, MakeHdbText("write"));
|
|
AddSICSHdbPar(cmd, "action", usMugger, MakeHdbText("write"));
|
|
|
|
par = AddSICSHdbPar(controller->node, "debug", usUser, MakeHdbInt(0));
|
|
|
|
cb = MakeHipadabaCallback(SctDebugCallback, controller, NULL);
|
|
if (cb) AppendHipadabaCallback(par, cb);
|
|
|
|
sct->base->controllerNode = controller->node;
|
|
sct->base->node = NULL;
|
|
|
|
return 1;
|
|
}
|
|
|
|
void SctKill(void *object) {
|
|
assert(sct == object);
|
|
ContextItem *p, *q;
|
|
|
|
for (p = sct->nodes; p != NULL; p = q) {
|
|
q = p->next;
|
|
free(p);
|
|
}
|
|
for (p = sct->trash; p != NULL; p = q) {
|
|
q = p->next;
|
|
free(p);
|
|
}
|
|
if (sct->desc != NULL) {
|
|
DeleteDescriptor(sct->desc);
|
|
}
|
|
free(sct);
|
|
sct = NULL;
|
|
}
|
|
|
|
void SctInit(void) {
|
|
if (sct) return;
|
|
sct = calloc(1, sizeof(*sct));
|
|
assert(sct);
|
|
sct->desc = CreateDescriptor("ScriptContext");
|
|
PushContext(NULL, NULL);
|
|
sct->base = sct->nodes;
|
|
AddCommand(pServ->pSics, "sct", SctCommand, SctKill, sct);
|
|
AddCmd("makesctcontroller", SctMakeController);
|
|
}
|