diff --git a/conman.c b/conman.c index 056dc3f0..b778188f 100644 --- a/conman.c +++ b/conman.c @@ -68,7 +68,7 @@ #include "commandlog.h" #include "stptok.h" #include "sicshipadaba.h" - +#include "protocol.h" /* #define UUDEB 1 define UUDEB , for buffer writing for checking encoding */ @@ -79,7 +79,7 @@ extern pServer pServ; /*------ Max Size of Command Stack */ -#define MAXSTACK 100 +#define MAXSTACK 1024 /*---------- Magic ID Header */ #define CONMAGIC 26051958 /*------------------------------------------------------------------------- @@ -1149,8 +1149,9 @@ pDynString SCEndBuffering(SConnection *pCon) int SCWriteZipped(SConnection *self, char *pName, void *pData, int iDataLen) { char outBuf[65546], *pBuf = NULL, noutBuf[ZIPBUF], *pHeader = NULL; - int compressedLength, iRet, iRet2, iCount; + int compressedLength, iRet, iRet2, iCount, protocolID; z_stream compStream; + commandContext cc; /* check for a valid connection */ if(!VerifyConnection(self)) @@ -1225,7 +1226,15 @@ pDynString SCEndBuffering(SConnection *pCon) /* write header line */ memset(outBuf,0,65536); - sprintf(outBuf,"SICSBIN ZIP %s %d\r\n",pName,compressedLength); + + protocolID = GetProtocolID(self); + if(protocolID == 5){ + cc = SCGetContext(self); + sprintf(outBuf,"SICSBIN ZIP %s %d %d\r\n",pName, + compressedLength, cc.transID); + } else { + sprintf(outBuf,"SICSBIN ZIP %s %d \r\n",pName,compressedLength); + } pHeader = strdup(outBuf); if(pHeader == NULL) { diff --git a/danu.c b/danu.c index d77f3dea..9ec4d6d7 100644 --- a/danu.c +++ b/danu.c @@ -363,8 +363,9 @@ int NewThousand(pDataNumber self) if(SCMatchRights(pCon,usMugger)) { - DecrementDataNumber(self); - SCWrite(pCon,"Data file killed",eWarning); + iNum = DecrementDataNumber(self); + snprintf(pBueffel,511,"Data file %d killed", iNum); + SCWrite(pCon,pBueffel,eWarning); return 1; } else diff --git a/exe.w b/exe.w index 58c62057..47579b99 100644 --- a/exe.w +++ b/exe.w @@ -174,6 +174,9 @@ int ExeManagerWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, int runExeBatchBuffer(void *pData, SConnection *pCon, SicsInterp *pSics, char *name); pDynString findBatchFile(SicsInterp *pSics, char *name); +int exeHdbBuffer(SConnection *pCon, + SicsInterp *pSics, char *name); +int exeHdbNode(pHdb exeNode, SConnection *pCon); @} @o exeman.i -d @{ diff --git a/exebuf.c b/exebuf.c index b38dfd7a..431a6d33 100644 --- a/exebuf.c +++ b/exebuf.c @@ -166,13 +166,17 @@ int exeBufProcess(pExeBuf self, SicsInterp *pSics, self->lineno = 0; pTcl = InterpGetTcl(pSics); - InvokeCallBack(pCall,BATCHSTART,self->name); - + if(pCall != NULL){ + InvokeCallBack(pCall,BATCHSTART,self->name); + } + if (echo) { SCsetMacro(pCon,0); } while((command = findBlockEnd(self)) != NULL){ - InvokeCallBack(pCall,BATCHAREA,NULL); + if(pCall != NULL){ + InvokeCallBack(pCall,BATCHAREA,NULL); + } cmd = GetCharArray(command); if (echo) { @@ -223,7 +227,9 @@ int exeBufProcess(pExeBuf self, SicsInterp *pSics, SCSetInterrupt(pCon,eContinue); } } - InvokeCallBack(pCall,BATCHEND,self->name); + if(pCall != NULL){ + InvokeCallBack(pCall,BATCHEND,self->name); + } return 1; } /*------------------------------------------------------------------------*/ diff --git a/exebuf.h b/exebuf.h index 026a9730..21058511 100644 --- a/exebuf.h +++ b/exebuf.h @@ -1,5 +1,5 @@ -#line 210 "exe.w" +#line 213 "exe.w" /** * Buffer handling code for the Exe Buffer batch file processing @@ -89,7 +89,7 @@ */ char *exeBufName(pExeBuf self); -#line 223 "exe.w" +#line 226 "exe.w" #endif diff --git a/exebuf.i b/exebuf.i index 62a15a24..5ce8fea3 100644 --- a/exebuf.i +++ b/exebuf.i @@ -1,5 +1,5 @@ -#line 201 "exe.w" +#line 204 "exe.w" /*-------------------------------------------------------------------- Internal header file for the exe buffer module. Do not edit. This is @@ -16,6 +16,6 @@ typedef struct __EXEBUF{ int lineno; } ExeBuf; -#line 206 "exe.w" +#line 209 "exe.w" diff --git a/exeman.c b/exeman.c index 5ce0a74f..ad70629c 100644 --- a/exeman.c +++ b/exeman.c @@ -297,12 +297,12 @@ static int SCHdbWrite(SConnection *self, char *message, int outCode){ } if(v.v.text != NULL){ DynStringConcat(val,v.v.text); - if(strrchr(v.v.text,(int)'\n') == NULL && strlen(v.v.text) > 2){ + if(strrchr(v.v.text,(int)'\n') == NULL && strlen(v.v.text) > 1){ DynStringConcatChar(val,'\n'); } } DynStringConcat(val,message); - if(strrchr(message,(int)'\n') == NULL && strlen(message) > 2){ + if(strrchr(message,(int)'\n') == NULL && strlen(message) > 1){ DynStringConcatChar(val,'\n'); } if(v.v.text != NULL){ @@ -314,6 +314,66 @@ static int SCHdbWrite(SConnection *self, char *message, int outCode){ return 1; } /*--------------------------------------------------------------------*/ +int exeHdbNode(pHdb exeNode, SConnection *pCon){ + char pBueffel[512], *name = NULL; + pHdb node = NULL; + pExeBuf buffer = NULL; + hdbValue v; + int status; + commandContext cc; + writeFunc oldWrite; + + /* + * clear log buffer + */ + node = GetHipadabaNode(exeNode,"log"); + if(node == NULL){ + SCWrite(pCon,"ERROR: Hdb node not found or in wrong format",eError); + return 0; + } + v = MakeHdbText(strdup("")); + UpdateHipadabaPar(node,v,pCon); + /* + * prepare context + */ + name = GetHipadabaPath(node); + cc = SCGetContext(pCon); + strncpy(cc.deviceID, name,255); + strncpy(bufferNode,name,511); + + /* + * load commands into buffer + */ + node = GetHipadabaNode(exeNode,"commands"); + if(node == NULL){ + SCWrite(pCon,"ERROR: Hdb node not found or in wrong format",eError); + return 0; + } + + GetHipadabaPar(node,&v,pCon); + if(v.dataType != HIPTEXT || v.v.text == NULL){ + SCWrite(pCon,"ERROR: Hdb node is of wrong type or contains no data",eError); + return 0; + + } + + buffer = exeBufCreate(name); + if(!buffer){ + SCWrite(pCon,"ERROR: out of memory creating batch buffer",eError); + return 0; + } + exeBufAppend(buffer,v.v.text); + + strncpy(bufferNode,name,511); + oldWrite = SCGetWriteFunc(pCon); + SCSetWriteFunc(pCon,SCHdbWrite); + SCPushContext2(pCon,cc); + status = exeBufProcess(buffer,pServ->pSics,pCon,NULL,0); + SCSetWriteFunc(pCon,oldWrite); + SCPopContext(pCon); + return status; +} +/*--------------------------------------------------------------------*/ static int runHdbBuffer(pExeMan self, SConnection *pCon, SicsInterp *pSics, char *name){ char pBueffel[512]; @@ -381,6 +441,15 @@ static int runHdbBuffer(pExeMan self, SConnection *pCon, SCPopContext(pCon); return status; } +/*--------------------------------------------------------------------*/ +int exeHdbBuffer(SConnection *pCon, + SicsInterp *pSics, char *name){ + pExeMan self = (pExeMan)FindCommandData(pSics,"exe","ExeManager"); + if(self != NULL){ + return runHdbBuffer(self,pCon,pSics,name); + } + return 0; +} /*-------------------------------------------------------------------*/ int runExeBatchBuffer(void *pData, SConnection *pCon, SicsInterp *pSics, char *name){ diff --git a/exeman.h b/exeman.h index 479c5087..ddee48dd 100644 --- a/exeman.h +++ b/exeman.h @@ -16,5 +16,8 @@ int ExeManagerWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, int runExeBatchBuffer(void *pData, SConnection *pCon, SicsInterp *pSics, char *name); pDynString findBatchFile(SicsInterp *pSics, char *name); +int exeHdbBuffer(SConnection *pCon, + SicsInterp *pSics, char *name); +int exeHdbNode(pHdb exeNode, SConnection *pCon); #endif diff --git a/exeman.i b/exeman.i index c5436d01..965dc003 100644 --- a/exeman.i +++ b/exeman.i @@ -1,5 +1,5 @@ -#line 179 "exe.w" +#line 182 "exe.w" /*------------------------------------------------------------------- Internal header file for the exe manager module. Do not edit. This @@ -20,5 +20,5 @@ typedef struct __EXEMAN{ int echo; }ExeMan, *pExeMan; -#line 184 "exe.w" +#line 187 "exe.w" diff --git a/fomerge.c b/fomerge.c index 99629336..eaedb483 100644 --- a/fomerge.c +++ b/fomerge.c @@ -647,22 +647,12 @@ static int putElastic(SicsInterp *pSics, SConnection *pCon, } status = CalculateFitFromData(fitter,(float *)fTimeBin,lSum,iTime); free(lSum); - if(status != 1) - { - SCWrite(pCon,"WARNING: problem locating elastic peak",eWarning); - } GetFitResults(fitter,&fCenter,&fStdDev,&fFWHM,&fVal); fVal = fCenter - fElastic; if(fVal < 0.) fVal = - fVal; /* bad value, leave at theoretical value */ - if(fVal > 10.) - { - SCWrite(pCon, - "WARNING: bad fit result, using theoretical elastic peak position", - eWarning); - } - else + if(fVal < 10.) { fElastic = fCenter; } diff --git a/hdbqueue.c b/hdbqueue.c new file mode 100644 index 00000000..6e7dff18 --- /dev/null +++ b/hdbqueue.c @@ -0,0 +1,412 @@ +/** + * This is the new Hipadaba based queuing system in support of the MountainGum + * user interface. + * + * copyright: see file COPYRIGHT + * + * Mark Koennecke, July 2007 + */ +#include +#include +#include +#include "sicsobj.h" +#include "hdbqueue.h" +#include "sicshipadaba.h" +#include "dynstring.h" +#include "exeman.h" +#include "macro.h" +/*--------------------------------------------------------------------------*/ +typedef struct { + int iStop; + SConnection *pCon; +}HdbQueue, *pHdbQueue; +/*--------------------------------------------------------------------------*/ +static pHdbCallback CopyCallbackChain(pHdbCallback source){ + pHdbCallback current = NULL; + pHdbCallback result = NULL; + pHdbCallback head = NULL; + pHdbCallback tail = NULL; + + current = source; + while(current != NULL){ + result = MakeHipadabaCallback(current->userCallback, + current->userData, + NULL, + current->id, + current->internalID); + if(head == NULL){ + head = result; + tail = result; + } else { + tail->next = result; + result->previous = tail; + tail = result; + } + current = current->next; + } + return head; +} +/*---------------------------------------------------------------------------*/ +static pHdb MakeNewEntry(char *name, pHdbCallback update){ + pHdb entry = NULL, child = NULL; + hdbValue v; + + v = MakeHdbText("Undefined"); + entry = MakeHipadabaNode(name,HIPNONE, 1); + entry->updateCallbacks = CopyCallbackChain(update); + child = MakeSICSHdbPar("description",usUser,v); + child->updateCallbacks = CopyCallbackChain(update); + AddHipadabaChild(entry,child,NULL); + child = MakeSICSHdbPar("commands",usUser,v); + child->updateCallbacks = CopyCallbackChain(update); + AddHipadabaChild(entry,child,NULL); + child = MakeSICSHdbPar("log",usUser,v); + child->updateCallbacks = CopyCallbackChain(update); + AddHipadabaChild(entry,child,NULL); + + return entry; +} +/*---------------------------------------------------------------------------*/ +static int EnqueFunc(pSICSOBJ self, SConnection *pCon, pHdb par[], int nPar){ + pHdb entry = NULL; + pHdb work = NULL; + char name[80]; + hdbValue v; + + if(nPar < 1){ + SCWrite(pCon,"ERROR: internal: not enough parameters to EnqueFunc",eError); + return 0; + } + + /* + * new entry + */ + memset(&v,0,sizeof(hdbValue)); + work = GetHipadabaNode(self->objectNode,"control/maxEntry"); + assert(work != NULL); + snprintf(name,80,"%3.3d", work->value.v.intValue); + entry = MakeNewEntry(name, work->updateCallbacks); + if(entry == NULL){ + SCWrite(pCon,"ERROR: out of memory in EnqueFunc",eError); + return 0; + } + /* + * Update maxEntry + */ + cloneHdbValue(&work->value,&v); + v.v.intValue++; + UpdateHipadabaPar(work,v,pCon); + + work = GetHipadabaNode(self->objectNode,"queue"); + assert(work != NULL); + AddHipadabaChild(work, entry, pCon); + + /* + * save description + */ + work = GetHipadabaNode(entry,"description"); + assert(work != NULL); + UpdateHipadabaPar(work,par[0]->value,pCon); + + + return 1; +} +/*---------------------------------------------------------------------------*/ +static int AddCmdData(pSICSOBJ self, SConnection *pCon, pHdb par[], int nPar){ + pHdb work = NULL; + pHdb commandNode = NULL; + char name[80]; + pDynString txt = NULL; + + if(nPar < 1){ + SCWrite(pCon,"ERROR: internal: not enough parameters to AddCmdData",eError); + return 0; + } + + work = GetHipadabaNode(self->objectNode,"control/maxEntry"); + assert(work != NULL); + snprintf(name,80,"queue/%3.3d/commands", work->value.v.intValue-1); + commandNode = GetHipadabaNode(self->objectNode,name); + if(commandNode == NULL){ + SCWrite(pCon,"ERROR: Internal error in AddCommand",eError); + return 0; + } + txt = CreateDynString(80,80); + if(strstr(commandNode->value.v.text,"Undefined") == NULL){ + DynStringCopy(txt,commandNode->value.v.text); + } + DynStringConcat(txt,par[0]->value.v.text); + DynStringConcat(txt,"\n"); + free(commandNode->value.v.text); + commandNode->value.v.text = strdup(GetCharArray(txt)); + NotifyHipadabaPar(commandNode,pCon); + DeleteDynString(txt); + return 1; +} +/*--------------------------------------------------------------------------*/ +static void sequentialNames(pHdb obj,SConnection *pCon){ + pHdb work = NULL; + pHdb current = NULL; + int count = 0; + char name[80]; + + work = GetHipadabaNode(obj,"queue"); + assert(work != NULL); + current = work->child; + while(current != NULL){ + snprintf(name,80,"%3.3d",count); + if(current != NULL && current->name != NULL){ + free(current->name); + } + current->name = strdup(name); + count++; + current = current->next; + } + InvokeCallbackChain(work->treeChangeCallbacks,work,pCon,work->value); + + work = GetHipadabaNode(obj,"control/maxEntry"); + assert(work != NULL); + work->value.v.intValue = count; + NotifyHipadabaPar(work,pCon); +} +/*---------------------------------------------------------------------------*/ +static int Dequeue(pSICSOBJ self, SConnection *pCon, pHdb par[], int nPar){ + pHdb work = NULL; + char name[80]; + + if(nPar < 1){ + SCWrite(pCon,"ERROR: internal: not enough parameters to Dequeue",eError); + return 0; + } + + snprintf(name,80,"queue/%3.3d", par[0]->value.v.intValue); + work = GetHipadabaNode(self->objectNode,name); + if(work != NULL){ + DeleteHipadabaNode(work,pCon); + sequentialNames(self->objectNode, pCon); + return 1; + } + + return 0; +} +/*---------------------------------------------------------------------------*/ +static int Clean(pSICSOBJ self, SConnection *pCon, pHdb par[], int nPar){ + int i; + pHdb current = NULL, queue = NULL; + pHdb currentEntry = NULL, tmp; + + currentEntry = GetHipadabaNode(self->objectNode,"control/currentEntry"); + queue = GetHipadabaNode(self->objectNode,"queue"); + current = queue->child; + for(i = 0; i < currentEntry->value.v.intValue; i++){ + if(current != NULL){ + tmp = current->next; + DeleteNodeData(current); + current = tmp; + } + } + queue->child = tmp; + currentEntry->value.v.intValue = 0; + sequentialNames(self->objectNode, pCon); + NotifyHipadabaPar(currentEntry,pCon); + return 1; +} +/*----------------------------------------------------------------------------*/ +static int QueueTask(void *pData){ + pSICSOBJ self = (pSICSOBJ)pData; + int status, pos; + pHdb work = NULL; + pHdb exeNode = NULL; + pHdb max = NULL; + char name[80]; + pHdbQueue priv = (pHdbQueue)self->pPrivate; + + if(priv->iStop == 1){ + return 0; + } + + work = GetHipadabaNode(self->objectNode,"control/currentEntry"); + max = GetHipadabaNode(self->objectNode,"control/maxEntry"); + assert(work != NULL && max != NULL); + pos = work->value.v.intValue; + snprintf(name,80,"queue/%3.3d", pos); + + exeNode = GetHipadabaNode(self->objectNode,name); + if(exeNode != NULL){ + MacroPush(priv->pCon); + exeHdbNode(exeNode, priv->pCon); + MacroPop(); + } + if(priv->iStop == 1 || SCGetInterrupt(priv->pCon) != eContinue){ + return 0; + } + + pos++; + work->value.v.intValue = pos; + NotifyHipadabaPar(work,priv->pCon); + if(pos >= max->value.v.intValue){ + return 0; + } + + return 1; +} +/*---------------------------------------------------------------------------*/ +static int Start(pSICSOBJ self, SConnection *pCon, pHdb par[], int nPar){ + pHdbQueue priv = (pHdbQueue)self->pPrivate; + + priv->iStop = 0; + priv->pCon = pCon; + + TaskRegister(pServ->pTasker, + QueueTask, + NULL, + NULL, + self, + 10); + return 1; +} +/*---------------------------------------------------------------------------*/ +static int Stop(pSICSOBJ self, SConnection *pCon, pHdb par[], int nPar){ + pHdbQueue priv = (pHdbQueue)self->pPrivate; + + priv->iStop = 1; + return 1; +} +/*----------------------------------------------------------------------------*/ +static int Move(pSICSOBJ self, SConnection *pCon, pHdb par[], int nPar){ + pHdb moveNode = NULL; + pHdb insertNode = NULL; + pHdb prevNode = NULL, queueNode = NULL; + pHdb tmp; + char name[80]; + + if(nPar < 2){ + SCWrite(pCon,"ERROR: internal: not enough parameters to Move",eError); + return 1; + } + + if(par[1]->value.v.intValue == par[0]->value.v.intValue + 1){ + /* + * already in right sequence, nothing to do + */ + return 1; + } + + snprintf(name,80,"queue/%3.3d", par[1]->value.v.intValue); + moveNode = GetHipadabaNode(self->objectNode,name); + + snprintf(name,80,"queue/%3.3d", par[0]->value.v.intValue); + insertNode = GetHipadabaNode(self->objectNode,name); + if(moveNode == NULL || insertNode == NULL){ + SCWrite(pCon,"ERROR: move not possible, participating nodes not found", + eError); + return 0; + } + queueNode = GetHipadabaNode(self->objectNode,"queue"); + + if(moveNode == queueNode->child){ + queueNode->child = queueNode->child->next; + moveNode->next = insertNode->next; + insertNode->next = moveNode; + } else { + prevNode = queueNode->child; + while(prevNode != NULL && prevNode->next != moveNode){ + prevNode = prevNode->next; + } + if(insertNode == queueNode->child ){ + /* + * insert at top + */ + tmp = queueNode->child; + queueNode->child = moveNode; + prevNode->next = moveNode->next; + moveNode->next = tmp; + } else { + tmp = insertNode->next; + insertNode->next = moveNode; + prevNode->next = moveNode->next; + moveNode->next = tmp; + } + } + sequentialNames(self->objectNode, pCon); + + return 1; +} +/*---------------------------------------------------------------------------*/ +static void Configure(pSICSOBJ self){ + pHdb n = NULL, par = NULL; + hdbValue intValue, textValue, funcValue; + pHdb obj = self->objectNode; + + intValue = MakeHdbInt(0); + textValue = MakeHdbText("Undefined"); + + n = MakeHipadabaNode("control",HIPNONE,1); + AddHipadabaChild(obj,n,NULL); + AddSICSHdbPar(n,"maxEntry",usInternal,intValue); + AddSICSHdbPar(n,"currentEntry",usInternal,intValue); + + + n = MakeHipadabaNode("queue",HIPNONE,1); + AddHipadabaChild(obj,n, NULL); + + funcValue = makeHdbData(HIPFUNC,1,EnqueFunc); + n = MakeSICSHdbPar("enqueue",usUser, funcValue); + AddSICSHdbPar(n,"description",usUser,textValue); + AddHipadabaChild(obj,n,NULL); + AppendHipadabaCallback(n,HCBSET,MakeSICSFuncCallback(self)); + + funcValue = makeHdbData(HIPFUNC,1,AddCmdData); + n = MakeSICSHdbPar("addcommand",usUser, funcValue); + AddSICSHdbPar(n,"command",usUser,textValue); + AddHipadabaChild(obj,n,NULL); + AppendHipadabaCallback(n,HCBSET,MakeSICSFuncCallback(self)); + + + funcValue = makeHdbData(HIPFUNC,1,Dequeue); + n = MakeSICSHdbPar("dequeue",usUser,funcValue); + AddHipadabaChild(obj,n,NULL); + AddSICSHdbPar(n,"index",usUser,intValue); + AppendHipadabaCallback(n,HCBSET,MakeSICSFuncCallback(self)); + + + funcValue = makeHdbData(HIPFUNC,1,Clean); + n = MakeSICSHdbPar("clean",usUser, funcValue); + AddHipadabaChild(obj,n,NULL); + AppendHipadabaCallback(n,HCBSET,MakeSICSFuncCallback(self)); + + funcValue = makeHdbData(HIPFUNC,1,Start); + n = MakeSICSHdbPar("start",usUser, funcValue); + AddHipadabaChild(obj,n,NULL); + AppendHipadabaCallback(n,HCBSET,MakeSICSFuncCallback(self)); + + funcValue = makeHdbData(HIPFUNC,1,Stop); + n = MakeSICSHdbPar("stop",usUser, funcValue); + AddHipadabaChild(obj,n,NULL); + AppendHipadabaCallback(n,HCBSET,MakeSICSFuncCallback(self)); + + funcValue = makeHdbData(HIPFUNC,1,Move); + n = MakeSICSHdbPar("move",usUser,funcValue); + AddHipadabaChild(obj,n,NULL); + AddSICSHdbPar(n,"moveindex",usUser,intValue); + AddSICSHdbPar(n,"insertindex",usUser,intValue); + AppendHipadabaCallback(n,HCBSET,MakeSICSFuncCallback(self)); + +} +/*---------------------------------------------------------------------------*/ +int MakeHDBQueue(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]){ + pSICSOBJ self = NULL; + pHdbQueue priv = NULL; + + priv = (pHdbQueue)malloc(sizeof(HdbQueue)); + self = SetupSICSOBJ(pCon,pSics, pData,argc, argv); + if(self == NULL || priv == NULL){ + return 0; + } + Configure(self); + memset(priv,0,sizeof(HdbQueue)); + self->pPrivate = priv; + self->KillPrivate = free; + return 1; +} diff --git a/hdbqueue.h b/hdbqueue.h new file mode 100644 index 00000000..a1663da8 --- /dev/null +++ b/hdbqueue.h @@ -0,0 +1,15 @@ +/** + * This is the new Hipadab based queuing system in support of the MountainGum + * user interface. + * + * copyright: see file COPYRIGHT + * + * Mark Koennecke, July 2007 + */ +#ifndef HDBQUEUE_H_ +#define HDBQUEUE_H_ + +int MakeHDBQueue(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]); + +#endif /*HDBQUEUE_H_*/ diff --git a/hipadaba.c b/hipadaba.c index f45ec8cd..1aed5924 100644 --- a/hipadaba.c +++ b/hipadaba.c @@ -29,7 +29,7 @@ void DeleteCallbackChain(pHdbCallback root){ } } /*-----------------------------------------------------------------------*/ -static void DeleteNodeData(pHdb node){ +void DeleteNodeData(pHdb node){ pHdb tmp = NULL; if(node == NULL){ @@ -57,7 +57,7 @@ static void DeleteNodeData(pHdb node){ free(node); } /*-------------------------------------------------------------------------*/ -static int InvokeCallbackChain(pHdbCallback root, pHdb node, +int InvokeCallbackChain(pHdbCallback root, pHdb node, void *callData, hdbValue v){ pHdbCallback current = root; int status; @@ -92,6 +92,17 @@ void RemoveHdbNodeFromParent(pHdb node, void *callData){ parent,callData,parent->value); } } +/*----------------------------------------------------------------------*/ +int CountHdbChildren(pHdb node){ + int count = 0; + pHdb current = NULL; + current = node->child; + while(current != NULL){ + current = current->next; + count++; + } + return count; +} /*-----------------------------------------------------------------------*/ static void RemoveCallbackNode(pHdbCallback victim){ if(victim->previous != NULL) { @@ -347,6 +358,9 @@ hdbValue makeHdbData(int datatype, int length, void *data){ case HIPOBJ: val.v.obj = data; break; + case HIPFUNC: + val.v.obj = data; + break; } return val; } @@ -480,6 +494,7 @@ int compareHdbValue(hdbValue v1, hdbValue v2){ return 1; break; case HIPOBJ: + case HIPFUNC: if(v2.v.obj == v1.v.obj) { return 1; } else { @@ -523,6 +538,7 @@ int getHdbValueLength(hdbValue v){ length = strlen(v.v.text); break; case HIPOBJ: + case HIPFUNC: length = sizeof(void *); break; } @@ -913,6 +929,7 @@ int copyHdbValue(hdbValue *source, hdbValue *target){ } break; case HIPOBJ: + case HIPFUNC: target->v.obj = source->v.obj; break; default: @@ -943,6 +960,16 @@ int UpdateHipadabaPar(pHdb node, hdbValue v, void *callData){ return 1; } /*-----------------------------------------------------------------------------*/ +int NotifyHipadabaPar(pHdb node,void *callData){ + int status; + + status = InvokeCallbackChain(node->updateCallbacks, node, callData, node->value); + if(status != 1 ){ + return status; + } + return 1; +} +/*-----------------------------------------------------------------------------*/ int GetHipadabaPar(pHdb node, hdbValue *v, void *callData){ int status; diff --git a/hipadaba.h b/hipadaba.h index 885d4280..4a003bbc 100644 --- a/hipadaba.h +++ b/hipadaba.h @@ -39,6 +39,7 @@ #define HIPINTVARAR 5 #define HIPFLOATVARAR 6 #define HIPOBJ 7 +#define HIPFUNC 8 /* -------- callback types */ #define HCBSET 0 #define HCBUPDATE 1 @@ -192,7 +193,13 @@ pHdb MakeHipadabaNode(char *name, int datatype, int length); */ void AddHipadabaChild(pHdb parent, pHdb child, void *callData); /** - * delete a hipadaba node and all its children + * Delete only the node data, without invoking any callbacks + * @param node The node to delete. + */ +void DeleteNodeData(pHdb node); +/** + * delete a hipadaba node and all its children. Then invoke the tree + * change callback to notify listeners. * @parma node The node to delete * @param callData User data for the tree change callback */ @@ -228,6 +235,12 @@ void RemoveHdbNodeFromParent(pHdb node, void *callData); * @param root The callback chain to delete */ void DeleteCallbackChain(pHdbCallback root); +/** + * count the numbers of children in thie Hdb node + * @param node The node to count children for + * @return The number of children + */ +int CountHdbChildren(pHdb node); /*===================== function protoypes: Callbacks ========================*/ /** * make a new hipdaba callback @@ -270,6 +283,16 @@ void RemoveHipadabaCallback(pHdb root, int id); * @param internalID The internal ID callbacks have to match in order to be removed. */ void InternalRemoveHipadabaCallback(pHdb root, int internalID); +/** + * invoke a callback chain. + * @param root The callback chain to invoke + * @param node The node reposnible for this callback chain + * @param callData Some data belonging to the callback + * @param v The new value for this callback + * @return 1 on success, 0 on failure + */ +int InvokeCallbackChain(pHdbCallback root, pHdb node, + void *callData, hdbValue v); /*============== Parameter Handling ===============================*/ /** @@ -290,6 +313,14 @@ int SetHipadabaPar(pHdb node, hdbValue v, void *callData); * @return 0 on failure, 1 on success */ int UpdateHipadabaPar(pHdb node, hdbValue v, void *callData); +/** + * notify any update listeners that this node has been internally modidifed. + * @param node The node modified + * @param callData Addtional data for the callback + * @return 1 on success, 0 on failure + */ +int NotifyHipadabaPar(pHdb node,void *callData); + /** * Read a hipadaba parameter * @param node The node for which to read the parameter diff --git a/make_gen b/make_gen index 7dc548a9..bf2c5708 100644 --- a/make_gen +++ b/make_gen @@ -33,7 +33,7 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \ sinfox.o sicslist.o cone.o hipadaba.o sicshipadaba.o statistics.o \ moregress.o hdbcommand.o multicounter.o regresscter.o histregress.o \ sicshdbadapter.o polldriv.o sicspoll.o statemon.o hmslave.o \ - nwatch.o asyncqueue.o asyncprotocol.o + nwatch.o asyncqueue.o asyncprotocol.o sicsobj.o hdbqueue.o MOTOROBJ = motor.o simdriv.o COUNTEROBJ = countdriv.o simcter.o counter.o diff --git a/ofac.c b/ofac.c index ccc8576f..9f83d051 100644 --- a/ofac.c +++ b/ofac.c @@ -124,6 +124,8 @@ #include "statemon.h" #include "asyncqueue.h" #include "asyncprotocol.h" +#include "sicsobj.h" +#include "hdbqueue.h" /*----------------------- Server options creation -------------------------*/ static int IFServerOption(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]) @@ -341,6 +343,8 @@ StateMonFactory,NULL,NULL); AddCommand(pInter,"MakeAsyncProtocol",AsyncProtocolFactory,NULL,NULL); AddCommand(pInter,"MakeAsyncQueue",AsyncQueueFactory,NULL,NULL); + AddCommand(pInter,"MakeSicsObj",InstallSICSOBJ,NULL,NULL); + AddCommand(pInter,"MakeHdbQueue",MakeHDBQueue,NULL,NULL); /* install site specific commands @@ -412,6 +416,8 @@ RemoveCommand(pSics,"MakeStateMon"); RemoveCommand(pSics,"MakeAsyncQueue"); RemoveCommand(pSics,"MakeAsyncProtocol"); + RemoveCommand(pSics,"MakeSicsObject"); + RemoveCommand(pSics,"MakeHdbQueue"); /* remove site specific installation commands */ diff --git a/scan.c b/scan.c index 8b9f310f..e61a3d48 100644 --- a/scan.c +++ b/scan.c @@ -547,10 +547,6 @@ CountEntry CollectCounterData(pScanData self) { /*--------- drive */ iRet = self->ScanDrive(self,i); - if(!iRet) - { - return 0; - } /* finished, check for interrupts. Whatever happened, user interrupt or HW interrupt, it will be on our connection */ @@ -579,13 +575,15 @@ CountEntry CollectCounterData(pScanData self) return 0; break; } + if(!iRet) + { + SCWrite(self->pCon,"WARNING: skipped scan point after drive failure", + eWarning); + continue; + } + /*-------------- count */ iRet = self->ScanCount(self, i); - if(!iRet) - { - return 0; - } - /* finished, check for interrupts. Whatever happened, user interrupt or HW interrupt, it will be on our connection */ @@ -610,6 +608,13 @@ CountEntry CollectCounterData(pScanData self) return 0; break; } + if(!iRet) + { + SCWrite(self->pCon,"WARNING: skipped scan point after count failure", + eWarning); + continue; + } + /*-------- scan post processing */ self->CollectScanData(self,i); InvokeCallBack(self->pCall,SCANPOINT,self); diff --git a/sicshipadaba.c b/sicshipadaba.c index 3a7edaaf..f61c0d88 100644 --- a/sicshipadaba.c +++ b/sicshipadaba.c @@ -25,6 +25,7 @@ #include #include "protocol.h" #include +#include "sicsobj.h" /*== there can be only hipadaba in SICS, some globals to care for that == */ static pHdb root = NULL; @@ -102,12 +103,18 @@ static int SICSDriveCallback(void *userData, void *callData, pHdb node, hdbValue v){ SConnection *pCon = NULL; pDummy dum = NULL; + char pSicsdev[80]; pCon = (SConnection *)callData; dum = (pDummy)userData; assert(pCon != NULL && dum != NULL); - return StartDevice(pServ->pExecutor,node->name,dum->pDescriptor, - userData, pCon, (float)v.v.doubleValue); + if(GetHdbProperty(node,"sicsdev",pSicsdev,79)){ + return StartDevice(pServ->pExecutor,pSicsdev,dum->pDescriptor, + userData, pCon, (float)v.v.doubleValue); + } else { + return StartDevice(pServ->pExecutor,node->name,dum->pDescriptor, + userData, pCon, (float)v.v.doubleValue); + } } /*---------------------------------------------------------------------------------------*/ pHdbCallback MakeSICSDriveCallback(void *sicsObject){ @@ -145,6 +152,37 @@ static int SICSReadDriveCallback(void *userData, void *callData, pHdb node, } return 1; } +/*--------------------------------------------------------------------------*/ +static int SICSFuncCallback(void *userData, void *callData, pHdb node, + hdbValue v){ + pHdb par[64], current = NULL; + int nPar = 0; + SICSOBJFunc func = NULL; + + assert(node->value.dataType == HIPFUNC); + if(userData == NULL || callData == NULL){ + printf("Great Badness in calling SICSFuncCallback\n"); + return 0; + } + + current = node->child; + while(current != NULL){ + par[nPar] = current; + nPar++; + current = current->next; + } + func = (SICSOBJFunc)node->value.v.obj; + if(func != NULL){ + return func((pSICSOBJ)userData,(SConnection *)callData, par,nPar); + } else { + printf("Great Badness in calling SICSFuncCallback\n"); + return 0; + } +} +/*---------------------------------------------------------------------------*/ +pHdbCallback MakeSICSFuncCallback(void *obj){ + return MakeHipadabaCallback(SICSFuncCallback, obj,NULL,-1,-1); +} /*--------------------------------------------------------------------------------------*/ pHdbCallback MakeSICSReadDriveCallback(void *sicsObject){ return MakeHipadabaCallback(SICSReadDriveCallback, sicsObject,NULL,-1,-1); @@ -220,7 +258,50 @@ int formatNameValue(Protocol protocol, char *name, char *value, pDynString resul } return protocol; } - +/*----------------------------------------------------------------------------*/ +static int sendZippedNodeData(pHdb node, SConnection *pCon){ + hdbValue newValue; + int i, *iData = NULL; + char *path = NULL; + + memset(&newValue,0,sizeof(hdbValue)); + GetHipadabaPar(node, &newValue, pCon); + path = GetHipadabaPath(node); + switch(newValue.dataType){ + case HIPINTAR: + case HIPINTVARAR: + for(i = 0; i < newValue.arrayLength; i++){ + newValue.v.intArray[i] = htonl(newValue.v.intArray[i]); + } + SCWriteZipped(pCon,path, newValue.v.intArray, + newValue.arrayLength*sizeof(int)); + break; + case HIPFLOATAR: + case HIPFLOATVARAR: + iData = (int *)malloc(newValue.arrayLength*sizeof(int)); + if(iData == NULL){ + SCWrite(pCon,"ERROR: out of memory in sendZippedData",eError); + free(path); + return 0; + } + memset(iData,0,newValue.arrayLength*sizeof(int)); + for(i = 0; i < newValue.arrayLength; i++){ + iData[i] = htonl((int)newValue.v.floatArray[i]*65536.); + } + SCWriteZipped(pCon,path, iData, + newValue.arrayLength*sizeof(int)); + free(iData); + break; + default: + SCWrite(pCon,"ERROR: zipped writing not supported for this datatype", + eError); + free(path); + return 0; + } + free(path); + ReleaseHdbValue(&newValue); + return 1; +} /*----------------------------------------------------------------------------------------*/ static int SICSNotifyCallback(void *userData, void *callData, pHdb node, hdbValue v){ @@ -229,7 +310,8 @@ static int SICSNotifyCallback(void *userData, void *callData, pHdb node, pDynString result = NULL; char *pPath = NULL; Protocol protocol = normal_protocol; - int outCode, macro; + int outCode, macro, status; + char value[80]; cbInfo = (HdbCBInfo *)userData; pPath = GetHipadabaPath(node); @@ -244,6 +326,19 @@ static int SICSNotifyCallback(void *userData, void *callData, pHdb node, */ macro = SCinMacro(cbInfo->pCon); SCsetMacro(cbInfo->pCon,0); + /** + * if transfer = zip always transfer data in zipped form + */ + if(GetHdbProperty(node,"transfer",value,80) == 1){ + if(strstr(value,"zip") != NULL){ + SCPushContext2(cbInfo->pCon,cbInfo->context); + status = sendZippedNodeData(node, cbInfo->pCon); + SCPopContext(cbInfo->pCon); + SCsetMacro(cbInfo->pCon,macro); + free(pPath); + return status; + } + } if(v.arrayLength < 100){ printedData = formatValue(v); if(pPath == NULL || printedData == NULL || result == NULL){ @@ -1313,6 +1408,7 @@ int readHdbValue(hdbValue *v, char *data, char *error, int errlen){ double dValue; char number[80]; char *pPtr = NULL; + CommandList *pCom = NULL; switch(v->dataType){ case HIPNONE: @@ -1385,6 +1481,16 @@ int readHdbValue(hdbValue *v, char *data, char *error, int errlen){ v->v.floatArray[i] = dValue; } break; + case HIPOBJ: + pCom = FindCommand(pServ->pSics,data); + if(pCom == NULL && pCom->pData != NULL){ + snprintf(error,errlen,"object %s NOT found", data); + return 0; + } + v->v.obj = pCom->pData; + break; + case HIPFUNC: + break; default: assert(0); break; @@ -1404,6 +1510,8 @@ static char *hdbTypes[] = {"none", "floatar", "intvarar", "floatvarar", + "object", + "func", NULL}; /*-------------------------------------------------------------------------*/ static int convertHdbType(char *text){ @@ -1689,7 +1797,7 @@ static int SetHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData, return 0; } if(!cloneHdbValue(&targetNode->value,&newValue)){ - SCWrite(pCon,"ERROR: out of mmeory cloning node", + SCWrite(pCon,"ERROR: out of memory cloning node", eError); return 0; } @@ -1761,6 +1869,7 @@ static int UpdateHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData, return 0; } } else { + memset(&newValue,0,sizeof(hdbValue)); GetHipadabaPar(targetNode,&newValue,pCon); } status = UpdateHipadabaPar(targetNode,newValue,pCon); @@ -1771,6 +1880,25 @@ static int UpdateHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData, return status; } /*-----------------------------------------------------------------------------*/ +static int ZipGetHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]){ + pHdb targetNode = NULL; + char error[512], oriPath[512]; + int status; + + if(argc < 2) { + SCWrite(pCon,"ERROR: need path to node",eError); + return 0; + } + + strncpy(oriPath,argv[1], 511); + targetNode = locateSICSNode(pSics,pCon,argv[1]); + if(targetNode == NULL){ + return 0; + } + return sendZippedNodeData(targetNode,pCon); +} +/*---------------------------------------------------------------------------*/ static int GetHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]){ pHdb targetNode = NULL; @@ -1780,6 +1908,7 @@ static int GetHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData, int i, status; Protocol protocol = normal_protocol; int outCode; + char value[80]; if(argc < 2) { SCWrite(pCon,"ERROR: need path to node to print",eError); @@ -1791,6 +1920,14 @@ static int GetHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData, if(targetNode == NULL){ return 0; } + /* + * if transfer = zip, redirect to zip + */ + if(GetHdbProperty(targetNode,"transfer", value,80) == 1){ + if(strstr(value,"zip") != NULL){ + return ZipGetHdbNode(pCon,pSics,pData,argc,argv); + } + } memset(&newValue,0,sizeof(hdbValue)); GetHipadabaPar(targetNode, &newValue, pCon); parData = formatValue(newValue); @@ -1812,59 +1949,6 @@ static int GetHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData, return 1; } -/*-----------------------------------------------------------------------------*/ -static int ZipGetHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]){ - pHdb targetNode = NULL; - hdbValue newValue; - char error[512], oriPath[512]; - int i, status; - int *iData = NULL; - - if(argc < 2) { - SCWrite(pCon,"ERROR: need path to node",eError); - return 0; - } - - strncpy(oriPath,argv[1], 511); - targetNode = locateSICSNode(pSics,pCon,argv[1]); - if(targetNode == NULL){ - return 0; - } - memset(&newValue,0,sizeof(hdbValue)); - GetHipadabaPar(targetNode, &newValue, pCon); - switch(newValue.dataType){ - case HIPINTAR: - case HIPINTVARAR: - for(i = 0; i < newValue.arrayLength; i++){ - newValue.v.intArray[i] = htonl(newValue.v.intArray[i]); - } - SCWriteZipped(pCon,oriPath, newValue.v.intArray, - newValue.arrayLength*sizeof(int)); - break; - case HIPFLOATAR: - case HIPFLOATVARAR: - iData = (int *)malloc(newValue.arrayLength*sizeof(int)); - if(iData == NULL){ - SCWrite(pCon,"ERROR: out of memory in ZipGetHdbNode",eError); - return 0; - } - memset(iData,0,newValue.arrayLength*sizeof(int)); - for(i = 0; i < newValue.arrayLength; i++){ - iData[i] = htonl((int)newValue.v.floatArray[i]*65536.); - } - SCWriteZipped(pCon,oriPath, iData, - newValue.arrayLength*sizeof(int)); - free(iData); - break; - default: - SCWrite(pCon,"ERROR: zipped writing not supported for this datatype", - eError); - return 0; - } - ReleaseHdbValue(&newValue); - return 1; -} /*--------------------------------------------------------------------------*/ static int countChildren(pHdb node){ pHdb current = NULL; @@ -2316,6 +2400,63 @@ static int ChainHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData, SCSendOK(pCon); return 1; } +/* -------------------------------------------------------------------------- + * This is actually SCInvoke but without advancing the context. I think this + * is only of local use. It makes sure that commands executed as Hipadaba + * commands get logged properly. + */ + static int HDBInvoke(SConnection *self, SicsInterp *pInter, char *pCommand) + { + int iRet; + long lLen; + const char *pResult = NULL; + char *pBuffer = NULL, *pFile = NULL; + char pBueffel[80]; + int i, iSpace; + + assert(pInter); + + /* print command to log files */ + for( i = 0; i < self->iFiles; i++) + { + if(self->pFiles[i]) + { + fprintf(self->pFiles[i],"SICS>> %s\n",pCommand); + } + } + + /* print to command log if user or manager */ + if(SCGetRights(self) <= usUser) + { + if(self->pSock != NULL) + { + sprintf(pBueffel,"sock %d>>",self->pSock->sockid); + } + } + + /* invoke */ + self->inUse++; + self->eInterrupt = eContinue; + self->parameterChange = 0; + /* + get first word of command + */ + iRet = InterpExecute(pInter,self,pCommand); + if(self->parameterChange == 1) + { + /* + automatically save changed parameters + */ + pFile = IFindOption(pSICSOptions,"statusfile"); + if(pFile != NULL) + { + WriteSicsStatus(pInter,pFile,0); + self->parameterChange = 0; + } + } + self->inUse--; + return iRet; + } /*---------------------------------------------------------------------------*/ static int CommandSetCallback(void *userData, void *callData, pHdb node, hdbValue v){ @@ -2348,7 +2489,7 @@ static int CommandSetCallback(void *userData, void *callData, pHdb node, } current = current->next; } - status = SCInvoke(pCon, pServ->pSics,GetCharArray(cmd)); + status = HDBInvoke(pCon,pServ->pSics, GetCharArray(cmd)); DeleteDynString(cmd); return status; } else { diff --git a/sicshipadaba.h b/sicshipadaba.h index 29724ee7..85c1e010 100644 --- a/sicshipadaba.h +++ b/sicshipadaba.h @@ -119,6 +119,11 @@ pHdbCallback MakeMemSetCallback(float *address); * @return a suitable callback for notififications about tree changes. */ pHdbCallback MakeTreeChangeCallback(SConnection *pCon, int id); + /** + * make a clalback to invoke a function node + */ + pHdbCallback MakeSICSFuncCallback(void *obj); + /*======================== parameter creation ===================================*/ /** * make a simple SICS hdb parameter. Setting it will call update immediately. Use diff --git a/sicsobj.c b/sicsobj.c new file mode 100644 index 00000000..c862548d --- /dev/null +++ b/sicsobj.c @@ -0,0 +1,167 @@ +/** + * This is the header file for the new (as of 2007) style SICS objects + * + * copyright: see file COPYRIGHT + * + * Mark Koennecke, July 2007 + */ +#include +#include "assert.h" +#include "ifile.h" +#include "sicsobj.h" +#include "sicshipadaba.h" +/*--------------------------------------------------------------------------*/ +static void DefaultKill(void *data){ + return; +} +/*---------------------------------------------------------------------------*/ +pSICSOBJ MakeSICSOBJ(char *name, char *class){ + pSICSOBJ pNew = NULL; + + pNew = (pSICSOBJ)malloc(sizeof(SICSOBJ)); + if(pNew == NULL){ + return NULL; + } + memset(pNew,0,sizeof(SICSOBJ)); + pNew->pDes = CreateDescriptor(class); + pNew->objectNode = MakeHipadabaNode(name, HIPNONE, 1); + if(pNew->pDes == NULL || pNew->objectNode == NULL){ + free(pNew); + return(NULL); + } + pNew->pDes->parNode = pNew->objectNode; + pNew->KillPrivate = DefaultKill; + return pNew; +} +/*---------------------------------------------------------------------------*/ +void KillSICSOBJ(void *data){ + pSICSOBJ self = (pSICSOBJ)data; + if(self == NULL){ + return; + } + if(self->pDes != NULL){ + DeleteDescriptor(self->pDes); + } + if(self->KillPrivate != NULL && self->pPrivate != NULL){ + self->KillPrivate(self->pPrivate); + } + free(self); +} +/*===========================================================================*/ +static int assignPar(pHdb node, SConnection *pCon, char *data){ + char error[132], buffer[256]; + int status; + + status = readHdbValue(&node->value,data, error, 132); + if(status != 1){ + snprintf(buffer,255,"ERROR: error parsing %s: %s", + node->name, error); + SCWrite(pCon,buffer,eError); + return 0; + } + return 1; +} +/*---------------------------------------------------------------------------*/ +static int invokeOBJFunction(pSICSOBJ object, pHdb commandNode, SConnection *pCon, + int argc, char *argv[]){ + int status, i, count = 0; + pHdb currentPar = NULL; + SICSOBJFunc pFunc = NULL; + pHdb parArray[64]; + + /* + * assign parameters and fill parameter array for function at the same + * time. Be lenient about missing parameters: Then the old values will + * be used. + */ + for(i = 0, currentPar = commandNode->child; + i < argc && currentPar != NULL; + i++, currentPar = currentPar->next){ + if(argv[i] != NULL){ + status = assignPar(currentPar,pCon, argv[i]); + } + if(status != 1){ + return status; + } + parArray[i] = currentPar; + count++; + } + + pFunc = (SICSOBJFunc)commandNode->value.v.obj; + if(pFunc == NULL){ + SCWrite(pCon,"ERROR: internal error, function not found",eError); + return 0; + } + status = pFunc(object, pCon, parArray,count); + return status; +} +/*---------------------------------------------------------------------------*/ +int InvokeSICSOBJ(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]){ + pSICSOBJ self = NULL; + int status; + pHdb parNode; + char buffer[132]; + + self = (pSICSOBJ)pData; + assert(self != NULL); + + if(argc < 1){ + SCWrite(pCon,"ERROR: Nothing to process",eError); + return -1; + } + parNode = GetHipadabaNode(self->objectNode,argv[1]); + if(parNode != NULL && parNode->value.dataType == HIPFUNC){ + status = invokeOBJFunction(self, parNode, pCon, argc-2, &argv[2]); + } else { + status = ProcessSICSHdbPar(self->objectNode,pCon, argv[0], + argc-1,&argv[1]); + } + if(status == -1){ + snprintf(buffer,131,"ERROR: no command or parameter found for key: %s", + argv[1]); + SCWrite(pCon,buffer,eError); + status = 0; + } + + return status; +} +/*---------------------------------------------------------------------------*/ +pSICSOBJ SetupSICSOBJ(SConnection *pCon,SicsInterp *pSics, void *pData, + int argc, char *argv[]){ + pSICSOBJ pNew = NULL; + int status; + + if(argc < 3){ + SCWrite(pCon,"ERROR: not enough arguments to InstallSICSOBJ",eError); + return NULL; + } + pNew = MakeSICSOBJ(argv[1], argv[2]); + if(pNew == NULL){ + SCWrite(pCon,"ERROR: out of memory creating new SICS object",eError); + return NULL; + } + status = AddCommand(pSics, + argv[1], + InvokeSICSOBJ, + KillSICSOBJ, + pNew); + if(status != 1){ + KillSICSOBJ(pNew); + SCPrintf(pCon,eError,"ERROR: failed create duplicate command %s", argv[1]); + return NULL; + } + return pNew; + } +/*---------------------------------------------------------------------------*/ +int InstallSICSOBJ(SConnection *pCon,SicsInterp *pSics, void *pData, + int argc, char *argv[]){ + pSICSOBJ pNew = NULL; + + pNew = SetupSICSOBJ(pCon, pSics, pData, argc, argv); + if(pNew == NULL){ + return 0; + } else { + return 1; + } +} diff --git a/sicsobj.h b/sicsobj.h new file mode 100644 index 00000000..d848eed3 --- /dev/null +++ b/sicsobj.h @@ -0,0 +1,44 @@ +/** + * This is the header file for the new (as of 2007) style SICS objects + * + * copyright: see file COPYRIGHT + * + * Mark Koennecke, July 2007 + */ +#ifndef SICSOBJ2_H_ +#define SICSOBJ2_H_ +#include +#include +/*====================================================================== + * Be careful when changing this data structure. It has to be compatible + * in its first fields with the SICS object descriptor as defined in + * obdes.h in order to achieve backwards compatibility with old style + * SICS objects. + * =====================================================================*/ +typedef struct { + pObjectDescriptor pDes; + pHdb objectNode; + void *pPrivate; + void (*KillPrivate)(void *pPrivate); +}SICSOBJ, *pSICSOBJ; +/*-----------------------------------------------------------------------*/ +typedef int (*SICSOBJFunc)(pSICSOBJ self, SConnection *pCon, + pHdb par[], int nPar); +/*======================= Live & Death =================================*/ +pSICSOBJ MakeSICSOBJ(char *name, char *class); +void KillSICSOBJ(void *data); +/** + * This creates a new SICS object and installs it in the interpreter. It returns + * the newly created SICS object such that the caller can continue + * configuring it. + */ +pSICSOBJ SetupSICSOBJ(SConnection *pCon,SicsInterp *pSics, void *pData, + int argc, char *argv[]); +/*====================== Interpreter Interface ===========================*/ +int InvokeSICSOBJ(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]); +int InstallSICSOBJ(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]); + + +#endif /*SICSOBJ2_H_*/