diff --git a/SCinter.c b/SCinter.c index 193b2055..52d10f11 100644 --- a/SCinter.c +++ b/SCinter.c @@ -57,6 +57,7 @@ #include #include #include +#include #include "fortify.h" #include "sics.h" #include "splitter.h" @@ -151,6 +152,7 @@ static void freeList(int listID); pNew->pData = pData; pNew->pNext = NULL; pNew->startupOnly = startupOnly; + pNew->stat = StatisticsNew(pBueffel); /* find end of list */ tail = NULL; @@ -232,10 +234,14 @@ static void freeList(int listID); { pInterp->pCList = pVictim->pNext; } + if (pVictim->stat) { + StatisticsKill(pVictim->stat); + } free(pVictim); return 1; } + #define MAXLEN 256 #define MAXCOM 50 extern char *stptok(char *s, char *tok, unsigned int toklen, char *brk); @@ -252,6 +258,7 @@ extern char *SkipSpace(char *pPtr); char *pPtr; char **argv = NULL; commandContext comCon; + Statistics *old; assert(self); @@ -307,7 +314,9 @@ extern char *SkipSpace(char *pPtr); Tcl_ResetResult((Tcl_Interp *)self->pTcl); MacroPush(pCon); pCon->conStatus = 0; + old = StatisticsBegin(pCommand->stat); iRet = pCommand->OFunc(pCon, self, pCommand->pData, argc, argv); + StatisticsEnd(old); /* If a task is registered with the dev exec then conStatus is HWBusy*/ if (pCon->conStatus != HWBusy) { comCon = SCGetContext(pCon); @@ -444,29 +453,40 @@ extern char *SkipSpace(char *pPtr); void DeleteInterp(SicsInterp *self) { CommandList *pCurrent = NULL; - CommandList *pTemp; + CommandList *pTemp, *tail; Tcl_Interp *pTcl = NULL; int i; assert(self); self->iDeleting = 1; - /* delete Commandlist */ + /* find end of list */ + tail = NULL; pCurrent = self->pCList; - while(pCurrent) + while(pCurrent != NULL) { - if(pCurrent->KFunc) + tail = pCurrent; + pCurrent = pCurrent->pNext; + } + + /* delete Commandlist (reversed order) */ + if (tail) { + pCurrent = tail; + while(pCurrent) { - pCurrent->KFunc(pCurrent->pData); + if(pCurrent->KFunc) + { + pCurrent->KFunc(pCurrent->pData); + } + if(pCurrent->pName) + { + /* printf("Deleting %s\n",pCurrent->pName); */ + free(pCurrent->pName); + } + pTemp = pCurrent->pPrevious; + free(pCurrent); + pCurrent = pTemp; } - if(pCurrent->pName) - { - /* printf("Deleting %s\n",pCurrent->pName); */ - free(pCurrent->pName); - } - pTemp = pCurrent->pNext; - free(pCurrent); - pCurrent = pTemp; } FreeAliasList(&self->AList); /* M.Z. */ diff --git a/SCinter.h b/SCinter.h index dacaf28d..9bb8c3ff 100644 --- a/SCinter.h +++ b/SCinter.h @@ -10,6 +10,7 @@ #ifndef SICSINTERPRETER #define SICSINTERPRETER #include "Scommon.h" +#include "statistics.h" #include /* M.Z. */ #include "definealias.i" @@ -31,6 +32,7 @@ typedef struct __Clist { struct __Clist *pNext; struct __Clist *pPrevious; int startupOnly; + Statistics *stat; } CommandList; typedef struct __SINTER diff --git a/access.c b/access.c index 860c962a..110947e9 100644 --- a/access.c +++ b/access.c @@ -3,8 +3,9 @@ Mark Koennecke, November 1996 ----------------------------------------------------------------------------*/ -#ifndef PCODE -#define PCODE +#include +#include +#include static char *aCode[] = { "internal", @@ -13,4 +14,19 @@ "spy", NULL }; static int iCodes = 4; -#endif +/*--------------------------------------------------------------------------*/ +int decodeSICSPriv(char *privText){ + int code = 0; + + strtolower(privText); + while(aCode[code] != NULL){ + if(strcmp(aCode[code], privText) == 0){ + return code; + } + code++; + } + if(code >= iCodes){ + return -1; + } + return -1; +} diff --git a/choco.c b/choco.c index 4df78fc8..65ca8d01 100644 --- a/choco.c +++ b/choco.c @@ -99,7 +99,7 @@ if(argc < 2) { - sprintf(pMessage, "ERROR: Ragument required for %s",argv[0]); + sprintf(pMessage, "ERROR: argument required for %s",argv[0]); SCWrite(pCon,pMessage,eError); return 0; } @@ -149,7 +149,7 @@ return 0; } /*----------------------------------------------------------------------*/ - static void KillChoco(void *pData) + void KillChoco(void *pData) { pChoco self = NULL; diff --git a/choco.h b/choco.h index 08be2342..94bbe7e2 100644 --- a/choco.h +++ b/choco.h @@ -19,6 +19,7 @@ pCodri CHGetDriver(pChoco self); int CHList(pChoco self, SConnection *pCon, char *name); /*------------------------------------------------------------------------*/ + void KillChoco(void *pData); int ChocoAction(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); int ChocoFactory(SConnection *pCon, SicsInterp *pSics, void *pData, diff --git a/choco.tex b/choco.tex index 2dc57d2c..d1e00149 100644 --- a/choco.tex +++ b/choco.tex @@ -85,7 +85,7 @@ controller driver. \item[SetPar] tries to set the parameter parname to the value fValue. The last is floating point which covers the frequent occurence of numeric values. -\item[SetPar2] The same as SetPar but uses test string as input for +\item[SetPar2] The same as SetPar but uses text string as input for parameter setting. \item[GetPar] retrieves the parameter parname formatted as text. The value is put into the buffer pBuffer. iBufLen is the maximum number of @@ -129,6 +129,7 @@ $\langle$chocoint {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@ pCodri CHGetDriver(pChoco self);@\\ \mbox{}\verb@ int CHList(pChoco self, SConnection *pCon, char *name);@\\ \mbox{}\verb@/*------------------------------------------------------------------------*/@\\ +\mbox{}\verb@ void KillChoco(void *pData);@\\ \mbox{}\verb@ int ChocoAction(SConnection *pCon, SicsInterp *pSics, void *pData,@\\ \mbox{}\verb@ int argc, char *argv[]);@\\ \mbox{}\verb@ int ChocoFactory(SConnection *pCon, SicsInterp *pSics, void *pData,@\\ @@ -366,8 +367,7 @@ $\langle$evada {\footnotesize ?}$\rangle\equiv$ \subsubsection{To Do} This scheme seems to be quite promising for handling many SICS objects. The following enhancements could be considered. Allow to set -certain primitive parameters without a drivable interface. And add an -adapter for an environment variable in the controller. +certain primitive parameters without a drivable interface. diff --git a/choco.w b/choco.w index 10b6be55..2f79a9ee 100644 --- a/choco.w +++ b/choco.w @@ -72,7 +72,7 @@ controller driver. \item[SetPar] tries to set the parameter parname to the value fValue. The last is floating point which covers the frequent occurence of numeric values. -\item[SetPar2] The same as SetPar but uses test string as input for +\item[SetPar2] The same as SetPar but uses text string as input for parameter setting. \item[GetPar] retrieves the parameter parname formatted as text. The value is put into the buffer pBuffer. iBufLen is the maximum number of @@ -111,6 +111,7 @@ includes: pCodri CHGetDriver(pChoco self); int CHList(pChoco self, SConnection *pCon, char *name); /*------------------------------------------------------------------------*/ + void KillChoco(void *pData); int ChocoAction(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); int ChocoFactory(SConnection *pCon, SicsInterp *pSics, void *pData, @@ -267,8 +268,7 @@ controller driver: \subsubsection{To Do} This scheme seems to be quite promising for handling many SICS objects. The following enhancements could be considered. Allow to set -certain primitive parameters without a drivable interface. And add an -adapter for an environment variable in the controller. +certain primitive parameters without a drivable interface. diff --git a/conman.c b/conman.c index 26d92edd..c341ec79 100644 --- a/conman.c +++ b/conman.c @@ -65,6 +65,7 @@ #include "uubuffer.h" #include "commandlog.h" #include "stptok.h" +#include "sicshipadaba.h" /* #define UUDEB 1 @@ -361,6 +362,7 @@ extern pServer pServ; char pBueffel[132]; SConnection *pVictim = NULL; Item sItem; + pHdb root = NULL; pVictim = (SConnection *)pData; if(!VerifyConnection(pVictim)) @@ -388,6 +390,15 @@ extern pServer pServ; */ KillCapture(pVictim); + /* + * remove any callbacks which might still be active in the Hipadaba + */ + root = GetHipadabaRoot(); + if(root != NULL) + { + InternalRemoveHipadabaCallback(root,pVictim->ident); + } + /* If we have a grab, release it ! */ diff --git a/devexec.c b/devexec.c index c017e862..88ff73c7 100644 --- a/devexec.c +++ b/devexec.c @@ -9,6 +9,9 @@ revised for use with tasker: Mark Koennecke, September 1997 Locking added: Mark Koennecke, August 2002 + Refactored and instrumentation for instrument staticstics added. + Mark Koennecke, July 2006 + Copyright: Labor fuer Neutronenstreuung @@ -39,10 +42,12 @@ NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. -----------------------------------------------------------------------------*/ +#include #include #include #include #include +#include #include "fortify.h" #include "sics.h" #include "nserver.h" @@ -52,11 +57,52 @@ #include "devexec.h" #include "status.h" #include "lld.h" +#include "commandlog.h" +#include "ifile.h" /* #define DEBUG 1 */ +/*======================== Logging stuff ==================================*/ +static FILE *devLog = NULL; +/*-------------------------------------------------------------------------*/ +int openDevexecLog(){ + char *fileName = NULL; + char fileBuffer[1024]; + + if(devLog == NULL){ + fileName = IFindOption(pSICSOptions,"devexeclog"); + if(fileName != NULL){ + strcpy(fileBuffer,fileName); + } else { + fileBuffer[0] = '\0'; + fileName = getenv("HOME"); + if(fileName != NULL){ + strcpy(fileBuffer,fileName); + } + strcat(fileBuffer,"/log/devexec.log"); + } + devLog = fopen(fileBuffer,"a+"); + } + if(devLog == NULL){ + return 0; + } else { + return 1; + } +} +/*-------------------------------------------------------------------------*/ +void DevexecLog(char *operation, char *device) { + struct timeval tv; + struct timezone tm; + if(devLog != NULL){ + gettimeofday(&tv,&tm); + fprintf(devLog, "DEVEXEC:%s:%s:%ld:%ld\n",operation,device, + tv.tv_sec, tv.tv_usec); + fflush(devLog); + } +} +/*======================== internal data structures =======================*/ typedef struct _DevEntry { void *pData; pObjectDescriptor pDescriptor; @@ -64,6 +110,13 @@ char *name; commandContext comCon; } DevEntry, *pDevEntry; +/*------------------------------------------------------------------------*/ +typedef struct { + pExeList self; + pDevEntry pDev; + pICountable pCountInt; + pIDrivable pDrivInt; +}checkContext, *pCheckContext; /*-------------------------------------------------------------------------*/ static pDevEntry CreateDevEntry(pObjectDescriptor pDes, void *pData, float fVal, char *name) @@ -111,6 +164,7 @@ int iLock; pICallBack pCall; time_t lastRun; + int paused; } ExeList; static pExeList pExecutor = NULL; @@ -167,6 +221,10 @@ free(self); pServ->pExecutor = NULL; + if(devLog != NULL){ + fclose(devLog); + devLog = NULL; + } } /*--------------------------------------------------------------------------*/ void ExeInterest(pExeList self, pDevEntry pDev, char *text) { @@ -284,6 +342,7 @@ self->iEnd = 0; pCon->conStatus = HWBusy; } + DevexecLog("START",pNew->name); return 1; } else @@ -386,7 +445,7 @@ pCon,pCter->pDriv->fPreset); } /*--------------------------------------------------------------------------*/ - int CheckExeList(pExeList self) + int CheckExeListOld(pExeList self) { int iRet; pDevEntry pDev = NULL; @@ -402,7 +461,7 @@ /* Sometimes this gets called, though nothing is running. There are cases where this is feasible for maintainance, but in some cases it - is pure rubbish, because nothing runs. This will ne checkd here. + is pure rubbish, because nothing runs. This will be checked here. */ if((self->pOwner == NULL) || (LLDcheck(self->iList) == LIST_EMPTY)) { @@ -421,10 +480,7 @@ LLDnodeDataTo(self->iList,&pDev); if(pDev) { - /* - SCSetContext(self->pOwner,pDev->cmdID,pDev->name); - */ - SCPushContext(self->pOwner, pDev->comCon.transID, pDev->comCon.deviceID); + SCPushContext(self->pOwner, pDev->comCon.transID, pDev->comCon.deviceID); pDrivInt = pDev->pDescriptor->GetInterface(pDev->pData,DRIVEID); pCountInt = pDev->pDescriptor->GetInterface(pDev->pData,COUNTID); @@ -560,6 +616,196 @@ return 0; } } +/*-------------------------------------------------------------------------*/ +static int checkInterrupt(pCheckContext pCheck, int targetStatus){ + if(SCGetInterrupt(pCheck->self->pOwner) != eContinue) { + pCheck->self->iStatus = DEVINT; + SCPopContext(pCheck->self->pOwner); + SetStatus(eEager); + return -1; + } else { + return targetStatus; + } +} +/*--------------------------------------------------------------------------*/ +static int initializeCheck(pCheckContext pCheck, pDevEntry pDev){ + int eCode; + + SCPushContext(pCheck->self->pOwner, + pDev->comCon.transID, pDev->comCon.deviceID); + pCheck->pDev = pDev; + pCheck->pDrivInt = pDev->pDescriptor->GetInterface(pDev->pData,DRIVEID); + pCheck->pCountInt = pDev->pDescriptor->GetInterface(pDev->pData,COUNTID); + if(pCheck->pDrivInt != NULL){ + eCode = pCheck->pDrivInt->CheckStatus(pDev->pData,pCheck->self->pOwner); + } else if(pCheck->pCountInt != NULL) { + eCode = pCheck->pCountInt->CheckCountStatus(pDev->pData,pCheck->self->pOwner); + } + return eCode; +} +/*--------------------------------------------------------------------------*/ +static int finishDevice(pCheckContext pCheck){ + int status; + + if(pCheck->pCountInt != NULL) { + pCheck->pCountInt->TransferData(pCheck->pDev->pData,pCheck->self->pOwner); + } else if(pCheck->pDrivInt != NULL) { + pCheck->pDrivInt->iErrorCount = 0; + } + ExeInterest(pCheck->self, pCheck->pDev, "finished"); + DevexecLog("STOP",pCheck->pDev->name); + DeleteDevEntry(pCheck->pDev); + LLDnodeDelete(pCheck->self->iList); + status = LLDnodePtr2Prev(pCheck->self->iList); + SCWrite(pCheck->self->pOwner, "", eFinish); + pCheck->self->iStatus = DEVDONE; + return checkInterrupt(pCheck,status); +} +/*-------------------------------------------------------------------------*/ +static int errorDevice(pCheckContext pCheck){ + int status; + + ExeInterest(pCheck->self, pCheck->pDev, "finished with problem"); + DevexecLog("STOP",pCheck->pDev->name); + DeleteDevEntry(pCheck->pDev); + LLDnodeDelete(pCheck->self->iList); + status = LLDnodePtr2Prev(pCheck->self->iList); + SCWrite(pCheck->self->pOwner, "", eFinish); + pCheck->self->iStatus = DEVERROR; + if(pCheck->pDrivInt != NULL) { + pCheck->pDrivInt->iErrorCount++; + } + return checkInterrupt(pCheck,status); +} +/*-------------------------------------------------------------------------*/ +static int testFinish(pExeList self){ + if((self->pOwner == NULL) || (LLDcheck(self->iList) == LIST_EMPTY)) { + self->pOwner = NULL; + self->iRun = 0; + self->iEnd = 1; + self->iStop = 0; + self->lTask = -1; + return 1; + } else { + return 0; + } +} +/*--------------------------------------------------------------------------*/ + int CheckExeList(pExeList self) + { + int iRet, status; + checkContext check; + pDevEntry pDev = NULL; + pICountable pCountInt = NULL; + pIDrivable pDrivInt = NULL; + int eCode; + int isCounting=0, isDriving=0; + char pBueffel[512]; + SConnection *pCon; + pCon = self->pOwner; + + assert(self); + + /* Sometimes this gets called, though nothing is running. There are + cases where this is feasible for maintainance, but in some cases it + is pure rubbish, because nothing runs. This will be checked here. + */ + if(testFinish(self) == 1){ + return 1; + } + + /* + check the status of all registered devices. Remove when finished + */ + check.self = self; + status = LLDnodePtr2First(self->iList); + while(status != 0) + { + LLDnodeDataTo(self->iList,&pDev); + if(pDev) + { + eCode = initializeCheck(&check,pDev); + if(eCode != HWNoBeam && eCode != HWPause && self->paused == 1){ + DevexecLog("CONTINUE","ALL"); + self->paused = 0; + } + switch(eCode) + { + case HWIdle: + case OKOK: + status = finishDevice(&check); + if(status < 0){ + return status; + } + break; + case HWFault: /* real HW error: burning, no net etc.. */ + status = errorDevice(&check); + if(status < 0){ + return status; + } + break; + case HWNoBeam: + SetStatus(eOutOfBeam); + if(self->paused == 0){ + self->paused = 1; + DevexecLog("NOBEAM","ALL"); + } + status = checkInterrupt(&check,1); + if(status < 0){ + return status; + } + break; + case HWPause: + SetStatus(ePaused); + if(self->paused == 0){ + self->paused = 1; + DevexecLog("PAUSE","ALL"); + } + status = checkInterrupt(&check,1); + if(status < 0){ + /* + * continue in order to wait for devices to come to a stop + */ + ContinueExecution(self); + return status; + } + break; + case HWBusy: + if(check.pDrivInt != NULL) + { + isDriving = 1; + } + else if(check.pCountInt != NULL) + { + isCounting = 1; + } + self->iStatus = DEVBUSY; + break; + case HWPosFault: /* cannot get somewhere... */ + status = errorDevice(&check); + if(status < 0){ + return status; + } + break; + } + SCPopContext(self->pOwner); + } + status = LLDnodePtr2Next(self->iList); + } + + if (isCounting) { + if (isDriving) { + SetStatus(eCountDrive); + } else { + SetStatus(eCounting); + } + } else if (isDriving) { + SetStatus(eDriving); + } + + iRet = LLDnodePtr2First(self->iList); + return testFinish(self); + } /*---------------------------------------------------------------------------*/ int Wait4Success(pExeList self) { diff --git a/devexec.h b/devexec.h index 9c43e207..49ed26ea 100644 --- a/devexec.h +++ b/devexec.h @@ -171,5 +171,6 @@ pExeList GetExecutor(void); void SetExecutor(pExeList pExe); - +/*----------------------- Logging -----------------------------------------*/ + void DevexecLog(char *op, char *device); #endif diff --git a/devexec.tex b/devexec.tex index e6515b8f..20dd2e56 100644 --- a/devexec.tex +++ b/devexec.tex @@ -353,7 +353,8 @@ to the global SICS device executor. \mbox{}\verb@ @\\ \mbox{}\verb@ pExeList GetExecutor(void);@\\ \mbox{}\verb@ void SetExecutor(pExeList pExe);@\\ -\mbox{}\verb@ @\\ +\mbox{}\verb@/*----------------------- Logging -----------------------------------------*/@\\ +\mbox{}\verb@ void DevexecLog(char *op, char *device); @\\ \mbox{}\verb@#endif @\\ \mbox{}\verb@@$\diamond$ \end{list} diff --git a/devexec.w b/devexec.w index 45ff782c..f97023f3 100644 --- a/devexec.w +++ b/devexec.w @@ -299,7 +299,8 @@ to the global SICS device executor. pExeList GetExecutor(void); void SetExecutor(pExeList pExe); - +/*----------------------- Logging -----------------------------------------*/ + void DevexecLog(char *op, char *device); #endif @} diff --git a/drive.c b/drive.c index 1ad01395..8e85a51c 100644 --- a/drive.c +++ b/drive.c @@ -387,7 +387,7 @@ } else if(iRet == DEVINT) { - sprintf(pBueffel,"Driving Interrupted!"); + sprintf(pBueffel,"ERROR: Driving Interrupted!"); SCWrite(pCon,pBueffel,eError); ClearExecutor(GetExecutor()); SetStatus(eOld); diff --git a/evcontroller.c b/evcontroller.c index 991dcde4..69aea67a 100644 --- a/evcontroller.c +++ b/evcontroller.c @@ -71,13 +71,29 @@ static long EVIDrive(void *pData, SConnection *pCon, float fVal) { pEVControl self = NULL; - int iRet, iCode, i, iFix; + int iRet, iCode, i, iFix, savedStatus; char pError[132], pBueffel[256]; - + Tcl_Interp *pTcl = NULL; + self = (pEVControl)pData; assert(self); assert(pCon); + if (self->runScript != NULL) { + savedStatus = GetStatus(); + SetStatus(eBatch); + pTcl = InterpGetTcl(pServ->pSics); + snprintf(pBueffel, sizeof(pBueffel), "%s %f", self->runScript, fVal); + iRet = Tcl_Eval(pTcl,pBueffel); + SetStatus(savedStatus); + if(iRet != TCL_OK) + { + SCPrintf(pCon, eError, + "ERROR: %s while processing runscript for %s", + pTcl->result,self->pName); + } + } + self->fTarget = fVal; self->eMode = EVDrive; self->iStop = 0; @@ -848,6 +864,10 @@ static void ErrReport(pEVControl self) { free(self->creationArgs); } + if (self->runScript != NULL) + { + free(self->runScript); + } free(self); } /*--------------------------------------------------------------------------*/ @@ -855,7 +875,7 @@ static void ErrReport(pEVControl self) { char pBueffel[256], pError[132]; int iRet; - + assert(self); assert(pCon); @@ -1025,7 +1045,14 @@ static void ErrReport(pEVControl self) snprintf(pBueffel,255,"%s.errorScript = UNDEFINED", self->pName); } SCWrite(pCon,pBueffel, eValue); - + if(self->runScript != NULL) + { + SCPrintf(pCon, eValue, "%s.runScript = %s", self->pName, self->runScript); + } + else + { + SCPrintf(pCon, eValue, "%s.runScript = none", self->pName); + } return 1; } /*-------------------------------------------------------------------------*/ @@ -1161,10 +1188,10 @@ static void ErrReport(pEVControl self) } else /* parameter request */ { + strtolower(argv[1]); /* catch case of errorScript */ - strtolower(argv[1]); if(strcmp(argv[1],"errorscript") == 0) { if(self->errorScript != NULL) @@ -1180,6 +1207,22 @@ static void ErrReport(pEVControl self) SCWrite(pCon,pBueffel,eValue); return 1; } + /* + catch case of runScript + */ + if(strcmp(argv[1],"runscript") == 0) + { + if(self->runScript != NULL) + { + SCPrintf(pCon, eValue,"%s.runScript = %s",self->pName, + self->runScript); + } + else + { + SCPrintf(pCon, eValue,"%s.runScript = none",self->pName); + } + return 1; + } /* catch case for drivername */ @@ -1208,10 +1251,10 @@ static void ErrReport(pEVControl self) } else /* try to set parameter */ { + strtolower(argv[1]); /* first catch case of errorScript */ - strtolower(argv[1]); if(strcmp(argv[1],"errorscript") == 0) { if(self->errorScript != NULL) @@ -1223,6 +1266,24 @@ static void ErrReport(pEVControl self) SCparChange(pCon); return 1; } + /* + catch case of runScript + */ + if(strcmp(argv[1],"runscript") == 0) + { + if(self->runScript != NULL) + { + free(self->runScript); + } + if (strcasecmp(argv[2],"none") == 0) { + self->runScript = NULL; + } else { + self->runScript = Arg2Tcl(argc-2,&argv[2],NULL,0); + } + SCSendOK(pCon); + SCparChange(pCon); + return 1; + } iRet = Tcl_GetDouble(pSics->pTcl,argv[2],&dVal); if(iRet != TCL_OK) { @@ -1263,6 +1324,9 @@ static int EVSaveStatus(void *pData, char *name, FILE *fil) if(evc->errorScript != NULL) { fprintf(fil, " %s errorScript %s\n", evc->pName, evc->errorScript); } + if(evc->runScript != NULL) { + fprintf(fil, " %s runScript %s\n", evc->pName, evc->runScript); + } } fprintf(fil, "}\n"); } diff --git a/evcontroller.h b/evcontroller.h index 9bff66b5..96fc8d08 100644 --- a/evcontroller.h +++ b/evcontroller.h @@ -1,5 +1,5 @@ -#line 227 "evcontroller.w" +#line 232 "evcontroller.w" /*-------------------------------------------------------------------------- E N V I R O N M E N T C O N T R O L L E R @@ -14,7 +14,7 @@ #define SICSEVCONTROL #include "varlog.h" -#line 148 "evcontroller.w" +#line 153 "evcontroller.w" /*--------------------------- live & death --------------------------------*/ typedef struct __EVControl *pEVControl; @@ -45,6 +45,6 @@ -#line 240 "evcontroller.w" +#line 245 "evcontroller.w" #endif diff --git a/evcontroller.i b/evcontroller.i index 966d7c3f..d10a59f5 100644 --- a/evcontroller.i +++ b/evcontroller.i @@ -1,5 +1,5 @@ -#line 244 "evcontroller.w" +#line 249 "evcontroller.w" /*------------------------------------------------------------------------- Environment controller datastructure @@ -43,9 +43,10 @@ int iStop; SCStore conn; char *creationArgs; + char *runScript; void *pPrivate; void (*KillPrivate)(void *pData); } EVControl; -#line 262 "evcontroller.w" +#line 267 "evcontroller.w" diff --git a/evcontroller.tex b/evcontroller.tex index 06900005..3514e5c8 100644 --- a/evcontroller.tex +++ b/evcontroller.tex @@ -54,6 +54,7 @@ $\langle$evdata {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@ int iStop;@\\ \mbox{}\verb@ SCStore conn;@\\ \mbox{}\verb@ char *creationArgs;@\\ +\mbox{}\verb@ char *runScript;@\\ \mbox{}\verb@ void *pPrivate;@\\ \mbox{}\verb@ void (*KillPrivate)(void *pData);@\\ \mbox{}\verb@ } EVControl;@\\ @@ -88,6 +89,10 @@ holding the logging information. Then there is a switch, iWarned, which is used to prevent execessive output on environment controller error handling. iTcl is a boolean stating if the driver used is a proper C language driver or a Tcl driver. + creationArgs are the arguments needed to recreate the device. runScript +is a script called on every run or drive command. This script is intended +to set control parameters depending on the targetValue. The script is +called with the target temperature as argument. This is followed by the void pointer for use by a derived class. KillPrivate is a pointer to a function capable of deleting pPrivate properly. diff --git a/evcontroller.w b/evcontroller.w index ee8304b1..e9e4aeb6 100644 --- a/evcontroller.w +++ b/evcontroller.w @@ -49,6 +49,7 @@ used by EVControl: int iStop; SCStore conn; char *creationArgs; + char *runScript; void *pPrivate; void (*KillPrivate)(void *pData); } EVControl; @@ -76,6 +77,10 @@ holding the logging information. Then there is a switch, iWarned, which is used to prevent execessive output on environment controller error handling. iTcl is a boolean stating if the driver used is a proper C language driver or a Tcl driver. + creationArgs are the arguments needed to recreate the device. runScript +is a script called on every run or drive command. This script is intended +to set control parameters depending on the targetValue. The script is +called with the target temperature as argument. This is followed by the void pointer for use by a derived class. KillPrivate is a pointer to a function capable of deleting pPrivate properly. diff --git a/evdriver.i b/evdriver.i index 42f8701d..7cf16623 100644 --- a/evdriver.i +++ b/evdriver.i @@ -1,5 +1,5 @@ -#line 265 "evcontroller.w" +#line 270 "evcontroller.w" /*------------------------------------------------------------------------- Environment device driver datastructure @@ -12,7 +12,7 @@ #define DEVREDO 2 -#line 87 "evcontroller.w" +#line 92 "evcontroller.w" typedef struct __EVDriver { int (*SetValue)(pEVDriver self, float fNew); @@ -31,7 +31,7 @@ void (*KillPrivate)(void *pData); } EVDriver; -#line 276 "evcontroller.w" +#line 281 "evcontroller.w" /*-------------------- life & death of a driver --------------------------*/ pEVDriver CreateEVDriver(int argc, char *argv[]); diff --git a/exe.w b/exe.w index 3afd21ba..859ce1f8 100644 --- a/exe.w +++ b/exe.w @@ -171,6 +171,8 @@ int MakeExeManager(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); int ExeManagerWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); +int runExeBatchBuffer(void *pData, SConnection *pCon, SicsInterp *pSics, + char *name); @} @o exeman.i -d @{ diff --git a/exebuf.h b/exebuf.h index 9e1792f2..d32c05f3 100644 --- a/exebuf.h +++ b/exebuf.h @@ -1,5 +1,5 @@ -#line 207 "exe.w" +#line 209 "exe.w" /** * Buffer handling code for the Exe Buffer batch file processing @@ -89,7 +89,7 @@ */ char *exeBufName(pExeBuf self); -#line 220 "exe.w" +#line 222 "exe.w" #endif diff --git a/exebuf.i b/exebuf.i index 3d4638ba..ffa5f5ee 100644 --- a/exebuf.i +++ b/exebuf.i @@ -1,5 +1,5 @@ -#line 198 "exe.w" +#line 200 "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 203 "exe.w" +#line 205 "exe.w" diff --git a/exeman.c b/exeman.c index 468062b1..e0f01712 100644 --- a/exeman.c +++ b/exeman.c @@ -15,13 +15,13 @@ #include #include "fortify.h" #include "sics.h" -#include "exebuf.h" -#include "exeman.h" #include "sdynar.h" #include "dynstring.h" #include "lld.h" -#include "exeman.i" #include "splitter.h" +#include "exebuf.h" +#include "exeman.i" +#include "exeman.h" /*-------------------------------------------------------------------*/ static void KillExeMan(void *data){ @@ -175,9 +175,9 @@ static pDynString locateBatchBuffer(pExeMan self, char *name){ DeleteDynString(result); return NULL; } -/*-------------------------------------------------------------------*/ +/*--------------------------------------------------------------------*/ static int runBatchBuffer(pExeMan self, SConnection *pCon, - SicsInterp *pSics, char *name){ + SicsInterp *pSics, char *name){ pDynString filePath = NULL; char pBueffel[256]; pExeBuf buffer = NULL; @@ -214,6 +214,17 @@ static int runBatchBuffer(pExeMan self, SConnection *pCon, self->exeStackPtr--; return status; } +/*-------------------------------------------------------------------*/ +int runExeBatchBuffer(void *pData, SConnection *pCon, + SicsInterp *pSics, char *name){ + int status, oldEcho; + pExeMan self = (pExeMan)pData; + oldEcho = self->echo; + self->echo = 1; + status = runBatchBuffer(self,pCon,pSics,name); + self->echo = oldEcho; + return status; +} /*========================== path management ========================*/ static int handleBatchPath(pExeMan self, SConnection *pCon, int argc, char *argv[]){ @@ -374,6 +385,18 @@ static int startUpload(pExeMan self, SConnection *pCon){ } return 1; } +/*-------------------------------------------------------------------*/ +static int clearUpload(pExeMan self, SConnection *pCon){ + if(SCGetRights(pCon) > usUser){ + SCWrite(pCon,"ERROR: no permission to clear buffer upload",eError); + return 0; + } + if(self->uploadBuffer != NULL){ + exeBufDelete(self->uploadBuffer); + self->uploadBuffer = NULL; + } + return 1; +} /*---------------------------------------------------------------------*/ static int appendLine(pExeMan self, SConnection *pCon, int argc, char *argv[]){ @@ -958,6 +981,12 @@ int ExeManagerWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, SCSendOK(pCon); } return status; + }else if(strcmp(argv[1],"clearupload") == 0){ + status = clearUpload(self,pCon); + if(status){ + SCSendOK(pCon); + } + return status; }else if(strcmp(argv[1],"info") == 0){ status = infoHandler(self,pCon,argc,argv); return status; diff --git a/exeman.h b/exeman.h index 5ebbbfc8..0d5a08be 100644 --- a/exeman.h +++ b/exeman.h @@ -13,5 +13,7 @@ int MakeExeManager(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); int ExeManagerWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); +int runExeBatchBuffer(void *pData, SConnection *pCon, SicsInterp *pSics, + char *name); #endif diff --git a/exeman.i b/exeman.i index 1918f5a1..2b441c74 100644 --- a/exeman.i +++ b/exeman.i @@ -1,5 +1,5 @@ -#line 176 "exe.w" +#line 178 "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 181 "exe.w" +#line 183 "exe.w" diff --git a/fomerge.c b/fomerge.c index 96f5333c..99629336 100644 --- a/fomerge.c +++ b/fomerge.c @@ -483,11 +483,34 @@ static int updateHMFMData(SicsInterp *pSics, SConnection *pCon) return 1; } /*-------------------------------------------------------------------*/ -static int *calculateSum(HistInt *data, int iDet, int iTime) +static int *calculateDetSum(HistInt *data, int iDet, int iTime) { int i, j, iIndex; int *sum = NULL; + sum = (int *)malloc(iDet*sizeof(int)); + if(!sum) + { + return NULL; + } + memset(sum,0,iDet*sizeof(int)); + + for(i = 0; i < iDet; i++) + { + iIndex = i * iTime; + for(j = 0; j < iTime; j++) + { + sum[i] += data[iIndex+j]; + } + } + return sum; +} +/*-------------------------------------------------------------------*/ +static int *calculateTimeSum(HistInt *data, int iDet, int iTime) +{ + int i, j; + int *sum = NULL; + sum = (int *)malloc(iTime*sizeof(int)); if(!sum) { @@ -495,16 +518,16 @@ static int *calculateSum(HistInt *data, int iDet, int iTime) } memset(sum,0,iTime*sizeof(int)); - for(i = 0; i < iDet; i++) + for(i = 0; i < iTime; i++) { - iIndex = i * iTime; - for(j = 0; j < iTime; j++) + for(j = 0; j < iDet; j++) { - sum[i] += data[iIndex+j]; + sum[i] += data[j*iTime + i]; } } return sum; } + /*--------------------------------------------------------------------*/ static void checkSum(HistInt *sum, int iDet, char *name, SConnection *pCon){ int i, count; @@ -557,7 +580,7 @@ static int putSum(SicsInterp *pSics, SConnection *pCon, return NX_ERROR; } - sum = calculateSum(data,iDet,iTime); + sum = calculateDetSum(data,iDet,iTime); if(!sum) { SCWrite(pCon,"ERROR: out of memory summing bank",eError); @@ -592,7 +615,7 @@ static int putElastic(SicsInterp *pSics, SConnection *pCon, } fTimeBin = GetHistTimeBin(pMem,&iTime); iDet = getFMdim(MIDDLE); - sum = calculateSum(GetHistogramPointer(pMem,pCon),iDet,iTime); + sum = calculateTimeSum(GetHistogramPointer(pMem,pCon),iDet,iTime); if(!sum) { SCWrite(pCon,"ERROR: out of memory calculating elastic peak position", diff --git a/fourtable.h b/fourtable.h index a67718ef..0348975d 100644 --- a/fourtable.h +++ b/fourtable.h @@ -11,14 +11,14 @@ #ifndef FOURTABLE #define FOURTABLE - int MakeFourCircleTable(void); + int MakeFourCircleTable(); void DeleteFourCircleTable(int handle); - int HandleFourCircleCommands(int *table, SConnection *pCon, + int HandleFourCircleCommands(int *handle, SConnection *pCon, int argc, char *argv[], int *err); char *GetFourCircleScanVar(int handle, double two_theta); - int GetFourCircleScanNP(int handle, double two_theta); double GetFourCircleStep(int handle, double two_theta); - float GetFourCirclePreset(int handle, double two_theta); int SaveFourCircleTable(int handle, char *objName, FILE *fd); + float GetFourCirclePreset(int handle, double twoTheta); + int GetFourCircleScanNP(int handle, double twoTheta); #endif diff --git a/lin2ang.c b/lin2ang.c index 671e5838..5e5e6063 100644 --- a/lin2ang.c +++ b/lin2ang.c @@ -70,7 +70,7 @@ return 0; fprintf(fd,"%s length %f\n",name, self->length); - fprintf(fd,"%s zero %f\n",name, self->zero); + fprintf(fd,"%s softzero %f\n",name, self->zero); return 1; } @@ -275,20 +275,20 @@ } } /* zero point */ - if(strcmp(argv[1],"zero") == 0) + if(strcmp(argv[1],"softzero") == 0) { if(argc >= 3) { iRet = Tcl_GetDouble(pSics->pTcl,argv[2],&dVal); if(iRet != TCL_OK) { - SCWrite(pCon,"ERROR: zero parameter not recognised as number", + SCWrite(pCon,"ERROR: softzero parameter not recognised as number", eError); return 0; } if(!SCMatchRights(pCon,usUser)) { - SCWrite(pCon,"ERROR: Insufficient privilege to change zero point", + SCWrite(pCon,"ERROR: Insufficient privilege to change softzero point", eError); return 0; } @@ -298,7 +298,7 @@ } else { - sprintf(pBueffel,"%s.zero = %f",argv[0],self->zero); + sprintf(pBueffel,"%s.softzero = %f",argv[0],self->zero); SCWrite(pCon,pBueffel,eValue); return 1; } diff --git a/lld.c b/lld.c index 819bdbad..0c6ce124 100644 --- a/lld.c +++ b/lld.c @@ -208,6 +208,10 @@ void LLDdelete( int List ) assert( (unsigned) List < ListCount ); + if(ListControl == NULL) + { + return; + } Tmp = ListControl[ List ].first ; /* dummies are also deleted !!! */ while( NULL != Tmp ) /* still assuming last node has */ { /* a NULL next pointer ... */ diff --git a/macro.c b/macro.c index 2fdb4f36..e98b50f1 100644 --- a/macro.c +++ b/macro.c @@ -61,16 +61,15 @@ #include #include #include -#include "SCinter.h" -#include "conman.h" -#include "macro.h" +#include #include "status.h" -#include "obdes.h" +#include "macro.h" #include "splitter.h" #include "ifile.h" #include "Dbg.h" #include "servlog.h" #include "stringdict.h" +#include "exeman.h" #define SICSERROR "005567SICS" /*---------------------------------------------------------------------------- @@ -131,7 +130,8 @@ char *lastCommand = NULL, comBuffer[132]; int iRet = 0,i; int iMacro; - + Statistics *old; + /* get the datastructures */ pSics = (struct __SicsUnknown *)pData; assert(pSics); @@ -180,7 +180,9 @@ /* invoke */ iMacro = SCinMacro(pCon); SCsetMacro(pCon,1); + old=StatisticsBegin(pCommand->stat); iRet = pCommand->OFunc(pCon,pSinter,pCommand->pData,margc, myarg); + StatisticsEnd(old); SCsetMacro(pCon,iMacro); /* lastUnkown gets deeply stacked with each SICS command exec'd. @@ -431,6 +433,21 @@ static int ProtectedExec(ClientData clientData, Tcl_Interp *interp, } /*--------------------------------------------------------------------------*/ + int MacroFileEvalNew(SConnection *pCon, SicsInterp *pInter, void *pData, + int argc, char *argv[]) + { + void *pCom = NULL; + pCom = FindCommandData(pInter,"exe","ExeManager"); + assert(pCom != NULL); + + if(argc < 2){ + SCWrite(pCon,"ERROR: no batch buffer to execute specified", + eError); + return 0; + } + return runExeBatchBuffer(pCom,pCon,pInter,argv[1]); + } +/*----------------------------------------------------------------------*/ int MacroFileEval(SConnection *pCon, SicsInterp *pInter, void *pData, int argc, char *argv[]) { @@ -459,8 +476,8 @@ static int ProtectedExec(ClientData clientData, Tcl_Interp *interp, /* open filename */ if( argc < 2) { - SCWrite(pCon,"ERROR: No filename specified ",eError); - return 0; + SCWrite(pCon,"ERROR: No filename specified ",eError); + return 0; } fp = fopen(argv[1],"r"); if(!fp) @@ -490,7 +507,7 @@ static int ProtectedExec(ClientData clientData, Tcl_Interp *interp, { iChar = fgetc(fp); if(iChar == EOF) - { + { iChar = (int)'\n'; iRun = 0; } @@ -505,11 +522,11 @@ static int ProtectedExec(ClientData clientData, Tcl_Interp *interp, SetStatus(eEager); FirstWord(pCom,pBueffel); if(FindCommand(pInter,pBueffel) != NULL) - { + { sprintf(pBueffel,"%s:%d>> %s",pFile,iLine,pCom); SCWrite(pCon,pBueffel,eValue); if(pWhere != NULL) - { + { free(pWhere); } pWhere = strdup(pBueffel); @@ -524,16 +541,16 @@ static int ProtectedExec(ClientData clientData, Tcl_Interp *interp, { /* Tcl error */ if(strlen(pTcl->result) > 2) { - /* - local copy in order to resolve a valgrind error - */ - strncpy(pBueffel,pTcl->result,511); + /* + local copy in order to resolve a valgrind error + */ + strncpy(pBueffel,pTcl->result,511); SCWrite(pCon,pBueffel,eError); } pCom = Tcl_DStringValue(&command); - SCWrite(pCon,"ERROR: in Tcl block:",eError); + SCWrite(pCon,"ERROR: in Tcl block:",eError); SCWrite(pCon,pCom,eError); - SCWrite(pCon,"ERROR: end of Tcl error block",eError); + SCWrite(pCon,"ERROR: end of Tcl error block",eError); } else /* SICS error */ { @@ -546,7 +563,7 @@ static int ProtectedExec(ClientData clientData, Tcl_Interp *interp, fclose(fp); Tcl_DStringFree(&command); SCWrite(pCon,"ERROR: batch processing interrupted",eError); - SetStatus(eEager); + SetStatus(eEager); return 0; } else @@ -865,7 +882,7 @@ static int ProtectedExec(ClientData clientData, Tcl_Interp *interp, } /* make a string */ - pCommand = Arg2Tcl(argc,argv,pBueffel,sizeof(pBueffel)); + pCommand = Arg2Tcl0(argc-1,argv+1,pBueffel,sizeof(pBueffel),self->command); if (!pCommand) { SCWrite(pCon, "ERROR: no more memory", eError); return 0; @@ -895,8 +912,6 @@ static int ProtectedExec(ClientData clientData, Tcl_Interp *interp, } return 1; /* not reached */ } - -#include "access.c" /*--------------------------------------------------------------------------*/ int TclPublish(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]) @@ -924,17 +939,8 @@ static int ProtectedExec(ClientData clientData, Tcl_Interp *interp, } /* try convert last parameter to user code */ - iUser = 0; - strtolower(argv[2]); - while(aCode[iUser] != NULL) - { - if(strcmp(aCode[iUser],argv[2]) == 0) - { - break; - } - iUser++; - } - if(iUser > iCodes) + iUser = decodeSICSPriv(argv[2]); + if(iUser < 0) { sprintf(pBueffel,"ERROR: cannot identify %s as a valid user code", argv[2]); diff --git a/make_gen b/make_gen index 865d8930..5bcbf35a 100644 --- a/make_gen +++ b/make_gen @@ -8,7 +8,7 @@ COBJ = Sclient.o network.o ifile.o intcli.o $(FORTIFYOBJ) SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \ servlog.o sicvar.o nserver.o SICSmain.o motorlist.o\ - sicsexit.o costa.o task.o $(FORTIFYOBJ)\ + sicsexit.o costa.o task.o $(FORTIFYOBJ) access.o\ macro.o ofac.o obpar.o obdes.o drive.o status.o intserv.o \ devexec.o mumo.o mumoconf.o selector.o selvar.o fupa.o lld.o \ lld_blob.o strrepl.o lin2ang.o fomerge.o napi4.o napi5.o \ @@ -30,7 +30,7 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \ s_rnge.o sig_die.o gpibcontroller.o $(NIOBJ) mcreader.o mccontrol.o\ hmdata.o nxscript.o tclintimpl.o sicsdata.o mcstascounter.o \ mcstashm.o initializer.o remob.o tclmotdriv.o protocol.o \ - sinfox.o sicslist.o cone.o + sinfox.o sicslist.o cone.o hipadaba.o sicshipadaba.o statistics.o MOTOROBJ = motor.o simdriv.o COUNTEROBJ = countdriv.o simcter.o counter.o diff --git a/mesure.c b/mesure.c index 771864fd..851e5b17 100644 --- a/mesure.c +++ b/mesure.c @@ -32,6 +32,7 @@ #include "nxscript.h" #include "fourtable.h" #include "lld.h" +#include "stdscan.h" extern void SNXFormatTime(char *pBueffel, int iLen); extern float nintf(float f); @@ -65,6 +66,7 @@ int iLogFile; /* log file num at connection */ SConnection *pCon; /* log file owning connection */ char *pCurrentFile; /* current file root */ + char headerTemplate[512]; int iCount; /* count of reflection */ int CountMode; /* timer or preset */ int np; /* number of scan points */ @@ -146,7 +148,7 @@ static void ListMesure(pMesure self, char *name, SConnection *pCon) pMesure CreateMesure(pHKL pCryst, pScanData pScanner, pMotor pOmega, char *pOm, pMotor p2Theta, char *p2t, char *pFileRoot, - pDataNumber pDanu) + pDataNumber pDanu, char *hdTemplate) { pMesure pNew = NULL; @@ -197,7 +199,8 @@ static void ListMesure(pMesure self, char *name, SConnection *pCon) pNew->lCounts = (long *)malloc(90*sizeof(long)); #endif pNew->lCounts = (long *)malloc(50*sizeof(long)); - pNew->stepTable = MakeFourCircleTable(); + pNew->stepTable = MakeFourCircleTable(); + strncpy(pNew->headerTemplate,hdTemplate,511); return pNew; } /*------------------------------------------------------------------------*/ @@ -249,7 +252,7 @@ static void ListMesure(pMesure self, char *name, SConnection *pCon) /* check no of parameters inicom name hkl scan omega root danu */ - if(argc < 8) + if(argc < 9) { SCWrite(pCon, "ERROR: Insufficient number of parameters to MesureFactory",eError); @@ -336,7 +339,7 @@ static void ListMesure(pMesure self, char *name, SConnection *pCon) /* finally create the thing */ pNew = CreateMesure(pCryst,pScan,pMot,argv[4], pMot2, argv[5], - argv[6],pDanu); + argv[6],pDanu,argv[8]); if(!pNew) { SCWrite(pCon,"ERROR: no memory in MesureFactory",eError); @@ -759,7 +762,7 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon) char *pFile = NULL, *pPtr; float zero, pos; pMotor pMot = NULL; - + FILE *temp = NULL; assert(self); assert(pCon); @@ -813,6 +816,19 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon) SCSetInterrupt(pCon,eAbortBatch); return 0; } + temp = fopen(self->headerTemplate,"r"); + if(temp == NULL) + { + SCWrite(pCon,"ERROR: failed to open header template",eError); + } + if(temp != NULL && self->fRefl != NULL) + { + WriteTemplate(self->fRefl, temp, pFilename, NULL, + pCon, pServ->pSics); + fclose(temp); + } + + /* open hkl-data file */ strcpy(pFilename,pRoot); @@ -855,59 +871,6 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon) sprintf(pBuff,"user = %s",pVar->text); strcat(pBueffel,pBuff); } - fprintf(self->fRefl,"%s\n",pBueffel); - fprintf(self->fRefl,"lambda = %f Angstroem\n",fVal); - fprintf(self->fRefl, - "UB = %7.6f %7.6f %7.6f %7.6f %7.6f %7.6f %7.6f %7.6f %7.6f\n", - fUB[0], fUB[1],fUB[2],fUB[3],fUB[4],fUB[5],fUB[6],fUB[7],fUB[8]); - - - /* - * zero points for Juerg - */ - pBueffel[0] = '\0'; - if(self->pCryst->pTheta != NULL){ - MotorGetPar(self->pCryst->pTheta,"softzero",&zero); - snprintf(pBuff,131,"stt.zero = %f ", zero); - strcat(pBueffel,pBuff); - } - if(self->pCryst->pOmega != NULL){ - MotorGetPar(self->pCryst->pOmega,"softzero",&zero); - snprintf(pBuff,131,"om.zero = %f ", zero); - strcat(pBueffel,pBuff); - } - if(self->pCryst->pChi != NULL){ - MotorGetPar(self->pCryst->pChi,"softzero",&zero); - snprintf(pBuff,131,"chi.zero = %f ", zero); - strcat(pBueffel,pBuff); - } - if(self->pCryst->pPhi != NULL){ - MotorGetPar(self->pCryst->pPhi,"softzero",&zero); - snprintf(pBuff,131,"phi.zero = %f ", zero); - strcat(pBueffel,pBuff); - } - fprintf(self->fRefl,"%s\n",pBueffel); - - /* - * CEX motors .... - */ - pBueffel[0] = '\0'; - pMot = FindCommandData(pServ->pSics,"cex1","Motor"); - if(pMot != NULL){ - MotorGetSoftPosition(pMot,pCon,&pos); - snprintf(pBuff,131,"cex1 = %f ",pos); - strcat(pBueffel,pBuff); - } - pMot = FindCommandData(pServ->pSics,"cex2","Motor"); - if(pMot != NULL){ - MotorGetSoftPosition(pMot,pCon,&pos); - snprintf(pBuff,131,"cex2 = %f ",pos); - strcat(pBueffel,pBuff); - } - if(strlen(pBueffel) > 1) { - fprintf(self->fRefl,"%s\n",pBueffel); - } - return 1; } /*---------------------------------------------------------------------------*/ diff --git a/mesure.h b/mesure.h index 9d89f607..295e3dca 100644 --- a/mesure.h +++ b/mesure.h @@ -17,8 +17,8 @@ /*--------------------- live & death --------------------------------------*/ pMesure CreateMesure(pHKL pCryst, pScanData pScanner, pMotor pOmega, char *pom, - pMotor p2Theta, char *p2t, - char *pFileRoot,pDataNumber pDanu); + pMotor p2Theta, char *p2t, + char *pFileRoot,pDataNumber pDanu, char *headerTemplate); void DeleteMesure(void *pData); int MesureFactory(SConnection *pCon, SicsInterp *pSics, void *pData, diff --git a/mesure.tex b/mesure.tex index 68dd6121..e9ab4dbd 100644 --- a/mesure.tex +++ b/mesure.tex @@ -30,7 +30,8 @@ $\langle$mesureint {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@/*--------------------- live & death --------------------------------------*/@\\ \mbox{}\verb@ pMesure CreateMesure(pHKL pCryst, pScanData pScanner, @\\ \mbox{}\verb@ pMotor pOmega, char *pom,@\\ -\mbox{}\verb@ char *pFileRoot,pDataNumber pDanu);@\\ +\mbox{}\verb@ pMotor p2Theta, char *p2t,@\\ +\mbox{}\verb@ char *pFileRoot,pDataNumber pDanu, char *headerTemplate);@\\ \mbox{}\verb@ void DeleteMesure(void *pData);@\\ \mbox{}\verb@@\\ \mbox{}\verb@ int MesureFactory(SConnection *pCon, SicsInterp *pSics, void *pData,@\\ @@ -117,11 +118,13 @@ $\langle$fourtableint {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@@\\ \mbox{}\verb@ int MakeFourCircleTable();@\\ \mbox{}\verb@ void DeleteFourCircleTable(int handle);@\\ -\mbox{}\verb@ int HandleFourCircleCommands(int handle, SConnection *pCon, @\\ +\mbox{}\verb@ int HandleFourCircleCommands(int *handle, SConnection *pCon, @\\ \mbox{}\verb@ int argc, char *argv[], int *err);@\\ \mbox{}\verb@ char *GetFourCircleScanVar(int handle, double two_theta);@\\ \mbox{}\verb@ double GetFourCircleStep(int handle, double two_theta);@\\ \mbox{}\verb@ int SaveFourCircleTable(int handle, char *objName, FILE *fd);@\\ +\mbox{}\verb@ float GetFourCirclePreset(int handle, double twoTheta);@\\ +\mbox{}\verb@ int GetFourCircleScanNP(int handle, double twoTheta);@\\ \mbox{}\verb@@$\diamond$ \end{list} \vspace{-1ex} diff --git a/mesure.w b/mesure.w index 3806ad08..3ef463e4 100644 --- a/mesure.w +++ b/mesure.w @@ -26,7 +26,7 @@ The interface to this object consists of these functions: pMesure CreateMesure(pHKL pCryst, pScanData pScanner, pMotor pOmega, char *pom, pMotor p2Theta, char *p2t, - char *pFileRoot,pDataNumber pDanu); + char *pFileRoot,pDataNumber pDanu, char *headerTemplate); void DeleteMesure(void *pData); int MesureFactory(SConnection *pCon, SicsInterp *pSics, void *pData, @@ -100,11 +100,13 @@ interface to this module is: @d fourtableint @{ int MakeFourCircleTable(); void DeleteFourCircleTable(int handle); - int HandleFourCircleCommands(int handle, SConnection *pCon, + int HandleFourCircleCommands(int *handle, SConnection *pCon, int argc, char *argv[], int *err); char *GetFourCircleScanVar(int handle, double two_theta); double GetFourCircleStep(int handle, double two_theta); int SaveFourCircleTable(int handle, char *objName, FILE *fd); + float GetFourCirclePreset(int handle, double twoTheta); + int GetFourCircleScanNP(int handle, double twoTheta); @} Many functions takes as the first argument a handle to the four circle table as created by MakeFourCircleTable. diff --git a/motor.c b/motor.c index 99211b46..e23181fc 100644 --- a/motor.c +++ b/motor.c @@ -492,6 +492,8 @@ extern void KillPiPiezo(void *pData); pM = (pMotor)self; + /* MotorHalt(pM); */ + if(pM->name) free(pM->name); diff --git a/motorlist.c b/motorlist.c index 8dc4db9f..60c3ff77 100644 --- a/motorlist.c +++ b/motorlist.c @@ -83,7 +83,7 @@ static long MOLISetValue(void *data, SConnection *pCon, float val){ return test; } else { tuktuk.running = 1; - LLDnodeDataFrom(self,&tuktuk); + LLDnodeDataFrom(self,&tuktuk); } iRet = LLDnodePtr2Next(self); } diff --git a/nserver.c b/nserver.c index fddfde42..47556084 100644 --- a/nserver.c +++ b/nserver.c @@ -35,6 +35,7 @@ #include "site.h" #include "tcldrivable.h" #include "nserver.h" +#include "sicshipadaba.h" int ServerSetupInterrupt(int iPort, pNetRead pNet, pTaskMan pTasker); /* @@ -42,6 +43,8 @@ */ extern void StopExit(void); /* in SICSmain.c */ + + extern int openDevexecLog(); /* in devexec.c */ /* ========================= Less dreadful file statics =================== */ #define DEFAULTINIFILE "servo.tcl" @@ -215,6 +218,8 @@ assert(pCom); assert(pCom->pData); self->pExecutor = (pExeList)pCom->pData; + openDevexecLog(); + DevexecLog("START","SICS"); /* initialize Interrupt Port */ @@ -304,6 +309,7 @@ /* clear all pending bullshit */ ClearExecutor(self->pExecutor); + DevexecLog("STOP","SICS"); /* shut telnet down */ KillTelnet(); @@ -396,6 +402,7 @@ KillFreeConnections(); + killSICSHipadaba(); /* make fortify print his findings */ Fortify_DumpAllMemory(iFortifyScope); diff --git a/nxscript.c b/nxscript.c index 29d36937..06146906 100644 --- a/nxscript.c +++ b/nxscript.c @@ -394,10 +394,12 @@ static void updateHMDim(NXScript *self, pHistMem mem){ timeBin = GetHistTimeBin(mem,&timeLength); if(timeLength > 2){ sprintf(dummy,"%d",timeLength); - status = NXDupdate(self->dictHandle,"timedim",dummy); - if(status == 0) { - NXDadd(self->dictHandle,"timedim",dummy); - } + } else { + sprintf(dummy,"%d",1); + } + status = NXDupdate(self->dictHandle,"timedim",dummy); + if(status == 0) { + NXDadd(self->dictHandle,"timedim",dummy); } } /*---------------------------------------------------------------------- diff --git a/obdes.c b/obdes.c index 64c16800..7fac44e5 100644 --- a/obdes.c +++ b/obdes.c @@ -44,6 +44,7 @@ #include "obdes.h" #include "conman.h" #include "servlog.h" +#include "hipadaba.h" /*-------------------------------------------------------------------------*/ static void *DefaultGetInterface(void *pData,int iID) @@ -67,6 +68,7 @@ } pRes->name = strdup(name); pRes->pKeys = NULL; + pRes->parNode = NULL; pRes->SaveStatus = DefaultSave; pRes->GetInterface = DefaultGetInterface; return pRes; @@ -77,6 +79,14 @@ assert(self); if(self->name) free(self->name); if(self->pKeys) IFDeleteOptions(self->pKeys); + /* + * delate a parameter node only when not linked elsewhere + */ + if(self->parNode != NULL){ + if(self->parNode->mama == NULL){ + DeleteHipadabaNode(self->parNode); + } + } free(self); } diff --git a/obdes.h b/obdes.h index d82dc49d..f842a2e9 100644 --- a/obdes.h +++ b/obdes.h @@ -23,12 +23,14 @@ #define SICSDESCRIPTOR #include #include +#include typedef struct { char *name; int (*SaveStatus)(void *self, char *name,FILE *fd); void *(*GetInterface)(void *self, int iInterfaceID); IPair *pKeys; + pHdb parNode; } ObjectDescriptor, *pObjectDescriptor; /*---------------------------------------------------------------------------*/ diff --git a/ofac.c b/ofac.c index 4f653561..996f7f98 100644 --- a/ofac.c +++ b/ofac.c @@ -118,6 +118,7 @@ #include "sinfox.h" #include "sicslist.h" #include "cone.h" +#include "sicshipadaba.h" /*----------------------- Server options creation -------------------------*/ static int IFServerOption(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]) @@ -207,8 +208,11 @@ /* permanent commands */ AddCommand(pInter,"Sics_Exitus",SicsExit,NULL,NULL); AddCommand(pInter,"FileEval",MacroFileEval,NULL,NULL); + AddCommand(pInter,"InternEval",InternalFileEval,NULL,NULL); +/* AddCommand(pInter,"FileWhere",MacroWhere,WhereKill,NULL); +*/ AddCommand(pInter,"ClientPut",ClientPut,NULL,NULL); AddCommand(pInter,"broadcast",Broadcast,NULL,NULL); AddCommand(pInter,"transact",TransactAction,NULL,NULL); @@ -242,6 +246,7 @@ AddCommand(pInter,"scriptcallback",CallbackScript,NULL,NULL); AddCommand(pInter,"help",SicsHelp,KillHelp,NULL); AddCommand(pInter,"list",SicsList,NULL,NULL); + AddCommand(pInter,"InstallHdb",InstallSICSHipadaba,NULL,NULL); /* commands to do with the executor. Only StopExe carries the DeleteFunction in order to avoid double deletion. All the @@ -371,7 +376,7 @@ RemoveCommand(pSics,"MakeLin2Ang"); RemoveCommand(pSics,"MakeSync"); RemoveCommand(pSics,"MakeHMControl"); - /* RemoveCommand(pSics,"MakeRS232Controller"); */ + RemoveCommand(pSics,"MakeRS232Controller"); RemoveCommand(pSics,"MakeMaxDetector"); RemoveCommand(pSics,"AntiColliderInstall"); RemoveCommand(pSics,"MakeGPIB"); @@ -407,6 +412,7 @@ /* insert here initialization routines ... */ INIT(SiteInit); /* site specific initializations */ + INIT(StatisticsInit); } /*--------------------------------------------------------------------------*/ @@ -423,18 +429,15 @@ InitGeneral(); /* general initialization */ - InitIniCommands(pSics,pServ->pTasker); - /* create a connection */ pCon = SCCreateDummyConnection(pSics); if(!pCon) { return 0; } - /* removed (gives double output to stdout) - pCon->iFiles = 1; - pCon->pFiles[0] = stdout; - */ + MakeExeManager(pCon,pSics,NULL,1, NULL); + InitIniCommands(pSics,pServ->pTasker); + pCon->iFiles = 0; /* evaluate the file */ diff --git a/optimise.c b/optimise.c index d74cae09..7b507cf7 100644 --- a/optimise.c +++ b/optimise.c @@ -22,6 +22,7 @@ #include "scan.i" #include "fitcenter.h" #include "optimise.h" +#include "stdscan.h" #ifdef CYGNUS #define MAXFLOAT 9999999.99 @@ -83,7 +84,6 @@ { return 1; } - /*------------------------------------------------------------------------*/ pOptimise CreateOptimiser(pCounter pCount) @@ -466,6 +466,197 @@ return iReturn; } +/*------------------------------------------------------------------------ + * We use the scan object here for counting. The reason is that this + * handles well in the common case of a single counter but also has + * provisions for other counting methods through the scan modules + * scripting mechanism + * ------------------------------------------------------------------------*/ +static long ClimbCount(pOptimise self, SConnection *pCon) +{ + int status; + long data[1]; + int (*CollectFunc)(pScanData self, int iPoint) = NULL; + + SilentPrepare(self->pScanner); + + status = self->pScanner->ScanCount(self->pScanner,0); + if(status != 1) + { + return status; + } + if(self->pScanner->CollectScanData == CollectScanData) + { + CollectFunc = self->pScanner->CollectScanData; + self->pScanner->CollectScanData = CollectSilent; + } + status = self->pScanner->CollectScanData(self->pScanner,0); + if(CollectFunc != NULL) + { + self->pScanner->CollectScanData = CollectFunc; + } + if(status != 1) + { + return status; + } + GetScanCounts(self->pScanner,data,1); + return data[0]; +} +/*------------------------------------------------------------------------*/ +static int ClimbDrive(SConnection *pCon,char *name, float value) +{ + int status; + + status = Start2Run(pCon,pServ->pSics,name,value); + if(status != 1) + { + return DRIVEERROR; + } + status = Wait4Success(GetExecutor()); + if(status != DEVDONE) + { + return DRIVEERROR; + } + return 1; +} +/*-------------------------------------------------------------------------*/ + static int ClimbVariable(pOptimise self, SConnection *pCon, int i) + { + pOVarEntry pOvar; + void *pData; + int status, direction = 1; + long oneCount, twoCount, lastCount, currentCount; + float varValue, startValue; + char buffer[256]; + int (*CollectFunc)(pScanData self, int iPoint) = NULL; + + assert(self); + assert( (i >= 0) && (i < self->iVar)); + assert(pCon); + + /* get variable data */ + DynarGet(self->pVariables,i,&pData); + pOvar = (pOVarEntry)pData; + startValue = pOvar->fCenter; + + /* + * prepare scan object + */ + self->pScanner->pCon = pCon; + self->pScanner->pSics = pServ->pSics; + self->pScanner->iNP = 1; + self->pScanner->iMode = self->eCount; + self->pScanner->fPreset = self->fPreset; + + /* + * test for upwards direction + */ + varValue = pOvar->fCenter + pOvar->fStep; + status = ClimbDrive(pCon,pOvar->pName,varValue); + if(!status) + { + return DRIVEERROR; + } + oneCount = ClimbCount(self,pCon); + if(oneCount < 0) + { + return SCANERROR; + } + if(SCGetInterrupt(pCon) != eContinue) + { + return SCANABORT; + } + varValue = pOvar->fCenter - pOvar->fStep; + status = ClimbDrive(pCon,pOvar->pName,varValue); + if(!status) + { + return DRIVEERROR; + } + twoCount = ClimbCount(self,pCon); + if(SCGetInterrupt(pCon) != eContinue) + { + return SCANABORT; + } + if(twoCount < 0) + { + return SCANERROR; + } + if(oneCount > twoCount) + { + direction = 1; + lastCount = oneCount; + } + else + { + direction = -1; + lastCount = twoCount; + } + + /* + * drive to the last best position + */ + varValue = pOvar->fCenter + direction*pOvar->fStep; + status = ClimbDrive(pCon,pOvar->pName,varValue); + if(!status) + { + return DRIVEERROR; + } + currentCount = lastCount; + + /* + * climb upwards as long as possible + */ + while(1) + { + pOvar->fCenter = varValue; + varValue = pOvar->fCenter + direction * pOvar->fStep; + status = ClimbDrive(pCon,pOvar->pName,varValue); + if(!status) + { + return DRIVEERROR; + } + if(SCGetInterrupt(pCon) != eContinue) + { + return SCANABORT; + } + currentCount = ClimbCount(self,pCon); + if(currentCount < 0) + { + return SCANERROR; + } + if(SCGetInterrupt(pCon) != eContinue) + { + return SCANABORT; + } + snprintf(buffer,255,"Climbing %s, value = %f, count = %ld", + pOvar->pName, varValue, currentCount); + SCWrite(pCon,buffer,eWarning); + + if(currentCount <= lastCount) + { + /* + * we are finished. Drive to previous position and + * break + */ + status = ClimbDrive(pCon,pOvar->pName,pOvar->fCenter); + if(!status) + { + return DRIVEERROR; + } + break; + } + else + { + /* + * go on, we are not over the top yet + */ + lastCount = currentCount; + } + } + pOvar->fShift = ABS(startValue - pOvar->fCenter); + + return 1; + } /*---------------------------------------------------------------------------*/ static int CheckSuccess(pOptimise self) { @@ -530,6 +721,45 @@ } return MAXCYCLE; } +/*---------------------------------------------------------------------------*/ + int OptimiserClimb(pOptimise self, SConnection *pCon) + { + int i, iRet, iCycle, iRedoVar = 0; + char pBueffel[256]; + + assert(self); + + if(self->iVar < 1) + { + SCWrite(pCon,"ERROR: Nothing to optimise",eError); + return 0; + } + + iRet = OptimiserInit(self,pCon); + if(!iRet) + { + return iRet; + } + for(iCycle = 0; iCycle < self->iMaxCycles; iCycle++) + { + sprintf(pBueffel,"Optimiser cycle %d of %d started",iCycle, self->iMaxCycles); + SCWrite(pCon,pBueffel,eStatus); + for(i = iRedoVar; i < self->iVar; i++) + { + iRet = ClimbVariable(self,pCon,i); + if(iRet <= 0) + { + return iRet; + } + } + iRet = CheckSuccess(self); + if(iRet) + { + return 1; + } + } + return MAXCYCLE; + } /*--------------------------------------------------------------------------*/ int MakeOptimiser(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]) @@ -717,6 +947,52 @@ break; } } +/*-------- climb */ + else if(strcmp(argv[1],"climb") == 0) + { + /* check rights */ + if(!SCMatchRights(pCon,usUser)) + { + SCWrite(pCon,"ERROR: You are not aurhorised to do this!",eError); + return 0; + } + iRet = OptimiserClimb(self,pCon); + switch(iRet) + { + case PEAKLOST: + SCWrite(pCon,"ERROR: lost the peak, sorry!",eError); + return 0; + break; + case MAXCYCLE: + sprintf(pBueffel,"ERROR: could not optimise peak in %d cycles", + self->iMaxCycles); + SCWrite(pCon,pBueffel,eError); + return 0; + break; + case SCANERROR: + SCWrite(pCon,"ERROR: failed to scan the peak",eError); + return 0; + break; + case SCANABORT: + SCWrite(pCon,"ERROR: Scan was aborted, Optimiser follows",eError); + return 0; + break; + case DRIVEERROR: + SCWrite(pCon,"ERROR: Failure to drive variable to new position",eError); + return 0; + break; + case 1: + SCWrite(pCon,"At long last, I finished optimising the peak",eValue); + return 1; + break; + default: + SCWrite(pCon,"ERROR: Unidentified error krept into Optimiser",eError); + return 0; + break; + } + SCWrite(pCon,"Optimiser climbed successfully",eValue); + return 1; + } /* ------ count mode */ if(strcmp(argv[1],"countmode") == 0) { diff --git a/oscillate.c b/oscillate.c index ecd844d5..09be9e24 100644 --- a/oscillate.c +++ b/oscillate.c @@ -170,7 +170,6 @@ static int StartOscillation(pOscillator self, SConnection *pCon){ static void KillOscillator(void *data){ pOscillator self = (pOscillator)data; if(self != NULL){ - StopOscillation(self); if(self->pDes != NULL){ DeleteDescriptor(self->pDes); } diff --git a/protocol.c b/protocol.c index 22b2e97e..6b9577bb 100644 --- a/protocol.c +++ b/protocol.c @@ -552,7 +552,11 @@ int SCWriteSycamore(SConnection *pCon, char *pBuffer, int iOut) if (iOut == eEvent) { DynStringConcat(pMsgString, " type="); - DynStringConcat(pMsgString, pEventType[pCon->conEventType]); + /* Default type to VALUECHANGE if conEventType not set */ + if (-1 == pCon->conEventType) + DynStringConcat(pMsgString, pEventType[0]); + else + DynStringConcat(pMsgString, pEventType[pCon->conEventType]); /* DynStringConcat(pMsgString, " status="); DynStringConcat(pMsgString, pStatus[pCon->conStatus]);*/ } diff --git a/remob.c b/remob.c index fca5591e..12dc5187 100644 --- a/remob.c +++ b/remob.c @@ -534,7 +534,6 @@ int RemobAction(SConnection *pCon, SicsInterp *pSics, void *pData, float fValue; long lID; char *endp; - char *argv0; char *cmd; /* char acce[128], inte[128]; @@ -559,10 +558,7 @@ int RemobAction(SConnection *pCon, SicsInterp *pSics, void *pData, snprintf(inte, sizeof(inte), "!%s.interruptmode", remob->name); */ - argv0 = argv[0]; - argv[0] = remob->name; - cmd = Arg2Tcl(argc, argv, buf, sizeof buf); - argv[0] = argv0; + cmd = Arg2Tcl0(argc-1, argv+1, buf, sizeof buf, remob->name); if (cmd) { RemTransact(remserver, rc, pCon, cmd, ">", NULL); if (cmd != buf) free(cmd); diff --git a/scan.tex b/scan.tex index 4f5f46e4..ce5eecc1 100644 --- a/scan.tex +++ b/scan.tex @@ -52,6 +52,7 @@ $\langle$scanvar {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@ float fStep;@\\ \mbox{}\verb@ float *fData;@\\ \mbox{}\verb@ int dataList;@\\ +\mbox{}\verb@ int logVar;@\\ \mbox{}\verb@ }VarEntry, *pVarEntry;@\\ \mbox{}\verb@@$\diamond$ \end{list} @@ -88,6 +89,14 @@ $\langle$scanvarint {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@ pVarEntry MakeScanVar(SicsInterp *pSics, SConnection *pCon, char@\\ \mbox{}\verb@ *name, float start, float step);@\\ \mbox{}\verb@ /**@\\ +\mbox{}\verb@ * make a variable which is logged during the scan but not driven.@\\ +\mbox{}\verb@ * @{\tt @}\verb@param pSics The interpreter in order to locate the variable.@\\ +\mbox{}\verb@ * @{\tt @}\verb@param pCon A connection object for error reporting@\\ +\mbox{}\verb@ * @{\tt @}\verb@param name The name of the variable to log@\\ +\mbox{}\verb@ */@\\ +\mbox{}\verb@ pVarEntry MakeLogVar(SicsInterp *pSics, @\\ +\mbox{}\verb@ SConnection *pCon, char *name);@\\ +\mbox{}\verb@ /**@\\ \mbox{}\verb@ * InitScanVar clears the list of scan points@\\ \mbox{}\verb@ * @{\tt @}\verb@param pvar The scna variable to clear@\\ \mbox{}\verb@ */@\\ @@ -145,6 +154,21 @@ $\langle$scanvarint {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@ * @{\tt @}\verb@param np The number of slots in fData.@\\ \mbox{}\verb@ */@\\ \mbox{}\verb@ void CopyScanVar(pVarEntry pVar, float *fData, int np);@\\ +\mbox{}\verb@ /**@\\ +\mbox{}\verb@ * CheckScanVar checks if the scan variable can be driven through the@\\ +\mbox{}\verb@ * whole range.@\\ +\mbox{}\verb@ * @{\tt @}\verb@param pVar The scan variable to check@\\ +\mbox{}\verb@ * @{\tt @}\verb@param pCon The connection object to which to report errors.@\\ +\mbox{}\verb@ * @{\tt @}\verb@param np The number of points to check for.@\\ +\mbox{}\verb@ * @{\tt @}\verb@return 0 on failuyre, 1 on success@\\ +\mbox{}\verb@ */@\\ +\mbox{}\verb@ int CheckScanVar(pVarEntry pVar, SConnection *pCon, int np);@\\ +\mbox{}\verb@ /**@\\ +\mbox{}\verb@ * queries if the variable is alogged variable or a drive one.@\\ +\mbox{}\verb@ * @{\tt @}\verb@param pVar The variable to query.@\\ +\mbox{}\verb@ * @{\tt @}\verb@return 1 if log var, 0 else@\\ +\mbox{}\verb@ */@\\ +\mbox{}\verb@ int isLogVar(pVarEntry pVar);@\\ \mbox{}\verb@@$\diamond$ \end{list} \vspace{-1ex} @@ -451,6 +475,15 @@ $\langle$stdscan {\footnotesize ?}$\rangle\equiv$ \begin{list}{}{} \item \mbox{}\verb@@\\ \mbox{}\verb@ /**@\\ +\mbox{}\verb@ * make a filename according to SICS rules for this scan@\\ +\mbox{}\verb@ */@\\ +\mbox{}\verb@ char *ScanMakeFileName(SicsInterp *pSics, SConnection *pCon);@\\ +\mbox{}\verb@ /*@\\ +\mbox{}\verb@ * write the header bits from the template@\\ +\mbox{}\verb@ */@\\ +\mbox{}\verb@ void WriteTemplate(FILE *fd, FILE *temp, char *filename, pScanData pScan, @\\ +\mbox{}\verb@ SConnection *pCon, SicsInterp *pSics);@\\ +\mbox{}\verb@ /**@\\ \mbox{}\verb@ * write the header of the scan file@\\ \mbox{}\verb@ */@\\ \mbox{}\verb@ int WriteHeader(pScanData self);@\\ @@ -474,6 +507,10 @@ $\langle$stdscan {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@ */ @\\ \mbox{}\verb@ int NonCheckPrepare(pScanData self);@\\ \mbox{}\verb@ /**@\\ +\mbox{}\verb@ * prepare for a scan without complaining...@\\ +\mbox{}\verb@ */@\\ +\mbox{}\verb@ int SilentPrepare(pScanData self);@\\ +\mbox{}\verb@ /**@\\ \mbox{}\verb@ * ScanDrive handles driving to the scan point iPoint.@\\ \mbox{}\verb@ */ @\\ \mbox{}\verb@ int ScanDrive(pScanData self, int iPoint);@\\ @@ -494,6 +531,7 @@ $\langle$stdscan {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@ */@\\ \mbox{}\verb@ int CollectScanData(pScanData self, int iPoint);@\\ \mbox{}\verb@ int CollectScanDataJochen(pScanData self, int iPoint);@\\ +\mbox{}\verb@ int CollectSilent(pScanData self, int iPoint);@\\ \mbox{}\verb@/*===================================================================*/@\\ \mbox{}\verb@ /**@\\ \mbox{}\verb@ * Script invocation for writing the scan header.@\\ diff --git a/scan.w b/scan.w index 545394a4..9f1f9122 100644 --- a/scan.w +++ b/scan.w @@ -47,6 +47,7 @@ Scan variables are held in this data structure: float fStep; float *fData; int dataList; + int logVar; }VarEntry, *pVarEntry; @} The VarEntry structure holds the data for each single scan variable. @@ -69,6 +70,14 @@ Scan variables have an interface: */ pVarEntry MakeScanVar(SicsInterp *pSics, SConnection *pCon, char *name, float start, float step); + /** + * make a variable which is logged during the scan but not driven. + * @@param pSics The interpreter in order to locate the variable. + * @@param pCon A connection object for error reporting + * @@param name The name of the variable to log + */ + pVarEntry MakeLogVar(SicsInterp *pSics, + SConnection *pCon, char *name); /** * InitScanVar clears the list of scan points * @@param pvar The scna variable to clear @@ -127,6 +136,21 @@ Scan variables have an interface: * @@param np The number of slots in fData. */ void CopyScanVar(pVarEntry pVar, float *fData, int np); + /** + * CheckScanVar checks if the scan variable can be driven through the + * whole range. + * @@param pVar The scan variable to check + * @@param pCon The connection object to which to report errors. + * @@param np The number of points to check for. + * @@return 0 on failuyre, 1 on success + */ + int CheckScanVar(pVarEntry pVar, SConnection *pCon, int np); + /** + * queries if the variable is alogged variable or a drive one. + * @@param pVar The variable to query. + * @@return 1 if log var, 0 else + */ + int isLogVar(pVarEntry pVar); @} \subsubsection{The Scan Object} @@ -396,6 +420,15 @@ format of this template is documented in the SICS managers documentation. @d stdscan @{ + /** + * make a filename according to SICS rules for this scan + */ + char *ScanMakeFileName(SicsInterp *pSics, SConnection *pCon); + /* + * write the header bits from the template + */ + void WriteTemplate(FILE *fd, FILE *temp, char *filename, pScanData pScan, + SConnection *pCon, SicsInterp *pSics); /** * write the header of the scan file */ @@ -419,6 +452,10 @@ documentation. * second version of PrepareScan which does not check scan limits */ int NonCheckPrepare(pScanData self); + /** + * prepare for a scan without complaining... + */ + int SilentPrepare(pScanData self); /** * ScanDrive handles driving to the scan point iPoint. */ @@ -440,6 +477,7 @@ documentation. */ int CollectScanData(pScanData self, int iPoint); int CollectScanDataJochen(pScanData self, int iPoint); + int CollectSilent(pScanData self, int iPoint); /*===================================================================*/ /** * Script invocation for writing the scan header. diff --git a/scanvar.h b/scanvar.h index 7bb1dbfb..e73c5080 100644 --- a/scanvar.h +++ b/scanvar.h @@ -21,7 +21,7 @@ float fStep; float *fData; int dataList; - int logVar; + int logVar; }VarEntry, *pVarEntry; /*---------------------------------------------------------------------*/ @@ -35,22 +35,21 @@ * @param start The start position from which to scan * @param step The step width with which to scan. * @return A pointer to a new scan variable object on success, NULL - * else NULL + * else */ pVarEntry MakeScanVar(SicsInterp *pSics, SConnection *pCon, char *name, float start, float step); - /* - * Make a variable which is logged during the scan - * @param pSics The SICS interpreter to search for the variable - * @param pCon A connection to report problems to - * @param name The name of the variable to log - * @return A pointer to a new scan variable object on success, NULL - * else NULL + /** + * make a variable which is logged during the scan but not driven. + * @param pSics The interpreter in order to locate the variable. + * @param pCon A connection object for error reporting + * @param name The name of the variable to log */ - pVarEntry MakeLogVar(SicsInterp *pSics, SConnection *pCon, char *name); + pVarEntry MakeLogVar(SicsInterp *pSics, + SConnection *pCon, char *name); /** * InitScanVar clears the list of scan points - * @param pvar The scan variable to clear + * @param pvar The scna variable to clear */ void InitScanVar(pVarEntry pVar); /** @@ -76,14 +75,6 @@ * @return The step width for the scan. */ float ScanVarStep(pVarEntry pVar); - /** - * check if the scan is possible, i.e the scan variable does - * not violate the limits in the scan - * @param pVar The scan variable to check - * @param pCon The connection to report errors to - * @return 1 when OK, 0 when the limits are violated. - */ - int CheckScanVar(pVarEntry pVar, SConnection *pCon, int np); /** * StartScanVar starts the scan variable to drive to the next * position. @@ -115,7 +106,19 @@ */ void CopyScanVar(pVarEntry pVar, float *fData, int np); /** - * enquires if a variable is a logged variable or a proper scan variable - */ + * CheckScanVar checks if the scan variable can be driven through the + * whole range. + * @param pVar The scan variable to check + * @param pCon The connection object to which to report errors. + * @param np The number of points to check for. + * @return 0 on failuyre, 1 on success + */ + int CheckScanVar(pVarEntry pVar, SConnection *pCon, int np); + /** + * queries if the variable is alogged variable or a drive one. + * @param pVar The variable to query. + * @return 1 if log var, 0 else + */ int isLogVar(pVarEntry pVar); + #endif diff --git a/sics.h b/sics.h index b7044e5b..a2dc465f 100644 --- a/sics.h +++ b/sics.h @@ -36,6 +36,12 @@ extern pServer pServ; +/** + * Decode privilege text. Implemented in access.c + * @param the text to decode + * @return -1 if code invalid, else the privilege code + */ +int decodeSICSPriv(char *privText); #endif diff --git a/sicvar.c b/sicvar.c index 4d351a38..5b8af4c9 100644 --- a/sicvar.c +++ b/sicvar.c @@ -136,14 +136,7 @@ "float", NULL }; - static char *cAccess[] = { - "internal", - "mugger", - "user", - "spy", - NULL - }; - + int VarFactory(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]) { @@ -196,30 +189,8 @@ } /* argv[3] must be the access code, check that now */ - i = 0; - while(cAccess[i] != NULL) - { - if(strcmp(argv[3],cAccess[i]) == 0) - { - break; - } - i++; - } - switch(i) - { - case 0: - iCode = usInternal; - break; - case 1: - iCode = usMugger; - break; - case 2: - iCode = usUser; - break; - case 3: - iCode = usSpy; - break; - default: + i = decodeSICSPriv(argv[3]); + if(i < 0){ sprintf(pBueffel," %s access code %s not recognized", argv[1], argv[3]); SCWrite(pCon,pBueffel,eError); @@ -227,7 +198,7 @@ } /* now we can actually install the variable */ - pRes = VarCreate(iCode,eType,argv[1]); + pRes = VarCreate(i,eType,argv[1]); if(!pRes) { sprintf(pBueffel,"Memory Error creating variable %s", argv[1]); diff --git a/splitter.c b/splitter.c index 7d67de02..13f97702 100644 --- a/splitter.c +++ b/splitter.c @@ -400,12 +400,18 @@ typedef enum _CharType {eSpace, eNum,eeText,eQuote} CharType; return 1; } /*--------------------------------------------------------------------------*/ -char *Arg2Tcl(int argc, char *argv[], char *buffer, int buffersize) { - int i, l, firstArgToQuote, quote; +char *Arg2Tcl0(int argc, char *argv[], char *buffer, int buffersize, char *prepend) { + int i, l, firstArgToQuote, quote, prependlen; char ch; char *res, *arg; - l = 0; + if (prepend) { + prependlen = strlen(prepend); + l = prependlen + 1; + } else { + prependlen = 0; + l = 0; + } firstArgToQuote = argc; quote = 0; for (i=0; i= firstArgToQuote) *res++ = '"'; arg = argv[i]; @@ -464,6 +475,10 @@ char *Arg2Tcl(int argc, char *argv[], char *buffer, int buffersize) { *res='\0'; return buffer; } +/*--------------------------------------------------------------------------*/ +char *Arg2Tcl(int argc, char *argv[], char *buffer, int buffersize) { + return Arg2Tcl0(argc, argv, buffer, buffersize, NULL); +} /*============================================================================ Testprogram, can be activated by defining MAIN diff --git a/splitter.h b/splitter.h index a5e6fbbf..2dfb3448 100644 --- a/splitter.h +++ b/splitter.h @@ -87,5 +87,10 @@ typedef struct _TokenEntry { if (result != NULL && result != buffer) free(result); !*/ - + char *Arg2Tcl0(int argc, char *argv[], char *buffer, int buffersize, char *prepend); + /*! + This function is added for convenience, and acts similar to Arg2Tcl. + If prepend is not NULL, its contents appear untreated before the args. + A space is used as separator. + !*/ #endif diff --git a/stdscan.c b/stdscan.c index 8a25f6ff..c2deb893 100644 --- a/stdscan.c +++ b/stdscan.c @@ -64,8 +64,240 @@ static char *fixExtension(char *filename) } return fixExtension(pRes); } +/*-------------------------------------------------------------------------*/ +void WriteTemplate(FILE *fd, FILE *temp, char *filename, pScanData pScan, + SConnection *pCon, SicsInterp *pSics) +{ + char pBuffer[512], pError[512], *pPtr, *pName; + CommandList *pCom = NULL; + pSicsVariable pVar = NULL; + pDummy pDum = NULL; + pIDrivable pDriv = NULL; + pMotor pMot = NULL; + pVarEntry pScanVar = NULL; + void *pVoid = NULL; + float fVal; + int iRet; + + /* loop through description file and act along the way */ + while(fgets(pBuffer,511,temp) != NULL) + { + pPtr = strstr(pBuffer,"!!VAR("); + if(pPtr) /* handle a Sics variable */ + { + /* extract the name */ + pName = pPtr + 6; /* first char of name */ + *pPtr = '\0'; /* this is the starter of the line */ + pPtr = pName; + while( (*pPtr != '\0') && (*pPtr != ')') ) + { + pPtr++; + } + *pPtr = '\0'; + /* find the variable */ + pCom = FindCommand(pSics,pName); + if(!pCom) + { + sprintf(pError,"ERROR: variable %s NOT found",pName); + SCWrite(pCon,pError,eError); + continue; + } + pVar = (pSicsVariable)pCom->pData; + if(!pVar) + { + sprintf(pError,"ERROR: variable %s NOT found",pName); + SCWrite(pCon,pError,eError); + continue; + } + switch(pVar->eType) + { + case veFloat: + sprintf(pError,"%f",pVar->fVal); + break; + case veInt: + sprintf(pError,"%d",pVar->iVal); + break; + case veText: + sprintf(pError,"%s",pVar->text); + break; + } + /* finally write */ + fprintf(fd,"%s %s\n",pBuffer,pError); + continue; + }/* end variable */ +/*------- Drivable */ + pPtr = strstr(pBuffer,"!!DRIV("); + if(pPtr) + { + /* extract the name */ + pName = pPtr + 7; /* first char of name */ + *pPtr = '\0'; /* this is the starter of the line */ + pPtr = pName; + while( (*pPtr != '\0') && (*pPtr != ')') ) + { + pPtr++; + } + *pPtr = '\0'; + /* find the variable */ + pCom = FindCommand(pSics,pName); + if(!pCom) + { + sprintf(pError,"ERROR: variable %s NOT found",pName); + SCWrite(pCon,pError,eError); + continue; + } + pDum = (pDummy)pCom->pData; + if(!pDum) + { + sprintf(pError,"ERROR: variable %s is NOT drivable",pName); + SCWrite(pCon,pError,eError); + continue; + } + pDriv = (pIDrivable)pDum->pDescriptor->GetInterface(pDum,DRIVEID); + if(!pDriv) + { + sprintf(pError,"ERROR: variable %s is NOT drivable",pName); + SCWrite(pCon,pError,eError); + continue; + } + fVal = pDriv->GetValue(pDum,pCon); + fprintf(fd,"%s %f\n",pBuffer,fVal); + continue; + } /* end drive */ +/*------- zero point */ + pPtr = strstr(pBuffer,"!!ZERO("); + if(pPtr) + { + /* extract the name */ + pName = pPtr + 7; /* first char of name */ + *pPtr = '\0'; /* this is the starter of the line */ + pPtr = pName; + while( (*pPtr != '\0') && (*pPtr != ')') ) + { + pPtr++; + } + *pPtr = '\0'; + /* find the motor */ + pMot = FindMotor(pSics,pName); + if(!pMot) + { + sprintf(pError,"ERROR: motor %s NOT found",pName); + SCWrite(pCon,pError,eError); + continue; + } + iRet = MotorGetPar(pMot,"softzero",&fVal); + if(!iRet) + { + SCWrite(pCon,"ERROR: failed to read zero point",eError); + continue; + } + fprintf(fd,"%s %f\n",pBuffer,fVal); + continue; + } /* end zero point */ +/*---------- scripted info */ + pPtr = strstr(pBuffer,"!!SCRIPT("); + if(pPtr) + { + /* extract the name */ + pName = pPtr + 9; /* first char of name */ + *pPtr = '\0'; /* this is the starter of the line */ + pPtr = pName; + while( (*pPtr != '\0') && (*pPtr != ')') ) + { + pPtr++; + } + *pPtr = '\0'; + if(Tcl_Eval(InterpGetTcl(pSics),pName) == TCL_OK) + { + fprintf(fd,"%s\n",Tcl_GetStringResult(InterpGetTcl(pSics))); + } + else + { + SCWrite(pCon,"ERROR: failed to execute Tcl command",eError); + strncpy(pBuffer, Tcl_GetStringResult(InterpGetTcl(pSics)), 511); + SCWrite(pCon,pBuffer,eError); + continue; + } + } +/* ------- date */ + pPtr = strstr(pBuffer,"!!DATE!!"); + if(pPtr) + { + *pPtr = '\0'; + SNXFormatTime(pError,511); + fprintf(fd,"%s %s\n",pBuffer,pError); + continue; + } +/*-------- filename */ + pPtr = strstr(pBuffer,"!!FILE!!"); + if(pPtr) + { + *pPtr = '\0'; + fprintf(fd,"%s %s\n",pBuffer,filename); + continue; + } +/*------------ scanzero */ + pPtr = strstr(pBuffer,"!!SCANZERO!!"); + if(pPtr && pScan != NULL) + { + *pPtr = '\0'; + /* write zero point of first scan variable if motor */ + DynarGet(pScan->pScanVar,0,&pVoid); + pScanVar = (pVarEntry)pVoid; + if(pScanVar) + { + pMot = NULL; + pMot = FindMotor(pSics,ScanVarName(pScanVar)); + if(pMot != NULL) + { + MotorGetPar(pMot,"softzero",&fVal); + fprintf(fd,"%s zero = %8.3f\n",ScanVarName(pScanVar), + fVal); + } + } + } +/* --------- plain text */ + fprintf(fd,"%s",pBuffer); + } /* end while */ +} /*---------------------------------------------------------------------------*/ int WriteHeader(pScanData self) + { + int i, iRet; + FILE *fd; + + assert(self->pSics); + assert(self->pCon); + + /* open data file */ + self->fd = fopen(self->pFile,"w"); + if(!self->fd) + { + SCWrite(self->pCon,"ERROR: cannot write data file",eError); + return 0; + } + + /* open header description file */ + fd = fopen(self->pHeaderFile,"r"); + if(!fd) + { + SCWrite(self->pCon,"ERROR: cannot open header description file",eError); + return 0; + } + + WriteTemplate(self->fd,fd,self->pFile, + self, self->pCon, self->pSics); + + /* remember position for seeking to it for writing data */ + self->lPos = ftell(self->fd); + + fclose(fd); + fclose(self->fd); + self->fd = NULL; + return 1; + } +/*---------------------------------------------------------------------------*/ + int WriteHeaderOld(pScanData self) { int i, iRet; FILE *fd; @@ -615,7 +847,7 @@ int prepareDataFile(pScanData self){ return CollectScanDataIntern(self,iPoint,1); } /*------------------------------------------------------------------------*/ - static int CollectSilent(pScanData self, int iPoint) + int CollectSilent(pScanData self, int iPoint) { pVarEntry pVar = NULL; void *pDings; diff --git a/stdscan.h b/stdscan.h index 5ad5c223..d0030c9e 100644 --- a/stdscan.h +++ b/stdscan.h @@ -11,8 +11,15 @@ #ifndef SICSSTDSCAN #define SICSSTDSCAN + /** + * make a filename according to SICS rules for this scan + */ char *ScanMakeFileName(SicsInterp *pSics, SConnection *pCon); - + /* + * write the header bits from the template + */ + void WriteTemplate(FILE *fd, FILE *temp, char *filename, pScanData pScan, + SConnection *pCon, SicsInterp *pSics); /** * write the header of the scan file */ @@ -36,7 +43,9 @@ * second version of PrepareScan which does not check scan limits */ int NonCheckPrepare(pScanData self); - + /** + * prepare for a scan without complaining... + */ int SilentPrepare(pScanData self); /** * ScanDrive handles driving to the scan point iPoint. @@ -59,6 +68,7 @@ */ int CollectScanData(pScanData self, int iPoint); int CollectScanDataJochen(pScanData self, int iPoint); + int CollectSilent(pScanData self, int iPoint); /*===================================================================*/ /** * Script invocation for writing the scan header. diff --git a/tasdrive.c b/tasdrive.c index 9fd4e8bf..b0211af6 100644 --- a/tasdrive.c +++ b/tasdrive.c @@ -192,22 +192,24 @@ static int TASHalt(void *pData){ } /*--------------------------------------------------------------------------*/ -static void writeMotPos(SConnection *pCon, char *name, +static void writeMotPos(SConnection *pCon, int silent, char *name, float val, float target){ char pBueffel[132]; - snprintf(pBueffel,131,"Driving %5s from %8.3f to %8.3f", - name, val, target); - SCWrite(pCon,pBueffel,eWarning); - + if(silent != 1) { + snprintf(pBueffel,131,"Driving %5s from %8.3f to %8.3f", + name, val, target); + SCWrite(pCon,pBueffel,eWarning); + } } /*---------------------------------------------------------------------------*/ static int startMotors(ptasMot self, tasAngles angles, SConnection *pCon, int driveQ, int driveTilt){ float val; double curve; - int status; + int status, silent; + silent = self->math->silent; /* monochromator */ @@ -220,7 +222,7 @@ static int startMotors(ptasMot self, tasAngles angles, return status; } } - writeMotPos(pCon,"a1",val, angles.monochromator_two_theta/2.); + writeMotPos(pCon,silent,"a1",val, angles.monochromator_two_theta/2.); val = self->math->motors[A2]->pDrivInt->GetValue(self->math->motors[A2],pCon); if(ABS(val - angles.monochromator_two_theta) > MOTPREC){ @@ -231,7 +233,7 @@ static int startMotors(ptasMot self, tasAngles angles, return status; } } - writeMotPos(pCon,"a2",val, angles.monochromator_two_theta); + writeMotPos(pCon,silent,"a2",val, angles.monochromator_two_theta); if(self->math->motors[MCV] != NULL){ curve = maCalcVerticalCurvature(self->math->machine.monochromator, @@ -245,7 +247,7 @@ static int startMotors(ptasMot self, tasAngles angles, return status; } } - writeMotPos(pCon,"mcv",val, curve); + writeMotPos(pCon,silent,"mcv",val, curve); } if(self->math->motors[MCH] != NULL){ @@ -260,7 +262,7 @@ static int startMotors(ptasMot self, tasAngles angles, return status; } } - writeMotPos(pCon,"mch",val, curve); + writeMotPos(pCon,silent,"mch",val, curve); } /* @@ -277,7 +279,7 @@ static int startMotors(ptasMot self, tasAngles angles, return status; } } - writeMotPos(pCon,self->math->motors[A5]->name, + writeMotPos(pCon,silent,self->math->motors[A5]->name, val, angles.analyzer_two_theta/2.); val = self->math->motors[A6]->pDrivInt->GetValue(self->math->motors[A6],pCon); @@ -289,7 +291,7 @@ static int startMotors(ptasMot self, tasAngles angles, return status; } } - writeMotPos(pCon,"a6",val, angles.analyzer_two_theta); + writeMotPos(pCon,silent,"a6",val, angles.analyzer_two_theta); if(self->math->motors[ACV] != NULL){ curve = maCalcVerticalCurvature(self->math->machine.analyzer, @@ -303,7 +305,7 @@ static int startMotors(ptasMot self, tasAngles angles, return status; } } - writeMotPos(pCon,"acv",val, curve); + writeMotPos(pCon,silent,"acv",val, curve); } if(self->math->motors[ACH] != NULL){ curve = maCalcHorizontalCurvature(self->math->machine.analyzer, @@ -319,7 +321,7 @@ static int startMotors(ptasMot self, tasAngles angles, } } } - writeMotPos(pCon,"ach",val, curve); + writeMotPos(pCon,silent,"ach",val, curve); } if(driveQ == 0){ @@ -338,7 +340,7 @@ static int startMotors(ptasMot self, tasAngles angles, return status; } } - writeMotPos(pCon,"a3",val, angles.a3); + writeMotPos(pCon,silent,"a3",val, angles.a3); val = self->math->motors[A4]->pDrivInt->GetValue(self->math->motors[A4],pCon); if(ABS(val - angles.sample_two_theta) > MOTPREC){ @@ -349,7 +351,7 @@ static int startMotors(ptasMot self, tasAngles angles, return status; } } - writeMotPos(pCon,"a4",val, angles.sample_two_theta); + writeMotPos(pCon,silent,"a4",val, angles.sample_two_theta); if(driveTilt == 1){ val = self->math->motors[SGL]->pDrivInt->GetValue(self->math->motors[SGL],pCon); @@ -361,7 +363,7 @@ static int startMotors(ptasMot self, tasAngles angles, return status; } } - writeMotPos(pCon,"sgl",val, angles.sgl); + writeMotPos(pCon,silent,"sgl",val, angles.sgl); val = self->math->motors[SGU]->pDrivInt->GetValue(self->math->motors[SGU],pCon); if(ABS(val - angles.sgu) > MOTPREC){ @@ -372,7 +374,7 @@ static int startMotors(ptasMot self, tasAngles angles, return status; } } - writeMotPos(pCon,"sgu",val, angles.sgu); + writeMotPos(pCon,silent,"sgu",val, angles.sgu); } self->math->mustDrive = 0; return OKOK; diff --git a/tasscanub.c b/tasscanub.c index 644f7828..8b291b19 100644 --- a/tasscanub.c +++ b/tasscanub.c @@ -197,6 +197,8 @@ static int TASUBHeader(pScanData self) int fx; tasReflection r; double kfix; + pSicsVariable sVar = NULL; + float f1, f2, f3, f4; assert(self); assert(pTAS); @@ -345,6 +347,57 @@ static int TASUBHeader(pScanData self) r.qe.qk, r.qe.ql); + /* + * write mupad stuff if available + */ + sVar = FindCommandData(pServ->pSics,"w1","SicsVariable"); + if(sVar != NULL) + { + f1 = sVar->fVal; + sVar = FindCommandData(pServ->pSics,"w2","SicsVariable"); + if(sVar != NULL) + { + f2 = sVar->fVal; + } + sVar = FindCommandData(pServ->pSics,"w3","SicsVariable"); + if(sVar != NULL) + { + f3 = sVar->fVal; + } + sVar = FindCommandData(pServ->pSics,"w4","SicsVariable"); + if(sVar != NULL) + { + f4 = sVar->fVal; + } + fprintf(self->fd,"PARAM: W1=%8.4f, W2=%8.4f, W3=%8.4f, W4=%8.4f\n", + f1, f2, f3, f4); + + sVar = FindCommandData(pServ->pSics,"p1","SicsVariable"); + if(sVar != NULL) + { + f1 = sVar->fVal; + } + sVar = FindCommandData(pServ->pSics,"p2","SicsVariable"); + if(sVar != NULL) + { + f2 = sVar->fVal; + } + sVar = FindCommandData(pServ->pSics,"p3","SicsVariable"); + if(sVar != NULL) + { + f3 = sVar->fVal; + } + sVar = FindCommandData(pServ->pSics,"p4","SicsVariable"); + if(sVar != NULL) + { + f4 = sVar->fVal; + } + fprintf(self->fd,"PARAM: P1=%8.4f, P2=%8.4f, P3=%8.4f, P4=%8.4f\n", + f1, f2, f3, f4); + + + } + /* write currents if in polarisation mode */ @@ -639,6 +692,7 @@ static int TASUBScanDrive(pScanData self, int iPoint) int iTAS = 0; pMotor pMot; + pTAS->ub->silent = 1; /* loop through all the scan variables */ @@ -668,6 +722,7 @@ static int TASUBScanDrive(pScanData self, int iPoint) else { status = Wait4Success(GetExecutor()); + pTAS->ub->silent = 0; } return 1; } @@ -776,6 +831,8 @@ static int TASUBScanCount(pScanData self, int iPoint) /* loop over all scan variables */ status = 1; + + pTAS->ub->silent = 0; for(i = 0; i < self->iScanVar; i++) { DynarGet(self->pScanVar,i,&pDings); diff --git a/tasub.c b/tasub.c index b04967b7..0db04c9f 100644 --- a/tasub.c +++ b/tasub.c @@ -241,6 +241,10 @@ int TasUBFactory(SConnection *pCon,SicsInterp *pSics, void *pData, SCWrite(pCon,"ERROR: need name to install tasUB",eError); return 0; } + if(argc > 2 && argc < 14){ + SCWrite(pCon,"ERROR: not enough motor names specified form MakeTasUB",eError); + return 0; + } pNew = MakeTasUB(); if(pNew == NULL){ SCWrite(pCon,"ERROR: out of memory creating tasUB",eError); @@ -250,19 +254,39 @@ int TasUBFactory(SConnection *pCon,SicsInterp *pSics, void *pData, /* assign motors */ - pNew->motors[0] = FindMotor(pSics,"a1"); - pNew->motors[1] = FindMotor(pSics,"a2"); - pNew->motors[2] = FindMotor(pSics,"mcv"); - pNew->motors[3] = FindMotor(pSics,"mch"); - pNew->motors[4] = FindMotor(pSics,"a3"); - pNew->motors[5] = FindMotor(pSics,"a4"); - pNew->motors[6] = FindMotor(pSics,"sgu"); - pNew->motors[7] = FindMotor(pSics,"sgl"); - pNew->motors[8] = FindMotor(pSics,"a5"); - pNew->motors[9] = FindMotor(pSics,"a6"); - pNew->motors[10] = FindMotor(pSics,"acv"); - pNew->motors[11] = FindMotor(pSics,"ach"); - + if(argc < 14){ + /* + * default names and assignement + */ + pNew->motors[0] = FindMotor(pSics,"a1"); + pNew->motors[1] = FindMotor(pSics,"a2"); + pNew->motors[2] = FindMotor(pSics,"mcv"); + pNew->motors[3] = FindMotor(pSics,"mch"); + pNew->motors[4] = FindMotor(pSics,"a3"); + pNew->motors[5] = FindMotor(pSics,"a4"); + pNew->motors[6] = FindMotor(pSics,"sgu"); + pNew->motors[7] = FindMotor(pSics,"sgl"); + pNew->motors[8] = FindMotor(pSics,"a5"); + pNew->motors[9] = FindMotor(pSics,"a6"); + pNew->motors[10] = FindMotor(pSics,"acv"); + pNew->motors[11] = FindMotor(pSics,"ach"); + } else { + /* + * user defined names + */ + pNew->motors[0] = FindMotor(pSics,argv[2]); + pNew->motors[1] = FindMotor(pSics,argv[3]); + pNew->motors[2] = FindMotor(pSics,argv[4]); + pNew->motors[3] = FindMotor(pSics,argv[5]); + pNew->motors[4] = FindMotor(pSics,argv[6]); + pNew->motors[5] = FindMotor(pSics,argv[7]); + pNew->motors[6] = FindMotor(pSics,argv[8]); + pNew->motors[7] = FindMotor(pSics,argv[9]); + pNew->motors[8] = FindMotor(pSics,argv[10]); + pNew->motors[9] = FindMotor(pSics,argv[11]); + pNew->motors[10] = FindMotor(pSics,argv[12]); + pNew->motors[11] = FindMotor(pSics,argv[13]); + } /* curvature motors may be missing, anything else is a serious problem */ @@ -275,6 +299,7 @@ int TasUBFactory(SConnection *pCon,SicsInterp *pSics, void *pData, status += testMotor(pNew, pCon,"a5",A5); status += testMotor(pNew, pCon,"a6",A6); if(status != 8){ + SCWrite(pCon,"ERROR: a required motor is mssing, tasub NOT installed",eError); return 0; } @@ -1489,6 +1514,25 @@ int TasUBWrapper(SConnection *pCon,SicsInterp *pSics, void *pData, SCWrite(pCon,pBueffel,eValue); return 1; } + } else if(strcmp(argv[1],"silent") == 0){ + if(argc > 2){ + strtolower(argv[2]); + if(!SCMatchRights(pCon,usUser)){ + return 0; + } + status = Tcl_GetInt(InterpGetTcl(pSics),argv[2],&newSS); + if(status != TCL_OK){ + SCWrite(pCon,"ERROR: failed to convert argument to number",eError); + return 0; + } + self->silent = newSS; + SCSendOK(pCon); + return 1; + } else { + snprintf(pBueffel,131,"%s.silent = %d",argv[0],self->silent); + SCWrite(pCon,pBueffel,eValue); + return 1; + } } else { snprintf(pBueffel,131,"ERROR: subcommand %s to %s not defined",argv[1], argv[0]); diff --git a/tasub.h b/tasub.h index ac97a2de..1d22c3ab 100644 --- a/tasub.h +++ b/tasub.h @@ -30,6 +30,7 @@ pMotor motors[12]; tasReflection r1, r2; int ubValid; + int silent; }tasUB, *ptasUB; diff --git a/tasub.w b/tasub.w index afd15d07..a74ba7f1 100644 --- a/tasub.w +++ b/tasub.w @@ -32,6 +32,7 @@ A data structure: pMotor motors[12]; tasReflection r1, r2; int ubValid; + int silent; }tasUB, *ptasUB; @} \begin{description} @@ -55,6 +56,9 @@ A data structure: runtime. \item[r1,r2] The indexs of the reflections used for calculating the orientation matrix. +\item[ubValid] a flag denoting if the UB is valid. +\item[silent] A flga which when 1 suppresses the printing of motor positions + when driving. Usefule for scans. \end{description} For the virtual motors, there must be a data structure, too: diff --git a/tclintimpl.c b/tclintimpl.c index f64bf7b1..ec3b16f5 100644 --- a/tclintimpl.c +++ b/tclintimpl.c @@ -162,7 +162,7 @@ int TclIntAction(SConnection *pCon, SicsInterp *pSics, void *pData, cmd = Arg2Tcl(argc-2, &argv[2],pBuffer,1023); if (cmd) { if(self->fd != NULL){ - fprintf(self->fd,"%s\n",pBuffer); + fprintf(self->fd,"%s\n",cmd); } if (cmd != pBuffer) free(cmd); SCSendOK(pCon); diff --git a/ubcalc.c b/ubcalc.c index e78bf3ea..6948264f 100644 --- a/ubcalc.c +++ b/ubcalc.c @@ -541,6 +541,7 @@ static int cellFromUBWrapper(pUBCALC self, SConnection *pCon){ int UBCalcWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]){ pUBCALC self = (pUBCALC)pData; + char pBuffer[512]; assert(self); if(argc < 2){ @@ -550,7 +551,15 @@ int UBCalcWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, strtolower(argv[1]); if(strcmp(argv[1],"cell") == 0){ - return readCell(pCon, self, argc, argv); + if(argc > 3){ + return readCell(pCon, self, argc, argv); + } else { + snprintf(pBuffer,511,"ubcalc cell = %f %f %f %f %f %f", + self->direct.a, self->direct.b, self->direct.c, + self->direct.alpha, self->direct.beta,self->direct.gamma); + SCWrite(pCon,pBuffer,eValue); + return 1; + } } else if(strcmp(argv[1],"ref1") == 0){ return readReflection(pCon,pSics, &self->r1,argc,argv); } else if(strcmp(argv[1],"ref2") ==0){ diff --git a/varlog.c b/varlog.c index 16b5cd22..806821d6 100644 --- a/varlog.c +++ b/varlog.c @@ -120,6 +120,7 @@ { deleteCircular(self->pTail); } + free(self); /* M.Z. */ return 1; } /*--------------------------------------------------------------------------*/