/*--------------------------------------------------------------------------

				H I S T M E M
				
  The SICS histogram memory object. 
  
  Mark Koennecke, April 1996
  
  revised: Mark Koennecke, June 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 <arpa/inet.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <tcl.h>
#include <time.h>
#include "sics.h"
#include "fortify.h"
#include "countdriv.h"
#include "counter.h"
#include "stringdict.h"
#include "splitter.h"
#include "HistMem.h"
#include "HistDriv.i"
#include "HistMem.i"
#include "histsim.h"
#include "hardsup/sinqhm.h"
#include "sinqhmdriv.i"
#include "dynstring.h"
#include "event.h"

/*
#define LOADDEBUG 1
*/
/*------------------------------------------------------------------------*/
  static int HistHalt(void *pData)
  {
    pHistMem self = NULL;

    self = (pHistMem)pData;
    assert(self);

    if(!self->iInit)
    {
      return 0;
    }
    return self->pDriv->Halt(self->pDriv);
  }  
/*------------------------------------------------------------------------*/
  static int HistSave(void *pData, char *name, FILE *fd)
  {
    pHistMem self = NULL;
    char *pMode[] = {
                    "timer",
                    "monitor",
                    NULL
                   };
    CounterMode eCount;
    float fVal;
    
    self = (pHistMem)pData;
    assert(self);

    if(!self->iInit)
    {
      return 0;
    }

    /* counting modes */
    eCount = GetHistCountMode(self);
    fprintf(fd,"%s CountMode %s\n",name,pMode[eCount]);
    fVal = GetHistPreset(self);
    fprintf(fd,"%s preset %f\n",name,fVal);
    
    /* time binning if TOF */
    if(self->pDriv->eHistMode == eHTOF)
    {
      fprintf(fd,"%s genbin %f %f %d\n",
              name, self->pDriv->fTime[0], 
              self->pDriv->fTime[1] - self->pDriv->fTime[0],
              self->pDriv->iTimeChan);
      fprintf(fd,"%s init\n",name);
    }    

    return 1;
  }  
/*------------------------------------------------------------------------*/
  static void *GetHistInterface(void *pData, int iID)
  {
    pHistMem self = NULL;
    
    self = (pHistMem)pData;
    if(iID == COUNTID)
    {
      return self->pCountInt;
    }
    else if(iID == CALLBACKINTERFACE)
    {
       return self->pCall;
    }
    return NULL;
  }
/*-------------------------------------------------------------------------*/
  static int HistStartCount(void *pData, SConnection *pCon)
  {
    pHistMem self = NULL;
    char pBueffel[512];
    char pError[80];
    int iErr, iRet, i;
    
    self = (pHistMem)pData;
    assert(self);

    if(!self->iInit)
    {
      SCWrite(pCon,"ERROR: histogram memory not initialised",eError);
      return 0;
    }

    /* try at least three times to do it */
      for(i = 0; i < 3; i++)
      {
             iRet = self->pDriv->Start(self->pDriv, pCon);
             if(iRet == OKOK)
             {
               self->pDriv->iUpdate = 1;
               self->iLocalUpdate = 1;
               self->tLocal = time(NULL) + self->iUpdateIntervall;
               return iRet;
             }       
             else
             {
                iRet = self->pDriv->GetError(self->pDriv,&iErr,pError,79);
                sprintf(pBueffel,"WARNING: %s ",pError);
                SCWrite(pCon,pBueffel,eError);
                iRet = self->pDriv->TryAndFixIt(self->pDriv,iErr);
                if(iRet == COTERM)
                {
                  SCWrite(pCon,"ERROR: failed to fix histogram memory problem",
                          eError);
                  SCSetInterrupt(pCon,eAbortBatch);
                  return HWFault;
                } 
             }
      }
      SCWrite(pCon,"ERROR: failed to fix histogram memory problem",eError);
      SCSetInterrupt(pCon,eAbortBatch);
      return HWFault;   
  }
/*-------------------------------------------------------------------------*/
  static int HistPause(void *pData, SConnection *pCon)
  {
    pHistMem self = NULL;
    char pBueffel[512];
    char pError[80];
    int iErr, iRet, i;
    
    self = (pHistMem)pData;
    assert(self);

    if(!self->iInit)
    {
      SCWrite(pCon,"ERROR: histogram memory not initialised",eError);
      return 0;
    }

    /* try at least three times to do it */
      for(i = 0; i < 3; i++)
      {
             iRet = self->pDriv->Pause(self->pDriv, pCon);
             if(iRet == OKOK)
             {
               self->pDriv->iUpdate = 1;
               return iRet;
             }       
             else
             {
                iRet = self->pDriv->GetError(self->pDriv,&iErr,pError,79);
                sprintf(pBueffel,"WARNING: %s ",pError);
                SCWrite(pCon,pBueffel,eError);
                iRet = self->pDriv->TryAndFixIt(self->pDriv,iErr);
                if(iRet == COTERM)
                {
                  SCWrite(pCon,"ERROR: failed to fix histogram memory problem",eError);
                  SCSetInterrupt(pCon,eAbortBatch);
                  return HWFault;
                } 
             }
      }
      SCWrite(pCon,"ERROR: failed to fix histogram memory problem",eError);
      SCSetInterrupt(pCon,eAbortBatch);
      return HWFault;   
  }
  
/*-------------------------------------------------------------------------*/
  static int HistContinue(void *pData, SConnection *pCon)
  {
    pHistMem self = NULL;
    char pBueffel[512];
    char pError[80];
    int iErr, iRet, i;
    
    self = (pHistMem)pData;
    assert(self);

    if(!self->iInit)
    {
      SCWrite(pCon,"ERROR: histogram memory not initialised",eError);
      return 0;
    }

    /* try at least three times to do it */
      for(i = 0; i < 3; i++)
      {
             iRet = self->pDriv->Continue(self->pDriv, pCon);
             if(iRet == OKOK)
             {
               self->pDriv->iUpdate = 1;
               return iRet;
             }       
             else
             {
                iRet = self->pDriv->GetError(self->pDriv,&iErr,pError,79);
                sprintf(pBueffel,"WARNING: %s ",pError);
                SCWrite(pCon,pBueffel,eError);
                iRet = self->pDriv->TryAndFixIt(self->pDriv,iErr);
                if(iRet == COTERM)
                {
                  SCWrite(pCon,"ERROR: failed to fix histogram memory problem",eError);
                  SCSetInterrupt(pCon,eAbortBatch);
                  return HWFault;
                } 
             }
      }
      SCWrite(pCon,"ERROR: failed to fix histogram memory problem",eError);
      SCSetInterrupt(pCon,eAbortBatch);
      return HWFault;   
  }
/*-------------------------------------------------------------------------*/
  static int HistCountStatus(void *pData, SConnection *pCon)
  {
      pHistMem self = NULL;
      int eCt, iRet, iErr;
      char pBueffel[512], pError[90];
    
      self = (pHistMem)pData;
      assert(self);
      
      if(!self->iInit)
      {
         SCWrite(pCon,"ERROR: histogram memory not initialised",eError);
         return COTERM;
      }
      
      eCt = self->pDriv->GetCountStatus(self->pDriv,pCon);
      if(eCt == HWFault)
      {
         iRet = self->pDriv->GetError(self->pDriv,&iErr,pError,79);
         sprintf(pBueffel,"WARNING: %s ",pError);
         SCWrite(pCon,pBueffel,eError);
         iRet = self->pDriv->TryAndFixIt(self->pDriv,iErr);
         if(iRet == COTERM)
         {
           SCWrite(pCon,"ERROR: failed to fix histogram memory problem",eError);
           SCSetInterrupt(pCon,eAbortBatch);
           SCSetError(pCon,eCt);
           return eCt;
         }  
         else
         {
           self->iLocalUpdate = 1;
           return HWBusy;
         }
      }
      if(eCt == HWBusy)
         self->iLocalUpdate = 1;
      
      if(eCt == HWIdle)
      {
	/* force an update of local histogram data with next
           GetHistogram
	*/   
         self->iLocalUpdate = 1;
         self->tLocal = 0;
      }
     
      return eCt;
  }  
/*-------------------------------------------------------------------------
  The question arises if the histograms shall be duplicated on the host 
  computer or not. They need to be in order to be written to file!
*/
  static int HistTransfer(void *pData, SConnection *pCon)
  {
    pHistMem self = NULL;
    int i, iErr, iRet, iStatus;
    char pBueffel[512], pError[80];
    
    self = (pHistMem)pData;
    assert(self);
    
    if(!self->iInit)
    {
         SCWrite(pCon,"ERROR: histogram memory not initialised",eError);
         return COTERM;
    }

    /* try at least three times */
      for(i = 0; i < 3; i++)
      {
             iRet = self->pDriv->GetData(self->pDriv, pCon);
             if(iRet == OKOK)
             {
               self->pDriv->iUpdate = 0;
               iStatus = iRet;
             }       
             else
             {
                iRet = self->pDriv->GetError(self->pDriv,&iErr,pError,79);
                sprintf(pBueffel,"WARNING: %s ",pError);
                SCWrite(pCon,pBueffel,eError);
                iRet = self->pDriv->TryAndFixIt(self->pDriv,iErr);
                if(iRet == COTERM)
                {
                  SCWrite(pCon,"ERROR: failed to fix histogram memory problem",                          eError);
                  SCSetInterrupt(pCon,eAbortBatch);
                  iStatus = HWFault;
                } 
             }
      }
      if(iRet == OKOK)
      {
        return iStatus;
      }
      SCWrite(pCon,"ERROR: failed to fix histogram memory problem",eError);
      SCSetInterrupt(pCon,eAbortBatch);
      return HWFault;   
  }  	
/*-------------------------------------------------------------------------*/
  pHistMem CreateHistMemory(char *driver)
  {
     pHistMem pNew = NULL;
     
     /* make memory */
     pNew = (pHistMem)malloc(sizeof(HistMem));
     if(!pNew)
     {
       return NULL;
     }
     memset(pNew,0,sizeof(HistMem));
     
     /* make object descriptor */
     pNew->pDes = CreateDescriptor("HistMem");
     if(!pNew->pDes)
     {
       free(pNew);
       return NULL;
     } 
     pNew->pDes->SaveStatus = HistSave;
     pNew->pDes->GetInterface = GetHistInterface;
     
    /* initialise countable interface */
     pNew->pCountInt = CreateCountableInterface();
     if(!pNew->pCountInt)
     {
       DeleteDescriptor(pNew->pDes);
       free(pNew);
       return NULL;
     } 
     /* initialise callback interface */
     pNew->pCall = CreateCallBackInterface();
     if(!pNew->pCall)
     {
        DeleteDescriptor(pNew->pDes);
        free(pNew);
        return NULL;
     } 
     pNew->pCountInt->StartCount = HistStartCount;
     pNew->pCountInt->CheckCountStatus = HistCountStatus;
     pNew->pCountInt->TransferData = HistTransfer;
     pNew->pCountInt->Halt = HistHalt;
     pNew->pCountInt->Pause = HistPause;
     pNew->pCountInt->Continue = HistContinue;
     pNew->iLocalData = NULL;
     pNew->iLocalLength = 0;
     pNew->iUpdateIntervall = 0;
     pNew->iLocalUpdate = 1;
     pNew->tLocal = 0;   
  
     /* initialise options dictionary */
     pNew->pOption = CreateStringDict();
     if(!pNew->pOption)
     {
       DeleteDescriptor(pNew->pDes);
       free(pNew);
       return NULL;
     }
     StringDictAddPair(pNew->pOption,"update","0");     

     /* initialise driver */
     if(strcmp(driver,"sim") == 0)
     {
        pNew->pDriv = CreateSIMHM(pNew->pOption);
     }
     else if(strcmp(driver,"sinqhm") == 0)
     {
       pNew->pDriv = CreateSINQDriver(pNew->pOption);
     }
     else /* no driver found */
     {
        DeleteDescriptor(pNew->pDes);
        DeleteStringDict(pNew->pOption);
        free(pNew);
        return NULL;
     }
     pNew->iAccess = usUser;
     pNew->iExponent = 0;
     pNew->iInit = 0;

     return pNew;  
  }  	
/*-----------------------------------------------------------------------*/
  void  DeleteHistMemory(void *pData)
  {
     pHistMem self;
     
     self = (pHistMem)pData;
     assert(self);
     
     if(self->pDriv)
     {
          DeleteHistDriver(self->pDriv);
     }
     if(self->pDes)
     {
          DeleteDescriptor(self->pDes);
     }
     Fortify_CheckAllMemory();
     
     if(self->pCountInt)
     {
         free(self->pCountInt);
     }
     if(self->pCall)
     {
       DeleteCallBackInterface(self->pCall);
     }
     if(self->pOption)
     {
          DeleteStringDict(self->pOption);
     }     
     if(self->iLocalData)
     {
        free(self->iLocalData);
     }
     free(self);
  }
/*-------------------------------------------------------------------------*/
  int MakeHistMemory(SConnection *pCon, SicsInterp *pSics, void *pData,
                     int argc, char *argv[])
  {
     pHistMem pNew = NULL;
     char pBueffel[512];
     int iRet;
     
     /* check no of arguments */
     if(argc < 3)
     {
       sprintf(pBueffel,"ERROR: insufficient no of arguments to %s",argv[0]);
       SCWrite(pCon,pBueffel,eError);
       return 0;
     }
     
     /* make new HM */
     strtolower(argv[2]);
     pNew = CreateHistMemory(argv[2]);
     if(!pNew)
     {
       sprintf(pBueffel,"ERROR: failed to create Histogram Memory %s, driver %s may be invalid or no memory",
                         argv[1], argv[2]);
       SCWrite(pCon,pBueffel,eError);
       return 0;                         
     }
     
     /* install HM as command */
     iRet = AddCommand(pSics,argv[1],HistAction,DeleteHistMemory,(void *)pNew);
     if(!iRet)
     {
        sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[1]);
        SCWrite(pCon,pBueffel,eError);
        DeleteHistMemory((void *)pNew);
        return 0;
     }
     return 1;
  }
/*------------------------------------------------------------------------*/
  int HistGetOption(pHistMem self, char *name, char *result, int iLen)
  {
     assert(self);
     strtolower(name);
     return StringDictGet(self->pOption,name, result,iLen);
  }
/*-----------------------------------------------------------------------*/
  int HistSetOption(pHistMem self, char *name, char *value)
  {
    assert(self);
    self->iInit = 1;
    strtolower(name);
    return StringDictUpdate(self->pOption,name, value);
  }
/*-----------------------------------------------------------------------*/
 int HistConfigure(pHistMem self, SConnection *pCon, SicsInterp *pSics)
 {
    int iRet, iVal;
    char pValue[80];
    
    assert(self);
    assert(pCon);
    
    /* handle update intervall */
    iRet = StringDictGet(self->pOption,"update",pValue,79);
    assert(iRet); /* this is a programming error, we added it
                     when creating the histogram memory object
		  */
    iRet = Tcl_GetInt(pSics->pTcl,pValue,&iVal);
    if(iRet != TCL_OK)
    {
       SCWrite(pCon,"WARNING: invalid value for update ignored",
               eWarning);  
    }    
    else
    {
       self->iUpdateIntervall = iVal;
    }

    iRet = HistDriverConfig(self->pDriv,self->pOption,pCon);
    if(!iRet)
    {
       SCWrite(pCon,"ERROR: failed to configure histogram memory",eError);
       return 0;
    }
    iRet = self->pDriv->Configure(self->pDriv,pCon, self->pOption,pSics);
    if(!iRet)
    {
       SCWrite(pCon,"ERROR: failed to configure histogram memory",eError);
       return 0;
    }
    self->iLocalUpdate = 1;
    self->tLocal = 0;
    return 1;
 }
/*--------------------------------------------------------------------------*/
 float GetHistPreset(pHistMem self)
 {
     int i;
     float fVal;
     
     assert(self);
     
     fVal = self->pDriv->fCountPreset;
     if(self->pDriv->eCount == ePreset)
     {
       for(i = 0; i < self->iExponent; i++)
       {
         fVal /= 10.;
       }
     }
     return fVal;
 }   
/*--------------------------------------------------------------------------*/ 
 int SetHistPreset(pHistMem self, float fVal)
 {
     int i;
     
     assert(self);
     
     if(fVal < .0)
     {
        return 0;
     }
     if(GetHistCountMode(self) == ePreset)
     {
        for(i = 0; i < self->iExponent;i++)
        {
          fVal *= 10.;
        }
     }
     self->pDriv->fCountPreset = fVal;
     return 1;
 }   
/*--------------------------------------------------------------------------*/
 int GetHistDim(pHistMem self, int iDim[MAXDIM], int *nDim)
 {
     int i, myDim;
   
     assert(self);

     for(i = 0, myDim = 0; i < self->pDriv->nDim; i++)
     {
         if(self->pDriv->iDims[i] > 0)
         {
             iDim[i] = self->pDriv->iDims[i];
             myDim++;
         }
     }
     if(self->pDriv->eHistMode ==  eHTOF)
     {
       iDim[myDim] = self->pDriv->iTimeChan;
       myDim++;
     }
     *nDim = myDim;
     return 1;
 }
/*------------------------------------------------------------------------*/
 static long SumRow(int *iData, int iDataLength, int iStart, int iEnd)
 {
   int i;
   long lSum;

   if(iEnd > iDataLength)
   {
     return -1;
   }

   lSum = 0;
   for(i = iStart; i < iEnd; i++)
   {
     lSum += iData[i];
   }
   return lSum;
 } 
/*--------------------------------------------------------------------------*/
 long HistSum(pHistMem self, SConnection *pCon,
              int iStart[MAXDIM], int iEnd[MAXDIM])
 {
    int i, iDataDim[MAXDIM], nDim, iIndex;
    long lSum;
    char pBueffel[132];
    HistInt *iData = NULL;
    int iHistLength, iRet;

    assert(self);

    /* do some serious error checking */
    GetHistDim(self,iDataDim,&nDim);
    if(nDim <= 0)
    {
      SCWrite(pCon,"ERROR: Now data dimensions specified, cannot sum",eError);
      return -1;
    }
    for(i = 0; i < nDim; i++)
    {
      if( (iStart[i] < 0) || (iStart[i] > iDataDim[i]) )
      {
         sprintf(pBueffel,"ERROR: %d is out of data dimension range", 
                iStart[i]);
         SCWrite(pCon,pBueffel,eError);
         return -1;
      }
      if( (iEnd[i] < 0) || (iEnd[i] > iDataDim[i]) )
      {
         sprintf(pBueffel,"ERROR: %d is out of data dimension range", 
                iEnd[i]);
         SCWrite(pCon,pBueffel,eError);
         return -1;
      }
    }
 
    /* get histogram data */
    iHistLength = GetHistLength(self);
    iData = (HistInt *)malloc(iHistLength*sizeof(HistInt));
    if(!iData)
    {
      SCWrite(pCon,"ERROR: Failed to allocate data in sum", eError);
      return -1;
    }
    iRet = GetHistogram(self,pCon,0,0,iHistLength,iData,
                        iHistLength*sizeof(HistInt));
    if(!iRet)
    {
       SCWrite(pCon,"ERROR: could not get hold of data to sum",eError);
       return -1;
    }
    
    /* actually sum */
    switch(nDim)
    {
        case 1:
              lSum = SumRow(iData, iHistLength, iStart[0], iEnd[0]);
              break;
        case 2:
              lSum = 0;
              for(i = iStart[0]; i < iEnd[0]; i++)
	      {
                iIndex = i*iDataDim[1];
                lSum += SumRow(iData,iHistLength, 
                               iIndex+iStart[1], iIndex+iEnd[1]);
              }
              break;
        default:
              sprintf(pBueffel,
                "ERROR: summing in %d dimensions not yet implemented",
                 nDim);
              SCWrite(pCon,pBueffel,eError);
              lSum = -1;
              break;
    } 
    free(iData);
    return lSum;
 }
/*---------------------------------------------------------------------------*/
 CounterMode GetHistCountMode(pHistMem self)
 {
   assert(self);
   return self->pDriv->eCount;
 }
/*--------------------------------------------------------------------------*/
 int SetHistCountMode(pHistMem self, CounterMode eNew)
 {
    int i;
    
    assert(self);
    if(eNew == self->pDriv->eCount)
    {
      return 1;
    }
    
    if(eNew == eTimer)
    {
      for(i = 0; i < self->iExponent; i++)
      {
         self->pDriv->fCountPreset /= 10.;
      } 
    }
    if(eNew == ePreset)
    {
      for(i = 0; i < self->iExponent; i++)
      {
         self->pDriv->fCountPreset *= 10.;
      } 
    }
    self->pDriv->eCount = eNew;
    return 1;

 } 
/*--------------------------------------------------------------------------*/
 long GetHistMonitor(pHistMem self, int i, SConnection *pCon)
 {
   assert(self);
   return self->pDriv->GetMonitor(self->pDriv,i,pCon);
 } 
/*-------------------------------------------------------------------------*/
 const float *GetHistTimeBin(pHistMem self, int *iLength)
 {
    assert(self);
    *iLength = self->pDriv->iTimeChan;
    return self->pDriv->fTime; 
 } 
/*-------------------------------------------------------------------------*/
 int GetHistLength(pHistMem self)
 {
    assert(self);
    
    return self->pDriv->iRank*self->pDriv->iLength;
 } 
/*--------------------------------------------------------------------------*/
 float GetHistCountTime(pHistMem self, SConnection *pCon)
 {
   assert(self);
   return self->pDriv->GetTime(self->pDriv,pCon);
 } 
/*-------------------------------------------------------------------------*/
 int HistDoCount(pHistMem self, SConnection *pCon)
 {
    assert(self);

    /* send a COUNTSTART event */
    InvokeCallBack(self->pCall,COUNTSTART,pCon);

    /* start */
    return StartDevice(GetExecutor(),"HistogramMemory", self->pDes, self,
                       pCon, self->pDriv->fCountPreset);
 }
/*-----------------------------------------------------------------------*/
 int HistBlockCount(pHistMem self, SConnection *pCon)
 {
    int iRet;
    
    assert(self);
    
    /* start counting */
    iRet = StartDevice(GetExecutor(),"HistogramMemory", self->pDes, self,
                       pCon, self->pDriv->fCountPreset);
    if(!iRet)
    {
      /* error has already been reported */
      return 0;
    }
    
    /* send a COUNTSTART event */
    InvokeCallBack(self->pCall,COUNTSTART,pCon);
    
     /* wait till end */
     iRet = Wait4Success(GetExecutor());
     if(iRet == DEVINT)
     {
       SCWrite(pCon,"Counting aborted due to Interrupt",eStatus);
     }
     else if(iRet == DEVERROR)
     {
       SCWrite(pCon,"Counting finished with Problems",eStatus);
       iRet = 1; 
     }
     else
     {
       SCWrite(pCon,"Counting finished",eStatus);
       iRet = 1;
     }

     /* whatever happened, send a COUNTEND event */
     InvokeCallBack(self->pCall,COUNTEND,NULL);
     
     return iRet;

 }
/*-------------------------------------------------------------------------*/
 int SetHistogram(pHistMem self, SConnection *pCon, 
                  int i, int iStart, int iEnd, HistInt *lData)
 {
    int ii, iErr, iRet;
    char pBueffel[512], pError[80];
    
    assert(self);

    if(!self->iInit)
    {
         SCWrite(pCon,"ERROR: histogram memory not initialised",eError);
         return 0;
    }

    /* try at least three times */
      for(ii = 0; ii < 3; ii++)
      {
             iRet = self->pDriv->SetHistogram(self->pDriv,pCon,
                                              i,iStart,iEnd,lData);
             if(iRet == OKOK)
             {
               self->iLocalUpdate = 1;
               self->tLocal = 0;
               self->pDriv->iUpdate = 0;
               return 1;
             }       
             else
             {
                iRet = self->pDriv->GetError(self->pDriv,&iErr,pError,79);
                sprintf(pBueffel,"ERROR: %s ",pError);
                SCWrite(pCon,pBueffel,eError);
                iRet = self->pDriv->TryAndFixIt(self->pDriv,iErr);
                if(iRet == COTERM)
                {
                  return 0;
                } 
             }
      }
      return 0;   
 }
/*-------------------------------------------------------------------------*/
 int GetHistogram(pHistMem self, SConnection *pCon, 
                  int i, int iStart, int iEnd, HistInt *lData, int iDataLen)
 {
    int ii, iErr, iRet, iCopy;
    char pBueffel[512], pError[80];
    HistInt *lHist = NULL;
    
    assert(self);

    if(!self->iInit)
    {
         SCWrite(pCon,"ERROR: histogram memory not initialised",eError);
         return 0;
    }

    /* get the full histogram if an update is needed */
    if( (self->iLocalUpdate) && (time(NULL) > self->tLocal) ) 
    {
#ifdef LOADDEBUG
        fprintf(stdout,"Getting new histogram from HM\n");
#endif
	/* check data allocation */
        if(self->iLocalLength != self->pDriv->iLength)
        {
          if(self->iLocalData)
          {
             free(self->iLocalData);
             self->iLocalData = NULL;
          }
          self->iLocalData = (HistInt *)malloc(
                                 self->pDriv->iLength*sizeof(HistInt));
          if(!self->iLocalData)
          {
            SCWrite(pCon,"ERROR: failed to allocate data in GetHistogram",
                    eError);
            return 0;
          }
          self->iLocalLength = self->pDriv->iLength;
          memset(self->iLocalData,0,self->iLocalLength*sizeof(HistInt));
        }
        /* try at least three times */
        for(ii = 0; ii < 3; ii++)
        {
              iRet = self->pDriv->GetHistogram(self->pDriv,pCon,
                                              i,0,self->iLocalLength,
                                              self->iLocalData);
               if(iRet == OKOK)
               {
                  self->iLocalUpdate = 0;
                  self->tLocal = time(NULL) + self->iUpdateIntervall;
                  break;
               }       
               else
               {
                  iRet = self->pDriv->GetError(self->pDriv,&iErr,pError,79);
                  sprintf(pBueffel,"ERROR: %s ",pError);
                  SCWrite(pCon,pBueffel,eError);
                  iRet = self->pDriv->TryAndFixIt(self->pDriv,iErr);
                  if(iRet == COTERM)
                  {
                    return 0;
                  } 
               }
	}
     }

    /* copy from buffer if there and updated */
    if(self->iLocalData)
    {
#ifdef LOADDEBUG
        fprintf(stdout,"Copying histogram data from memory\n");
#endif
        lHist = self->iLocalData + iStart;
        if(iEnd*sizeof(HistInt) < iDataLen)
        {
           iCopy = iEnd;
        }
        else
        {
          iCopy = iDataLen/sizeof(HistInt); 
        }
        memcpy(lData,lHist,iCopy*sizeof(HistInt));
    }
    return 1;
 }
/*-----------------------------------------------------------------------*/
 HistInt *GetHistogramPointer(pHistMem self, SConnection *pCon)
 {
    int ii, iErr, iRet, iCopy;
    char pBueffel[512], pError[80];
    HistInt *lHist = NULL;
    
    assert(self);

    if(!self->iInit)
    {
         SCWrite(pCon,"ERROR: histogram memory not initialised",eError);
         return NULL;
    }

    if(self->iLocalData == NULL)
    {
          self->iLocalUpdate = 1;
          self->tLocal = 0;
    }

    /* get the full histogram if an update is needed */
    if( (self->iLocalUpdate) && (time(NULL) > self->tLocal) )
    {
#ifdef LOADDEBUG
        fprintf(stdout,"Getting new histogram from HM\n");
#endif
	/* check data allocation */
        if(self->iLocalLength != self->pDriv->iLength)
        {
          if(self->iLocalData)
          {
             free(self->iLocalData);
             self->iLocalData = NULL;
          }
          self->iLocalData = (HistInt *)malloc(
                                 self->pDriv->iLength*sizeof(HistInt));
          if(!self->iLocalData)
          {
            SCWrite(pCon,"ERROR: failed to allocate data in GetHistogram",
                    eError);
            return NULL;
          }
          self->iLocalLength = self->pDriv->iLength;
          memset(self->iLocalData,0,self->iLocalLength*sizeof(HistInt));
        }
        /* try at least three times */
        for(ii = 0; ii < 3; ii++)
        {
              iRet = self->pDriv->GetHistogram(self->pDriv,pCon,
                                              0,0,self->iLocalLength,
                                              self->iLocalData);
               if(iRet == OKOK)
               {
                  self->iLocalUpdate = 0;
                  self->tLocal = time(NULL) + self->iUpdateIntervall;
                  break;
               }       
               else
               {
                  iRet = self->pDriv->GetError(self->pDriv,&iErr,pError,79);
                  sprintf(pBueffel,"ERROR: %s ",pError);
                  SCWrite(pCon,pBueffel,eError);
                  iRet = self->pDriv->TryAndFixIt(self->pDriv,iErr);
                  if(iRet == COTERM)
                  {
                    return NULL;
                  } 
               }
	}
     }

#ifdef LOADDEBUG
        fprintf(stdout,"Copying histogram data from memory\n");
#endif
     return self->iLocalData;
 }
/*--------------------------------------------------------------------------*/
 int PresetHistogram(pHistMem self, SConnection *pCon, HistInt lVal)
 {
    int ii, iErr, iRet;
    char pBueffel[512], pError[80];
    
    assert(self);

    if(!self->iInit)
    {
      SCWrite(pCon,"ERROR: histogram memory not initialised",eError);
      return 0;
    }

    /* try at least three times */
      for(ii = 0; ii < 3; ii++)
      {
             iRet = self->pDriv->Preset(self->pDriv,pCon,lVal);
             if(iRet == OKOK)
             {
               self->pDriv->iUpdate = 0;
               self->iLocalUpdate = 1;
               self->tLocal = 0;
               return 1;
             }       
             else
             {
                iRet = self->pDriv->GetError(self->pDriv,&iErr,pError,79);
                sprintf(pBueffel,"ERROR: %s ",pError);
                SCWrite(pCon,pBueffel,eError);
                iRet = self->pDriv->TryAndFixIt(self->pDriv,iErr);
                if(iRet == COTERM)
                {
                  return 0;
                } 
             }
      }
      return 0;   
 } 
/*-----------------------------------------------------------------------*/
  static int HMCountInterest(int iEvent, void *pEvent, void *pUser)
  {
     SConnection *pCon = NULL;
     char pBueffel[512];
     
     if(iEvent == COUNTSTART)
     {     
       pCon = (SConnection *)pUser;
       assert(pCon);
       SCWrite(pCon,"HMCOUNTSTART",eWarning);
       return 1;        
     }
     else if(iEvent == COUNTEND)
     {
       pCon = (SConnection *)pUser;
       assert(pCon);
       SCWrite(pCon,"HMCOUNTEND",eWarning);
       return 1;        
     }
     return 0;    
  }  
/*--------------------------------------------------------------------------*/
   int HistAction(SConnection *pCon, SicsInterp *pSics, void *pData,
                     int argc, char *argv[])
   {
      pHistMem self = NULL;
      char pBueffel[512], pNumber[20];
      int iaStart[MAXDIM], iaEnd[MAXDIM];
      Tcl_DString tResult;
      int iRet, iVal;
      char *pBuf = NULL, *pPtr;
      float fVal;
      long lVal;
      HistInt *lData = NULL;
      int iStart, iEnd, iNum, i;
      CounterMode eCount;
      char *pMode[] = {
                    "timer",
                    "monitor",
                    NULL
                   };
      double dStart, dStep;
      int nDim, iSwitch;
      long lID;

      
      assert(pCon);
      assert(pSics);
      assert(pData);
      
      self = (pHistMem)pData;
      
      /* check arguments */
      if(argc < 2)
      {
        sprintf(pBueffel,"ERROR: no arguments specified to %s", argv[0]);
        SCWrite(pCon,pBueffel,eError);
        return 0;
      }
      
      /* configure command */
      strtolower(argv[1]);
      if(strcmp(argv[1],"interest") == 0)
      {
         lID = RegisterCallback(self->pCall, COUNTSTART, HMCountInterest,
                                                    pCon, NULL);
         SCRegister(pCon,pSics, self->pCall,lID);
         lID = RegisterCallback(self->pCall, COUNTEND, HMCountInterest,
                                                    pCon, NULL);
         SCRegister(pCon,pSics, self->pCall,lID);
         SCSendOK(pCon);
         return 1;
      }
      else if(strcmp(argv[1],"configure") == 0)
      {
         /* enough arguments ? */
         if(argc < 4)
         {
           if(argc < 3)
           {
             sprintf(pBueffel,"ERROR: not enough arguments to %s configure",
                     argv[0]);
             SCWrite(pCon,pBueffel,eError);
             return 0; 
           }
           else /* get value case */
           {
             strtolower(argv[2]);
             iRet = HistGetOption(self,argv[2],NULL,0);
             if(!iRet)
             {
                sprintf(pBueffel,"ERROR: option %s not known", argv[2]);
                SCWrite(pCon,pBueffel,eError);
                return 0;
             }
             pBuf = (char *)malloc((iRet+60)*sizeof(char));
             if(!pBuf)
             {
               SCWrite(pCon,"ERROR: no memory in HistAction",eError);
               return 0;
             }
             memset(pBuf,0,iRet+60);
             HistGetOption(self,argv[2],pBuf,iRet);
             sprintf(pBueffel,"%s.%s = %s",argv[0],argv[2],pBuf);
             SCWrite(pCon,pBueffel,eValue);
             free(pBuf);
             return 1;
           }          
         }
         /* do it */
         Arg2Text(argc - 3, &argv[3],pBueffel, 511);
         /* authorise */
         if(!SCMatchRights(pCon,usMugger))
         {
            sprintf(pBueffel,"ERROR: you need to be manager in order to configure %s",
                    argv[0]);
            SCWrite(pCon,pBueffel,eError);
            return 0;        
         }
         strtolower(argv[2]);
         iRet = HistSetOption(self,argv[2],pBueffel);
         if(!iRet)
         {
           sprintf(pBueffel,"ERROR: option %s not known", argv[2]);
           SCWrite(pCon,pBueffel,eError);
           return 0;
         }
      }
      else if(strcmp(argv[1],"preset") == 0) /* preset */
      {
        if(argc < 3) /* get value */
        {
           fVal = GetHistPreset(self);
           sprintf(pBueffel,"%s.preset = %f",argv[0],fVal);
           SCWrite(pCon,pBueffel,eValue);
           return 1;
        }
        else /* set case */
        {
          fVal = atof(argv[2]);
          if(!SCMatchRights(pCon,self->iAccess))
          {
            SCWrite(pCon,"ERROR: you are not priviledged for attempted operation",eError);
            return 0;
          }
          iRet = SetHistPreset(self,fVal);
          SCSendOK(pCon);
          return 1;
        }
      }
      else if(strcmp(argv[1],"exponent") == 0) /* preset */
      {
        if(argc < 3) /* get value */
        {
           sprintf(pBueffel,"%s.exponent = %d",argv[0],self->iExponent);
           SCWrite(pCon,pBueffel,eValue);
           return 1;
        }
        else /* set case */
        {
          if(!SCMatchRights(pCon,self->iAccess))
          {
            SCWrite(pCon,"ERROR: you are not priviledged for attempted operation",eError);
            return 0;
          }
          self->iExponent = atoi(argv[2]);
          SCSendOK(pCon);
          return 1;
        }
      }
      else if(strcmp(argv[1],"countmode") == 0) /* countmode */
      {
        if(argc < 3) /* get value */
        {
           eCount = GetHistCountMode(self);
           sprintf(pBueffel,"%s.CountMode = %s",argv[0],pMode[eCount]);
           SCWrite(pCon,pBueffel,eValue);
           return 1;
        }
        else /* set case */
        {
          strtolower(argv[2]);
          if(!SCMatchRights(pCon,self->iAccess))
          {
            SCWrite(pCon,"ERROR: you are not priviledged for attempted operation",eError);
            return 0;
          }
          if(strcmp(argv[2],"timer") == 0)
          {
            eCount = eTimer;
          }
          else if(strcmp(argv[2],"monitor") == 0)
          {
            eCount = ePreset;
          }
          else
          {
            sprintf(pBueffel,"ERROR: %s invalid as CountMode",argv[2]);
            SCWrite(pCon,pBueffel,eError);
            return 0;
          }
          iRet = SetHistCountMode(self,eCount);
          SCSendOK(pCon);
          return 1;
        }
      
      }
      else if(strcmp(argv[1],"init") == 0)
      {
        if(SCMatchRights(pCon,usMugger))
        {
           iRet = HistConfigure(self,pCon,pSics);
           if(iRet)
           {
             self->iInit = 1;
           }
           else
           {
             self->iInit = 0;
           }
           return iRet;
        }
        else
        {
            SCWrite(pCon,"ERROR: you are not privileged for attempted operation",eError);
            return 0;
        }
      }
      else if(strcmp(argv[1],"count") == 0)
      {
        if(SCMatchRights(pCon,self->iAccess))
        {
           if(IsCounting(pServ->pExecutor))
	   {
               SCWrite(pCon,"WARNING: already counting!",eWarning);
               return 1;
           }
           iRet = HistDoCount(self,pCon);
           if(iRet == 1)
           {
             SCSendOK(pCon);
           }
           return iRet;
        }
        else
        {
            SCWrite(pCon,"ERROR: you are not privileged for attempted operation",eError);
            return 0;
        }
      }
/* count in blocking mode */      
      else if(strcmp(argv[1],"countblock") == 0)
      {
        if(SCMatchRights(pCon,self->iAccess))
        {
           iRet = HistBlockCount(self,pCon);
           if(iRet == 1)
           {
             SCSendOK(pCon);
           }
           return iRet;
        }
        else
        {
            SCWrite(pCon,"ERROR: you are not privileged for attempted operation",eError);
            return 0;
        }
      }
      else if(strcmp(argv[1],"initval") == 0) /* initialize to a value */
      {
          /* check user rights */
          if(!SCMatchRights(pCon,self->iAccess))
          {
            SCWrite(pCon,"ERROR: you are not priviledged for attempted operation",eError);
            return 0;
          }
          
          /* enough arguments */
          if(argc < 3)
          {
            sprintf(pBueffel,"ERROR: insufficient number of arguments to %s %s",
                    argv[0], argv[1]);
            SCWrite(pCon,pBueffel,eError);
            return 0;        
          }
          lVal = atoi(argv[2]);
          iRet = PresetHistogram(self,pCon,lVal);
          if(iRet)
          {
            SCSendOK(pCon);
          }
          return iRet;
      }
      else if(strcmp(argv[1],"get") == 0) /* get a histogram */
      {
        /* check parameters, first required: no of Hist */
        if(argc < 3)
        {
            sprintf(pBueffel,"ERROR: insufficient number of arguments to %s %s",
                    argv[0], argv[1]);
            SCWrite(pCon,pBueffel,eError);
            return 0;        
         }
         iNum = atoi(argv[2]);

         /* check iNum */
         if( (iNum < 0) || (iNum > self->pDriv->iRank))
         {
           sprintf(pBueffel,"ERROR: requested histogram no %d out of range",
                   iNum);
           SCWrite(pCon,pBueffel,eError);
           return 0;        
         }
         
         /* optional iStart, default 0 */
         iStart = 0;
         if(argc > 3 )
         {
           iStart = atoi(argv[3]);
         }
         
         /* check iStart */
         if(iStart < 0)
         {
            SCWrite(pCon,"WARNING: Invalid start position defaulted to 0",eWarning); 
            iStart = 0;
         }
         
         /* optional iEnd, default to maximum */
         iEnd = self->pDriv->iLength;
         if(argc > 4)
         {
           iEnd = atoi(argv[4]);
         }
         
         /* check iEnd */
         if(iEnd > self->pDriv->iLength)
         {
           iEnd = self->pDriv->iLength;
           SCWrite(pCon,
           "WARNING: invalid end parameter reset to max ",eWarning);
         }
         
         /* allocate data storage and get it */
         lData = (HistInt *)malloc(iEnd*sizeof(HistInt));
         if(!lData)
         {
           SCWrite(pCon,"ERROR: no memory in HistAction/get",eError);
           return 0;
         }
         memset(lData,0,iEnd*sizeof(HistInt));
         iRet = GetHistogram(self,pCon,iNum,iStart,iEnd,
                             lData,iEnd*sizeof(long));
         if(!iRet)
         {
           sprintf(pBueffel,"ERROR: cannot retrieve histogram %d",iNum);
           SCWrite(pCon,pBueffel,eError);
           free(lData);
           return 0;
         }                    
         
         /* OK, got it, convert to text using Tcl's Dstring for lazyness */
         Tcl_DStringInit(&tResult);
         Tcl_DStringAppend(&tResult,"Histogram =",-1);
         for(i = 0; i < iEnd - iStart; i++)
         {
            sprintf(pNumber," %d",lData[i]);
            Tcl_DStringAppend(&tResult,pNumber,-1);
         }
         
         /* Write it */
         SCWrite(pCon,Tcl_DStringValue(&tResult),eValue);
         
         /* clean up and go */
         free(lData);
         Tcl_DStringFree(&tResult);
         return 1;          
      }
/*-------- get uuencoded */
      else if(strcmp(argv[1],"uuget") == 0) /* get a histogram */
      {
        /* check parameters, first required: no of Hist */
        if(argc < 3)
        {
            sprintf(pBueffel,"ERROR: insufficient number of arguments to %s %s",
                    argv[0], argv[1]);
            SCWrite(pCon,pBueffel,eError);
            return 0;        
         }
         iNum = atoi(argv[2]);

         /* check iNum */
         if( (iNum < 0) || (iNum > self->pDriv->iRank))
         {
           sprintf(pBueffel,"ERROR: requested histogram no %d out of range",
                   iNum);
           SCWrite(pCon,pBueffel,eError);
           return 0;        
         }
         
         /* optional iStart, default 0 */
         iStart = 0;
         if(argc > 3 )
         {
           iStart = atoi(argv[3]);
         }
         
         /* check iStart */
         if(iStart < 0)
         {
            SCWrite(pCon,"WARNING: Invalid start position defaulted to 0",eWarning); 
            iStart = 0;
         }
         
         /* optional iEnd, default to maximum */
         iEnd = self->pDriv->iLength;
         if(argc > 4)
         {
           iEnd = atoi(argv[4]);
         }
         
         /* check iEnd */
         if(iEnd > self->pDriv->iLength)
         {
           iEnd = self->pDriv->iLength;
           SCWrite(pCon,
           "WARNING: invalid end parameter reset to max ",eWarning);
         }
         
         /* allocate data storage and get it */
         lData = (HistInt *)malloc((iEnd+1)*sizeof(HistInt));
         if(!lData)
         {
           SCWrite(pCon,"ERROR: no memory in HistAction/get",eError);
           return 0;
         }
         memset(lData,0,(iEnd+1)*sizeof(HistInt));
         iRet = GetHistogram(self,pCon,iNum,iStart,iEnd,
                             &lData[1],iEnd*sizeof(HistInt));
         if(!iRet)
         {
           sprintf(pBueffel,"ERROR: cannot retrieve histogram %d",iNum);
           SCWrite(pCon,pBueffel,eError);
           free(lData);
           return 0;
         }                    
         /* lData[0] is the length of the histogram */
         lData[0] = iEnd;
         
         /* convert to network byte order */
         for(i = 0; i < iEnd+1; i++)
         {
           lData[i] = htonl(lData[i]);
         }
         /* Write it */
         SCWriteUUencoded(pCon,"SicsHistogram",lData,(iEnd+1)*sizeof(HistInt));
         
         /* clean up and go */
         free(lData);
         return 1;          
      }
   /* retrive time binning */   
      else if(strcmp(argv[1],"timebin") == 0)
      {
         Tcl_DStringInit(&tResult);
         Tcl_DStringAppend(&tResult,"histogram.timebins = ",-1);
         for(i = 0; i < self->pDriv->iTimeChan; i++)
         {
           sprintf(pBueffel," %8.2f", self->pDriv->fTime[i]);
           Tcl_DStringAppend(&tResult,pBueffel,-1);
         }
         /* Write it */
         SCWrite(pCon,Tcl_DStringValue(&tResult),eValue);
         
         /* clean up and go */
         Tcl_DStringFree(&tResult);
         return 1;          
      }
   /* generate time binning */   
      else if(strcmp(argv[1],"genbin") == 0)
      {
          if(!SCMatchRights(pCon,usMugger))
          {
            SCWrite(pCon,"ERROR: yoy are not authorised for this operation",eError);
            return 0;
          }
          if(argc < 5)
          {
            SCWrite(pCon,"ERROR: not enough aguments to genbin",eError);
            return 0;
          }
          iRet = Tcl_GetDouble(pSics->pTcl,argv[2],&dStart);
          if(iRet != TCL_OK)
          {
            sprintf(pBueffel,"ERROR: Failed to convert %s to number",argv[2]);
            SCWrite(pCon,pBueffel,eError);
            return 0;
          }
          iRet = Tcl_GetDouble(pSics->pTcl,argv[3],&dStep);
          if(iRet != TCL_OK)
          {
            sprintf(pBueffel,"ERROR: Failed to convert %s to number",argv[2]);
            SCWrite(pCon,pBueffel,eError);
            return 0;
          }
          iRet = Tcl_GetInt(pSics->pTcl,argv[4],&iNum);
          if(iRet != TCL_OK)
          {
            sprintf(pBueffel,"ERROR: Failed to convert %s to number",argv[2]);
            SCWrite(pCon,pBueffel,eError);
            return 0;
          }
          /* do it */
          if(iNum >= MAXCHAN)
          {
            SCWrite(pCon,"ERROR: number of requested time bins exceeds maximum permissible number",
                    eError);
            return 0;        
          }
          for(i = 0; i < iNum; i++)
          {
            self->pDriv->fTime[i] = dStart + i* dStep;
          }
          self->pDriv->iTimeChan = iNum;
          self->iInit = 0;
          self->pDriv->iLength = 1;
          for(i = 0; i < self->pDriv->iRank; i++)
          {
            self->pDriv->iLength *= self->pDriv->iDims[i];
          }
          self->pDriv->iLength *= self->pDriv->iTimeChan;
          SCSendOK(pCon);
          return 1;          
      }
  /* set a time bin */    
      else if(strcmp(argv[1],"setbin") == 0)
      {
          if(!SCMatchRights(pCon,usMugger))
          {
            SCWrite(pCon,"ERROR: yoy are not authorised for this operation",eError);
            return 0;
          }
          if(argc < 4)
          {
            SCWrite(pCon,"ERROR: not enough aguments to setbin",eError);
            return 0;
          }
          iRet = Tcl_GetInt(pSics->pTcl,argv[2],&iNum);
          if(iRet != TCL_OK)
          {
            sprintf(pBueffel,"ERROR: Failed to convert %s to number",argv[2]);
            SCWrite(pCon,pBueffel,eError);
            return 0;
          }
          iRet = Tcl_GetDouble(pSics->pTcl,argv[3],&dStep);
          if(iRet != TCL_OK)
          {
            sprintf(pBueffel,"ERROR: Failed to convert %s to number",argv[2]);
            SCWrite(pCon,pBueffel,eError);
            return 0;
          }
          if( (iNum < 0) || (iNum > MAXCHAN) )
          {
             SCWrite(pCon,"ERROR: requested time bin out or permissible range",eError);
             return 0;
          } 
          self->pDriv->fTime[iNum] = dStep;
          if(iNum > self->pDriv->iTimeChan)
          {
            self->pDriv->iTimeChan = iNum;
            self->pDriv->iLength = 1;
            for(i = 0; i < self->pDriv->iRank; i++)
            {
              self->pDriv->iLength *= self->pDriv->iDims[i];
            }
            self->pDriv->iLength *= self->pDriv->iTimeChan;
          }
          self->iInit = 0;
          SCSendOK(pCon);
          return 1;                  
      }
    /* clear time bin info */  
      else if(strcmp(argv[1],"clearbin") == 0)
      {
         self->pDriv->iTimeChan = 0;
         self->iInit = 1;
         SCSendOK(pCon);
      }
/*-------- sum */
      else if(strcmp(argv[1],"sum") == 0)
      {
	  /* read following arguments as ints and put them 
             into the iStart and iEnd array in succession.
             But first check if we have an even number.
	  */        
          if( ((argc-2) % 2) || (argc-2) == 0)
          {
             SCWrite(pCon,
               "ERROR: need start and end for each dimension",
               eError);
             return 0;
          }
          nDim = 0;
          iSwitch = 0;
          for(i = 0; i < argc -2; i++)
          {
             iRet = Tcl_GetInt(pSics->pTcl,argv[i+2],&iVal);
             if(iSwitch)
             {
               iaEnd[nDim] = iVal;
               nDim++;
               iSwitch = 0;    
             }
             else
             {
                iSwitch = 1;
                iaStart[nDim] = iVal;
             }
          }
          lVal = HistSum(self,pCon,iaStart,iaEnd);
          if(lVal < 0)
          {
            SCWrite(pCon,"ERROR: summing failed",eError);
            return 0;
          }
          sprintf(pBueffel,"%s.sum = %ld",argv[0],lVal);
          SCWrite(pCon,pBueffel,eValue);
          return 1;
      }
      else
      {
        sprintf(pBueffel,"ERROR: %s does not understand command %s",
                argv[0], argv[1]);
        SCWrite(pCon, pBueffel,eError);
        return 0;        
      }
   }









