318 lines
8.3 KiB
C
318 lines
8.3 KiB
C
/*-----------------------------------------------------------------------------
|
|
R \"U N S T A C K
|
|
|
|
See header file for the rationale of this.
|
|
|
|
Copyright:
|
|
|
|
Labor fuer Neutronenstreuung
|
|
Paul Scherrer Institut
|
|
CH-5423 Villigen-PSI
|
|
|
|
|
|
The authors hereby grant permission to use, copy, modify, distribute,
|
|
and license this software and its documentation for any purpose, provided
|
|
that existing copyright notices are retained in all copies and that this
|
|
notice is included verbatim in any distributions. No written agreement,
|
|
license, or royalty fee is required for any of the authorized uses.
|
|
Modifications to this software may be copyrighted by their authors
|
|
and need not follow the licensing terms described here, provided that
|
|
the new terms are clearly indicated on the first page of each file where
|
|
they apply.
|
|
|
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
|
POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
|
|
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
|
|
NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
|
|
MODIFICATIONS.
|
|
----------------------------------------------------------------------------*/
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <tcl.h>
|
|
#include "fortify.h"
|
|
#include "lld.h"
|
|
#include "lld_blob.h"
|
|
#include "lld_str.h"
|
|
#include "conman.h"
|
|
#include "obdes.h"
|
|
#include "buffer.h"
|
|
#include "fupa.h"
|
|
#include "splitter.h"
|
|
#include "ruli.h"
|
|
#include "nserver.h"
|
|
/*--------------------------------------------------------------------------*/
|
|
pRuenStack CreateRuenStack(void)
|
|
{
|
|
pRuenStack pNew = NULL;
|
|
|
|
pNew = (pRuenStack) malloc(sizeof(RuenStack));
|
|
if (!pNew) {
|
|
return NULL;
|
|
}
|
|
pNew->pDes = CreateDescriptor("SicsRuenStack");
|
|
if (!pNew->pDes) {
|
|
free(pNew);
|
|
return NULL;
|
|
}
|
|
|
|
pNew->iList = LLDcreate(sizeof(pRuenBuffer));
|
|
if (pNew->iList == -1) {
|
|
DeleteDescriptor(pNew->pDes);
|
|
free(pNew);
|
|
return NULL;
|
|
}
|
|
return pNew;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
void DeleteRuenStack(void *self)
|
|
{
|
|
pRuenStack pOld = (pRuenStack) self;
|
|
|
|
assert(pOld);
|
|
|
|
if (pOld->pDes) {
|
|
DeleteDescriptor(pOld->pDes);
|
|
}
|
|
LLDdelete(pOld->iList);
|
|
free(pOld);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
int RuenStackAdd(pRuenStack self, pRuenBuffer pVictim)
|
|
{
|
|
assert(self);
|
|
|
|
return LLDnodePrepend(self->iList, &pVictim);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
int RuenStackUnlink(pRuenStack self, int i)
|
|
{
|
|
int iNum;
|
|
int iRet;
|
|
|
|
assert(self);
|
|
|
|
iRet = LLDnodePtr2First(self->iList);
|
|
iNum = 0;
|
|
while (iRet != 0) {
|
|
if (iNum == i) {
|
|
LLDnodeDelete(self->iList);
|
|
return 1;
|
|
}
|
|
iNum++;
|
|
iRet = LLDnodePtr2Next(self->iList);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
int RuenStackInsert(pRuenStack self, int i, pRuenBuffer pVictim)
|
|
{
|
|
int iNum;
|
|
int iRet;
|
|
|
|
assert(self);
|
|
|
|
iRet = LLDnodePtr2First(self->iList);
|
|
iNum = 0;
|
|
while (iRet != 0) {
|
|
if (iNum == i) {
|
|
LLDnodeInsert(self->iList, &pVictim);
|
|
return 1;
|
|
}
|
|
iNum++;
|
|
iRet = LLDnodePtr2Next(self->iList);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
int RuenStackList(pRuenStack self, SConnection * pCon)
|
|
{
|
|
int iRet;
|
|
void *pPtr = NULL;
|
|
char pBueffel[512];
|
|
int iCount = 1;
|
|
pRuenBuffer pBuf = NULL;
|
|
|
|
assert(self);
|
|
|
|
iRet = LLDnodePtr2First(self->iList);
|
|
SCWrite(pCon, "Listing the RunStack", eValue);
|
|
while (iRet != 0) {
|
|
LLDnodeDataTo(self->iList, &pPtr);
|
|
pBuf = (pRuenBuffer) pPtr;
|
|
sprintf(pBueffel, "[%d] %s", iCount, pBuf->name);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
iRet = LLDnodePtr2Next(self->iList);
|
|
iCount++;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
int RuenStackRun(pRuenStack self, SConnection * pCon, SicsInterp * pSics)
|
|
{
|
|
int iRet;
|
|
pRuenBuffer pBuf = NULL;
|
|
pRuenBuffer pTest = NULL;
|
|
|
|
|
|
assert(self);
|
|
assert(pCon);
|
|
assert(pSics);
|
|
|
|
/* while stack not empty */
|
|
iRet = LLDnodePtr2Last(self->iList);
|
|
while (iRet != 0) {
|
|
pBuf = (pRuenBuffer) LLDnodePtr(self->iList);
|
|
/* verify RuenBuffer */
|
|
pTest = NULL;
|
|
pTest = FindRuenBuffer(pSics, pBuf->name);
|
|
if (!pTest) { /* buffer no longer alive */
|
|
/* skip */
|
|
} else {
|
|
BufferRun(pBuf, pCon, pSics);
|
|
}
|
|
/* delete the last one from stack, set to last one again */
|
|
LLDnodeDelete(self->iList);
|
|
iRet = LLDnodePtr2Last(self->iList);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
int RuenStackBatch(pRuenStack self, SConnection * pCon, SicsInterp * pSics)
|
|
{
|
|
int iRet, iWait;
|
|
pRuenBuffer pBuf = NULL;
|
|
pRuenBuffer pTest = NULL;
|
|
|
|
assert(self);
|
|
assert(pCon);
|
|
assert(pSics);
|
|
|
|
for (;;) {
|
|
iRet = LLDnodePtr2Last(self->iList);
|
|
if (iRet) {
|
|
pBuf = (pRuenBuffer) LLDnodePtr(self->iList);
|
|
/* verify RuenBuffer */
|
|
pTest = NULL;
|
|
pTest = FindRuenBuffer(pSics, pBuf->name);
|
|
if (!pTest) { /* buffer no longer alive */
|
|
/* skip */
|
|
LLDnodeDelete(self->iList);
|
|
} else {
|
|
BufferRun(pBuf, pCon, pSics);
|
|
LLDnodeDelete(self->iList);
|
|
}
|
|
} else {
|
|
/* wait and look again */
|
|
iWait = SicsWait(10);
|
|
if (!iWait) {
|
|
return iWait;
|
|
}
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
int RuenStackAction(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
int iRet, iRet2;
|
|
char pBueffel[512];
|
|
char **argx;
|
|
FuPaResult PaRes;
|
|
pRuenStack pStack = NULL;
|
|
pRuenBuffer pBuf = NULL;
|
|
FuncTemplate BufferTemplate[] = {
|
|
{"add", 1, {FUPATEXT}},
|
|
{"del", 1, {FUPAINT}},
|
|
{"ins", 2, {FUPAINT, FUPATEXT}},
|
|
{"list", 0, {0, 0}},
|
|
{"run", 0, {0, 0}},
|
|
{"batch", 0, {0, 0}},
|
|
};
|
|
|
|
assert(pCon);
|
|
assert(pSics);
|
|
pStack = (pRuenStack) pData;
|
|
assert(pStack);
|
|
|
|
|
|
/* you need to be user to use this facility */
|
|
if (!SCMatchRights(pCon, usUser)) {
|
|
return 0;
|
|
}
|
|
/* parse function args */
|
|
argtolower(argc, argv);
|
|
argx = &argv[1];
|
|
iRet =
|
|
EvaluateFuPa((pFuncTemplate) & BufferTemplate, 6, argc - 1, argx,
|
|
&PaRes);
|
|
if (iRet < 0) {
|
|
sprintf(pBueffel, "%s", PaRes.pError);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
|
|
switch (iRet) {
|
|
case 0: /* add */
|
|
pBuf = FindRuenBuffer(pSics, PaRes.Arg[0].text);
|
|
if (!pBuf) {
|
|
sprintf(pBueffel, "ERROR: cannot find RuenBuffer %s",
|
|
PaRes.Arg[0].text);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
iRet2 = RuenStackAdd(pStack, pBuf);
|
|
if (iRet2)
|
|
SCSendOK(pCon);
|
|
return iRet2;
|
|
break;
|
|
case 1: /* del */
|
|
iRet2 = RuenStackUnlink(pStack, PaRes.Arg[0].iVal);
|
|
if (iRet2)
|
|
SCSendOK(pCon);
|
|
return iRet2;
|
|
break;
|
|
case 2: /* ins */
|
|
pBuf = FindRuenBuffer(pSics, PaRes.Arg[1].text);
|
|
if (!pBuf) {
|
|
sprintf(pBueffel, "ERROR: cannot find RuenBuffer %s",
|
|
PaRes.Arg[1].text);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
iRet2 = RuenStackInsert(pStack, PaRes.Arg[0].iVal, pBuf);
|
|
if (iRet2)
|
|
SCSendOK(pCon);
|
|
return iRet2;
|
|
break;
|
|
case 3: /* list */
|
|
return RuenStackList(pStack, pCon);
|
|
break;
|
|
case 4: /* run */
|
|
return RuenStackRun(pStack, pCon, pSics);
|
|
break;
|
|
case 5: /* batch */
|
|
return RuenStackBatch(pStack, pCon, pSics);
|
|
break;
|
|
default:
|
|
assert(0);
|
|
}
|
|
return 1;
|
|
}
|