Files
sics/countersec.c
2016-02-15 11:38:23 +01:00

775 lines
23 KiB
C

/**
* This is a second generation style counter object. It is supposed to work
* nicely with a scriptcontext to drive the actual hardware. This is supposed
* to interface to single counters and histogram memories. This tries to be
* backwards compatible with the old style counter module; thus some
* fields in the data structure will not be used.
*
* copyright: see file COPYRIGHT
*
* Mark Koennecke, February 2009
*/
#include <math.h>
#include <time.h>
#include <sics.h>
#include <counter.h>
#include "sicshipadaba.h"
/*---------------------------------------------------------------------------
* defines for commmands
* -------------------------------------------------------------------------*/
#define START 1000
#define STOP 1001
#define PAUSE 1002
#define CONT 1003
/*---------------------------------------------------------------------------*/
typedef struct {
float fPreset;
float fCurrent;
char *pName;
} MonEvent, *pMonEvent;
/*-------------------------------------------------------------------------*/
static void SecCounterSetError(pCounter self, char *text)
{
hdbValue v;
pHdb node;
node = GetHipadabaNode(self->pDes->parNode, "error");
if(node != NULL){
v = MakeHdbText(strdup(text));
UpdateHipadabaPar(node,v,NULL);
Log(VERBOSE,"par","%s:error:%s", self->name,text);
ReleaseHdbValue(&v);
}
}
/*---------------------------------------------------------------------------*/
int SecCtrInvokeFunction(pCounter self, SConnection *pCon, int code)
{
pHdb node = NULL, status = NULL;
hdbValue v;
node = GetHipadabaNode(self->pDes->parNode, "control");
status = GetHipadabaNode(self->pDes->parNode, "status");
assert(node != NULL);
assert(status != NULL);
v = MakeHdbFloat(code);
if(code != START && strcmp(status->value.v.text,"starting") == 0){
UpdateHipadabaPar(node,MakeHdbText("run"),NULL);
}
return SetHipadabaPar(node,v,pCon);
}
/*---------------------------------------------------------------------------*/
static int SecCtrHalt(void *pData)
{
pCounter self = (pCounter)pData;
pHdb node = NULL;
assert(self != NULL);
SecCtrInvokeFunction(self,pServ->dummyCon, STOP);
node = GetHipadabaNode(self->pDes->parNode, "status");
assert(node != NULL);
if(strcmp(node->value.v.text,"starting") == 0){
UpdateHipadabaPar(node,MakeHdbText("run"),NULL);
}
ReleaseCountLock(self->pCountInt);
return 1;
}
/*---------------------------------------------------------------------------*/
static int SecStartCount(void *pData, SConnection *pCon)
{
pCounter self = (pCounter)pData;
int status;
pHdb node, statusNode;
assert(self != NULL);
if (!GetCountLock(self->pCountInt, pCon)) {
return 0;
}
statusNode = GetHipadabaNode(self->pDes->parNode, "status");
UpdateHipadabaPar(statusNode,MakeHdbText("starting"), pCon);
status = SecCtrInvokeFunction(self,pCon, START);
self->haltFixFlag = 0;
if(status == 1){
self->isUpToDate = 0;
self->badStatusCount = 0;
self->tStart = time(NULL);
node = GetHipadabaNode(self->pDes->parNode, "control");
UpdateHipadabaPar(node,MakeHdbFloat(.0), pCon);
Log(VERBOSE,"par","%s:control:%s", self->name,"0");
SetHdbProperty(node,"geterror", NULL);
/*
* set time to 0. Otherwise, if there is a delay,
* the check for overrun counters in SecCtrCheckStatus
* may trigger!
*/
node = GetHipadabaNode(self->pDes->parNode, "time");
UpdateHipadabaPar(node,MakeHdbFloat(.0), pCon);
Log(VERBOSE,"par","%s:time:%s", self->name,"0");
InvokeCallBack(self->pCall,COUNTSTART, pCon);
SecCounterSetError(self,"None");
return 1;
} else {
UpdateHipadabaPar(statusNode,MakeHdbText("error"), pCon);
ReleaseCountLock(self->pCountInt);
return HWFault;
}
}
/*---------------------------------------------------------------------------*/
static int SecPause(void *pData, SConnection *pCon)
{
pCounter self = (pCounter)pData;
assert(self != NULL);
return SecCtrInvokeFunction(self,pCon, PAUSE);
}
/*---------------------------------------------------------------------------*/
static int SecContinue(void *pData, SConnection *pCon)
{
pCounter self = (pCounter)pData;
assert(self != NULL);
return SecCtrInvokeFunction(self,pCon, CONT);
}
/*----------------------------------------------------------------------------*/
static int SecCtrCheckStatus(void *pData, SConnection *pCon)
{
pCounter self = (pCounter)pData;
pHdb node = NULL, control = NULL;
hdbValue v;
int status;
MonEvent sMon;
float fControl, fPreset;
char error[132];
assert(self != NULL);
node = GetHipadabaNode(self->pDes->parNode,"status");
assert(node != NULL);
status = GetHipadabaPar(node,&v,pCon);
if(status != 1){
ReleaseCountLock(self->pCountInt);
return HWFault;
}
if(v.v.text == NULL){
return HWBusy;
}
if (strstr(v.v.text, "idle") != NULL) {
InvokeCallBack(self->pCall, COUNTEND, NULL);
ReleaseCountLock(self->pCountInt);
status = HWIdle;
} else if (strstr(v.v.text, "run") != NULL) {
status = HWBusy;
} else if (strstr(v.v.text, "starting") != NULL) {
status = HWBusy;
} else if (strstr(v.v.text, "nobeam") != NULL) {
status = HWNoBeam;
} else if (strstr(v.v.text, "pause") != NULL) {
status = HWPause;
} else if (strstr(v.v.text, "restart") != NULL) {
SecStartCount(self, pCon);
return HWBusy;
} else if (strstr(v.v.text, "error") != NULL) {
InvokeCallBack(self->pCall, COUNTEND, NULL);
ReleaseCountLock(self->pCountInt);
if(GetHdbProperty(node,"geterror",error,sizeof(error)) == 1){
SCPrintf(pCon,eError,"ERROR: %s", error);
SecCounterSetError(self,error);
} else {
SecCounterSetError(self,"Undefined counter error: set status geterror");
SCPrintf(pCon,eError,"ERROR: Unknown counter status error: set status geterror property");
}
status = HWFault;
} else {
SCPrintf(pCon, eError, "ERROR: unknown counter status %s found",
v.v.text);
ReleaseCountLock(self->pCountInt);
status = HWFault;
}
ReleaseHdbValue(&v);
if(self->getMode(self) == eTimer){
node = GetHipadabaNode(self->pDes->parNode,"time");
assert(node != NULL);
GetHipadabaPar(node,&v,pCon);
fControl = v.v.doubleValue;
} else {
node = GetHipadabaNode(self->pDes->parNode,"values");
if(node != NULL) {
/*
This can be NULL if the counter is a HM. The values does not
exist and fControl is useless
The 1 below is only correct for PSI where only the first
monitor can be the control monitor. Elsewhere this must be the
control monitor channel
This may need to change with the second generation DAQ where the
count control channel can be changed.
*/
fControl = v.v.intArray[1];
}
}
node = GetHipadabaNode(self->pDes->parNode,"preset");
assert(node != NULL);
GetHipadabaPar(node,&v,pCon);
fPreset = v.v.doubleValue;
sMon.fCurrent = fControl;
sMon.fPreset = fPreset;
sMon.pName = self->name;
self->badStatusCount = 0;
/*
* check for overrun counter boxes
*/
if(self->getMode(self) == eTimer &&
(sMon.fCurrent > sMon.fPreset +1)
&& self->haltFixFlag == 0){
SecCtrHalt(self);
self->haltFixFlag = 1;
}
/*
* invoke notifiactions, if necessary
*/
if (self->iCallbackCounter > 20) {
InvokeCallBack(self->pCall, MONITOR, &sMon);
self->iCallbackCounter = 0;
} else {
self->iCallbackCounter++;
}
return status;
}
/*---------------------------------------------------------------------------
* Here is an issue: this ought to wait until data has arrived. Callers
* think now that the data is up to date. With scriptcontext this may not be
* the case. The update may come later or even never. Perhaps this needs
* to be emulated:
* - set a property to some value when starting
* - add an update callback which deletes the property when done.
* - Check that property or the geterror property here in a loop
* until done or we timeout.
*
* Nope! Update October 2013:
* How it is normally done is to read the data through scripcontext when
* counting is finished and not to finish with counting until this has
* been done. The code below is only usefule for non scriptcontext
* drivers.
* -----------------------------------------------------------------------*/
static int SecCtrTransferData(void *pData, SConnection *pCon)
{
pCounter self = (pCounter)pData;
assert(self != NULL);
pHdb node = NULL;
hdbValue v;
int status;
node = GetHipadabaNode(self->pDes->parNode,"values");
assert(node != NULL);
self->isUpToDate = 1;
status = GetHipadabaPar(node,&v,pCon);
ReleaseHdbValue(&v);
return status;
}
/*------------------------------------------------------------------------*/
static void *SecCtrCounterGetInterface(void *pData, int iID)
{
pCounter self = NULL;
self = (pCounter) pData;
assert(self);
if (iID == COUNTID) {
return self->pCountInt;
} else if (iID == CALLBACKINTERFACE) {
return self->pCall;
}
return NULL;
}
/*--------------------------------------------------------------------------*/
static int SecCtrSetMode(pCounter self, CounterMode eNew)
{
hdbValue v;
pHdb node = NULL;
node = GetHipadabaNode(self->pDes->parNode,"mode");
assert(node != NULL);
switch(eNew){
case eTimer:
v = MakeHdbText("timer");
break;
case ePreset:
v = MakeHdbText("monitor");
break;
}
Log(VERBOSE,"par","%s:mode:%s", self->name,v.v.text);
return SetHipadabaPar(node,v,NULL);
}
/*---------------------------------------------------------------------------*/
static CounterMode SecCtrGetMode(pCounter self)
{
hdbValue v;
pHdb node = NULL;
CounterMode mode;
node = GetHipadabaNode(self->pDes->parNode,"mode");
assert(node != NULL);
GetHipadabaPar(node,&v,NULL);
assert(v.v.text != NULL);
if(strcmp(v.v.text,"timer") == 0){
mode = eTimer;
} else {
mode = ePreset;
}
ReleaseHdbValue(&v);
return mode;
}
/*--------------------------------------------------------------------------*/
static int SecCtrSetPreset(pCounter self, float val)
{
hdbValue v;
pHdb node = NULL;
node = GetHipadabaNode(self->pDes->parNode,"preset");
assert(node != NULL);
v = MakeHdbFloat(val);
Log(VERBOSE,"par","%s:preset:%f", self->name,v.v.doubleValue);
return SetHipadabaPar(node,v,NULL);
}
/*--------------------------------------------------------------------------*/
static void SecCtrSetCountParameters(void *pData, float fPreset,
CounterMode eMode)
{
pCounter self = NULL;
assert(pData);
self = (pCounter) pData;
SetCounterPreset(self, fPreset);
SetCounterMode(self, eMode);
}
/*---------------------------------------------------------------------------*/
static float SecCtrGetPreset(pCounter self)
{
hdbValue v;
pHdb node = NULL;
node = GetHipadabaNode(self->pDes->parNode,"preset");
assert(node != NULL);
GetHipadabaPar(node,&v,NULL);
return (float)v.v.doubleValue;
}
/*---------------------------------------------------------------------------*/
static float SecCtrGetControlValue(pCounter self)
{
hdbValue v;
pHdb node = NULL;
node = GetHipadabaNode(self->pDes->parNode,"control");
assert(node != NULL);
GetHipadabaPar(node,&v,NULL);
return (float)v.v.doubleValue;
}
/*--------------------------------------------------------------------------*/
static int SecCtrGetNMonitor(pCounter self)
{
hdbValue v;
pHdb node = NULL;
node = GetHipadabaNode(self->pDes->parNode,"values");
assert(node != NULL);
GetHipadabaPar(node,&v,NULL);
return v.arrayLength;
}
/*--------------------------------------------------------------------------*/
static long SecCtrGetMonitor(pCounter self, int iNum, SConnection *pCon)
{
hdbValue v;
pHdb node = NULL;
long val;
if (!self->isUpToDate) {
self->pCountInt->TransferData(self, pCon);
}
node = GetHipadabaNode(self->pDes->parNode,"values");
assert(node != NULL);
GetHipadabaPar(node,&v,pCon);
if(iNum >= 0 && iNum < v.arrayLength){
val = (long)v.v.intArray[iNum];
} else {
val = -1L;
}
ReleaseHdbValue(&v);
return val;
}
/*--------------------------------------------------------------------------*/
static long SecCtrGetCounts(pCounter self, SConnection *pCon)
{
return SecCtrGetMonitor(self,0,pCon);
}
/*--------------------------------------------------------------------------*/
static void SecCtrSetMonitor(pCounter self, int iNum, long val)
{
hdbValue v;
pHdb node = NULL;
node = GetHipadabaNode(self->pDes->parNode,"values");
assert(node != NULL);
GetHipadabaPar(node,&v,NULL);
if(iNum >= 0 && iNum < v.arrayLength){
v.v.intArray[iNum] = val;
UpdateHipadabaPar(node,v,NULL);
}
}
/*---------------------------------------------------------------------------*/
static float SecCtrGetTime(pCounter self, SConnection *pCon)
{
hdbValue v;
pHdb node = NULL;
node = GetHipadabaNode(self->pDes->parNode,"time");
assert(node != NULL);
GetHipadabaPar(node,&v,pCon);
return (float)v.v.doubleValue;
}
/*--------------------------------------------------------------------------*/
static int CountCmd(pSICSOBJ ccmd, SConnection * con,
Hdb * cmdNode, Hdb * par[], int nPar)
{
float preset;
pHdb presetNode = NULL;
if(nPar < 1){
presetNode = GetHipadabaNode(ccmd->objectNode,"preset");
if(presetNode != NULL){
preset = presetNode->value.v.doubleValue;
} else {
/*
This can really only happen when the counter is corrupt
*/
assert(0);
}
} else {
preset = par[0]->value.v.doubleValue;
}
return DoCount((pCounter)ccmd, preset, con, 1);
}
/*--------------------------------------------------------------------------*/
static int GetMonitorCmd(pSICSOBJ ccmd, SConnection * con,
Hdb * cmdNode, Hdb * par[], int nPar)
{
long counts;
pCounter self = (pCounter)ccmd;
if(nPar < 1) {
SCWrite(con,"ERROR: missing monitor no in getmonitor",eError);
return 0;
}
counts = self->getMonitor(self,par[0]->value.v.intValue,con);
SCPrintf(con,eValue,"%s.monitor.%d = %ld", self->name,
par[0]->value.v.intValue,counts);
return 1;
}
/*--------------------------------------------------------------------------*/
static int GetCountsCmd(pSICSOBJ ccmd, SConnection * con,
Hdb * cmdNode, Hdb * par[], int nPar)
{
long counts;
pCounter self = (pCounter)ccmd;
counts = self->getCounts(self,con);
SCPrintf(con,eValue,"%s.counts = %ld", self->name,counts);
return 1;
}
/*--------------------------------------------------------------------------*/
static int CountNBCmd(pSICSOBJ ccmd, SConnection * con,
Hdb * cmdNode, Hdb * par[], int nPar)
{
float preset;
pHdb presetNode = NULL;
if(nPar < 1){
presetNode = GetHipadabaNode(ccmd->objectNode,"preset");
if(presetNode != NULL){
preset = presetNode->value.v.doubleValue;
} else {
/*
This can really only happen when the counter is corrupt
*/
assert(0);
}
} else {
preset = par[0]->value.v.doubleValue;
}
return DoCount((pCounter)ccmd, preset, con, 0);
}
/*--------------------------------------------------------------------------*/
static int StopCmd(pSICSOBJ ccmd, SConnection * con,
Hdb * cmdNode, Hdb * par[], int nPar)
{
pCounter self = (pCounter)ccmd;
return self->pCountInt->Halt(self);
}
/*--------------------------------------------------------------------------*/
static int PauseCmd(pSICSOBJ ccmd, SConnection * con,
Hdb * cmdNode, Hdb * par[], int nPar)
{
pCounter self = (pCounter)ccmd;
return self->pCountInt->Pause(self,con);
}
/*--------------------------------------------------------------------------*/
static int ContinueCmd(pSICSOBJ ccmd, SConnection * con,
Hdb * cmdNode, Hdb * par[], int nPar)
{
pCounter self = (pCounter)ccmd;
return self->pCountInt->Continue(self,con);
}
/*-------------------------------------------------------------------------*/
extern int CounterInterest(int iEvent, void *pEvent, void *pUser);
/*--------------------------------------------------------------------------*/
static int InterestCmd(pSICSOBJ ccmd, SConnection * con,
Hdb * cmdNode, Hdb * par[], int nPar)
{
long lID;
pCounter self = (pCounter)ccmd;
lID = RegisterCallback(self->pCall, MONITOR, CounterInterest,
SCCopyConnection(con), SCDeleteConnection);
SCSendOK(con);
return 1;
}
/*--------------------------------------------------------------------------*/
static int CountStatusCmd(pSICSOBJ ccmd, SConnection * con,
Hdb * cmdNode, Hdb * par[], int nPar)
{
float preset, done;
int exponent;
pHdb node, data;
node = GetHipadabaNode(ccmd->objectNode,"preset");
assert(node != NULL);
preset = node->value.v.doubleValue;
node = GetHipadabaNode(ccmd->objectNode,"mode");
assert(node != NULL);
strtolower(node->value.v.text);
if(strcmp(node->value.v.text,"timer") == 0) {
data = GetHipadabaNode(ccmd->objectNode,"time");
assert(data != NULL);
done = data->value.v.doubleValue;
} else {
data = GetHipadabaNode(ccmd->objectNode,"values");
assert(data != NULL);
done = data->value.v.intArray[0];
data = GetHipadabaNode(ccmd->objectNode,"exponent");
assert(data != NULL);
exponent = data->value.v.intValue;
if(exponent != 0){
done /= pow(10,exponent);
}
}
SCPrintf(con,eValue,"%s.CountStatus = %f %f",
ccmd->objectNode->name, preset, done);
return 1;
}
/*--------------------------------------------------------------------------
Disallows status changes from starting to anything else but run or
error
----------------------------------------------------------------------------*/
static hdbCallbackReturn SecStatusCallback(pHdb node, void *userData,
pHdbMessage message)
{
pHdbDataMessage mm = NULL;
hdbValue v;
pCounter self = (pCounter)userData;
mm = GetHdbUpdateMessage(message);
if (mm != NULL) {
v = *mm->v;
if(strcmp(node->value.v.text,"starting") == 0) {
if(strstr(v.v.text,"run") == 0 && strstr(v.v.text,"error") == 0) {
return hdbAbort;
}
}
if(strcmp(v.v.text,node->value.v.text) != 0){
Log(VERBOSE,"par","%s:status:%s", self->name,v.v.text);
}
}
return hdbContinue;
}
/*--------------------------------------------------------------------------*/
pCounter CreateSecCounter(SConnection *pCon, char *type, char *name, int length)
{
pCounter pRes = NULL;
pHdb node = NULL, child = NULL;
pRes = (pCounter) malloc(sizeof(Counter));
if (!pRes) {
SCWrite(pCon,"ERROR: out of memory in MakeSecCter", eError);
return NULL;
}
memset(pRes,0,sizeof(Counter));
pRes->pDes = CreateDescriptor(type);
if (!pRes->pDes) {
SCWrite(pCon,"ERROR: out of memory in MakeSecCter", eError);
return 0;
}
/* initialize Descriptor functions */
pRes->pDes->GetInterface = SecCtrCounterGetInterface;
pRes->pDes->SaveStatus = SaveSICSOBJ;
/* initialise countable interface */
pRes->pCountInt = CreateCountableInterface();
if (!pRes->pCountInt) {
DeleteDescriptor(pRes->pDes);
SCWrite(pCon,"ERROR: out of memory in MakeSecCter", eError);
return 0;
}
pRes->pCountInt->SetCountParameters = SecCtrSetCountParameters;
pRes->pCountInt->StartCount = SecStartCount;
pRes->pCountInt->CheckCountStatus = SecCtrCheckStatus;
pRes->pCountInt->TransferData = SecCtrTransferData;
pRes->pCountInt->Halt = SecCtrHalt;
pRes->pCountInt->Pause = SecPause;
pRes->pCountInt->Continue = SecContinue;
pRes->iCallbackCounter = 20;
pRes->setMode = SecCtrSetMode;
pRes->getMode = SecCtrGetMode;
pRes->getNMonitor = SecCtrGetNMonitor;
pRes->setPreset = SecCtrSetPreset;
pRes->getPreset = SecCtrGetPreset;
pRes->getControlValue = SecCtrGetControlValue;
pRes->getCounts = SecCtrGetCounts;
pRes->getMonitor = SecCtrGetMonitor;
pRes->setMonitor = SecCtrSetMonitor;
pRes->getTime = SecCtrGetTime;
pRes->pCall = CreateCallBackInterface();
pRes->isUpToDate = 1;
pRes->iExponent = 0;
pRes->name = strdup(name);
node = MakeHipadabaNode(name,HIPNONE, 0);
pRes->pDes->parNode = node;
pRes->objectNode = node;
child = MakeSICSHdbPar("time", usInternal, MakeHdbFloat(.0));
if (child == NULL) {
return NULL;
}
AddHipadabaChild(node, child, NULL);
child = MakeSICSHdbPar("preset", usUser, MakeHdbFloat(.0));
if (child == NULL) {
return NULL;
}
SetHdbProperty(child, "__save", "true");
AddHipadabaChild(node, child, NULL);
child = MakeSICSHdbPar("mode", usUser, MakeHdbText("monitor"));
if (child == NULL) {
return NULL;
}
SetHdbProperty(child, "__save", "true");
SetHdbProperty(child, "values", "timer,monitor");
PrependHipadabaCallback(child,MakeHipadabaCallback(SICSValueCheckCallback,
NULL,NULL));
AddHipadabaChild(node, child, NULL);
child = MakeSICSHdbPar("status", usInternal, MakeHdbText("idle"));
if (child == NULL) {
return NULL;
}
AppendHipadabaCallback(child,
MakeHipadabaCallback(SecStatusCallback, pRes,
NULL));
AddHipadabaChild(node, child, NULL);
child = MakeSICSHdbPar("error", usInternal, MakeHdbText("None"));
if (child == NULL) {
return NULL;
}
AddHipadabaChild(node, child, NULL);
child = MakeSICSHdbPar("control", usUser, MakeHdbFloat(.0));
if (child == NULL) {
return NULL;
}
AddHipadabaChild(node, child, NULL);
child = MakeSICSHdbPar("values", usInternal,
makeHdbValue(HIPINTAR, length));
if (child == NULL) {
return NULL;
}
AddHipadabaChild(node, child, NULL);
child = MakeSICSHdbPar("exponent", usUser,
MakeHdbInt(0));
if (child == NULL) {
return NULL;
}
SetHdbProperty(child, "__save", "true");
AddHipadabaChild(node, child, NULL);
child = AddSICSHdbPar(node,"count", usUser, MakeSICSFunc(CountCmd));
AddSICSHdbPar(child, "preset", usUser, MakeHdbFloat(2));
child = AddSICSHdbPar(node,"countnb", usUser, MakeSICSFunc(CountNBCmd));
AddSICSHdbPar(child, "preset", usUser, MakeHdbFloat(2));
child = AddSICSHdbPar(node,"getmonitor", usSpy, MakeSICSFunc(GetMonitorCmd));
AddSICSHdbPar(child, "no", usSpy, MakeHdbInt(1));
child = AddSICSHdbPar(node,"getcounts", usUser, MakeSICSFunc(GetCountsCmd));
child = AddSICSHdbPar(node,"stop", usUser, MakeSICSFunc(StopCmd));
child = AddSICSHdbPar(node,"pause", usUser, MakeSICSFunc(PauseCmd));
child = AddSICSHdbPar(node,"continue", usUser, MakeSICSFunc(ContinueCmd));
child = AddSICSHdbPar(node,"interest", usUser, MakeSICSFunc(InterestCmd));
child = AddSICSHdbPar(node,"countstatus", usUser, MakeSICSFunc(CountStatusCmd));
return pRes;
}
/*--------------------------------------------------------------------------*/
int MakeSecCter(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
pCounter pRes = NULL;
int status, length;
pHdb node, child;
if(argc < 3) {
SCWrite(pCon,"ERROR: need at least a name and length to create a counter",
eError);
return 0;
}
length = atoi(argv[2]);
pRes = CreateSecCounter(pCon,"SingleCounter", argv[1], length);
if(pRes == NULL){
return 0;
}
status =
AddCommand(pSics, argv[1], InterInvokeSICSOBJ, DeleteCounter,
(void *) pRes);
if (status != 1) {
SCPrintf(pCon,eError, "ERROR: duplicate command %s not created", argv[1]);
return 0;
}
return 1;
}