556 lines
14 KiB
C
556 lines
14 KiB
C
/*--------------------------------------------------------------------------
|
|
L N S R \"U N B U F F E R
|
|
|
|
|
|
Mark Koennecke, January 1997
|
|
|
|
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"
|
|
/*-------------------------------------------------------------------------*/
|
|
static int SaveBuffer(void *pData, char *name, FILE * fd)
|
|
{
|
|
pRuenBuffer self = NULL;
|
|
int iRet;
|
|
char *pPtr = NULL;
|
|
|
|
assert(fd);
|
|
assert(pData);
|
|
|
|
self = (pRuenBuffer) pData;
|
|
fprintf(fd, "# RuenBuffer %s\n", name);
|
|
fprintf(fd, "Buf new %s\n", name);
|
|
iRet = LLDnodePtr2First(self->iLineList);
|
|
while (iRet != 0) {
|
|
pPtr = (char *) LLDnodePtr(self->iLineList);
|
|
fprintf(fd, "%s append %s\n", name, pPtr);
|
|
iRet = LLDnodePtr2Next(self->iLineList);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
pRuenBuffer CreateRuenBuffer(char *name)
|
|
{
|
|
pRuenBuffer pNew = NULL;
|
|
|
|
pNew = (pRuenBuffer) malloc(sizeof(RuenBuffer));
|
|
if (!pNew) {
|
|
return NULL;
|
|
}
|
|
pNew->pDes = CreateDescriptor("SicsRuenBuffer");
|
|
if (!pNew->pDes) {
|
|
free(pNew);
|
|
return NULL;
|
|
}
|
|
|
|
pNew->name = strdup(name);
|
|
(void)Fortify_CheckAllMemory();
|
|
pNew->iLineList = LLDblobCreate();
|
|
if (pNew->iLineList == -1) {
|
|
DeleteDescriptor(pNew->pDes);
|
|
free(pNew->name);
|
|
free(pNew);
|
|
return NULL;
|
|
}
|
|
pNew->pDes->SaveStatus = SaveBuffer;
|
|
return pNew;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
static void DeleteLineBuffer(int iList)
|
|
{
|
|
int iRet;
|
|
char *pPtr;
|
|
|
|
iRet = LLDnodePtr2First(iList);
|
|
while (iRet != 0) {
|
|
pPtr = (char *) LLDnodePtr(iList);
|
|
free(pPtr);
|
|
iRet = LLDnodePtr2Next(iList);
|
|
}
|
|
LLDdelete(iList);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
void DeleteRuenBuffer(void *self)
|
|
{
|
|
int iRet;
|
|
pRuenBuffer pOld = (pRuenBuffer) self;
|
|
|
|
assert(pOld);
|
|
/* delete line buffer */
|
|
DeleteLineBuffer(pOld->iLineList);
|
|
if (pOld->name) {
|
|
free(pOld->name);
|
|
}
|
|
if (pOld->pDes) {
|
|
DeleteDescriptor(pOld->pDes);
|
|
}
|
|
free(pOld);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
pRuenBuffer CopyRuenBuffer(pRuenBuffer pOld, char *name)
|
|
{
|
|
pRuenBuffer pNew = NULL;
|
|
int iRet;
|
|
char *pPtr;
|
|
|
|
pNew = CreateRuenBuffer(name);
|
|
if (!pNew) {
|
|
return NULL;
|
|
}
|
|
|
|
/* copy list */
|
|
iRet = LLDnodePtr2First(pOld->iLineList);
|
|
while (iRet != 0) {
|
|
pPtr = (char *) LLDnodePtr(pOld->iLineList);
|
|
LLDstringAdd(pNew->iLineList, pPtr);
|
|
iRet = LLDnodePtr2Next(pOld->iLineList);
|
|
}
|
|
return pNew;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
int BufferAppendLine(pRuenBuffer self, char *line)
|
|
{
|
|
assert(self);
|
|
|
|
return LLDstringAppend(self->iLineList, line);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
int BufferDel(pRuenBuffer self, int i)
|
|
{
|
|
int iNum;
|
|
int iRet;
|
|
|
|
assert(self);
|
|
|
|
iRet = LLDnodePtr2First(self->iLineList);
|
|
iNum = 0;
|
|
while (iRet != 0) {
|
|
if (iNum == i) {
|
|
LLDstringDelete(self->iLineList);
|
|
return 1;
|
|
}
|
|
iNum++;
|
|
iRet = LLDnodePtr2Next(self->iLineList);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
int BufferInsertAfter(pRuenBuffer self, int i, char *line)
|
|
{
|
|
int iNum;
|
|
int iRet;
|
|
|
|
assert(self);
|
|
|
|
iRet = LLDnodePtr2First(self->iLineList);
|
|
iNum = 0;
|
|
while (iRet != 0) {
|
|
if (iNum == i) {
|
|
LLDstringInsert(self->iLineList, line);
|
|
return 1;
|
|
}
|
|
iNum++;
|
|
iRet = LLDnodePtr2Next(self->iLineList);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
int BufferPrint(pRuenBuffer self, SConnection * pCon)
|
|
{
|
|
int iRet;
|
|
char *pPtr = NULL;
|
|
char pBueffel[512];
|
|
int iCount = 1;
|
|
|
|
iRet = LLDnodePtr2First(self->iLineList);
|
|
sprintf(pBueffel, "Listing for Bueffer %s", self->name);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
while (iRet != 0) {
|
|
pPtr = (char *) LLDnodePtr(self->iLineList);
|
|
sprintf(pBueffel, "[%d] %s", iCount, pPtr);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
iRet = LLDnodePtr2Next(self->iLineList);
|
|
iCount++;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
extern char *StrReplace(char *str, char *old, char *pNew);
|
|
/* realised in Strrepl.c
|
|
*/
|
|
|
|
int BufferReplace(pRuenBuffer self, char *pattern, char *pReplace)
|
|
{
|
|
int iRet;
|
|
char *pPtr = NULL;
|
|
char pBueffel[1024];
|
|
char *pRet;
|
|
|
|
iRet = LLDnodePtr2First(self->iLineList);
|
|
while (iRet != 0) {
|
|
pPtr = (char *) LLDnodePtr(self->iLineList);
|
|
strcpy(pBueffel, pPtr);
|
|
pRet = NULL;
|
|
pRet = StrReplace(pBueffel, pattern, pReplace);
|
|
if (pRet) {
|
|
LLDstringDelete(self->iLineList);
|
|
iRet = LLDnodePtr2Next(self->iLineList);
|
|
LLDnodePtr2Prev(self->iLineList);
|
|
if (iRet) {
|
|
LLDstringInsert(self->iLineList, pBueffel);
|
|
} else {
|
|
LLDstringAppend(self->iLineList, pBueffel);
|
|
}
|
|
}
|
|
iRet = LLDnodePtr2Next(self->iLineList);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
int BufferRun(pRuenBuffer self, SConnection * pCon, SicsInterp * pSics)
|
|
{
|
|
int iRet;
|
|
char *pPtr = NULL;
|
|
int iInt, iRes;
|
|
|
|
iRes = 1;
|
|
iRet = LLDnodePtr2First(self->iLineList);
|
|
while (iRet != 0) {
|
|
pPtr = (char *) LLDnodePtr(self->iLineList);
|
|
iInt = InterpExecute(pSics, pCon, pPtr);
|
|
if (!iInt) {
|
|
if (SCGetInterrupt(pCon) > eAbortBatch) {
|
|
iRes = 0;
|
|
break;
|
|
}
|
|
}
|
|
iRet = LLDnodePtr2Next(self->iLineList);
|
|
}
|
|
return iRes;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
int BufferSave(pRuenBuffer self, char *file)
|
|
{
|
|
int iRet;
|
|
char *pPtr = NULL;
|
|
FILE *fd = NULL;
|
|
|
|
fd = fopen(file, "w");
|
|
if (fd == NULL) {
|
|
return 0;
|
|
}
|
|
iRet = LLDnodePtr2First(self->iLineList);
|
|
while (iRet != 0) {
|
|
pPtr = (char *) LLDnodePtr(self->iLineList);
|
|
fprintf(fd, "%s\n", pPtr);
|
|
iRet = LLDnodePtr2Next(self->iLineList);
|
|
}
|
|
fclose(fd);
|
|
return 1;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
int BufferLoad(pRuenBuffer self, char *file)
|
|
{
|
|
int iRet;
|
|
char *pPtr = NULL;
|
|
FILE *fd = NULL;
|
|
char pBueffel[256];
|
|
|
|
fd = fopen(file, "r");
|
|
if (fd == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
pPtr = fgets(pBueffel, 255, fd);
|
|
while (pPtr != NULL) {
|
|
LLDstringAppend(self->iLineList, pBueffel);
|
|
pPtr = fgets(pBueffel, 255, fd);
|
|
}
|
|
|
|
fclose(fd);
|
|
return 1;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
pRuenBuffer FindRuenBuffer(SicsInterp * pSics, char *name)
|
|
{
|
|
pRuenBuffer pBuf = NULL;
|
|
CommandList *pCom = NULL;
|
|
|
|
pCom = FindCommand(pSics, name);
|
|
if (!pCom) {
|
|
return NULL;
|
|
}
|
|
pBuf = (pRuenBuffer) pCom->pData;
|
|
if (!pBuf) {
|
|
return NULL;
|
|
}
|
|
if (!pBuf->pDes) {
|
|
return NULL;
|
|
}
|
|
if (strcmp(pBuf->pDes->name, "SicsRuenBuffer") != 0) {
|
|
return NULL;
|
|
}
|
|
return pBuf;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
int InitBufferSys(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
pRuenStack pStack = NULL;
|
|
|
|
pStack = CreateRuenStack();
|
|
if (!pStack) {
|
|
SCWrite(pCon, "ERROR: No memory to create Ruen-Stack", eError);
|
|
return 0;
|
|
}
|
|
AddCommand(pSics, "Buf", BufferCommand, NULL, NULL);
|
|
AddCommand(pSics, "Stack", RuenStackAction, DeleteRuenStack, pStack);
|
|
return 1;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
int BufferCommand(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
int iRet, iRet2;
|
|
char pBueffel[512];
|
|
char **argx;
|
|
FuPaResult PaRes;
|
|
pRuenBuffer pBuf = NULL;
|
|
FuncTemplate BufferTemplate[] = {
|
|
{"new", 1, {FUPATEXT}},
|
|
{"del", 1, {FUPATEXT}},
|
|
{"copy", 2, {FUPATEXT, FUPATEXT}},
|
|
};
|
|
|
|
assert(pCon);
|
|
assert(pSics);
|
|
|
|
/* minimum user to use this */
|
|
if (!SCMatchRights(pCon, usUser)) {
|
|
return 0;
|
|
}
|
|
/* parse function args */
|
|
argtolower(argc, argv);
|
|
argx = &argv[1];
|
|
iRet =
|
|
EvaluateFuPa((pFuncTemplate) & BufferTemplate, 3, argc - 1, argx,
|
|
&PaRes);
|
|
if (iRet < 0) {
|
|
sprintf(pBueffel, "%s", PaRes.pError);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
|
|
switch (iRet) {
|
|
case 0: /* new */
|
|
pBuf = CreateRuenBuffer(PaRes.Arg[0].text);
|
|
if (!pBuf) {
|
|
SCWrite(pCon, "ERROR: Out of memory allocating buffer", eError);
|
|
return 0;
|
|
}
|
|
iRet2 = AddCommand(pSics, pBuf->name, BufferAction, DeleteRuenBuffer,
|
|
(void *) pBuf);
|
|
if (!iRet2) {
|
|
sprintf(pBueffel, "ERROR: duplicate command %s not created",
|
|
pBuf->name);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
DeleteRuenBuffer((void *) pBuf);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
break;
|
|
case 1: /* del */
|
|
return RemoveCommand(pSics, PaRes.Arg[0].text);
|
|
break;
|
|
case 2: /* copy */
|
|
pBuf = FindRuenBuffer(pSics, PaRes.Arg[0].text);
|
|
if (!pBuf) {
|
|
sprintf(pBueffel, "ERROR: Buffer %s not found", PaRes.Arg[0].text);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
pBuf = CopyRuenBuffer(pBuf, PaRes.Arg[1].text);
|
|
if (!pBuf) {
|
|
sprintf(pBueffel, "ERROR: creating buffer %s ", PaRes.Arg[1].text);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
iRet2 = AddCommand(pSics, pBuf->name, BufferAction, DeleteRuenBuffer,
|
|
(void *) pBuf);
|
|
if (!iRet2) {
|
|
sprintf(pBueffel, "ERROR: duplicate command %s not created",
|
|
pBuf->name);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
DeleteRuenBuffer((void *) pBuf);
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
break;
|
|
default:
|
|
assert(0);
|
|
break;
|
|
|
|
}
|
|
assert(0);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
int BufferAction(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
int iRet, iRet2;
|
|
char pBueffel[512];
|
|
char **argx;
|
|
FuPaResult PaRes;
|
|
pRuenBuffer pBuf = NULL;
|
|
FuncTemplate BufferTemplate[] = {
|
|
{"append", 0, {FUPATEXT}},
|
|
{"del", 1, {FUPAINT}},
|
|
{"ins", 1, {FUPAINT}},
|
|
{"save", 1, {FUPATEXT}},
|
|
{"load", 1, {FUPATEXT}},
|
|
{"subst", 2, {FUPATEXT, FUPATEXT}},
|
|
{"print", 0, {0, 0}},
|
|
{"run", 0, {0, 0}}
|
|
};
|
|
|
|
assert(pCon);
|
|
assert(pSics);
|
|
pBuf = (pRuenBuffer) pData;
|
|
assert(pBuf);
|
|
|
|
|
|
/* You need to be user in order to do this */
|
|
if (!SCMatchRights(pCon, usUser)) {
|
|
return 0;
|
|
}
|
|
/* parse function args */
|
|
argx = &argv[1];
|
|
strtolower(argx[0]);
|
|
iRet =
|
|
EvaluateFuPa((pFuncTemplate) & BufferTemplate, 8, argc - 1, argx,
|
|
&PaRes);
|
|
if (iRet < 0) {
|
|
sprintf(pBueffel, "%s", PaRes.pError);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
|
|
switch (iRet) {
|
|
case 0: /* append */
|
|
argx = &argv[2];
|
|
Arg2Text(argc - 2, argx, pBueffel, 511);
|
|
BufferAppendLine(pBuf, pBueffel);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
break;
|
|
case 1: /* del */
|
|
iRet2 = BufferDel(pBuf, PaRes.Arg[0].iVal);
|
|
if (iRet2)
|
|
SCSendOK(pCon);
|
|
break;
|
|
case 2: /* ins */
|
|
argx = &argv[3];
|
|
Arg2Text(argc - 3, argx, pBueffel, 511);
|
|
iRet2 = BufferInsertAfter(pBuf, PaRes.Arg[0].iVal, pBueffel);
|
|
if (iRet2)
|
|
SCSendOK(pCon);
|
|
return iRet2;
|
|
break;
|
|
case 3: /* save */
|
|
iRet2 = BufferSave(pBuf, PaRes.Arg[0].text);
|
|
if (!iRet2) {
|
|
sprintf(pBueffel, "ERROR: cannot open %s for writing",
|
|
PaRes.Arg[0].text);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
} else {
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
break;
|
|
case 4: /* load */
|
|
iRet2 = BufferLoad(pBuf, PaRes.Arg[0].text);
|
|
if (!iRet2) {
|
|
sprintf(pBueffel, "ERROR: cannot open %s for reading ",
|
|
PaRes.Arg[0].text);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
} else {
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
break;
|
|
case 5: /* subst */
|
|
iRet2 = BufferReplace(pBuf, PaRes.Arg[0].text, PaRes.Arg[1].text);
|
|
if (iRet2)
|
|
SCSendOK(pCon);
|
|
break;
|
|
case 6: /* print */
|
|
return BufferPrint(pBuf, pCon);
|
|
break;
|
|
case 7: /* run */
|
|
return BufferRun(pBuf, pCon, pSics);
|
|
default:
|
|
assert(0);
|
|
}
|
|
return 1;
|
|
}
|