diff --git a/SCinter.c b/SCinter.c index 611fca13..aa64ea9f 100644 --- a/SCinter.c +++ b/SCinter.c @@ -270,10 +270,10 @@ extern char *SkipSpace(char *pPtr); assert(pCon); /* write info to Log */ - if(pCon->pSock) + if(pCon->sockHandle >= 0) { sprintf(pBueffel,"Executing -> %s <- from socket %d",pText, - pCon->pSock->sockid); + pCon->sockHandle); SICSLogWrite(pBueffel,eCommand); } else @@ -282,6 +282,7 @@ extern char *SkipSpace(char *pPtr); SICSLogWrite(pBueffel,eCommand); } + /* convert to argc, argv */ argc = 0; argv = NULL; @@ -315,7 +316,7 @@ extern char *SkipSpace(char *pPtr); /* invoke the command */ - self->eOut = eStatus; + self->eOut = eValue; Tcl_ResetResult((Tcl_Interp *)self->pTcl); MacroPush(pCon); pCon->conStatus = 0; @@ -324,8 +325,8 @@ extern char *SkipSpace(char *pPtr); StatisticsEnd(old); /* If a task is registered with the dev exec then conStatus is HWBusy*/ if (pCon->conStatus != HWBusy) { - comCon = SCGetContext(pCon); - if (0 != strcmp("contextdo",comCon.deviceID)) + /*comCon = SCGetContext(pCon);*/ + if (0 != strcmp("contextdo",pCon->deviceID)) SCWrite(pCon,"",eFinish); } MacroPop(); @@ -552,7 +553,7 @@ static void printAll(SicsInterp *pSics, SConnection *pCon) strcat(pBueffel," "); strcat(pBueffel,pCurrent->pName); strcat(pBueffel,"\r\n"); - SCWrite(pCon,pBueffel,eStatus); + SCWrite(pCon,pBueffel,eValue); iNum = 0; pBueffel[0]='\0'; } @@ -563,7 +564,7 @@ static void printAll(SicsInterp *pSics, SConnection *pCon) if(strlen(pBueffel) > 2) { strcat(pBueffel,"\r\n"); - SCWrite(pCon,pBueffel,eStatus); + SCWrite(pCon,pBueffel,eValue); } } /*------------------------------------------------------------------------*/ @@ -597,7 +598,7 @@ static void printAllTypes(SicsInterp *pSics, SConnection *pCon, int iFiltered) if(-1==typeListID) { strcpy(pBueffel,"ERROR: Cannot generate list of object types\r\n"); - SCWrite(pCon,pBueffel,eStatus); + SCWrite(pCon,pBueffel,eValue); return; } @@ -679,7 +680,7 @@ static void printInterface(SicsInterp *pSics, SConnection *pCon, int id) strcat(pBueffel," "); strcat(pBueffel,pCurrent->pName); strcat(pBueffel,"\r\n"); - SCWrite(pCon,pBueffel,eStatus); + SCWrite(pCon,pBueffel,eValue); iNum = 0; pBueffel[0]='\0'; } @@ -690,7 +691,7 @@ static void printInterface(SicsInterp *pSics, SConnection *pCon, int id) /* write final entries */ strcat(pBueffel,"\r\n"); - SCWrite(pCon,pBueffel,eStatus); + SCWrite(pCon,pBueffel,eValue); } /*----------------------------------------------------------------------- printMatch prints only those objects which match the wildcard string given @@ -732,7 +733,7 @@ static void printMatch(SicsInterp *pSics, SConnection *pCon, char *mask) strcat(pBueffel," "); strcat(pBueffel,pCurrent->pName); strcat(pBueffel,"\r\n"); - SCWrite(pCon,pBueffel,eStatus); + SCWrite(pCon,pBueffel,eValue); pBueffel[0]='\0'; iNum = 0; } @@ -743,7 +744,7 @@ static void printMatch(SicsInterp *pSics, SConnection *pCon, char *mask) /* write final entries */ strcat(pBueffel,"\r\n"); - SCWrite(pCon,pBueffel,eStatus); + SCWrite(pCon,pBueffel,eValue); } /*----------------------------------------------------------------------- printType prints only those objects whose descriptor match the type given @@ -794,7 +795,7 @@ static void printType(SicsInterp *pSics, SConnection *pCon, char *typeName) /* write final entries */ strcat(pBueffel,"\r\n"); - SCWrite(pCon,Tcl_DStringValue(&txt),eStatus); + SCWrite(pCon,Tcl_DStringValue(&txt),eValue); Tcl_DStringFree(&txt); } /*--------------------------------------------------------------------------*/ @@ -1042,7 +1043,7 @@ static void printList(SConnection *pCon, int listID) if ((MAXBUF-3) > retCode) { retCode = LLDstringData(listID,pBueffel); strcat(pBueffel,"\r\n"); - SCWrite(pCon,pBueffel,eStatus); + SCWrite(pCon,pBueffel,eValue); } } while(0!=LLDnodePtr2Next(listID)); } diff --git a/Scommon.h b/Scommon.h index bf7da342..c65443d0 100644 --- a/Scommon.h +++ b/Scommon.h @@ -40,19 +40,21 @@ /* this enum defines the output types in SICS */ typedef enum { - eInternal, - eCommand, - eHWError, - eInError, - eStatus, - eValue, - eStart, - eFinish, - eEvent, - eWarning, - eError, - eHdbValue, - eHdbEvent + eInternal, /* internal */ + eCommand, /* reserved, not used */ + eHWError, /* reserved, used only for SICSLog */ + eInError, /* reserved, used as a mark in the handling of output codes */ + eStatus, /* reserved, deprecated */ + eValue, /* value reponse: copied into Tcl */ + eStart, /* start message */ + eFinish, /* finish message */ + eEvent, /* some callback messages */ + eWarning, /* warnings */ + eError, /* error: copied into Tcl */ + eHdbValue, /* hipadaba value chnage */ + eHdbEvent, /* Hipadaba event */ + eLog, /* log message: is always written to client */ + eLogError /* error message to log: is always written to client */ } OutCode; #include "interrupt.h" diff --git a/ascon.c b/ascon.c index 68f0641b..fd333752 100644 --- a/ascon.c +++ b/ascon.c @@ -305,7 +305,9 @@ int AsconStdHandler(Ascon *a) { l = GetDynStringLength(a->wrBuffer) - a->wrPos; ret = AsconWriteChars(a->fd, GetCharArray(a->wrBuffer) + a->wrPos, l); if (ret < 0) { - AsconError(a, "send failed:", errno); + if(errno != EINTR && errno != EAGAIN){ + AsconError(a, "send failed:", errno); + } /* * Ooops: which state shall we go to after a write fail? * This seems to retry. @@ -352,7 +354,10 @@ int AsconStdHandler(Ascon *a) { ret = AsconReadChar(a->fd, &chr); } if (ret < 0) { - AsconError(a, "AsconReadChar failed:", errno); + /* EINTR means we shall retry */ + if(errno != EINTR && errno != EAGAIN){ + AsconError(a, "AsconReadChar failed:", errno); + } return 1; } if (a->state == AsconReadDone) { @@ -453,6 +458,13 @@ void AsconKill(Ascon *a) { } free(a); } +void AsconDisconnect(Ascon *a){ + if(a->fd > 0){ + close(a->fd); + } + a->fd = -1; + a->state = AsconConnectStart; +} AsconStatus AsconTask(Ascon *a) { double now; @@ -491,6 +503,8 @@ AsconStatus AsconTask(Ascon *a) { if (now > a->lastReconnect + a->reconnectInterval) { a->lastReconnect = now; close(a->fd); + /* allow the system to cleanup the socket, otherwise a reconnect will fail*/ + sleep(1); a->fd = -1; a->state = AsconConnectStart; } diff --git a/ascon.h b/ascon.h index fe6f4d32..e54306e1 100644 --- a/ascon.h +++ b/ascon.h @@ -36,6 +36,10 @@ Ascon *AsconMake(SConnection *con, int argc, char *argv[]); * \param a the connection to be killed */ void AsconKill(Ascon *a); +/** \brief Disconnect function + * \param a the connection to disconnect + */ +void AsconDisconnect(Ascon *a); /** \brief the task handler. To be called repeatedly. * \param a the connection diff --git a/asyncqueue.c b/asyncqueue.c index a86f561e..62ec857e 100644 --- a/asyncqueue.c +++ b/asyncqueue.c @@ -648,7 +648,7 @@ int AsyncQueueAction(SConnection *pCon, SicsInterp *pSics, } else { snprintf(line, 132, "%s.delay = %d", argv[0], self->iDelay); - SCWrite(pCon, line, eStatus); + SCWrite(pCon, line, eValue); return OKOK; } return OKOK; @@ -675,7 +675,7 @@ int AsyncQueueAction(SConnection *pCon, SicsInterp *pSics, } else { snprintf(line, 132, "%s.timeout = %d", argv[0], self->timeout); - SCWrite(pCon, line, eStatus); + SCWrite(pCon, line, eValue); return OKOK; } return OKOK; @@ -702,7 +702,7 @@ int AsyncQueueAction(SConnection *pCon, SicsInterp *pSics, } else { snprintf(line, 132, "%s.retries = %d", argv[0], self->retries); - SCWrite(pCon, line, eStatus); + SCWrite(pCon, line, eValue); return OKOK; } return OKOK; diff --git a/background.c b/background.c new file mode 100644 index 00000000..ec67e2a1 --- /dev/null +++ b/background.c @@ -0,0 +1,87 @@ +/** + * This is for backgrounding operations in SICS. They run in an own + * task. + * + * copyright: see file COPYRIGHT + * + * Mark Koennecke, February 2009 + */ +#include +#include "splitter.h" +#include "background.h" + +/*---------------------------------------------------------------------------*/ +typedef struct { + SConnection *con; + char *command; +} BckTask, *pBckTask; +/*---------------------------------------------------------------------------*/ +static void KillBckTask(void *data){ + pBckTask self = (pBckTask)data; + if(self == NULL){ + return; + } + if(self->con){ + SCDeleteConnection(self->con); + } + if(self->command){ + free(self->command); + } +} +/*---------------------------------------------------------------------------*/ +static int BackgroundTask(void *data){ + pBckTask self = (pBckTask)data; + + assert(self != NULL); + + InterpExecute(pServ->pSics,self->con,self->command); + return 0; +} +/*----------------------------------------------------------------------------*/ +int BackgroundCommand(SConnection *pCon, char *command){ + pBckTask self = NULL; + + self = calloc(1,sizeof(BckTask)); + if(self == NULL){ + return 0; + } + + self->con = SCCopyConnection(pCon); + self->command = strdup(command); + if(self->con == NULL || self->command == NULL){ + free(self); + return 0; + } + + TaskRegister(pServ->pTasker, + BackgroundTask, + NULL, + KillBckTask, + self, + 1); + return 1; +} +/*------------------------------------------------------------------------*/ +int BackgroundAction(SConnection *pCon, SicsInterp *pSics, + void *pData, int argc, char *argv[]){ + int status; + char command[1024]; + + memset(command,0,1024); + Arg2Text(argc-1,&argv[1], command, 1024); + status = BackgroundCommand(pCon,command); + if(status == 0){ + SCWrite(pCon,"ERROR: out of memory starting task", eError); + return 0; + } + SCSendOK(pCon); + return 1; +} +/*--------------------------------------------------------------------------*/ +void InstallBackground(SicsInterp *pSics){ + AddCommand(pSics, + "bg", + BackgroundAction, + NULL, + NULL); +} diff --git a/background.h b/background.h new file mode 100644 index 00000000..fb065cab --- /dev/null +++ b/background.h @@ -0,0 +1,26 @@ +/** + * This is for backgrounding operations in SICS. They run in an own + * task. + * + * copyright: see file COPYRIGHT + * + * Mark Koennecke, February 2009 + */ +#ifndef BACKGROUND_H_ +#define BACKGROUND_H_ + +/** + * interpreter inteface + */ +int BackgroundAction(SConnection *pCon, SicsInterp *pSics, + void *pData, int argc, char *argv[]); +/* + * actual function which does the backgrounding + */ +int BackgroundCommand(SConnection *pCon, char *command); +/* + * used only once for installing Background +*/ +void InstallBackground(SicsInterp *pSics); + +#endif /*BACKGROUND_H_*/ diff --git a/callback.c b/callback.c index beffabab..e1bef5a9 100644 --- a/callback.c +++ b/callback.c @@ -50,22 +50,24 @@ #include "splitter.h" #define CALLBACK 17777 +static int debug = 0; -/*--------------------- The interface datastructure ---------------------*/ - typedef struct __ICallBack { - int iID; - int iList; - } ICallBack; - /*-------------- The data stored for a single callback ------------------*/ - typedef struct { + typedef struct __CBItem{ long iID; SICSCallBack pFunc; void *pUserData; KillFuncIT pKill; int iEvent; - commandContext comCon; + int killFlag; + struct __CBItem *next; } CallBackItem, *pCallBackItem; +/*--------------------- The interface datastructure ---------------------*/ + typedef struct __ICallBack { + int iID; + pCallBackItem head; + } ICallBack; + /*------------------------------------------------------------------------*/ static int CheckPointer(pICallBack self) { @@ -89,19 +91,14 @@ } pNew->iID = CALLBACK; - pNew->iList = LLDcreate(sizeof(CallBackItem)); - if(pNew->iList < 0) - { - free(pNew); - return NULL; - } + pNew->head = NULL; return pNew; } /*--------------------------------------------------------------------------*/ void DeleteCallBackInterface(pICallBack self) { int iRet; - CallBackItem sItem; + pCallBackItem pItem, pTmp; if(!CheckPointer(self)) { @@ -109,73 +106,160 @@ } /* kill all userdata associated with callbacks */ - iRet = LLDnodePtr2First(self->iList); - while(iRet != 0) + pItem = self->head; + while(pItem != NULL) { - LLDnodeDataTo(self->iList,&sItem); - if(sItem.pKill != NULL) - { - sItem.pKill(sItem.pUserData); - } - iRet = LLDnodePtr2Next(self->iList); + pTmp = pItem->next; + if(pItem->pKill != NULL) + { + pItem->pKill(pItem->pUserData); + } + free(pItem); + pItem = pTmp; } - - LLDdelete(self->iList); - free(self); + free(self); } +/*--------------------------------------------------------------------------*/ +static void markUserdata4Kill(pICallBack self, void *pData) +{ + pCallBackItem pItem = NULL; + + pItem = self->head; + while(pItem != NULL){ + if(pData != NULL && pItem->pUserData == pData) + { + pItem->killFlag = 1; + } + pItem = pItem->next; + } +} +/*-------------------------------------------------------------------------*/ +static void cleanCallbackList(pICallBack self) +{ + pCallBackItem toKill, current; + + /* + * killing at the head + */ + while(self->head != NULL && self->head->killFlag == 0){ + toKill = self->head; + self->head = toKill->next; + if(toKill->pKill != NULL){ + toKill->pKill(toKill->pUserData); + } + free(toKill); + } + + if(self->head == NULL){ + return; + } + + /* + * killing in the middle and the end + */ + current = self->head; + while(current->next != NULL){ + if(current->next->killFlag == 1){ + toKill = current->next; + current->next = toKill->next; + if(toKill->pKill != NULL){ + toKill->pKill(toKill->pUserData); + } + free(toKill); + } else { + current = current->next; + } + } +} /*--------------------------------------------------------------------------*/ int InvokeCallBack(pICallBack self, int iEvent, void *pEventData) { - CallBackItem sItem; + pCallBackItem pItem; int iCurrent, iRet; - int iResult = 1; + int iResult = 1, iKill = 0;; if(!CheckPointer(self)) { return 0; } - iCurrent = LLDnodePtr2First(self->iList); - while(iCurrent != 0) + pItem = self->head; + while(pItem != NULL) { - LLDnodeDataTo(self->iList,&sItem); - if(sItem.iEvent == iEvent) + if(pItem->iEvent == iEvent && pItem->killFlag == 0) { - iRet = sItem.pFunc(iEvent, pEventData,sItem.pUserData,sItem.comCon); - if(!iRet) + iRet = pItem->pFunc(iEvent, pEventData,pItem->pUserData); + if(iRet < 0) + { + pItem->killFlag = 1; + if(pItem->pUserData != NULL) + { + markUserdata4Kill(self, pItem->pUserData); + iKill = 1; + } + } + else if(iRet != 1) { iResult = 0; } } - iCurrent = LLDnodePtr2Next(self->iList); + pItem = pItem->next; } + + /* kill run */ + if(iKill == 1){ + cleanCallbackList(self); + } + return iResult; } /*--------------------------------------------------------------------------*/ static long lCount = 1L; - long RegisterCallback(pICallBack self, commandContext comCon, int iEvent, + long RegisterCallback(pICallBack self, int iEvent, SICSCallBack pFunc, void *pUserData, KillFunc pKFunc) { - CallBackItem sItem; + pCallBackItem pItem = NULL; if(!CheckPointer(self)) { return 0; } - sItem.iID = lCount++; + pItem = calloc(1,sizeof(CallBackItem)); + if(pItem == NULL){ + return -1; + } + pItem->iID = lCount++; assert(pFunc); - sItem.pFunc = pFunc; - sItem.iEvent = iEvent; - sItem.pUserData = pUserData; - sItem.pKill = pKFunc; - sItem.comCon = comCon; - - LLDnodeAppendFrom(self->iList,&sItem); - return sItem.iID; + pItem->pFunc = pFunc; + pItem->iEvent = iEvent; + pItem->pUserData = pUserData; + pItem->pKill = pKFunc; + pItem->killFlag = 0; + pItem->next = self->head; + self->head = pItem; + if(debug){ + printf("Registered callback at %p\n",self); + } + return pItem->iID; } +/*------------------------------------------------------------------------*/ +static void markById(pICallBack self, int lID) +{ + pCallBackItem pItem = NULL; + + pItem = self->head; + while(pItem != NULL) + { + if(pItem->iID == lID) + { + pItem->killFlag = 1; + } + pItem = pItem->next; + } +} /*-------------------------------------------------------------------------*/ int RemoveCallback(pICallBack self, long lID) { @@ -186,22 +270,8 @@ { return 0; } - - iCurrent = LLDnodePtr2First(self->iList); - while(iCurrent != 0) - { - LLDnodeDataTo(self->iList,&sItem); - if(sItem.iID == lID) - { - if(sItem.pKill != NULL) - { - sItem.pKill(sItem.pUserData); - } - LLDnodeDelete(self->iList); - return 1; - } - iCurrent = LLDnodePtr2Next(self->iList); - } + markById(self,lID); + cleanCallbackList(self); return 0; } /*--------------------------------------------------------------------------*/ @@ -214,23 +284,37 @@ { return 0; } - - iCurrent = LLDnodePtr2First(self->iList); - while(iCurrent != 0) - { - LLDnodeDataTo(self->iList,&sItem); - if(sItem.pUserData == pUserData) - { - if(sItem.pKill != NULL) - { - sItem.pKill(sItem.pUserData); - } - LLDnodeDelete(self->iList); - } - iCurrent = LLDnodePtr2Next(self->iList); - } + markUserdata4Kill(self,pUserData); + cleanCallbackList(self); return 1; } + /*--------------------------------------------------------------------------*/ + int RemoveCallbackCon(pICallBack self, SConnection *con) + { + pCallBackItem pItem; + SConnection *tst = NULL; + + if(!CheckPointer(self)) + { + return 0; + } + + pItem = self->head; + while(pItem != NULL) + { + tst = (SConnection *)pItem->pUserData; + if(VerifyConnection(tst) && tst->ident == con->ident) + { + if(debug){ + printf("Killing callback on connection.ident = %ld\n", con->ident); + } + pItem->killFlag = 1; + } + pItem = pItem->next; + } + cleanCallbackList(self); + return 1; + } /*------------------------------------------------------------------- a write function for the connection which writes to stdout -------------------------------------------------------------------*/ @@ -246,8 +330,7 @@ static int CallbackWrite(SConnection *pCon,char *message, int outCode) /*----------------------------------------------------------------------- the actual callback function invoking the script ------------------------------------------------------------------------*/ -static int ScriptCallback(int iEvent, void *pEventData, void *pUserData, - commandContext cc) +static int ScriptCallback(int iEvent, void *pEventData, void *pUserData) { SConnection *pCon = NULL; Tcl_Interp *pTcl; @@ -264,18 +347,6 @@ static int ScriptCallback(int iEvent, void *pEventData, void *pUserData, fprintf(stdout,"ERROR: ScriptCallback: no script to execute\n"); return 0; } - /* - SCSetWriteFunc(pCon,CallbackWrite); - MacroPush(pCon); - pTcl = InterpGetTcl(pServ->pSics); - status = Tcl_Eval(pTcl,(char *)pUserData); - if(status != TCL_OK) - { - fprintf(stdout,"ERROR: in CallbackScript: %s\n",(char *)pUserData); - fprintf(stdout,"Tcl-error: %s\n",pTcl->result); - } - MacroPop(); - */ SCSetRights(pCon,usInternal); status = InterpExecute(pServ->pSics,pCon,(char *)pUserData); @@ -335,7 +406,7 @@ int CallbackScript(SConnection *pCon, SicsInterp *pSics, void *pData, return 0; } Arg2Text(argc-4,&argv[4],pBuffer,131); - lID = RegisterCallback(pCall,SCGetContext(pCon), + lID = RegisterCallback(pCall, iEvent,ScriptCallback, strdup(pBuffer),free); sprintf(pBuffer,"callback = %ld", lID); diff --git a/cone.c b/cone.c index 4fc4d5d9..b0f4fe8f 100644 --- a/cone.c +++ b/cone.c @@ -5,6 +5,10 @@ COPYRIGHT: see file COPYRIGHT Mark Koennecke, March 2006 + + Reworked for new four circle infrastructure. + + Mark Koennecke, August 2008 ------------------------------------------------------------------------*/ #include #include @@ -12,11 +16,15 @@ #include "hkl.i" #include "vector.h" #include "fourlib.h" +#include "singlex.h" +#include "sicsobj.h" +#include "sicshipadaba.h" /*=================== Object Descriptor Interface ===================================================*/ static void *ConeGetInterface(void *pData, int iID){ pConeData self = NULL; + pSICSOBJ obj = (pSICSOBJ)pData; - self = (pConeData)pData; + self = (pConeData)obj->pPrivate; if(self == NULL){ return NULL; } @@ -25,28 +33,15 @@ static void *ConeGetInterface(void *pData, int iID){ } return NULL; } -/*---------------------------------------------------------------------------------------------------*/ -static void ConeSaveStatus(void *data, char *name, FILE *fd){ - pConeData self = (pConeData)data; - if(self == NULL){ - return; - } - fprintf(fd,"%s center %d\n", name,self->center); - fprintf(fd,"%s target %f %f %f\n", name, self->target.h, - self->target.k, self->target.l); - fprintf(fd,"%s qscale %f \n", name, self->qScale); -} /*=================== Drivable Interface ============================================================*/ static int ConeHalt(void *pData){ + pSICSOBJ obj = pData; pConeData self = NULL; - self = (pConeData)pData; + self = (pConeData)obj->pPrivate; assert(self != NULL); - - self->pHkl->pTheta->pDrivInt->Halt(self->pHkl->pTheta); - self->pHkl->pOmega->pDrivInt->Halt(self->pHkl->pOmega); - self->pHkl->pChi->pDrivInt->Halt(self->pHkl->pChi); - self->pHkl->pPhi->pDrivInt->Halt(self->pHkl->pPhi); + + stopHKLMotors(self->pHkl); return 1; } /*-----------------------------------------------------------------------------------------------------*/ @@ -62,7 +57,7 @@ static int ConeCheckLimits(void *self, float fVal, char *error, int errLen){ static MATRIX makeCsToPsiMatrix(reflection center, double lambda){ MATRIX psiToCs = NULL, csToPsi = NULL, t1, t2; double z1[3], u; - + psiToCs = makeInstToConeVectorMatrix(center,lambda); if(psiToCs == NULL){ return NULL; @@ -88,37 +83,71 @@ static MATRIX makeCsToPsiMatrix(reflection center, double lambda){ * me a lot of trouble keeping track of parameter changes in UBCALC etc. * ---------------------------------------------------------------------------*/ static long ConeSetValue(void *pData, SConnection *pCon, float fVal){ + pSICSOBJ obj = pData, refList; pConeData self = NULL; - float fSet[4]; + double fSet[4]; + float ffSet[4]; double openingAngle, length; MATRIX csToPsi = NULL, B = NULL, newScat = NULL; - int status; - reflection center; + int status, i; + reflection center, target; char buffer[131]; - + const double *cell; + double hkl[3], ang[4]; + lattice direct; + hdbValue v; + if(!SCMatchRights(pCon,usUser)){ return 0; } - self = (pConeData)pData; + self = (pConeData)obj->pPrivate; assert(self != NULL); /* * calculate opening angle */ B = mat_creat(3,3,UNIT_MATRIX); - status = calculateBMatrix(self->ubi->direct,B); + cell = SXGetCell(); + direct.a = cell[0]; + direct.b = cell[1]; + direct.c = cell[2]; + direct.alpha = cell[3]; + direct.beta = cell[4]; + direct.gamma = cell[5]; + status = calculateBMatrix(direct,B); if(status < 0){ SCWrite(pCon,"ERROR: cell has no volume",eError); return 0; } - center = getReflection(self->ubi,self->center); - openingAngle = angleBetweenReflections(B,center,self->target); + /* + * get center from the main reflection list + */ + refList = SXGetReflectionList(); + SICSHdbGetPar(obj,pCon,"center", &v); + if(!GetRefIndexID(refList,v.v.text,hkl)){ + SCPrintf(pCon,eError,"ERROR: cannot find reflection with ID: %s", v.v.text); + return 0; + } + center.h = hkl[0]; + center.k = hkl[1]; + center.l = hkl[2]; + GetRefAnglesID(refList,v.v.text,ang); + center.s2t = ang[0]; + center.om = ang[1]; + center.chi = ang[2]; + center.phi = ang[3]; + + SICSHdbGetPar(obj,pCon,"target",&v); + target.h = v.v.floatArray[0]; + target.k = v.v.floatArray[1]; + target.l = v.v.floatArray[2]; + openingAngle = angleBetweenReflections(B,center,target); /* * calculate conversion matrix from cone system to PSI system */ - csToPsi = makeCsToPsiMatrix(center,self->ubi->hkl->fLambda); + csToPsi = makeCsToPsiMatrix(center,SXGetLambda()); if(csToPsi == NULL){ SCWrite(pCon,"ERROR: bad parameters: failed to generate conversion matrix", eError); @@ -129,7 +158,16 @@ static long ConeSetValue(void *pData, SConnection *pCon, float fVal){ * calculate scattering vector on cone and make its length * match the length of the apropriate scattering vector */ - length = scatteringVectorLength(B,self->target) * self->qScale; + SICSHdbGetPar(obj,pCon,"target",&v); + target.h = v.v.floatArray[0]; + target.k = v.v.floatArray[1]; + target.l = v.v.floatArray[2]; + SICSHdbGetPar(obj,pCon,"qscale",&v); + /* + * calculate scattering vector on cone and make its length + * match the length of the apropriate scattering vector + */ + length = scatteringVectorLength(B,target) * v.v.doubleValue; newScat = calcConeVector(openingAngle, fVal, length, csToPsi); if(newScat == NULL){ SCWrite(pCon,"ERROR: fails to calculate cone vector",eError); @@ -139,7 +177,7 @@ static long ConeSetValue(void *pData, SConnection *pCon, float fVal){ /* * try to find setting angles for this vector */ - status = findAllowedBisecting(self->pHkl->fLambda,newScat, fSet, + status = findAllowedBisecting(SXGetLambda(),newScat, fSet, hklInRange, self->pHkl); /* * clean up matrices @@ -157,201 +195,119 @@ static long ConeSetValue(void *pData, SConnection *pCon, float fVal){ /* * start motors */ - return startHKLMotors(self->pHkl, pCon,fSet); + for(i = 0; i < 4; i++){ + ffSet[i] = fSet[i]; + } + return startHKLMotors(self->pHkl, pCon,ffSet); } /*---------------------------------------------------------------------------------------------------*/ static int checkMotors(pConeData self, SConnection *pCon){ - int status; - - status = self->pHkl->pTheta->pDrivInt->CheckStatus(self->pHkl->pTheta, pCon); - if(status != HWIdle && status != OKOK){ - return status; - } - status = self->pHkl->pOmega->pDrivInt->CheckStatus(self->pHkl->pOmega, pCon); - if(status != HWIdle && status != OKOK){ - return status; - } - status = self->pHkl->pChi->pDrivInt->CheckStatus(self->pHkl->pChi, pCon); - if(status != HWIdle && status != OKOK){ - return status; - } - status = self->pHkl->pPhi->pDrivInt->CheckStatus(self->pHkl->pPhi, pCon); - if(status != HWIdle && status != OKOK){ - return status; + int status, i; + pMotor pMot = NULL; + MotorFunction mots[] = {TwoTheta, Omega, Chi, Phi}; + + for(i = 0; i < 4; i++){ + pMot = SXGetMotor(mots[i]); + if(pMot != NULL){ + status = pMot->pDrivInt->CheckStatus(pMot, pCon); + if(status != HWIdle && status != OKOK){ + return status; + } + } } return HWIdle; } /*-----------------------------------------------------------------------------------------------------*/ static int ConeCheckStatus(void *pData, SConnection *pCon){ + pSICSOBJ obj = pData; pConeData self = NULL; int status; - self = (pConeData)pData; + self = (pConeData)obj->pPrivate; assert(self != NULL); return checkMotors(self,pCon); } /*-----------------------------------------------------------------------------------------------------*/ static float ConeGetValue(void *pData, SConnection *pCon){ + pSICSOBJ obj = pData; pConeData self = NULL; float fVal[3]; int status; - self = (pConeData)pData; + self = (pConeData)obj->pPrivate; assert(self != NULL); return self->lastConeAngle; } /*=============================== Live and Death ====================================*/ -static pConeData MakeConeMot(pUBCALC u){ +static pConeData MakeConeMot(){ pConeData self = NULL; - assert(u != NULL); - self = (pConeData)malloc(sizeof(coneData)); if(self == NULL){ return NULL; } memset(self,0,sizeof(coneData)); - self->pDes = CreateDescriptor("Cone"); self->pDriv = CreateDrivableInterface(); - if(self->pDes == NULL || self->pDriv == NULL){ + if(self->pDriv == NULL){ free(self); return NULL; } - self->pDes->GetInterface = ConeGetInterface; + self->pDriv->Halt = ConeHalt; self->pDriv->CheckLimits = ConeCheckLimits; self->pDriv->SetValue = ConeSetValue; self->pDriv->CheckStatus = ConeCheckStatus; self->pDriv->GetValue = ConeGetValue; - self->ubi = u; - self->pHkl = u->hkl; - self->qScale = 1.0; return self; } -/*----------------------------------------------------------------------------------*/ -static void KillConeMot(void *pData){ - pConeData self = NULL; - - self = (pConeData)pData; - if(self == NULL){ - return; - } - if(self->pDes != NULL){ - DeleteDescriptor(self->pDes); - } - if(self->pDriv){ - free(self->pDriv); - } - free(self); -} -/*=============================== Interpreter Interface ============================*/ -int ConeAction(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]){ - pConeData self = NULL; - float value; - int id; - char pBuffer[132]; - - self = (pConeData)pData; - assert(self != NULL); - - if(argc > 1) { - strtolower(argv[1]); - if(strcmp(argv[1],"center") == 0){ - if(argc > 2){ - if(!SCMatchRights(pCon,usUser)){ - return 0; - } - id = atoi(argv[2]); - if(id < 0 || id > 2 ){ - SCWrite(pCon,"ERROR: id must be between 0 - 3",eError); - return 0; - } - self->center = id; - SCSendOK(pCon); - return 1; - } else { - snprintf(pBuffer,131,"%s.center = %d", argv[0], self->center); - SCWrite(pCon,pBuffer,eValue); - return 1; - } - } else if(strcmp(argv[1],"qscale") == 0){ - if(argc > 2){ - if(!SCMatchRights(pCon,usUser)){ - return 0; - } - self->qScale = atof(argv[2]); - SCSendOK(pCon); - return 1; - } else { - snprintf(pBuffer,131,"%s.qscale = %f", argv[0], self->qScale); - SCWrite(pCon,pBuffer,eValue); - return 1; - } - } else if (strcmp(argv[1],"target") == 0){ - if(argc >= 5){ - if(!SCMatchRights(pCon,usUser)){ - return 0; - } - self->target.h = atof(argv[2]); - self->target.k = atof(argv[3]); - self->target.l = atof(argv[4]); - self->qScale = 1.; - SCSendOK(pCon); - return 1; - } else { - snprintf(pBuffer,131,"%s.target = %f %f %f", argv[0], - self->target.h, self->target.k, self->target.l); - SCWrite(pCon,pBuffer,eValue); - return 1; - } - } else { - SCWrite(pCon,"ERROR: subcommand to cone not known",eError); - return 0; - } - } - - /* - * default: print value - */ - value = self->pDriv->GetValue(self,pCon); - if(value < -9000.){ - snprintf(pBuffer,131,"ERROR: failed to read %s",argv[0]); - SCWrite(pCon,pBuffer,eError); - return 0; - } - snprintf(pBuffer,131,"%s = %f", argv[0], value); - SCWrite(pCon,pBuffer,eValue); - return 1; -} /*------------------------------------------------------------------------------------------*/ int MakeCone(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]){ - pUBCALC ubi = NULL; + pSICSOBJ pNew = NULL; pConeData pMot = NULL; - char pBuffer[131]; + char pBuffer[131], pName[80]; int status; + pHdb cmd; + + if(argc > 1){ + strcpy(pName,argv[1]); + } else { + strcpy(pName,"cone"); + } - if(argc < 3){ - SCWrite(pCon,"ERROR: insuffient number of arguments to MakeCone",eError); - return 0; - } - - ubi = FindCommandData(pSics,argv[2],"UBcalc"); - if(ubi == NULL){ - snprintf(pBuffer,131,"ERROR: %s is no UBcalc object" , argv[2]); - SCWrite(pCon,pBuffer,eError); - return 0; - } - - pMot = MakeConeMot(ubi); - if(pMot == NULL){ + pNew = MakeSICSOBJ(pName,"Cone"); + pMot = MakeConeMot(); + if(pNew == NULL || pMot == NULL){ SCWrite(pCon,"ERROR: out of memory creating cone virtual motor",eError); return 0; } - status = AddCommand(pSics,argv[1],ConeAction,KillConeMot,pMot); + + pNew->pDes->GetInterface = ConeGetInterface; + pNew->pPrivate = pMot; + pNew->KillPrivate = DefaultFree; + + cmd = AddSICSHdbPar(pNew->objectNode,"target", usUser, makeHdbValue(HIPFLOATAR,3)); + SetHdbProperty(cmd,"__save", "true"); + cmd = AddSICSHdbPar(pNew->objectNode,"qscale", usUser, MakeHdbFloat(1.)); + SetHdbProperty(cmd,"__save", "true"); + cmd = AddSICSHdbPar(pNew->objectNode,"center", usUser, MakeHdbText("unknown")); + SetHdbProperty(cmd,"__save", "true"); + + + if(argc > 2){ + pMot->pHkl = FindCommandData(pSics,argv[2],"4-Circle-Calculus"); + } else { + pMot->pHkl = FindCommandData(pSics,"hkl","4-Circle-Calculus"); + } + if(pMot->pHkl == NULL){ + snprintf(pBuffer,131,"ERROR: %s is no hkl object" , argv[2]); + SCWrite(pCon,pBuffer,eError); + return 0; + } + + status = AddCommand(pSics,pName,InterInvokeSICSOBJ,KillSICSOBJ,pNew); if(status != 1){ SCWrite(pCon,"ERROR: failed to create duplicate cone motor",eError); } return status; - } diff --git a/cone.h b/cone.h index b30ca423..9f59a426 100644 --- a/cone.h +++ b/cone.h @@ -13,21 +13,12 @@ #include "ubcalc.h" /*-----------------------------------------------------------------------*/ - typedef struct { - pObjectDescriptor pDes; pIDrivable pDriv; - reflection target; float lastConeAngle; - float qScale; - pUBCALC ubi; - int center; - pHKL pHkl; + pHKL pHkl; } coneData, *pConeData; - /*----------------------------------------------------------------------*/ int MakeCone(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); -int ConeAction(SConnection *pCon, SicsInterp *pSics, void *pData, - int argc, char *argv[]); #endif diff --git a/confvirtualmot.c b/confvirtualmot.c index 73074fb1..84d4ef72 100644 --- a/confvirtualmot.c +++ b/confvirtualmot.c @@ -241,15 +241,19 @@ static int ConfCheckLimits(void *pData, float fVal, char *error, int errLen){ { free(self->pName); } + if(self->pCon) + { + SCDeleteConnection(self->pCon); + } free(self); } /*------------------- The CallBack function for interest ------------------ * iEvent: Event ID, see event.h for SICS events * pEvent: May contain data from event generating object * pUser: Data available when registering interest, see RegisteredInfo struct - * defined above for available info */ - static int InterestCallback(int iEvent, void *pEvent, void *pUser, - commandContext cc) + * defined above for available info +--------------------------------------------------------------------------*/ + static int InterestCallback(int iEvent, void *pEvent, void *pUser) { pRegisteredInfo pInfo = NULL; char pBueffel[80]; @@ -257,7 +261,11 @@ static int ConfCheckLimits(void *pData, float fVal, char *error, int errLen){ assert(pEvent); assert(pUser); - + + if(!SCisConnected(pInfo->pCon)){ + return -1; + } + pEventData = (EventInfo *)pEvent; pInfo = (RegisteredInfo *)pUser; @@ -265,7 +273,7 @@ static int ConfCheckLimits(void *pData, float fVal, char *error, int errLen){ pInfo->lastValue = pEventData->fVal; (pInfo->pCon)->conEventType=POSITION; sprintf(pBueffel,"%s.position = %f ", pInfo->pName, pInfo->lastValue); - SCWriteInContext(pInfo->pCon,pBueffel,eEvent,cc); + SCWrite(pInfo->pCon,pBueffel,eEvent); } return 1; } @@ -552,7 +560,7 @@ int ConfigurableVirtualMotorAction(SConnection *pCon, SicsInterp *pSics, return 0; } pRegInfo->pName = strdup(argv[0]); - pRegInfo->pCon = pCon; + pRegInfo->pCon = SCCopyConnection(pCon); value = ConfGetValue(self,pCon); if(!iRet) { @@ -562,8 +570,8 @@ int ConfigurableVirtualMotorAction(SConnection *pCon, SicsInterp *pSics, } pRegInfo->lastValue = value; - lID = RegisterCallback(self->pCall, SCGetContext(pCon),MOTDRIVE, InterestCallback, pRegInfo, KillInfo); - SCRegister(pCon,pSics, self->pCall,lID); + lID = RegisterCallback(self->pCall, MOTDRIVE, + InterestCallback, pRegInfo, KillInfo); SCSendOK(pCon); return 1; } else { diff --git a/conman.c b/conman.c index ff748652..e0cef426 100644 --- a/conman.c +++ b/conman.c @@ -42,6 +42,10 @@ Aded buffering support, Mark Koennecke, July 2006 Copyright: see copyright.h + + substantially revised for asynchronous I/O + + Mark Koennecke, January 2009 -----------------------------------------------------------------------------*/ #include "fortify.h" #include @@ -93,7 +97,6 @@ extern pServer pServ; /*------------- a number for generating automatic names --------------------*/ static int iName = 0; - static SConnection *freeConnections = NULL; static long lastIdent = 0; /*------------- sending connection (prevent double write when listening) ----*/ static SConnection *sendingConnection = NULL; @@ -114,12 +117,27 @@ extern pServer pServ; /*--------------------------------------------------------------------------*/ static void FreeConnection(SConnection *pCon) { - memset(pCon,0,sizeof(SConnection)); - pCon->ident = 0; - pCon->next = freeConnections; - pCon->listening = 0; - freeConnections = pCon; + free(pCon); } +/*------------------------------------------------------------------------*/ + void KillFreeConnections() + { + } + /*-------------------------------------------------------------------------*/ +static SConnection *SCMakeConnection() +{ + SConnection *pRes = NULL; + + pRes = (SConnection *)malloc(sizeof(SConnection)); + if(!pRes) + { + /* This is a serious, very serious error! */ + SICSLogWrite("ERROR: No memory to allocate connection!!",eInternal); + return NULL; + } + memset(pRes,0,sizeof(SConnection)); + return pRes; +} /*--------------------------------------------------------------------------*/ static SConnection *CreateConnection(SicsInterp *pSics) { @@ -127,23 +145,8 @@ extern pServer pServ; SConnection *pRes = NULL; char pBueffel[253]; char pHost[132]; - - if (!freeConnections) - { /* no more free connection: get one by malloc */ - pRes = (SConnection *)malloc(sizeof(SConnection)); - if(!pRes) - { - /* This is a serious, very serious error! */ - SICSLogWrite("ERROR: No memory to allocate connection!!",eInternal); - return NULL; - } - memset(pRes,0,sizeof(SConnection)); - } - else - { /* reuse an old connection */ - pRes = freeConnections; - freeConnections = pRes->next; - } + + pRes = SCMakeConnection(); do { /* loop until an unused ident is found. This test needed only for @@ -185,7 +188,6 @@ extern pServer pServ; } pRes->iOutput = eInError; /* gets everything except internal messages */ - pRes->iFiles = 0; /* default: no logfiles */ pRes->inUse = 0; pRes->iMacro = 0; pRes->iTelnet = 0; @@ -195,11 +197,7 @@ extern pServer pServ; pRes->listening = 0; pRes->conStart = time(NULL); pRes->write = SCNormalWrite; - for(i = 0; i < 10; i++) - { - pRes->pFiles[i] = NULL; - } - + /* initialise context variables */ pRes->iCmdCtr = 0; pRes->conEventType=-1; @@ -212,25 +210,20 @@ extern pServer pServ; } /*--------------------------------------------------------------------------*/ - SConnection *SCreateConnection(SicsInterp *pSics,mkChannel *pSock, int iUser) + SConnection *SCreateConnection(SicsInterp *pSics,int sockHandle, int iUser) { SConnection *pRes = NULL; char pBueffel[253]; char pHost[132]; - assert(pSock); - pRes = CreateConnection(pSics); SetCommandStackMaxSize(pRes->pStack,MAXSTACK); - pRes->pSock = pSock; + pRes->sockHandle = sockHandle; pRes->iUserRights = iUser; pRes->iGrab = TokenGrabActive(); - - return pRes; - } /*--------------------------------------------------------------------------*/ SConnection *SCCreateDummyConnection(SicsInterp *pSics) @@ -239,7 +232,7 @@ extern pServer pServ; pRes = CreateConnection(pSics); - pRes->pSock = NULL; + pRes->sockHandle = -1; pRes->iUserRights = usInternal; pRes->iGrab = 0; @@ -248,7 +241,7 @@ extern pServer pServ; return pRes; } /*--------------------------------------------------------------------------*/ - static int VerifyConnection(SConnection *self) + int VerifyConnection(SConnection *self) { if(!self) { @@ -262,75 +255,6 @@ extern pServer pServ; } return 1; } -/*----------------------------------------------------------------------------*/ - int SCAddLogFile(SConnection *self, char *name) - { - char pBueffel[256]; - int iNum, i; - - if(!VerifyConnection(self)) - { - return 0; - } - - - /* find an empty number */ - if(self->iFiles < MAXLOGFILES) - { - iNum = self->iFiles; - self->iFiles++; - } - else /* scan for an empty slot */ - { - iNum = -1; - for(i = 0; i < self->iFiles; i++) - { - if(self->pFiles[i] == NULL) - { - iNum = i; - break; - } - } - } - /* nothing found ? */ - if(iNum < 0) - { - SCWrite(self,"ERROR: maximum number of logfiles exhausted",eError); - return -1; - } - - /* do the job */ - self->pFiles[iNum] = fopen(name,"a+"); - if(self->pFiles[iNum] == NULL) - { - sprintf(pBueffel,"ERROR Could not open logfile - %s -",name); - SCWrite(self,pBueffel, 10); - return -1; /* false */ - } - else - { - return iNum; /* success */ - } - } -/*--------------------------------------------------------------------------*/ - int SCDelLogFile(SConnection *self, int iNum) - { - if(!VerifyConnection(self)) - { - return 0; - } - - if( (iNum >= 0) && (iNum < MAXLOGFILES) ) - { - if(self->pFiles[iNum]) - { - fclose(self->pFiles[iNum]); - self->pFiles[iNum] = NULL; - return 1; - } - } - return 0; - } /*----------------------------------------------------------------------------*/ void SCSetOutputClass(SConnection *self, int iClass) { @@ -369,14 +293,91 @@ extern pServer pServ; /* SCPrintf(self,eError, "SCsetMacro = %lx, %d\n", (long int)self, iMode); */ return 1; } + /*--------------------------------------------------------------------------*/ + void SCDeleteMasterFields(SConnection *pVictim) + { + int iRet; + Item sItem; + pHdb root = NULL; + char pBueffel[512]; + + if(pVictim->pDes == NULL) + { + return; + } + + if(SCActive(pVictim)) + { + SCnoSock(pVictim); + ANETclose(pVictim->sockHandle); + WriteToCommandLog("SYS>", + "ERROR: Erraneous deletion of used Connection stopped"); + pVictim->sockHandle = -1; + return; + } + + /* remove the connection from the server log if it has captured + something + */ + KillCapture(pVictim); + + /* + * remove any callbacks which might still be active in the Hipadaba + */ + root = GetHipadabaRoot(); + if(root != NULL) + { + RemoveConnectionCallbacks(root,pVictim); + } + + /* + If we have a grab, release it ! + */ + if(!pVictim->iGrab) + { + if(pServ->pTasker) + { + TaskSignal(pServ->pTasker,TOKENRELEASE,NULL); + TokenRelease(); + } + } + + /* log the kill */ + if(pVictim->sockHandle >= 0 && pVictim->iLogin == 1 && + (pVictim->iUserRights < 3 || !CompactCommandLog()) ) + { + sprintf(pBueffel,"Deleting connection %d",pVictim->sockHandle); + WriteToCommandLog("SYS>",pBueffel); + SICSLogWrite(pBueffel,eInternal); + } + + /* close all open files and sockets */ + if(pVictim->sockHandle > 0) + { + ANETwrite(pVictim->sockHandle,"SICSCLOSE",sizeof("SICSCLOSE")); + ANETprocess(); + ANETclose(pVictim->sockHandle); + } + RemoveCommand(pServ->pSics,ConName(pVictim->ident)); + /* remove all callbacks on this connection */ + iRet = LLDnodePtr2First(pVictim->iList); + while(iRet != 0) + { + LLDnodeDataTo(pVictim->iList,&sItem); + RemoveCallback(sItem.pInterface, sItem.lID); + iRet = LLDnodePtr2Next(pVictim->iList); + } + LLDdelete(pVictim->iList); + LLDdelete(pVictim->contextStack); + DeleteDescriptor(pVictim->pDes); + + } /*---------------------------------------------------------------------------*/ void SCDeleteConnection(void *pData) { int i, iRet; char pBueffel[132]; SConnection *pVictim = NULL; - Item sItem; - pHdb root = NULL; pVictim = (SConnection *)pData; if(!VerifyConnection(pVictim)) @@ -384,94 +385,14 @@ extern pServer pServ; return; } - if(SCActive(pVictim)) + SCDeleteMasterFields(pVictim); + + /* remove command stack */ + if(pVictim->pStack != NULL) { - SCnoSock(pVictim); - if(pVictim->pSock) - { - NETClosePort(pVictim->pSock); - free(pVictim->pSock); - pVictim->pSock = NULL; - } - WriteToCommandLog("SYS>", - "ERROR: Erraneous deletion of used Connection stopped"); - return; + DeleteCommandStack(pVictim->pStack); } - - - /* remove the connection from the server log if it has captured - something - */ - KillCapture(pVictim); - - /* - * remove any callbacks which might still be active in the Hipadaba - */ - root = GetHipadabaRoot(); - if(root != NULL) - { - RemoveConnectionCallbacks(root,pVictim); - } - - /* - If we have a grab, release it ! - */ - if(!pVictim->iGrab) - { - if(pServ->pTasker) - { - TaskSignal(pServ->pTasker,TOKENRELEASE,NULL); - TokenRelease(); - } - } - - /* log the kill */ - if(pVictim->pSock && pVictim->iLogin == 1 && - (pVictim->iUserRights < 3 || !CompactCommandLog()) ) - { - sprintf(pBueffel,"Deleting connection %d",pVictim->pSock->sockid); - WriteToCommandLog("SYS>",pBueffel); - SICSLogWrite(pBueffel,eInternal); - } - - /* close all open files and sockets */ - if(pVictim->pSock) - { - NETWrite(pVictim->pSock,"SICSCLOSE",sizeof("SICSCLOSE")); - NETClosePort(pVictim->pSock); - free(pVictim->pSock); - } - for(i = 0; i < pVictim->iFiles; i++) - { - if(pVictim->pFiles[i] != NULL) - { - fclose(pVictim->pFiles[i]); - } - } - - RemoveCommand(pServ->pSics,ConName(pVictim->ident)); - - if(pVictim->pDes) - { - DeleteDescriptor(pVictim->pDes); - } - - /* remove all callbacks on this connection */ - iRet = LLDnodePtr2First(pVictim->iList); - while(iRet != 0) - { - LLDnodeDataTo(pVictim->iList,&sItem); - RemoveCallback(sItem.pInterface, sItem.lID); - iRet = LLDnodePtr2Next(pVictim->iList); - } - LLDdelete(pVictim->iList); - - /* remove command stack */ - if(pVictim->pStack) - { - DeleteCommandStack(pVictim->pStack); - } - + /* remove possible buffers */ if(pVictim->data != NULL) { @@ -480,9 +401,64 @@ extern pServer pServ; pVictim->lMagic=0; /* make a write to a freed connection harmless */ /* finally free pVictim*/ - LLDdelete(pVictim->contextStack); FreeConnection(pVictim); } +/*--------------------------------------------------------------------------*/ +SConnection *SCCopyConnection(SConnection *pCon){ + SConnection *result = NULL; + + result = SCMakeConnection(); + if(result == NULL){ + return NULL; + } + result->sockHandle = pCon->sockHandle; + result->lMagic = pCon->lMagic; + result->iUserRights = pCon->iUserRights; + result->ident = pCon->ident; + result->iMacro = pCon->iMacro; + result->iTelnet = pCon->iTelnet; + result->iOutput = pCon->iOutput; + result->write = pCon->write; + result->listening = pCon->listening; + result->eInterrupt = pCon->eInterrupt; + result->inUse = pCon->inUse; + result->sicsError = pCon->sicsError; + result->iCmdCtr = pCon->iCmdCtr; + result->conEventType = pCon->conEventType; + result->conStatus = pCon->conStatus; + result->iProtocolID = pCon->iProtocolID; + result->transID = pCon->transID; + strcpy(result->deviceID, pCon->deviceID); + result->conStart = pCon->conStart; + result->contextStack = -1; + result->iList = -1; + return result; +} +/*---------------------------------------------------------------------------*/ +SConnection *SCfindMaster(SConnection *pCon) +{ + SConnection *result = NULL; + result = (SConnection *)FindCommandData(pServ->pSics,ConName(pCon->ident),"Connection"); + if(result == NULL) + { + printf("VERY, Very, very serious programming error!\n"); + printf("I continue but things may be wrong! Please debug ASAP!\n"); + if(pServ->dummyCon == NULL){ + pServ->dummyCon = SCCreateDummyConnection(pServ->pSics); + } + result = pServ->dummyCon; + } + return result; +} +/*---------------------------------------------------------------------------*/ +int SCisConnected(SConnection *pCon) +{ + if(!VerifyConnection(pCon)) + { + return 0; + } + return ANETvalidHandle(pCon->sockHandle); +} /*---------------------------------------------------------------------------*/ static int HasNL(char *buffer) { @@ -558,6 +534,56 @@ extern pServer pServ; } return iRet; } +/*-----------------------------------------------------------*/ + int TelnetWriteANET(int sockHandle, char *pBuffer) + { + char *pStart = NULL, *pPtr; + int iCount, iState; + int iRet = 1; + + pStart = pBuffer; + pPtr = pStart; + iState = TXT; + iCount = 0; + while(*pPtr != '\0') + { + switch(iState) + { + case TXT: + if( (*pPtr == '\r') || (*pPtr == '\n') ) + { + iState = LF; + iRet = ANETwrite(sockHandle,pStart,iCount); + iRet = ANETwrite(sockHandle,"\r\n",2); + iCount = 0; + } + else + { + iCount++; + } + break; + case LF: + if( (*pPtr != '\r') && (*pPtr != '\n') ) + { + pStart = pPtr; + iCount = 1; + iState = TXT; + } + else + { + /* do nothing */ + } + break; + } + pPtr++; + } + if(iCount > 0) + { + iRet = ANETwrite(sockHandle,pStart,iCount); + iRet = ANETwrite(sockHandle,"\r\n",2); + } + return iRet; + } /*-------------------------------------------------------------------------*/ int SCWrite(SConnection *self, char *pBuffer, int iOut) { @@ -578,9 +604,16 @@ extern pServer pServ; int SCWriteInContext(SConnection *pCon, char *pBuffer, int out, commandContext cc) { int status; - SCPushContext2(pCon,cc); + int transID; + char oldDevice[256]; + + transID = pCon->transID; + strcpy(oldDevice,pCon->deviceID); + pCon->transID = cc.transID; + strncpy(pCon->deviceID, cc.deviceID,SCDEVIDLEN); status = SCWrite(pCon,pBuffer,out); - SCPopContext(pCon); + pCon->transID = transID; + strncpy(pCon->deviceID, oldDevice,SCDEVIDLEN); return status; } /*-------------------------------------------------------------------------*/ @@ -634,18 +667,18 @@ static int doSockWrite(SConnection *self, char *buffer) { int iRet = 1; - if(self->pSock) + if(self->sockHandle >= 0) { if(self->iTelnet) { - iRet = TelnetWrite(self->pSock,buffer); + iRet = TelnetWriteANET(self->sockHandle,buffer); } else { - iRet = NETWrite(self->pSock,buffer,strlen(buffer)); + iRet = ANETwrite(self->sockHandle,buffer,strlen(buffer)); if(!HasNL(buffer)) { - iRet = NETWrite(self->pSock,"\n",strlen("\n")); + iRet = ANETwrite(self->sockHandle,"\n",strlen("\n")); } } if(!iRet) @@ -654,7 +687,7 @@ static int doSockWrite(SConnection *self, char *buffer) if(!self->listening && self->iLogin == 1 && (self->iUserRights < 3 || !CompactCommandLog()) ) { - WriteToCommandLog("SYS>","Connection broken on send"); + WriteToCommandLog("SYS>","Connection broken on send"); } } } @@ -668,28 +701,59 @@ static int doSockWrite(SConnection *self, char *buffer) } return iRet; } -/*-------------------------------------------------------------------------*/ -static void writeToLogFiles(SConnection *self, char *buffer) +/*--------------------------------------------------------------------------*/ +static void testAndWriteCommandLog(SConnection *pCon, char *buffer, int iOut) { - int i; - for(i = 0; i < self->iFiles; i++) - { - if(self->pFiles[i]) - { - fputs(buffer,self->pFiles[i]); - if(! HasNL(buffer)) - { - fputs("\n",self->pFiles[i]); - fflush(self->pFiles[i]); - } - } - } + if(SCGetRights(pCon) <= usUser){ + if(SCinMacro(pCon) != 1){ + WriteToCommandLogId(NULL,pCon->sockHandle, buffer); + } else { + if(iOut == eLog || iOut == eLogError){ + WriteToCommandLogId(NULL,pCon->sockHandle, buffer); + } + } + } +} +/*--------------------------------------------------------------------------*/ +static void testAndStoreInTcl(SConnection *pCon, char *buffer, int iOut) +{ + if(SCinMacro(pCon)){ + if(iOut == eValue || iOut == eError){ + InterpWrite(pServ->pSics,buffer); + } + } +} +/*-------------------------------------------------------------------------*/ +static int testAndWriteSocket(SConnection *pCon, char *buffer, int iOut) +{ + switch(iOut){ + case eStatus: + case eStart: + case eFinish: + case eEvent: + case eHdbValue: + case eHdbEvent: + case eLog: + case eLogError: + return doSockWrite(pCon,buffer); + break; + case eValue: + case eError: + case eWarning: + if(!SCinMacro(pCon) && iOut >= pCon->iOutput){ + return doSockWrite(pCon,buffer); + } else { + return 0; + } + break; + } + printf("Unrecognized ouput code in testAndWriteSocket: FIX!!!\n"); + return 0; } /*--------------------------------------------------------------------------*/ int SCNormalWrite(SConnection *self, char *buffer, int iOut) { int i, iPtr, iRet; - char pBueffel[80]; if(!VerifyConnection(self)) { @@ -701,59 +765,14 @@ static void writeToLogFiles(SConnection *self, char *buffer) } /* log it for any case */ - if(self->pSock) - { - iRet = self->pSock->sockid; - } - else - { - iRet = 0; - } - sprintf(pBueffel,"Next line intended for socket: %d",iRet); - SICSLogWrite(pBueffel,eInternal); SICSLogWrite(buffer,iOut); - /* write to commandlog if user or manager privilege */ - if(SCGetRights(self) <= usUser) - { - if(self->iMacro != 1) - { - sendingConnection = self; - WriteToCommandLogId(NULL,iRet,buffer); - sendingConnection = NULL; - } - else - { - if(iOut == eError || iOut == eWarning) - { - sendingConnection = self; - WriteToCommandLogId(NULL,iRet,buffer); - sendingConnection = NULL; - } - } - } + testAndWriteCommandLog(self,buffer,iOut); + + testAndStoreInTcl(self,buffer,iOut); + + testAndWriteSocket(self,buffer,iOut); - /* put it into the interpreter if present */ - if(SCinMacro(self)) - { - InterpWrite(pServ->pSics,buffer); - /* print it to client if error message */ - if((iOut== eError) || (iOut == eWarning) ) - { - iRet = doSockWrite(self,buffer); - } - } - else /* not in interpreter, normal logic */ - { - /* is this really to be printed ? */ - if(iOut < self->iOutput) - return 0; - - /* first the socket */ - iRet = doSockWrite(self,buffer); - - writeToLogFiles(self,buffer); - } return 1; } /*--------------------------------------------------------------------------*/ @@ -774,37 +793,12 @@ static void writeToLogFiles(SConnection *self, char *buffer) } /* log it for any case */ - if(self->pSock) - { - iRet = self->pSock->sockid; - } - else - { - iRet = 0; - } - sprintf(pBueffel,"Next line intended for socket: %d",iRet); - SICSLogWrite(pBueffel,eInternal); + sprintf(pBueffel,"Next line intended for socket: %d",self->sockHandle); SICSLogWrite(buffer,iOut); - /* write to commandlog if user or manager privilege */ - if(SCGetRights(self) <= usUser) - { - if(self->iMacro != 1) - { - sendingConnection = self; - WriteToCommandLogId(NULL,iRet,buffer); - sendingConnection = NULL; - } - else - { - if(iOut == eError || iOut == eWarning) - { - sendingConnection = self; - WriteToCommandLogId(NULL,iRet,buffer); - sendingConnection = NULL; - } - } - } + testAndWriteCommandLog(self,buffer,iOut); + + testAndStoreInTcl(self,buffer, iOut); /* * copy in ACT @@ -813,30 +807,10 @@ static void writeToLogFiles(SConnection *self, char *buffer) pPtr = (char *)malloc((strlen(buffer)+30)*sizeof(char)); memset(pPtr,0,strlen(buffer)+20); } - cx = SCGetContext(self); - sprintf(pPtr,"%d::>%s<::", cx.transID, buffer); + sprintf(pPtr,"%d::>%s<::", self->transID, buffer); + + testAndWriteSocket(self,pPtr, iOut); - /* put it into the interpreter if present */ - if(SCinMacro(self)) - { - InterpWrite(pServ->pSics,buffer); - /* print it to client if error message */ - if((iOut== eError) || (iOut == eWarning) ) - { - iRet = doSockWrite(self,pPtr); - } - } - else /* not in interpreter, normal logic */ - { - /* is this really to be printed ? */ - if(iOut < self->iOutput) - return 0; - - /* first the socket */ - iRet = doSockWrite(self,pPtr); - - writeToLogFiles(self,buffer); - } if(pPtr != pBueffel){ free(pPtr); } @@ -859,26 +833,13 @@ static void writeToLogFiles(SConnection *self, char *buffer) } /* log it for any case */ - if(self->pSock) - { - iRet = self->pSock->sockid; - } - else - { - iRet = 0; - } - sprintf(pBueffel,"Next line intended for socket: %d",iRet); + sprintf(pBueffel,"Next line intended for socket: %d",self->sockHandle); SICSLogWrite(pBueffel,eInternal); SICSLogWrite(buffer,iOut); - /* write to commandlog if user or manager privilege */ - if(SCGetRights(self) <= usUser && self->iMacro != 1) - { - sendingConnection = self; - WriteToCommandLogId(NULL,iRet,buffer); - sendingConnection = NULL; - } + testAndWriteCommandLog(self,buffer,iOut); + testAndStoreInTcl(self, buffer, iOut); /* prepare the message with the outcode appended. */ @@ -903,31 +864,8 @@ static void writeToLogFiles(SConnection *self, char *buffer) strcat(bufPtr,pCode[iOut]); strcat(bufPtr,"\r\n"); - - /* put it into the interpreter if present */ - if(SCinMacro(self)) - { - InterpWrite(pServ->pSics,buffer); - /* print it to client if error message */ - if((iOut== eError) || (iOut == eWarning) ) - { - iRet = doSockWrite(self,bufPtr); - } - } - else /* not in interpreter, normal logic */ - { - /* is this really to be printed ? */ - if(iOut < self->iOutput) - { - free(bufPtr); - return 0; - } - - /* first the socket */ - iRet = doSockWrite(self,bufPtr); - - writeToLogFiles(self,buffer); - } + testAndWriteSocket(self, bufPtr, iOut); + free(bufPtr); return 1; } @@ -989,33 +927,15 @@ pDynString SCEndBuffering(SConnection *pCon) } /* log it for any case */ - if(self->pSock) - { - iRet = self->pSock->sockid; - } - else - { - iRet = 0; - } - sprintf(pBueffel,"Next line intended for socket: %d",iRet); + sprintf(pBueffel,"Next line intended for socket: %d",self->sockHandle); SICSLogWrite(pBueffel,eInternal); SICSLogWrite(buffer,iOut); + + testAndStoreInTcl(self, buffer, iOut); + + testAndWriteSocket(self, buffer, iOut); - /* put it into the interpreter if present */ - if(SCinMacro(self)) - { - InterpWrite(pServ->pSics,buffer); - } - else /* not in interpreter, normal logic */ - { - /* is this really to be printed ? */ - if(iOut < self->iOutput) - return 0; - - /* the socket */ - iRet = doSockWrite(self,buffer); - } - return 1; + return 1; } /*--------------------------------------------------------------------------*/ int SCNotWrite(SConnection *self, char *buffer, int iOut) @@ -1029,24 +949,12 @@ pDynString SCEndBuffering(SConnection *pCon) } /* log it for any case */ - if(self->pSock) - { - iRet = self->pSock->sockid; - } - else - { - iRet = 0; - } - sprintf(pBueffel,"Next line intended for socket: %d",iRet); + sprintf(pBueffel,"Next line intended for socket: %d",self->sockHandle); SICSLogWrite(pBueffel,eInternal); SICSLogWrite(buffer,iOut); - /* put it into the interpreter if present */ - if(SCinMacro(self)) - { - InterpWrite(pServ->pSics,buffer); - } - return 1; + testAndStoreInTcl(self, buffer, iOut); + return 1; } /*-------------------------------------------------------------------------- This version writes only to configured log files but not to sockets. @@ -1063,54 +971,17 @@ pDynString SCEndBuffering(SConnection *pCon) } /* log it for any case */ - if(self->pSock) - { - iRet = self->pSock->sockid; - } - else - { - iRet = -10; - } - - /* put into Serverlog */ - sprintf(pBueffel,"Next line intended for socket: %d",iRet); + sprintf(pBueffel,"Next line intended for socket: %d",self->sockHandle); SICSLogWrite(pBueffel,eInternal); SICSLogWrite(buffer,iOut); - /* write to commandlog if user or manager privilege */ - if(SCGetRights(self) <= usUser) - { - if(self->iMacro != 1) - { - sendingConnection = self; - WriteToCommandLogId(NULL,iRet,buffer); - sendingConnection = NULL; - } - else - { - if(iOut == eError || iOut == eWarning) - { - sendingConnection = self; - WriteToCommandLogId(NULL,iRet,buffer); - sendingConnection = NULL; - } - } - } + testAndWriteCommandLog(self,buffer,iOut); + + testAndStoreInTcl(self, buffer, iOut); + + testAndWriteSocket(self, buffer, iOut); - /* put it into the interpreter if present */ - if(SCinMacro(self)) - { - InterpWrite(pServ->pSics,buffer); - } - else /* not in interpreter, normal logic */ - { - /* is this really to be printed ? */ - if(iOut < self->iOutput) - return 0; - - writeToLogFiles(self,buffer); - } return 1; } /*-----------------------------------------------------------------------*/ @@ -1144,11 +1015,11 @@ pDynString SCEndBuffering(SConnection *pCon) /* the uuencoder ensures proper telnet */ if(pCon->iTelnet) { - NETWrite(pCon->pSock,pPtr,iLength); + ANETwrite(pCon->sockHandle,pPtr,iLength); } else { - NETWrite(pCon->pSock,pPtr,iLength); + ANETwrite(pCon->sockHandle,pPtr,iLength); } #ifdef UUDEB @@ -1291,8 +1162,8 @@ pDynString SCEndBuffering(SConnection *pCon) SCWrite(self,outBuf,eError); return 0; } - iRet = NETWrite(self->pSock,pHeader,strlen(pHeader)); - iRet = NETWrite(self->pSock,pBuf,compStream.total_out); + iRet = ANETwrite(self->sockHandle,pHeader,strlen(pHeader)); + iRet = ANETwrite(self->sockHandle,pBuf,compStream.total_out); if(iRet != 1) { sprintf(outBuf,"ERROR: network error %d on zipped send",iRet); @@ -1303,67 +1174,12 @@ pDynString SCEndBuffering(SConnection *pCon) free(pHeader); free(pBuf); - - /* - Writing smaller buffers. Seems not to be working properly - with Java. - */ - /* - compStream.next_in = (Bytef *)pData; - compStream.avail_in = iDataLen; - compStream.avail_out = ZIPBUF; - compStream.next_out = (Bytef *)noutBuf; - iCount = 0; - while(compStream.total_in < iDataLen) - { - iRet = deflate(&compStream,Z_NO_FLUSH); - if(iRet != Z_OK) - { - sprintf(outBuf,"ERROR: zlib error: %d",iRet); - SCWrite(self,outBuf,eError); - return 0; - } - iRet = NETWrite(self->pSock,noutBuf,ZIPBUF - compStream.avail_out); - if(iRet != 1) - { - sprintf(outBuf,"ERROR: network error %d on zipped send",iRet); - SCWrite(self,outBuf,eError); - return 0; - } - iCount += ZIPBUF - compStream.avail_out; - compStream.next_out = (Bytef *)noutBuf; - compStream.avail_out = ZIPBUF; - } - for(;;) - { - iRet = deflate(&compStream,Z_FINISH); - iRet2 = NETWrite(self->pSock,noutBuf,ZIPBUF - compStream.avail_out); - if(iRet2 != 1) - { - sprintf(outBuf,"ERROR: network error %d on zipped send",iRet); - SCWrite(self,outBuf,eError); - return 0; - } - iCount += ZIPBUF - compStream.avail_out; - if(iRet == Z_STREAM_END) break; - if(iRet != Z_OK) - { - sprintf(outBuf,"ERROR: zlib error: %d",iRet); - SCWrite(self,outBuf,eError); - return 0; - } - compStream.next_out = (Bytef *)noutBuf; - compStream.avail_out = ZIPBUF; - } - deflateEnd(&compStream); - */ - return 1; } /*-------------------------------------------------------------------------*/ int SCSendOK(SConnection *self) { - return SCWrite(self,"OK",eStatus); + return SCWrite(self,"OK",eValue); } /*--------------------------------------------------------------------------*/ int SCRead(SConnection *self, char *buffer, int iLen) @@ -1376,16 +1192,16 @@ pDynString SCEndBuffering(SConnection *pCon) return 0; } - if(self->pSock == NULL) + if(self->sockHandle < 0) { printf("SICS>> "); fgets(buffer,iLen-1,stdin); return 1; } - if(self->pSock) + if(self->sockHandle >= 0) { - iRet = NETRead(self->pSock,buffer,iLen,10); + iRet = ANETread(self->sockHandle,buffer,iLen); if(iRet == 0) /* no data */ { return 0; @@ -1475,7 +1291,7 @@ pDynString SCEndBuffering(SConnection *pCon) SetStatus(eOld); CostaLock(pCon->pStack); strncpy(pResult,pPtr,iLen); - WriteToCommandLogId(" prompted>", pCon->pSock->sockid, pPtr); + WriteToCommandLogId(" prompted>", pCon->sockHandle, pPtr); return 1; } } @@ -1490,7 +1306,7 @@ pDynString SCEndBuffering(SConnection *pCon) { return 0; } - + return self->iUserRights; } /*---------------------------------------------------------------------------*/ @@ -1528,22 +1344,24 @@ pDynString SCEndBuffering(SConnection *pCon) /*--------------------------------------------------------------------------*/ void SCSetInterrupt(SConnection *self, int eCode) { + SConnection *pCon = NULL; if(!VerifyConnection(self)) { return; } - - self->eInterrupt = eCode; + pCon = SCfindMaster(self); + pCon->eInterrupt = eCode; } /*---------------------------------------------------------------------------*/ int SCGetInterrupt(SConnection *self) { + SConnection *pCon = NULL; if(!VerifyConnection(self)) { return 0; } - - return self->eInterrupt; + pCon = SCfindMaster(self); + return pCon->eInterrupt; } /*----------------------------------------------------------------*/ extern char *trim(char *in); @@ -1556,6 +1374,7 @@ pDynString SCEndBuffering(SConnection *pCon) char *pBuffer = NULL, *pFile = NULL; char pBueffel[80]; int i, iSpace; + SConnection *pCopy = NULL; if(!VerifyConnection(self)) { @@ -1563,14 +1382,6 @@ pDynString SCEndBuffering(SConnection *pCon) } assert(pInter); - /* print command to log files */ - for( i = 0; i < self->iFiles; i++) - { - if(self->pFiles[i]) - { - fprintf(self->pFiles[i],"SICS>> %s\n",pCommand); - } - } /* print to command log if user or manager */ if(SCGetRights(self) <= usUser) @@ -1581,10 +1392,10 @@ pDynString SCEndBuffering(SConnection *pCon) */ if(SCGetWriteFunc(self) != SCNotWrite) { - sendingConnection = self; - if(self->pSock != NULL) + sendingConnection = self; + if(self->sockHandle >= 0) { - WriteToCommandLogCmd(self->pSock->sockid, pCommand); + WriteToCommandLogCmd(self->sockHandle, pCommand); } else { WriteToCommandLog("CRON>>",pCommand); } @@ -1600,9 +1411,21 @@ pDynString SCEndBuffering(SConnection *pCon) */ memset(pBueffel,0,80); stptok(trim(pCommand),pBueffel,79," "); - SCAdvanceContext(self,pBueffel); - iRet = InterpExecute(pInter,self,pCommand); - SCPopContext(self); + self->iCmdCtr++; + if(999999 < self->iCmdCtr){ + self->iCmdCtr = 0; + } + self->transID = self->iCmdCtr; + pCopy = SCCopyConnection(self); + if(pCopy == NULL){ + SCWrite(self,"ERROR: out of memory in SCInvoke",eError); + return 0; + } + strncpy(pCopy->deviceID, pBueffel,SCDEVIDLEN); + /* SCAdvanceContext(self,pBueffel); */ + iRet = InterpExecute(pInter,pCopy,pCommand); + /* SCPopContext(self); */ + SCDeleteConnection(pCopy); StatusFileTask(NULL); /* save changed parameters */ self->inUse--; @@ -1624,6 +1447,7 @@ pDynString SCEndBuffering(SConnection *pCon) char pHost[132]; int i, iRet; int iNum; + SConnection *pMaster = NULL; if(!VerifyConnection(pCon)) { @@ -1638,6 +1462,7 @@ pDynString SCEndBuffering(SConnection *pCon) SCWrite(pCon,pBueffel,eError); return 0; } + pMaster = SCfindMaster(pCon); /* handle list*/ strtolower(argv[1]); @@ -1645,7 +1470,7 @@ pDynString SCEndBuffering(SConnection *pCon) { sprintf(pBueffel,"OutCode = %s\nUserRights = %d", pCode[pCon->iOutput], SCGetRights(pCon)); - SCWrite(pCon,pBueffel,eStatus); + SCWrite(pCon,pBueffel,eValue); return 1; } else if(strcmp(argv[1],"myname") == 0) @@ -1690,37 +1515,7 @@ pDynString SCEndBuffering(SConnection *pCon) return 0; } - /* decide what to do */ - if(strcmp(argv[1],"file") == 0) - { - iRet = SCAddLogFile(pCon,argv[2]); - if(iRet >= 0 ) - { - sprintf(pBueffel,"File = %d",iRet); - SCWrite(pCon,pBueffel,eStatus); - return 1; - } - } - if(strcmp(argv[1],"close") == 0) /* close file */ - { - iNum = atoi(argv[2]); - if( (iNum >= 0) && (iNum < MAXLOGFILES)) - { - if(pCon->pFiles[iNum]) - { - fclose(pCon->pFiles[iNum]); - pCon->pFiles[iNum] = NULL; - SCSendOK(pCon); - return 1; - } - } - else - { - SCWrite(pCon, "Invalid file number specified ",eError); - return 0; - } - } - else if(strcmp(argv[1],"outcode") == 0) + if(strcmp(argv[1],"outcode") == 0) { i = 0; strtolower(argv[2]); @@ -1739,6 +1534,7 @@ pDynString SCEndBuffering(SConnection *pCon) return 0; } pCon->iOutput = i; + pMaster->iOutput = i; SCSendOK(pCon); return 1; } @@ -1747,15 +1543,18 @@ pDynString SCEndBuffering(SConnection *pCon) strtolower(argv[2]); if(strcmp(argv[2],"normal") == 0) { - SCSetWriteFunc(pCon,SCNormalWrite); + SCSetWriteFunc(pCon,SCNormalWrite); + SCSetWriteFunc(pMaster,SCNormalWrite); } else if(strcmp(argv[2],"withcode") == 0) { - SCSetWriteFunc(pCon,SCWriteWithOutcode); + SCSetWriteFunc(pCon,SCWriteWithOutcode); + SCSetWriteFunc(pMaster,SCWriteWithOutcode); } else if(strcmp(argv[2],"act") == 0) { - SCSetWriteFunc(pCon,SCACTWrite); + SCSetWriteFunc(pCon,SCACTWrite); + SCSetWriteFunc(pMaster,SCACTWrite); } else { @@ -1783,17 +1582,20 @@ pDynString SCEndBuffering(SConnection *pCon) } if (CompactCommandLog()) { if (pCon->iUserRights < 3 || i < 3) { - NETInfo(pCon->pSock,pHost,sizeof pHost); + ANETinfo(pCon->sockHandle,pHost,sizeof pHost); sprintf(pBueffel,"User %s from %s switched to %d privilege", argv[2],pHost,i); - WriteToCommandLogId("SYS>",pCon->pSock->sockid,pBueffel); + snprintf(pBueffel,512,"User at %d switched to %d privilige", + pCon->sockHandle, i); + WriteToCommandLogId("SYS>",pCon->sockHandle,pBueffel); } } else { - sprintf(pBueffel,"User %s socket %d switched to %d privilege", - argv[2],pCon->pSock->sockid,i); + sprintf(pBueffel,"User %s handle %d switched to %d privilege", + argv[2],pCon->sockHandle,i); WriteToCommandLog("SYS>",pBueffel); } pCon->iUserRights = i; + pMaster->iUserRights = i; SCWrite(pCon,"Change of Authorisation Acknowledged",eWarning); return 1; } @@ -1806,6 +1608,7 @@ pDynString SCEndBuffering(SConnection *pCon) { pICallBack pInter = NULL; Item sItem; + SConnection *pMaster = NULL; pInter = (pICallBack)pData; if(!VerifyConnection(pCon)) @@ -1817,7 +1620,8 @@ pDynString SCEndBuffering(SConnection *pCon) sItem.lID = lID; sItem.pInterface = pInter; - LLDnodeAppendFrom(pCon->iList,&sItem); + pMaster = SCfindMaster(pCon); + LLDnodeAppendFrom(pMaster->iList,&sItem); return 1; } /*----------------------------------------------------------------------*/ @@ -1826,22 +1630,25 @@ pDynString SCEndBuffering(SConnection *pCon) int iRet; Item sItem; pICallBack pInter; + SConnection *pMaster = NULL; if(!VerifyConnection(pCon)) { return 0; } pInter = (pICallBack)pData; - iRet = LLDnodePtr2First(pCon->iList); + pMaster = SCfindMaster(pCon); + + iRet = LLDnodePtr2First(pMaster->iList); while(iRet != 0) { - LLDnodeDataTo(pCon->iList,&sItem); + LLDnodeDataTo(pMaster->iList,&sItem); if(sItem.pInterface == pInter) { - LLDnodeDelete(pCon->iList); - LLDnodePtr2Prev(pCon->iList); + LLDnodeDelete(pMaster->iList); + LLDnodePtr2Prev(pMaster->iList); } - iRet = LLDnodePtr2Next(pCon->iList); + iRet = LLDnodePtr2Next(pMaster->iList); } return 1; } @@ -1850,21 +1657,23 @@ pDynString SCEndBuffering(SConnection *pCon) { int iRet; Item sItem; + SConnection *pMaster = NULL; if(!VerifyConnection(pCon)) { return 0; } - iRet = LLDnodePtr2First(pCon->iList); + pMaster = SCfindMaster(pCon); + iRet = LLDnodePtr2First(pMaster->iList); while(iRet != 0) { - LLDnodeDataTo(pCon->iList,&sItem); + LLDnodeDataTo(pMaster->iList,&sItem); if(sItem.lID == ID ) { - LLDnodeDelete(pCon->iList); - LLDnodePtr2Prev(pCon->iList); + LLDnodeDelete(pMaster->iList); + LLDnodePtr2Prev(pMaster->iList); } - iRet = LLDnodePtr2Next(pCon->iList); + iRet = LLDnodePtr2Next(pMaster->iList); } return 1; } @@ -1874,21 +1683,23 @@ pDynString SCEndBuffering(SConnection *pCon) int iRet; Item sItem; pICallBack pInter; + SConnection *pMaster = NULL; if(!VerifyConnection(pCon)) { return 0; } + pMaster = SCfindMaster(pCon); pInter = (pICallBack)pData; - iRet = LLDnodePtr2First(pCon->iList); + iRet = LLDnodePtr2First(pMaster->iList); while(iRet != 0) { - LLDnodeDataTo(pCon->iList,&sItem); + LLDnodeDataTo(pMaster->iList,&sItem); if(sItem.pInterface == pInter) { return sItem.lID; } - iRet = LLDnodePtr2Next(pCon->iList); + iRet = LLDnodePtr2Next(pMaster->iList); } return -1; } @@ -1910,6 +1721,9 @@ pDynString SCEndBuffering(SConnection *pCon) return; } + if(self->pCon){ + SCDeleteConnection(self->pCon); + } if(self->pAction) { free(self->pAction); @@ -1921,19 +1735,22 @@ pDynString SCEndBuffering(SConnection *pCon) The callback function for connection callbacks. Invokes command given at registration time. */ - static int ConCallBack(int iEvent, void *pEventData, void *pUserData, - commandContext cc) + static int ConCallBack(int iEvent, void *pEventData, void *pUserData) { pCBAction self = NULL; self = (pCBAction)pUserData; assert(self); + /* check kill condition */ + if(self->pCon == NULL) + { + return -1; + } + if(self->pAction) { - SCPushContext2(self->pCon,cc); - InterpExecute(pServ->pSics,self->pCon,self->pAction); - SCPopContext(self->pCon); + InterpExecute(pServ->pSics,self->pCon,self->pAction); } return 1; } @@ -2019,11 +1836,16 @@ pDynString SCEndBuffering(SConnection *pCon) SCWrite(pCon,"ERROR: memory exhausted in SConnection",eError); return 0; } - pCB->pCon = pCon; + pCB->pCon = SCCopyConnection(pCon); + if(!pCB->pCon) + { + SCWrite(pCon,"ERROR: memory exhausted in SConnection",eError); + return 0; + } pCB->pSics = pSics; pCB->pAction = script; sItem.pInterface = pInterface; - sItem.lID = RegisterCallback(pInterface, SCGetContext(pCB->pCon), iEvent, ConCallBack, + sItem.lID = RegisterCallback(pInterface, iEvent, ConCallBack, pCB, CBKill); LLDnodeAppendFrom(self->iList,&sItem); SCSendOK(pCon); @@ -2046,11 +1868,6 @@ pDynString SCEndBuffering(SConnection *pCon) { return 0; } - if(self->pSock->iType == 0) - { - NetReadRemove(pServ->pReader,self->pSock); - self->iEnd = 1; - } if(self->iEnd) { @@ -2064,16 +1881,22 @@ pDynString SCEndBuffering(SConnection *pCon) } } + if(!SCisConnected(self)){ + self->iEnd = 1; + return 1; + } + + /* a timeout check on logins */ if(!self->iLogin && time(NULL) > self->conStart + 120) { - NetReadRemove(pServ->pReader,self->pSock); - SCWrite(self, "No valid login in two minutes, closing..",eError); + ANETclose(self->sockHandle); + SCWrite(self, "No valid login in two minutes, closing..",eError); self->iEnd = 1; return 1; } - /* pop and execute */ + /* pop and execute */ iRet = CostaPop(self->pStack,&pPtr); if(iRet) { @@ -2087,7 +1910,7 @@ pDynString SCEndBuffering(SConnection *pCon) */ if(strstr(pPtr,"logoff") != NULL) { - NetReadRemove(pServ->pReader,self->pSock); + ANETclose(self->sockHandle); self->iEnd = 1; free(pPtr); return 1; @@ -2103,7 +1926,7 @@ pDynString SCEndBuffering(SConnection *pCon) if (strstr(pPtr,"How are you") == pPtr) { SCWrite(self,"I am fine",eError); - NetReadRemove(pServ->pReader,self->pSock); + ANETclose(self->sockHandle); self->iEnd = 1; free(pPtr); return 1; @@ -2120,16 +1943,16 @@ pDynString SCEndBuffering(SConnection *pCon) pHost[0] = '\0'; if (CompactCommandLog()) { if (iRet < 3) { - NETInfo(self->pSock,pHost,131); + ANETinfo(self->sockHandle,pHost,131); sprintf(pBueffel,"Accepted connection %s from %s as %s", ConName(self->ident), pHost, pUser); SICSLogWrite(pBueffel,eInternal); - WriteToCommandLogId("SYS>", self->pSock->sockid, pBueffel); + WriteToCommandLogId("SYS>", self->sockHandle, pBueffel); } } else { - NETInfo(self->pSock,pHost,131); + ANETinfo(self->sockHandle,pHost,131); sprintf(pBueffel,"Accepted connection %s on socket %d from %s", - ConName(self->ident), self->pSock->sockid, pHost); + ConName(self->ident), self->sockHandle, pHost); SICSLogWrite(pBueffel,eInternal); WriteToCommandLog("SYS >", pBueffel); } @@ -2146,7 +1969,6 @@ pDynString SCEndBuffering(SConnection *pCon) } } - if(self->iEnd) { if(SCActive(self)) @@ -2331,24 +2153,10 @@ int SCVerifyConnection(SConnection *self) return VerifyConnection(self); } /*------------------------------------------------------------------------*/ -void SCWriteToLogFiles(SConnection *self, char *buffer) -{ - writeToLogFiles(self,buffer); -} -/*------------------------------------------------------------------------*/ int SCDoSockWrite(SConnection *self, char *buffer) { return doSockWrite(self,buffer); } -/*--------------------------------------------------------------------------*/ -void KillFreeConnections(void) { - SConnection *next; - while (freeConnections) { - next = freeConnections->next; - free(freeConnections); - freeConnections = next; - } -} /*-------------------------------------------------------------------------*/ int SCPushContext(SConnection *self, int ID, char *deviceID) { @@ -2380,9 +2188,8 @@ commandContext SCGetContext(SConnection *pCon) { return neu; } - if(LLDnodePtr2Last(pCon->contextStack) == 1){ - LLDnodeDataTo(pCon->contextStack, &neu); - } + neu.transID = pCon->transID; + strncpy(neu.deviceID,pCon->deviceID,SCDEVIDLEN); return neu; } /*-----------------------------------------------------*/ diff --git a/conman.h b/conman.h index aaf0e006..12d46c82 100644 --- a/conman.h +++ b/conman.h @@ -1,4 +1,3 @@ - /*-------------------------------------------------------------------------- C O N N E C T I O N O B J E C T @@ -15,6 +14,10 @@ Mark Koennecke, December 2004 copyright: see copyright.h + + substantially for the new asynchronous I/O system + + Mark Koennecke, January 2009 ----------------------------------------------------------------------------*/ #ifndef SICSCONNECT #define SICSCONNECT @@ -22,6 +25,7 @@ #include "costa.h" #include "SCinter.h" #include "network.h" +#include "asynnet.h" #include "obdes.h" #include "commandcontext.h" #include "dynstring.h" @@ -32,80 +36,57 @@ typedef int (*writeFunc)(struct __SConnection *pCon, char *pMessage, int iCode); typedef struct __SConnection { - /* object basics */ - pObjectDescriptor pDes; - long lMagic; - long ident; - struct __SConnection *next; - - /* I/O control */ - /* our socket */ - mkChannel *pSock; - - /* per connection log files */ - FILE *pFiles[MAXLOGFILES]; - int iFiles; - - int iMacro; /* suppress I/O in macro*/ + /* Copy Object Fields*/ + pObjectDescriptor pDes; /* must be here */ + long lMagic; /* connection object ID */ + long ident; /* connection idetification */ + struct __SConnection *next; /* pointer for freeConnection managenment */ + int sockHandle; /* socket handle */ int iTelnet; /* telnet flag */ - int iOutput; - writeFunc write; /* function doing - writing */ - int listening; /* for listening to commandlog or other data */ - - /* execution context */ - int eInterrupt; - int iUserRights; - int inUse; - int iGrab; /* grab flag for token*/ - int sicsError; - - /* - * for I/O Buffering - */ - pDynString data; - writeFunc oldWriteFunc; - - /* - stuff supporting the sycamore protocol and a - command context - */ - long iCmdCtr; - int conEventType; + int iMacro; /* suppress I/O in macro */ + writeFunc write; /* function doing writing */ + int sicsError; /* Tcl interpreter requirement */ + pDynString data; /* for I/O buffering */ + writeFunc oldWriteFunc; /* saved write function used in I/O buffering */ + long iCmdCtr; /* sycamore protocol used */ + int conEventType; /* sycamore protocol support */ int conStatus; /* should use status enum ffr */ - int iProtocolID; - int contextStack; - - /* a FIFO */ - pCosta pStack; - - /* callback registry */ - int iList; - - /* Tasking Stuff */ - int iEnd; - /* for keeping track of the login - process on a non telnet connection. - Should only be used in SCTaskFunction - */ - int iLogin; - time_t conStart; + int transID; /* transaction ID */ + char deviceID[256]; /* transaction device ID */ + int iUserRights; /* user rights of the connection */ + + /* master connection object fields */ + int iList; /* callback registry, may go? */ + int iEnd; /* flag to end connection task */ + int iLogin; /* flag for successful login process */ + time_t conStart; /* time when connection was built: used during login */ + int iOutput; /* output filter flag */ + int listening; /* for listening to commandlog or other data */ + int eInterrupt; /* interrupts */ + int inUse; /* usage counter for the connection */ + int iGrab; /* grab flag for token*/ + int iProtocolID; /* ID of the protocol on this connection */ + pCosta pStack; /* stack of pending commands */ + int contextStack; /* context stack: may go? */ + mkChannel *pSock; /* for temporary backwards compatability */ } SConnection; #include "nserver.h" /*------------------------------ live & death ----------------------------*/ - SConnection *SCreateConnection(SicsInterp *pSics, mkChannel *pSock, + SConnection *SCreateConnection(SicsInterp *pSics, int sockHandle, int iUserRights); SConnection *SCCreateDummyConnection(SicsInterp *pSics); void SCDeleteConnection(void *pVictim); - + SConnection *SCCopyConnection(SConnection *pCon); + SConnection *SCfindMaster(SConnection *pCon); + int SCisConnected(SConnection *pCon); + int VerifyConnection(SConnection *pCon); + int SCVerifyConnection(SConnection *self); /*------------------------------- tasking --------------------------------*/ int SCTaskFunction(void *pCon); void SCSignalFunction(void *pCon, int iSignal, void *pSigData); /* ***************************** I/O ************************************** */ - int SCAddLogFile(SConnection *self, char *name); - int SCDelLogFile(SConnection *pCon, int iFile); void SCSetOutputClass(SConnection *self, int iClass); int SCWrite(SConnection *self, char *pBuffer, int iOut); int SCPrintf(SConnection *self, int iOut, char *fmt, ...); @@ -126,21 +107,6 @@ typedef int (*writeFunc)(struct __SConnection *pCon, /*********************** I/O Buffering ***********************************/ int SCStartBuffering(SConnection *pCon); pDynString SCEndBuffering(SConnection *pCon); -/************************* CallBack *********************************** */ - int SCRegister(SConnection *pCon, SicsInterp *pSics, - void *pInter, long lID); - int SCUnregister(SConnection *pCon, void *pInter); - /** - * delete a callback with the given ID - */ - int SCUnregisterID(SConnection *pCon, long ID); - /** - * retrieve the ID of a callback on the callback interface - * given in pData. This, together with SCUnregisterID allows to - * ceanly remove all callbacks on a connection - * returns -1 if no ID can be found. - */ - long SCgetCallbackID(SConnection *pCon, void *pData); /******************************* Error **************************************/ void SCSetInterrupt(SConnection *self, int eCode); int SCGetInterrupt(SConnection *self); @@ -156,9 +122,6 @@ typedef int (*writeFunc)(struct __SConnection *pCon, int SCGetOutClass(SConnection *self); int SCGetGrab(SConnection *pCon); int SCActive(SConnection *pCon); -/********************* simulation mode ************************************/ - void SCSetSimMode(SConnection *pCon, int value); - int SCinSimMode(SConnection *pCon); /* **************************** Invocation ******************************** */ int SCInvoke(SConnection *self,SicsInterp *pInter,char *pCommand); @@ -167,6 +130,23 @@ typedef int (*writeFunc)(struct __SConnection *pCon, int argc, char *argv[]); int ConSicsAction(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); + +/*------------------------------------------------------------------------*/ +int SCDoSockWrite(SConnection *self, char *buffer); +int SCWriteInContext(SConnection *pCon, char *buffer, int code, commandContext cc); + + +/* ================== ===================================================== + * These routines are obsolete and may not even work anymore. + * Mark Koennecke, January 2009 + * ==========================================================================*/ +void SCWriteToLogFiles(SConnection *self, char *buffer); +long SCTagContext(SConnection *self, char *tagName); +long SCAdvanceContext(SConnection *self, char *tagName); +int SCPushContext(SConnection *pCon, int ID, char *deviceID); +int SCPushContext2(SConnection *pCon, commandContext cc); +int SCPopContext(SConnection *pCon); +commandContext SCGetContext(SConnection *pCon); /******************************** Store ************************************/ typedef struct SCStore SCStore; @@ -189,18 +169,20 @@ void SCStoreFree(SCStore *conStore); /* free an SCStore */ void KillFreeConnections(void); - -/*------------------------------------------------------------------------*/ -int SCVerifyConnection(SConnection *self); -void SCWriteToLogFiles(SConnection *self, char *buffer); -int SCDoSockWrite(SConnection *self, char *buffer); -int SCWriteInContext(SConnection *pCon, char *buffer, int code, commandContext cc); - -long SCTagContext(SConnection *self, char *tagName); -long SCAdvanceContext(SConnection *self, char *tagName); -int SCPushContext(SConnection *pCon, int ID, char *deviceID); -int SCPushContext2(SConnection *pCon, commandContext cc); -int SCPopContext(SConnection *pCon); -commandContext SCGetContext(SConnection *pCon); +/************************* CallBack *********************************** */ + int SCRegister(SConnection *pCon, SicsInterp *pSics, + void *pInter, long lID); + int SCUnregister(SConnection *pCon, void *pInter); + /** + * delete a callback with the given ID + */ + int SCUnregisterID(SConnection *pCon, long ID); + /** + * retrieve the ID of a callback on the callback interface + * given in pData. This, together with SCUnregisterID allows to + * ceanly remove all callbacks on a connection + * returns -1 if no ID can be found. + */ + long SCgetCallbackID(SConnection *pCon, void *pData); #endif diff --git a/counter.c b/counter.c index 495bee96..28ac711e 100644 --- a/counter.c +++ b/counter.c @@ -96,6 +96,10 @@ self = (pCounter)pData; assert(self); + if(!GetCountLock(self->pCountInt, pCon)){ + return 0; + } + /* try at least three times to do it */ for(i = 0; i < 3; i++) { @@ -118,12 +122,14 @@ { SCWrite(pCon,"ERROR: Cannot fix counter problem, aborting",eError); SCSetInterrupt(pCon,eAbortBatch); + ReleaseCountLock(self->pCountInt); return HWFault; } } } SCWrite(pCon,"ERROR: Cannot fix counter problem, aborting",eError); SCSetInterrupt(pCon,eAbortBatch); + ReleaseCountLock(self->pCountInt); return HWFault; } /*-----------------------------------------------------------------------*/ @@ -235,6 +241,7 @@ SCWrite(pCon,"ERROR: Cannot fix counter problem, aborting",eError); SCSetInterrupt(pCon,eAbortBatch); InvokeCallBack(self->pCall,COUNTEND,NULL); + ReleaseCountLock(self->pCountInt); return eCt; } else @@ -267,6 +274,7 @@ if(eCt == HWIdle) { InvokeCallBack(self->pCall,COUNTEND,NULL); + ReleaseCountLock(self->pCountInt); } return eCt; } @@ -462,7 +470,7 @@ if(!iRet) { SetStatus(eOld); - SCWrite(pCon,"Counting aborted",eStatus); + SCWrite(pCon,"Counting aborted",eError); return 0; } @@ -476,16 +484,16 @@ iRet = Wait4Success(GetExecutor()); if(iRet == DEVINT) { - SCWrite(pCon,"Counting aborted due to Interrupt",eStatus); + SCWrite(pCon,"Counting aborted due to Interrupt",eError); } else if(iRet == DEVERROR) { - SCWrite(pCon,"Counting finished with Problems",eStatus); + SCWrite(pCon,"Counting finished with Problems",eError); iRet = 1; } else { - SCWrite(pCon,"Counting finished",eStatus); + SCWrite(pCon,"Counting finished",eValue); iRet = 1; } SetStatus(eOld); @@ -715,15 +723,18 @@ return 1; } /*-----------------------------------------------------------------------*/ - static int CounterInterest(int iEvent, void *pEvent, void *pUser, - commandContext cc) + static int CounterInterest(int iEvent, void *pEvent, void *pUser) { SConnection *pCon = NULL; pMonEvent pMon = NULL; char pBueffel[512]; int rights; - if(iEvent != MONITOR) + if(pCon == NULL || !SCisConnected(pCon)){ + return -1; + } + + if(iEvent != MONITOR || pCon == NULL) { return 0; } @@ -737,10 +748,8 @@ /** * prevent this to be written to log files */ - rights = SCGetRights(pCon); SCSetRights(pCon,usSpy); - SCWriteInContext(pCon,pBueffel,eWarning,cc); - SCSetRights(pCon,rights); + SCWrite(pCon,pBueffel,eWarning); return 1; } /*-----------------------------------------------------------------------*/ @@ -817,6 +826,10 @@ return 1; break; case 2: /* Set Preset */ + if(isRunning(self->pCountInt)){ + SCWrite(pCon,"ERROR: cannot change preset while counting", eError); + return 0; + } if(isAuthorised(pCon,usUser)) { iRet2 = SetCounterPreset(self,PaRes.Arg[0].fVal); @@ -844,6 +857,10 @@ return 1; break; case 4: /* Set Mode */ + if(isRunning(self->pCountInt)){ + SCWrite(pCon,"ERROR: cannot change mode while counting", eError); + return 0; + } if(isAuthorised(pCon,usUser)) { if(strcmp(PaRes.Arg[0].text,"timer") == 0) @@ -905,13 +922,13 @@ SCWrite(pCon,pBueffel,eValue); return 1; case 9: /* interest */ - lID = RegisterCallback(self->pCall, SCGetContext(pCon), MONITOR, CounterInterest, - pCon, NULL); - SCRegister(pCon,pSics, self->pCall,lID); + lID = RegisterCallback(self->pCall, MONITOR, CounterInterest, + SCCopyConnection(pCon), + SCDeleteConnection); SCSendOK(pCon); return 1; case 10: /* uninterest */ - RemoveCallback2(self->pCall,pCon); + RemoveCallbackCon(self->pCall,pCon); SCSendOK(pCon); return 1; case 11: /* status */ @@ -1008,6 +1025,10 @@ /* mode */ if(PaRes.Arg[0].iVal) /* set case */ { + if(isRunning(self->pCountInt)){ + SCWrite(pCon,"ERROR: cannot change mode while counting",eError); + return 0; + } if(isAuthorised(pCon,usUser)) { if(strcmp(PaRes.Arg[0].text,"timer") == 0) @@ -1053,6 +1074,10 @@ case 18: /* preset */ if(PaRes.Arg[0].iVal) /* set case */ { + if(isRunning(self->pCountInt)){ + SCWrite(pCon,"ERROR: cannot set preset while counting", eError); + return 0; + } if(isAuthorised(pCon,usUser)) { iRet2 = SetCounterPreset(self,PaRes.Arg[0].fVal); @@ -1095,6 +1120,10 @@ } break; case 20: /* setpar*/ + if(isRunning(self->pCountInt)){ + SCWrite(pCon,"ERROR: cannot change parameters while counting", eError); + return 0; + } if(!SCMatchRights(pCon,usMugger)) { return 0; diff --git a/danu.c b/danu.c index aac6ee68..de9ef6e7 100644 --- a/danu.c +++ b/danu.c @@ -95,14 +95,19 @@ static int writeDataNumber(pDataNumber self, int iNum) return 1; } /*------------------- The CallBack function for interest ------------------*/ - static int InterestCallback(int iEvent, void *pEvent, void *pUser, - commandContext cc) + static int InterestCallback(int iEvent, void *pEvent, void *pUser) { pDataNumber self = NULL; SConnection *pCon = NULL; char pBueffel[132]; int iNum; + pCon = (SConnection *)pUser; + if(pCon == NULL || !SCisConnected(pCon)) + { + return -1; + } + if(iEvent != VALUECHANGE) { return 1; @@ -111,7 +116,6 @@ static int writeDataNumber(pDataNumber self, int iNum) assert(pEvent); assert(pUser); - pCon = (SConnection *)pUser; self = (pDataNumber)pEvent; /* @@ -121,7 +125,7 @@ static int writeDataNumber(pDataNumber self, int iNum) if(iNum > 0) { snprintf(pBueffel,131,"sicsdatanumber = %d", iNum); - SCWriteInContext(pCon,pBueffel,eValue,cc); + SCWrite(pCon,pBueffel,eValue); } return 1; } @@ -331,16 +335,16 @@ int NewThousand(pDataNumber self) } if(strcmp(argv[1],"interest") == 0) { - lID = RegisterCallback(self->pCall, SCGetContext(pCon), + lID = RegisterCallback(self->pCall, VALUECHANGE, InterestCallback, - pCon, NULL); - SCRegister(pCon,pSics, self->pCall,lID); + SCCopyConnection(pCon), + SCDeleteConnection); SCSendOK(pCon); return 1; } if(strcmp(argv[1],"uninterest") == 0) { - RemoveCallback2(self->pCall,pCon); + RemoveCallbackCon(self->pCall,pCon); SCSendOK(pCon); } diff --git a/devexec.c b/devexec.c index 5fb75981..d351b22f 100644 --- a/devexec.c +++ b/devexec.c @@ -12,6 +12,9 @@ Refactored and instrumentation for instrument staticstics added. Mark Koennecke, July 2006 + Reworked to use copied connection objects instead of context pushes. + Mark Koennecke, January 2009 + Copyright: Labor fuer Neutronenstreuung @@ -113,7 +116,7 @@ void DevexecLog(char *operation, char *device) { pObjectDescriptor pDescriptor; float fVal; char *name; - commandContext comCon; + SConnection *pCon; } DevEntry, *pDevEntry; /*------------------------------------------------------------------------*/ typedef struct { @@ -123,7 +126,8 @@ typedef struct { pIDrivable pDrivInt; }checkContext, *pCheckContext; /*-------------------------------------------------------------------------*/ - static pDevEntry CreateDevEntry(pObjectDescriptor pDes, void *pData, + static pDevEntry CreateDevEntry(pObjectDescriptor pDes, SConnection *pCon, + void *pData, float fVal, char *name) { pDevEntry pNew = NULL; @@ -139,7 +143,7 @@ typedef struct { pNew->pData = pData; pNew->name = strdup(name); pNew->fVal = fVal; - memset(&pNew->comCon,0,sizeof(commandContext)); + pNew->pCon = SCCopyConnection(pCon); return pNew; } /*-------------------------------------------------------------------------*/ @@ -151,9 +155,11 @@ typedef struct { { free(self->name); } + if(self->pCon){ + SCDeleteConnection(self->pCon); + } free(self); } - /* ----------------- The Executor himself ---------------------------------*/ typedef struct __EXELIST{ pObjectDescriptor pDes; @@ -242,6 +248,11 @@ typedef struct { if(self->pCall) DeleteCallBackInterface(self->pCall); + if(self->pOwner){ + SCDeleteConnection(self->pOwner); + self->pOwner = NULL; + } + free(self); pServ->pExecutor = NULL; if(devLog != NULL){ @@ -279,7 +290,7 @@ typedef struct { /* may we? */ if(self->pOwner != NULL) { - if(pCon != self->pOwner) + if(pCon->ident != self->pOwner->ident) { /* this hack helps on rita2, when using the sendsics script which opens a client for every command */ @@ -288,7 +299,8 @@ typedef struct { overwriteOwner = overwriteOption && *overwriteOption != '0'; } if (overwriteOwner) { - self->pOwner = pCon; + SCDeleteConnection(self->pOwner); + self->pOwner = SCCopyConnection(pCon); } else { SCWrite(pCon, "ERROR: somebody else is still driving, Request rejected",eError); @@ -298,7 +310,7 @@ typedef struct { } else { - self->pOwner = pCon; + self->pOwner = SCCopyConnection(pCon); } if(self->iLock == 1) { @@ -308,14 +320,12 @@ typedef struct { /* well create a new entry */ self->iStop = 0; - pNew = CreateDevEntry(pDes,pData,fNew,name); + pNew = CreateDevEntry(pDes,pCon,pData,fNew,name); if(!pNew) { SCWrite(pCon,"ERROR: memory exhausted in Device Executor ",eError); return 0; } - pNew->comCon = SCGetContext(pCon); - strncpy(pNew->comCon.deviceID,name,SCDEVIDLEN); /* start it */ pDrivInt = pDes->GetInterface(pData,DRIVEID); @@ -328,7 +338,7 @@ typedef struct { oldVal = pDrivInt->GetValue(pData,pCon); snprintf(pBueffel,131,"Driving %s from %8.3f to %8.3f", name, oldVal, fNew); - SCWrite(pCon,pBueffel,eWarning); + SCWrite(pCon,pBueffel,eValue); } } else if(pCountInt) @@ -346,9 +356,9 @@ typedef struct { { LLDnodeAppendFrom(self->iList,&pNew); sprintf(pBueffel,"started"); - if(NULL!=pNew->comCon.deviceID) + if(NULL!=pNew->pCon->deviceID) { - snprintf(pBueffel,130,"started (%s)",pNew->comCon.deviceID); + snprintf(pBueffel,130,"started (%s)",pNew->pCon->deviceID); } ExeInterest(self, pNew, pBueffel); self->iRun = 1; @@ -375,13 +385,15 @@ typedef struct { DeleteDevEntry(pNew); if(LLDcheck(self->iList) >= LIST_EMPTY) { + if(self->pOwner != NULL){ + SCDeleteConnection(self->pOwner); + } self->pOwner = NULL; } return 0; } return 0; } -/*-----------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/ int StartMotor(pExeList self, SicsInterp *pSics, SConnection *pCon, char *name, float fVal) @@ -467,183 +479,10 @@ typedef struct { return StartDevice(self,name,pCter->pDes,(void *)pCter, pCon,pCter->pDriv->fPreset); } -/*--------------------------------------------------------------------------*/ - int CheckExeListOld(pExeList self) - { - int iRet; - 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((self->pOwner == NULL) || (LLDcheck(self->iList) == LIST_EMPTY)) - { - self->iRun = 0; - self->iEnd = 1; - self->iStop = 0; - return 1; - } - - /* - check the status of all registered devices. Remove when finished - */ - iRet = LLDnodePtr2First(self->iList); - while(iRet != 0) - { - LLDnodeDataTo(self->iList,&pDev); - if(pDev) - { - SCPushContext(self->pOwner, pDev->comCon.transID, pDev->comCon.deviceID); - - pDrivInt = pDev->pDescriptor->GetInterface(pDev->pData,DRIVEID); - pCountInt = pDev->pDescriptor->GetInterface(pDev->pData,COUNTID); - - if(pDrivInt) - { - eCode = pDrivInt->CheckStatus(pDev->pData,self->pOwner); - } - else if(pCountInt) - { - eCode = pCountInt->CheckCountStatus(pDev->pData,self->pOwner); - } - switch(eCode) - { - case HWIdle: - case OKOK: - if(pCountInt) - { - pCountInt->TransferData(pDev->pData,self->pOwner); - } - else if(pDrivInt) - { - pDrivInt->iErrorCount = 0; - } - ExeInterest(self, pDev, "finished"); - DeleteDevEntry(pDev); - LLDnodeDelete(self->iList); - SCWrite(pCon, "", eFinish); - iRet = LLDnodePtr2Prev(self->iList); - if(SCGetInterrupt(self->pOwner) != eContinue) - { - self->iStatus = DEVINT; - SCPopContext(self->pOwner); - return -1; - } - self->iStatus = DEVDONE; - break; - case HWFault: /* real HW error: burning, no net etc.. */ - ExeInterest(self, pDev, "finished with problem"); - DeleteDevEntry(pDev); - pDev = NULL; - SCWrite(pCon, "", eFinish); - LLDnodeDataTo(self->iList,&pDev); - LLDnodeDelete(self->iList); - iRet = LLDnodePtr2Prev(self->iList); - self->iStatus = DEVERROR; - if(pDrivInt) - { - pDrivInt->iErrorCount++; - } - if(SCGetInterrupt(self->pOwner) != eContinue) - { - self->iStatus = DEVINT; - SCPopContext(self->pOwner); - return -1; - } - break; - case HWNoBeam: - SetStatus(eOutOfBeam); - if(SCGetInterrupt(self->pOwner) != eContinue) - { - SetStatus(eEager); - self->iStatus = DEVINT; - SCPopContext(self->pOwner); - return -1; - } - break; - case HWPause: - SetStatus(ePaused); - if(SCGetInterrupt(self->pOwner) != eContinue) - { - ContinueExecution(self); - self->iStatus = DEVINT; - SCPopContext(self->pOwner); - return -1; - } - break; - case HWBusy: - if(pDrivInt != NULL) - { - isDriving = 1; - } - else if(pCountInt != NULL) - { - isCounting = 1; - } - self->iStatus = DEVBUSY; - break; - case HWPosFault: /* cannot get somewhere... */ - ExeInterest(self, pDev, "finished with problem"); - DeleteDevEntry(pDev); - LLDnodeDelete(self->iList); - SCWrite(pCon, "", eFinish); - self->iStatus = DEVERROR; - if(pDrivInt) - { - pDrivInt->iErrorCount++; - } - if(SCGetInterrupt(self->pOwner) != eContinue) - { - self->iStatus = DEVINT; - SCPopContext(self->pOwner); - return -1; - } - break; - } - SCPopContext(self->pOwner); - } - iRet = LLDnodePtr2Next(self->iList); - } - - if (isCounting) { - if (isDriving) { - SetStatus(eCountDrive); - } else { - SetStatus(eCounting); - } - } else if (isDriving) { - SetStatus(eDriving); - } - - iRet = LLDnodePtr2First(self->iList); - if(LLDcheck(self->iList) == LIST_EMPTY) - { - self->pOwner = NULL; - self->iEnd = 1; - self->iRun = 0; - self->lTask = -1; - return 1; - } - else - { - 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 { @@ -654,15 +493,13 @@ static int checkInterrupt(pCheckContext pCheck, int targetStatus){ static int initializeCheck(pCheckContext pCheck, pDevEntry pDev){ int eCode = HWFault; - 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); + eCode = pCheck->pDrivInt->CheckStatus(pDev->pData,pDev->pCon); } else if(pCheck->pCountInt != NULL) { - eCode = pCheck->pCountInt->CheckCountStatus(pDev->pData,pCheck->self->pOwner); + eCode = pCheck->pCountInt->CheckCountStatus(pDev->pData,pDev->pCon); } return eCode; } @@ -671,7 +508,7 @@ static int finishDevice(pCheckContext pCheck){ int status; if(pCheck->pCountInt != NULL) { - pCheck->pCountInt->TransferData(pCheck->pDev->pData,pCheck->self->pOwner); + pCheck->pCountInt->TransferData(pCheck->pDev->pData,pCheck->pDev->pCon); } else if(pCheck->pDrivInt != NULL) { pCheck->pDrivInt->iErrorCount = 0; } @@ -704,6 +541,9 @@ static int errorDevice(pCheckContext pCheck){ /*-------------------------------------------------------------------------*/ static int testFinish(pExeList self){ if((self->pOwner == NULL) || (LLDcheck(self->iList) == LIST_EMPTY)) { + if(self->pOwner != NULL){ + SCDeleteConnection(self->pOwner); + } self->pOwner = NULL; self->iRun = 0; self->iEnd = 1; @@ -725,8 +565,6 @@ static int testFinish(pExeList self){ int eCode; int isCounting=0, isDriving=0; char pBueffel[512]; - SConnection *pCon; - pCon = self->pOwner; assert(self); @@ -812,7 +650,6 @@ static int testFinish(pExeList self){ } break; } - SCPopContext(self->pOwner); } status = LLDnodePtr2Next(self->iList); } @@ -866,12 +703,12 @@ static int testFinish(pExeList self){ iRet = CheckExeList(self); if(iRet == 1) /* nothing to do! */ { - SCWrite(pCon,"Machine idle",eStatus); + SCWrite(pCon,"Machine idle",eValue); return 1; } else if(iRet == -1) { - SCWrite(pCon,"Handling Interrupt",eStatus); + SCWrite(pCon,"Handling Interrupt",eError); return 0; } @@ -884,7 +721,7 @@ static int testFinish(pExeList self){ if(pDev) { sprintf(pBueffel,"\t%s %f",pDev->name,pDev->fVal); - SCWrite(pCon,pBueffel,eStatus); + SCWrite(pCon,pBueffel,eValue); } iRet = LLDnodePtr2Next(self->iList); } @@ -949,9 +786,7 @@ static int testFinish(pExeList self){ } iRet = LLDnodePtr2Next(self->iList); } - SCPushContext(self->pOwner,0,"system"); SCWrite(self->pOwner,"ERROR: Full Stop called!!",eError); - SCPopContext(self->pOwner); if(SCGetInterrupt(self->pOwner) > eContinue) { self->iStatus = DEVINT; @@ -1009,12 +844,10 @@ static int testFinish(pExeList self){ pDev = (pDevEntry)LLDnodePtr(self->iList); if(pDev) { - SCPushContext(self->pOwner, pDev->comCon.transID, pDev->comCon.deviceID); - pCountInt = pDev->pDescriptor->GetInterface(pDev->pData,COUNTID); if(pCountInt) { - iRet = pCountInt->Pause(pDev->pData,self->pOwner); + iRet = pCountInt->Pause(pDev->pData,pDev->pCon); if(!iRet) { iRes = 0; @@ -1022,7 +855,6 @@ static int testFinish(pExeList self){ } } - SCPopContext(self->pOwner); iRet = LLDnodePtr2Next(self->iList); } SetStatus(ePaused); @@ -1072,13 +904,11 @@ static int testFinish(pExeList self){ pCountInt = pDev->pDescriptor->GetInterface(pDev->pData,COUNTID); if(pCountInt) { - SCPushContext(self->pOwner, pDev->comCon.transID, pDev->comCon.deviceID); - iRet = pCountInt->Continue(pDev->pData,self->pOwner); + iRet = pCountInt->Continue(pDev->pData,pDev->pCon); if(!iRet) { iRes = 0; } - SCPopContext(self->pOwner); } } @@ -1113,6 +943,7 @@ static int testFinish(pExeList self){ { self->iStatus = DEVINT; } + SCDeleteConnection(self->pOwner); } self->pOwner = NULL; self->iEnd = 1; @@ -1156,15 +987,17 @@ static int testFinish(pExeList self){ return iRet; } /*------------------- The CallBack function for interest ------------------*/ - static int DrivStatCallback(int iEvent, void *text, void *pCon, - commandContext cc) + static int DrivStatCallback(int iEvent, void *text, void *pCon) { assert(pCon); assert(text); - - SCPushContext2(pCon,cc); - SCWrite(pCon, text, eValue); - SCPopContext(pCon); + SConnection *con = (SConnection *)pCon; + + if(con == NULL || !SCisConnected(con)) + { + return -1; + } + SCWrite(pCon, text, eLog); return 1; } /*--------------------------------------------------------------------------*/ @@ -1183,17 +1016,15 @@ static int testFinish(pExeList self){ if (argc == 2) { if (strcmp(argv[1], "interest") == 0) { - list = RegisterCallback(self->pCall, SCGetContext(pCon), + list = RegisterCallback(self->pCall, DRIVSTAT, DrivStatCallback, - pCon, NULL); - SCRegister(pCon, pSics, self->pCall,list); + SCCopyConnection(pCon), NULL); SCSendOK(pCon); return 1; } if (strcmp(argv[1], "uninterest") == 0) - { - RemoveCallback2(self->pCall, pCon); - SCUnregister(pCon, self->pCall); + { + RemoveCallbackCon(self->pCall,pCon); SCSendOK(pCon); return 1; } @@ -1240,12 +1071,12 @@ static int testFinish(pExeList self){ } else if(iRet == DEVDONE) { - SCWrite(pCon,"All done",eStatus); + SCWrite(pCon,"All done",eValue); iRet = 1; } else if(iRet == DEVERROR) { - SCWrite(pCon,"Finished with Problems",eStatus); + SCWrite(pCon,"Finished with Problems",eValue); iRet = 1; } SetStatus(eEager); @@ -1422,6 +1253,7 @@ static int testFinish(pExeList self){ { int *iInt; pExeList self = NULL; + SConnection *pCon = NULL; self = (pExeList)pEL; assert(self); @@ -1433,12 +1265,16 @@ static int testFinish(pExeList self){ { if(self->pOwner) { - SCPushContext(self->pOwner,0,"system"); - SCWrite(self->pOwner, + pCon = SCCopyConnection(self->pOwner); + if(pCon != NULL){ + pCon->transID = 0; + strcpy(pCon->deviceID,"system"); + SCWrite(pCon, "ERROR: Interrupting Current Hardware Operation", eError); - SCSetInterrupt(self->pOwner,*iInt); - SCPopContext(self->pOwner); + SCSetInterrupt(pCon,*iInt); + SCDeleteConnection(pCon); + } } StopExe(self,"all"); } @@ -1456,7 +1292,7 @@ void UnlockDeviceExecutor(pExeList self) assert(self); self->iLock = 0; } - + diff --git a/devser.c b/devser.c index af7da49b..3bc74d21 100644 --- a/devser.c +++ b/devser.c @@ -217,7 +217,13 @@ void DevKill(DevSer *devser) { } } -void DevQueue(DevSer *devser, void *actionData, DevPrio prio, +void DevDisconnect(DevSer *devser){ + if(devser->asyncConn){ + AsconDisconnect(devser->asyncConn); + } +} + +int DevQueue(DevSer *devser, void *actionData, DevPrio prio, DevActionHandler hdl, DevActionMatch *matchFunc, DevKillActionData *killFunc) { DevAction *action, **ptr2Last; @@ -228,13 +234,14 @@ void DevQueue(DevSer *devser, void *actionData, DevPrio prio, ptr2Last = &devser->actions; for (action = devser->actions; action != NULL && action->prio >= prio; action = action->next) { if (action->hdl == hdl && matchFunc(actionData, action->data)) { - return; /* there is already an identical action */ + return 0; /* there is already an identical action */ } ptr2Last = &action->next; } new = DevNewAction(actionData, hdl, killFunc, prio); new->next = action; *ptr2Last = new; + return 1; } int DevUnschedule(DevSer *devser, void *actionData, diff --git a/devser.h b/devser.h index 95f29a8a..d5d42248 100644 --- a/devser.h +++ b/devser.h @@ -54,6 +54,10 @@ void DevDebugMode(DevSer *devser, int steps); * \param devser the device serializer */ void DevKill(DevSer *devser); +/** \brief Disconnect + * \param devser The device serializer to disconnect + */ +void DevDisconnect(DevSer *devser); /** \brief Queue an action * @@ -67,8 +71,10 @@ void DevKill(DevSer *devser); * \param killFunc the action data kill function (called from DevKill and * after the action has finished, i.e. when hdl returned NULL) * or NULL if no kill function is needed. + * \return 0 when not queued because a similar action is already on the queue, + * 1 on success. */ -void DevQueue(DevSer *devser, void *actionData, DevPrio prio, +int DevQueue(DevSer *devser, void *actionData, DevPrio prio, DevActionHandler hdl, DevActionMatch *matchFunc, DevKillActionData *killFunc) ; diff --git a/diffscan.c b/diffscan.c index 08fd95d3..0d568401 100644 --- a/diffscan.c +++ b/diffscan.c @@ -312,7 +312,7 @@ static int DiffScanTask(void *pData){ if(data->Monitors[self->scaleMonitor -1] - self->last.Monitors[self->scaleMonitor-1] < 5) { SCWrite(self->scanObject->pCon, - "WARNING: low count rate",eWarning); + "WARNING: low count rate",eLog); } rawCount = data->lCount; rawMon = data->Monitors[self->scaleMonitor-1]; @@ -329,7 +329,7 @@ static int DiffScanTask(void *pData){ self->scanObject->iCounts -1, fPos, countValue, rawCount, rawMon); - SCWrite(self->scanObject->pCon,pBueffel,eWarning); + SCWrite(self->scanObject->pCon,pBueffel,eLog); InvokeCallBack(self->scanObject->pCall,SCANPOINT,self->scanObject); /* diff --git a/drive.c b/drive.c index 8e85a51c..4d622a3c 100644 --- a/drive.c +++ b/drive.c @@ -131,21 +131,21 @@ { SCSetInterrupt(pCon,eContinue); sprintf(pBueffel,"Driving %s aborted at %9.3f",name, fPos); - SCWrite(pCon,pBueffel,eStatus); + SCWrite(pCon,pBueffel,eError); } return 0; } else if(iRet == DEVDONE) { sprintf(pBueffel,"Driving %s to %9.3f done", name, fPos); - SCWrite(pCon,pBueffel,eStatus); + SCWrite(pCon,pBueffel,eValue); return 1; } else { sprintf(pBueffel, "Driving %s finished with problems, position: %9.3f",name,fPos); - SCWrite(pCon,pBueffel,eStatus); + SCWrite(pCon,pBueffel,eValue); return 1; } } @@ -393,7 +393,7 @@ SetStatus(eOld); return 0; } - SCWrite(pCon,"Driving finished sucessfully",eStatus); + SCWrite(pCon,"Driving finished sucessfully",eValue); SetStatus(eOld); return 1; } diff --git a/dynstring.c b/dynstring.c index 0fca397b..0fbbde52 100644 --- a/dynstring.c +++ b/dynstring.c @@ -254,6 +254,19 @@ return self->iTextLen; } +/*---------------------------------------------------------------------------*/ + int DynStringBackspace(pDynString self) + { + assert(self); + assert(self->iMAGIC == DYNMAGIC); + + if(self->iTextLen > 0) + { + self->pBuffer[self->iTextLen - 1] = '\0'; + self->iTextLen--; + } + return 1; + } diff --git a/dynstring.h b/dynstring.h index 9d93f327..a40b7acb 100644 --- a/dynstring.h +++ b/dynstring.h @@ -87,6 +87,10 @@ int DynStringClear(pDynString self); /* - removes all old dat from the dynstring + removes all old data from the dynstring */ + int DynStringBackspace(pDynString self); + /* + removes one character at the end from the dynstring + */ #endif diff --git a/evcontroller.c b/evcontroller.c index 3a2e5a7e..41707d08 100644 --- a/evcontroller.c +++ b/evcontroller.c @@ -100,7 +100,14 @@ self->start = time(NULL); self->lastt = 0; self->iWarned = 0; - self->conn = SCSave(pCon, self->conn); + if(self->conn != NULL){ + SCDeleteConnection(self->conn); + } + self->conn = SCCopyConnection(pCon); + if(self->conn == NULL){ + SCWrite(pCon,"ERROR: out of memory in EVIDrive", eError); + return 0; + } /* try at least three times to do it */ for(i = 0; i < 3; i++) @@ -302,7 +309,7 @@ { sprintf(pBueffel,"%s inside tolerance, wait %.2f sec to settle", self->pName, (self->lastt + tmo - now)*1.0); - SCWrite(pCon,pBueffel,eWarning); + SCWrite(pCon,pBueffel,eLog); } notifyStatus(self, pCon, HWBusy); return HWBusy; @@ -322,7 +329,7 @@ if (tmo > 0) { sprintf(pBueffel,"%s outside tolerance, settling time suspended", self->pName); - SCWrite(pCon,pBueffel,eWarning); + SCWrite(pCon,pBueffel,eLog); } self->lastt -= now; } @@ -376,7 +383,7 @@ } /*---------------------------- Error Handlers --------------------------------*/ -static void ErrWrite(char *txt, SCStore *conn) +static void ErrWrite(char *txt, SConnection *conn) { pExeList pExe; SConnection *pCon = NULL; @@ -386,13 +393,11 @@ static void ErrWrite(char *txt, SCStore *conn) if (pCon) { - SCWrite(pCon,txt,eWarning); + SCWrite(pCon,txt,eLog); } else { - pCon = SCStorePush(conn); - SCWrite(pCon, txt, eWarning); - SCStorePop(conn); + SCWrite(conn, txt, eLog); } } /*-----------------------------------------------------------------------*/ @@ -436,7 +441,7 @@ static void ErrReport(pEVControl self) pExe = GetExecutor(); if(IsCounting(pExe)) { - SCWrite(GetExeOwner(pExe),"Pausing till OK",eError); + SCWrite(GetExeOwner(pExe),"Pausing till OK",eLogError); PauseExecution(pExe); /* wait till OK */ @@ -796,7 +801,10 @@ static void ErrReport(pEVControl self) pRes->pName = strdup(pName); pRes->eMode = EVIdle; pRes->iWarned = 0; - pRes->conn = NULL; + if(pRes->conn != NULL){ + SCDeleteConnection(pRes->conn); + pRes->conn = NULL; + } /* a terminal error gives a -1 in iRet */ if(iRet < 0) @@ -871,7 +879,7 @@ static void ErrReport(pEVControl self) } if (self->conn != NULL) { - SCStoreFree(self->conn); + SCDeleteConnection(self->conn); } free(self); } @@ -1064,17 +1072,21 @@ static void ErrReport(pEVControl self) return 1; } /*-------------------------------------------------------------------------*/ - static int EVCallBack(int iEvent, void *pEventData, void *pUserData, - commandContext cc) + static int EVCallBack(int iEvent, void *pEventData, void *pUserData) { char *pBuf = (char *)pEventData; SConnection *pCon = (SConnection *)pUserData; char pBueffel[132]; + + if(pCon == NULL || !SCisConnected(pCon)) + { + return -1; + } - if(iEvent == VALUECHANGE) + if(iEvent == VALUECHANGE && pCon != NULL) { pCon->conEventType=POSITION; - SCWriteInContext(pCon,pBuf,eEvent,cc); + SCWrite(pCon,pBuf,eEvent); return 1; } return 1; @@ -1135,16 +1147,15 @@ static void ErrReport(pEVControl self) /* install automatic notification */ else if(strcmp(argv[1],"interest") == 0) { - lID = RegisterCallback(self->pCall, SCGetContext(pCon), + lID = RegisterCallback(self->pCall, VALUECHANGE, EVCallBack, - pCon, NULL); - SCRegister(pCon,pSics, self->pCall,lID); + SCCopyConnection(pCon), SCDeleteConnection); SCSendOK(pCon); return 1; } else if(strcmp(argv[1],"uninterest") == 0) { - RemoveCallback2(self->pCall,pCon); + RemoveCallbackCon(self->pCall,pCon); SCSendOK(pCon); return 1; } diff --git a/evcontroller.i b/evcontroller.i index ad57cdbc..cdc30101 100644 --- a/evcontroller.i +++ b/evcontroller.i @@ -41,7 +41,7 @@ int iWarned; int iTcl; int iStop; - SCStore *conn; + SConnection *conn; char *creationArgs; char *runScript; void *pPrivate; diff --git a/evcontroller.tex b/evcontroller.tex index c51b8ee5..b11ecba6 100644 --- a/evcontroller.tex +++ b/evcontroller.tex @@ -52,7 +52,7 @@ $\langle$evdata {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@ int iWarned;@\\ \mbox{}\verb@ int iTcl;@\\ \mbox{}\verb@ int iStop;@\\ -\mbox{}\verb@ SCStore *conn;@\\ +\mbox{}\verb@ SConnection *conn;@\\ \mbox{}\verb@ char *creationArgs;@\\ \mbox{}\verb@ char *runScript;@\\ \mbox{}\verb@ void *pPrivate;@\\ diff --git a/evcontroller.w b/evcontroller.w index 0146f28f..b93cbc6d 100644 --- a/evcontroller.w +++ b/evcontroller.w @@ -47,7 +47,7 @@ used by EVControl: int iWarned; int iTcl; int iStop; - SCStore *conn; + SConnection *conn; char *creationArgs; char *runScript; void *pPrivate; diff --git a/exe.w b/exe.w index cd01232c..f68c3625 100644 --- a/exe.w +++ b/exe.w @@ -159,6 +159,7 @@ typedef struct __EXEMAN{ int runList; pExeBuf uploadBuffer; int echo; + SConnection *runCon; }ExeMan, *pExeMan; @} The fields: diff --git a/exebuf.c b/exebuf.c index 7ee47eb7..ddbe5f0d 100644 --- a/exebuf.c +++ b/exebuf.c @@ -197,7 +197,10 @@ int exeBufProcess(pExeBuf self, SicsInterp *pSics, cmdName[l] = '\0'; if (FindCommand(pSics, cmdName) != NULL) { /* print only SICS commands */ - SCPrintf(pCon, eValue, "%s:%d>> %s",self->name,self->lineno,cmd); + SCPrintf(pCon, eLog, "%s:%d>> %s",self->name,self->lineno,cmd); + } else { + /* debugging */ + /* SCPrintf(pCon, eValue, "%s:%d>> %s",self->name,self->lineno,cmd); */ } } } @@ -209,11 +212,11 @@ int exeBufProcess(pExeBuf self, SicsInterp *pSics, Tcl Error */ if(strlen(pTcl->result) >= 2){ - SCWrite(pCon,pTcl->result,eError); + SCPrintf(pCon,eLogError,"ERROR: Tcl reported: %s", pTcl->result); } - SCWrite(pCon,"ERROR: Tcl error in block:",eError); + SCWrite(pCon,"ERROR: Tcl error in block:",eLogError); SCWrite(pCon,GetCharArray(command),eError); - SCWrite(pCon,"ERROR: end of Tcl error block",eError); + SCWrite(pCon,"ERROR: end of Tcl error block",eLogError); } else { /* SICS error: has already been reported diff --git a/exebuf.h b/exebuf.h index bb1edba4..fc9de594 100644 --- a/exebuf.h +++ b/exebuf.h @@ -1,5 +1,5 @@ -#line 226 "exe.w" +#line 227 "exe.w" /** * Buffer handling code for the Exe Buffer batch file processing @@ -102,7 +102,7 @@ */ char *exeBufName(pExeBuf self); -#line 239 "exe.w" +#line 240 "exe.w" #endif diff --git a/exebuf.i b/exebuf.i index 32da477f..f69493a0 100644 --- a/exebuf.i +++ b/exebuf.i @@ -1,5 +1,5 @@ -#line 217 "exe.w" +#line 218 "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 222 "exe.w" +#line 223 "exe.w" diff --git a/exeman.c b/exeman.c index d5415592..f963b913 100644 --- a/exeman.c +++ b/exeman.c @@ -1,3 +1,4 @@ + /** * Implementation file for the exe buffer buffer manager. * @@ -225,6 +226,12 @@ static int runBatchBuffer(pExeMan self, SConnection *pCon, if(!SCMatchRights(pCon,usUser)) { return 0; } + + if(self->runCon != NULL && self->runCon != pCon){ + SCWrite(pCon,"ERROR: another batch buffer is already runnig", eError); + return 0; + } + filePath = locateBatchBuffer(self,name); if(filePath == NULL){ snprintf(pBueffel,255,"ERROR: batch buffer %s not found in path", @@ -320,9 +327,8 @@ int exeHdbNode(pHdb exeNode, SConnection *pCon){ pExeBuf buffer = NULL; hdbValue v; int status; - commandContext cc; - writeFunc oldWrite; - + SConnection *conCon = NULL; + /* * clear log buffer */ @@ -337,8 +343,12 @@ int exeHdbNode(pHdb exeNode, SConnection *pCon){ * prepare context */ name = GetHipadabaPath(log); - cc = SCGetContext(pCon); - strncpy(cc.deviceID, name,255); + conCon = SCCopyConnection(pCon); + if(conCon == NULL){ + SCWrite(pCon,"ERROR: out of memory in exehdbNode", eError); + return 0; + } + strncpy(conCon->deviceID, name,255); strncpy(bufferNode,name,511); /* @@ -365,12 +375,9 @@ int exeHdbNode(pHdb exeNode, SConnection *pCon){ exeBufAppend(buffer,v.v.text); strncpy(bufferNode,name,511); - oldWrite = SCGetWriteFunc(pCon); - SCSetWriteFunc(pCon,SCHdbWrite); - SCPushContext2(pCon,cc); - status = exeBufProcess(buffer,pServ->pSics,pCon,NULL,0); - SCSetWriteFunc(pCon,oldWrite); - SCPopContext(pCon); + SCSetWriteFunc(conCon,SCHdbWrite); + status = exeBufProcess(buffer,pServ->pSics,conCon,NULL,0); + SCDeleteConnection(conCon); exeBufDelete(buffer); free(name); if(strlen(log->value.v.text) < 2){ @@ -388,13 +395,16 @@ static int runHdbBuffer(pExeMan self, SConnection *pCon, pHdb node = NULL; hdbValue v; int status; - commandContext cc; - writeFunc oldWrite; - + SConnection *conCon = NULL; + if(!SCMatchRights(pCon,usUser)) { return 0; } + if(self->runCon != NULL && self->runCon != pCon){ + SCWrite(pCon,"ERROR: another bacth buffer is still running", eError); + return 0; + } /* * clear log buffer */ @@ -409,8 +419,8 @@ static int runHdbBuffer(pExeMan self, SConnection *pCon, /* * prepare context */ - cc = SCGetContext(pCon); - strcpy(cc.deviceID, pBueffel); + conCon = SCCopyConnection(pCon); + strcpy(conCon->deviceID, pBueffel); /* * load commands into buffer @@ -437,15 +447,14 @@ static int runHdbBuffer(pExeMan self, SConnection *pCon, exeBufAppend(buffer,v.v.text); strncpy(bufferNode,name,511); - oldWrite = SCGetWriteFunc(pCon); - SCSetWriteFunc(pCon,SCHdbWrite); - SCPushContext2(pCon,cc); + SCSetWriteFunc(conCon,SCHdbWrite); self->exeStackPtr++; + self->runCon = conCon; DynarPut(self->exeStack,self->exeStackPtr,buffer); - status = exeBufProcess(buffer,pSics,pCon,self->pCall,self->echo); + status = exeBufProcess(buffer,pSics,conCon,self->pCall,self->echo); self->exeStackPtr--; - SCSetWriteFunc(pCon,oldWrite); - SCPopContext(pCon); + self->runCon = NULL; + SCDeleteConnection(conCon); return status; } /*--------------------------------------------------------------------*/ @@ -519,6 +528,9 @@ typedef struct { /*------------------------------------------------------------------*/ static void killExeInfo(void *pData){ pExeInfo self = (pExeInfo)pData; + if(self->pCon != NULL){ + SCDeleteConnection(self->pCon); + } if(self != NULL){ free(self); } @@ -533,32 +545,41 @@ static pExeInfo makeExeInfo(SConnection *pCon, pExeMan self){ eError); return NULL; } - pNew->pCon = pCon; + memset(pNew,0,sizeof(exeInfo)); + pNew->pCon = SCCopyConnection(pCon); + if(pNew->pCon == NULL){ + SCWrite(pCon, + "ERROR: failed to allocate info structure for registering callbacks", + eError); + return NULL; + } pNew->exe = self; return pNew; } /*------------------------------------------------------------------*/ -static int BufferCallback(int iEvent, void *pEvent, void *pUser, - commandContext cc){ +static int BufferCallback(int iEvent, void *pEvent, void *pUser){ pExeInfo self = (pExeInfo)pUser; char *name = (char *)pEvent; char pBueffel[132]; + if(!SCisConnected(self->pCon)){ + return -1; + } + if(iEvent == BATCHSTART){ snprintf(pBueffel,131,"BATCHSTART=%s",name); - SCWriteInContext(self->pCon,pBueffel,eWarning,cc); + SCWrite(self->pCon,pBueffel,eLog); return 1; } if(iEvent == BATCHEND){ snprintf(pBueffel,131,"BATCHEND=%s",name); - SCWriteInContext(self->pCon,pBueffel,eWarning,cc); + SCWrite(self->pCon,pBueffel,eLog); return 1; } return 0; } /*-------------------------------------------------------------------*/ -static int LineCallBack(int iEvent, void *pEvent, void *pUser, - commandContext cc){ +static int LineCallBack(int iEvent, void *pEvent, void *pUser){ pExeInfo self = (pExeInfo)pUser; char pBueffel[256]; int start, end, lineno; @@ -566,6 +587,11 @@ static int LineCallBack(int iEvent, void *pEvent, void *pUser, pExeBuf buf = NULL; assert(self); + + if(!SCisConnected(self->pCon)){ + return -1; + } + if(iEvent == BATCHAREA){ DynarGet(self->exe->exeStack,self->exe->exeStackPtr,&pPtr); buf = (pExeBuf)pPtr; @@ -573,7 +599,7 @@ static int LineCallBack(int iEvent, void *pEvent, void *pUser, exeBufRange(buf,&start,&end,&lineno); snprintf(pBueffel,255,"%s.range = %d = %d",exeBufName(buf), start,end); - SCWriteInContext(self->pCon,pBueffel,eWarning,cc); + SCWrite(self->pCon,pBueffel,eLog); return 1; } return 0; @@ -588,15 +614,12 @@ static void registerCallbacks(SConnection *pCon, SicsInterp *pSics, if(info == NULL){ return; } - lID = RegisterCallback(self->pCall, SCGetContext(pCon),BATCHSTART, BufferCallback, + lID = RegisterCallback(self->pCall,BATCHSTART, BufferCallback, info, killExeInfo); - SCRegister(pCon,pSics, self->pCall,lID); - lID = RegisterCallback(self->pCall, SCGetContext(pCon),BATCHEND, BufferCallback, + lID = RegisterCallback(self->pCall, BATCHEND, BufferCallback, info, NULL); - SCRegister(pCon,pSics, self->pCall,lID); - lID = RegisterCallback(self->pCall, SCGetContext(pCon),BATCHAREA, LineCallBack, + lID = RegisterCallback(self->pCall, BATCHAREA, LineCallBack, info, NULL); - SCRegister(pCon,pSics, self->pCall,lID); } /*--------------------------------------------------------------------*/ static void unregisterCallbacks(SConnection *pCon, pExeMan self){ @@ -607,7 +630,6 @@ static void unregisterCallbacks(SConnection *pCon, pExeMan self){ lID = SCgetCallbackID(pCon,self->pCall); if(lID >= 0){ RemoveCallback(self->pCall,lID); - SCUnregisterID(pCon,lID); } } } @@ -1148,7 +1170,7 @@ static int execQueue(pExeMan self, SConnection *pCon, SicsInterp *pSics){ pExeBuf buf = NULL; int status; - if(self->exeStackPtr >= 0){ + if(self->exeStackPtr >= 0 || (self->runCon != NULL && self->runCon != pCon) ){ SCWrite(pCon, "ERROR: cannot start queue while batch buffers are still running",eError); return 0; @@ -1157,6 +1179,7 @@ static int execQueue(pExeMan self, SConnection *pCon, SicsInterp *pSics){ return 0; } + self->runCon = pCon; while(LLDnodePtr2First(self->runList) != 0){ LLDnodeDataTo(self->runList,&buf); LLDnodeDelete(self->runList); @@ -1164,6 +1187,7 @@ static int execQueue(pExeMan self, SConnection *pCon, SicsInterp *pSics){ if(buf == NULL){ SCWrite(pCon, "ERROR: serious trouble, buffer not in queue, inform programmer",eError); + self->runCon = NULL; return 0; } DynarPut(self->exeStack,self->exeStackPtr,buf); @@ -1171,9 +1195,11 @@ static int execQueue(pExeMan self, SConnection *pCon, SicsInterp *pSics){ self->exeStackPtr--; if(SCGetInterrupt(pCon) >= eAbortBatch){ SCWrite(pCon,"ERROR: queue processing interrupted",eError); + self->runCon = NULL; return 0; } } + self->runCon = 0; return 1; } /*========================== interpreter action =======================*/ @@ -1280,7 +1306,7 @@ int ExeManagerWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, }else if(strcmp(argv[1],"clear") == 0){ clearQueue(self); SCSendOK(pCon); - return 1; + return 1; }else if(strcmp(argv[1],"queue") == 0){ printQueue(self,pCon); SCSendOK(pCon); diff --git a/exeman.i b/exeman.i index 8b8512fb..aa3eb3d2 100644 --- a/exeman.i +++ b/exeman.i @@ -1,5 +1,5 @@ -#line 195 "exe.w" +#line 196 "exe.w" /*------------------------------------------------------------------- Internal header file for the exe manager module. Do not edit. This @@ -18,7 +18,8 @@ typedef struct __EXEMAN{ int runList; pExeBuf uploadBuffer; int echo; + SConnection *runCon; }ExeMan, *pExeMan; -#line 200 "exe.w" +#line 201 "exe.w" diff --git a/fitcenter.c b/fitcenter.c index d042bd0a..6f8f0c4c 100644 --- a/fitcenter.c +++ b/fitcenter.c @@ -322,12 +322,12 @@ if(SCGetInterrupt(pCon) == eAbortOperation) { SCSetInterrupt(pCon,eContinue); - SCWrite(pCon,"Driving Aborted",eStatus); + SCWrite(pCon,"Driving Aborted",eError); } return 0; break; case DEVDONE: - SCWrite(pCon,"Driving to center done",eStatus); + SCWrite(pCon,"Driving to center done",eValue); break; default: SCWrite(pCon, diff --git a/fourlib.c b/fourlib.c index f954f322..ee4fc8d0 100644 --- a/fourlib.c +++ b/fourlib.c @@ -608,11 +608,11 @@ void z1FromAllAngles(double lambda, double omega , double gamma, mat_free(z3); } /*-----------------------------------------------------------------------*/ -int findAllowedBisecting(double lambda, MATRIX z1, float fSet[4], +int findAllowedBisecting(double lambda, MATRIX z1, double *fSet, inRange testFunc, void *userData){ int status, i, mask[4]; double stt, om, chi, phi, psi, ompsi, chipsi, phipsi; - float fTest[4]; + double fTest[4]; status = z1mToBisecting(lambda,z1, &stt, &om, &chi, &phi); chi = circlify(chi); diff --git a/fourlib.h b/fourlib.h index 34fd23fa..ad3c50fa 100644 --- a/fourlib.h +++ b/fourlib.h @@ -187,8 +187,8 @@ int calcTheta(double lambda, MATRIX z1, double *d, double *theta); * in testing the range. * @return 0 on failure, 1 on success. */ -typedef int (*inRange)(void *userData, float dSet[4], int mask[4]); -int findAllowedBisecting(double lambda, MATRIX z1, float fSet[4], +typedef int (*inRange)(void *userData, double dSet[4], int mask[4]); +int findAllowedBisecting(double lambda, MATRIX z1, double fSet[4], inRange testFunc, void *userData); #endif diff --git a/fourmess.c b/fourmess.c new file mode 100644 index 00000000..03388aa9 --- /dev/null +++ b/fourmess.c @@ -0,0 +1,778 @@ +/** + * This is a new version of the four circle reflection measurement module. Its task is + * to provide functionality required for measuring a list of reflections. This is done + * with the help of some scripts binding things together. This module provides: + * - a table of scan parameters for measuring reflections at different angles. + * - the functions required to produce the scan data files for single detector + * mode. + * - a list of reflections to measure. + * + * In contrast to the old mesure module, this only provides some help to + * scripts. Thus, through scripts, a more flexible measurement is possible. + * + * copyright: see file COPYRIGHT + * + * Mark Koennecke, July 2008 + */ +#include +#include +#include "singlex.h" +#include "sicsobj.h" +#include "fourtable.h" +#include "sicshipadaba.h" +#include "sicsvar.h" +#include +#include "scan.h" +#include "stdscan.h" +#include "evcontroller.h" +#include "integrate.h" +#include "sginfo.h" +#include "matrix/matrix.h" +#include "cell.h" +#include "fourlib.h" + +extern void SNXFormatTime(char *pBueffel, int iLen); + +/*---------------------------------------------------------------------------*/ +typedef struct { + FILE *profFile; /* file with reflection profiles, ccl */ + FILE *hklFile; /* file with integrated intensities */ + int stepTable; /* table with the scan parameters */ + char *currentFileRoot; + pSICSOBJ messList; + pHdb currentRefl; /* the current reflection being measured */ + int count; + pScanData pScanner; + int masterCount; /* the number of master reflection as craeted by indgen */ +}FourMess, *pFourMess; +/*---------------------------------------------------------------------------*/ +static void KillFourMess(void *data){ + pFourMess priv = (pFourMess)data; + if(priv == NULL){ + return; + } + if(priv->profFile != NULL){ + fclose(priv->profFile); + } + if(priv->hklFile != NULL){ + fclose(priv->hklFile); + } + if(priv->currentFileRoot != NULL){ + free(priv->currentFileRoot); + } + if(priv->stepTable >= 0){ + DeleteFourCircleTable(priv->stepTable); + } + free(priv); +} +/*----------------------------------------------------------------------------*/ +static int FourMessAction(SConnection *pCon, SicsInterp *pSics, + void *data, int argc, char *argv[]){ + pFourMess priv = NULL; + pSICSOBJ self = (pSICSOBJ)data; + int err, status; + + assert(self != NULL); + priv = self->pPrivate; + assert(priv != NULL); + + if(argc < 2){ + SCWrite(pCon,"ERROR: insufficient number of arguments to fmess", + eError); + return 0; + } + + if(strcmp(argv[1],"table") == 0){ + return HandleFourCircleCommands(&priv->stepTable,pCon, + argc,argv,&err); + } + + status = InvokeSICSOBJ(pCon,pSics,data,argc,argv); + if(status < 0){ + SCPrintf(pCon,eError, "ERROR: %s no subcommand or parameter", + argv[1]); + return 0; + } + return status; +} +/*-----------------------------------------------------------------------------*/ +static int FourMessClose(pSICSOBJ self, SConnection *pCon, pHdb commandNode, + pHdb par[], int nPar){ + pFourMess priv = NULL; + + priv = self->pPrivate; + if(priv->hklFile != NULL){ + fclose(priv->hklFile); + priv->hklFile = NULL; + } + if(priv->profFile != NULL){ + fclose(priv->profFile); + priv->profFile = NULL; + } + return 1; +} +/*-----------------------------------------------------------------------------*/ +static int FourMessStart(pSICSOBJ self, SConnection *pCon, pHdb commandNode, + pHdb par[], int nPar){ + pFourMess priv = NULL; + char pFilename[512], pRoot[512]; + char pBueffel[1024]; + double lambda; + const double *dUB; + pSicsVariable pVar = NULL; + char *pFile = NULL, *pPtr; + FILE *temp = NULL; + pHdb node; + hdbValue v; + + assert(self); + assert(pCon); + + priv = self->pPrivate; + + if(nPar < 1){ + SCWrite(pCon,"ERROR: need file name parameter to start",eError); + return 0; + } + + /* close open files if so */ + if(priv->hklFile != NULL){ + FourMessClose(self,pCon,commandNode,par,nPar); + } + + /* create filename root */ + GetHipadabaPar(par[0],&v, pCon); + pFile = strdup(v.v.text); + pPtr = strrchr(pFile,(int)'.'); + pPtr++; + *pPtr = '\0'; + if(priv->currentFileRoot != NULL){ + free(priv->currentFileRoot); + } + priv->currentFileRoot = strdup(pFile); + free(pFile); + strncpy(pRoot,priv->currentFileRoot,511); + + + /* open the reflection file */ + sprintf(pBueffel,"Writing to %s.ccl, .rfl",pRoot); + SCWrite(pCon,pBueffel,eValue); + strcpy(pFilename,pRoot); + strcat(pFilename,"ccl"); + priv->profFile = fopen(pFilename,"w"); + if(!priv->profFile){ + sprintf(pBueffel,"ERROR: SERIOUS TROUBLE: cannot open %s!", + pFilename); + SCWrite(pCon,pBueffel,eError); + SCSetInterrupt(pCon,eAbortBatch); + return 0; + } + + node = GetHipadabaNode(self->objectNode,"template"); + assert(node != NULL); + GetHipadabaPar(node,&v,pCon); + temp = fopen(v.v.text,"r"); + if(temp == NULL) + { + SCWrite(pCon,"ERROR: failed to open header template",eError); + } + if(temp != NULL ) + { + WriteTemplate(priv->profFile, temp, pFilename, NULL, + pCon, pServ->pSics); + fclose(temp); + } + + /* open hkl-data file */ + strcpy(pFilename,pRoot); + strcat(pFilename,"rfl"); + priv->hklFile = fopen(pFilename,"w"); + if(!priv->hklFile){ + sprintf(pBueffel,"ERROR: SERIOUS TROUBLE: cannot open %s!", + pFilename); + SCWrite(pCon,pBueffel,eError); + SCSetInterrupt(pCon,eAbortBatch); + return 0; + } + fputs(pFilename,priv->hklFile); + fputs("\n",priv->hklFile); + + /* write some header data */ + SNXFormatTime(pBueffel,1024); + fprintf(priv->hklFile,"filetime = %s\n",pBueffel); + lambda = SXGetLambda(); + fprintf(priv->hklFile,"lambda = %f Angstroem\n",lambda); + dUB = SXGetUB(); + fprintf(priv->hklFile, + "UB = %7.6f %7.6f %7.6f %7.6f %7.6f %7.6f %7.6f %7.6f %7.6f\n", + dUB[0], dUB[1],dUB[2],dUB[3],dUB[4],dUB[5],dUB[6],dUB[7],dUB[8]); + + /* write sample & user info */ + strcpy(pBueffel,"CCL, Instr=TRICS, "); + pVar = FindVariable(pServ->pSics,"sample"); + if(pVar){ + fprintf(priv->hklFile,"sample = %s\n",pVar->text); + } + pVar = FindVariable(pServ->pSics,"user"); + if(pVar){ + fprintf(priv->hklFile,"user = %s \n",pVar->text); + } + priv->count = 0; + return 1; +} +/*----------------------------------------------------------------------------*/ +static int FourMessScanPar(pSICSOBJ self, SConnection *pCon, pHdb commandNode, + pHdb par[], int nPar){ + pFourMess priv = self->pPrivate; + char *scanvar; + double stt, dVal; + int np, preset; + pDynString data; + + assert(priv != NULL); + if(nPar < 1){ + SCWrite(pCon,"ERROR: need two theta parameter to scanpar", eError); + return 0; + } + stt = par[0]->value.v.doubleValue; + + scanvar = GetFourCircleScanVar(priv->stepTable,stt); + dVal = GetFourCircleStep(priv->stepTable,stt); + np = GetFourCircleScanNP(priv->stepTable,stt); + preset = GetFourCirclePreset(priv->stepTable,stt); + if(strcmp(scanvar,"NOT FOUND") == 0){ + SCPrintf(pCon,eValue,"%s,%f,%d,%d","om", dVal,np,preset); + } else { + SCPrintf(pCon,eValue,"%s,%f,%d,%d",scanvar,dVal,np,preset); + } + return 1; +} +/*----------------------------------------------------------------------------*/ +static hdbCallbackReturn SetScannerCB(pHdb node, void *userData, + pHdbMessage mm){ + pHdbDataMessage set = NULL; + pFourMess priv = (pFourMess)userData; + SConnection *pCon = NULL; + pScanData old; + + if((set = GetHdbSetMessage(mm)) != NULL){ + old = priv->pScanner; + priv->pScanner = FindCommandData(pServ->pSics,set->v->v.text,"ScanObject"); + if(priv->pScanner == NULL){ + priv->pScanner = old; + pCon = set->callData; + if(pCon != NULL){ + SCWrite(pCon,"ERROR: scan object not found", eError); + } + return hdbAbort; + } + } + return hdbContinue; +} +/*---------------------------------------------------------------------------*/ +static double getProtonAverage(pFourMess self){ + int np, i; + long *lData = NULL, lSum = 0; + + np = GetScanNP(self->pScanner); + lData = (long *)malloc((np+1)*sizeof(long)); + if(lData == NULL || np == 0){ + return 0.; + } + memset(lData,0,(np+1)*sizeof(long)); + GetScanMonitor(self->pScanner,2,lData, np); + for(i = 0; i < np; i++){ + lSum += lData[i]; + } + free(lData); + return (double)lSum/(double)np; +} +/*---------------------------------------------------------------------------*/ +static int FourMessStoreIntern(pSICSOBJ self, SConnection *pCon, + double fHkl[3], double fPosition[4]){ + pFourMess priv = self->pPrivate; + float fSum, fSigma, fTemp, fStep, fPreset; + int i, iLF, iRet, iNP,ii; + long *lCounts = NULL; + pEVControl pEva = NULL; + pDummy pPtr = NULL; + pIDrivable pDriv = NULL; + char pBueffel[512], pTime[512], pNum[10]; + double prot; + + if(priv->pScanner == NULL){ + SCWrite(pCon,"ERROR: store: scan not configured", eLogError); + return 0; + } + + if(priv->hklFile == NULL){ + SCWrite(pCon,"ERROR: store: no files open", eLogError); + return 0; + } + + /* get necessary data */ + fSum = 0.; + fSigma = 0.; + iRet = ScanIntegrate(priv->pScanner,&fSum, &fSigma); + if(iRet != 1){ + switch(iRet){ + case INTEGLEFT: + sprintf(pBueffel, + "WARNING: integration failed --> no left side to: %f %f %f", + fHkl[0], fHkl[1],fHkl[2]); + break; + case INTEGRIGHT: + sprintf(pBueffel, + "WARNING: integration failed -->no right side to: %f %f %f", + fHkl[0], fHkl[1],fHkl[2]); + break; + case INTEGNOPEAK: + sprintf(pBueffel, + "WARNING: integration failed -->no peak found: %f %f %f", + fHkl[0], fHkl[1],fHkl[2]); + break; + case INTEGFUNNYBACK: + sprintf(pBueffel, + "WARNING: integration problem, asymmetric background: %f %f %f", + fHkl[0], fHkl[1],fHkl[2]); + break; + } + SCWrite(pCon,pBueffel,eLog); + } + iNP = GetScanNP(priv->pScanner); + lCounts = malloc(iNP*sizeof(long)); + if(lCounts == NULL){ + SCWrite(pCon,"ERROR: out of memory in store", eLogError); + return 0; + } + GetScanCounts(priv->pScanner,lCounts,iNP); + + /* write it */ + if(priv->profFile){ + fprintf(priv->profFile,"%4d %7.3f %7.3f %7.3f %7.2f %7.2f %7.2f %7.2f %7.0f %7.2f\n", + priv->count, fHkl[0],fHkl[1],fHkl[2], + fPosition[0], fPosition[1], + fPosition[2], fPosition[3], + fSum,fSigma); + } + if(priv->hklFile){ + fprintf(priv->hklFile,"%5d %6.2f %6.2f %6.2f %7.2f %7.2f %7.2f %7.2f %7.0f %7.2f\n", + priv->count, fHkl[0],fHkl[1],fHkl[2], + fPosition[0], fPosition[1], + fPosition[2],fPosition[3], + fSum,fSigma); + } + sprintf(pBueffel,"%5d %6.2f %6.2f %6.2f %7.2f %7.2f %7.2f %7.2f %7.0f %7.2f\n", + priv->count, fHkl[0],fHkl[1],fHkl[2], + fPosition[0], fPosition[1], + fPosition[2], fPosition[3], + fSum,fSigma); + SCWrite(pCon,pBueffel,eLog); + + /* get temperature */ + fTemp = -777.77; + pEva = (pEVControl)FindCommandData(pServ->pSics,"temperature", + "Environment Controller"); + if(pEva == NULL){ + pPtr = (pDummy)FindCommandData(pServ->pSics,"temperature", + "RemObject"); + if(pPtr != NULL){ + pDriv = pPtr->pDescriptor->GetInterface(pPtr,DRIVEID); + if(pDriv != NULL){ + fTemp = pDriv->GetValue(pPtr,pCon); + } + } + } else { + iRet = EVCGetPos(pEva, pCon,&fTemp); + } + + /* write profile */ + if(priv->profFile){ + /* collect data */ + SNXFormatTime(pBueffel,512); + GetScanVarStep(priv->pScanner,0,&fStep); + fPreset = GetScanPreset(priv->pScanner); + prot = getProtonAverage(priv); + fprintf(priv->profFile,"%3d %7.4f %9.0f %7.3f %12f %s\n",iNP,fStep, + fPreset,fTemp,prot, pBueffel); + for(i = 0; i < iNP; i++){ + for(ii = 0; ii < 10 && i < iNP; ii++){ + fprintf(priv->profFile," %7ld",lCounts[i]); + iLF = 1; + i++; + } + fprintf(priv->profFile,"\n"); + i--; + iLF = 0; + } + if(iLF){ + fprintf(priv->profFile,"\n"); + } + fflush(priv->profFile); + } + + strcpy(pTime,pBueffel); + sprintf(pBueffel,"%3d%8.4f%10.0f%8.3f %s\n",iNP,fStep, + fPreset,fTemp,pTime); + SCWrite(pCon,pBueffel,eLog); + pBueffel[0] = '\0'; + for(i = 0; i < iNP; i++){ + for(ii = 0; ii < 10 && i < iNP; ii++){ + sprintf(pNum," %6ld",lCounts[i]); + strcat(pBueffel,pNum); + iLF = 1; + i++; + } + SCWrite(pCon,pBueffel,eLog); + pBueffel[0] = '\0'; + i--; + iLF = 0; + } + if(iLF){ + SCWrite(pCon,pBueffel,eLog); + } + free(lCounts); + return 1; + +} +/*----------------------------------------------------------------------------*/ +static int FourMessStore(pSICSOBJ self, SConnection *pCon, pHdb commandNode, + pHdb par[], int nPar){ + double fHkl[3], fPosition[4]; + int i; + + if(nPar < 7) { + SCWrite(pCon,"ERROR: not enough arguments for store",eError); + return 0; + } + + /* load hkl */ + for(i = 0; i < 3; i++){ + fHkl[i] = par[i]->value.v.doubleValue; + } + + /* load positions */ + for(i = 0; i < 4; i++){ + fPosition[i] = par[i+3]->value.v.doubleValue; + } + + return FourMessStoreIntern(self, pCon,fHkl, fPosition); +} +/*------------------------------------------------------------------*/ +static int weakScan(pSICSOBJ self, SConnection *pCon){ + int i, np; + long low = 99999, high = -99999, *lCounts = NULL; + pFourMess priv = self->pPrivate; + hdbValue v; + + /* + the scan is always OK if we do not test for weak conditions or we are in psd mode + */ + SICSHdbGetPar(self,pCon,"weak",&v); + if(v.v.intValue == 0){ + return 0; + } + + np = GetScanNP(priv->pScanner); + lCounts = malloc(np*sizeof(long)); + if(lCounts == NULL){ + SCWrite(pCon,"ERROR: out of memory in weakScan test", eLogError); + return 0; + } + GetScanCounts(priv->pScanner,lCounts,np); + for(i = 0; i < np; i++){ + if(lCounts[i] < low){ + low = lCounts[i]; + } + if(lCounts[i] > high){ + high = lCounts[i]; + } + } + /* + I am using the weakest point here as a rough estimate of + the background + */ + SICSHdbGetPar(self,pCon,"weakthreshold",&v); + if(high - 2 * low > v.v.intValue){ + return 0; + } else { + return 1; + } +} +/*----------------------------------------------------------------------------*/ +static int FourMessWeak(pSICSOBJ self, SConnection *pCon, pHdb commandNode, + pHdb par[], int nPar){ + int weak; + + weak = weakScan(self,pCon); + SCPrintf(pCon,eLog,"weak = %d", weak); + return 1; +} +/*----------------------------------------------------------------------------*/ +static int GenIndex(pSICSOBJ self, SConnection *pCon, pHdb commandNode, + pHdb par[], int nPar){ + double lambda = SXGetLambda(), d, om, hkl[3]; + int h, k, l, minh, mink, minl, suppress; + hdbValue hkllim, sttlim; + T_SgInfo *sginfo = SXGetSpaceGroup(); + pFourMess priv = self->pPrivate; + int count = 0; + MATRIX B, H, Z1; + const double *cell; + lattice direct; + + if(nPar < 1) { + SCWrite(pCon,"ERROR: need a suppression flag for indgen", + eError); + return 0; + } + SICSHdbGetPar(self,pCon,"hkllim",&hkllim); + SICSHdbGetPar(self,pCon,"sttlim",&sttlim); + suppress = par[0]->value.v.intValue; + + minh = hkllim.v.intArray[3]; + mink = hkllim.v.intArray[4]; + minl = hkllim.v.intArray[5]; + + SetListMin_hkl(sginfo,hkllim.v.intArray[1], hkllim.v.intArray[2], + &minh, &mink, &minl); + ClearReflectionList(priv->messList); + cell = SXGetCell(); + direct.a = cell[0]; + direct.b = cell[1]; + direct.c = cell[2]; + direct.alpha = cell[3]; + direct.beta = cell[4]; + direct.gamma = cell[5]; + B = mat_creat(3,3,UNIT_MATRIX); + if(!calculateBMatrix(direct,B)){ + SCWrite(pCon,"ERROR: invalid cell", eError); + return 0; + } + H = mat_creat(3,1,ZERO_MATRIX); + + + for(h = hkllim.v.intArray[0]; h < hkllim.v.intArray[3]; h++){ + for(k = hkllim.v.intArray[1]; k < hkllim.v.intArray[4]; k++){ + for(l = hkllim.v.intArray[2]; l < hkllim.v.intArray[5]; l++){ + /* first test: extinct */ + if(IsSysAbsent_hkl(sginfo,h,k,l,NULL) != 0 ){ + continue; + } + /* second test: a symmetrically equivalent already seen */ + if((suppress != 0) && IsSuppressed_hkl(sginfo,minh,mink,minl, + hkllim.v.intArray[1],hkllim.v.intArray[2],h,k,l ) != 0){ + continue; + } + /* third test: within stt limits */ + H[0][0] = (double)h; + H[1][0] = (double)k; + H[2][0] = (double)l; + Z1 = mat_mul(B,H); + calcTheta(lambda,Z1,&d,&om); + om *= 2.; + mat_free(Z1); + if(om > sttlim.v.floatArray[0] && om < sttlim.v.floatArray[1]){ + hkl[0] = (double)h; + hkl[1] = (double)k; + hkl[2] = (double)l; + AddRefIdx(priv->messList,hkl); + count++; + } + } + } + } + mat_free(B); + mat_free(H); + priv->masterCount = count; + SCPrintf(pCon,eValue,"%d reflections generated", count); + return 1; +} +/*-----------------------------------------------------------------------------*/ +static int GenInconsumerate(pSICSOBJ self, SConnection *pCon, pHdb commandNode, + pHdb par[], int nPar){ + double hkl[3], qvec[3]; + pFourMess priv = self->pPrivate; + int i, j; + + if(nPar < 3) { + SCWrite(pCon, + "ERROR: need q displacement vector with three compononts", + eError); + return 0; + } + qvec[0] = par[0]->value.v.doubleValue; + qvec[1] = par[1]->value.v.doubleValue; + qvec[2] = par[2]->value.v.doubleValue; + + for(i = 0; i < priv->masterCount; i++){ + GetRefIndex(priv->messList,i,hkl); + for(j = 0; j < 3; j++){ + hkl[j] += qvec[j]; + } + AddRefIdx(priv->messList, hkl); + } + SCPrintf(pCon,eValue,"%d additional inconsumerate reflections generated", + priv->masterCount); + return 1; +} +/*----------------------------------------------------------------------------*/ +static int hklCompare(const void *h1, const void *h2){ + const double *hkl1 = h1, *hkl2 = h2; + + if(hkl1[3] < hkl2[3]){ + return -1; + } else if (hkl1[3] == hkl2[3]) { + return 0; + } else { + return 1; + } +} +/*----------------------------------------------------------------------------*/ +static int SortRef(pSICSOBJ self, SConnection *pCon, pHdb commandNode, + pHdb par[], int nPar){ + double *sortlist, d, lambda, om, hkl[4], ang[4]; + const double *cell; + int nRefl, i, j; + MATRIX B, H, Z1; + lattice direct; + pFourMess priv = self->pPrivate; + + lambda = SXGetLambda(); + cell = SXGetCell(); + direct.a = cell[0]; + direct.b = cell[1]; + direct.c = cell[2]; + direct.alpha = cell[3]; + direct.beta = cell[4]; + direct.gamma = cell[5]; + B = mat_creat(3,3,UNIT_MATRIX); + if(!calculateBMatrix(direct,B)){ + SCWrite(pCon,"ERROR: invalid cell", eError); + return 0; + } + H = mat_creat(3,1,ZERO_MATRIX); + + nRefl = ReflectionListCount(priv->messList); + sortlist = malloc(nRefl*4*sizeof(double)); + if(sortlist == NULL){ + SCWrite(pCon,"ERROR: out of memory in SortRef",eError); + return 0; + } + /* + * I am using hkl[3] for storing the theta value to sort for! */ + for(i = 0; i < nRefl; i++){ + GetRefIndex(priv->messList,i,hkl); + for(j = 0; j < 3; j++){ + H[j][0] = hkl[j]; + } + Z1 = mat_mul(B,H); + calcTheta(lambda,Z1,&d, &om); + mat_free(Z1); + hkl[3] = om; + memcpy(sortlist + i*4, hkl, 4*sizeof(double)); + } + + qsort(sortlist,nRefl,4*sizeof(double),hklCompare); + + ClearReflectionList(priv->messList); + for(i = 0; i < nRefl; i++){ + ang[1] = sortlist[i*4+3]; + ang[0] = 2.*ang[1]; + ang[2] = .0; + ang[3] = .0; + /* AddRefIdxAng(priv->messList, sortlist+i*4,ang); */ + AddRefIdx(priv->messList, sortlist+i*4); + } + free(sortlist); + mat_free(B); + mat_free(H); + SCSendOK(pCon); + return 1; +} +/*----------------------------------------------------------------------------*/ +static int FourMessSave(void *data, char *name, FILE *fd){ + pSICSOBJ self = data; + pFourMess priv = self->pPrivate; + + SaveSICSOBJ(data,name,fd); + SaveFourCircleTable(priv->stepTable, name, fd); + return 1; +} +/*----------------------------------------------------------------------------*/ +void InstallFourMess(SConnection *pCon, SicsInterp *pSics){ + pFourMess priv = NULL; + pSICSOBJ pNew = NULL; + pHdb cmd = NULL; + int hkl[] = {-10,-10,10,10,10,10}; + double sttlim[] = {5.0, 180}; + + pNew = MakeSICSOBJ("fmess","FourMess"); + priv = calloc(1,sizeof(FourMess)); + if(pNew == NULL || priv == NULL){ + SCWrite(pCon,"ERROR: out of memory creating fourmess", eError); + } + pNew->pDes->SaveStatus = FourMessSave; + pNew->pPrivate = priv; + pNew->KillPrivate = KillFourMess; + + priv->stepTable = MakeFourCircleTable(); + priv->messList = CreateReflectionList(pCon,pSics,"messref"); + if(priv->stepTable < 0 || priv->messList == NULL){ + SCWrite(pCon,"ERROR: out of memory creating fourmess", eError); + } + + cmd = AddSICSHdbPar(pNew->objectNode,"weak", usUser, MakeHdbInt(0)); + SetHdbProperty(cmd,"__save","true"); + cmd = AddSICSHdbPar(pNew->objectNode,"weakthreshold", usUser, + MakeHdbInt(20)); + SetHdbProperty(cmd,"__save","true"); + cmd = AddSICSHdbPar(pNew->objectNode,"mode", usUser, MakeHdbText("Monitor")); + + cmd = AddSICSHdbPar(pNew->objectNode,"hkllim", usUser, MakeHdbIntArray(6,hkl)); + SetHdbProperty(cmd,"__save","true"); + cmd = AddSICSHdbPar(pNew->objectNode,"sttlim", usUser, MakeHdbFloatArray(2,sttlim)); + SetHdbProperty(cmd,"__save","true"); + + cmd = AddSICSHdbPar(pNew->objectNode,"start", usUser, MakeSICSFunc(FourMessStart)); + cmd = AddSICSHdbPar(cmd,"filename", usUser, MakeHdbText("Unknown")); + cmd = AddSICSHdbPar(pNew->objectNode,"close", usUser, MakeSICSFunc(FourMessClose)); + + cmd = AddSICSHdbPar(pNew->objectNode,"scanpar", usUser, MakeSICSFunc(FourMessScanPar)); + cmd = AddSICSHdbPar(cmd,"twotheta", usUser, MakeHdbFloat(.0)); + + cmd = AddSICSHdbPar(pNew->objectNode,"store", usUser, MakeSICSFunc(FourMessStore)); + AddSICSHdbPar(cmd,"h", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd,"k", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd,"l", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd,"stt", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd,"om", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd,"chi", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd,"phi", usUser, MakeHdbFloat(.0)); + cmd = AddSICSHdbPar(pNew->objectNode,"weak", usUser, MakeSICSFunc(FourMessWeak)); + + cmd = AddSICSHdbPar(pNew->objectNode,"indgen", usUser, MakeSICSFunc(GenIndex)); + AddSICSHdbPar(cmd,"sup", usUser, MakeHdbInt(1)); + + cmd = AddSICSHdbPar(pNew->objectNode,"genw", usUser, MakeSICSFunc(GenInconsumerate)); + AddSICSHdbPar(cmd,"hw", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd,"kw", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd,"lw", usUser, MakeHdbFloat(.0)); + + cmd = AddSICSHdbPar(pNew->objectNode,"indsort", usUser, MakeSICSFunc(SortRef)); + + + cmd = AddSICSHdbPar(pNew->objectNode,"template", usMugger, MakeHdbText("Unknown")); + cmd = AddSICSHdbPar(pNew->objectNode,"scanobj", usMugger, MakeHdbText("xxxscan")); + PrependHipadabaCallback(cmd, + MakeHipadabaCallback(SetScannerCB, priv,NULL)); + + priv->pScanner = FindCommandData(pSics,"xxxscan","ScanObject"); + + AddCommand(pSics, + "fmess", + FourMessAction, + KillSICSOBJ, + pNew); +} + diff --git a/fourmess.h b/fourmess.h new file mode 100644 index 00000000..c3f3f6c6 --- /dev/null +++ b/fourmess.h @@ -0,0 +1,25 @@ +/** + * This is a new version of the four circle reflection measurement module. Its task is + * to provide functionality required for measuring a list of reflections. This is done + * with the help of some scripts bind things together. This module provides: + * - a table of scan parameters for measuring reflections at different angles. + * - the functions required to produce the scan data files for single detector + * mode. + * - a list of reflections to measure. + * + * In contrast to the old mesure module, this module is more flexible and + * allows for reflection list processing in all modes and for all detectors. + * + * copyright: see file COPYRIGHT + * + * Mark Koennecke, July 2008 + */ + +#ifndef _FOURMESS +#define _FOURMESS +#include + +void InstallFourMess(SConnection *pCon, SicsInterp *pSics); + +#endif + diff --git a/fourtable.c b/fourtable.c index 38941613..8fb1089c 100644 --- a/fourtable.c +++ b/fourtable.c @@ -125,7 +125,7 @@ static int addToList(int handle, SConnection *pCon, int argc, char *argv[]){ } strncpy(entry.scanVar,argv[4],29); strtolower(entry.scanVar); - if(strcmp(entry.scanVar,"om") != 0 && strcmp(entry.scanVar,"o2t") != 0){ + if(strcmp(entry.scanVar,"om") != 0 && strstr(entry.scanVar,"o2t") == NULL){ SCWrite(pCon,"ERROR: Invalied scan variable specified, only om, o2t allowed",eError); return 0; } diff --git a/genericcontroller.c b/genericcontroller.c index 75586942..028aa379 100644 --- a/genericcontroller.c +++ b/genericcontroller.c @@ -236,7 +236,6 @@ static int MakeGenPar(pSICSOBJ self, SConnection *pCon, pGenController priv; pAsyncUnit assi; pAsyncTxn trans; - commandContext comCon; char replyCommand[2048]; } GenContext, *pGenContext; /*-------------------------------------------------------------------------- @@ -266,14 +265,11 @@ static int MakeGenPar(pSICSOBJ self, SConnection *pCon, break; } - if(genCon->pCon != NULL){ - SCPushContext2(genCon->pCon, genCon->comCon); - } genCon->priv->replyCallback(genCon->obj, genCon->pCon, genCon->node, genCon->replyCommand, reply, strlen(reply)); if(genCon->pCon != NULL){ - SCPopContext(genCon->pCon); - } + SCDeleteConnection(genCon->pCon); + } free(genCon); return 1; @@ -362,9 +358,8 @@ static pGenContext PrepareToEnque(pSICSOBJ self, SConnection *pCon, pHdb node){ result->node = node; result->priv = priv; result->obj = self; - result->pCon = pCon; + result->pCon = SCCopyConnection(pCon); priv->comError = GCOK; - result->comCon = SCGetContext(pCon); free(command); return result; diff --git a/histmem.c b/histmem.c index ebf09b14..3a111160 100644 --- a/histmem.c +++ b/histmem.c @@ -167,6 +167,10 @@ extern pHistDriver MakeHMSlaveHM(pStringDict pOpt); self = (pHistMem)pData; assert(self); + if(!GetCountLock(self->pCountInt, pCon)){ + return HWFault; + } + if(!self->iInit) { SCWrite(pCon,"ERROR: histogram memory not initialised",eError); @@ -195,6 +199,7 @@ extern pHistDriver MakeHMSlaveHM(pStringDict pOpt); SCWrite(pCon,"ERROR: failed to fix histogram memory problem", eError); SCSetInterrupt(pCon,eAbortBatch); + ReleaseCountLock(self->pCountInt); return HWFault; } } @@ -321,6 +326,7 @@ extern pHistDriver MakeHMSlaveHM(pStringDict pOpt); SCWrite(pCon,"ERROR: failed to fix histogram memory problem",eError); SCSetInterrupt(pCon,eAbortBatch); InvokeCallBack(self->pCall,COUNTEND,NULL); + ReleaseCountLock(self->pCountInt); return eCt; } else @@ -339,6 +345,7 @@ extern pHistDriver MakeHMSlaveHM(pStringDict pOpt); */ updateHMData(self->pDriv->data); InvokeCallBack(self->pCall,COUNTEND,NULL); + ReleaseCountLock(self->pCountInt); } return eCt; @@ -595,6 +602,11 @@ extern pHistDriver MakeHMSlaveHM(pStringDict pOpt); assert(self); assert(pCon); + if(isRunning(self->pCountInt)){ + SCWrite(pCon,"ERROR: cannot configure histogram memory while counting", eError); + return 0; + } + iRet = HistDriverConfig(self->pDriv,self->pDriv->pOption,pCon); if(!iRet) { @@ -766,16 +778,16 @@ void HistDirty(pHistMem self) iRet = Wait4Success(GetExecutor()); if(iRet == DEVINT) { - SCWrite(pCon,"Counting aborted due to Interrupt",eStatus); + SCWrite(pCon,"Counting aborted due to Interrupt",eError); } else if(iRet == DEVERROR) { - SCWrite(pCon,"Counting finished with Problems",eStatus); + SCWrite(pCon,"Counting finished with Problems",eValue); iRet = 1; } else { - SCWrite(pCon,"Counting finished",eStatus); + SCWrite(pCon,"Counting finished",eValue); iRet = 1; } @@ -791,7 +803,7 @@ void HistDirty(pHistMem self) char pBueffel[512], pError[80]; assert(self); - + if(!self->iInit) { SCWrite(pCon,"ERROR: histogram memory not initialised",eError); @@ -934,24 +946,29 @@ void HistDirty(pHistMem self) return 0; } /*----------------------------------------------------------------------*/ - static int HMCountInterest(int iEvent, void *pEvent, void *pUser, - commandContext cc) + static int HMCountInterest(int iEvent, void *pEvent, void *pUser) { SConnection *pCon = NULL; char pBueffel[512]; - if(iEvent == COUNTSTART) + pCon = (SConnection *)pUser; + + if(pCon == NULL || !SCisConnected(pCon)) + { + return -1; + } + + if(iEvent == COUNTSTART && pUser != NULL) { pCon = (SConnection *)pUser; assert(pCon); - SCWriteInContext(pCon,"HMCOUNTSTART",eWarning,cc); + SCWrite(pCon,"HMCOUNTSTART",eWarning); return 1; } else if(iEvent == COUNTEND) { - pCon = (SConnection *)pUser; assert(pCon); - SCWriteInContext(pCon,"HMCOUNTEND",eWarning,cc); + SCWrite(pCon,"HMCOUNTEND",eWarning); return 1; } return 0; @@ -982,11 +999,13 @@ static int checkHMEnd(pHistMem self, char *text){ int i,iRet,iLen,iRank,iDiscard,tofMode; float fVal; char *pMode[] = {"timer","monitor",NULL}; + pDynString buf = NULL; memset(pBuffer, 0, sizeof(pBuffer)); memset(pValue, 0, sizeof(pValue)); memset(name, 0, sizeof(name)); - + + SCStartBuffering(pCon); iRet = StringDictGet(self->pDriv->pOption,"name",name,19); if(0==iRet) { strcpy(name,"*"); @@ -994,7 +1013,7 @@ static int checkHMEnd(pHistMem self, char *text){ iRet = StringDictGet(self->pDriv->pOption,"driver",pValue,sizeof(pValue)-1); if(0pDriv->pOption,"update",&fVal); @@ -1003,13 +1022,13 @@ static int checkHMEnd(pHistMem self, char *text){ } else { sprintf(pBuffer,"%s.update = 0 (no buffering)",name); } - SCWrite(pCon,pBuffer,eStatus); + SCWrite(pCon,pBuffer,eValue); iRet = StringDictGetAsNumber(self->pDriv->pOption,"rank",&fVal); if(0pDriv->pOption,pValue,&fVal); if(0pDriv->pOption,pValue,sizeof(pValue)-1); } /* Display Count Mode */ sprintf(pBuffer,"%s.CountMode = %s",name,pMode[self->pDriv->eCount]); - SCWrite(pCon,pBuffer,eStatus); + SCWrite(pCon,pBuffer,eValue); /* Display Preset */ sprintf(pBuffer,"%s.preset = %f",name,self->pDriv->fCountPreset); - SCWrite(pCon,pBuffer,eStatus); + SCWrite(pCon,pBuffer,eValue); if(self->pDriv->data->nTimeChan > 2) { tofMode = 1; @@ -1051,7 +1070,11 @@ static int checkHMEnd(pHistMem self, char *text){ tofMode = 0; } sprintf(pBuffer,"%s.tofMode = %d",name,tofMode); - SCWrite(pCon,pBuffer,eStatus); + SCWrite(pCon,pBuffer,eValue); + buf = SCEndBuffering(pCon); + if(buf != NULL){ + SCWrite(pCon,GetCharArray(buf), eValue); + } } /*--------------------------------------------------------------------------*/ @@ -1098,14 +1121,12 @@ static int checkHMEnd(pHistMem self, char *text){ strtolower(argv[1]); if(strcmp(argv[1],"interest") == 0) { - lID = RegisterCallback(self->pCall, SCGetContext(pCon), + lID = RegisterCallback(self->pCall, COUNTSTART, HMCountInterest, - pCon, NULL); - SCRegister(pCon,pSics, self->pCall,lID); - lID = RegisterCallback(self->pCall, SCGetContext(pCon), + SCCopyConnection(pCon), SCDeleteConnection); + lID = RegisterCallback(self->pCall, COUNTEND, HMCountInterest, - pCon, NULL); - SCRegister(pCon,pSics, self->pCall,lID); + SCCopyConnection(pCon), SCDeleteConnection); SCSendOK(pCon); return 1; } @@ -1178,6 +1199,10 @@ static int checkHMEnd(pHistMem self, char *text){ } else /* set case */ { + if(isRunning(self->pCountInt)){ + SCWrite(pCon,"ERROR: cannot change preset while counting", eError); + return 0; + } fVal = atof(argv[2]); if(!SCMatchRights(pCon,self->iAccess)) { @@ -1221,6 +1246,10 @@ static int checkHMEnd(pHistMem self, char *text){ else /* set case */ { strtolower(argv[2]); + if(isRunning(self->pCountInt)){ + SCWrite(pCon,"ERROR: cannot change countmode while counting", eError); + return 0; + } if(!SCMatchRights(pCon,self->iAccess)) { return 0; @@ -1638,16 +1667,14 @@ static int checkHMEnd(pHistMem self, char *text){ /* generate time binning */ else if(strcmp(argv[1],"genbin") == 0) { + if(isRunning(self->pCountInt)){ + SCWrite(pCon,"ERROR: cannot change time binning while counting", eError); + return 0; + } if(!SCMatchRights(pCon,usMugger)) { return 0; } - if(GetStatus() == eCounting) - { - SCWrite(pCon,"ERROR: cannot modify timebinning while counting", - eError); - return 0; - } if(argc < 5) { SCWrite(pCon,"ERROR: not enough aguments to genbin",eError); @@ -1695,6 +1722,10 @@ static int checkHMEnd(pHistMem self, char *text){ /* set a time bin */ else if(strcmp(argv[1],"setbin") == 0) { + if(isRunning(self->pCountInt)){ + SCWrite(pCon,"ERROR: cannot change time binning while counting", eError); + return 0; + } if(!SCMatchRights(pCon,usMugger)) { return 0; @@ -1732,6 +1763,10 @@ static int checkHMEnd(pHistMem self, char *text){ /* clear time bin info */ else if(strcmp(argv[1],"clearbin") == 0) { + if(isRunning(self->pCountInt)){ + SCWrite(pCon,"ERROR: cannot change time binning while counting", eError); + return 0; + } clearTimeBinning(self->pDriv->data); SCSendOK(pCon); return 1; diff --git a/hkl.c b/hkl.c index 4351f20c..5f2e32b5 100644 --- a/hkl.c +++ b/hkl.c @@ -22,6 +22,10 @@ Added handling of the chi ==0 or chi == 180 degree case to tryTweakOmega Mark Koennecke, December 2003 + + Heavily reworked to fit into the new four circle setup + + Mark Koennecke, July 2008 -----------------------------------------------------------------------------*/ #include #include @@ -35,7 +39,10 @@ #include "hkl.h" #include "hkl.i" #include "splitter.h" - +#include "singlex.h" +#include "motorlist.h" +#include "cell.h" +#include "ubfour.h" /* the tolerance in chi we give before we allow to fix omega with phi */ @@ -51,33 +58,16 @@ { return 1; } - fprintf(fd,"#Crystallographic Settings\n"); - if(self->iManual == 1) - { - fprintf(fd,"%s lambda %f\n",name, self->fLambda); - } - fprintf(fd, - "%s setub %8.6f %8.6f %8.6f %8.6f %8.6f %8.6f %8.6f %8.6f %8.6f\n", - name, - self->fUB[0], self->fUB[1], self->fUB[2], self->fUB[3], self->fUB[4], - self->fUB[5], self->fUB[6], self->fUB[7], self->fUB[8]); - fprintf(fd,"%s hm %d\n",name, self->iHM); + fprintf(fd,"#HKL Settings\n"); fprintf(fd,"%s scantolerance %f\n", name,self->scanTolerance); - fprintf(fd,"%s nb %d\n", name, self->iNOR); return 1; } /*---------------------------------------------------------------------------*/ - pHKL CreateHKL(pMotor pTheta, pMotor pOmega, pMotor pChi, - pMotor pPhi, pMotor pNu) + pHKL CreateHKL() { pHKL pNew = NULL; - assert(pTheta); - assert(pOmega); - assert(pChi); - assert(pPhi); - /* allocate memory */ pNew = (pHKL)malloc(sizeof(HKL)); if(!pNew) @@ -88,25 +78,16 @@ /* create object descriptor */ pNew->pDes = CreateDescriptor("4-Circle-Calculus"); - if(!pNew->pDes) + pNew->pMotDriv = makeMotListInterface(); + if(!pNew->pDes || pNew->pMotDriv == NULL) { free(pNew); return NULL; } pNew->pDes->SaveStatus = HKLSave; - pNew->pTheta = pTheta; - pNew->pOmega = pOmega; - pNew->pChi = pChi; - pNew->pPhi = pPhi; - pNew->pNu = pNu; - pNew->fLambda = 1.38; - pNew->iManual = 1; pNew->iQuad = 1; pNew->iHM = 0; - pNew->fUB[0] = 1.; - pNew->fUB[4] = 1.; - pNew->fUB[8] = 1.; pNew->UBinv = NULL; pNew->scanTolerance = 2.5; @@ -127,63 +108,22 @@ { DeleteDescriptor(self->pDes); } - + if(self->pMotDriv) + { + free(self->pMotDriv); + } + free(self); } /*---------------------------------------------------------------------------*/ int HKLFactory(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]) { - pMotor pTheta = NULL, pOmega = NULL, pChi = NULL, - pPhi = NULL, pNu = NULL; pHKL self = NULL; int iRet; - - /* check no of arguments */ - if(argc < 5) - { - SCWrite(pCon,"ERROR: Insufficient number of arguments to HKLFactory", - eError); - return 0; - } - - /* check motors */ - pTheta = FindMotor(pSics,argv[1]); - if(!pTheta) - { - SCWrite(pCon,"ERROR: cannot find two theta motor",eError); - return 0; - } - pOmega = FindMotor(pSics,argv[2]); - if(!pOmega) - { - SCWrite(pCon,"ERROR: cannot find omega motor",eError); - return 0; - } - pPhi = FindMotor(pSics,argv[3]); - if(!pPhi) - { - SCWrite(pCon,"ERROR: cannot find phi motor",eError); - return 0; - } - pChi = FindMotor(pSics,argv[4]); - if(!pChi) - { - SCWrite(pCon,"ERROR: cannot find chi motor",eError); - return 0; - } - - if(argc >= 6) - { - pNu = FindMotor(pSics,argv[5]); - if(!pNu) - { - SCWrite(pCon,"WARNING: cannot find nu motor",eWarning); - } - } - + /* make a new structure */ - self = CreateHKL(pTheta, pOmega, pPhi, pChi, pNu); + self = CreateHKL(); if(!self) { SCWrite(pCon,"ERROR: cannot allocate HKL data structure",eError); @@ -204,130 +144,20 @@ } return 1; } -#include "selvar.i" -/*---------------------------------------------------------------------------*/ - - static int HKLCallback(int iEvent, void *pEvent, void *pUser, - commandContext cc) - { - pHKL self = NULL; - pSelVar pVar = NULL; - float fVal; - - if(iEvent == WLCHANGE) - { - self = (pHKL)pUser; - pVar = (pSelVar)pEvent; - assert(self); - assert(pVar); - - if(pVar->pCon != NULL) - { - fVal = GetSelValue(pVar, pVar->pCon); - if(fVal > -900.) - { - self->fLambda = fVal; - return 1; - } - } - } - return 1; - } -/*--------------------------------------------------------------------------*/ - int SetWavelengthVariable(SConnection *pCon, pHKL self, pSelVar pVar) - { - pICallBack pCall = NULL, pCall2 = NULL; - pDummy pDum = NULL; - float fVal; - commandContext comCon; - - assert(pCon); - assert(self); - assert(pVar); - - /* try to get callback interface of the new mono variable */ - pDum = (pDummy)pVar; - pCall2 = pDum->pDescriptor->GetInterface(pDum,CALLBACKINTERFACE); - if(!pCall2) - { - return 0; - } - - /* clear old stuff, if apropriate */ - if(self->pMono) - { - pDum = (pDummy)self->pMono; - pCall = pDum->pDescriptor->GetInterface(pDum,CALLBACKINTERFACE); - if(pCall) - { - RemoveCallback(pCall,self->lID); - self->lID = 0; - self->pMono = NULL; - self->iManual = 1; - } - } - - /* install new callback */ - comCon.transID = 0; - strncpy(comCon.deviceID,"internal",SCDEVIDLEN); - self->lID = RegisterCallback(pCall2, - comCon, - WLCHANGE, - HKLCallback, - self, - NULL); - self->pMono = pVar; - self->iManual = 0; - - /* update the current value */ - fVal = GetSelValue(pVar,pCon); - if(fVal > -900.) - { - self->fLambda = fVal; - } - else - { - return 0; - } - return 1; - } /*-------------------------------------------------------------------------*/ void SetHKLScanTolerance(pHKL self, float fVal) { assert(self); self->scanTolerance = fVal; } -/*-------------------------------------------------------------------------*/ - int SetWavelengthManual(pHKL self, float fVal) - { - pICallBack pCall = NULL; - pDummy pDum = NULL; - - assert(self); - - /* clear old stuff, if apropriate */ - if(self->pMono) - { - pDum = (pDummy)self->pMono; - pCall = pDum->pDescriptor->GetInterface(pDum,CALLBACKINTERFACE); - if(pCall) - { - RemoveCallback(pCall,self->lID); - self->lID = 0; - self->pMono = NULL; - self->iManual = 1; - } - } - - self->fLambda = fVal; - return 1; - } /*------------------------------------------------------------------------*/ int GetLambda(pHKL self, float *fVal) { assert(self); + double val; - *fVal = self->fLambda; + val = SXGetLambda(); + *fVal = (float)val; return 1; } /*-------------------------------------------------------------------------*/ @@ -343,45 +173,51 @@ void SetHKLScanTolerance(pHKL self, float fVal) } return 1; } +/*-------------------------------------------------------------------------*/ +static void invertMatrix(pHKL self, float fUB[9]){ + int i; + MATRIX m; + + if(self->UBinv != NULL) + { + mat_free(self->UBinv); + } + m = mat_creat(3,3,ZERO_MATRIX); + for(i = 0; i < 3; i++) + { + m[0][i] = fUB[i]; + m[1][i] = fUB[3+i]; + m[2][i] = fUB[6+i]; + } + self->UBinv = mat_inv(m); + mat_free(m); +} /*-------------------------------------------------------------------------*/ int SetUB(pHKL self, float fUB[9]) { int i; - MATRIX m; + double dUB[9]; assert(self); - for(i = 0; i < 9; i++) - { - self->fUB[i] = fUB[i]; + for(i = 0; i < 9; i++){ + dUB[i] = fUB[i]; } - /* invert UB matrix for use in backwards calculation */ - if(self->UBinv != NULL) - { - mat_free(self->UBinv); - } - m = mat_creat(3,3,ZERO_MATRIX); - for(i = 0; i < 3; i++) - { - m[0][i] = self->fUB[i]; - m[1][i] = self->fUB[3+i]; - m[2][i] = self->fUB[6+i]; - } - self->UBinv = mat_inv(m); - mat_free(m); - + SXSetUB(dUB); + invertMatrix(self,fUB); + return 1; } /*-------------------------------------------------------------------------*/ int GetUB(pHKL self, float fUB[9]) { int i; + const double *dUB; - assert(self); - + dUB = SXGetUB(); for(i = 0; i < 9; i++) { - fUB[i] = self->fUB[i]; + fUB[i] = (float)dUB[i]; } return 1; } @@ -392,299 +228,56 @@ void SetHKLScanTolerance(pHKL self, float fVal) assert(self); /* cannot set normal beam geometry if no nu motor */ - if( (iNOB == 1) && (self->pNu == NULL)) + if( (iNOB == 1) && (SXGetMotor(Nu) == NULL)) return 0; - self->iNOR = iNOB; + switch(iNOB){ + case 0: + SXSetMode(Bisecting); + break; + case 1: + SXSetMode(NB); + break; + default: + return 0; + } return 1; } -/*-----------------------------------------------------------------------*/ -static int checkTheta(pHKL self, double *stt){ - char pError[132]; - int iTest; - float fHard; - - iTest = MotorCheckBoundary(self->pTheta,(float)*stt, &fHard,pError,131); - if(!iTest) - { - /* - check if it is on the other detectors - */ - if(self->iHM){ - iTest = MotorCheckBoundary(self->pTheta,(float)*stt-45., - &fHard,pError,131); - if(iTest){ - *stt -= 45.; - } else { - iTest = MotorCheckBoundary(self->pTheta,(float)*stt-90., - &fHard,pError,131); - if(iTest) { - *stt -= 90.; - } - } - } - if(!iTest){ - return -1; - } - } - return 1; -} -/*-----------------------------------------------------------------------*/ -static int checkBisecting(pHKL self, - double *stt, double om, double chi, double phi) -{ - int iTest; - float fHard, fLimit; - char pError[132]; - - /* check two theta */ - iTest = checkTheta(self, stt); - if(!iTest){ - return -1; - } - - /* for omega check against the limits +- SCANBORDER in order to allow for - a omega scan - */ - MotorGetPar(self->pOmega,"softlowerlim",&fLimit); - if((float)om < fLimit + self->scanTolerance){ - iTest = 0; - } else { - iTest = 1; - MotorGetPar(self->pOmega,"softupperlim",&fLimit); - if((float)om > fLimit - self->scanTolerance){ - iTest = 0; - } else { - iTest = 1; - } - } - - /* check chi and phi*/ - iTest += MotorCheckBoundary(self->pChi,(float)chi, &fHard,pError,131); - iTest += MotorCheckBoundary(self->pPhi,(float)phi, &fHard,pError,131); - if(iTest == 3) /* none of them burns */ - { - return 1; - } - return 0; -} -/*-----------------------------------------------------------------------*/ -static int checkNormalBeam(double om, double *gamma, double nu, - float fSet[4], SConnection *pCon, pHKL self) -{ - int iTest; - char pError[132]; - float fHard; - - fSet[0] = (float)*gamma; - fSet[1] = (float)om; - fSet[2] = (float)nu; - - /* check omega, gamma and nu */ - iTest = MotorCheckBoundary(self->pOmega,(float)om, &fHard,pError,131); - iTest += checkTheta(self,gamma); - iTest += MotorCheckBoundary(self->pNu,(float)nu, &fHard,pError,131); - if(iTest == 3) /* none of them burns */ - { - return 1; - } - return 0; -} -/*--------------------------------------------------------------------*/ -static int chiVertical(double chi){ - if(ABS(chi - .0) < CHITOLERANCE){ - return 1; - } - if(ABS(chi - 180.0) < CHITOLERANCE){ - return 1; - } - return 0; -} -/*----------------------------------------------------------------------- - tryOmegaTweak tries to calculate a psi angle in order to put an - offending omega back into range. - - This routine also handles the special case when chi ~ 0 or chi ~ 180. - Then it is possible to fix a omega problem by turing in phi. - -----------------------------------------------------------------------*/ -static int tryOmegaTweak(pHKL self, MATRIX z1, double *stt, double *om, - double *chi, double *phi){ - int status; - float fLower, fUpper, omTarget, omOffset, phiSign; - double dumstt, offom, offchi, offphi; - - - status = checkBisecting(self,stt,*om,*chi,*phi); - if(status < 0){ - return 0; /* stt is burning */ - } else if(status == 1){ - return 1; - } - - /* - Is omega really the problem? - */ - omTarget = -9999; - MotorGetPar(self->pOmega,"softlowerlim",&fLower); - MotorGetPar(self->pOmega,"softupperlim",&fUpper); - if(*om < fLower + self->scanTolerance) { - omTarget = fLower + self->scanTolerance; - } - if(*om > fUpper - self->scanTolerance){ - omTarget = fUpper - self->scanTolerance; - } - if(omTarget < -7000){ - return 0; - } + /*-----------------------------------------------------------------------*/ + static int checkTheta(pHKL self, double *stt){ + char pError[132]; + int iTest; + float fHard; + pMotor pTheta; - /* - calculate omega offset - */ - omOffset = *om - omTarget; - omOffset = -omOffset; - - /* - check for the special case of chi == 0 or chi == 180 - */ - if(chiVertical(*chi)){ - dumstt = *stt; - offom = omTarget; - offchi = *chi; - MotorGetPar(self->pPhi,"sign",&phiSign); - offphi = *phi - omOffset*phiSign; - if(checkBisecting(self,&dumstt,offom,offchi,offphi)){ - *om = offom; - *chi = offchi; - *phi = offphi; - return 1; + pTheta = SXGetMotor(TwoTheta); + if(pTheta == NULL){ + return 0; } - } - - /* - calculate angles with omega offset - */ - status = z1ToAnglesWithOffset(self->fLambda,z1, omOffset, &dumstt, - &offom, &offchi, &offphi); - if(!status){ - return 0; - } - - if(checkBisecting(self,&dumstt,offom,offchi,offphi)){ - *om = offom; - *chi = offchi; - *phi = offphi; - return 1; - } - return 0; -} -/*-----------------------------------------------------------------------*/ -static MATRIX calculateScatteringVector(pHKL self, float fHKL[3]) -{ - MATRIX z1, hkl, ubm; - int i; - - hkl = mat_creat(3,1,ZERO_MATRIX); - ubm = mat_creat(3,3,ZERO_MATRIX); - for(i = 0; i < 3; i++) - { - hkl[i][0] = fHKL[i]; - ubm[0][i] = self->fUB[i]; - ubm[1][i] = self->fUB[i+3]; - ubm[2][i] = self->fUB[i+6]; - } - z1 = mat_mul(ubm,hkl); - mat_free(ubm); - mat_free(hkl); - - return z1; -} -/*---------------------------------------------------------------------*/ -static int calculateBisectingOld(MATRIX z1, pHKL self, SConnection *pCon, - float fSet[4], double myPsi, int iRetry) -{ - double stt, om, chi, phi, psi, ompsi, chipsi, phipsi; - int i, test; - - /* - just the plain angle calculation - */ - if(!z1mToBisecting(self->fLambda,z1,&stt,&om,&chi,&phi)) - { - return 0; - } - - /* - check if angles in limits. If omega problem: try to tweak - */ - chi = circlify(chi); - phi = circlify(phi); - if(iRetry > 1) - { - if(tryOmegaTweak(self,z1,&stt,&om,&chi,&phi)){ - fSet[0] = (float)stt; - fSet[1] = (float)om; - fSet[2] = (float)circlify(chi); - fSet[3]= (float)circlify(phi); - return 1; + + iTest = MotorCheckBoundary(pTheta,(float)*stt, &fHard,pError,131); + if(!iTest){ + return -1; } - } - /* - if this does not work, try rotating through psi in order to - find a useful setting - */ - for(i = 0; i < iRetry; i++) - { - if(iRetry > 1) - { - psi = i*.5; - } - else - { - psi = myPsi; - } - rotatePsi(om,chi,phi,psi,&ompsi,&chipsi,&phipsi); - chipsi = circlify(chipsi); - phipsi = circlify(phipsi); - test = checkBisecting(self,&stt,ompsi,chipsi,phipsi); - if(test == 1) - { - fSet[0] = (float)stt; - fSet[1] = (float)ompsi; - fSet[2] = (float)chipsi; - fSet[3]= (float)phipsi; - return 1; - } + return iTest; } - - /* - giving up! But calculate one more time in order to show Jurg where - he should be. - */ - z1mToBisecting(self->fLambda,z1,&stt,&om,&chi,&phi); - if(iRetry == 1){ - rotatePsi(om,chi,phi,psi,&ompsi,&chipsi,&phipsi); - fSet[0] = (float)stt; - fSet[1] = (float)ompsi; - fSet[2] = (float)chipsi; - fSet[3]= (float)phipsi; - } else { - fSet[0] = (float)stt; - fSet[1] = (float)om; - fSet[2] = (float)chi; - fSet[3]= (float)phi; - } - - return 0; -} /*----------------------------------------------------------------------*/ -int hklInRange(void *data, float fSet[4], int mask[4]) +int hklInRange(void *data, double fSet[4], int mask[4]) { pHKL self = (pHKL)data; float fHard, fLimit; char pError[132]; int i, test; double dTheta; - + pMotor pOmega, pChi, pPhi; + + pOmega = SXGetMotor(Omega); + pChi = SXGetMotor(Chi); + pPhi = SXGetMotor(Phi); + if(pOmega == NULL || pChi == NULL || pPhi == NULL){ + return 0; + } + /* check two theta */ dTheta = fSet[0]; mask[0] = checkTheta(self, &dTheta); @@ -693,12 +286,12 @@ int hklInRange(void *data, float fSet[4], int mask[4]) /* for omega check against the limits +- SCANBORDER in order to allow for a omega scan. */ - MotorGetPar(self->pOmega,"softlowerlim",&fLimit); + MotorGetPar(pOmega,"softlowerlim",&fLimit); if((float)fSet[1] < fLimit + self->scanTolerance){ - mask[1] = 0; - } else { mask[1] = 1; - MotorGetPar(self->pOmega,"softupperlim",&fLimit); + } else { + mask[1] = 0; + MotorGetPar(pOmega,"softupperlim",&fLimit); if((float)fSet[1] > fLimit - self->scanTolerance){ mask[1] = 0; } else { @@ -707,8 +300,8 @@ int hklInRange(void *data, float fSet[4], int mask[4]) } /* check chi and phi*/ - mask[2] = MotorCheckBoundary(self->pChi,fSet[2], &fHard,pError,131); - mask[3] = MotorCheckBoundary(self->pPhi,fSet[3], &fHard,pError,131); + mask[2] = MotorCheckBoundary(pChi,fSet[2], &fHard,pError,131); + mask[3] = MotorCheckBoundary(pPhi,fSet[3], &fHard,pError,131); for(i = 0, test = 0; i < 4; i++){ test += mask[i]; } @@ -718,164 +311,6 @@ int hklInRange(void *data, float fSet[4], int mask[4]) return 1; } } -/*---------------------------------------------------------------------*/ -static int calculateBisecting(MATRIX z1, pHKL self, SConnection *pCon, - float fSet[4], double myPsi, int iRetry) -{ - double stt, om, chi, phi, psi, ompsi, chipsi, phipsi; - int i, test, mask[4]; - - /* - just the plain angle calculation - */ - if(!z1mToBisecting(self->fLambda,z1,&stt,&om,&chi,&phi)) - { - return 0; - } - - fSet[0] = stt; - fSet[1] = om; - fSet[2] = chi; - fSet[3] = phi; - if(iRetry == 1) { - rotatePsi(om,chi,phi,myPsi,&ompsi,&chipsi,&phipsi); - fSet[1] = ompsi; - fSet[2] = circlify(chipsi); - fSet[3] = circlify(phipsi); - return 1; - } else { - if(hklInRange(self,fSet, mask) == 1){ - return 1; - } else { - if(tryOmegaTweak(self,z1, &stt, &om, &chi, &phi) == 1){ - fSet[0] = stt; - fSet[1] = om; - fSet[2] = chi; - fSet[3] = phi; - return 1; - } else { - return findAllowedBisecting(self->fLambda, z1, fSet, hklInRange,self); - } - } - } -} -/*-----------------------------------------------------------------------*/ -static int calculateNormalBeam(MATRIX z1, pHKL self, SConnection *pCon, - float fSet[4], double myPsi, int iRetry) -{ - int i, iTest, status; - double stt, om, chi, phi, gamma, nu, psi, omnb; - float currentPhi, currentChi; - double ompsi, chipsi, phipsi; - MATRIX chim, phim, z4, z3; - - /* - The usual condition for normal beam calculations is that both chi - and phi are 0. This is not the case at TRICS. Therefore we have to - multiply the scattering vector first with the chi and phi rotations - before we start. - */ - iTest = MotorGetSoftPosition(self->pChi,pCon,¤tChi); - if(iTest != 1) - { - return 0; - } - iTest = MotorGetSoftPosition(self->pPhi,pCon,¤tPhi); - if(iTest != 1) - { - return 0; - } - phim = mat_creat(3,3,ZERO_MATRIX); - phimat(phim,(double)currentPhi); - z4 = mat_mul(phim,z1); - chim = mat_creat(3,3,ZERO_MATRIX); - chimat(chim,(double)currentChi); - z3 = mat_mul(chim,z4); - mat_free(phim); - mat_free(chim); - mat_free(z4); - - - status = z1mToNormalBeam(self->fLambda, z3, &gamma, &omnb, &nu); - /* omnb += 180.; */ - mat_free(z3); - if(status != 1) - { - return 0; - } - if(checkNormalBeam(omnb, &gamma, nu,fSet,pCon,self)){ - return 1; - } else { - if(checkNormalBeam(omnb + 360., &gamma, nu, fSet,pCon,self)){ - return 1; - } else { - return 0; - } - } -} -/*---------------------------------------------------------------------*/ -static int calculateNormalBeamOmega(MATRIX z1, pHKL self, - SConnection *pCon, - float fSet[4], double omOffset) -{ - int iTest; - double stt, om, chi, phi, gamma, nu, psi; - float currentPhi, currentChi; - double ompsi, chipsi, phipsi; - MATRIX chim, phim, z4, z3; - - /* - The usual condition for normal beam calculations is that both chi - and phi are 0. This is not the case at TRICS. Therefore we have to - multiply the scattering vector first with the chi and phi rotations - before we start. - */ - iTest = MotorGetSoftPosition(self->pChi,pCon,¤tChi); - if(iTest != 1) - { - return 0; - } - iTest = MotorGetSoftPosition(self->pPhi,pCon,¤tPhi); - if(iTest != 1) - { - return 0; - } - phim = mat_creat(3,3,ZERO_MATRIX); - phimat(phim,(double)currentPhi); - z4 = mat_mul(phim,z1); - chim = mat_creat(3,3,ZERO_MATRIX); - chimat(chim,(double)currentChi); - z3 = mat_mul(chim,z4); - mat_free(phim); - mat_free(chim); - mat_free(z4); - - - /* - do the bisecting angles first - */ - if(!z1ToAnglesWithOffset(self->fLambda,z3, omOffset, &stt, - &ompsi, &chi, &phi)) - { - return 0; - } - - if(ABS(chi -90.) < .001 && ABS(phi-180.) < .001) - { - chi = .0; - phi = .0; - } - - if(bisToNormalBeam(stt,ompsi,chi,phi, - &om, &gamma, &nu)) - { - if(checkNormalBeam(om, &gamma, nu,fSet,pCon,self)) - { - return 1; - } - } - return 0; -} /*------------------------------------------------------------------------- calculates the four circle settings. If the position can not be reached because of a limit violation, then psi is rotated in 10 degree steps @@ -887,13 +322,11 @@ static int calculateNormalBeamOmega(MATRIX z1, pHKL self, int CalculateSettings(pHKL self, float fHKL[3], float fPsi, int iHamil, float fSet[4], SConnection *pCon) { - char pError[132]; char pBueffel[512]; - float fHard, fVal, fUpper, fLower; double myPsi = fPsi; - MATRIX z1; - double stt, om, chi, phi, ompsi, chipsi, phipsi; - int i,iRetry, status; + int i,status; + pSingleDiff single = NULL; + double dHkl[4], dSet[4]; /* catch shitty input */ if( (fHKL[0] == 0.) && (fHKL[1] == 0.) && (fHKL[2] == 0.)) @@ -906,143 +339,54 @@ static int calculateNormalBeamOmega(MATRIX z1, pHKL self, /* some people are stupid.......... */ myPsi = circlify(fPsi); - /* - no retries if specific psi requested. - */ - if((myPsi > 0.1) ) - { - iRetry = 1; + single = SXGetDiffractometer(); + assert(single != NULL); + + for(i = 0; i < 3; i++){ + dHkl[i] = fHKL[i]; } - else - { - iRetry = 699; + dHkl[3] = myPsi; + + status = single->calculateSettings(single,dHkl, dSet); + for(i = 0; i < 4; i++){ + fSet[i] = dSet[i]; } - - - z1 = calculateScatteringVector(self,fHKL); - - if(self->iNOR == 0) - { - status = calculateBisecting(z1,self,pCon,fSet, myPsi, iRetry); - } - else if(self->iNOR == 1) - { - status = calculateNormalBeam(z1,self,pCon,fSet, myPsi, iRetry); - } - else - { - myPsi = fPsi; - status = calculateNormalBeamOmega(z1,self,pCon,fSet, myPsi); - } - - - if(!status) - { - if(iRetry == 1) - { - sprintf(pBueffel, + + if(!status){ + sprintf(pBueffel, "ERROR: cannot calculate %4.1f %4.1f %4.1f, psi = %4.1f", - fHKL[0], fHKL[1], fHKL[2], fPsi); - SCWrite(pCon,pBueffel,eError); - } - else - { - sprintf(pBueffel,"ERROR: cannot calculate %4.1f %4.1f %4.1f", - fHKL[0], fHKL[1], fHKL[2]); - SCWrite(pCon,pBueffel,eError); - } + fHKL[0], fHKL[1], fHKL[2], dHkl[3]); + SCWrite(pCon,pBueffel,eError); } - mat_free(z1); - return status; - - return 0; } /*------------------------------------------------------------------------*/ -static void stopHKLMotors(pHKL self) +void stopHKLMotors(pHKL self) { - if(self->pTheta != NULL) - { - self->pTheta->pDrivInt->Halt(self->pTheta); - } - if(self->pOmega != NULL) - { - self->pOmega->pDrivInt->Halt(self->pOmega); - } - if(self->pChi != NULL) - { - self->pChi->pDrivInt->Halt(self->pChi); - } - if(self->pPhi != NULL) - { - self->pPhi->pDrivInt->Halt(self->pPhi); - } - if(self->pNu != NULL) - { - self->pNu->pDrivInt->Halt(self->pNu); - } + pSingleDiff single = NULL; + + single = SXGetDiffractometer(); + assert(single != NULL); + self->pMotDriv->Halt(&single->motList); } /*------------------------------------------------------------------------*/ -int startHKLMotors(pHKL self, SConnection *pCon, float fSet[4]) -{ +int startHKLMotors(pHKL self, SConnection *pCon, float fSet[4]){ char pBueffel[512]; - pDummy pDum; - int iRet; - - /* start all the motors */ - pDum = (pDummy)self->pTheta; - iRet = StartDevice(pServ->pExecutor, "HKL", - pDum->pDescriptor, pDum, pCon,fSet[0]); - if(!iRet) - { - SCWrite(pCon,"ERROR: cannot start two theta motor",eError); - stopHKLMotors(self); - return 0; - } + pSingleDiff single = NULL; + double dSet[4]; + int i, status; - pDum = (pDummy)self->pOmega; - iRet = StartDevice(pServ->pExecutor, "HKL", - pDum->pDescriptor, pDum, pCon,fSet[1]); - if(!iRet) - { - SCWrite(pCon,"ERROR: cannot start omega motor",eError); - stopHKLMotors(self); - return 0; - } - - /* special case: normal beam */ - if(self->iNOR) - { - pDum = (pDummy)self->pNu; - iRet = StartDevice(pServ->pExecutor, "HKL", - pDum->pDescriptor, pDum, pCon,fSet[2]); - if(!iRet) - { - SCWrite(pCon,"ERROR: cannot start nu motor",eError); - return 0; - } - return 1; + single = SXGetDiffractometer(); + assert(single != NULL); + + for(i = 0; i < 4; i++){ + dSet[i] = fSet[i]; } - - pDum = (pDummy)self->pChi; - iRet = StartDevice(pServ->pExecutor, "HKL", - pDum->pDescriptor, pDum, pCon,fSet[2]); - if(!iRet) - { - SCWrite(pCon,"ERROR: cannot start chi motor",eError); - stopHKLMotors(self); - return 0; - } - pDum = (pDummy)self->pPhi; - iRet = StartDevice(pServ->pExecutor, "HKL", - pDum->pDescriptor, pDum, pCon,fSet[3]); - if(!iRet) - { - SCWrite(pCon,"ERROR: cannot start phi",eError); - stopHKLMotors(self); - return 0; - } - return 1; + single->settingsToList(single,dSet); + + status = self->pMotDriv->SetValue(&single->motList,pCon,.1); + + return status; } /*-------------------------------------------------------------------------*/ int RunHKL(pHKL self, float fHKL[3], @@ -1076,72 +420,14 @@ int startHKLMotors(pHKL self, SConnection *pCon, float fSet[4]) /*-------------------------------------------------------------------------*/ int DriveSettings(pHKL self, float fSet[4], SConnection *pCon) { - int iRet,i, iReturn; - char pBueffel[512]; - pDummy pDum; + int iRet; + + iRet = startHKLMotors(self, pCon, fSet); + if(iRet != 1){ + stopHKLMotors(self); + } - iReturn = 1; - - /* start all the motors */ - pDum = (pDummy)self->pTheta; - iRet = StartDevice(pServ->pExecutor, "HKL", - pDum->pDescriptor, pDum, pCon,fSet[0]); - if(!iRet) - { - SCWrite(pCon,"ERROR: cannot start two theta motor",eError); - StopExe(pServ->pExecutor,"all"); - iReturn = 0; - goto ente; - } - - pDum = (pDummy)self->pOmega; - iRet = StartDevice(pServ->pExecutor, "HKL", - pDum->pDescriptor, pDum, pCon,fSet[1]); - if(!iRet) - { - SCWrite(pCon,"ERROR: cannot start omega motor",eError); - StopExe(pServ->pExecutor,"all"); - iReturn = 0; - goto ente; - } - - /* special case: normal beam */ - if(self->iNOR) - { - pDum = (pDummy)self->pNu; - iRet = StartDevice(pServ->pExecutor, "HKL", - pDum->pDescriptor, pDum, pCon,fSet[2]); - if(!iRet) - { - SCWrite(pCon,"ERROR: cannot start nu motor",eError); - StopExe(pServ->pExecutor,"all"); - iReturn = 0; - } - goto ente; - } - - pDum = (pDummy)self->pChi; - iRet = StartDevice(pServ->pExecutor, "HKL", - pDum->pDescriptor, pDum, pCon,fSet[2]); - if(!iRet) - { - SCWrite(pCon,"ERROR: cannot start chi motor",eError); - StopExe(pServ->pExecutor,"all"); - iReturn = 0; - goto ente; - } - pDum = (pDummy)self->pPhi; - iRet = StartDevice(pServ->pExecutor, "HKL", - pDum->pDescriptor, pDum, pCon,fSet[3]); - if(!iRet) - { - StopExe(pServ->pExecutor,"all"); - iReturn = 0; - SCWrite(pCon,"ERROR: cannot start phi",eError); - } - -ente: - /* wait for end */ + /* wait for end */ iRet = Wait4Success(pServ->pExecutor); switch(iRet) { @@ -1149,23 +435,23 @@ ente: if(SCGetInterrupt(pCon) == eAbortOperation) { SCSetInterrupt(pCon,eContinue); - SCWrite(pCon,"Driving to HKL Aborted",eStatus); + SCWrite(pCon,"Driving to HKL Aborted",eLogError); } return 0; break; case DEVDONE: - SCWrite(pCon,"Driving to Reflection done",eStatus); + SCWrite(pCon,"Driving to Reflection done",eValue); break; default: SCWrite(pCon,"WARNING: driving to HKL finished with problems", eWarning); if(SCGetInterrupt(pCon) != eContinue) - { + { return 0; } break; } - return iReturn; + return iRet; } /*--------------------------------------------------------------------------*/ int DriveHKL(pHKL self, float fHKL[3], @@ -1180,8 +466,7 @@ ente: /* start running */ iReturn = 1; iRet = RunHKL(self,fHKL,fPsi,iHamil,pCon); - if(!iRet) - { + if(!iRet){ StopExe(pServ->pExecutor,"all"); iReturn = 0; } @@ -1194,7 +479,7 @@ ente: if(SCGetInterrupt(pCon) == eAbortOperation) { SCSetInterrupt(pCon,eContinue); - SCWrite(pCon,"Driving to HKL Aborted",eStatus); + SCWrite(pCon,"Driving to HKL Aborted",eError); } return 0; break; @@ -1210,7 +495,7 @@ ente: snprintf(pBueffel,131,"Driving to %8.4f %8.4f %8.4f done", fHKL[0], fHKL[1], fHKL[2]); } - SCWrite(pCon,pBueffel,eStatus); + SCWrite(pCon,pBueffel,eValue); break; default: SCWrite(pCon,"WARNING: driving to HKL finished with problems", @@ -1223,17 +508,30 @@ ente: } return iReturn; } -/*-----------------------------------------------------------------------*/ +/*----------------------------------------------------------------------- + * This is only used in mesure, remove when mesure can be killed + * ----------------------------------------------------------------------*/ int GetCurrentPosition(pHKL self, SConnection *pCon, float fPos[4]) { float fVal; int iRet, iResult; + pMotor pTheta, pOmega, pChi, pPhi, pNu; + + pTheta = SXGetMotor(TwoTheta); + pOmega = SXGetMotor(Omega); + pChi = SXGetMotor(Chi); + pPhi = SXGetMotor(Phi); + if(pTheta == NULL || pOmega == NULL || pChi == NULL || pPhi == NULL){ + SCWrite(pCon,"ERROR: configuration problem, stt,om,chi,phi motors not found,", + eError); + return 0; + } assert(self); assert(pCon); iResult = 1; - iRet = MotorGetSoftPosition(self->pTheta,pCon, &fVal); + iRet = MotorGetSoftPosition(pTheta,pCon, &fVal); if(iRet == 1) { fPos[0] = fVal; @@ -1242,7 +540,7 @@ ente: { iResult = 0; } - iRet = MotorGetSoftPosition(self->pOmega,pCon, &fVal); + iRet = MotorGetSoftPosition(pOmega,pCon, &fVal); if(iRet == 1) { fPos[1] = fVal; @@ -1253,9 +551,15 @@ ente: } /* normal beam geometry */ - if(self->iNOR == 1) + if(SXGetMode() == NB) { - iRet = MotorGetSoftPosition(self->pNu,pCon, &fVal); + pNu = SXGetMotor(Nu); + if(pNu){ + SCWrite(pCon,"ERROR: configuration problem, nu motor not found,", + eError); + return 0; + } + iRet = MotorGetSoftPosition(pNu,pCon, &fVal); if(iRet == 1) { fPos[2] = fVal; @@ -1268,7 +572,7 @@ ente: } /* bissecting geometry */ - iRet = MotorGetSoftPosition(self->pChi,pCon, &fVal); + iRet = MotorGetSoftPosition(pChi,pCon, &fVal); if(iRet == 1) { fPos[2] = fVal; @@ -1277,7 +581,7 @@ ente: { iResult = 0; } - iRet = MotorGetSoftPosition(self->pPhi,pCon, &fVal); + iRet = MotorGetSoftPosition(pPhi,pCon, &fVal); if(iRet == 1) { fPos[3] = fVal; @@ -1292,42 +596,19 @@ ente: /*------------------------------------------------------------------------- For the conversion from angles to HKL. -------------------------------------------------------------------------*/ - static int angle2HKL(pHKL self ,double tth, double om, - double chi, double phi, float fHKL[3]) - { - MATRIX rez, z1m; - double z1[3]; - int i; - - if(self->UBinv == NULL){ - return 0; - } - z1FromAngles(self->fLambda,tth,om,chi,phi,z1); - z1m = vectorToMatrix(z1); - /* multiply with UBinv in order to yield HKL */ - rez = mat_mul(self->UBinv,z1m); - for(i = 0; i < 3; i++) - { - fHKL[i] = (float)rez[i][0]; - } - mat_free(z1m); - mat_free(rez); - - return 1; - } -/*---------------------------------------------------------------------------*/ - int GetHKLFromAngles(pHKL self, SConnection *pCon, float fHKL[3]) - { - int status; - float fAng[4]; - - status = GetCurrentPosition(self,pCon,fAng); - if(status == 1) - { - angle2HKL(self,fAng[0], fAng[1], fAng[2], fAng[3],fHKL); - return 1; - } - return 0; + int GetHKLFromAngles(pHKL self, SConnection *pCon, float fHKL[3]){ + pSingleDiff single = NULL; + double dHkl[3]; + int i, status; + + single = SXGetDiffractometer(); + assert(single != NULL); + + status = single->hklFromAngles(single,dHkl); + for(i = 0; i < 3; i++){ + fHKL[i] = dHkl[i]; + } + return status; } /*--------------------------------------------------------------------------*/ static int GetCommandData(int argc, char *argv[], float fHKL[3], @@ -1383,6 +664,43 @@ ente: } return 1; } +/*--------------------------------------------------------------------------*/ +static int HKLCalculateTheta(pHKL self,float fHKL[3], double *stt){ + int status, i; + MATRIX B, HC, H; + double theta, d; + const double *cell; + reflection r; + lattice direct; + + B = mat_creat(3,3,UNIT_MATRIX); + H = mat_creat(3,1,ZERO_MATRIX); + if(B == NULL) { + return UBNOMEMORY; + } + cell = SXGetCell(); + direct.a = cell[0]; + direct.b = cell[1]; + direct.c = cell[2]; + direct.alpha = cell[3]; + direct.beta = cell[4]; + direct.gamma = cell[5]; + + status = calculateBMatrix(direct,B); + if(status < 0) { + return status; + } + for(i = 0; i < 3; i++){ + H[i][0] = fHKL[i]; + } + HC = mat_mul(B,H); + status = calcTheta(SXGetLambda(), HC, &d, &theta); + mat_free(HC); + mat_free(B); + mat_free(H); + *stt = 2.*theta; + return status; +} /*--------------------------------------------------------------------------*/ int HKLAction(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]) @@ -1391,10 +709,13 @@ ente: char pBueffel[512]; float fUB[9], fPsi, fVal; float fHKL[3], fSet[4]; - double dVal; + double dHKL[3], dSet[4]; + double dVal, lambda, stt; + const double *dUB; pHKL self = NULL; CommandList *pCom = NULL; pDummy pDum = NULL; + pSingleDiff single = NULL; assert(pCon); assert(pSics); @@ -1402,6 +723,8 @@ ente: self = (pHKL)pData; assert(self); + single = SXGetDiffractometer(); + /* enough arguments ? */ if(argc < 2) { @@ -1415,17 +738,18 @@ ente: { sprintf(pBueffel, "lambda = %f Normal Beam = %d Quadrant = %d HM = %d", - self->fLambda, self->iNOR, + SXGetLambda(), self->iNOR, self->iQuad,self->iHM); SCWrite(pCon,pBueffel,eValue); + dUB = SXGetUB(); sprintf(pBueffel,"UB = { %f %f %f", - self->fUB[0], self->fUB[1],self->fUB[2]); + dUB[0], dUB[1], dUB[2]); SCWrite(pCon,pBueffel,eValue); sprintf(pBueffel," %f %f %f", - self->fUB[3], self->fUB[4],self->fUB[5]); + dUB[3], dUB[4],dUB[5]); SCWrite(pCon,pBueffel,eValue); sprintf(pBueffel," %f %f %f }", - self->fUB[6], self->fUB[7],self->fUB[8]); + dUB[6], dUB[7],dUB[8]); SCWrite(pCon,pBueffel,eValue); return 1; sprintf(pBueffel,"Last HKL: %f %f %f ", @@ -1439,28 +763,11 @@ ente: /*----------- current */ else if(strcmp(argv[1],"current") == 0) { - if(self->iNOR) - { - sprintf(pBueffel,"Last HKL: %8.4f %8.4f %8.4f ", - self->fLastHKL[0], self->fLastHKL[1],self->fLastHKL[2]); - SCWrite(pCon,pBueffel,eValue); - return 1; - } - else - { - /* do a serious calculation based on angles */ - iRet = GetCurrentPosition(self,pCon,fSet); - if(iRet == 0) - { - return 0; - } - angle2HKL(self,(double)fSet[0],(double)fSet[1], - (double)fSet[2],(double)fSet[3],fHKL); - sprintf(pBueffel,"Current HKL: %8.4f %8.4f %8.4f ", + GetHKLFromAngles(self,pCon,fHKL); + sprintf(pBueffel,"Current HKL: %8.4f %8.4f %8.4f ", fHKL[0], fHKL[1],fHKL[2]); - SCWrite(pCon,pBueffel,eValue); - return 1; - } + SCWrite(pCon,pBueffel,eValue); + return 1; } else if(strcmp(argv[1],"fromangles") == 0) { @@ -1472,19 +779,20 @@ ente: return 0; } for(i = 0; i < 4; i++) - { - iRet = Tcl_GetDouble(InterpGetTcl(pSics),argv[i+2],&dVal); - if(iRet != TCL_OK) - { - snprintf(pBueffel,511,"ERROR: failed to convert %s to number", - argv[i+2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - fSet[i] = (float)dVal; + { + iRet = Tcl_GetDouble(InterpGetTcl(pSics),argv[i+2],&dVal); + if(iRet != TCL_OK){ + snprintf(pBueffel,511,"ERROR: failed to convert %s to number", + argv[i+2]); + SCWrite(pCon,pBueffel,eError); + return 0; + } + dSet[i] = dVal; + } + single->hklFromAnglesGiven(single,dSet,dHKL); + for(i = 0; i < 3; i++){ + fHKL[i] = dHKL[i]; } - angle2HKL(self,(double)fSet[0],(double)fSet[1], - (double)fSet[2],(double)fSet[3],fHKL); sprintf(pBueffel,"HKL from angles: %8.4f %8.4f %8.4f ", fHKL[0], fHKL[1],fHKL[2]); SCWrite(pCon,pBueffel,eValue); @@ -1493,83 +801,21 @@ ente: /*------------- lambda */ else if(strcmp(argv[1],"lambda") == 0) { - if(argc < 3) - { - snprintf(pBueffel,132,"%s.lambda = %f", argv[0],self->fLambda); - SCWrite(pCon,pBueffel,eValue); - return 1; - } - if(!SCMatchRights(pCon,usUser)) - { - return 0; - } - if(!isNumeric(argv[2])) - { - sprintf(pBueffel,"ERROR: %s was not recognized as a number", argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - fVal = atof(argv[2]); - iRet = SetWavelengthManual(self,fVal); - if(!iRet) - { - SCWrite(pCon,"ERROR: cannot set wavelength",eError); - return 0; - } - SCSendOK(pCon); - return 1; + lambda = SXGetLambda(); + snprintf(pBueffel,132,"%s.lambda = %f", argv[0],lambda); + SCWrite(pCon,pBueffel,eValue); } /*------------- getub*/ else if(strcmp(argv[1],"getub") == 0) { + dUB = SXGetUB(); snprintf(pBueffel,510,"%s.ub = %f %f %f %f %f %f %f %f %f", - argv[0], self->fUB[0], self->fUB[1], self->fUB[2], - self->fUB[3], self->fUB[4], self->fUB[5], - self->fUB[6], self->fUB[7], self->fUB[8]); + argv[0], dUB[0], dUB[1], dUB[2], + dUB[3], dUB[4], dUB[5], + dUB[6], dUB[7], dUB[8]); SCWrite(pCon,pBueffel,eValue); return 1; } -/*------- lambdavar*/ - else if(strcmp(argv[1],"lambdavar") == 0) - { - if(argc < 3) - { - SCWrite(pCon,"ERROR: Insufficient number of arguments to HKL lambdavar",eError); - return 0; - } - if(!SCMatchRights(pCon,usUser)) - { - return 0; - } - pCom = FindCommand(pSics,argv[2]); - if(!pCom) - { - sprintf(pBueffel,"ERROR: cannot find variable --> %s <--",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - pDum = (pDummy)pCom->pData; - if(!pDum) - { - sprintf(pBueffel,"ERROR: cannot find variable --> %s <--",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - if(strcmp(pDum->pDescriptor->name,"SicsSelVar") != 0) - { - sprintf(pBueffel,"ERROR: variable --> %s <-- has nothing to do with wavelength",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - iRet = SetWavelengthVariable(pCon,self,(pSelVar)pDum); - if(!iRet) - { - SCWrite(pCon,"ERROR: cannot set wavelength variable",eError); - return 0; - } - SCSendOK(pCon); - return 1; - } /*------------ UB */ else if(strcmp(argv[1],"setub") == 0) { @@ -1717,7 +963,7 @@ ente: return 0; } iRet = CalculateSettings(self,fHKL, fPsi, iHamil, fSet,pCon); - if(self->iNOR) + if(SXGetMode() == NB) { sprintf(pBueffel," gamma = %f, omega = %f, nu = %f", fSet[0], fSet[1], fSet[2]); @@ -1738,6 +984,18 @@ ente: } return 1; } +/*------------- calculate theta*/ + else if(strcmp(argv[1],"calctth") == 0) + { + iRet = GetCommandData(argc-2,&argv[2],fHKL, &fPsi, &iHamil,pCon); + if(!iRet) + { + return 0; + } + HKLCalculateTheta(self,fHKL, &stt); + SCPrintf(pCon,eValue,"two-theta = %lf", stt); + return 1; + } /*------------------ run */ else if(strcmp(argv[1],"run") == 0) { diff --git a/hkl.h b/hkl.h index 4f4c081b..5f8374eb 100644 --- a/hkl.h +++ b/hkl.h @@ -19,15 +19,12 @@ typedef struct __HKL *pHKL; /*-------------------------------------------------------------------------*/ - pHKL CreateHKL(pMotor pTheta, pMotor pOmega, - pMotor pChi, pMotor pPhi, pMotor pNu); + pHKL CreateHKL(); void DeleteHKL(void *pData); int HKLFactory(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); /*------------------------------------------------------------------------*/ - int SetWavelengthVariable(SConnection *pCon, pHKL self, pSelVar pVar); - int SetWavelengthManual(pHKL self, float fVal); void SetHKLScanTolerance(pHKL self, float value); int SetUB(pHKL self, float fUB[9]); int GetUB(pHKL self, float fUB[9]); @@ -48,7 +45,8 @@ int HKLAction(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); - int hklInRange(void *data, float fSet[4], int mask[4]); + int hklInRange(void *data, double fSet[4], int mask[4]); int startHKLMotors(pHKL self, SConnection *pCon, float fSet[4]); + void stopHKLMotors(pHKL self); #endif diff --git a/hkl.i b/hkl.i index 14cbaed0..d7f15383 100644 --- a/hkl.i +++ b/hkl.i @@ -9,24 +9,17 @@ typedef struct __HKL { pObjectDescriptor pDes; - double fUB[9]; MATRIX UBinv; - double fLambda; int iManual; double fLastHKL[5]; int iNOR; int iQuad; int iHM; - pMotor pTheta; - pMotor pOmega; - pMotor pChi; - pMotor pPhi; - pMotor pNu; - pSelVar pMono; long lID; float scanTolerance; float targetHKL[3]; int targetDirty; + pIDrivable pMotDriv; } HKL; diff --git a/hkl.tex b/hkl.tex index bed73427..20b3f38b 100644 --- a/hkl.tex +++ b/hkl.tex @@ -20,26 +20,19 @@ $\langle$hkldat {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@@\\ \mbox{}\verb@ typedef struct __HKL {@\\ \mbox{}\verb@ pObjectDescriptor pDes;@\\ -\mbox{}\verb@ double fUB[9];@\\ \mbox{}\verb@ MATRIX UBinv;@\\ -\mbox{}\verb@ double fLambda;@\\ \mbox{}\verb@ int iManual;@\\ \mbox{}\verb@ double fLastHKL[5];@\\ \mbox{}\verb@ int iNOR;@\\ \mbox{}\verb@ int iQuad;@\\ \mbox{}\verb@ int iHM;@\\ -\mbox{}\verb@ pMotor pTheta;@\\ -\mbox{}\verb@ pMotor pOmega;@\\ -\mbox{}\verb@ pMotor pChi;@\\ -\mbox{}\verb@ pMotor pPhi;@\\ -\mbox{}\verb@ pMotor pNu;@\\ -\mbox{}\verb@ pSelVar pMono;@\\ \mbox{}\verb@ long lID;@\\ \mbox{}\verb@ float scanTolerance;@\\ \mbox{}\verb@ float targetHKL[3];@\\ \mbox{}\verb@ int targetDirty;@\\ +\mbox{}\verb@ pIDrivable pMotDriv;@\\ \mbox{}\verb@ } HKL;@\\ -\mbox{}\verb@@$\diamond$ +\mbox{}\verb@@$\Diamond$ \end{list} \vspace{-1ex} \footnotesize\addtolength{\baselineskip}{-1ex} @@ -51,23 +44,12 @@ $\langle$hkldat {\footnotesize ?}$\rangle\equiv$ The fields are more or less self explaining: \begin{description} \item[pDes] The standard object descriptor. -\item[fUB] The UB matrix. -\item[iUB] is a flag which spcifies if a UB is specified. -\item[fLambda] The wavelength of the neutrons. \item[iManual] A flag which defines if the wavelength has been set manually or is updated automatically from a wavelength variable. \item[fLastHKL] the HKL of the last reflection calculated. \item[iNor] a flag for normal beam calculation mode. \item[iHM] a flag for histogram memory mode. In this mode two theta limits are checked alos for detector 2 and 3. -\item[pTheta] The two theta motor. All motor are needed for boundary -checking. -\item[pOmega] The omega axis motor. -\item[pChi] The chi axis motor. -\item[pPhi] the phi axis motor. -\item[pNu] the nu axis motor for normal beam geometry. - This is detector tilt. -\item[pMono] The selector variable doing the wavelength. \item[scanTolerance] The hkl module refuses to position a reflection if it is to close to omega limits for scanning. This is the tolerance to use. \item[targetHKL] The target HKL values to support the H, K, L virtual motors @@ -95,15 +77,12 @@ $\langle$hklint {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@@\\ \mbox{}\verb@ typedef struct __HKL *pHKL;@\\ \mbox{}\verb@/*-------------------------------------------------------------------------*/@\\ -\mbox{}\verb@ pHKL CreateHKL(pMotor pTheta, pMotor pOmega, @\\ -\mbox{}\verb@ pMotor pChi, pMotor pPhi, pMotor pNu);@\\ +\mbox{}\verb@ pHKL CreateHKL();@\\ \mbox{}\verb@ void DeleteHKL(void *pData);@\\ \mbox{}\verb@ @\\ \mbox{}\verb@ int HKLFactory(SConnection *pCon, SicsInterp *pSics, void *pData,@\\ \mbox{}\verb@ int argc, char *argv[]);@\\ \mbox{}\verb@/*------------------------------------------------------------------------*/@\\ -\mbox{}\verb@ int SetWavelengthVariable(SConnection *pCon, pHKL self, pSelVar pVar);@\\ -\mbox{}\verb@ int SetWavelengthManual(pHKL self, float fVal);@\\ \mbox{}\verb@ void SetHKLScanTolerance(pHKL self, float value);@\\ \mbox{}\verb@ int SetUB(pHKL self, float fUB[9]);@\\ \mbox{}\verb@ int GetUB(pHKL self, float fUB[9]);@\\ @@ -126,7 +105,8 @@ $\langle$hklint {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@ int argc, char *argv[]); @\\ \mbox{}\verb@ int hklInRange(void *data, float fSet[4], int mask[4]);@\\ \mbox{}\verb@ int startHKLMotors(pHKL self, SConnection *pCon, float fSet[4]);@\\ -\mbox{}\verb@@$\diamond$ +\mbox{}\verb@ void stopHKLMotors(pHKL self);@\\ +\mbox{}\verb@@$\Diamond$ \end{list} \vspace{-1ex} \footnotesize\addtolength{\baselineskip}{-1ex} @@ -197,7 +177,7 @@ drive properly. \mbox{}\verb@----------------------------------------------------------------------------*/@\\ \mbox{}\verb@@$\langle$hkldat {\footnotesize ?}$\rangle$\verb@@\\ \mbox{}\verb@@\\ -\mbox{}\verb@@$\diamond$ +\mbox{}\verb@@$\Diamond$ \end{list} \vspace{-2ex} \end{minipage}\\[4ex] @@ -227,7 +207,7 @@ drive properly. \mbox{}\verb@#include "selvar.h"@\\ \mbox{}\verb@@$\langle$hklint {\footnotesize ?}$\rangle$\verb@@\\ \mbox{}\verb@#endif @\\ -\mbox{}\verb@@$\diamond$ +\mbox{}\verb@@$\Diamond$ \end{list} \vspace{-2ex} \end{minipage}\\[4ex] @@ -257,7 +237,7 @@ $\langle$hklmotdat {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@ pIDrivable pDriv;@\\ \mbox{}\verb@ int index;@\\ \mbox{}\verb@ }HKLMot, *pHKLMot;@\\ -\mbox{}\verb@@$\diamond$ +\mbox{}\verb@@$\Diamond$ \end{list} \vspace{-1ex} \footnotesize\addtolength{\baselineskip}{-1ex} @@ -303,7 +283,7 @@ functions. The interpreter interface is minimal: only a value request is support \mbox{}\verb@#endif@\\ \mbox{}\verb@@\\ \mbox{}\verb@ @\\ -\mbox{}\verb@@$\diamond$ +\mbox{}\verb@@$\Diamond$ \end{list} \vspace{-2ex} \end{minipage}\\[4ex] diff --git a/hkl.w b/hkl.w index a1b510d3..ae676544 100644 --- a/hkl.w +++ b/hkl.w @@ -15,47 +15,29 @@ The object uses the following object data structure: @d hkldat @{ typedef struct __HKL { pObjectDescriptor pDes; - double fUB[9]; MATRIX UBinv; - double fLambda; int iManual; double fLastHKL[5]; int iNOR; int iQuad; int iHM; - pMotor pTheta; - pMotor pOmega; - pMotor pChi; - pMotor pPhi; - pMotor pNu; - pSelVar pMono; long lID; float scanTolerance; float targetHKL[3]; int targetDirty; + pIDrivable pMotDriv; } HKL; @} The fields are more or less self explaining: \begin{description} \item[pDes] The standard object descriptor. -\item[fUB] The UB matrix. -\item[iUB] is a flag which spcifies if a UB is specified. -\item[fLambda] The wavelength of the neutrons. \item[iManual] A flag which defines if the wavelength has been set manually or is updated automatically from a wavelength variable. \item[fLastHKL] the HKL of the last reflection calculated. \item[iNor] a flag for normal beam calculation mode. \item[iHM] a flag for histogram memory mode. In this mode two theta limits are checked alos for detector 2 and 3. -\item[pTheta] The two theta motor. All motor are needed for boundary -checking. -\item[pOmega] The omega axis motor. -\item[pChi] The chi axis motor. -\item[pPhi] the phi axis motor. -\item[pNu] the nu axis motor for normal beam geometry. - This is detector tilt. -\item[pMono] The selector variable doing the wavelength. \item[scanTolerance] The hkl module refuses to position a reflection if it is to close to omega limits for scanning. This is the tolerance to use. \item[targetHKL] The target HKL values to support the H, K, L virtual motors @@ -78,15 +60,12 @@ module: @d hklint @{ typedef struct __HKL *pHKL; /*-------------------------------------------------------------------------*/ - pHKL CreateHKL(pMotor pTheta, pMotor pOmega, - pMotor pChi, pMotor pPhi, pMotor pNu); + pHKL CreateHKL(); void DeleteHKL(void *pData); int HKLFactory(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); /*------------------------------------------------------------------------*/ - int SetWavelengthVariable(SConnection *pCon, pHKL self, pSelVar pVar); - int SetWavelengthManual(pHKL self, float fVal); void SetHKLScanTolerance(pHKL self, float value); int SetUB(pHKL self, float fUB[9]); int GetUB(pHKL self, float fUB[9]); @@ -109,6 +88,7 @@ module: int argc, char *argv[]); int hklInRange(void *data, float fSet[4], int mask[4]); int startHKLMotors(pHKL self, SConnection *pCon, float fSet[4]); + void stopHKLMotors(pHKL self); @} All functions return 0 on failure, 1 on success if not stated otherwise. Most functions take a pointer to a HKL data structure as first parameter. diff --git a/hklmot.c b/hklmot.c index 2d897360..49f88f2b 100644 --- a/hklmot.c +++ b/hklmot.c @@ -15,6 +15,7 @@ #include "hkl.h" #include "hkl.i" #include "hklmot.h" +#include "singlex.h" /*=================== Object Descriptor Interface ===================================================*/ static void *HKLGetInterface(void *pData, int iID){ pHKLMot self = NULL; @@ -28,21 +29,15 @@ static void *HKLGetInterface(void *pData, int iID){ } return NULL; } +/*--------------------------------------------------------------------------------------------------*/ +extern void stopHKLMotors(pHKL hkl); /*=================== Drivable Interface ============================================================*/ static int HKLHalt(void *pData){ pHKLMot self = NULL; self = (pHKLMot)pData; assert(self != NULL); - - self->pHkl->pTheta->pDrivInt->Halt(self->pHkl->pTheta); - self->pHkl->pOmega->pDrivInt->Halt(self->pHkl->pOmega); - if(self->pHkl->iNOR == 1){ - self->pHkl->pNu->pDrivInt->Halt(self->pHkl->pNu); - } else { - self->pHkl->pChi->pDrivInt->Halt(self->pHkl->pChi); - self->pHkl->pPhi->pDrivInt->Halt(self->pHkl->pPhi); - } + stopHKLMotors(self->pHkl); return 1; } /*-----------------------------------------------------------------------------------------------------*/ @@ -72,26 +67,52 @@ static long HKLSetValue(void *pData, SConnection *pCon, float fVal){ /*---------------------------------------------------------------------------------------------------*/ static int checkMotors(pHKLMot self, SConnection *pCon){ int status; + pMotor pTheta, pOmega, pChi, pPhi, pNu; + + pTheta = SXGetMotor(TwoTheta); + pOmega = SXGetMotor(Omega); + pChi = SXGetMotor(Chi); + pPhi = SXGetMotor(Phi); + if(pTheta == NULL || pOmega == NULL){ + SCWrite(pCon,"ERROR: configuration problem, stt,om motors not found,", + eError); + return HWFault; + } - status = self->pHkl->pTheta->pDrivInt->CheckStatus(self->pHkl->pTheta, pCon); + + status = pTheta->pDrivInt->CheckStatus(pTheta, pCon); if(status != HWIdle && status != OKOK){ return status; } - status = self->pHkl->pOmega->pDrivInt->CheckStatus(self->pHkl->pOmega, pCon); + status = pOmega->pDrivInt->CheckStatus(pOmega, pCon); if(status != HWIdle && status != OKOK){ return status; } - if(self->pHkl->iNOR == 1){ - status = self->pHkl->pNu->pDrivInt->CheckStatus(self->pHkl->pNu, pCon); + if(SXGetMode() == NB){ + pNu = SXGetMotor(Nu); + if(pNu == NULL){ + SCWrite(pCon,"ERROR: configuration problem, nu motor not found,", + eError); + return HWFault; + + } + status = pNu->pDrivInt->CheckStatus(pNu, pCon); if(status != HWIdle && status != OKOK){ return status; } } else { - status = self->pHkl->pChi->pDrivInt->CheckStatus(self->pHkl->pChi, pCon); + pChi = SXGetMotor(Chi); + pPhi = SXGetMotor(Phi); + if(pTheta == NULL || pOmega == NULL){ + SCWrite(pCon,"ERROR: configuration problem, chi, phi motors not found,", + eError); + return HWFault; + } + status = pChi->pDrivInt->CheckStatus(pChi, pCon); if(status != HWIdle && status != OKOK){ return status; } - status = self->pHkl->pPhi->pDrivInt->CheckStatus(self->pHkl->pPhi, pCon); + status = pPhi->pDrivInt->CheckStatus(pPhi, pCon); if(status != HWIdle && status != OKOK){ return status; } @@ -204,11 +225,11 @@ int HKLMotInstall(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, c char pBuffer[131]; if(argc < 2){ - SCWrite(pCon,"ERROR: Insifficient number of arguments to HKLMotInstall",eError); - return 0; + pHkl = (pHKL)FindCommandData(pSics,"hkl","4-Circle-Calculus"); + } else { + strtolower(argv[1]); + pHkl = (pHKL)FindCommandData(pSics,argv[1],"4-Circle-Calculus"); } - strtolower(argv[1]); - pHkl = (pHKL)FindCommandData(pSics,argv[1],"4-Circle-Calculus"); if(pHkl == NULL){ snprintf(pBuffer,131,"ERROR: %s is not present or no HKL object",argv[1]); SCWrite(pCon,pBuffer,eError); diff --git a/hmcontrol.c b/hmcontrol.c index 758ed638..d3e5ddc3 100644 --- a/hmcontrol.c +++ b/hmcontrol.c @@ -45,9 +45,11 @@ static int HMCHalt(void *pData) for(i = 0; i < self->nSlaves; i++) { status = self->slaves[i]->Halt(self->slaveData[i]); + ReleaseCountLock(self->slaves[i]); if(status != OKOK) retVal = status; } + ReleaseCountLock(self->pCount); return retVal; } /*-----------------------------------------------------------------------*/ @@ -59,8 +61,13 @@ static int HMCStart(void *pData, SConnection *pCon) self = (pHMcontrol)pData; assert(self); + if(!GetCountLock(self->pCount, pCon)){ + return HWFault; + } + for(i = 0; i < self->nSlaves; i++) { + ReleaseCountLock(self->slaves[i]); status = self->slaves[i]->StartCount(self->slaveData[i],pCon); if(status != OKOK) { diff --git a/initializer.c b/initializer.c index 4c8ee024..ef75f394 100644 --- a/initializer.c +++ b/initializer.c @@ -92,9 +92,9 @@ static int DriverList(SConnection *con, SicsInterp *sics, if (argc < 2 || strcasecmp(argv[1], "list") == 0) { for (p = list; p != NULL; p = p->next) { if (argc < 3) { - SCPrintf(con, eStatus, "%s %s %s", p->type, p->name, p->desc); + SCPrintf(con, eValue, "%s %s %s", p->type, p->name, p->desc); } else if (strcasecmp(argv[2], p->type) == 0) { - SCPrintf(con, eStatus, "%s %s", p->name, p->desc); + SCPrintf(con, eValue, "%s %s", p->name, p->desc); } } } else { diff --git a/interface.c b/interface.c index 11c08415..ea5d5631 100644 --- a/interface.c +++ b/interface.c @@ -167,6 +167,30 @@ int GetDrivablePosition(void *pObject, SConnection *pCon, float *fPos) { return (pICountable)FindInterface(pObject,COUNTID); } +/*--------------------------------------------------------------------------*/ + int GetCountLock(pICountable self, SConnection *pCon) + { + if(self->running == 1) + { + SCWrite(pCon,"ERROR: someone else is already counting!", eError); + return 0; + } + else + { + self->running = 1; + return 1; + } + } +/*--------------------------------------------------------------------------*/ + void ReleaseCountLock(pICountable self) + { + self->running = 0; + } +/*--------------------------------------------------------------------------*/ + int isRunning(pICountable self) + { + return self->running; + } /*--------------------------------------------------------------------------*/ pICallBack GetCallbackInterface(void *pObject) { diff --git a/interface.h b/interface.h index 326e491d..6be57bea 100644 --- a/interface.h +++ b/interface.h @@ -1,5 +1,5 @@ -#line 379 "interface.w" +#line 399 "interface.w" /*--------------------------------------------------------------------------- I N T E R F A C E S @@ -27,7 +27,7 @@ /* ----------------------- The drivable interface -----------------------*/ -#line 119 "interface.w" +#line 121 "interface.w" typedef struct { @@ -48,17 +48,18 @@ float *fPos); -#line 405 "interface.w" +#line 425 "interface.w" pIDrivable CreateDrivableInterface(void); /* ------------------------ The countable interface ---------------------*/ -#line 186 "interface.w" +#line 188 "interface.w" typedef struct { int ID; + int running; int (*Halt)(void *self); void (*SetCountParameters)(void *self, float fPreset, CounterMode eMode);\ @@ -70,25 +71,27 @@ } ICountable, *pICountable; pICountable GetCountableInterface(void *pObject); + int GetCountLock(pICountable self, SConnection *pCon); + void ReleaseCountLock(pICountable self); + int isRunning(pICountable self); - -#line 410 "interface.w" +#line 430 "interface.w" pICountable CreateCountableInterface(void); /* ------------------------- The CallBack Interface --------------------*/ -#line 239 "interface.w" +#line 253 "interface.w" typedef void (*KillFuncIT)(void *pData); typedef int (*SICSCallBack)(int iEvent, void *pEventData, - void *pUserData, commandContext cc); + void *pUserData); -#line 415 "interface.w" +#line 435 "interface.w" -#line 261 "interface.w" +#line 275 "interface.w" typedef struct __ICallBack *pICallBack; @@ -98,22 +101,23 @@ int InvokeCallBack(pICallBack pInterface, int iEvent, void *pEventData); /* callback client side */ - long RegisterCallback(pICallBack pInterface, commandContext comCon, + long RegisterCallback(pICallBack pInterface, int iEvent, SICSCallBack pFunc, void *pUserData, KillFuncIT pKill); int RemoveCallback(pICallBack pInterface, long iID); int RemoveCallback2(pICallBack pInterface, void *pUserData); + int RemoveCallbackCon(pICallBack pInterface, SConnection *pCon); int CallbackScript(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); pICallBack GetCallbackInterface(void *pData); -#line 416 "interface.w" +#line 436 "interface.w" /*---------------------- The Environment Interface --------------------*/ -#line 333 "interface.w" +#line 353 "interface.w" typedef enum { EVIdle, EVDrive, EVMonitor, EVError } EVMode; typedef struct { @@ -123,13 +127,13 @@ int (*HandleError)(void *self); } EVInterface, *pEVInterface; -#line 418 "interface.w" +#line 438 "interface.w" -#line 359 "interface.w" +#line 379 "interface.w" pEVInterface CreateEVInterface(void); -#line 419 "interface.w" +#line 439 "interface.w" #endif diff --git a/interface.tex b/interface.tex index c1331f38..663fefd9 100644 --- a/interface.tex +++ b/interface.tex @@ -51,12 +51,14 @@ $\langle$obdes {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@#define SICSDESCRIPTOR@\\ \mbox{}\verb@#include @\\ \mbox{}\verb@#include @\\ +\mbox{}\verb@#include @\\ \mbox{}\verb@@\\ \mbox{}\verb@ typedef struct {@\\ \mbox{}\verb@ char *name;@\\ \mbox{}\verb@ int (*SaveStatus)(void *self, char *name,FILE *fd);@\\ \mbox{}\verb@ void *(*GetInterface)(void *self, int iInterfaceID);@\\ \mbox{}\verb@ IPair *pKeys;@\\ +\mbox{}\verb@ pHdb parNode;@\\ \mbox{}\verb@ } ObjectDescriptor, *pObjectDescriptor;@\\ \mbox{}\verb@@\\ \mbox{}\verb@ /*---------------------------------------------------------------------------*/@\\ @@ -81,7 +83,7 @@ $\langle$obdes {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@ int iHasType(void *pData, char *Type);@\\ \mbox{}\verb@ @\\ \mbox{}\verb@#endif @\\ -\mbox{}\verb@@$\diamond$ +\mbox{}\verb@@$\Diamond$ \end{list} \vspace{-1ex} \footnotesize\addtolength{\baselineskip}{-1ex} @@ -152,7 +154,7 @@ $\langle$driv {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@ int GetDrivablePosition(void *pObject, SConnection *pCon,@\\ \mbox{}\verb@ float *fPos);@\\ \mbox{}\verb@@\\ -\mbox{}\verb@@$\diamond$ +\mbox{}\verb@@$\Diamond$ \end{list} \vspace{-1ex} \footnotesize\addtolength{\baselineskip}{-1ex} @@ -216,6 +218,7 @@ $\langle$count {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@@\\ \mbox{}\verb@ typedef struct {@\\ \mbox{}\verb@ int ID;@\\ +\mbox{}\verb@ int running;@\\ \mbox{}\verb@ int (*Halt)(void *self);@\\ \mbox{}\verb@ void (*SetCountParameters)(void *self, float fPreset,@\\ \mbox{}\verb@ CounterMode eMode);\@\\ @@ -227,8 +230,10 @@ $\langle$count {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@ } ICountable, *pICountable;@\\ \mbox{}\verb@@\\ \mbox{}\verb@ pICountable GetCountableInterface(void *pObject); @\\ -\mbox{}\verb@@\\ -\mbox{}\verb@@$\diamond$ +\mbox{}\verb@ int GetCountLock(pICountable self, SConnection *pCon);@\\ +\mbox{}\verb@ void ReleaseCountLock(pICountable self);@\\ +\mbox{}\verb@ int isRunning(pICountable self);@\\ +\mbox{}\verb@@$\Diamond$ \end{list} \vspace{-1ex} \footnotesize\addtolength{\baselineskip}{-1ex} @@ -237,6 +242,8 @@ $\langle$count {\footnotesize ?}$\rangle\equiv$ \end{list} \end{minipage}\\[4ex] \end{flushleft} +{\bf running } Is a flag which says if the counter is operating or not. + {\bf Halt and StartCount} are self explaining, they just do what they say. Please note, that counting configuration must have happened before usage of this interface. @@ -260,6 +267,13 @@ the existence of a countable interface. If it exists a pointer to it will be returned. NEVER free this pointer. If no countable interface exists, NULL will be returned. +{\bf GetCountLock} will try to set the running flag. If it is already running, an error + is printed to pCon and 0 is returned. + +{\bf ReleaseCountLock} release the count lock. + +{\bf isRunning} returns the running flag. + \subsubsection{The Callback Interface} The Callback Interface is SICS suport for component behaviour for objects. Consider objects A and B. A now is able to generate certain events when it's @@ -281,8 +295,8 @@ $\langle$callfunc {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@@\\ \mbox{}\verb@ typedef void (*KillFuncIT)(void *pData);@\\ \mbox{}\verb@ typedef int (*SICSCallBack)(int iEvent, void *pEventData, @\\ -\mbox{}\verb@ void *pUserData, commandContext cc);@\\ -\mbox{}\verb@@$\diamond$ +\mbox{}\verb@ void *pUserData);@\\ +\mbox{}\verb@@$\Diamond$ \end{list} \vspace{-1ex} \footnotesize\addtolength{\baselineskip}{-1ex} @@ -321,17 +335,18 @@ $\langle$cifunc {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@ int InvokeCallBack(pICallBack pInterface, int iEvent, void *pEventData); @\\ \mbox{}\verb@@\\ \mbox{}\verb@ /* callback client side */@\\ -\mbox{}\verb@ long RegisterCallback(pICallBack pInterface, commandContext comCon, @\\ +\mbox{}\verb@ long RegisterCallback(pICallBack pInterface, @\\ \mbox{}\verb@ int iEvent, SICSCallBack pFunc,@\\ \mbox{}\verb@ void *pUserData, KillFuncIT pKill);@\\ \mbox{}\verb@ int RemoveCallback(pICallBack pInterface, long iID);@\\ \mbox{}\verb@ int RemoveCallback2(pICallBack pInterface, void *pUserData);@\\ +\mbox{}\verb@ int RemoveCallbackCon(pICallBack pInterface, SConnection *pCon);@\\ \mbox{}\verb@@\\ \mbox{}\verb@ int CallbackScript(SConnection *pCon, SicsInterp *pSics, void *pData,@\\ \mbox{}\verb@ int argc, char *argv[]); @\\ \mbox{}\verb@@\\ \mbox{}\verb@ pICallBack GetCallbackInterface(void *pData); @\\ -\mbox{}\verb@@$\diamond$ +\mbox{}\verb@@$\Diamond$ \end{list} \vspace{-1ex} \footnotesize\addtolength{\baselineskip}{-1ex} @@ -378,6 +393,11 @@ RegisterCallBack. search key for deletion is the pointer to user data. All callbacks related to this user data in the interface specified will be removed. +{\bf RemoveCallbackCon} is another variant for removing callbacks. This time the +search key for deletion is the pointer to user data which must be a connection object. +All callbacks related to this connection in the interface specified will be removed. This is +a convenience function for removing interest callbacks in SICS. + {\bf CallbackScript} allows to connect callbacks to scripts. Please note, that those scripts will have a dummy connection to clients only and will not be able to write to clients. All output occurring in @@ -404,7 +424,7 @@ $\langle$envir {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@ int (*IsInTolerance)(void *self);@\\ \mbox{}\verb@ int (*HandleError)(void *self);@\\ \mbox{}\verb@ } EVInterface, *pEVInterface;@\\ -\mbox{}\verb@@$\diamond$ +\mbox{}\verb@@$\Diamond$ \end{list} \vspace{-1ex} \footnotesize\addtolength{\baselineskip}{-1ex} @@ -437,7 +457,7 @@ $\langle$envfunc {\footnotesize ?}$\rangle\equiv$ \begin{list}{}{} \item \mbox{}\verb@@\\ \mbox{}\verb@ pEVInterface CreateEVInterface(void);@\\ -\mbox{}\verb@@$\diamond$ +\mbox{}\verb@@$\Diamond$ \end{list} \vspace{-1ex} \footnotesize\addtolength{\baselineskip}{-1ex} @@ -465,7 +485,7 @@ $\langle$envfunc {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@ char * GetDescriptorKey(pObjectDescriptor self, char *keyName);@\\ \mbox{}\verb@ char * GetDescriptorGroup(pObjectDescriptor self);@\\ \mbox{}\verb@ char * GetDescriptorDescription(pObjectDescriptor self);@\\ -\mbox{}\verb@@$\diamond$ +\mbox{}\verb@@$\Diamond$ \end{list} \vspace{-2ex} \end{minipage}\\[4ex] @@ -517,7 +537,7 @@ $\langle$envfunc {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@@$\langle$envir {\footnotesize ?}$\rangle$\verb@@\\ \mbox{}\verb@@$\langle$envfunc {\footnotesize ?}$\rangle$\verb@@\\ \mbox{}\verb@#endif@\\ -\mbox{}\verb@@$\diamond$ +\mbox{}\verb@@$\Diamond$ \end{list} \vspace{-2ex} \end{minipage}\\[4ex] diff --git a/interface.w b/interface.w index c5dd1180..9aa75d36 100644 --- a/interface.w +++ b/interface.w @@ -46,12 +46,14 @@ Let's start with the objectdescriptor: #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; /*---------------------------------------------------------------------------*/ @@ -186,6 +188,7 @@ This is an interface for interacting with anything which counts. @d count @{ typedef struct { int ID; + int running; int (*Halt)(void *self); void (*SetCountParameters)(void *self, float fPreset, CounterMode eMode);\ @@ -197,9 +200,13 @@ This is an interface for interacting with anything which counts. } ICountable, *pICountable; pICountable GetCountableInterface(void *pObject); - + int GetCountLock(pICountable self, SConnection *pCon); + void ReleaseCountLock(pICountable self); + int isRunning(pICountable self); @} +{\bf running } Is a flag which says if the counter is operating or not. + {\bf Halt and StartCount} are self explaining, they just do what they say. Please note, that counting configuration must have happened before usage of this interface. @@ -223,6 +230,13 @@ the existence of a countable interface. If it exists a pointer to it will be returned. NEVER free this pointer. If no countable interface exists, NULL will be returned. +{\bf GetCountLock} will try to set the running flag. If it is already running, an error + is printed to pCon and 0 is returned. + +{\bf ReleaseCountLock} release the count lock. + +{\bf isRunning} returns the running flag. + \subsubsection{The Callback Interface} The Callback Interface is SICS suport for component behaviour for objects. Consider objects A and B. A now is able to generate certain events when it's @@ -239,7 +253,7 @@ function: @d callfunc @{ typedef void (*KillFuncIT)(void *pData); typedef int (*SICSCallBack)(int iEvent, void *pEventData, - void *pUserData, commandContext cc); + void *pUserData); @} The callback function is meant to return 0 for failure or 1 for success. @@ -267,11 +281,12 @@ interface: int InvokeCallBack(pICallBack pInterface, int iEvent, void *pEventData); /* callback client side */ - long RegisterCallback(pICallBack pInterface, commandContext comCon, + long RegisterCallback(pICallBack pInterface, int iEvent, SICSCallBack pFunc, void *pUserData, KillFuncIT pKill); int RemoveCallback(pICallBack pInterface, long iID); int RemoveCallback2(pICallBack pInterface, void *pUserData); + int RemoveCallbackCon(pICallBack pInterface, SConnection *pCon); int CallbackScript(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); @@ -317,6 +332,11 @@ RegisterCallBack. search key for deletion is the pointer to user data. All callbacks related to this user data in the interface specified will be removed. +{\bf RemoveCallbackCon} is another variant for removing callbacks. This time the +search key for deletion is the pointer to user data which must be a connection object. +All callbacks related to this connection in the interface specified will be removed. This is +a convenience function for removing interest callbacks in SICS. + {\bf CallbackScript} allows to connect callbacks to scripts. Please note, that those scripts will have a dummy connection to clients only and will not be able to write to clients. All output occurring in diff --git a/macro.c b/macro.c index bc3a10e5..ada160fb 100644 --- a/macro.c +++ b/macro.c @@ -529,7 +529,7 @@ extern int Nxinter_SafeInit(Tcl_Interp *pTcl); /* from Swig NeXus Tcl interface if(FindCommand(pInter,pBueffel) != NULL) { sprintf(pBueffel,"%s:%d>> %s",pFile,iLine,pCom); - SCWrite(pCon,pBueffel,eValue); + SCWrite(pCon,pBueffel,eLog); if(pWhere != NULL) { free(pWhere); @@ -627,21 +627,6 @@ extern int Nxinter_SafeInit(Tcl_Interp *pTcl); /* from Swig NeXus Tcl interface } SCnoSock(pIntern); - /* configure the log file */ - pFil = strdup(argv[1]); - pExt = strrchr(pFil,(int)'.'); - if(!pExt) - { - SCWrite(pCon,"ERROR: no extension found in InternalFileEval", - eError); - return 0; - } - else - { - strcpy(pExt,".log"); - SCAddLogFile(pIntern,pFil); - free(pFil); - } /* invoke the fileeval */ MacroPush(pIntern); @@ -664,9 +649,8 @@ extern int Nxinter_SafeInit(Tcl_Interp *pTcl); /* from Swig NeXus Tcl interface int ClientPut(SConnection *pCon, SicsInterp *pInter, void *pData, int argc, char *argv[]) { - OutCode eOut = eWarning; + OutCode eOut = eLog; int i = 0, iCode, iLen; - int iMacro; char *ppCode; char *pMessage = NULL; @@ -701,7 +685,7 @@ extern int Nxinter_SafeInit(Tcl_Interp *pTcl); /* from Swig NeXus Tcl interface } else { - i = 10; + i = eLog; iCode = argc; } @@ -740,8 +724,14 @@ extern int Nxinter_SafeInit(Tcl_Interp *pTcl); /* from Swig NeXus Tcl interface case 10: eOut = eError; break; + case 11: + eOut = eLog; + break; + case 12: + eOut = eLogError; + break; default: - eOut = eWarning; + eOut = eLog; iCode = argc; break; } @@ -756,19 +746,13 @@ extern int Nxinter_SafeInit(Tcl_Interp *pTcl); /* from Swig NeXus Tcl interface pMessage = (char *)malloc((iLen+100)*sizeof(char)); if(!pMessage) { - SCWrite(pCon,"ERROR: out of memory in clientput",eError); + SCWrite(pCon,"ERROR: out of memory in clientput",eLogError); return 0; } memset(pMessage,0,(iLen+100)*sizeof(char)); Arg2Text(iCode-1,&argv[1],pMessage,(iLen+100)*sizeof(char)); - /* now write, thereby tunneling macro flag in order to get proper - write to client and not into interpreter - */ - iMacro = SCinMacro(pCon); - SCsetMacro(pCon,0); SCWrite(pCon,pMessage,eOut); - SCsetMacro(pCon,iMacro); if(pMessage) { free(pMessage); @@ -784,14 +768,14 @@ extern int Nxinter_SafeInit(Tcl_Interp *pTcl); /* from Swig NeXus Tcl interface int iMacro; char *ppCode; char *pMessage = NULL; - commandContext cc; + SConnection *conCon = NULL; assert(pCon); assert(pInter); if(argc < 2) { - SCWrite(pCon,"Insufficient arguments to ClientPut",eError); + SCWrite(pCon,"Insufficient arguments to ClientPut",eLogError); return 0; } @@ -856,8 +840,14 @@ extern int Nxinter_SafeInit(Tcl_Interp *pTcl); /* from Swig NeXus Tcl interface case 10: eOut = eError; break; + case 11: + eOut = eLog; + break; + case 12: + eOut = eLogError; + break; default: - eOut = eWarning; + eOut = eLog; iCode = argc; break; } @@ -882,14 +872,13 @@ extern int Nxinter_SafeInit(Tcl_Interp *pTcl); /* from Swig NeXus Tcl interface write to client and not into interpreter. We also make sure that the device is gumput */ - iMacro = SCinMacro(pCon); - SCsetMacro(pCon,0); - cc = SCGetContext(pCon); - strcpy(cc.deviceID,"gumput"); - SCPushContext2(pCon,cc); - SCWrite(pCon,pMessage,eOut); - SCPopContext(pCon); - SCsetMacro(pCon,iMacro); + conCon = SCCopyConnection(pCon); + if(conCon == NULL){ + SCWrite(pCon,"ERROR: out of memory in gumput", eError); + } + strcpy(conCon->deviceID,"gumput"); + SCWrite(conCon,pMessage,eOut); + SCDeleteConnection(conCon); if(pMessage) { free(pMessage); @@ -908,7 +897,7 @@ extern int Nxinter_SafeInit(Tcl_Interp *pTcl); /* from Swig NeXus Tcl interface if(argc < 2) { - SCWrite(pCon,"Insufficient arguments to Broadcast",eError); + SCWrite(pCon,"Insufficient arguments to Broadcast",eLog); return 0; } @@ -917,10 +906,7 @@ extern int Nxinter_SafeInit(Tcl_Interp *pTcl); /* from Swig NeXus Tcl interface write to client and not into interpreter */ Arg2Text(argc-1, &argv[1],pBueffel,255); - iMacro = SCinMacro(pCon); - SCsetMacro(pCon,0); - ServerWriteGlobal(pBueffel,eWarning); - SCsetMacro(pCon,iMacro); + ServerWriteGlobal(pBueffel,eLog); return 1; } /*--------------------------------------------------------------------------- @@ -1013,13 +999,14 @@ extern int Nxinter_SafeInit(Tcl_Interp *pTcl); /* from Swig NeXus Tcl interface SCWrite(pCon, "ERROR: no more memory", eError); return 0; } + Tcl_ResetResult(pTcl); iRet = Tcl_Eval(pTcl,pCommand); - if (pCommand != pBueffel) free(pCommand); if(iRet == TCL_OK) { if(strlen(pTcl->result) > 0){ - SCPrintf(pCon, eStatus, "%s", pTcl->result); + SCPrintf(pCon, eValue, "%s", pTcl->result); } + if (pCommand != pBueffel) free(pCommand); return 1; } else @@ -1028,7 +1015,10 @@ extern int Nxinter_SafeInit(Tcl_Interp *pTcl); /* from Swig NeXus Tcl interface { Tcl_UnsetVar(pTcl,SICSERROR,TCL_GLOBAL_ONLY); } - SCPrintf(pCon,eError,"%s",pTcl->result); + if(strlen(pTcl->result) > 0){ + SCPrintf(pCon,eError,"ERROR: Tcl reported %s in %s",pTcl->result, pCommand); + } + if (pCommand != pBueffel) free(pCommand); return 0; } return 1; /* not reached */ @@ -1117,11 +1107,11 @@ extern int Nxinter_SafeInit(Tcl_Interp *pTcl); /* from Swig NeXus Tcl interface } strtolower(argv[0]); if(strcmp(argv[0],"fulltransact") == 0){ - SCPrintf(pCon,eError, "TRANSACTIONSTART %s",pCommand); + SCPrintf(pCon,eLog, "TRANSACTIONSTART %s",pCommand); } iRet = InterpExecute(pSics,pCon,pCommand); if (pCommand != pBuffer) free(pCommand); - SCWrite(pCon,"TRANSACTIONFINISHED",eError); + SCWrite(pCon,"TRANSACTIONFINISHED",eLog); return iRet; } diff --git a/make_gen b/make_gen index e53f064d..0f33b003 100644 --- a/make_gen +++ b/make_gen @@ -21,7 +21,7 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \ mesure.o uubuffer.o commandlog.o udpquieck.o fourtable.o\ rmtrail.o help.o nxupdate.o confvirtualmot.o vector.o\ simchop.o choco.o chadapter.o trim.o scaldate.o tasub.o\ - hklscan.o xytable.o exebuf.o exeman.o ubfour.o ubcalc.o\ + xytable.o exebuf.o exeman.o ubfour.o ubcalc.o\ circular.o maximize.o sicscron.o scanvar.o tasublib.o\ d_sign.o d_mod.o tcldrivable.o stdscan.o diffscan.o nxxml.o\ synchronize.o definealias.o oscillate.o tasdrive.o \ @@ -37,7 +37,10 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \ sicshdbadapter.o polldriv.o sicspoll.o statemon.o hmslave.o \ nwatch.o asyncqueue.o asyncprotocol.o sicsobj.o \ nxcopy.o nxinterhelper.o nxinter_wrap.o genericcontroller.o nxstack.o \ - sctdriveadapter.o sctdriveobj.o uselect.o + sctdriveadapter.o sctdriveobj.o reflist.o singlex.o fourmess.o \ + sgclib.o sgfind.o sgio.o sgsi.o sghkl.o singlediff.o singlebi.o \ + singlenb.o simindex.o simidx.o uselect.o singletas.o motorsec.o \ + rwpuffer.o asynnet.o background.o MOTOROBJ = motor.o simdriv.o COUNTEROBJ = countdriv.o simcter.o counter.o @@ -60,7 +63,7 @@ full: purge all SICServer: $(SOBJ) $(MOTOROBJ) $(COUNTEROBJ) \ $(VELOOBJ) $(DIFIL) $(EXTRA) \ $(SUBLIBS) - $(CC) -g -pg -o SICServer \ + $(CC) -g -o SICServer \ $(SOBJ) $(MOTOROBJ) $(COUNTEROBJ) \ $(VELOOBJ) $(DIFOBJ) $(EXTRA) $(LIBS) diff --git a/maximize.c b/maximize.c index a8b8affa..f6a3c99f 100644 --- a/maximize.c +++ b/maximize.c @@ -50,7 +50,7 @@ #include "motor.h" #define MAXPTS 100 -#define DEBUG 1 +#define DEBUG 0 typedef struct __MAXIMIZE { pObjectDescriptor pDes; @@ -382,8 +382,14 @@ fCent = x[i] +(fDisc -y[i])/fS; } /* finished ! */ + for(i = 0; i < iTop-1; i++){ + if(fCent >= x[i] && fCent < x[i+1] ){ + lCts = y[i]; + break; + } + } maxDrive(pVar,pVarName,fCent,pCon); - sprintf(pBueffel,"Found peak center at %8.2f", fCent); + sprintf(pBueffel,"Found peak center at %8.2f, Count = %ld", fCent, lCts); SCWrite(pCon,pBueffel,eValue); return 1; } diff --git a/mesure.c b/mesure.c index 5257678a..5a1c8514 100644 --- a/mesure.c +++ b/mesure.c @@ -423,7 +423,7 @@ static void ListMesure(pMesure self, char *name, SConnection *pCon) self->iCounts++; return 1; - } + } /*------------------------------------------------------------------------*/ static int getMesureNP(pMesure self, double twoTheta) { @@ -671,7 +671,7 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon) AddScanVar(self->pScanner, pServ->pSics,pCon,self->pCOmega, fStart, stepWidth); snprintf(pBueffel,131,"Scanning om from %f with step %f", fStart, stepWidth); - SCWrite(pCon,pBueffel,eValue); + SCWrite(pCon,pBueffel,eLog); /* Oksana does not want o2t scans to be tightly coupled, this is why we cannot use the normal o2t scan variable. Instead we calculate new limits and @@ -688,7 +688,7 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon) AddScanVar(self->pScanner, pServ->pSics,pCon,self->pC2Theta, fStart, stepWidth); snprintf(pBueffel,131,"Scanning 2theta from %f with step %f", fStart, stepWidth); - SCWrite(pCon,pBueffel,eValue); + SCWrite(pCon,pBueffel,eLog); } /* @@ -744,7 +744,7 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon) /* redo scan with preset * 5 */ - SCWrite(pCon,"Remeasuring weak reflection",eWarning); + SCWrite(pCon,"Remeasuring weak reflection",eLog); iRet = SilentScan(self->pScanner,np,self->CountMode, fPreset*5.,pServ->pSics,pCon); @@ -811,7 +811,9 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon) /* do the logfile */ strcpy(pFilename,pRoot); strcat(pFilename,"log"); + /* TODO self->iLogFile = SCAddLogFile(pCon,pFilename); + */ self->pCon = pCon; /* @@ -916,7 +918,9 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon) strcat(pFile,"/"); strcat(pFile,fileroot); strcat(pFile,".log"); + /* TODO: self->iLogFile = SCAddLogFile(pCon,pFile); + */ self->pCon = pCon; /* @@ -960,7 +964,9 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon) { assert(self); - SCDelLogFile(self->pCon,self->iLogFile); + /* TODO + * SCDelLogFile(self->pCon,self->iLogFile); + */ if(self->psd == 1) { self->pCon = NULL; @@ -1094,7 +1100,7 @@ static double getProtonAverage(pMesure self){ self->fPosition[0], self->fPosition[1], self->fPosition[2],self->fPosition[3], fSum,fSigma); - SCWrite(pCon,pBueffel,eStatus); + SCWrite(pCon,pBueffel,eLog); /* get temperature */ fTemp = -777.77; @@ -1218,7 +1224,7 @@ static double getProtonAverage(pMesure self){ /* make a mark */ SNXFormatTime(pTime,131); sprintf(pBueffel,"Starting at list %s at %s",pFile,pTime); - SCWrite(pCon,pBueffel,eStatus); + SCWrite(pCon,pBueffel,eLog); /* skippy! */ for(i = 0; i < iSkip; i++) @@ -1272,7 +1278,7 @@ static double getProtonAverage(pMesure self){ /* we are done */ SNXFormatTime(pTime,131); sprintf(pBueffel,"Finishing list %s at %s",pFile,pTime); - SCWrite(pCon,pBueffel,eStatus); + SCWrite(pCon,pBueffel,eLog); fclose(fd); return 1; @@ -1366,7 +1372,7 @@ static double getProtonAverage(pMesure self){ /* make a mark */ SNXFormatTime(pTime,131); sprintf(pBueffel,"Starting at list %s at %s",pFile,pTime); - SCWrite(pCon,pBueffel,eStatus); + SCWrite(pCon,pBueffel,eLog); /* skippy! */ for(i = 0; i < iSkip; i++) @@ -1409,7 +1415,7 @@ static double getProtonAverage(pMesure self){ /* we are done */ SNXFormatTime(pTime,131); sprintf(pBueffel,"Finishing list %s at %s",pFile,pTime); - SCWrite(pCon,pBueffel,eStatus); + SCWrite(pCon,pBueffel,eLog); fclose(fd); return 1; diff --git a/moregress.c b/moregress.c index de86e59b..e8f48045 100644 --- a/moregress.c +++ b/moregress.c @@ -200,6 +200,12 @@ static int RGSetDriverPar(void *data, SConnection *pCon, } else if (strcmp(name,"recover") == 0){ self->recover = (int)value; return 1; + } else if(strcmp(name,"hardupperlim") == 0) { + self->fUpper = value; + return 1; + } else if(strcmp(name,"hardlowerlim") == 0){ + self->fLower = value; + return 1; } return 0; } diff --git a/motor.c b/motor.c index 3258b07a..0a2802d1 100644 --- a/motor.c +++ b/motor.c @@ -9,6 +9,10 @@ callback added: Mark Koennecke, August 1997 endscript facility added: Mark Koennecke, August 2002 Modified to support driver parameters, Mark Koennecke, January 2003 + + Reworked to allow for multiple implementations of motors on the same + interface in preparation for second generation motors. + Mark Koennecke, December 2008 Copyright: @@ -115,7 +119,71 @@ self->stopped = 1; return self->pDriver->Halt((void *)self->pDriver); } - + /*--------------------------------------------------------------------------- + MotorCheckBoundary checks for violation of boundary conditions and + transforms from SoftCoordinates to hard coordinates. + */ + +static int MotorCheckBoundaryImpl(pMotor self, float fVal, float *fNew, + char *pError, int iErrLen) + { + float fHard; + float fZero; + char pBueffel[512]; + + assert(self); + + /* check for fixed */ + if(ObVal(self->ParArray,FIX) >= 0) + { + sprintf(pBueffel,"Motor %s is Fixed",self->name); + strncpy(pError,pBueffel,iErrLen); + return 0; /* is this an error? */ + } + + /* check against software boundaries */ + if(fVal > ObVal(self->ParArray,SUPP)) + { + sprintf(pBueffel,"%f violates upper software limit %f on %s", + fVal, ObVal(self->ParArray,SUPP),self->name); + strncpy(pError,pBueffel,iErrLen); + return 0; + } + if(fVal < ObVal(self->ParArray,SLOW)) + { + sprintf(pBueffel,"%f violates lower software limit %f on %s", + fVal,ObVal(self->ParArray,SLOW),self->name ); + strncpy(pError,pBueffel,iErrLen); + return 0; + } + + /* correct for zero point */ + fZero = ObVal(self->ParArray,SZERO); + fZero = -fZero; + fHard = fVal - fZero; + + /* apply sign */ + fHard = fHard*ObVal(self->ParArray,SIGN); + + /* check for hardware limits */ + if(fHard > self->pDriver->fUpper) + { + sprintf(pBueffel,"%f violates upper hardware limit %f on %s", + fVal,self->pDriver->fUpper,self->name); + strncpy(pError,pBueffel,iErrLen); + return 0; + } + if(fHard < self->pDriver->fLower) + { + sprintf(pBueffel,"%f violates lower hardware limit %f on %s", + fVal,self->pDriver->fLower,self->name); + strncpy(pError,pBueffel,iErrLen); + return 0; + } + + *fNew = fHard; + return 1; + } /*--------------------------------------------------------------------------*/ static int MotorLimits(void *sulf, float fVal, char *error, int iErrLen) { @@ -126,8 +194,42 @@ self = (pMotor)sulf; - return MotorCheckBoundary(self,fVal,&fHard,error,iErrLen); + return MotorCheckBoundaryImpl(self,fVal,&fHard,error,iErrLen); } + /* ------------------------------------------------------------------------*/ +static int MotorGetSoftPositionImpl(pMotor self, SConnection *pCon, float *fVal) +{ + int iRet; + float fValue; + + assert(self); + assert(pCon); + + /* get the hard position */ + iRet = MotorGetHardPosition(self,pCon,&fValue); + if(!iRet) + { + *fVal = fValue; + return 0; + } + /* apply zeropoint */ + if(ObVal(self->ParArray,SIGN) < 0.) + { + fValue += ObVal(self->ParArray,SZERO); + } + else + { + fValue -= ObVal(self->ParArray,SZERO); + } + *fVal = fValue; + + /* apply sign */ + /* *fVal = MotorHardToSoftPosition(self,fValue); */ + + *fVal = fValue*ObVal(self->ParArray,SIGN); + + return 1; + } /*---------------------------------------------------------------------------*/ static float MotorGetValue(void *pData, SConnection *pCon) { @@ -135,7 +237,7 @@ float fVal = 0.; assert(pData); - iRet = MotorGetSoftPosition((pMotor)pData,pCon,&fVal); + iRet = MotorGetSoftPositionImpl((pMotor)pData,pCon,&fVal); if(iRet != OKOK) { fVal = -9999999.99; @@ -397,143 +499,22 @@ static void handleMoveCallback(pMotor self, SConnection *pCon) return status; } /*---------------------------------------------------------------------------*/ - pMotor MotorInit(char *drivername, char *name, MotorDriver *pDriv) - { - pMotor pM = NULL; - - assert(drivername); - assert(pDriv); - assert(name); - - /* get memory */ - pM = (pMotor)malloc(sizeof(Motor)); - if(!pM) - { - return NULL; - } - - - /* create and initialize parameters */ - pM->ParArray = ObParCreate(MOTOBPARLENGTH); - if(!pM->ParArray) - { - free(pM); - return NULL; - } - ObParInit(pM->ParArray,SLOW,"softlowerlim",pDriv->fLower,usUser); - ObParInit(pM->ParArray,SUPP,"softupperlim",pDriv->fUpper,usUser); - ObParInit(pM->ParArray,SZERO,"softzero",ZEROINACTIVE,usUser); - ObParInit(pM->ParArray,FIX,"fixed",-1,usUser); - ObParInit(pM->ParArray,INT,"interruptmode",INTCONT,usMugger); - ObParInit(pM->ParArray,PREC,"precision",0.01,usMugger); - ObParInit(pM->ParArray,USRIGHTS,"accesscode",(float)usUser,usMugger); - ObParInit(pM->ParArray,SIGN,"sign",1.0,usMugger); - ObParInit(pM->ParArray,ECOUNT,"failafter",3.0,usMugger); - ObParInit(pM->ParArray,POSCOUNT,"maxretry",3.0,usMugger); - ObParInit(pM->ParArray,IGNOREFAULT,"ignorefault",0.0,usMugger); - ObParInit(pM->ParArray,MOVECOUNT,"movecount",10.0,usMugger); - pDriv->GetPosition(pDriv,&(pM->fPosition)); - pM->fTarget = pM->fPosition; - pM->endScriptID = 0; - - /* copy arguments */ - pM->pDriver = pDriv; - pM->drivername = strdup(drivername); - pM->name = strdup(name); - - - /* initialise object descriptor */ - pM->pDescriptor = CreateDescriptor("Motor"); - if(!pM->pDescriptor) - { - ObParDelete(pM->ParArray); - free(pM); - return NULL; - } - pM->pDescriptor->GetInterface = MotorGetInterface; - pM->pDescriptor->SaveStatus = MotorSaveStatus; - - /* initialise Drivable interface */ - pM->pDrivInt = CreateDrivableInterface(); - if(!pM->pDrivInt) - { - DeleteDescriptor(pM->pDescriptor); - ObParDelete(pM->ParArray); - free(pM); - return NULL; - } - pM->pDrivInt->SetValue = MotorRun; - pM->pDrivInt->CheckLimits = MotorLimits; - pM->pDrivInt->CheckStatus = MotorStatus; - pM->pDrivInt->GetValue = MotorGetValue; - pM->pDrivInt->Halt = MotorHalt; - - /* initialise callback interface */ - pM->pCall = CreateCallBackInterface(); - if(!pM->pCall) - { - MotorKill(pM); - return NULL; - } - - /* done */ - return pM; - } +int MotorGetPar(pMotor self, char *name, float *fVal) +{ + return self->MotorGetPar(self,name,fVal); +} +/*---------------------------------------------------------------------------*/ +int MotorSetPar(pMotor self, SConnection *pCon, char *name, float fVal) +{ + return self->MotorSetPar(self,pCon,name,fVal); +} +/*---------------------------------------------------------------------------*/ +int MotorGetHardPosition(pMotor self,SConnection *pCon, float *fVal) +{ + return self->MotorGetHardPosition(self, pCon, fVal); +} /*--------------------------------------------------------------------------*/ - -extern void KillPiPiezo(void *pData); - - void MotorKill(void *self) - { - pMotor pM; - assert(self); - - pM = (pMotor)self; - - /* MotorHalt(pM); */ - - if(pM->name) - free(pM->name); - - if(pM->pDrivInt) - { - free(pM->pDrivInt); - } - - if(pM->pCall) - { - DeleteCallBackInterface(pM->pCall); - } - - /* kill driver */ - if(pM->drivername) - { - if(pM->pDriver->KillPrivate != NULL) - { - pM->pDriver->KillPrivate(pM->pDriver); - if(pM->pDriver->name != NULL) - { - free(pM->pDriver->name); - } - free(pM->pDriver); - } - free(pM->drivername); - } - - /* get rid of parameter space */ - if(pM->ParArray) - { - ObParDelete(pM->ParArray); - } - - /* kill Descriptor */ - DeleteDescriptor(pM->pDescriptor); - - free(pM); - - } -/*--------------------------------------------------------------------------*/ - int MotorGetPar(pMotor self, char *name, float *fVal) +static int MotorGetParImpl(pMotor self, char *name, float *fVal) { ObPar *pPar = NULL; assert(self); @@ -585,7 +566,7 @@ extern void KillPiPiezo(void *pData); } } /*---------------------------------------------------------------------------*/ - int MotorSetPar(pMotor self, SConnection *pCon, char *name, float fVal) +static int MotorSetParImpl(pMotor self, SConnection *pCon, char *name, float fVal) { ObPar *pPar = NULL; char pBueffel[512]; @@ -657,73 +638,61 @@ extern void KillPiPiezo(void *pData); return iRet; } -/*--------------------------------------------------------------------------- - MotorCheckBoundary checks for violation of boundary conditions and - transforms from SoftCoordinates to hard coordinates. - */ - - int MotorCheckBoundary(pMotor self, float fVal, float *fNew, - char *pError, int iErrLen) +/*------------------------------------------------------------------------*/ +static int MotorGetHardPositionImpl(pMotor self,SConnection *pCon, float *fHard) { - float fHard; - float fZero; - char pBueffel[512]; + int iRet, iCode; + float fVal; + char pBueffel[512],pError[256]; + + assert(self); + assert(pCon); - assert(self); - - /* check for fixed */ - if(ObVal(self->ParArray,FIX) >= 0) + iRet = self->pDriver->GetPosition(self->pDriver,&fVal); + if(iRet == OKOK) /* all went well, the exception */ { - sprintf(pBueffel,"Motor %s is Fixed",self->name); - strncpy(pError,pBueffel,iErrLen); - return 0; /* is this an error? */ + *fHard = fVal; + return 1; } - - /* check against software boundaries */ - if(fVal > ObVal(self->ParArray,SUPP)) - { - sprintf(pBueffel,"%f violates upper software limit %f on %s", - fVal, ObVal(self->ParArray,SUPP),self->name); - strncpy(pError,pBueffel,iErrLen); - return 0; + else /* a problem, the usual case: try fix the problem */ + { /* no point in trying this three times */ + self->pDriver->GetError(self->pDriver,&iCode, pError,255); + iRet = self->pDriver->TryAndFixIt(self->pDriver,iCode, fVal); + sprintf(pBueffel,"WARNING: Trying to fix %s",pError); + SCWrite(pCon,pBueffel,eWarning); + switch(iRet) + { + case MOTFAIL: + sprintf(pBueffel,"ERROR: cannot fix motor %s", + self->name); + SCWrite(pCon,pBueffel,eError); + SCSetInterrupt(pCon,(int)ObVal(self->ParArray,INT)); + *fHard = fVal; + return 0; + case MOTOK: + case MOTREDO: + iRet = self->pDriver->GetPosition(self->pDriver,&fVal); + if(iRet) + { + *fHard = fVal*ObVal(self->ParArray,SIGN); + return 1; + } + else + { + sprintf(pBueffel,"ERROR: cannot fix motor %s", + self->name); + SCSetInterrupt(pCon,(int)ObVal(self->ParArray,INT)); + SCWrite(pCon,pBueffel,eError); + *fHard = fVal; + return 0; + } + } } - if(fVal < ObVal(self->ParArray,SLOW)) - { - sprintf(pBueffel,"%f violates lower software limit %f on %s", - fVal,ObVal(self->ParArray,SLOW),self->name ); - strncpy(pError,pBueffel,iErrLen); - return 0; - } - - /* correct for zero point */ - fZero = ObVal(self->ParArray,SZERO); - fZero = -fZero; - fHard = fVal - fZero; - - /* apply sign */ - fHard = fHard*ObVal(self->ParArray,SIGN); - - /* check for hardware limits */ - if(fHard > self->pDriver->fUpper) - { - sprintf(pBueffel,"%f violates upper hardware limit %f on %s", - fVal,self->pDriver->fUpper,self->name); - strncpy(pError,pBueffel,iErrLen); - return 0; - } - if(fHard < self->pDriver->fLower) - { - sprintf(pBueffel,"%f violates lower hardware limit %f on %s", - fVal,self->pDriver->fLower,self->name); - strncpy(pError,pBueffel,iErrLen); - return 0; - } - - *fNew = fHard; - return 1; - } + *fHard = fVal*ObVal(self->ParArray,SIGN); + return 0; + } /*---------------------------------------------------------------------------*/ - long MotorRun(void *sulf, SConnection *pCon, float fNew) +static long MotorRunImpl(void *sulf, SConnection *pCon, float fNew) { float fHard; int i, iRet, iCode; @@ -748,7 +717,7 @@ extern void KillPiPiezo(void *pData); } /* check boundaries first */ - iRet = MotorCheckBoundary(self,fNew,&fHard,pError,131); + iRet = MotorCheckBoundaryImpl(self,fNew,&fHard,pError,131); if(!iRet) { snprintf(pBueffel,511,"ERROR: %s",pError); @@ -824,59 +793,171 @@ extern void KillPiPiezo(void *pData); } return OKOK; } -/*------------------------------------------------------------------------*/ - int MotorGetHardPosition(pMotor self,SConnection *pCon, float *fHard) +/*---------------------------------------------------------------------------*/ + pMotor MotorInit(char *drivername, char *name, MotorDriver *pDriv) { - int iRet, iCode; - float fVal; - char pBueffel[512],pError[256]; - - assert(self); - assert(pCon); - - iRet = self->pDriver->GetPosition(self->pDriver,&fVal); - if(iRet == OKOK) /* all went well, the exception */ + pMotor pM = NULL; + + assert(drivername); + assert(pDriv); + assert(name); + + /* get memory */ + pM = (pMotor)malloc(sizeof(Motor)); + if(!pM) { - *fHard = fVal; - return 1; + return NULL; } - else /* a problem, the usual case: try fix the problem */ - { /* no point in trying this three times */ - self->pDriver->GetError(self->pDriver,&iCode, pError,255); - iRet = self->pDriver->TryAndFixIt(self->pDriver,iCode, fVal); - sprintf(pBueffel,"WARNING: Trying to fix %s",pError); - SCWrite(pCon,pBueffel,eWarning); - switch(iRet) + + + /* create and initialize parameters */ + pM->ParArray = ObParCreate(MOTOBPARLENGTH); + if(!pM->ParArray) + { + free(pM); + return NULL; + } + ObParInit(pM->ParArray,SLOW,"softlowerlim",pDriv->fLower,usUser); + ObParInit(pM->ParArray,SUPP,"softupperlim",pDriv->fUpper,usUser); + ObParInit(pM->ParArray,SZERO,"softzero",ZEROINACTIVE,usUser); + ObParInit(pM->ParArray,FIX,"fixed",-1,usUser); + ObParInit(pM->ParArray,INT,"interruptmode",INTCONT,usMugger); + ObParInit(pM->ParArray,PREC,"precision",0.01,usMugger); + ObParInit(pM->ParArray,USRIGHTS,"accesscode",(float)usUser,usMugger); + ObParInit(pM->ParArray,SIGN,"sign",1.0,usMugger); + ObParInit(pM->ParArray,ECOUNT,"failafter",3.0,usMugger); + ObParInit(pM->ParArray,POSCOUNT,"maxretry",3.0,usMugger); + ObParInit(pM->ParArray,IGNOREFAULT,"ignorefault",0.0,usMugger); + ObParInit(pM->ParArray,MOVECOUNT,"movecount",10.0,usMugger); + pDriv->GetPosition(pDriv,&(pM->fPosition)); + pM->fTarget = pM->fPosition; + pM->endScriptID = 0; + + /* copy arguments */ + pM->pDriver = pDriv; + pM->drivername = strdup(drivername); + pM->name = strdup(name); + + + /* initialise object descriptor */ + pM->pDescriptor = CreateDescriptor("Motor"); + if(!pM->pDescriptor) + { + ObParDelete(pM->ParArray); + free(pM); + return NULL; + } + pM->pDescriptor->GetInterface = MotorGetInterface; + pM->pDescriptor->SaveStatus = MotorSaveStatus; + + /* initialise Drivable interface */ + pM->pDrivInt = CreateDrivableInterface(); + if(!pM->pDrivInt) + { + DeleteDescriptor(pM->pDescriptor); + ObParDelete(pM->ParArray); + free(pM); + return NULL; + } + pM->pDrivInt->SetValue = MotorRunImpl; + pM->pDrivInt->CheckLimits = MotorLimits; + pM->pDrivInt->CheckStatus = MotorStatus; + pM->pDrivInt->GetValue = MotorGetValue; + pM->pDrivInt->Halt = MotorHalt; + + /* initialize function pointers */ + pM->MotorGetPar = MotorGetParImpl; + pM->MotorSetPar = MotorSetParImpl; + pM->MotorGetHardPosition = MotorGetHardPositionImpl; + + /* initialise callback interface */ + pM->pCall = CreateCallBackInterface(); + if(!pM->pCall) + { + MotorKill(pM); + return NULL; + } + + /* done */ + return pM; + } +/*--------------------------------------------------------------------------*/ +long MotorRun(void *data, SConnection *pCon, float fNew) +{ + pMotor self = (pMotor)data; + + return self->pDrivInt->SetValue(data,pCon,fNew); +} +/*--------------------------------------------------------------------------*/ +int MotorCheckBoundary(pMotor self, float fVal, float *fHard, + char *error, int iErrLen) +{ + return self->pDrivInt->CheckLimits(self,fVal,error,iErrLen); +} +/*--------------------------------------------------------------------------*/ +int MotorGetSoftPosition(pMotor self,SConnection *pCon, float *fVal) +{ + float myVal; + myVal = self->pDrivInt->GetValue(self,pCon); + *fVal = myVal; + if(myVal <= -9999999.99){ + return 0; + } else { + return 1; + } +} +/*--------------------------------------------------------------------------*/ +extern void KillPiPiezo(void *pData); + + void MotorKill(void *self) + { + pMotor pM; + assert(self); + + pM = (pMotor)self; + + /* MotorHalt(pM); */ + + if(pM->name) + free(pM->name); + + if(pM->pDrivInt) + { + free(pM->pDrivInt); + } + + if(pM->pCall) + { + DeleteCallBackInterface(pM->pCall); + } + + /* kill driver */ + if(pM->drivername) + { + if(pM->pDriver->KillPrivate != NULL) { - case MOTFAIL: - sprintf(pBueffel,"ERROR: cannot fix motor %s", - self->name); - SCWrite(pCon,pBueffel,eError); - SCSetInterrupt(pCon,(int)ObVal(self->ParArray,INT)); - *fHard = fVal; - return 0; - case MOTOK: - case MOTREDO: - iRet = self->pDriver->GetPosition(self->pDriver,&fVal); - if(iRet) - { - *fHard = fVal*ObVal(self->ParArray,SIGN); - return 1; - } - else - { - sprintf(pBueffel,"ERROR: cannot fix motor %s", - self->name); - SCSetInterrupt(pCon,(int)ObVal(self->ParArray,INT)); - SCWrite(pCon,pBueffel,eError); - *fHard = fVal; - return 0; - } - } - } - *fHard = fVal*ObVal(self->ParArray,SIGN); - return 0; - } + pM->pDriver->KillPrivate(pM->pDriver); + if(pM->pDriver->name != NULL) + { + free(pM->pDriver->name); + } + free(pM->pDriver); + } + free(pM->drivername); + } + + /* get rid of parameter space */ + if(pM->ParArray) + { + ObParDelete(pM->ParArray); + } + + /* kill Descriptor */ + DeleteDescriptor(pM->pDescriptor); + + free(pM); + + } /*------------------------------------------------------------------------*/ float MotorHardToSoftPosition(pMotor self, float fValue) { @@ -892,40 +973,6 @@ extern void KillPiPiezo(void *pData); /* apply sign */ return fValue*ObVal(self->ParArray,SIGN); } -/* ------------------------------------------------------------------------*/ - int MotorGetSoftPosition(pMotor self, SConnection *pCon, float *fVal) - { - int iRet; - float fValue; - - assert(self); - assert(pCon); - - /* get the hard position */ - iRet = MotorGetHardPosition(self,pCon,&fValue); - if(!iRet) - { - *fVal = fValue; - return 0; - } - /* apply zeropoint */ - if(ObVal(self->ParArray,SIGN) < 0.) - { - fValue += ObVal(self->ParArray,SZERO); - } - else - { - fValue -= ObVal(self->ParArray,SZERO); - } - *fVal = fValue; - - /* apply sign */ - /* *fVal = MotorHardToSoftPosition(self,fValue); */ - - *fVal = fValue*ObVal(self->ParArray,SIGN); - - return 1; - } /*---------------------------------------------------------------------------*/ int MotorCheckPosition(void *sulf, SConnection *pCon) { @@ -1079,9 +1126,9 @@ extern MotorDriver *MakePiPiezo(Tcl_Interp *pTcl, char *pArray); sprintf(pBueffel,"Parameter Listing for motor %s",self->name); SCWrite(pCon,pBueffel,eValue); sprintf(pBueffel,"%s.Position = %f\n", self->name,self->fPosition); - SCWrite(pCon,pBueffel,eStatus); + SCWrite(pCon,pBueffel,eValue); sprintf(pBueffel,"%s.TargetPosition = %f\n", self->name,self->fTarget); - SCWrite(pCon,pBueffel,eStatus); + SCWrite(pCon,pBueffel,eValue); snprintf(pBueffel,511,"%s.hardlowerlim = %f",self->name, self->pDriver->fLower); @@ -1093,7 +1140,7 @@ extern MotorDriver *MakePiPiezo(Tcl_Interp *pTcl, char *pArray); { sprintf(pBueffel,"%s.%s = %f\n",self->name, self->ParArray[i].name,self->ParArray[i].fVal); - SCWrite(pCon,pBueffel,eStatus); + SCWrite(pCon,pBueffel,eValue); } /* @@ -1129,11 +1176,14 @@ extern MotorDriver *MakePiPiezo(Tcl_Interp *pTcl, char *pArray); { free(self->pName); } + if(self->pCon != NULL) + { + SCDeleteConnection(self->pCon); + } free(self); } /*------------------- The CallBack function for interest ------------------*/ - static int InterestCallback(int iEvent, void *pEvent, void *pUser, - commandContext cc) + static int InterestCallback(int iEvent, void *pEvent, void *pUser) { pMotInfo pInfo = NULL; char pBueffel[80]; @@ -1145,11 +1195,15 @@ extern MotorDriver *MakePiPiezo(Tcl_Interp *pTcl, char *pArray); psCall = (MotCallback *)pEvent; pInfo = (MotInfo *)pUser; + if(!SCisConnected(pInfo->pCon)){ + return -1; + } + if (pInfo->lastValue != psCall->fVal) { pInfo->lastValue = psCall->fVal; (pInfo->pCon)->conEventType=POSITION; sprintf(pBueffel,"%s.position = %f ", pInfo->pName, pInfo->lastValue); - SCWriteInContext(pInfo->pCon,pBueffel,eEvent,cc); + SCWrite(pInfo->pCon,pBueffel,eEvent); } return 1; } @@ -1162,8 +1216,7 @@ extern MotorDriver *MakePiPiezo(Tcl_Interp *pTcl, char *pArray); } } /*------------------------ The endscript callback function ----------------*/ - static int EndScriptCallback(int iEvent, void *pEvent, void *pUser, - commandContext cc) + static int EndScriptCallback(int iEvent, void *pEvent, void *pUser) { char *pScript = NULL; MotCallback *psCall; @@ -1269,7 +1322,7 @@ extern MotorDriver *MakePiPiezo(Tcl_Interp *pTcl, char *pArray); return 0; } pMoti->pName = strdup(argv[0]); - pMoti->pCon = pCon; + pMoti->pCon = SCCopyConnection(pCon); iRet = MotorGetSoftPosition(self,pCon,&fValue); if(!iRet) { @@ -1280,16 +1333,15 @@ extern MotorDriver *MakePiPiezo(Tcl_Interp *pTcl, char *pArray); } pMoti->lastValue = fValue; - lID = RegisterCallback(self->pCall, SCGetContext(pCon),MOTDRIVE, InterestCallback, + lID = RegisterCallback(self->pCall, MOTDRIVE, InterestCallback, pMoti, KillInfo); - SCRegister(pCon,pSics, self->pCall,lID); DeleteTokenList(pList); SCSendOK(pCon); return 1; } else if(strcmp(pCurrent->text,"uninterest") == 0) { - RemoveCallback2(self->pCall,pCon); + RemoveCallbackCon(self->pCall,pCon); SCSendOK(pCon); DeleteTokenList(pList); return 1; @@ -1312,9 +1364,8 @@ extern MotorDriver *MakePiPiezo(Tcl_Interp *pTcl, char *pArray); return 0; } self->endScriptID = - RegisterCallback(self->pCall, SCGetContext(pCon),MOTEND, EndScriptCallback, + RegisterCallback(self->pCall, MOTEND, EndScriptCallback, strdup(pCurrent->text), KillScript); - SCRegister(pCon,pSics, self->pCall,self->endScriptID); DeleteTokenList(pList); SCSendOK(pCon); return 1; diff --git a/motor.h b/motor.h index 277afb1c..e5f11599 100644 --- a/motor.h +++ b/motor.h @@ -13,13 +13,17 @@ #include "modriv.h" #include "obdes.h" #include "interface.h" +#include "hipadaba.h" #define MOTOBPARLENGTH 12 typedef struct __Motor { - pObjectDescriptor pDescriptor; - ObPar *ParArray; + pObjectDescriptor pDescriptor; + pHdb objectNode; pIDrivable pDrivInt; pICallBack pCall; + int (*MotorSetPar)(struct __Motor *self, SConnection *pCon, char *name, float fVal); + int (*MotorGetPar)(struct __Motor *self, char *name, float *fVal); + int (*MotorGetHardPosition)(struct __Motor *self, SConnection *pCon, float *fVal); char *drivername; char *name; MotorDriver *pDriver; @@ -31,6 +35,10 @@ int retryCount; /* for retries in status */ int posFaultCount; int stopped; + int errorCount; + ObPar *ParArray; + void *pPrivate; + void (*KillPrivate)(void *); } Motor; typedef Motor *pMotor; /*------------------------------------------------------------------------ @@ -50,12 +58,10 @@ typedef struct { long MotorRun(void *self, SConnection *pCon, float fNew); int MotorCheckBoundary(pMotor self, float fVal, float *fHard, char *error, int iErrLen); - int MotorCheckPosition(void *self, SConnection *pCon); /* Where are we ? */ int MotorGetSoftPosition(pMotor self,SConnection *pCon, float *fVal); int MotorGetHardPosition(pMotor self,SConnection *pCon, float *fVal); - float MotorHardToSoftPosition(pMotor self, float fHard); /* creation */ int MotorCreate(SConnection *pCon, SicsInterp *pSics, void *pData, diff --git a/motorsec.c b/motorsec.c new file mode 100644 index 00000000..49dc6aa4 --- /dev/null +++ b/motorsec.c @@ -0,0 +1,749 @@ +/** + * This is the implementation of a second generation motor. A second + * generation motor differs in various aspects from a first generation + * motor though it is functionally equivalent and even adheres to the + * same interface. The differing aspects are: + * - The second generation motor deos not use the ObPar array for parameter storage + * but the Hipadaba parameter system rooted in self->pDes->objectNode. + * - The second generation motor does not use the driver. The second generation motor + * implements some functionality but is largely a shell. Scripts are supposed to add + * more parameters and link to a corresponding ScriptContext object which takes care + * of actual talking to the hardware. + * - The old callback system is also not implemented: third parties which are interested + * to be notified of changes to the motor position shall register a callback. + * + * This also means that many of the fields in the motor data structure are not used in + * this module but are present to support first generation motors. This must be so as we cannot + * replace all existing driver with new ones quickly. Here a list of fields which have no use: + * - pDriver + * - ParArray + * + * We need three different position parameters to keep this under control: + * - the physical value which is the main motor node + * - the targetposition which is is the hardware target where the motor is supposed + * to be + * - The hardposition which is the actual hardware position. This is also the + * one which is responsible for talking to the motor. + * + * Then we need a status parameter which is some text which says what the motor + * is up to. + * + * A less obvious use of a callback is the HardUpdateCallback. It automatically + * updates the physical motor position, too. + * + * copyright: see file COPYRIGHT + * + * Mark Koennecke, December 2008 + */ +#include +#include +#include +#include +#include "sics.h" +#include "sicshipadaba.h" +#include "sicsobj.h" +#include "motor.h" +#include "splitter.h" + +#define ABS(x) (x < 0 ? -(x) : (x)) + +/*--------------------------------------------------------------------------*/ +static int SecMotorGetPar(pMotor self, char *name, float *fVal){ + char pBueffel[512]; + hdbValue value;; + int status; + + snprintf(pBueffel,511,"%s ", name); + status = SICSHdbGetPar(self,NULL,pBueffel, &value); + *fVal = (float)value.v.doubleValue; + return status; +} +/*---------------------------------------------------------------------------*/ +static int SecMotorSetPar(pMotor self, SConnection *pCon, char *name, float fVal){ + int status; + hdbValue value; + value = MakeHdbFloat(fVal); + status = SICSHdbSetPar(self, + pCon,name,value); + if(status == 1){ + SCparChange(pCon); + return 1; + } else { + return 0; + } +} +/*-------------------------------------------------------------------------*/ +static void *MotorGetInterfaceSec(void *pData, int iID){ + pMotor self = NULL; + + self = (pMotor)pData; + assert(self); + if(iID == DRIVEID){ + return self->pDrivInt; + } else if(iID == CALLBACKINTERFACE) { + return self->pCall; + } + return NULL; +} +/*---------------------------------------------------------------------------*/ +static long SecMotorRun(void *sulf, SConnection *pCon, float fNew){ + pMotor self = (pMotor)sulf; + hdbValue v; + + v = MakeHdbFloat(fNew); + return SetHipadabaPar(self->pDescriptor->parNode,v,pCon); +} +/*--------------------------------------------------------------------------*/ +static int SecMotorCheckBoundary(pMotor self, float fVal, float *fTarget, + char *pError, int iErrLen){ + double fZero, fixed, lowerlim, upperlim, sign; + float fHard, hupper, hlower; + char pBueffel[512]; + hdbValue v; + + assert(self); + + assert(SICSHdbGetPar(self,NULL, + "fixed",&v) == 1); + fixed = v.v.doubleValue; + assert(SICSHdbGetPar(self,NULL, + "softzero",&v) == 1); + fZero = v.v.doubleValue; + assert(SICSHdbGetPar(self,NULL, + "softlowerlim",&v) == 1); + lowerlim = v.v.doubleValue; + assert(SICSHdbGetPar(self,NULL, + "softupperlim",&v) == 1); + upperlim = v.v.doubleValue; + assert(SICSHdbGetPar(self,NULL, + "sign",&v) == 1); + sign = v.v.doubleValue; + + *fTarget = fVal; + + /* check for fixed */ + if(fixed >= 0){ + sprintf(pBueffel,"Motor %s is Fixed",self->name); + strncpy(pError,pBueffel,iErrLen); + return 0; /* is this an error? */ + } + + /* check against software boundaries */ + if(fVal > upperlim){ + sprintf(pBueffel,"%f violates upper software limit %f on %s", + fVal, upperlim,self->name); + strncpy(pError,pBueffel,iErrLen); + return 0; + } + if(fVal < lowerlim){ + sprintf(pBueffel,"%f violates lower software limit %f on %s", + fVal,lowerlim,self->name ); + strncpy(pError,pBueffel,iErrLen); + return 0; + } + + /* correct for zero point */ + fZero = -fZero; + fHard = fVal - fZero; + + /* apply sign */ + fHard = fHard*sign; + + + /* check for hardware limits */ + SecMotorGetPar(self,"hardlowerlim",&hlower); + SecMotorGetPar(self,"hardupperlim",&hupper); + if(fHard > hupper){ + sprintf(pBueffel,"%f violates upper hardware limit %f on %s", + fVal,hupper,self->name); + strncpy(pError,pBueffel,iErrLen); + return 0; + } + if(fHard < hlower){ + sprintf(pBueffel,"%f violates lower hardware limit %f on %s", + fVal,hlower,self->name); + strncpy(pError,pBueffel,iErrLen); + return 0; + } + + *fTarget = fHard; + return 1; +} +/*--------------------------------------------------------------------------*/ +static int SecMotorLimits(void *sulf, float fVal, char *error, int iErrLen){ + float fHard; + pMotor self; + + assert(sulf); + + self = (pMotor)sulf; + + return SecMotorCheckBoundary(self,fVal,&fHard,error,iErrLen); +} +/*-----------------------------------------------------------------------*/ +static int checkPosition(pMotor self, SConnection *pCon){ + float precision, hard, target, maxretry; + pHdb node = NULL; + + if(SCGetInterrupt(pCon) != eContinue){ + return HWFault; + } + if(self->stopped){ + SCPrintf(pCon,eWarning,"WARNING: %s stopped", self->name); + return HWFault; + } + SecMotorGetPar(self,"hardposition",&hard); + SecMotorGetPar(self,"targetposition",&target); + SecMotorGetPar(self,"precision",&precision); + SecMotorGetPar(self,"maxretry",&maxretry); + if(ABS(target-hard) > precision){ + if(self->retryCount >= (int)maxretry){ + SCPrintf(pCon,eError, + "ERROR: Aborting %s after %d retries, off position by %f", + self->name, (int)maxretry, target - hard); + return HWFault; + } + self->retryCount++; + SCPrintf(pCon,eWarning,"WARNING: %s off position by %f, restarting", + self->name, target-hard); + node = GetHipadabaNode(self->pDescriptor->parNode,"status"); + assert(node != NULL); + UpdateHipadabaPar(node,MakeHdbText("run"), pCon); + node = GetHipadabaNode(self->pDescriptor->parNode,"hardposition"); + assert(node != NULL); + SetHipadabaPar(node,MakeHdbFloat(target), pCon); + return HWBusy; + } + return HWIdle; +} +/*-----------------------------------------------------------------------*/ +static void handleMoveCallback(pMotor self, SConnection *pCon){ + float movecount; + pHdb node = NULL; + hdbValue v; + + SecMotorGetPar(self,"movecount",&movecount); + self->posCount++; + if(self->posCount > (int)movecount){ + node = GetHipadabaNode(self->pDescriptor->parNode,"hardposition"); + GetHipadabaPar(node,&v,pCon); + UpdateHipadabaPar(node,v,pCon); + self->posCount = 0; + } +} +/*-----------------------------------------------------------------------*/ +static int SecMotorStatus(void *sulf, SConnection *pCon){ + pMotor self = NULL; + int status; + pHdb node = NULL; + hdbValue v; + float interrupt; + + assert(sulf); + self = (pMotor)sulf; + + node = GetHipadabaNode(self->pDescriptor->parNode,"status"); + assert(node != NULL); + status = GetHipadabaPar(node,&v,pCon); + + if(status != 1){ + return HWFault; + } + + if(v.v.text == NULL){ + return HWBusy; + } + if(strstr(v.v.text,"idle") != NULL){ + status = checkPosition(self,pCon); + } else if(strstr(v.v.text,"run") != NULL){ + handleMoveCallback(self,pCon); + status = HWBusy; + } else if(strstr(v.v.text,"poserror") != NULL){ + status = checkPosition(self,pCon); + } else if(strstr(v.v.text,"error") != NULL){ + status = HWFault; + } else { + SCPrintf(pCon,eError,"ERROR: unknown motor status %s found", v.v.text); + status = HWFault; + } + /* + * when terminating: force an update of the position. + */ + switch(status){ + case HWFault: + self->posCount = 10000; + handleMoveCallback(self,pCon); + SecMotorGetPar(self,"interrupt",&interrupt); + if(SCGetInterrupt(pCon) < (int)interrupt){ + SCSetInterrupt(pCon,(int)interrupt); + } + self->errorCount++; + break; + case HWIdle: + self->posCount = 10000; + handleMoveCallback(self,pCon); + self->errorCount = 0; + break; + } + return status; +} +/*---------------------------------------------------------------------------*/ +static float SecMotorGetValue(void *pData, SConnection *pCon){ + int status; + pMotor self = (pMotor)pData; + hdbValue v; + + assert(pData); + status = GetHipadabaPar(self->pDescriptor->parNode, &v,pCon); + if(status != 1){ + return -9999999.99; + } else { + return (float)v.v.doubleValue; + } +} +/*------------------------------------------------------------------------*/ +static int SecMotorHalt(void *sulf){ + pMotor self; + pHdb node = NULL, par[0]; + SICSOBJFunc haltFunc = NULL; + int status; + + assert(sulf); + self = (pMotor)sulf; + + node = GetHipadabaNode(self->pDescriptor->parNode,"halt"); + assert(node != NULL); + + haltFunc = (SICSOBJFunc)node->value.v.func; + assert(haltFunc != NULL); + self->stopped = 1; + return haltFunc((pSICSOBJ)self,pServ->dummyCon,node,par,0); +} +/*--------------------------------------------------------------------------*/ +static int SecMotorGetHardPosition(struct __Motor *self, + SConnection *pCon, float *fVal){ + hdbValue v; + int status; + pHdb node = NULL; + + node = GetHipadabaNode(self->pDescriptor->parNode,"hardposition"); + assert(node != NULL); + status = GetHipadabaPar(node,&v,pCon); + *fVal = (float)v.v.doubleValue; + return status; +} +/*---------------------------------------------------------------------------*/ +static void AddMotorPar(pHdb node, int priv, char *name){ + pHdb child = NULL; + + child = MakeSICSHdbPar(name,priv,MakeHdbFloat(.0)); + if(child != NULL){ + SetHdbProperty(child,"__save", "true"); + AddHipadabaChild(node,child,NULL); + } +} +/*---------------------------------------------------------------------------*/ +static float hardToSoftPosition(pMotor self, float hard){ + float sign, zero, fVal; + + SecMotorGetPar(self,"sign", &sign); + SecMotorGetPar(self,"softzero", &zero); + fVal = hard; + if(sign < 0){ + fVal += zero; + } else { + fVal -= zero; + } + fVal *= sign; + return fVal; +} +/*---------------------------------------------------------------------------*/ +static hdbCallbackReturn SecMotorCallback(pHdb node, void *userData, + pHdbMessage message){ + SConnection *pCon = NULL; + pHdbDataMessage mm = NULL; + hdbValue v; + pHdb child = NULL; + pMotor self = NULL; + float fHard, fVal, sign, zero; + char pBueffel[512], pError[132]; + int status; + + self = (pMotor)userData; + assert(self != NULL); + + mm = GetHdbSetMessage(message); + if(mm != NULL){ + pCon = (SConnection *)mm->callData; + v = *(mm->v); + + /* + * check permission + */ + SecMotorGetPar(self,"accesscode",&fVal); + if(!SCMatchRights(pCon,(int)fVal)){ + sprintf(pBueffel,"ERROR: You are not authorised to move motor %s", + self->name); + SCWrite(pCon,pBueffel,eError); + SCSetInterrupt(pCon,eAbortBatch); + return hdbAbort; + } + + /* + * check limits + */ + status = SecMotorCheckBoundary(self,(float)v.v.doubleValue, + &fHard,pError,131); + if(status != 1){ + snprintf(pBueffel,511,"ERROR: %s",pError); + SCWrite(pCon,pBueffel,eWarning); + SCSetInterrupt(pCon,eAbortOperation); + return hdbAbort; + } + + /* + * check the motor bad flag + */ + SecMotorGetPar(self,"ignorefault",&fVal); + if((int)fVal > 0){ + snprintf(pBueffel,511,"WARNING: motor %s is unreliable", + self->name); + SCWrite(pCon,pBueffel,eWarning); + self->errorCount = 0; + } + + /* + * check for alarm condition + */ + SecMotorGetPar(self,"failafter",&fVal); + if(self->errorCount > (int)fVal){ + /* big alarm */ + ServerWriteGlobal("ERROR: !!! MOTOR ALARM !!! MOTOR ALARM !!!",eError); + sprintf(pBueffel, + "ERROR: too many position errors counted at motor %s", + self->name); + ServerWriteGlobal(pBueffel,eError); + SCSetInterrupt(pCon,eAbortBatch); + self->errorCount = 0; + return hdbAbort; + } + + self->posFaultCount = 0; + self->retryCount = 0; + self->stopped = 0; + self->posCount = 0; + child = GetHipadabaNode(self->pDescriptor->parNode,"targetposition"); + UpdateHipadabaPar(child,MakeHdbFloat(fHard),pCon); + child = GetHipadabaNode(self->pDescriptor->parNode,"status"); + UpdateHipadabaPar(child,MakeHdbText("run"), pCon); + child = GetHipadabaNode(self->pDescriptor->parNode,"hardposition"); + SetHipadabaPar(child,MakeHdbFloat(fHard), pCon); + + return hdbContinue; + } + + mm = GetHdbGetMessage(message); + if(mm != NULL){ + pCon = (SConnection *)mm->callData; + SecMotorGetPar(self,"hardposition", &fVal); + fVal = hardToSoftPosition(self,fVal); + node->value.v.doubleValue = fVal; + mm->v->v.doubleValue = fVal; + return hdbContinue; + } + + return hdbContinue; +} +/*--------------------------------------------------------------------------*/ +static hdbCallbackReturn HardUpdateCallback(pHdb node, void *userData, + pHdbMessage message){ + pHdbDataMessage mm = NULL; + pMotor self = (pMotor)userData; + float fVal; + hdbValue v; + + assert(self != NULL); + + mm = GetHdbUpdateMessage(message); + if(mm != NULL){ + v = *mm->v; + fVal = hardToSoftPosition(self,(float)v.v.doubleValue); + v.v.doubleValue = fVal; + UpdateHipadabaPar(self->pDescriptor->parNode, v, mm->callData); + return hdbContinue; + } + return hdbContinue; +} +/*--------------------------------------------------------------------------*/ +static hdbCallbackReturn SecMotorSignCallback(pHdb node, void *userData, + pHdbMessage message){ + pMotor self = NULL; + SConnection *pCon = NULL; + pHdb zero = NULL; + double value; + pHdbDataMessage mm = NULL; + float limit; + hdbValue v; + + self = (pMotor)userData; + + mm = GetHdbSetMessage(message); + if(mm != NULL){ + pCon = (SConnection *)mm->callData; + if(!SCMatchRights(pCon,usMugger)){ + return hdbAbort; + } + v = *mm->v; + if(ABS(v.v.doubleValue) - 1. > .01){ + if(pCon!= NULL){ + SCWrite(pCon,"ERROR: invalid sign value",eError); + return hdbAbort; + } + } + SecMotorGetPar(self,"softlowerlim",&limit); + limit *= v.v.doubleValue; + SecMotorSetPar(self,pCon,"softlowerlim",limit); + SecMotorGetPar(self,"softupperlim",&limit); + limit *= v.v.doubleValue; + SecMotorSetPar(self,pCon,"softupperlim",limit); + SecMotorSetPar(self,pCon,"softzero",.0); + UpdateHipadabaPar(node,v,pCon); + return hdbContinue; + } + return hdbContinue; +} +/*---------------------------------------------------------------------------*/ +static hdbCallbackReturn SecMotorZeroCallback(pHdb node, void *userData, + pHdbMessage message){ + pMotor self = NULL; + float limit, oldZero, diff; + SConnection *pCon = NULL; + pHdbDataMessage mm = NULL; + hdbValue v; + + self = (pMotor)userData; + assert(self != NULL); + + mm = GetHdbSetMessage(message); + if(mm != NULL){ + pCon = (SConnection *)mm->callData; + if(!SCMatchRights(pCon,usUser)){ + return hdbAbort; + } + v = *mm->v; + SecMotorGetPar(self,"softzero", &oldZero); + diff = v.v.doubleValue - oldZero; + + SecMotorGetPar(self,"softupperlim",&limit); + limit -= diff; + SecMotorSetPar(self,pCon,"softupperlim",limit); + + SecMotorGetPar(self,"softlowerlim",&limit); + limit -= diff; + SecMotorSetPar(self,pCon,"softlowerlim",limit); + UpdateHipadabaPar(node,v,pCon); + return hdbContinue; + } + return hdbContinue; +} +/*---------------------------------------------------------------------------*/ +pMotor SecMotorInit(char *name){ + pMotor pM = NULL; + pHdb node = NULL, child = NULL; + hdbValue v; + + assert(name); + + /* get memory */ + pM = (pMotor)malloc(sizeof(Motor)); + if(!pM){ + return NULL; + } + memset(pM,0,sizeof(Motor)); + + /* initialise object descriptor */ + pM->pDescriptor = CreateDescriptor("Motor"); + if(!pM->pDescriptor){ + free(pM); + return NULL; + } + pM->pDescriptor->GetInterface = MotorGetInterfaceSec; + pM->pDescriptor->SaveStatus = SaveSICSOBJ; + pM->pDescriptor->parNode = MakeSICSHdbPar(name,usSpy,MakeHdbFloat(.0)); + if(pM->pDescriptor->parNode == NULL){ + free(pM); + return NULL; + } + node = pM->pDescriptor->parNode; + pM->objectNode = node; + AppendHipadabaCallback(pM->pDescriptor->parNode, + MakeHipadabaCallback(SecMotorCallback,pM,NULL)); + + /* copy arguments */ + pM->name = strdup(name); + + /* + * install parameters + */ + child = MakeSICSHdbPar("targetposition",usInternal,MakeHdbFloat(.0)); + if(child == NULL){ + return(NULL); + } + SetHdbProperty(child,"__save", "true"); + + AddHipadabaChild(node,child,NULL); + child = MakeHipadabaNode("hardposition",HIPFLOAT,1); + if(child == NULL){ + return(NULL); + } + AddHipadabaChild(node,child,NULL); + SetHdbProperty(child,"motname", name); + AppendHipadabaCallback(child, + MakeHipadabaCallback(HardUpdateCallback,pM,NULL)); + + child = MakeHipadabaNode("sign",HIPFLOAT, 1); + SetHdbProperty(child,"__save", "true"); + AddHipadabaChild(node,child,NULL); + AppendHipadabaCallback(child, + MakeHipadabaCallback(SecMotorSignCallback,pM,NULL)); + UpdateHipadabaPar(child,MakeHdbFloat(1.),NULL); + + child = MakeHipadabaNode("softzero",HIPFLOAT, 1); + SetHdbProperty(child,"__save", "true"); + AddHipadabaChild(node,child,NULL); + AppendHipadabaCallback(child, + MakeHipadabaCallback(SecMotorZeroCallback,pM,NULL)); + + child = MakeHipadabaNode("hardlowerlim",HIPFLOAT, 1); + AddHipadabaChild(node,child,NULL); + + child = MakeHipadabaNode("hardupperlim",HIPFLOAT, 1); + AddHipadabaChild(node,child,NULL); + + child = MakeSICSHdbPar("softlowerlim",usUser, + MakeHdbFloat(.0)); + SetHdbProperty(child,"__save", "true"); + AddHipadabaChild(node,child,NULL); + + child = MakeSICSHdbPar("softupperlim",usUser, + MakeHdbFloat(.0)); + SetHdbProperty(child,"__save", "true"); + AddHipadabaChild(node,child,NULL); + + child = MakeSICSHdbPar("fixed",usUser, + MakeHdbFloat(-1.)); + SetHdbProperty(child,"__save", "true"); + AddHipadabaChild(node,child,NULL); + + child = MakeSICSHdbPar("interruptmode",usMugger, + MakeHdbFloat(.0)); + SetHdbProperty(child,"__save", "true"); + AddHipadabaChild(node,child,NULL); + + child = MakeSICSHdbPar("precision",usMugger, + MakeHdbFloat(.1)); + SetHdbProperty(child,"__save", "true"); + AddHipadabaChild(node,child,NULL); + + child = MakeSICSHdbPar("accesscode",usMugger, + MakeHdbFloat((double)usUser)); + SetHdbProperty(child,"__save", "true"); + AddHipadabaChild(node,child,NULL); + + child = MakeSICSHdbPar("failafter",usMugger, + MakeHdbFloat((double)3.0)); + SetHdbProperty(child,"__save", "true"); + AddHipadabaChild(node,child,NULL); + + child = MakeSICSHdbPar("maxretry",usMugger, + MakeHdbFloat((double)3.0)); + SetHdbProperty(child,"__save", "true"); + AddHipadabaChild(node,child,NULL); + + child = MakeSICSHdbPar("ignorefault",usMugger, + MakeHdbFloat((double).0)); + SetHdbProperty(child,"__save", "true"); + AddHipadabaChild(node,child,NULL); + + child = MakeSICSHdbPar("movecount",usMugger, + MakeHdbFloat((double)10.0)); + SetHdbProperty(child,"__save", "true"); + AddHipadabaChild(node,child,NULL); + + child = MakeHipadabaNode("status",HIPTEXT,1); + SetHdbProperty(child,"motname", name); + AddHipadabaChild(node,child,NULL); + + pM->endScriptID = 0; + + /* initialise Drivable interface */ + pM->pDrivInt = CreateDrivableInterface(); + if(!pM->pDrivInt){ + DeleteDescriptor(pM->pDescriptor); + free(pM); + return NULL; + } + pM->pDrivInt->SetValue = SecMotorRun; + pM->pDrivInt->CheckLimits = SecMotorLimits; + pM->pDrivInt->CheckStatus = SecMotorStatus; + pM->pDrivInt->GetValue = SecMotorGetValue; + pM->pDrivInt->Halt = SecMotorHalt; + + /* + * initialize motor function pointers + */ + pM->MotorGetPar = SecMotorGetPar; + pM->MotorSetPar = SecMotorSetPar; + pM->MotorGetHardPosition = SecMotorGetHardPosition; + + /* initialise callback interface */ + pM->pCall = CreateCallBackInterface(); + if(!pM->pCall){ + MotorKill(pM); + return NULL; + } + + /* done */ + return pM; + } +/*--------------------------------------------------------------------------*/ +static void SecMotorKill(void *data){ + pMotor self = (pMotor)data; + if(self == NULL){ + return; + } + if(self->name) + free(self->name); + + if(self->pDrivInt){ + free(self->pDrivInt); + } + + if(self->pCall){ + DeleteCallBackInterface(self->pCall); + } + + /* kill Descriptor */ + DeleteDescriptor(self->pDescriptor); + + free(self); +} +/*--------------------------------------------------------------------------*/ +int SecMotorFactory(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]){ + pMotor pNew = NULL; + + if(argc < 2){ + SCWrite(pCon,"ERROR: need name for new motor", eError); + return 0; + } + + pNew = SecMotorInit(argv[1]); + if(pNew == NULL){ + SCWrite(pCon,"ERROR: out of memory creating motor", eError); + return 0; + } + return AddCommand(pSics,argv[1],InterInvokeSICSOBJ, + SecMotorKill,pNew); + +} diff --git a/motorsec.h b/motorsec.h new file mode 100644 index 00000000..68da0be3 --- /dev/null +++ b/motorsec.h @@ -0,0 +1,14 @@ +/** + * This is the header file for the second generation motor object. + * More details in the header of the implementation file. + * + * copyright: see file COPYRIGHT + * + * Mark Koennecke, December 2008 + */ +#ifndef MOTORSEC_H_ +#define MOTORSEC_H_ +int SecMotorFactory(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]); + +#endif /*MOTORSEC_H_*/ diff --git a/multicounter.c b/multicounter.c index 674fd3c3..7b1a9367 100644 --- a/multicounter.c +++ b/multicounter.c @@ -59,9 +59,11 @@ static int MMCCHalt(void *pData){ for(i = 0; i < self->nSlaves; i++){ status = self->slaves[i]->Halt(self->slaveData[i]); + ReleaseCountLock(self->slaves[i]); if(status != OKOK) retVal = status; } + ReleaseCountLock(pCount->pCountInt); return retVal; } /*-------------------------------------------------------------------------*/ @@ -77,9 +79,14 @@ static int MMCCStart(void *pData, SConnection *pCon) } assert(self); + if(!GetCountLock(pCount->pCountInt, pCon)){ + return HWFault; + } + for(i = 0; i < self->nSlaves; i++){ self->slaves[i]->SetCountParameters(self->slaveData[i], pCount->pDriv->fPreset, pCount->pDriv->eMode); + ReleaseCountLock(self->slaves[i]); status = self->slaves[i]->StartCount(self->slaveData[i],pCon); if(status != OKOK){ MMCCHalt(pData); diff --git a/nintf.c b/nintf.c index 42e554e0..acfe1055 100644 --- a/nintf.c +++ b/nintf.c @@ -3,6 +3,8 @@ is an implementation. Mark Koennecke, February 2000 + + Added double version, Mark Koennecke, August 2008 ---------------------------------------------------------------------------*/ #include @@ -24,3 +26,22 @@ } return (float) ip; } +/*-------------------------------------------------------------------*/ + double nintd(double f) + { + double ip, rm, dVal; + double fRes; + + dVal = (double)f; + rm = modf(dVal,&ip); + if(rm < .0)rm = -rm; + if(rm > .5) + { + if(ip < .0) + ip -= 1.; + else + ip += 1.; + + } + return (double) ip; + } diff --git a/nread.c b/nread.c index 438e83f4..49002932 100644 --- a/nread.c +++ b/nread.c @@ -10,7 +10,7 @@ Telnet Functionality added: Mark Koennecke, January 1998 Revamped login to non telnet connection. - Mark Koennecke, October 20000 + Mark Koennecke, October 2000 -----------------------------------------------------------------------------*/ #include @@ -67,6 +67,7 @@ extern int VerifyChannel(mkChannel *self); /* defined in network.c */ int iReadTimeout; int iEnd; long lMagic; + pDynString conList; } NetReader; /*--------------------------------------------------------------------------- The structure used for an item in the Net Reader list of connections @@ -97,7 +98,8 @@ extern int VerifyChannel(mkChannel *self); /* defined in network.c */ memset(pNew,0,sizeof(NetReader)); pNew->iList = LLDcreate(sizeof(NetItem)); - if(pNew->iList < 0) + pNew->conList = CreateDynString(1024,1024); + if(pNew->iList < 0 || pNew->conList == NULL) { free(pNew); return NULL; @@ -121,6 +123,10 @@ extern int VerifyChannel(mkChannel *self); /* defined in network.c */ } LLDdelete(self->iList); + if(self->conList != NULL) + { + DeleteDynString(self->conList); + } free(self); } /*--------------------------------------------------------------------------*/ @@ -208,10 +214,12 @@ extern int VerifyChannel(mkChannel *self); /* defined in network.c */ if(pNew) { /* create connection object */ + /* TODO pRes = SCreateConnection(self->pMain->pSics,pNew,3); + */ if(!pRes) { - SICSLogWrite("Failure to allocate new Connection",eInternal); + SICSLogWrite("Failure to allocate new Connection",eInternal); NETClosePort(pNew); free(pNew); return 0; @@ -370,7 +378,9 @@ extern int VerifyChannel(mkChannel *self); /* defined in network.c */ if(pNew) { /* create connection object */ + /* TODO pRes = SCreateConnection(self->pMain->pSics,pNew,usSpy); + */ if(!pRes) { SICSLogWrite("Failure to allocate new Connection",eInternal); @@ -706,9 +716,6 @@ extern int VerifyChannel(mkChannel *self); /* defined in network.c */ int conCount = 0; char num[50]; IPair *options = NULL; - char buffer[1024]; - int bufferLen; - static int bufferFull=0; self = (pNetRead)pData; assert(self); @@ -723,12 +730,13 @@ extern int VerifyChannel(mkChannel *self); /* defined in network.c */ return 0; } + ANETprocess(); + /* build the select mask */ FD_ZERO(&lMask); iRet = LLDnodePtr2First(self->iList); iCount = 0; - buffer[0] = '\0'; - bufferLen = 0; + DynStringClear(self->conList); while(iRet != 0) { LLDnodeDataTo(self->iList,&NItem); @@ -736,14 +744,10 @@ extern int VerifyChannel(mkChannel *self); /* defined in network.c */ { break; } - snprintf(num,sizeof num, "%d, type %d:", NItem.pSock->sockid, NItem.eType); - if (bufferLen + strlen(num) < sizeof buffer) { - strcpy(buffer + bufferLen, num); - bufferLen += strlen(num); - } else { - if (bufferFull == 0) { - bufferFull = 1; - } + + sprintf(num,"%d, type %d:", NItem.pSock->sockid, NItem.eType); + if(conCount < 100){ + DynStringConcat(self->conList,num); } FD_SET(NItem.pSock->sockid,&lMask); if(NItem.pSock->sockid > iCount) @@ -751,17 +755,20 @@ extern int VerifyChannel(mkChannel *self); /* defined in network.c */ iCount = NItem.pSock->sockid; } conCount++; + if(conCount > 100){ + WriteToCommandLog("WAYTOMANYCONNECTIONS> ", GetCharArray(self->conList)); + } iRet = LLDnodePtr2Next(self->iList); } + + if(conCount > 100){ + WriteToCommandLog("WAYTOMANYCONNECTIONS> ", GetCharArray(self->conList)); + } snprintf(num,sizeof num,"%d", conCount); IFSetOption(pSICSOptions,"ConnectionCount",num); - IFSetOption(pSICSOptions,"ConMask",buffer); + IFSetOption(pSICSOptions,"ConMask",GetCharArray(self->conList)); - if (bufferFull == 1) { - bufferFull = 2; - WriteToCommandLog("BUFFERFULL>",buffer); - } /* the select itself */ tmo.tv_usec = self->iReadTimeout; @@ -1072,5 +1079,348 @@ extern int VerifyChannel(mkChannel *self); /* defined in network.c */ } return 0; } +/*=================================================================================== + * new code to support the ANET network stuff + * =================================================================================*/ +typedef struct { + pDynString command; + int state; + SConnection *pCon; +}CommandCBData, *pCommandCBData; +/*----------------------------------------------------------------------------------*/ +static void killCommandCBData(void *data){ + pCommandCBData self = (pCommandCBData)data; + if(self == NULL){ + return; + } + if(self->command != NULL){ + DeleteDynString(self->command); + } + free(self); +} +/*----------------------------------------------------------------------------------*/ +static int testAndInvokeInterrupt(pCommandCBData self, int handle){ + char *pPtr; + char buffer[512]; + int iInt; + + pPtr = GetCharArray(self->command); + if(strstr(pPtr,"INT1712") != NULL){ + sscanf(pPtr, "%s %d",buffer, &iInt); + if(SCMatchRights(self->pCon,usUser)) { + TaskSignal(pServ->pTasker, SICSINT, &iInt); + snprintf(buffer,512, "INTERRUPT %d issued on sock %d", + iInt,handle); + WriteToCommandLog("SYS>", buffer); + if(iInt == eEndServer){ + TaskStop(pServ->pTasker); + } + } else { + SCWrite(self->pCon, + "ERROR: insufficient privilege to invoke Interrupt", + eError); + } + return 1; + } + return 0; +} +/*----------------------------------------------------------------------------------*/ +static int CommandDataCB(int handle, void *userData){ + pCommandCBData self = (pCommandCBData)userData; + int i, length, status; + char *pPtr = NULL; + + assert(self != NULL); + pPtr = ANETreadPtr(handle,&length); + if(pPtr == NULL){ + return 1; + } + for(i = 0; i < length; i++){ + switch(self->state){ + case COLLECT: + if(pPtr[i] == '\r' || pPtr[i] == '\n'){ + self->state = SKIPTERM; + if(!testAndInvokeInterrupt(self,handle)){ + status = CostaTop(self->pCon->pStack, GetCharArray(self->command)); + if(!status){ + SCWrite(self->pCon,"ERROR: Busy", eError); + } + } + DynStringClear(self->command); + } else { + if(pPtr[i] != '\0'){ + DynStringConcatChar(self->command, pPtr[i]); + } + } + break; + case SKIPTERM: + if(pPtr[i] != '\r' && pPtr[i] != '\n' && pPtr[i] != '\0'){ + DynStringConcatChar(self->command, pPtr[i]); + self->state = COLLECT; + } + break; + } + } + ANETreadConsume(handle, length); + return 1; +} +/*----------------------------------------------------------------------------------*/ +static int CommandAcceptCB(int handle, void *userData){ + SConnection *pCon = NULL; + pCommandCBData usData = NULL; + + pCon = SCreateConnection(pServ->pSics, handle, 3); + usData = malloc(sizeof(CommandCBData)); + if(pCon == NULL || usData == NULL){ + SICSLogWrite("Failure to allocate new Connection",eInternal); + return 0; + } + usData->command = CreateDynString(256,256); + if(usData->command == NULL){ + SICSLogWrite("Failure to allocate new Connection",eInternal); + return 0; + } + usData->pCon = pCon; + usData->state = COLLECT; + TaskRegister(pServ->pTasker, + SCTaskFunction, + SCSignalFunction, + SCDeleteConnection, + pCon, + 1); + ANETsetReadCallback(handle, CommandDataCB, + usData, killCommandCBData); + SCSendOK(pCon); + return 1; +} +/*-----------------------------------------------------------------------*/ + static int ANETTelnetReply(int sockHandle, char code, char cChar) + { + char pReply[3]; + + pReply[0] = IAC; + pReply[1] = code; + pReply[2] = cChar; + + ANETwrite(sockHandle,pReply,3); + return 1; + } +/*-----------------------------------------------------------------------*/ +static int ANETTelnetProcess(int handle, void *usData){ + pCommandCBData self = NULL; + int length, status, i; + int cChar; + char *pPtr = NULL; + char pError[256]; + self = (pCommandCBData)usData; + assert(self != NULL); + + pPtr = ANETreadPtr(handle,&length); + + /* do telnet analysis of the data buffer */ + for(i = 0; i < length; i++){ + cChar = (int)pPtr[i]; +#ifdef TELNETDEBUG + if( (cChar > 48) && (cChar < 128) ){ + printf("char: %c\n",cChar); + } else { + printf("Control: %d\n",cChar); + } +#endif + /* Telnet status switching */ + switch(self->state){ + case tData: + switch(cChar){ + case IAC: + self->state = tIAC; + break; + case '\r': + case '\n': + if(!testAndInvokeInterrupt(self,handle)){ + status = CostaTop(self->pCon->pStack, GetCharArray(self->command)); + if(!status){ + SCWrite(self->pCon,"ERROR: Busy", eError); + } + } + self->state = tCR; + DynStringClear(self->command); + break; + case (char)8: /* backspace */ + DynStringBackspace(self->command); + break; + case (char)0:/* ignore 0 character sent as end of text */ + break; + default: + DynStringConcatChar(self->command,(char)cChar); + break; + + } /* end of tData case */ + break; + case tCR: + if(cChar == '\r' || cChar == '\n' || cChar == '\0'){ + continue; + } else { + self->state = tData; + DynStringConcatChar(self->command,(char)cChar); + } + break; + case tIAC: + switch(cChar) + { + case IAC: + self->state = tData; + break; + case WILL: + self->state = tWill; + break; + case WONT: + self->state = tWont; + break; + case DONT: + self->state = tDont; + break; + case DO: + self->state = tDo; + break; + case EOR: + self->state = tData; + break; + case SB: + self->state = tSB; + break; + case EC: + DynStringBackspace(self->command); + self->state = tData; + break; + case EL: + DynStringClear(self->command); + self->state = tData; + break; + case IP: + SCSetInterrupt(self->pCon,eAbortBatch); + self->state = tData; + break; + default: + self->state = tData; + break; + } /* end of tIAC */ + break; + case tWill: /* we do not do options! */ + ANETTelnetReply(handle,DONT,cChar); + self->state = tData; + break; + case tWont: /* we do not do options! A Wont is sent by the client + if it cannot do a option we requested it to have. As + we do not try to force options, this should not happen + */ + self->state = tData; + break; + case tDo: /* we do not do options! */ + ANETTelnetReply(handle,WONT,cChar); + self->state = tData; + break; + case tDont: /* we do not do options! A Dont is sent by the client + if it cannot do a option we requested it to have. As + we do not try to force options, this should not happen + */ + self->state = tData; + break; + case tSB: /* as we do not have options, we cannot have suboption + negotaitions. Something is seriously wrong when + we are here. It is a protocoll error. However, we + ignore it silently. tSB marks the start of the + subnegotiation. The current character must be the + option code we are dealing with. + */ + self->state = tSE; + break; + case tSE: + /* now we are in the suboption parameter. Normally data + should be copied to a suboption string buffer here + until SE. + */ + switch(cChar) + { + case IAC: + break; + case SE: + self->state = tData; + /* suboption interpretation would go here */ + break; + default: + /* copy data to suboption buffer */ + break; + } + break; + + default: + /* There is something wrong here! */ + sprintf(pError,"ERROR: bad telnet code %d", cChar); + SICSLogWrite(pError,eInternal); + self->state = tData; + break; + + } /* end master swicth */ + } /* end for loop */ + ANETreadConsume(handle,length); + return 1; +} +/*----------------------------------------------------------------------------------*/ +static int TelnetAcceptCB(int handle, void *userData){ + SConnection *pCon = NULL; + pCommandCBData usData = NULL; + pTelTask pTel = NULL; + + pCon = SCreateConnection(pServ->pSics, handle, 3); + usData = malloc(sizeof(CommandCBData)); + if(pCon == NULL || usData == NULL){ + SICSLogWrite("Failure to allocate new Connection",eInternal); + return 0; + } + usData->command = CreateDynString(256,256); + if(usData->command == NULL){ + SICSLogWrite("Failure to allocate new Connection",eInternal); + return 0; + } + usData->pCon = pCon; + usData->state = tData; + /* Create a task object for the telnet connection */ + pTel = CreateTelnet(pCon); + if(!pTel){ + SICSLogWrite("Failure to allocate new Telnet Task Object", + eInternal); + SCDeleteConnection(pCon); + return 0; + } + /* register connection and task */ + pCon->iTelnet = 1; + TaskRegister(pServ->pTasker, + TelnetTask, + TelnetSignal, + DeleteTelnet, + pTel, + 1); + ANETsetReadCallback(handle, ANETTelnetProcess, + usData, killCommandCBData); + SCSendOK(pCon); + return 1; +} +/*------------------------------------------------------------------------------------*/ +static void NREADlog(int level, char *txt, void *userData){ + puts(txt); +} +/*------------------------------------------------------------------------------------*/ +int NetReadInstallANETPort(pNetRead self, eNRType eType, int iPort){ + ANETsetLog(NREADlog,NULL); + switch(eType){ + case naccept: + return ANETopenServerPort(iPort,CommandAcceptCB,NULL); + break; + case taccept: + return ANETopenServerPort(iPort,TelnetAcceptCB,NULL); + break; + } + return 0; +} diff --git a/nread.h b/nread.h index ea4cebda..084d178c 100644 --- a/nread.h +++ b/nread.h @@ -32,5 +32,7 @@ int NetReadWait4Data(pNetRead self, int iSocket); int NetReadReadable(pNetRead self, int iSocket); int NetReadResetUser(pNetRead self, int iSocket); +/*--------------------------------------------------------------------------*/ + int NetReadInstallANETPort(pNetRead self, eNRType eType, int iPort); #endif diff --git a/nread.tex b/nread.tex index 63df11cc..fd81c227 100644 --- a/nread.tex +++ b/nread.tex @@ -11,11 +11,11 @@ through a command channel A prior version of SICS had a select system call for each of these cases. It was found, that the code spent most of its time in the select system call -thus intrdoducing a major performance problem. +thus introducing a major performance problem. The select system call can handle more then one file descriptor in one call. This is exactly what this module handles. It does a global select on -all open sockets and forwards any pending data to approriate handlers. +all open sockets and forwards any pending data to appropriate handlers. This scheme brought a drastic performance improvement. @@ -25,13 +25,13 @@ differently: A connection request will be validated, a new connection object will be created and a new task for this connection object will be started. -A command will be placed in the apropriate command stack for the task +A command will be placed in the appropriate command stack for the task belonging to this connection to work on in a later stage. The netreader will also take care that all commands are complete, this is the terminator \verb+\n+ or \verb+\r+ has been sent. Both forms of interrupt will be interpreted and a suitable signal -will be sent to all runing tasks if the interrupt request is valid. +will be sent to all running tasks if the interrupt request is valid. In order to perform his tasks the network reader needs to maintain a list of all open sockets and their types. Additionally it needs to know about the @@ -61,6 +61,11 @@ come in on a user socket. This function is problematic with dynamically creates and deleted objects such as environment device objects. Its use is therefore no longer recommended. +In January 2009 a new asynchronous I/O structure was devised. This makes most of +NetReader obsolete. However, it was decided to keep the old structure for the +time being. A new function, NetReadInstallANETPort was added to install server +ports for the new system. + Thus the interface looks like this: \begin{flushleft} \small @@ -88,7 +93,9 @@ $\langle$nrint {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@ int NetReadWait4Data(pNetRead self, int iSocket);@\\ \mbox{}\verb@ int NetReadReadable(pNetRead self, int iSocket);@\\ \mbox{}\verb@ int NetReadResetUser(pNetRead self, int iSocket);@\\ -\mbox{}\verb@@$\diamond$ +\mbox{}\verb@/*--------------------------------------------------------------------------*/@\\ +\mbox{}\verb@ int NetReadInstallANETPort(pNetRead self, eNRType eType, int iPort); @\\ +\mbox{}\verb@@$\Diamond$ \end{list} \vspace{-1ex} \footnotesize\addtolength{\baselineskip}{-1ex} @@ -153,7 +160,7 @@ if not. \mbox{}\verb@#define SICSNETREADER@\\ \mbox{}\verb@@$\langle$nrint {\footnotesize ?}$\rangle$\verb@@\\ \mbox{}\verb@#endif@\\ -\mbox{}\verb@@$\diamond$ +\mbox{}\verb@@$\Diamond$ \end{list} \vspace{-2ex} \end{minipage}\\[4ex] diff --git a/nread.w b/nread.w index 6279c8c3..f9c1fba2 100644 --- a/nread.w +++ b/nread.w @@ -11,11 +11,11 @@ through a command channel A prior version of SICS had a select system call for each of these cases. It was found, that the code spent most of its time in the select system call -thus intrdoducing a major performance problem. +thus introducing a major performance problem. The select system call can handle more then one file descriptor in one call. This is exactly what this module handles. It does a global select on -all open sockets and forwards any pending data to approriate handlers. +all open sockets and forwards any pending data to appropriate handlers. This scheme brought a drastic performance improvement. @@ -25,13 +25,13 @@ differently: A connection request will be validated, a new connection object will be created and a new task for this connection object will be started. -A command will be placed in the apropriate command stack for the task +A command will be placed in the appropriate command stack for the task belonging to this connection to work on in a later stage. The netreader will also take care that all commands are complete, this is the terminator \verb+\n+ or \verb+\r+ has been sent. Both forms of interrupt will be interpreted and a suitable signal -will be sent to all runing tasks if the interrupt request is valid. +will be sent to all running tasks if the interrupt request is valid. In order to perform his tasks the network reader needs to maintain a list of all open sockets and their types. Additionally it needs to know about the @@ -61,6 +61,11 @@ come in on a user socket. This function is problematic with dynamically creates and deleted objects such as environment device objects. Its use is therefore no longer recommended. +In January 2009 a new asynchronous I/O structure was devised. This makes most of +NetReader obsolete. However, it was decided to keep the old structure for the +time being. A new function, NetReadInstallANETPort was added to install server +ports for the new system. + Thus the interface looks like this: @d nrint @{ @@ -83,6 +88,8 @@ Thus the interface looks like this: int NetReadWait4Data(pNetRead self, int iSocket); int NetReadReadable(pNetRead self, int iSocket); int NetReadResetUser(pNetRead self, int iSocket); +/*--------------------------------------------------------------------------*/ + int NetReadInstallANETPort(pNetRead self, eNRType eType, int iPort); @} This starts off with the definition of a data type for the net reader and an diff --git a/nserver.c b/nserver.c index de27ba07..de87b13a 100644 --- a/nserver.c +++ b/nserver.c @@ -213,6 +213,7 @@ IFDeleteOptions(pSICSOptions); return 0; } + /* self->pServerPort = NETOpenPort(iPort); if(!self->pServerPort) { @@ -222,7 +223,9 @@ return 0; } NetReadRegister(pReader, self->pServerPort, naccept, NULL); - + */ + NetReadInstallANETPort(pReader,naccept, iPort); + /* the device executor */ openDevexecLog(); DevexecLog("START","SICS"); @@ -273,7 +276,7 @@ /* install telnet port */ InstallTelnet(); - + /* If the restore file has not been loaded, do so now */ if(!hasRestored()) { diff --git a/nxscript.c b/nxscript.c index a97178d2..dd02c6d6 100644 --- a/nxscript.c +++ b/nxscript.c @@ -8,6 +8,7 @@ Mark Koennecke, February 2003 Mark Koennecke, January 2004 + added putHdb and putHdbSlab, Mark Koennecke, December 2008 ------------------------------------------------------------------------*/ #include #include @@ -30,6 +31,7 @@ #include "nxdict.h" #include "nxscript.h" #include "sicsdata.h" +#include "sicshipadaba.h" extern char *trim(char *str); @@ -96,7 +98,7 @@ char *makeFilename(SicsInterp *pSics, SConnection *pCon) { if(dir == NULL){ mkdir(pRes,S_IRWXU | S_IRGRP | S_IXGRP); snprintf(pBueffel,255,"Creating dir: %s", pRes); - SCWrite(pCon,pBueffel,eWarning); + SCWrite(pCon,pBueffel,eLog); } else { closedir(dir); } @@ -126,6 +128,28 @@ void changeExtension(char *filename, char *newExtension){ assert(strlen(pPtr) >= strlen(newExtension)); strcpy(pPtr,newExtension); } +/*----------------------------------------------------------------------*/ +static int listToArray(SicsInterp *pSics, char *list, + int intar[NX_MAXRANK]){ + int argc, status, i, val; + CONST char **argv; + Tcl_Interp *pTcl = InterpGetTcl(pSics); + + status = Tcl_SplitList(pTcl, list, &argc, &argv); + if(status != TCL_OK){ + return status; + } + + for(i = 0; i < argc; i++){ + status = Tcl_GetInt(pTcl,argv[i],&val); + if(status != TCL_OK){ + return status; + } + intar[i] = val; + } + Tcl_Free((char *)argv); + return TCL_OK; +} /*======================== Action =======================================*/ static int handleFileOperations(SConnection *pCon, pNXScript self, int argc, char *argv[]){ @@ -209,7 +233,7 @@ static void putMotor(SConnection *pCon, SicsInterp *pSics, pNXScript self, if(argc < 4){ SCWrite(pCon,"ERROR: insufficient number of arguments to putmotor", - eError); + eLogError); return; } @@ -219,7 +243,7 @@ static void putMotor(SConnection *pCon, SicsInterp *pSics, pNXScript self, brumm = (pMotor)FindCommandData(pSics,argv[3],"Motor"); if(!brumm){ sprintf(buffer,"ERROR: motor %s not found!", argv[3]); - SCWrite(pCon,buffer,eError); + SCWrite(pCon,buffer,eLogError); return; } @@ -229,14 +253,14 @@ static void putMotor(SConnection *pCon, SicsInterp *pSics, pNXScript self, status = MotorGetSoftPosition(brumm, pCon,&fVal); if(!status){ sprintf(buffer,"ERROR: failed to read position of %s", argv[3]); - SCWrite(pCon,buffer,eError); + SCWrite(pCon,buffer,eLogError); return; } status = NXDputalias(self->fileHandle,self->dictHandle,argv[2],&fVal); if(status != NX_OK){ sprintf(buffer,"ERROR: failed to write %s with alias %s", argv[3],argv[2]); - SCWrite(pCon,buffer,eError); + SCWrite(pCon,buffer,eLogError); return; } @@ -251,7 +275,7 @@ static void putMotor(SConnection *pCon, SicsInterp *pSics, pNXScript self, if(status != NX_OK){ sprintf(buffer,"ERROR: failed to write %s zero with alias %s", argv[3],argv[2]); - SCWrite(pCon,buffer,eError); + SCWrite(pCon,buffer,eLogError); return; } } @@ -268,7 +292,7 @@ static void putCounter(SConnection *pCon, SicsInterp *pSics, pNXScript self, if(argc < 4){ SCWrite(pCon,"ERROR: insufficient number of arguments to putcounter", - eError); + eLogError); return; } memset(dummy,0,80*sizeof(char)); @@ -279,7 +303,7 @@ static void putCounter(SConnection *pCon, SicsInterp *pSics, pNXScript self, cter = (pCounter)FindCommandData(pSics,argv[3],"SingleCounter"); if(!cter){ sprintf(buffer,"ERROR: counter %s not found!", argv[3]); - SCWrite(pCon,buffer,eError); + SCWrite(pCon,buffer,eLogError); return; } @@ -292,7 +316,7 @@ static void putCounter(SConnection *pCon, SicsInterp *pSics, pNXScript self, status = NXDputalias(self->fileHandle,self->dictHandle,newAlias,&fVal); if(status != NX_OK){ sprintf(buffer,"ERROR: failed to write preset to %s", newAlias); - SCWrite(pCon,buffer,eError); + SCWrite(pCon,buffer,eLogError); } /* @@ -309,7 +333,7 @@ static void putCounter(SConnection *pCon, SicsInterp *pSics, pNXScript self, status = NXDputalias(self->fileHandle,self->dictHandle,newAlias,dummy); if(status != NX_OK){ sprintf(buffer,"ERROR: failed to write counter mode to %s", newAlias); - SCWrite(pCon,buffer,eError); + SCWrite(pCon,buffer,eLogError); } /* @@ -322,7 +346,7 @@ static void putCounter(SConnection *pCon, SicsInterp *pSics, pNXScript self, status = NXDputalias(self->fileHandle,self->dictHandle,newAlias,&fVal); if(status != NX_OK){ sprintf(buffer,"ERROR: failed to write count time to %s", newAlias); - SCWrite(pCon,buffer,eError); + SCWrite(pCon,buffer,eLogError); } } @@ -352,7 +376,7 @@ static void putSicsData(SConnection *pCon, SicsInterp *pSics, if(argc < 4){ SCWrite(pCon,"ERROR: insufficient number of arguments to putSicsData", - eError); + eLogError); return; } @@ -362,14 +386,14 @@ static void putSicsData(SConnection *pCon, SicsInterp *pSics, data = (pSICSData)FindCommandData(pSics,argv[3],"SICSData"); if(data == NULL){ snprintf(buffer,255,"ERROR: sicsdata %s not found!", argv[3]); - SCWrite(pCon,buffer,eError); + SCWrite(pCon,buffer,eLogError); return; } status = NXDputalias(self->fileHandle,self->dictHandle,argv[2],data->data); if(status != NX_OK){ sprintf(buffer,"ERROR: failed to write sicsdata to %s", argv[2]); - SCWrite(pCon,buffer,eError); + SCWrite(pCon,buffer,eLogError); } } /*----------------------------------------------------------------------*/ @@ -380,25 +404,177 @@ static void putAttribute(SConnection *pCon, SicsInterp *pSics, if(argc < 5){ SCWrite(pCon,"ERROR: insufficient number of arguments to putAttribute", - eError); + eLogError); return; } status = NXDopenalias(self->fileHandle,self->dictHandle,argv[2]); if(status != NX_OK){ sprintf(buffer,"ERROR: failed to open alias %s", argv[2]); - SCWrite(pCon,buffer,eError); + SCWrite(pCon,buffer,eLogError); return; } status = NXputattr(self->fileHandle,argv[3],(void *)argv[4], strlen(argv[4])+1, type); if(status != NX_OK){ sprintf(buffer,"ERROR: failed to write attribute %s", argv[3]); - SCWrite(pCon,buffer,eError); + SCWrite(pCon,buffer,eLogError); } NXopenpath(self->fileHandle,"/"); } /*----------------------------------------------------------------------*/ +static void putHdb(SConnection *pCon, SicsInterp *pSics, pNXScript self, + int argc, char *argv[]){ + pHdb node = NULL; + char alias[512]; + hdbValue v; + float fVal, *floatAr = NULL; + int i; + + if(argc < 3){ + SCWrite(pCon,"ERROR: putHdb needs at least node name", + eLogError); + return; + } + node = FindHdbNode(NULL,argv[2], pCon); + if(node == NULL){ + SCPrintf(pCon,eLogError,"ERROR: node %s not found", argv[2]); + return; + } + memset(alias,0,512*sizeof(char)); + if(!GetHdbProperty(node,"nxalias", alias, 512)){ + if(argc < 4) { + SCPrintf(pCon,eLogError,"ERROR: neither nxalias property nor alias on command line found for %s", + argv[2]); + return; + } else { + strncpy(alias, argv[3],512); + } + } + GetHipadabaPar(node,&v,pCon); + switch(v.dataType){ + case HIPNONE: + return; + break; + case HIPINT: + NXDputalias(self->fileHandle, self->dictHandle, alias, + &v.v.intValue); + break; + case HIPFLOAT: + fVal = v.v.doubleValue; + NXDputalias(self->fileHandle, self->dictHandle, alias, + &fVal); + break; + case HIPTEXT: + NXDputalias(self->fileHandle, self->dictHandle, alias, + v.v.text); + break; + case HIPINTAR: + case HIPINTVARAR: + NXDputalias(self->fileHandle, self->dictHandle, alias, + v.v.intArray); + break; + case HIPFLOATAR: + case HIPFLOATVARAR: + floatAr = malloc(v.arrayLength*sizeof(float)); + if(floatAr == NULL){ + SCPrintf(pCon,eLogError,"ERROR: out of memory writing %s", node->name); + return; + } + for(i = 0; i < v.arrayLength; i++){ + floatAr[i] = v.v.floatArray[i]; + } + NXDputalias(self->fileHandle, self->dictHandle, alias, + floatAr); + free(floatAr); + break; + } + ReleaseHdbValue(&v); +} +/*----------------------------------------------------------------------*/ +static void putHdbSlab(SConnection *pCon, SicsInterp *pSics, pNXScript self, + int argc, char *argv[]){ + pHdb node = NULL; + char alias[512]; + hdbValue v; + float fVal, *floatAr = NULL; + int start[NX_MAXRANK], size[NX_MAXRANK]; + int i, status; + + if(argc < 5){ + SCWrite(pCon,"ERROR: putHdbSlab needs at least node name start, size", + eLogError); + return; + } + node = FindHdbNode(NULL,argv[2], pCon); + if(node == NULL){ + SCPrintf(pCon,eLogError,"ERROR: node %s not found", argv[2]); + return; + } + memset(alias,0,512*sizeof(char)); + if(!GetHdbProperty(node,"nxalias", alias, 512)){ + SCPrintf(pCon,eLogError, + "ERROR: nxalias property not found for %s", + argv[2]); + return; + } + status = NXDopenalias(self->fileHandle, self->dictHandle,alias); + if(status != NX_OK){ + SCPrintf(pCon,eLogError,"ERROR: failed to open alias for %s", argv[2]); + return; + } + + status = listToArray(pSics,argv[3],start); + if(status != TCL_OK){ + SCWrite(pCon,"ERROR: failed to convert start value list", eLogError); + return; + } + + status = listToArray(pSics,argv[4],size); + if(status != TCL_OK){ + SCWrite(pCon,"ERROR: failed to convert size value list", eLogError); + return; + } + + GetHipadabaPar(node,&v,pCon); + switch(v.dataType){ + case HIPNONE: + return; + break; + case HIPINT: + status = NXputslab(self->fileHandle, &v.v.intValue, start,size); + break; + case HIPFLOAT: + fVal = v.v.doubleValue; + status = NXputslab(self->fileHandle, &fVal, start,size); + break; + case HIPTEXT: + status = NXputslab(self->fileHandle, v.v.text, start,size); + break; + case HIPINTAR: + case HIPINTVARAR: + status = NXputslab(self->fileHandle, v.v.intArray, start,size); + break; + case HIPFLOATAR: + case HIPFLOATVARAR: + floatAr = malloc(v.arrayLength*sizeof(float)); + if(floatAr == NULL){ + SCPrintf(pCon,eLogError,"ERROR: out of memory writing %s", node->name); + return; + } + for(i = 0; i < v.arrayLength; i++){ + floatAr[i] = v.v.floatArray[i]; + } + status = NXputslab(self->fileHandle, floatAr, start,size); + free(floatAr); + break; + } + if(status != NX_OK){ + SCPrintf(pCon,eLogError,"ERROR: failed to write slab for node %s", argv[2]); + } + ReleaseHdbValue(&v); +} +/*----------------------------------------------------------------------*/ static void updateHMDim(NXScript *self, pHistMem mem){ int iDim[MAXDIM]; int i, rank, timeLength, status; @@ -444,7 +620,7 @@ static void putHistogramMemory(SConnection *pCon, SicsInterp *pSics, if(argc < 4){ SCWrite(pCon,"ERROR: insufficient number of arguments to puthm", - eError); + eLogError); return; } @@ -454,7 +630,7 @@ static void putHistogramMemory(SConnection *pCon, SicsInterp *pSics, mem = (pHistMem)FindCommandData(pSics,argv[3],"HistMem"); if(!mem){ sprintf(buffer,"ERROR: HistMem %s not found!", argv[3]); - SCWrite(pCon,buffer,eError); + SCWrite(pCon,buffer,eLogError); return; } @@ -475,14 +651,14 @@ static void putHistogramMemory(SConnection *pCon, SicsInterp *pSics, if(status != TCL_OK){ sprintf(buffer,"ERROR: failed to convert %s to integer", argv[4]); - SCWrite(pCon,buffer,eError); + SCWrite(pCon,buffer,eLogError); return; } status = Tcl_GetInt(InterpGetTcl(pSics),argv[5],&length); if(status != TCL_OK){ sprintf(buffer,"ERROR: failed to convert %s to integer", argv[5]); - SCWrite(pCon,buffer,eError); + SCWrite(pCon,buffer,eLogError); return; } } @@ -495,7 +671,7 @@ static void putHistogramMemory(SConnection *pCon, SicsInterp *pSics, if(status != TCL_OK){ sprintf(buffer,"ERROR: failed to convert %s to integer", argv[6]); - SCWrite(pCon,buffer,eError); + SCWrite(pCon,buffer,eLogError); return; } } @@ -507,7 +683,7 @@ static void putHistogramMemory(SConnection *pCon, SicsInterp *pSics, iData = (HistInt *)malloc(length*sizeof(HistInt)); if(!iData){ SCWrite(pCon,"ERROR: out of memory for reading histogram memory", - eError); + eLogError); return; } memset(iData,0,length*sizeof(HistInt)); @@ -526,7 +702,7 @@ static void putHistogramMemory(SConnection *pCon, SicsInterp *pSics, } } if(!status){ - SCWrite(pCon,"ERROR: failed to read histogram memory",eError); + SCWrite(pCon,"ERROR: failed to read histogram memory",eLogError); if(subset){ free(iData); } @@ -539,7 +715,7 @@ static void putHistogramMemory(SConnection *pCon, SicsInterp *pSics, status = NXDputalias(self->fileHandle, self->dictHandle,argv[2],iData); if(status != NX_OK){ sprintf(buffer,"ERROR: failed to write histogram memory data"); - SCWrite(pCon,buffer,eError); + SCWrite(pCon,buffer,eLogError); } if(subset){ @@ -563,7 +739,7 @@ static void putHistogramMemoryChunked(SConnection *pCon, SicsInterp *pSics, if(argc < 5){ SCWrite(pCon,"ERROR: insufficient number of arguments to puthmchunked", - eError); + eLogError); return; } @@ -573,7 +749,7 @@ static void putHistogramMemoryChunked(SConnection *pCon, SicsInterp *pSics, mem = (pHistMem)FindCommandData(pSics,argv[3],"HistMem"); if(!mem){ sprintf(buffer,"ERROR: HistMem %s not found!", argv[3]); - SCWrite(pCon,buffer,eError); + SCWrite(pCon,buffer,eLogError); return; } @@ -592,7 +768,7 @@ static void putHistogramMemoryChunked(SConnection *pCon, SicsInterp *pSics, if(status != TCL_OK){ sprintf(buffer,"ERROR: failed to convert %s to integer", argv[4]); - SCWrite(pCon,buffer,eError); + SCWrite(pCon,buffer,eLogError); return; } @@ -603,7 +779,7 @@ static void putHistogramMemoryChunked(SConnection *pCon, SicsInterp *pSics, iData = (HistInt *)malloc(length*sizeof(HistInt)); if(!iData){ SCWrite(pCon,"ERROR: out of memory for reading histogram memory", - eError); + eLogError); return; } memset(iData,0,length*sizeof(HistInt)); @@ -622,7 +798,7 @@ static void putHistogramMemoryChunked(SConnection *pCon, SicsInterp *pSics, } } if(!status){ - SCWrite(pCon,"ERROR: failed to read histogram memory",eError); + SCWrite(pCon,"ERROR: failed to read histogram memory",eLogError); if(subset){ free(iData); } @@ -635,7 +811,7 @@ static void putHistogramMemoryChunked(SConnection *pCon, SicsInterp *pSics, status = NXDputalias(self->fileHandle, self->dictHandle,argv[2],iData); if(status != NX_OK){ sprintf(buffer,"ERROR: failed to write histogram memory data"); - SCWrite(pCon,buffer,eError); + SCWrite(pCon,buffer,eLogError); } if(subset){ @@ -646,28 +822,6 @@ static void putHistogramMemoryChunked(SConnection *pCon, SicsInterp *pSics, return; } /*----------------------------------------------------------------------*/ -static int listToArray(SicsInterp *pSics, char *list, - int intar[NX_MAXRANK]){ - int argc, status, i, val; - CONST char **argv; - Tcl_Interp *pTcl = InterpGetTcl(pSics); - - status = Tcl_SplitList(pTcl, list, &argc, &argv); - if(status != TCL_OK){ - return status; - } - - for(i = 0; i < argc; i++){ - status = Tcl_GetInt(pTcl,argv[i],&val); - if(status != TCL_OK){ - return status; - } - intar[i] = val; - } - Tcl_Free((char *)argv); - return TCL_OK; -} -/*----------------------------------------------------------------------*/ static void putSlab(SConnection *pCon, SicsInterp *pSics, pNXScript self, int argc, char *argv[]){ int start[NX_MAXRANK], size[NX_MAXRANK]; @@ -678,25 +832,25 @@ static void putSlab(SConnection *pCon, SicsInterp *pSics, pNXScript self, if(argc < 6){ SCWrite(pCon,"ERROR: insufficient number of arguments to putslab", - eError); + eLogError); return; } status = NXDopenalias(self->fileHandle, self->dictHandle,argv[2]); if(status != NX_OK){ - SCPrintf(pCon,eError,"ERROR: failed to open alias %s", argv[2]); + SCPrintf(pCon,eLogError,"ERROR: failed to open alias %s", argv[2]); return; } status = listToArray(pSics,argv[3],start); if(status != TCL_OK){ - SCWrite(pCon,"ERROR: failed to convert start value list", eError); + SCWrite(pCon,"ERROR: failed to convert start value list", eLogError); return; } status = listToArray(pSics,argv[4],size); if(status != TCL_OK){ - SCWrite(pCon,"ERROR: failed to convert size value list", eError); + SCWrite(pCon,"ERROR: failed to convert size value list", eLogError); return; } @@ -731,7 +885,7 @@ static void putSlab(SConnection *pCon, SicsInterp *pSics, pNXScript self, if(written == 0){ SCWrite(pCon,"ERROR: failed to write data, data not recognised", - eError); + eLogError); } } /*-------------------------------------------------------------------*/ @@ -746,7 +900,7 @@ static void putTimeBinning(SConnection *pCon, SicsInterp *pSics, if(argc < 4){ SCWrite(pCon,"ERROR: insufficient number of arguments to puttimebinning", - eError); + eLogError); return; } @@ -756,7 +910,7 @@ static void putTimeBinning(SConnection *pCon, SicsInterp *pSics, mem = (pHistMem)FindCommandData(pSics,argv[3],"HistMem"); if(!mem){ sprintf(buffer,"ERROR: HistMem %s not found!", argv[3]); - SCWrite(pCon,buffer,eError); + SCWrite(pCon,buffer,eLogError); return; } @@ -768,7 +922,7 @@ static void putTimeBinning(SConnection *pCon, SicsInterp *pSics, if(!status){ sprintf(buffer,"ERROR: alias %s for time binning not found", argv[2]); - SCWrite(pCon,buffer,eError); + SCWrite(pCon,buffer,eLogError); return; } timeBin = GetHistTimeBin(mem,&timeLength); @@ -780,7 +934,7 @@ static void putTimeBinning(SConnection *pCon, SicsInterp *pSics, if(self->timeDivisor != 1){ timeCopy = (float *)malloc(timeLength*sizeof(float)); if(timeCopy == NULL){ - SCWrite(pCon,"ERROR: out of memory writing time binning",eError); + SCWrite(pCon,"ERROR: out of memory writing time binning",eLogError); return; } for(i = 0; i < timeLength; i++){ @@ -796,7 +950,7 @@ static void putTimeBinning(SConnection *pCon, SicsInterp *pSics, if(status != NX_OK){ sprintf(buffer,"ERROR: failed to write time binning"); - SCWrite(pCon,buffer,eError); + SCWrite(pCon,buffer,eLogError); } SCSendOK(pCon); return; @@ -814,7 +968,7 @@ static void putArray(SConnection *pCon, SicsInterp *pSics, if(argc < 5){ SCWrite(pCon,"ERROR: insufficient number of arguments to array", - eError); + eLogError); return; } tcl = InterpGetTcl(pSics); @@ -825,8 +979,8 @@ static void putArray(SConnection *pCon, SicsInterp *pSics, */ status = Tcl_GetInt(tcl,argv[4],&length); if(status != TCL_OK){ - sprintf(buffer,"ERROR: failed to convert %s to integer",argv[4]); - SCWrite(pCon,buffer,eError); + sprintf(buffer,"ERROR: failed to convert %s to integer in putarray",argv[4]); + SCWrite(pCon,buffer,eLogError); return; } @@ -838,9 +992,9 @@ static void putArray(SConnection *pCon, SicsInterp *pSics, } if(data == NULL){ snprintf(buffer,255, - "ERROR: out of memory or invalid length at %s, length = %s", + "ERROR: out of memory or invalid length in putarray at %s, length = %s", argv[2],argv[4]); - SCWrite(pCon,buffer,eError); + SCWrite(pCon,buffer,eLogError); return; } memset(data,0,length*sizeof(float)); @@ -854,14 +1008,14 @@ static void putArray(SConnection *pCon, SicsInterp *pSics, if(varData != NULL){ status = Tcl_GetDouble(tcl,varData,&dVal); if(status != TCL_OK){ - sprintf(buffer,"ERROR: failed to convert %s to double", + sprintf(buffer,"ERROR: failed to convert %s to double in putarray", varData); - SCWrite(pCon,buffer,eError); + SCWrite(pCon,buffer,eLogError); } data[i] = (float)dVal; } else { - snprintf(buffer,254,"WARNING: failed to find array element %d", i); - SCWrite(pCon,buffer,eError); + snprintf(buffer,254,"WARNING: failed to find array element %d in putarray", i); + SCWrite(pCon,buffer,eLogError); } } @@ -870,9 +1024,9 @@ static void putArray(SConnection *pCon, SicsInterp *pSics, */ status = NXDdefget(self->dictHandle,argv[2],buffer,254); if(!status){ - sprintf(buffer,"ERROR: alias %s for array not found", + sprintf(buffer,"ERROR: alias %s for array not found in putarray", argv[2]); - SCWrite(pCon,buffer,eError); + SCWrite(pCon,buffer,eLogError); free(data); return; } @@ -883,8 +1037,8 @@ static void putArray(SConnection *pCon, SicsInterp *pSics, */ status = NXDputdef(self->fileHandle,self->dictHandle,defString,data); if(status != NX_OK){ - sprintf(buffer,"ERROR: failed to write array"); - SCWrite(pCon,buffer,eError); + sprintf(buffer,"ERROR: failed to write array in putarray"); + SCWrite(pCon,buffer,eLogError); } free(data); SCSendOK(pCon); @@ -902,7 +1056,7 @@ static void putIntArray(SConnection *pCon, SicsInterp *pSics, if(argc < 5){ SCWrite(pCon,"ERROR: insufficient number of arguments to array", - eError); + eLogError); return; } tcl = InterpGetTcl(pSics); @@ -914,7 +1068,7 @@ static void putIntArray(SConnection *pCon, SicsInterp *pSics, status = Tcl_GetInt(tcl,argv[4],&length); if(status != TCL_OK){ sprintf(buffer,"ERROR: failed to convert %s to integer",argv[4]); - SCWrite(pCon,buffer,eError); + SCWrite(pCon,buffer,eLogError); return; } @@ -925,7 +1079,7 @@ static void putIntArray(SConnection *pCon, SicsInterp *pSics, data = (int *)malloc(length*sizeof(int)); } if(data == NULL){ - SCWrite(pCon,"ERROR: out of memory or invalid length",eError); + SCWrite(pCon,"ERROR: out of memory or invalid length",eLogError); return; } memset(data,0,length*sizeof(int)); @@ -941,12 +1095,12 @@ static void putIntArray(SConnection *pCon, SicsInterp *pSics, if(status != TCL_OK){ sprintf(buffer,"ERROR: failed to convert %s to int", varData); - SCWrite(pCon,buffer,eError); + SCWrite(pCon,buffer,eLogError); } data[i] = iVal; } else { snprintf(buffer,254,"WARNING: failed to find array element %d", i); - SCWrite(pCon,buffer,eError); + SCWrite(pCon,buffer,eLogError); } } @@ -957,7 +1111,7 @@ static void putIntArray(SConnection *pCon, SicsInterp *pSics, if(!status){ sprintf(buffer,"ERROR: alias %s for array not found", argv[2]); - SCWrite(pCon,buffer,eError); + SCWrite(pCon,buffer,eLogError); free(data); return; } @@ -969,7 +1123,7 @@ static void putIntArray(SConnection *pCon, SicsInterp *pSics, status = NXDputdef(self->fileHandle,self->dictHandle,defString,data); if(status != NX_OK){ sprintf(buffer,"ERROR: failed to write array"); - SCWrite(pCon,buffer,eError); + SCWrite(pCon,buffer,eLogError); } free(data); SCSendOK(pCon); @@ -983,7 +1137,7 @@ static void putGlobal(SConnection *pCon, SicsInterp *pSics, if(argc < 4){ SCWrite(pCon,"ERROR: insufficient number of arguments to putglobal", - eError); + eLogError); return; } @@ -991,7 +1145,7 @@ static void putGlobal(SConnection *pCon, SicsInterp *pSics, status = NXputattr(self->fileHandle,argv[2],value,strlen(value), NX_CHAR); if(status != NX_OK){ - SCWrite(pCon,"ERROR: failed to write attribute",eError); + SCWrite(pCon,"ERROR: failed to write attribute",eLogError); } SCSendOK(pCon); } @@ -1007,14 +1161,14 @@ static int handlePut(SConnection *pCon, SicsInterp *pSics, pNXScript self, if(strcmp(argv[1],"putfloat") == 0){ if(argc < 4){ SCWrite(pCon,"ERROR: insufficient number of arguments to putfloat", - eError); + eLogError); return 1; } status = Tcl_GetDouble(InterpGetTcl(pSics),argv[3],&dVal); if(status != TCL_OK){ sprintf(buffer,"ERROR: failed to convert %s to float", argv[3]); - SCWrite(pCon,buffer,eError); + SCWrite(pCon,buffer,eLogError); return 1; } fVal = (float)dVal; @@ -1023,20 +1177,20 @@ static int handlePut(SConnection *pCon, SicsInterp *pSics, pNXScript self, if(status != NX_OK){ sprintf(buffer,"ERROR: failed to write %f to alias %s", fVal, argv[2]); - SCWrite(pCon,buffer,eError); + SCWrite(pCon,buffer,eLogError); } return 1; } else if(strcmp(argv[1],"putint") == 0){ if(argc < 4){ SCWrite(pCon,"ERROR: insufficient number of arguments to putint", - eError); + eLogError); return 1; } status = Tcl_GetInt(InterpGetTcl(pSics),argv[3],&iVal); if(status != TCL_OK){ sprintf(buffer,"ERROR: failed to convert %s to int", argv[3]); - SCWrite(pCon,buffer,eError); + SCWrite(pCon,buffer,eLogError); return 1; } status = NXDputalias(self->fileHandle, self->dictHandle, @@ -1044,14 +1198,14 @@ static int handlePut(SConnection *pCon, SicsInterp *pSics, pNXScript self, if(status != NX_OK){ sprintf(buffer,"ERROR: failed to write %d to alias %s", iVal, argv[2]); - SCWrite(pCon,buffer,eError); + SCWrite(pCon,buffer,eLogError); } return 1; } else if (strcmp(argv[1],"puttext") == 0){ /*====================*/ if(argc < 4){ SCWrite(pCon,"ERROR: insufficient number of arguments to puttext", - eError); + eLogError); return 1; } Arg2Text(argc-3,&argv[3],buffer,1023); @@ -1060,7 +1214,7 @@ static int handlePut(SConnection *pCon, SicsInterp *pSics, pNXScript self, if(status != NX_OK){ sprintf(buffer,"ERROR: alias %s not found in puttext", argv[2]); - SCWrite(pCon,buffer,eError); + SCWrite(pCon,buffer,eLogError); return 1; } if(strlen(defString) < 900){ @@ -1070,7 +1224,7 @@ static int handlePut(SConnection *pCon, SicsInterp *pSics, pNXScript self, strcat(defString," }"); } else { SCWrite(pCon,"ERROR: out of definition string space in puttext", - eError); + eLogError); return 1; } status = NXDputdef(self->fileHandle,self->dictHandle, @@ -1078,7 +1232,7 @@ static int handlePut(SConnection *pCon, SicsInterp *pSics, pNXScript self, if(status != NX_OK){ sprintf(buffer,"ERROR: failed to write alias %s", argv[2]); - SCWrite(pCon,buffer,eError); + SCWrite(pCon,buffer,eLogError); } return 1; } else if(strcmp(argv[1],"putmot") == 0){ @@ -1089,6 +1243,14 @@ static int handlePut(SConnection *pCon, SicsInterp *pSics, pNXScript self, /* ================*/ putCounter(pCon,pSics,self, argc,argv); return 1; + } else if(strcmp(argv[1],"puthdb") == 0){ + /* ================*/ + putHdb(pCon,pSics,self, argc,argv); + return 1; + } else if(strcmp(argv[1],"puthdbslab") == 0){ + /* ================*/ + putHdbSlab(pCon,pSics,self, argc,argv); + return 1; }else if(strcmp(argv[1],"puthm") == 0){ /*=================*/ putHistogramMemory(pCon,pSics,self,argc, argv); @@ -1115,7 +1277,7 @@ static int handlePut(SConnection *pCon, SicsInterp *pSics, pNXScript self, /*===============*/ putSlab(pCon,pSics,self,argc,argv); } else { - SCWrite(pCon,"ERROR: put command not recognised",eError); + SCWrite(pCon,"ERROR: put command not recognised",eLogError); } return 1; } @@ -1128,7 +1290,7 @@ static void makeLink(SConnection *pCon, SicsInterp *pSics, if(argc < 4){ SCWrite(pCon,"ERROR: insufficient number of arguments to makelink", - eError); + eLogError); return; } @@ -1137,7 +1299,7 @@ static void makeLink(SConnection *pCon, SicsInterp *pSics, if(status != NX_OK){ snprintf(pBueffel,255,"ERROR: linking %s against %s failed", argv[2], argv[3]); - SCWrite(pCon,pBueffel,eError); + SCWrite(pCon,pBueffel,eLogError); return; } @@ -1150,12 +1312,12 @@ static void updateDictVar(SConnection *pCon, pNXScript self, int argc, if(self->dictHandle == NULL){ SCWrite(pCon,"ERROR: cannot update variable, dictionary not open", - eError); + eLogError); return; } if(argc < 4){ SCWrite(pCon,"ERROR: insufficient number of arguments to updateDictVar", - eError); + eLogError); return; } NXDupdate(self->dictHandle,argv[2],argv[3]); @@ -1176,7 +1338,7 @@ int NXScriptAction(SConnection *pCon, SicsInterp *pSics, void *pData, return 1; } if(argc < 2){ - SCWrite(pCon,"ERROR: no keyword found",eError); + SCWrite(pCon,"ERROR: no keyword found",eLogError); return 1; } strtolower(argv[1]); @@ -1193,7 +1355,7 @@ int NXScriptAction(SConnection *pCon, SicsInterp *pSics, void *pData, } } else if(strcmp(argv[1],"divisor") == 0){ if(argc < 3) { - SCWrite(pCon,"ERROR: no diviso found",eError); + SCWrite(pCon,"ERROR: no divisor found",eLogError); return 1; } if(!SCMatchRights(pCon,usMugger)){ @@ -1216,7 +1378,7 @@ int NXScriptAction(SConnection *pCon, SicsInterp *pSics, void *pData, if we are here, we can only continue if files are open */ if(self->fileHandle == NULL || self->dictHandle == NULL){ - SCWrite(pCon,"ERROR: cannot write, files not open",eError); + SCWrite(pCon,"ERROR: cannot write, files not open",eLogError); return 1; } @@ -1232,7 +1394,7 @@ int NXScriptAction(SConnection *pCon, SicsInterp *pSics, void *pData, if(strcmp(argv[1],"isalias") == 0) { if(argc < 3) { - SCWrite(pCon,"ERROR: need alias to test",eError); + SCWrite(pCon,"ERROR: need alias to test",eLogError); return 1; } if(NXDget(self->dictHandle,argv[2],buffer,131) == NX_OK){ diff --git a/nxupdate.c b/nxupdate.c index 0bd0e028..f72b998a 100644 --- a/nxupdate.c +++ b/nxupdate.c @@ -46,8 +46,7 @@ static int UpdateTask(void *pData){ } } /*--------------------------------------------------------------------*/ -static int CountCallback(int iEvent, void *pEventData, void *pUser, - commandContext cc){ +static int CountCallback(int iEvent, void *pEventData, void *pUser){ pNXupdate self = NULL; SConnection *pCon = NULL; @@ -258,7 +257,6 @@ int UpdateFactory(SConnection *pCon, SicsInterp *pSics, void *pData, char pBueffel[256]; pNXupdate self = NULL; CommandList *pCom = NULL; - commandContext comCon; if(argc < 3){ SCWrite(pCon,"ERROR: insuffcient number of argument to UpdateFactory", @@ -311,11 +309,9 @@ int UpdateFactory(SConnection *pCon, SicsInterp *pSics, void *pData, /* register callbacks */ - comCon.transID = 0; - strncpy(comCon.deviceID,"internal",SCDEVIDLEN); - RegisterCallback(pCall,comCon,COUNTSTART,CountCallback, + RegisterCallback(pCall,COUNTSTART,CountCallback, self,NULL); - RegisterCallback(pCall,comCon,COUNTEND,CountCallback, + RegisterCallback(pCall,COUNTEND,CountCallback, self,NULL); AddCommand(pSics,argv[1],UpdateAction,KillUpdate,self); diff --git a/obdes.h b/obdes.h index f842a2e9..2fb9f1e8 100644 --- a/obdes.h +++ b/obdes.h @@ -1,5 +1,5 @@ -#line 365 "interface.w" +#line 385 "interface.w" #line 29 "interface.w" @@ -56,7 +56,7 @@ typedef struct { #endif -#line 366 "interface.w" +#line 386 "interface.w" /*--------------------------------------------------------------------------*/ /* Additional properties used by the ANSTO site to provide more information diff --git a/ofac.c b/ofac.c index 1bc2c26a..53aedb63 100644 --- a/ofac.c +++ b/ofac.c @@ -85,7 +85,6 @@ #include "udpquieck.h" #include "choco.h" #include "chadapter.h" -#include "hklscan.h" #include "xytable.h" #include "maximize.h" #include "difrac.h" @@ -129,6 +128,10 @@ #include "hdbqueue.h" #include "genericcontroller.h" #include "proxy.h" +#include "reflist.h" +#include "singlex.h" +#include "motorsec.h" +#include "background.h" /*----------------------- Server options creation -------------------------*/ static int IFServerOption(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]) @@ -257,7 +260,8 @@ AddCommand(pInter,"list",SicsList,NULL,NULL); AddCommand(pInter,"InstallHdb",InstallSICSHipadaba,NULL,NULL); MakeProtocol(pInter); - + InstallBackground(pInter); + /* commands to do with the executor. Only StopExe carries the DeleteFunction in order to avoid double deletion. All the other commands operate on the same datastructure. @@ -269,7 +273,7 @@ AddCommand(pInter,"pause",PauseAction,NULL,pExe); AddCommand(pInter,"continue",ContinueAction,NULL,pExe); AddCommand(pInter,"devexec",DevexecAction,NULL,pExe); - + /* add additional object creation commands here */ AddCommand(pInter,"TokenInit",TokenInit,NULL,NULL); AddCommand(pInter,"ServerOption",IFServerOption,NULL,NULL); @@ -296,7 +300,6 @@ AddCommand(pInter,"kill_command",SICSKill,NULL,NULL); AddCommand(pInter,"MakeChopper",ChocoFactory,NULL,NULL); AddCommand(pInter,"ChopperAdapter",CHAdapterFactory,NULL,NULL); - AddCommand(pInter,"MakeHklscan",HklscanFactory,NULL,NULL); AddCommand(pInter,"MakeXYTable",XYFactory,NULL,NULL); AddCommand(pInter,"MakeMaximize",MaximizeFactory,NULL,NULL); AddCommand(pInter,"MakeLin2Ang",MakeLin2Ang,NULL,NULL); @@ -350,6 +353,9 @@ AddCommand(pInter,"MakeGenController",GenControllerFactory,NULL,NULL); AddCommand(pInter,"genconfigure",GenControllerConfigure,NULL,NULL); AddCommand(pInter,"MakeProxy",ProxyFactory,NULL,NULL); + AddCommand(pInter,"MakeRefList",MakeReflectionList,NULL,NULL); + AddCommand(pInter,"MakeSingleX",MakeSingleX,NULL,NULL); + AddCommand(pInter,"MakeSecMotor",SecMotorFactory,NULL,NULL); /* install site specific commands @@ -425,6 +431,9 @@ RemoveCommand(pSics,"MakeGenController"); RemoveCommand(pSics,"genconfigure"); RemoveCommand(pSics,"MakeProxy"); + RemoveCommand(pSics,"MakeRefList"); + RemoveCommand(pSics,"MakeSingleX"); + RemoveCommand(pSics,"MakeSecMotor"); /* remove site specific installation commands */ @@ -475,21 +484,12 @@ InitIniCommands(pSics,pServ->pTasker); InstallBckRestore(pCon,pSics); - pCon->iFiles = 0; /* evaluate the file */ sprintf(pBueffel,"fileeval %s",file); iRet = InterpExecute(pSics,pCon,pBueffel); - if(!iRet) - { - KillIniCommands(pSics); - RemoveStartupCommands(); - SCDeleteConnection(pCon); - return 0; - } /* done */ - pCon->iFiles = 0; SCDeleteConnection(pCon); KillIniCommands(pSics); RemoveStartupCommands(); diff --git a/optimise.c b/optimise.c index 64afe2cb..066dc53c 100644 --- a/optimise.c +++ b/optimise.c @@ -347,7 +347,7 @@ return 0; } sprintf(pBueffel,"Trying hard to optimise variable %s",pOvar->pName); - SCWrite(pCon,pBueffel,eWarning); + SCWrite(pCon,pBueffel,eLog); iRet = SilentScan(self->pScanner,pOvar->iStep,self->eCount, self->fPreset,pServ->pSics,pCon); if(!iRet) @@ -397,11 +397,11 @@ strcat(pBueffel,cData); break; } - SCWrite(pCon,pBueffel,eWarning); + SCWrite(pCon,pBueffel,eLog); if(fMax < self->fThreshold) { - SCWrite(pCon,"Peak may be lost, increasing scan range",eWarning); + SCWrite(pCon,"Peak may be lost, increasing scan range",eLog); pOvar->iLost++; if(pOvar->iLost > 2) { @@ -435,11 +435,11 @@ { pOvar->fShift = ABS(pOvar->fCenter - fNewCenter); sprintf(pBueffel,"%s shifted by %8.2f ",pOvar->pName,pOvar->fShift); - SCWrite(pCon,pBueffel,eWarning); + SCWrite(pCon,pBueffel,eLog); pOvar->fPrecision = 3*fStdDev; sprintf(pBueffel,"%s precision set to 3*StdDev = %8.3f", pOvar->pName, 3*fStdDev); - SCWrite(pCon,pBueffel,eWarning); + SCWrite(pCon,pBueffel,eLog); pOvar->fCenter = fNewCenter; } /* drive to the new center */ @@ -627,7 +627,7 @@ static int findDirection(pOptimise self, pOVarEntry pOvar, SConnection *pCon) } snprintf(buffer,255,"Climbing %s, value = %f, count = %ld", pOvar->pName, varValue, currentCount); - SCWrite(pCon,buffer,eWarning); + SCWrite(pCon,buffer,eLog); if(currentCount <= lastCount) { @@ -695,7 +695,7 @@ static int findDirection(pOptimise self, pOVarEntry pOvar, SConnection *pCon) for(iCycle = 0; iCycle < self->iMaxCycles; iCycle++) { sprintf(pBueffel,"Optimiser cycle %d of %d started",iCycle, self->iMaxCycles); - SCWrite(pCon,pBueffel,eStatus); + SCWrite(pCon,pBueffel,eLog); for(i = iRedoVar; i < self->iVar; i++) { iRet = CenterVariable(self,pCon,i); @@ -740,7 +740,7 @@ static int findDirection(pOptimise self, pOVarEntry pOvar, SConnection *pCon) for(iCycle = 0; iCycle < self->iMaxCycles; iCycle++) { sprintf(pBueffel,"Optimiser cycle %d of %d started",iCycle, self->iMaxCycles); - SCWrite(pCon,pBueffel,eStatus); + SCWrite(pCon,pBueffel,eLog); for(i = iRedoVar; i < self->iVar; i++) { iRet = ClimbVariable(self,pCon,i); diff --git a/outcode.c b/outcode.c index ad7fa0ee..42183aa9 100644 --- a/outcode.c +++ b/outcode.c @@ -22,6 +22,8 @@ "error", "hdbvalue", "hdbevent", + "log", + "logerror", NULL }; static int iNoCodes = 13; #endif diff --git a/perfmon.c b/perfmon.c index 7fd72800..da06ddd8 100644 --- a/perfmon.c +++ b/perfmon.c @@ -147,8 +147,7 @@ return self->fCPS; } /*------------------- The CallBack function for interest ------------------*/ - static int InterestCallback(int iEvent, void *pEvent, void *pUser, - commandContext cc) + static int InterestCallback(int iEvent, void *pEvent, void *pUser) { float *fPos; SConnection *pCon; @@ -160,8 +159,13 @@ fPos = (float *)pEvent; pCon = (SConnection *)pUser; + if(pCon == NULL || !SCisConnected(pCon)) + { + return -1; + } + sprintf(pBueffel,"Performance = %f", *fPos); - SCWriteInContext(pCon,pBueffel,eValue,cc); + SCWrite(pCon,pBueffel,eValue); return 1; } /*---------------------------------------------------------------------------- @@ -207,10 +211,9 @@ if(strcmp(argv[1],"interest") == 0) { - lID = RegisterCallback(self->pCall, SCGetContext(pCon), + lID = RegisterCallback(self->pCall, VALUECHANGE, InterestCallback, - pCon, NULL); - SCRegister(pCon,pSics, self->pCall,lID); + SCCopyConnection(pCon), SCDeleteConnection); SCSendOK(pCon); return 1; } diff --git a/protocol.c b/protocol.c index 909ac1ca..eb429c6c 100644 --- a/protocol.c +++ b/protocol.c @@ -173,7 +173,7 @@ void DeleteProtocol(void *self) /*------------------------------------------------------------------*/ static int ContextDo(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]){ - commandContext comCon; + SConnection *comCon = NULL; char buffer[1024]; char *command; int status; @@ -183,23 +183,27 @@ static int ContextDo(SConnection *pCon, SicsInterp *pSics, void *pData, return 0; } - status = Tcl_GetInt(pSics->pTcl,argv[1],&comCon.transID); + comCon = SCCopyConnection(pCon); + if(comCon == NULL){ + SCWrite(pCon,"EROOR: out of memory in contextdo", eError); + return 0; + } + status = Tcl_GetInt(pSics->pTcl,argv[1],&comCon->transID); if(status != TCL_OK){ snprintf(buffer,1023,"ERROR: failed to convert %s to transaction ID", argv[1]); SCWrite(pCon,buffer,eError); return 0; } - strncpy(comCon.deviceID,argv[2],SCDEVIDLEN); + strncpy(comCon->deviceID,argv[2],SCDEVIDLEN); memset(buffer,0,sizeof(buffer)); command = Arg2Tcl(argc-2,&argv[2],buffer,sizeof buffer); if (!command) { SCWrite(pCon,"ERROR: no more memory",eError); return 0; } - SCPushContext2(pCon,comCon); - status = InterpExecute(pSics,pCon,command); + status = InterpExecute(pSics,comCon,command); if (command != buffer) free(command); - SCPopContext(pCon); + SCDeleteConnection(comCon); return status; } /*--------------------------------------------------------------------------*/ @@ -236,7 +240,7 @@ static int ProtocolOptions(SConnection* pCon, pProtocol pPro) for(i=0;iiNumPros;i++) { sprintf(pBuffer,"Protocol[%d] = %s",i,pPro->pProList[i]); - SCWrite(pCon,pBuffer,eStatus); + SCWrite(pCon,pBuffer,eValue); } return 1; } @@ -246,18 +250,22 @@ static int ProtocolHelp(SConnection* pCon, Protocol* pPro) { SCWrite(pCon, "Usage: protocol {help|list|options|reset} | set protocolName", - eStatus); + eValue); return 1; } /*------------------------------------------------------------------------*/ static int ProtocolSet(SConnection* pCon, Protocol* pPro, char *pProName) { + SConnection *pMaster = NULL; + int proID; if(!SCVerifyConnection(pCon)) { return 0; } + pMaster = SCfindMaster(pCon); + assert(pMaster != NULL); /* lazy initialisation of defaultWriter since connection is verified */ InitDefaultProtocol(pCon,pPro); @@ -278,28 +286,35 @@ static int ProtocolSet(SConnection* pCon, Protocol* pPro, char *pProName) break; case 1: /* normal (connection start default) */ - SCSetWriteFunc(pCon,SCNormalWrite); + SCSetWriteFunc(pMaster,SCNormalWrite); + SCSetWriteFunc(pCon,SCNormalWrite); break; case 2: /* outcodes */ - SCSetWriteFunc(pCon,SCWriteWithOutcode); + SCSetWriteFunc(pMaster,SCWriteWithOutcode); + SCSetWriteFunc(pCon,SCWriteWithOutcode); break; case 3: /* sycamore */ - SCSetWriteFunc(pCon,SCWriteSycamore); + SCSetWriteFunc(pMaster,SCWriteSycamore); + SCSetWriteFunc(pCon,SCWriteSycamore); break; case 4: /* json */ - SCSetWriteFunc(pCon,SCWriteJSON_String); + SCSetWriteFunc(pCon,SCWriteJSON_String); + SCSetWriteFunc(pMaster,SCWriteJSON_String); break; case 5: - SCSetWriteFunc(pCon,SCACTWrite); + SCSetWriteFunc(pMaster,SCACTWrite); + SCSetWriteFunc(pCon,SCACTWrite); break; case 0: /* default = psi_sics */ default: - SCSetWriteFunc(pCon,pPro->defaultWriter); + SCSetWriteFunc(pMaster,pPro->defaultWriter); + SCSetWriteFunc(pCon,pPro->defaultWriter); break; } pCon->iProtocolID = proID; + pMaster->iProtocolID = proID; SCSendOK(pCon); return 1; } @@ -356,7 +371,7 @@ static int ProtocolList(SConnection* pCon, Protocol* pPro) { SCWrite(pCon, "Usage: protocol {help|list|options|reset} | set protocolName", - eStatus); + eValue); return 1; } @@ -589,7 +604,6 @@ int SCWriteSycamore(SConnection *pCon, char *pBuffer, int iOut) /* first the socket */ /*strcat(pMsg, pBueffel);*/ iRet = SCDoSockWrite(pCon,GetCharArray(pMsg)); - SCWriteToLogFiles(pCon,GetCharArray(pMsg)); } if (pMsg != NULL) DeleteDynString(pMsg); @@ -742,7 +756,6 @@ int SCWriteJSON_String(SConnection *pCon, char *pBuffer, int iOut) iRet = 0; } else { iRet = SCDoSockWrite(pCon,json_object_to_json_string(my_object)); - SCWriteToLogFiles(pCon,pBuffer); } } if (tmp_json != NULL && !is_error(tmp_json)) diff --git a/remob.c b/remob.c index 9a407a7c..ad168088 100644 --- a/remob.c +++ b/remob.c @@ -45,7 +45,7 @@ typedef struct RemServer { int taskActive; int interestActive; int forwardMessages; - SCStore *conn; + SConnection *conn; } RemServer; struct Remob { @@ -156,7 +156,7 @@ static int RemHandle(RemServer *remserver) { /*-------------------------------------------------------------------------*/ static void RemCopy(RemChannel *rc, SConnection *pCon) { if (pCon != NULL && rc->line[0] != '\0') { - SCPrintf(pCon, eStatus, " %s", rc->line); + SCPrintf(pCon, eLog, " %s", rc->line); } } /*-------------------------------------------------------------------------*/ @@ -260,10 +260,8 @@ static int RemServerTask(void *data) { if (remserver->forwardMessages) { /* forward all other messages */ - if (SCStoreConnected(remserver->conn)) { - pCon = SCStorePush(remserver->conn); - RemCopy(rc, pCon); - SCStorePop(remserver->conn); + if (SCisConnected(remserver->conn)) { + RemCopy(rc, remserver->conn); } } } @@ -406,7 +404,10 @@ static float RemobGetValue(void *pData, SConnection *pCon) { assert(remob); - remserver->conn = SCSave(pCon, remserver->conn); + if(remserver->conn != NULL){ + SCDeleteConnection(remserver->conn); + } + remserver->conn = SCCopyConnection(pCon); none = -1.25e6; value= none; snprintf(buf, sizeof(buf), "<%s", remob->name); @@ -457,7 +458,10 @@ static int RemobStatus(void *pData, SConnection *pCon) { assert(remob); - remob->server->conn = SCSave(pCon, remob->server->conn); + if(remob->server->conn != NULL){ + SCDeleteConnection(remob->server->conn); + } + remob->server->conn = SCCopyConnection(pCon); return remob->status; } /*---------------------------------------------------------------------------*/ @@ -475,10 +479,14 @@ static long RemobRun(void *self, SConnection *pCon, float fNew) { RemChannel *rc; int nChan; - remserver = remob->server; - remserver->conn = SCSave(pCon, remserver->conn); assert(remob); assert(pCon); + + remserver = remob->server; + if(remserver->conn != NULL){ + SCDeleteConnection(remserver->conn); + } + remserver->conn = SCCopyConnection(pCon); rights = SCGetRights(pCon); nChan = rights <= usUser; @@ -526,6 +534,9 @@ static void KillInfo(void *pData) { if (self->pName) { free(self->pName); } + if(self->pCon){ + SCDeleteConnection(self->pCon); + } free(self); } /*------------------- The CallBack function for interest ------------------*/ @@ -572,7 +583,10 @@ int RemobAction(SConnection *pCon, SicsInterp *pSics, void *pData, nChan = (rights <= usUser); rc = &remserver->rc[nChan]; if (rights >= usUser) { - remserver->conn = SCSave(pCon, remserver->conn); + if(remserver->conn != NULL){ + SCDeleteConnection(remserver->conn); + } + remserver->conn = SCCopyConnection(pCon); } if (argc == 1) { iRet = RemTransact(remserver, nChan, pCon, remob->name, ">", NULL); @@ -629,7 +643,7 @@ static void RemobKill(void *self) { if (remob->pCall) { DeleteCallBackInterface(remob->pCall); } - + /* kill Descriptor */ if (remob->desc) { DeleteDescriptor(remob->desc); @@ -664,7 +678,10 @@ int RemServerAction(SConnection *pCon, SicsInterp *pSics, void *pData, nChan = (rights <= usUser); rc = &remserver->rc[nChan]; if (nChan) { - remserver->conn = SCSave(pCon, remserver->conn); + if(remserver->conn != NULL){ + SCDeleteConnection(remserver->conn); + } + remserver->conn = SCCopyConnection(pCon); } if (argc == 1) { serverport = IFindOption(pSICSOptions,"ServerPort"); @@ -680,7 +697,7 @@ int RemServerAction(SConnection *pCon, SicsInterp *pSics, void *pData, } } if (thishostname == NULL) thishostname = "undef"; - SCPrintf(pCon, eStatus, "%s = %s:%d %s:%s", + SCPrintf(pCon, eValue, "%s = %s:%d %s:%s", argv[0], remserver->host, remserver->port, thishostname, serverport); } else if (argc>2 && strcasecmp(argv[1],"nowait") == 0) { RemConnect(remserver, nChan); @@ -737,7 +754,9 @@ static void RemServerKill(void *self) { DeleteDescriptor(remserver->desc); if (remserver->name) free(remserver->name); if (remserver->host) free(remserver->host); - SCStoreFree(remserver->conn); + if(remserver->conn != NULL){ + SCDeleteConnection(remserver->conn); + } free(remserver); } /*-----------------------------------------------------------------------*/ diff --git a/rs232controller.c b/rs232controller.c index 9d6c22ca..9d0f9d09 100644 --- a/rs232controller.c +++ b/rs232controller.c @@ -237,7 +237,7 @@ int readRS232TillTerm(prs232 self, void *data, int *datalen){ } else if(iRet == -1) { - printf("Incomplete read: %s\n", (char *)data); + printf("Incomplete read: %s, errno = %d\n", (char *)data, errno); return INCOMPLETE; } else if (iRet < 0) @@ -374,7 +374,7 @@ int transactRS232(prs232 self, void *send, int sendLen, } else { - printf("RS232 IN/TRANS/INCOMPLETE: %s",(char *)reply); + printf("RS232 IN/TRANS/INCOMPLETE: %s, errno = %d",(char *)reply, errno); } } if(iRet == 0) diff --git a/scan.c b/scan.c index e61a3d48..bdfb8cd9 100644 --- a/scan.c +++ b/scan.c @@ -395,7 +395,7 @@ int StoreScanCounts(pScanData self, char *data) if(data == NULL) { SCWrite(self->pCon,"WARNING: StoreScanCounts called without data", - eWarning); + eLog); return 1; } InitCountEntry(&sCount); @@ -409,9 +409,9 @@ int StoreScanCounts(pScanData self, char *data) } else { - SCWrite(self->pCon,"WARNING: No data in StoreScanCounts",eWarning); + SCWrite(self->pCon,"WARNING: No data in StoreScanCounts",eLog); snprintf(pBueffel,255,"Received: %s", data); - SCWrite(self->pCon,pBueffel,eWarning); + SCWrite(self->pCon,pBueffel,eLog); return 1; } pPtr = stptok(pPtr,pNumber,29," \t"); @@ -431,7 +431,7 @@ int StoreScanCounts(pScanData self, char *data) { SCWrite(self->pCon, "ERROR: I have only space for 10 Monitors in count structure", - eError); + eLogError); return 0; } } @@ -484,7 +484,7 @@ CountEntry CollectCounterData(pScanData self) iRet = Tcl_Eval(pTcl,self->pCommand); if(iRet != TCL_OK) { - SCWrite(self->pCon,pTcl->result,eError); + SCWrite(self->pCon,pTcl->result,eLogError); return sCount; } /* interprete the Tcl result as a list of counts @@ -495,7 +495,7 @@ CountEntry CollectCounterData(pScanData self) pPtr = strtok(pAns," "); if(!pPtr) { - SCWrite(self->pCon,"ERROR: no counts found in Tcl-result",eError); + SCWrite(self->pCon,"ERROR: no counts found in Tcl-result",eLogError); } sscanf(pPtr,"%f",&fVal); sCount.lCount = (long)fVal; @@ -559,11 +559,11 @@ CountEntry CollectCounterData(pScanData self) SCSetInterrupt(self->pCon,eContinue); SCWrite(self->pCon, "WARNING: skipped scan point due to motor failure", - eWarning); + eLog); continue; break; case eAbortScan: - SCWrite(self->pCon,"ERROR: Scan aborted",eError); + SCWrite(self->pCon,"ERROR: Scan aborted",eLogError); /* eat the interrupt, the requested op has been done */ @@ -571,14 +571,14 @@ CountEntry CollectCounterData(pScanData self) return 0; break; default: /* all others */ - SCWrite(self->pCon,"ERROR: Scan aborted",eError); + SCWrite(self->pCon,"ERROR: Scan aborted",eLogError); return 0; break; } if(!iRet) { SCWrite(self->pCon,"WARNING: skipped scan point after drive failure", - eWarning); + eLog); continue; } @@ -596,7 +596,7 @@ CountEntry CollectCounterData(pScanData self) continue; break; case eAbortScan: - SCWrite(self->pCon,"ERROR: Scan aborted",eError); + SCWrite(self->pCon,"ERROR: Scan aborted",eLogError); /* eat the interrupt, the requested op has been done */ @@ -604,14 +604,14 @@ CountEntry CollectCounterData(pScanData self) return 0; break; default: /* all others */ - SCWrite(self->pCon,"ERROR: Scan aborted",eError); + SCWrite(self->pCon,"ERROR: Scan aborted",eLogError); return 0; break; } if(!iRet) { SCWrite(self->pCon,"WARNING: skipped scan point after count failure", - eWarning); + eLog); continue; } @@ -1264,8 +1264,7 @@ CountEntry CollectCounterData(pScanData self) return 1; } /*--------------------------------------------------------------------------*/ - static int ScanInterest(int iEvent, void *pEventData, void *pUser, - commandContext cc) + static int ScanInterest(int iEvent, void *pEventData, void *pUser) { pScanData self = NULL; SConnection *pCon = NULL; @@ -1280,14 +1279,18 @@ CountEntry CollectCounterData(pScanData self) assert(self); assert(pCon); + if(!SCisConnected(pCon)){ + return -1; + } + if(iEvent == SCANSTART) { - SCWriteInContext(pCon,"NewScan",eWarning,cc); + SCWrite(pCon,"NewScan",eLog); return 1; } else if(iEvent == SCANEND) { - SCWriteInContext(pCon,"ScanEnd",eWarning,cc); + SCWrite(pCon,"ScanEnd",eLog); return 1; } else if(iEvent == SCANPOINT) @@ -1319,7 +1322,7 @@ CountEntry CollectCounterData(pScanData self) strcat(pPtr,"}"); oldWrite = SCGetWriteFunc(pCon); SCSetWriteFunc(pCon,SCOnlySockWrite); - SCWrite(pCon,pPtr,eWarning); + SCWrite(pCon,pPtr,eLog); SCSetWriteFunc(pCon,oldWrite); free(lData); free(pPtr); @@ -1328,8 +1331,7 @@ CountEntry CollectCounterData(pScanData self) return 1; } /*--------------------------------------------------------------------------*/ - static int ScanDynInterest(int iEvent, void *pEventData, void *pUser, - commandContext cc) + static int ScanDynInterest(int iEvent, void *pEventData, void *pUser) { pScanData self = NULL; SConnection *pCon = NULL; @@ -1347,14 +1349,19 @@ CountEntry CollectCounterData(pScanData self) assert(self); assert(pCon); + if(!SCisConnected(pCon)) + { + return -1; + } + if(iEvent == SCANSTART) { - SCWriteInContext(pCon,"NewScan",eWarning,cc); + SCWrite(pCon,"NewScan",eLog); return 1; } else if(iEvent == SCANEND) { - SCWriteInContext(pCon,"ScanEnd",eWarning,cc); + SCWrite(pCon,"ScanEnd",eLog); return 1; } else if(iEvent == SCANPOINT) @@ -1376,16 +1383,15 @@ CountEntry CollectCounterData(pScanData self) } snprintf(pBueffel,255,"%s.scanpoint = {%d %f %ld}", self->objectName,i,fVal,lVal); - SCWriteInContext(pCon,pBueffel,eValue,cc); + SCWrite(pCon,pBueffel,eLog); } return 1; } /*--------------------------------------------------------------------------*/ - static int ScanUUInterest(int iEvent, void *pEventData, void *pUser, - commandContext cc) + static int ScanUUInterest(int iEvent, void *pEventData, void *pUser) { pScanData self = NULL; - SConnection *pCon = NULL; + SConnection *pCon = NULL, *comCon = NULL; char pItem[20]; long *lData = NULL; int *iData = NULL; @@ -1396,15 +1402,21 @@ CountEntry CollectCounterData(pScanData self) assert(self); assert(pCon); - + /* + printf("ScanUUInterest called for pCon = %p handle %d\n", pCon, pCon->sockHandle); + */ + if(!SCisConnected(pCon)){ + return -1; + } + if(iEvent == SCANSTART) { - SCWriteInContext(pCon,"NewScan",eWarning,cc); + SCWrite(pCon,"NewScan",eLog); return 1; } else if(iEvent == SCANEND) { - SCWriteInContext(pCon,"ScanEnd",eWarning,cc); + SCWrite(pCon,"ScanEnd",eLog); return 1; } else if(iEvent == SCANPOINT) @@ -1426,9 +1438,7 @@ CountEntry CollectCounterData(pScanData self) { iData[i] = htonl((int)lData[i]); } - SCPushContext2(pCon,cc); SCWriteUUencoded(pCon,"ScanData",iData,self->iNP*sizeof(int)); - SCPopContext(pCon); free(lData); free(iData); return 1; @@ -1929,53 +1939,53 @@ static int DumpScan(pScanData self, SConnection *pCon) /*-------- interest */ else if(strcmp(argv[1],"interest") == 0) { - lID = RegisterCallback(self->pCall, SCGetContext(pCon),SCANSTART, ScanInterest, - pCon, NULL); - SCRegister(pCon,pSics, self->pCall,lID); - lID = RegisterCallback(self->pCall, SCGetContext(pCon),SCANEND, ScanInterest, - pCon, NULL); - SCRegister(pCon,pSics, self->pCall,lID); - lID = RegisterCallback(self->pCall, SCGetContext(pCon),SCANPOINT, ScanInterest, - pCon, NULL); - SCRegister(pCon,pSics, self->pCall,lID); + /* + printf("Registering scan callbacks on handle %d\n", pCon->sockHandle); + */ + lID = RegisterCallback(self->pCall, SCANSTART, ScanInterest, + SCCopyConnection(pCon), SCDeleteConnection); + lID = RegisterCallback(self->pCall, SCANEND, ScanInterest, + SCCopyConnection(pCon),SCDeleteConnection); + lID = RegisterCallback(self->pCall, SCANPOINT, ScanInterest, + SCCopyConnection(pCon), SCDeleteConnection); SCSendOK(pCon); return 1; } /*-------- interest */ else if(strcmp(argv[1],"dyninterest") == 0) { - lID = RegisterCallback(self->pCall, SCGetContext(pCon),SCANSTART, ScanDynInterest, - pCon, NULL); - SCRegister(pCon,pSics, self->pCall,lID); - lID = RegisterCallback(self->pCall, SCGetContext(pCon), SCANEND, ScanDynInterest, - pCon, NULL); - SCRegister(pCon,pSics, self->pCall,lID); - lID = RegisterCallback(self->pCall, SCGetContext(pCon),SCANPOINT, ScanDynInterest, - pCon, NULL); - SCRegister(pCon,pSics, self->pCall,lID); + /* + printf("Registering scanDyn callbacks on handle %d\n", pCon->sockHandle); + */ + lID = RegisterCallback(self->pCall, SCANSTART, ScanDynInterest, + SCCopyConnection(pCon), SCDeleteConnection); + lID = RegisterCallback(self->pCall,SCANEND, ScanDynInterest, + SCCopyConnection(pCon), SCDeleteConnection); + lID = RegisterCallback(self->pCall, SCANPOINT, ScanDynInterest, + SCCopyConnection(pCon), SCDeleteConnection); SCSendOK(pCon); return 1; } /*-------- uuinterest */ else if(strcmp(argv[1],"uuinterest") == 0) { - lID = RegisterCallback(self->pCall, SCGetContext(pCon),SCANSTART, ScanUUInterest, - pCon, NULL); - SCRegister(pCon,pSics, self->pCall,lID); - lID = RegisterCallback(self->pCall, SCGetContext(pCon),SCANEND, ScanUUInterest, - pCon, NULL); - SCRegister(pCon,pSics, self->pCall,lID); - lID = RegisterCallback(self->pCall, SCGetContext(pCon),SCANPOINT, ScanUUInterest, - pCon, NULL); - SCRegister(pCon,pSics, self->pCall,lID); + /* + printf("Registering scanUU callbacks on handle %d, con = %p\n", + conSave->sockHandle, conSave); + */ + lID = RegisterCallback(self->pCall, SCANSTART, ScanUUInterest, + SCCopyConnection(pCon), SCDeleteConnection); + lID = RegisterCallback(self->pCall, SCANEND, ScanUUInterest, + SCCopyConnection(pCon),SCDeleteConnection); + lID = RegisterCallback(self->pCall, SCANPOINT, ScanUUInterest, + SCCopyConnection(pCon), SCDeleteConnection); SCSendOK(pCon); return 1; } /* ------- uninterest */ else if(strcmp(argv[1],"uninterest") == 0) { - RemoveCallback2(self->pCall,pCon); - SCUnregister(pCon,self->pCall); + RemoveCallbackCon(self->pCall,pCon); SCSendOK(pCon); return 1; } @@ -2134,7 +2144,7 @@ static int DumpScan(pScanData self, SConnection *pCon) iRet = Tcl_GetInt(InterpGetTcl(pSics),argv[2],&lNP); if(iRet != TCL_OK) { - sprintf(pBueffel,"ERROR: expected number, got %s",argv[3]); + sprintf(pBueffel,"ERROR: expected number, got %s",argv[2]); SCWrite(pCon,pBueffel,eError); return 0; } @@ -2187,7 +2197,7 @@ static int DumpScan(pScanData self, SConnection *pCon) iRet = Tcl_GetInt(InterpGetTcl(pSics),argv[2],&lNP); if(iRet != TCL_OK) { - sprintf(pBueffel,"ERROR: expected number, got %s",argv[3]); + sprintf(pBueffel,"ERROR: expected number, got %s",argv[2]); SCWrite(pCon,pBueffel,eError); return 0; } diff --git a/script.c b/script.c index a539ca7c..5622af40 100644 --- a/script.c +++ b/script.c @@ -79,12 +79,12 @@ if(pOwner) { Interrupt2Text(SCGetInterrupt(pOwner),pBueffel,131); - SCWrite(pCon,pBueffel,eStatus); + SCWrite(pCon,pBueffel,eValue); } else { Interrupt2Text(SCGetInterrupt(pCon),pBueffel,131); - SCWrite(pCon,pBueffel,eStatus); + SCWrite(pCon,pBueffel,eValue); } return 1; } diff --git a/scriptcontext.c b/scriptcontext.c index 4f8524de..6c6b221e 100644 --- a/scriptcontext.c +++ b/scriptcontext.c @@ -33,7 +33,7 @@ typedef struct ScriptContext { struct SctController { DevSer *devser; Hdb *node; /* the controller node */ - SCStore *conn; + SConnection*conn; int verbose; }; @@ -41,13 +41,13 @@ struct SctController { typedef struct SctData { char *name; SctController *controller; - SCStore *conCtx; + SConnection*conCtx; int answered; Hdb *node; } SctData; static ScriptContext *sct = NULL; -static SCStore *currentCon = NULL; +static SConnection *currentCon = NULL; static struct { char *name; @@ -184,6 +184,14 @@ int SctCommand(SConnection *con, SicsInterp *sics, void *object, return 1; } + /** + * controller + */ + if(strcmp(argv[1],"controller") == 0){ + SCWrite(con,cNode->name, eValue); + return 1; + } + /* * time stamping */ @@ -271,9 +279,9 @@ static char *SctActionHandler(void *actionData, char *lastReply) { char timeKey[50], timeVal[50]; if (currentCon) { - con = SCStorePush(currentCon); + con = currentCon; } else { - con = SCStorePush(controller->conn); + con = controller->conn; } SetProp(node, controller->node, "result", lastReply); if (controller->verbose && lastReply != NULL && *lastReply != '\0') { @@ -310,26 +318,16 @@ static char *SctActionHandler(void *actionData, char *lastReply) { send = GetProp(node, controller->node, "send"); if (send != NULL && send[0] != '\0') { if (controller->verbose) { - SCPrintf(con, eWarning, "send : %s", send); - } - if (currentCon) { - SCStorePop(currentCon); - } else { - SCStorePop(controller->conn); + SCPrintf(con, eLog, "send : %s", send); } return send; } } - SCPrintf(con, eError, "ERROR: too many quick scripts chained"); + SCPrintf(con, eLogError, "ERROR: too many quick scripts chained"); finish: SetProp(node, controller->node, "state", "idle"); - if (currentCon) { - SCStorePop(currentCon); - } else { - SCStorePop(controller->conn); - } if (data->conCtx != NULL) { - SCStoreFree(data->conCtx); + SCDeleteConnection(data->conCtx); data->conCtx = NULL; } return send; @@ -337,7 +335,7 @@ finish: static char *SctWriteHandler(void *actionData, char *lastReply) { SctData *data = actionData; - SCStore *old; + SConnection*old; char *result; old = currentCon; @@ -470,14 +468,12 @@ static hdbCallbackReturn SctActionCallback(Hdb *node, void *userData, } if (data->conCtx != NULL) { - con2 = SCStorePush(data->conCtx); GetHdbPath(node, path, sizeof path); - SCPrintf(con2, eValue, "%s target changed to %s before completion", + SCPrintf(data->conCtx, eLog, "%s target changed to %s before completion", path, GetCharArray(text)); - SCStorePop(data->conCtx); } DeleteDynString(text); - data->conCtx = SCSave(con, data->conCtx); + data->conCtx = SCCopyConnection(con); data->answered = 0; DevQueue(data->controller->devser, data, prio, SctWriteHandler, SctMatch, NULL); @@ -490,12 +486,12 @@ static hdbCallbackReturn SctActionCallback(Hdb *node, void *userData, if (currentCon) { /* update called from a write action */ data->answered = 1; GetHdbPath(node, path, sizeof path); - con = SCStorePush(currentCon); + con = currentCon; text = formatValue(*(mm->v), node); - SCPrintf(con, eStatus, "%s = %s", path, + /* Markus: who is receiving this message? */ + SCPrintf(con, eLog, "%s = %s", path, GetCharArray(text)); DeleteDynString(text); - SCStorePop(currentCon); } return hdbContinue; } @@ -537,7 +533,7 @@ static void SctKillData(void *d) { SctData *data = d; if (data->name) free(data->name); - if (data->conCtx) SCStoreFree(data->conCtx); + if (data->conCtx) SCDeleteConnection(data->conCtx); free(data); } @@ -564,7 +560,7 @@ int SctAddPollNode(SctController *controller, Hdb *node, double interval, assert(data); data->controller = controller; data->node = node; - data->conCtx = NULL; + data->conCtx = NULL; /* we might need a dummy connection here */ data->name = strdup(action); return DevSchedule(controller->devser, data, prio, interval, @@ -755,10 +751,16 @@ void SctQueueNode(SctController *controller, Hdb *node, data->name = strdup(action); data->conCtx = NULL; - DevQueue(data->controller->devser, data, prio, - SctWriteHandler, SctMatch, SctKillData); - if (con != NULL) { - data->conCtx = SCSave(con, NULL); + if(!DevQueue(data->controller->devser, data, prio, + SctWriteHandler, SctMatch, SctKillData)){ + if(data->name != NULL){ + free(data->name); + } + free(data); + } else { + if (con != NULL) { + data->conCtx = SCCopyConnection(con); + } } return; } @@ -813,6 +815,9 @@ static void KillSctTransact(void *data){ if(self->command){ free(self->command); } + if(self->con){ + SCDeleteConnection(self->con); + } free(self); } @@ -844,7 +849,7 @@ static int SctTransactCmd(pSICSOBJ ccmd, SConnection *con, SCWrite(con,"ERROR: out of memory in SctTransactCommand", eError); return 0; } - st->con = con; + st->con = SCCopyConnection(con); st->command = strdup(par[0]->value.v.text); DevQueue(c->devser, st, WritePRIO, @@ -863,6 +868,8 @@ static int SctSendCmd(pSICSOBJ ccmd, SConnection *con, Hdb *cmdNode, Hdb *par[], int nPar) { pSctTransact st = NULL; SctController *c; + char *prioText = NULL; + int prio; c = (SctController *)ccmd->pPrivate; @@ -871,14 +878,28 @@ static int SctSendCmd(pSICSOBJ ccmd, SConnection *con, SCWrite(con,"ERROR: out of memory in SctSendCmd", eError); return 0; } - st->con = con; + st->con = SCCopyConnection(con); st->command = strdup(par[0]->value.v.text); - DevQueue(c->devser, st, WritePRIO, + prioText = ParText(cmdNode, "prio", nPar, "write"); + prio = DevText2Prio(prioText); + if(prio == NullPRIO){ + prio = WritePRIO; + } + + DevQueue(c->devser, st, prio, TransactionHandler, SctTransactMatch, KillSctTransact); return 1; } +static int SctDisconnect(pSICSOBJ ccmd, SConnection *con, + Hdb *cmdNode, Hdb *par[], int nPar) { + SctController *c; + + c = (SctController *)ccmd->pPrivate; + DevDisconnect(c->devser); + return 1; +} static hdbCallbackReturn SctDebugCallback(Hdb *node, void *userData, hdbMessage *msg) { @@ -911,9 +932,7 @@ static void SctKillController(void *c) { CleanStack(controller->node); RemoveSICSInternalCallback(controller); if (controller->conn) { - con = SCLoad(controller->conn); - SCDeleteConnection(con); - SCStoreFree(controller->conn); + SCDeleteConnection(controller->conn); } DevKill(controller->devser); free(controller); @@ -943,7 +962,7 @@ static int SctMakeController(SConnection *con, SicsInterp *sics, ccmd = MakeSICSOBJv(nodeName, "SctController", HIPNONE, usSpy); controller->node = ccmd->objectNode; - controller->conn = SCSave(SCCreateDummyConnection(pServ->pSics), NULL); + controller->conn = SCCreateDummyConnection(pServ->pSics); assert(ccmd); assert(controller->node->mama == NULL); @@ -992,8 +1011,11 @@ static int SctMakeController(SConnection *con, SicsInterp *sics, cmd = AddSICSHdbPar(controller->node, "send", usMugger, MakeSICSFunc(SctSendCmd)); AddSICSHdbPar(cmd, "data", usMugger, MakeHdbText("")); + AddSICSHdbPar(cmd, "prio", usMugger, MakeHdbText("")); - + cmd = AddSICSHdbPar(controller->node, + "disconnect", usMugger, MakeSICSFunc(SctDisconnect)); + par = AddSICSHdbPar(controller->node, "debug", usUser, MakeHdbInt(-1)); cb = MakeHipadabaCallback(SctDebugCallback, controller, NULL); diff --git a/selector.c b/selector.c index ac817eda..1438dd6f 100644 --- a/selector.c +++ b/selector.c @@ -356,28 +356,28 @@ end: /* print known parameters */ iLen = ObParLength(self->pParams); sprintf(pBueffel,"Parameter Listing for %s\n",self->name); - SCWrite(pCon,pBueffel,eStatus); + SCWrite(pCon,pBueffel,eValue); for(i = 0; i < iLen; i++) { sprintf(pBueffel,"%s.%s = %f\n",self->name, self->pParams[i].name,self->pParams[i].fVal); - SCWrite(pCon,pBueffel,eStatus); + SCWrite(pCon,pBueffel,eValue); } /* print motornames as well */ sprintf(pBueffel,"%s.ThetaMotor = %s\n",self->name,self->pTheta->name); - SCWrite(pCon,pBueffel,eStatus); + SCWrite(pCon,pBueffel,eValue); sprintf(pBueffel,"%s.TwoThetaMotor = %s\n",self->name,self->pTwoTheta->name); - SCWrite(pCon,pBueffel,eStatus); + SCWrite(pCon,pBueffel,eValue); if(self->pBend1) { sprintf(pBueffel,"%s.VerticalBenderMotor = %s\n",self->name,self->pBend1->name); - SCWrite(pCon,pBueffel,eStatus); + SCWrite(pCon,pBueffel,eValue); } if(self->pBend2) { sprintf(pBueffel,"%s.HorizontalBenderMotor = %s\n",self->name,self->pBend2->name); - SCWrite(pCon,pBueffel,eStatus); + SCWrite(pCon,pBueffel,eValue); } } /*----------------------------------------------------------------------------- @@ -790,7 +790,7 @@ end: { sprintf(pBueffel,"WARNING: monochromator %s out of sync by %f\n", self->name,fVal); - SCWrite(pCon,pBueffel,eStatus); + SCWrite(pCon,pBueffel,eWarning); } /* calculate wavelength from angles */ diff --git a/selvar.c b/selvar.c index a8533910..02683d8d 100644 --- a/selvar.c +++ b/selvar.c @@ -480,8 +480,7 @@ return 1; } /*------------------------------------------------------------------------*/ - static int WaveLengthCallBack(int iEvent, void *pEvent, void *pUser, - commandContext cc) + static int WaveLengthCallBack(int iEvent, void *pEvent, void *pUser) { SConnection *pCon = NULL; pSelVar self = NULL; @@ -493,9 +492,14 @@ assert(pCon); assert(self); + if(pCon == NULL || !SCisConnected(pCon)) + { + return -1; + } + fVal = GetSelValue(self,pCon); sprintf(pBueffel,"%s.value = %f", self->name, fVal); - SCWriteInContext(pCon,pBueffel,eValue,cc); + SCWrite(pCon,pBueffel,eValue); return 1; } /*-------------------------------------------------------------------------- @@ -527,10 +531,9 @@ strtolower(argv[1]); if(strcmp(argv[1],"interest") == 0) { - lID = RegisterCallback(self->pCall, SCGetContext(pCon), + lID = RegisterCallback(self->pCall, WLCHANGE, WaveLengthCallBack, - pCon, NULL); - SCRegister(pCon,pSics, self->pCall,lID); + SCCopyConnection(pCon), SCDeleteConnection); SCSendOK(pCon); return 1; } @@ -570,7 +573,7 @@ { fWave = GetMonoPosition(self->pSel,pCon); sprintf(pBueffel,"%s = %f",argv[0],fWave); - SCWrite(pCon,pBueffel,eStatus); + SCWrite(pCon,pBueffel,eValue); return 1; } return 0; @@ -597,10 +600,9 @@ strtolower(argv[1]); if(strcmp(argv[1],"interest") == 0) { - lID = RegisterCallback(self->pCall, SCGetContext(pCon), + lID = RegisterCallback(self->pCall, WLCHANGE, WaveLengthCallBack, pCon, NULL); - SCRegister(pCon,pSics, self->pCall,lID); SCSendOK(pCon); return 1; } @@ -644,7 +646,7 @@ fWave = 777.77; } sprintf(pBueffel,"%s = %f",argv[0],fWave); - SCWrite(pCon,pBueffel,eStatus); + SCWrite(pCon,pBueffel,eValue); return 1; } return 0; diff --git a/servlog.c b/servlog.c index a6ebb607..d5e4e133 100644 --- a/servlog.c +++ b/servlog.c @@ -284,8 +284,8 @@ { if( (pCurrent->iOut == eOut) || (pCurrent->iAllFlag == 1) ) { - NETWrite(pCurrent->pCon->pSock,pText,strlen(pText)); - NETWrite(pCurrent->pCon->pSock,"\n",1); + ANETwrite(pCurrent->pCon->sockHandle,pText,strlen(pText)); + ANETwrite(pCurrent->pCon->sockHandle,"\n",1); } pCurrent = pCurrent->pNext; } diff --git a/sgclib.c b/sgclib.c new file mode 100644 index 00000000..76ec59f2 --- /dev/null +++ b/sgclib.c @@ -0,0 +1,2505 @@ +/* + Space Group Info's (c) 1994-96 Ralf W. Grosse-Kunstleve + */ + +#include +#include +#include + + +#define SGCLIB_C__ +#include "sginfo.h" + + +static const char *Err_Ill_SMx_in_List = + "Error: Illegal SeitzMx in list"; + + +void SetSgError(const char *msg) +{ + if (SgError == NULL) SgError = msg; +} + + +int iModPositive(int ix, int iy) +{ + if (iy > 0) + { + ix %= iy; + if (ix < 0) ix += iy; + } + + return ix; +} + + +static void SwapRTMx(T_RTMx *Mx_a, T_RTMx *Mx_b) +{ + int i; + T_RTMx BufMx; + + + for (i = 0; i < 12; i++) BufMx.a[i] = Mx_a->a[i]; + for (i = 0; i < 12; i++) Mx_a->a[i] = Mx_b->a[i]; + for (i = 0; i < 12; i++) Mx_b->a[i] = BufMx.a[i]; +} + + +static void CopyRotMxInfo(T_RotMxInfo *target, const T_RotMxInfo *source) +{ + memcpy(target, source, sizeof (*target)); +} + + +static void SwapRotMxInfo(T_RotMxInfo *RMx_a, T_RotMxInfo *RMx_b) +{ + T_RotMxInfo Buffer; + + memcpy(&Buffer, RMx_a, sizeof (Buffer)); + memcpy(RMx_a, RMx_b, sizeof (Buffer)); + memcpy(RMx_b, &Buffer, sizeof (Buffer)); +} + + +int traceRotMx(const int *RotMx) +{ + return RotMx[0] + RotMx[4] + RotMx[8]; +} + + +int deterRotMx(const int *RotMx) +{ + int det; + + det = RotMx[0] * (RotMx[4] * RotMx[8] - RotMx[5] * RotMx[7]); + det -= RotMx[1] * (RotMx[3] * RotMx[8] - RotMx[5] * RotMx[6]); + det += RotMx[2] * (RotMx[3] * RotMx[7] - RotMx[4] * RotMx[6]); + + return det; +} + + +void RotMx_t_Vector(int *R_t_V, const int *RotMx, const int *Vector, int FacTr) +{ + const int *vec; + + + if (FacTr > 0) + { + vec = Vector; + *R_t_V = *RotMx++ * *vec++; + *R_t_V += *RotMx++ * *vec++; + *R_t_V += *RotMx++ * *vec; + *R_t_V %= FacTr; if (*R_t_V < 0) *R_t_V += FacTr; + R_t_V++; + vec = Vector; + *R_t_V = *RotMx++ * *vec++; + *R_t_V += *RotMx++ * *vec++; + *R_t_V += *RotMx++ * *vec; + *R_t_V %= FacTr; if (*R_t_V < 0) *R_t_V += FacTr; + R_t_V++; + vec = Vector; + *R_t_V = *RotMx++ * *vec++; + *R_t_V += *RotMx++ * *vec++; + *R_t_V += *RotMx * *vec; + *R_t_V %= FacTr; if (*R_t_V < 0) *R_t_V += FacTr; + } + else + { + vec = Vector; + *R_t_V = *RotMx++ * *vec++; + *R_t_V += *RotMx++ * *vec++; + *R_t_V++ += *RotMx++ * *vec; + vec = Vector; + *R_t_V = *RotMx++ * *vec++; + *R_t_V += *RotMx++ * *vec++; + *R_t_V++ += *RotMx++ * *vec; + vec = Vector; + *R_t_V = *RotMx++ * *vec++; + *R_t_V += *RotMx++ * *vec++; + *R_t_V += *RotMx * *vec; + } +} + + +void RotMxMultiply(int *rmxab, const int *rmxa, const int *rmxb) +{ + const int *a, *b; + + /* no loops to be as fast as posslible */ + + a = rmxa; + b = rmxb; + *rmxab = *a++ * *b; b += 3; /* r11 */ + *rmxab += *a++ * *b; b += 3; + *rmxab += *a * *b; b -= 5; + rmxab++; + + a = rmxa; + *rmxab = *a++ * *b; b += 3; /* r12 */ + *rmxab += *a++ * *b; b += 3; + *rmxab += *a * *b; b -= 5; + rmxab++; + + a = rmxa; + *rmxab = *a++ * *b; b += 3; /* r13 */ + *rmxab += *a++ * *b; b += 3; + *rmxab += *a++ * *b; b = rmxb; + rmxab++; + + rmxa = a; + *rmxab = *a++ * *b; b += 3; /* r21 */ + *rmxab += *a++ * *b; b += 3; + *rmxab += *a * *b; b -= 5; + rmxab++; + + a = rmxa; + *rmxab = *a++ * *b; b += 3; /* r22 */ + *rmxab += *a++ * *b; b += 3; + *rmxab += *a * *b; b -= 5; + rmxab++; + + a = rmxa; + *rmxab = *a++ * *b; b += 3; /* r23 */ + *rmxab += *a++ * *b; b += 3; + *rmxab += *a++ * *b; b = rmxb; + rmxab++; + + rmxa = a; + *rmxab = *a++ * *b; b += 3; /* r31 */ + *rmxab += *a++ * *b; b += 3; + *rmxab += *a * *b; b -= 5; + rmxab++; + + a = rmxa; + *rmxab = *a++ * *b; b += 3; /* r32 */ + *rmxab += *a++ * *b; b += 3; + *rmxab += *a * *b; b -= 5; + rmxab++; + + a = rmxa; + *rmxab = *a++ * *b; b += 3; /* r33 */ + *rmxab += *a++ * *b; b += 3; + *rmxab += *a * *b; +} + + +void RotateRotMx(int *RotMx, const int *RMx, const int *InvRMx) +{ + int BufMx[9]; + + + RotMxMultiply(BufMx, RotMx, InvRMx); + RotMxMultiply(RotMx, RMx, BufMx); +} + + +void SeitzMxMultiply(T_RTMx *smxab, const T_RTMx *smxa, const T_RTMx *smxb) +{ + const int *ar, *a, *b, *bt; + int *ab; + + /* no loops to be as fast as posslible */ + + ar = smxa->a; + a = smxa->a; + b = smxb->a; + ab = smxab->a; + + *ab = *a++ * *b; b += 3; /* r11 */ + *ab += *a++ * *b; b += 3; + *ab += *a * *b; b -= 5; + ab++; + + a = ar; + *ab = *a++ * *b; b += 3; /* r12 */ + *ab += *a++ * *b; b += 3; + *ab += *a * *b; b -= 5; + ab++; + + a = ar; + *ab = *a++ * *b; b += 3; /* r13 */ + *ab += *a++ * *b; b += 3; + *ab += *a++ * *b; b = smxb->a; + ab++; + + ar = a; + *ab = *a++ * *b; b += 3; /* r21 */ + *ab += *a++ * *b; b += 3; + *ab += *a * *b; b -= 5; + ab++; + + a = ar; + *ab = *a++ * *b; b += 3; /* r22 */ + *ab += *a++ * *b; b += 3; + *ab += *a * *b; b -= 5; + ab++; + + a = ar; + *ab = *a++ * *b; b += 3; /* r23 */ + *ab += *a++ * *b; b += 3; + *ab += *a++ * *b; b = smxb->a; + ab++; + + ar = a; + *ab = *a++ * *b; b += 3; /* r31 */ + *ab += *a++ * *b; b += 3; + *ab += *a * *b; b -= 5; + ab++; + + a = ar; + *ab = *a++ * *b; b += 3; /* r32 */ + *ab += *a++ * *b; b += 3; + *ab += *a * *b; b -= 5; + ab++; + + a = ar; + *ab = *a++ * *b; b += 3; /* r33 */ + *ab += *a++ * *b; b += 3; + *ab += *a++ * *b++; bt = b; + ab++; + + ar = smxa->a; + *ab = *ar++ * *b++; /* t1 */ + *ab += *ar++ * *b++; + *ab += *ar++ * *b; b = bt; + *ab += *a++; + *ab %= STBF; if (*ab < 0) *ab += STBF; + ab++; + + *ab = *ar++ * *b++; /* t2 */ + *ab += *ar++ * *b++; + *ab += *ar++ * *b; b = bt; + *ab += *a++; + *ab %= STBF; if (*ab < 0) *ab += STBF; + ab++; + + *ab = *ar++ * *b++; /* t3 */ + *ab += *ar++ * *b++; + *ab += *ar * *b; + *ab += *a; + *ab %= STBF; if (*ab < 0) *ab += STBF; +} + + +void RTMxMultiply(T_RTMx *rtmxab, const T_RTMx *rtmxa, const T_RTMx *rtmxb, + int FacAug, int FacTr) +{ + const int *ar, *a, *b, *bt; + int *ab; + + /* no loops to be as fast as posslible */ + + ar = rtmxa->a; + a = rtmxa->a; + b = rtmxb->a; + ab = rtmxab->a; + + *ab = *a++ * *b; b += 3; /* r11 */ + *ab += *a++ * *b; b += 3; + *ab += *a * *b; b -= 5; + ab++; + + a = ar; + *ab = *a++ * *b; b += 3; /* r12 */ + *ab += *a++ * *b; b += 3; + *ab += *a * *b; b -= 5; + ab++; + + a = ar; + *ab = *a++ * *b; b += 3; /* r13 */ + *ab += *a++ * *b; b += 3; + *ab += *a++ * *b; b = rtmxb->a; + ab++; + + ar = a; + *ab = *a++ * *b; b += 3; /* r21 */ + *ab += *a++ * *b; b += 3; + *ab += *a * *b; b -= 5; + ab++; + + a = ar; + *ab = *a++ * *b; b += 3; /* r22 */ + *ab += *a++ * *b; b += 3; + *ab += *a * *b; b -= 5; + ab++; + + a = ar; + *ab = *a++ * *b; b += 3; /* r23 */ + *ab += *a++ * *b; b += 3; + *ab += *a++ * *b; b = rtmxb->a; + ab++; + + ar = a; + *ab = *a++ * *b; b += 3; /* r31 */ + *ab += *a++ * *b; b += 3; + *ab += *a * *b; b -= 5; + ab++; + + a = ar; + *ab = *a++ * *b; b += 3; /* r32 */ + *ab += *a++ * *b; b += 3; + *ab += *a * *b; b -= 5; + ab++; + + a = ar; + *ab = *a++ * *b; b += 3; /* r33 */ + *ab += *a++ * *b; b += 3; + *ab += *a++ * *b++; bt = b; + ab++; + + if (FacTr > 0) + { + ar = rtmxa->a; + *ab = *ar++ * *b++; /* t1 */ + *ab += *ar++ * *b++; + *ab += *ar++ * *b; b = bt; + *ab += *a++ * FacAug; + *ab %= FacTr; if (*ab < 0) *ab += FacTr; + ab++; + + *ab = *ar++ * *b++; /* t2 */ + *ab += *ar++ * *b++; + *ab += *ar++ * *b; b = bt; + *ab += *a++ * FacAug; + *ab %= FacTr; if (*ab < 0) *ab += FacTr; + ab++; + + *ab = *ar++ * *b++; /* t3 */ + *ab += *ar++ * *b++; + *ab += *ar * *b; + *ab += *a * FacAug; + *ab %= FacTr; if (*ab < 0) *ab += FacTr; + } + else + { + ar = rtmxa->a; + *ab = *ar++ * *b++; /* t1 */ + *ab += *ar++ * *b++; + *ab += *ar++ * *b; b = bt; + *ab += *a++ * FacAug; + ab++; + + *ab = *ar++ * *b++; /* t2 */ + *ab += *ar++ * *b++; + *ab += *ar++ * *b; b = bt; + *ab += *a++ * FacAug; + ab++; + + *ab = *ar++ * *b++; /* t3 */ + *ab += *ar++ * *b++; + *ab += *ar * *b; + *ab += *a * FacAug; + } +} + + +void InverseRotMx(const int *RotMx, int *InvRotMx) +{ + InvRotMx[0] = RotMx[4] * RotMx[8] - RotMx[5] * RotMx[7]; + InvRotMx[1] = - RotMx[1] * RotMx[8] + RotMx[2] * RotMx[7]; + InvRotMx[2] = RotMx[1] * RotMx[5] - RotMx[2] * RotMx[4]; + InvRotMx[3] = - RotMx[3] * RotMx[8] + RotMx[5] * RotMx[6]; + InvRotMx[4] = RotMx[0] * RotMx[8] - RotMx[2] * RotMx[6]; + InvRotMx[5] = - RotMx[0] * RotMx[5] + RotMx[2] * RotMx[3]; + InvRotMx[6] = RotMx[3] * RotMx[7] - RotMx[4] * RotMx[6]; + InvRotMx[7] = - RotMx[0] * RotMx[7] + RotMx[1] * RotMx[6]; + InvRotMx[8] = RotMx[0] * RotMx[4] - RotMx[1] * RotMx[3]; +} + + +void InverseRTMx(const T_RTMx *RTMx, T_RTMx *InvRTMx) +{ + int *iR; + const int *T; + + + iR = InvRTMx->s.R; + + InverseRotMx(RTMx->s.R, iR); + + T = RTMx->s.T; + + InvRTMx->s.T[0] = - iR[0] * T[0] - iR[1] * T[1] - iR[2] * T[2]; + InvRTMx->s.T[1] = - iR[3] * T[0] - iR[4] * T[1] - iR[5] * T[2]; + InvRTMx->s.T[2] = - iR[6] * T[0] - iR[7] * T[1] - iR[8] * T[2]; +} + + +int IsSMxTransl0(const T_LatticeInfo *LatticeInfo, const int *SeitzMxT) +{ + int iTrV, nTrV, t; + const int *TrV; + + + nTrV = LatticeInfo->nTrVector; + TrV = LatticeInfo->TrVector; + + for (iTrV = 0; iTrV < nTrV; iTrV++) + { + t = (SeitzMxT[0] + TrV[0]) % STBF; + if (t == 0) { + t = (SeitzMxT[1] + TrV[1]) % STBF; + if (t == 0) { + t = (SeitzMxT[2] + TrV[2]) % STBF; + if (t == 0) + return 1; + }} + + TrV += 3; + } + + return 0; +} + + +static int IsSpecialSeitzMx(T_SgInfo *SgInfo, const T_RTMx *SMx, int ExpandLT) +{ + int i, special, smx11; + const T_LatticeInfo *ExpLT; + + + /* check rotation part for identity or inversion operation */ + + smx11 = SMx->s.R[0]; + if ( smx11 != 1 + && smx11 != -1) return 0; + + for (i = 1; i < 9; i++) + { + if (i % 4) { + if (SMx->s.R[i] != 0) return 0; } + else { + if (SMx->s.R[i] != smx11) return 0; } + } + + if (smx11 == 1) special = SpecialSMx_Identity; + else special = SpecialSMx_Inversion; + + /* rotation part is identity or inversion + check translation part now + */ + + if (IsSMxTransl0(SgInfo->LatticeInfo, SMx->s.T) == 1) + return (special | SpecialSMx_Transl0); + + if (ExpandLT && (smx11 == 1 || SgInfo->Centric)) + { + /* try to expand lattice type */ + + ExpLT = NULL; + + switch (SgInfo->LatticeInfo->Code) + { + case 'P': + if (IsSMxTransl0(LI_A, SMx->s.T) == 1) + { ExpLT = LI_A; break; } + if (IsSMxTransl0(LI_B, SMx->s.T) == 1) + { ExpLT = LI_B; break; } + if (IsSMxTransl0(LI_C, SMx->s.T) == 1) + { ExpLT = LI_C; break; } + if (IsSMxTransl0(LI_I, SMx->s.T) == 1) + { ExpLT = LI_I; break; } + if (IsSMxTransl0(LI_R, SMx->s.T) == 1) + { ExpLT = LI_R; break; } + if (IsSMxTransl0(LI_S, SMx->s.T) == 1) + { ExpLT = LI_S; break; } + if (IsSMxTransl0(LI_T, SMx->s.T) == 1) + { ExpLT = LI_T; break; } + case 'A': + case 'B': + case 'C': + if (IsSMxTransl0(LI_F, SMx->s.T) == 1) + ExpLT = LI_F; + } + + if (ExpLT != NULL) + { + SgInfo->LatticeInfo = ExpLT; + SgInfo->StatusLatticeTr = -1; + return (special | SpecialSMx_Transl0); + } + } + + return special; +} + + +int CompareSeitzMx(const T_LatticeInfo *LatticeInfo, + const T_RTMx *SeitzMxA, const T_RTMx *SeitzMxB) +{ + int i, iTrV, nTrV, t; + const int *TrV; + + + /* compare rotation part */ + + for (i = 0; i < 9; i++) + if (SeitzMxA->s.R[i] != SeitzMxB->s.R[i]) return 1; + + /* rotation part is same + check translation + */ + + nTrV = LatticeInfo->nTrVector; + TrV = LatticeInfo->TrVector; + + for (iTrV = 0; iTrV < nTrV; iTrV++, TrV += 3) + { + t = (SeitzMxA->s.T[0] + TrV[0]) % STBF; + if (t == SeitzMxB->s.T[0]) { + t = (SeitzMxA->s.T[1] + TrV[1]) % STBF; + if (t == SeitzMxB->s.T[1]) { + t = (SeitzMxA->s.T[2] + TrV[2]) % STBF; + if (t == SeitzMxB->s.T[2]) + return 0; + }} + } + + return -1; +} + + +int GetRotMxOrder(const int *RotMx) +{ + int deter = deterRotMx(RotMx); + + if (deter == -1 || deter == 1) + { + switch (traceRotMx(RotMx)) + { + case -3: return -1; + case -2: return -6; + case -1: if (deter == -1) return -4; + else return 2; + case 0: if (deter == -1) return -3; + else return 3; + case 1: if (deter == -1) return -2; + else return 4; + case 2: return 6; + case 3: return 1; + } + } + + return 0; +} + + +static int nNextBasis_of_DirCode(const int DirCode, + const int **RMx, const int **InvRMx) +{ + switch (DirCode) + { + case '.': *RMx = *InvRMx = NULL; return 1; + case '=': + case '"': + case '\'': + case '|': + case '\\': *RMx = RMx_3_111; *InvRMx = RMx_3i111; return 3; + case '*': *RMx = RMx_4_001; *InvRMx = RMx_4i001; return 4; + default: + break; + } + + SetSgError("Internal Error: Corrupt DirCode"); + return -1; +} + + +int GetRotMxInfo(const int *RotMx, T_RotMxInfo *RotMxInfo) +{ + int i; + int nNextBasis, iNextBasis; + int nLoopInv, iLoopInv; + int Order, AbsOrder; + int RMxCopy[9], MatchMx[9], InvMatchMx[9], REV[3]; + int *mmx; + const int *NBRMx, *InvNBRMx; + + const T_TabXtalRotMx *txrmx; + + + Order = GetRotMxOrder(RotMx); + + if (RotMxInfo) + RotMxInfo->Order = Order; + + if (Order) + { + AbsOrder = abs(Order); + + if (Order > 0) + for (i = 0; i < 9; i++) RMxCopy[i] = RotMx[i]; + else + for (i = 0; i < 9; i++) RMxCopy[i] = -RotMx[i]; + + for (txrmx = TabXtalRotMx; txrmx->Order; txrmx++) + if (txrmx->Order == AbsOrder) break; + + while (txrmx->Order == AbsOrder) + { + nNextBasis = nNextBasis_of_DirCode(txrmx->DirCode, &NBRMx, &InvNBRMx); + + if (nNextBasis < 0) + return 0; + + if (AbsOrder > 2) nLoopInv = 2; + else nLoopInv = 1; + + for (i = 0; i < 9; i++) MatchMx[i] = txrmx->RMx[i]; + + for (iNextBasis = 0; iNextBasis < nNextBasis; iNextBasis++) + { + if (iNextBasis) + RotateRotMx(MatchMx, NBRMx, InvNBRMx); + + mmx = MatchMx; + + for (iLoopInv = 0; iLoopInv < nLoopInv; iLoopInv++) + { + if (iLoopInv) + { + InverseRotMx(MatchMx, InvMatchMx); + mmx = InvMatchMx; + } + + for (i = 0; i < 9; i++) + if (mmx[i] != RMxCopy[i]) break; + + if (i == 9) /* matrix has been found */ + { + if (RotMxInfo) + { + RotMxInfo->Inverse = iLoopInv; + + if (nNextBasis == 3) + { + switch(iNextBasis) + { + case 0: RotMxInfo->RefAxis = 'z'; break; + case 1: RotMxInfo->RefAxis = 'x'; break; + case 2: RotMxInfo->RefAxis = 'y'; break; + } + } + else + RotMxInfo->RefAxis = 'o'; + + RotMxInfo->DirCode = txrmx->DirCode; + + for (i = 0; i < 3; i++) + RotMxInfo->EigenVector[i] = txrmx->EigenVector[i]; + + for (; iNextBasis--;) + { + RotMx_t_Vector(REV, NBRMx, RotMxInfo->EigenVector, 0); + + if (iNextBasis-- == 0) + { + for (i = 0; i < 3; i++) + RotMxInfo->EigenVector[i] = REV[i]; + + break; + } + + RotMx_t_Vector(RotMxInfo->EigenVector, NBRMx, REV, 0); + } + } + + return Order; + } + } + } + + txrmx++; + } + } + + return 0; +} + + +const T_RotMxInfo *ListOrBufRotMxInfo(const T_SgInfo *SgInfo, int iList, + T_RotMxInfo *BufRotMxInfo) +{ + T_RotMxInfo *RMxI; + + + RMxI = SgInfo->ListRotMxInfo; + if (RMxI) + RMxI += iList; + else + { + RMxI = BufRotMxInfo; + + if (GetRotMxInfo(SgInfo->ListSeitzMx[iList].s.R, RMxI) == 0) { + SetSgError(Err_Ill_SMx_in_List); + return NULL; + } + } + + return RMxI; +} + + +static int CoreAdd2ListSeitzMx(T_SgInfo *SgInfo, const T_RTMx *NewSMx) +{ + int i, iList; + T_RTMx *lsmx; + T_RotMxInfo RotMxInfo; + const T_LatticeInfo *LI; + + static const char *Err_NonXtalOp = + "Error: Generators produce non-crystallographic operation"; + + + if (SgInfo->GenOption) LI = SgInfo->LatticeInfo; + else LI = LI_P; + + lsmx = SgInfo->ListSeitzMx; + + for (iList = 0; iList < SgInfo->nList; iList++, lsmx++) + if (CompareSeitzMx(LI, NewSMx, lsmx) == 0) + return 0; /* matrix is not unique */ + + if (GetRotMxInfo(NewSMx->s.R, &RotMxInfo) == 0) { + SetSgError(Err_NonXtalOp); + return -1; + } + + if (SgInfo->nList >= SgInfo->MaxList) + { + if (SgInfo->nList >= 192) + SetSgError(Err_NonXtalOp); + else + SetSgError("Internal Error: Allocated space for ListSeitzMx too small"); + + return -1; + } + + for (i = 0; i < 12; i++) lsmx->a[i] = NewSMx->a[i]; + + if (SgInfo->ListRotMxInfo != NULL) + CopyRotMxInfo(&SgInfo->ListRotMxInfo[SgInfo->nList], &RotMxInfo); + + SgInfo->nList++; + + return 1; +} + + +int Add2ListSeitzMx(T_SgInfo *SgInfo, const T_RTMx *NewSMx) +{ + int i, special, Enter; + int iMult, jMult; + T_RTMx TrialSMx, *iMultSMx, *jMultSMx; + + static const char *Err_Ill_lattice_translation = + "Error: Illegal lattice translation"; + + + if (SgInfo->nList == 0) + { + /* make sure identity matrix is first in list */ + + InitSeitzMx(&TrialSMx, 1); + + if (CoreAdd2ListSeitzMx(SgInfo, &TrialSMx) < 0) + return -1;; + } + + for (i = 0; i < 9; i++) + TrialSMx.s.R[i] = NewSMx->s.R[i]; + + for (i = 0; i < 3; i++) { + TrialSMx.s.T[i] = NewSMx->s.T[i] % STBF; + if (TrialSMx.s.T[i] < 0) + TrialSMx.s.T[i] += STBF; + } + + iMult = SgInfo->nList; + iMultSMx = &SgInfo->ListSeitzMx[iMult]; + + jMult = 1; + jMultSMx = &SgInfo->ListSeitzMx[1]; /* skip first = identity matrix */ + + for (;;) + { + Enter = 1; + + special = IsSpecialSeitzMx(SgInfo, &TrialSMx, 1); + + if (special & SpecialSMx_Identity) + { + if (! (special & SpecialSMx_Transl0)) { + SetSgError(Err_Ill_lattice_translation); + return -1; + } + + if (SgInfo->GenOption) + Enter = 0; + } + else if (special & SpecialSMx_Inversion) + { + if (! (special & SpecialSMx_Transl0)) + { + if (SgInfo->Centric) { + SetSgError(Err_Ill_lattice_translation); + return -1; + } + + SgInfo->InversionOffOrigin = 1; + } + else + { + if (SgInfo->InversionOffOrigin) + SgInfo->Centric = 1; + + SgInfo->InversionOffOrigin = 0; + + if (SgInfo->GenOption) + { + if (SgInfo->Centric == 0) + SgInfo->Centric = -1; + + Enter = 0; + } + else + SgInfo->Centric = 1; + } + } + + if (Enter && CoreAdd2ListSeitzMx(SgInfo, &TrialSMx) < 0) + return -1; + + if (SgInfo->GenOption < 0) + break; + + if (jMult > iMult) + { + iMult++; + iMultSMx++; + + jMult = 1; + jMultSMx = &SgInfo->ListSeitzMx[1]; /* skip first = identity matrix */ + } + + if (iMult == SgInfo->nList) + break; + + SeitzMxMultiply(&TrialSMx, jMultSMx, iMultSMx); + + jMult++; + jMultSMx++; + } + + return 0; +} + + +int AddInversion2ListSeitzMx(T_SgInfo *SgInfo) +{ + T_RTMx SeitzMx; + + InitSeitzMx(&SeitzMx, -1); + return Add2ListSeitzMx(SgInfo, &SeitzMx); +} + + +int AddLatticeTr2ListSeitzMx(T_SgInfo *SgInfo, + const T_LatticeInfo *LatticeInfo) +{ + int iTrV, nTrV; + const int *TrV; + T_RTMx SeitzMx; + + + InitRotMx(SeitzMx.s.R, 1); + + nTrV = LatticeInfo->nTrVector; + TrV = &LatticeInfo->TrVector[3]; /* skip first vector which is always 000 */ + + for (iTrV = 1; iTrV < nTrV; iTrV++) + { + SeitzMx.s.T[0] = *TrV++; + SeitzMx.s.T[1] = *TrV++; + SeitzMx.s.T[2] = *TrV++; + + if (Add2ListSeitzMx(SgInfo, &SeitzMx) < 0) + return -1; + } + + if (SgInfo->GenOption) + SgInfo->StatusLatticeTr = 0; + else + SgInfo->StatusLatticeTr = 1; + + return 0; +} + + +static int RemoveLatticeTr(T_SgInfo *SgInfo) +{ + int iList, jList, i; + T_RTMx *smxi, *smxj, *lastsmx; + T_RotMxInfo *lrmxi, *lastrmxi; + + + if (SgInfo->LatticeInfo->Code == 'P') + return 0; + + if (SgInfo->StatusLatticeTr == -1) + { + if (AddLatticeTr2ListSeitzMx(SgInfo, SgInfo->LatticeInfo) < 0) + return -1; + } + + iList = 0; + + while (iList < SgInfo->nList) + { + smxi = &SgInfo->ListSeitzMx[iList]; + jList = iList + 1; + + while (jList < SgInfo->nList) + { + smxj = &SgInfo->ListSeitzMx[jList]; + + if (CompareSeitzMx(SgInfo->LatticeInfo, smxi, smxj) == 0) + { + /* copy last element to this place */ + + SgInfo->nList--; + lastsmx = &SgInfo->ListSeitzMx[SgInfo->nList]; + for (i = 0; i < 12; i++) smxj->a[i] = lastsmx->a[i]; + + if (SgInfo->ListRotMxInfo != NULL) + { + lrmxi = &SgInfo->ListRotMxInfo[jList]; + lastrmxi = &SgInfo->ListRotMxInfo[SgInfo->nList]; + CopyRotMxInfo(lrmxi, lastrmxi); + } + } + else + jList++; + } + + iList++; + } + + SgInfo->StatusLatticeTr = 0; + + return 0; +} + + +static int RemoveInversion(T_SgInfo *SgInfo) +{ + int i, iList, special, deter, Centric, InversionOffOrigin; + T_RTMx *lsmx, *smx, ProperSMx; + T_RotMxInfo *lrmxi, *rmxi; + + + Centric = 0; + InversionOffOrigin = 0; + + lsmx = SgInfo->ListSeitzMx; + + for (iList = 0; iList < SgInfo->nList; iList++, lsmx++) + { + special = IsSpecialSeitzMx(SgInfo, lsmx, 0); + + if (special & SpecialSMx_Inversion) + { + if (special & SpecialSMx_Transl0) + Centric = 1; + else + InversionOffOrigin = 1; + + break; + } + } + + if (InversionOffOrigin && Centric) { + SetSgError("Internal Error: Corrupt SgInfo"); + return -1; + } + + if (Centric == 0) + { + if (InversionOffOrigin) { + SgInfo->Centric = 0; + SgInfo->InversionOffOrigin = 1; + } + else + { + if (SgInfo->Centric) SgInfo->Centric = -1; + SgInfo->InversionOffOrigin = 0; + } + } + else + { + SgInfo->InversionOffOrigin = 0; + + lsmx = SgInfo->ListSeitzMx; + lrmxi = SgInfo->ListRotMxInfo; + iList = 0; + + while (iList < SgInfo->nList) + { + deter = deterRotMx(lsmx->s.R); + + if (deter == -1 && SgInfo->Centric == -1) + { + for (i = 0; i < 9; i++) + ProperSMx.s.R[i] = -lsmx->s.R[i]; + + for (i = 0; i < 3; i++) { + ProperSMx.s.T[i] = -lsmx->s.T[i] % STBF; + if (ProperSMx.s.T[i] < 0) + ProperSMx.s.T[i] += STBF; + } + + smx = SgInfo->ListSeitzMx; + + for (i = 0; i < SgInfo->nList; i++, smx++) + if (CompareSeitzMx(LI_P, &ProperSMx, smx) == 0) break; + + if (i == SgInfo->nList) + { + for (i = 0; i < 12; i++) lsmx->a[i] = ProperSMx.a[i]; + + deter = deterRotMx(lsmx->s.R); + + if (deter != 1 || (lrmxi && GetRotMxInfo(lsmx->s.R, lrmxi) == 0)) { + SetSgError(Err_Ill_SMx_in_List); + return -1; + } + } + } + + if (deter == -1) + { + /* copy last element to this place */ + + SgInfo->nList--; + if (SgInfo->nList != iList) + { + smx = &SgInfo->ListSeitzMx[SgInfo->nList]; + for (i = 0; i < 12; i++) lsmx->a[i] = smx->a[i]; + + if (lrmxi) + { + rmxi = &SgInfo->ListRotMxInfo[SgInfo->nList]; + CopyRotMxInfo(lrmxi, rmxi); + } + } + } + else if (deter == 1) + { + lsmx++; + if (lrmxi != NULL) lrmxi++; + iList++; + } + else { + SetSgError(Err_Ill_SMx_in_List); + return -1; + } + } + + SgInfo->Centric = -1; + } + + return 0; +} + + +int ApplyOriginShift(T_SgInfo *SgInfo) +{ + int HaveOrSh, iList, i; + T_RTMx *lsmx, SMx; + int OrSh[3], lo[3]; + + + HaveOrSh = 0; + + for (i = 0; i < 3; i++) { + OrSh[i] = SgInfo->OriginShift[i] * (STBF / 12); + if (OrSh[i]) HaveOrSh = 1; + } + + if (HaveOrSh == 0) + return 0; + + lsmx = SgInfo->ListSeitzMx; + + for (iList = 0; iList < SgInfo->nList; iList++, lsmx++) + { + RotMx_t_Vector(lo, lsmx->s.R, OrSh, STBF); + + for (i = 0; i < 3; i++) + lsmx->s.T[i] = iModPositive(lsmx->s.T[i] - lo[i] + OrSh[i], STBF); + } + + if (SgInfo->Centric == -1) + { + lsmx = &SMx; + + InitSeitzMx(lsmx, -1); + + RotMx_t_Vector(lo, lsmx->s.R, OrSh, STBF); + + for (i = 0; i < 3; i++) + lsmx->s.T[i] = iModPositive(lsmx->s.T[i] - lo[i] + OrSh[i], STBF); + + if (CoreAdd2ListSeitzMx(SgInfo, lsmx) < 0) + return -1; + + SgInfo->Centric = 0; + SgInfo->InversionOffOrigin = 1; + } + + return 1; +} + + +static void TidyTranslation(T_SgInfo *SgInfo) +{ + int iList; + int iTrV, nTrV; + const int *TrV; + T_RTMx *lsmx; + int t1, t2, t3, *lt1, *lt2, *lt3, mint1, mint2, mint3; + int n0t, n0mint; + + + nTrV = SgInfo->LatticeInfo->nTrVector; + + lsmx = SgInfo->ListSeitzMx; + + for (iList = 0; iList < SgInfo->nList; iList++, lsmx++) + { + mint1 = *(lt1 = &lsmx->s.T[0]); + mint2 = *(lt2 = &lsmx->s.T[1]); + mint3 = *(lt3 = &lsmx->s.T[2]); + + TrV = SgInfo->LatticeInfo->TrVector; + + for (iTrV = 0; iTrV < nTrV; iTrV++) + { + t1 = ((*lt1) + *TrV++) % STBF; + t2 = ((*lt2) + *TrV++) % STBF; + t3 = ((*lt3) + *TrV++) % STBF; + + n0t = (t1 == 0) + (t2 == 0) + (t3 == 0); + n0mint = (mint1 == 0) + (mint2 == 0) + (mint3 == 0); + + if ( n0t > n0mint + || ( n0t == n0mint + && ( t1 + t2 + t3 < mint1 + mint2 + mint3 + || ( t1 + t2 + t3 == mint1 + mint2 + mint3 + && (t1 < mint1 || (t1 == mint1 && t2 < mint2)))))) { + mint1 = t1; mint2 = t2; mint3 = t3; + } + } + + *lt1 = mint1; + *lt2 = mint2; + *lt3 = mint3; + } +} + + +static T_SgInfo *Pt_SgInfo_ListSortFunction = NULL; + +static int SgInfoListSortFunction(const int *iList_a, const int *iList_b) +{ + int val_a, val_b, n0_a, n0_b, i; + T_RTMx *smx_a, *smx_b; + T_RotMxInfo RotMxInfo_a, RotMxInfo_b, *rmxi_a, *rmxi_b; + T_SgInfo *SgInfo = Pt_SgInfo_ListSortFunction; + + + if (SgError != NULL) return 0; + + if (SgInfo->ListRotMxInfo == NULL) + { + rmxi_a = &RotMxInfo_a; + rmxi_b = &RotMxInfo_b; + + smx_a = &SgInfo->ListSeitzMx[*iList_a]; + smx_b = &SgInfo->ListSeitzMx[*iList_b]; + + if ( GetRotMxInfo(smx_a->s.R, rmxi_a) == 0 + || GetRotMxInfo(smx_b->s.R, rmxi_b) == 0) + { + SetSgError(Err_Ill_SMx_in_List); + return 0; + } + } + else + { + rmxi_a = &SgInfo->ListRotMxInfo[*iList_a]; + rmxi_b = &SgInfo->ListRotMxInfo[*iList_b]; + } + + val_a = abs(rmxi_a->Order); + val_b = abs(rmxi_b->Order); + + if (val_a == 1 && val_b != 1) return -1; + if (val_a != 1 && val_b == 1) return 1; + if (rmxi_a->Order == 1 && rmxi_b->Order != 1) return -1; + if (rmxi_a->Order != 1 && rmxi_b->Order == 1) return 1; + + if (val_a != 1) + { + if (val_a > val_b) return -1; + if (val_a < val_b) return 1; + if (rmxi_a->Order > rmxi_b->Order) return -1; + if (rmxi_a->Order < rmxi_b->Order) return 1; + } + + n0_a = n0_b = 0; + + for (i = 0; i < 3; i++) + { + if (rmxi_a->EigenVector[i] == 0) n0_a++; + if (rmxi_b->EigenVector[i] == 0) n0_b++; + } + if (n0_a > n0_b) return -1; + if (n0_a < n0_b) return 1; + + val_a = val_b = 0; + + for (i = 0; i < 3; i++) + { + if (val_a < abs(rmxi_a->EigenVector[i])) + val_a = abs(rmxi_a->EigenVector[i]); + if (val_b < abs(rmxi_b->EigenVector[i])) + val_b = abs(rmxi_b->EigenVector[i]); + } + if (val_a < val_b) return -1; + if (val_a > val_b) return 1; + + val_a = 100 * abs(rmxi_a->EigenVector[2]); + val_a += 10 * abs(rmxi_a->EigenVector[0]); + val_a += abs(rmxi_a->EigenVector[1]); + val_b = 100 * abs(rmxi_b->EigenVector[2]); + val_b += 10 * abs(rmxi_b->EigenVector[0]); + val_b += abs(rmxi_b->EigenVector[1]); + + if (n0_a < 2) + { + if (val_a < val_b) return -1; + if (val_a > val_b) return 1; + } + else + { + if (val_a > val_b) return -1; + if (val_a < val_b) return 1; + } + + for (i = 0; i < 3; i++) + { + if (rmxi_a->EigenVector[i] > rmxi_b->EigenVector[i]) return -1; + if (rmxi_a->EigenVector[i] < rmxi_b->EigenVector[i]) return 1; + } + + if (rmxi_a->Inverse < rmxi_b->Inverse) return -1; + if (rmxi_a->Inverse > rmxi_b->Inverse) return 1; + + smx_a = &SgInfo->ListSeitzMx[*iList_a]; + smx_b = &SgInfo->ListSeitzMx[*iList_b]; + + for (i = 0; i < 3; i++) + { + if (smx_a->s.T[i] < smx_b->s.T[i]) return -1; + if (smx_a->s.T[i] > smx_b->s.T[i]) return 1; + } + + return 0; +} + + +static int PostSortSgInfoList(const T_SgInfo *SgInfo, int *List_iList) +{ + int nList, iL_iL, jL_iL; + T_RTMx BufMx1, BufMx2, *smxab; + const T_RTMx *lsmx, *smxb; + T_RotMxInfo RotMxInfo; + const T_RotMxInfo *rmxi; + int nO_1, iO, save, i, i_; + + + nList = SgInfo->nList; + + iL_iL = 0; + + while (iL_iL < nList) + { + lsmx = &SgInfo->ListSeitzMx[List_iList[iL_iL]]; + + rmxi = ListOrBufRotMxInfo(SgInfo, List_iList[iL_iL], &RotMxInfo); + if (rmxi == NULL) + return -1; + + iL_iL++; + + iO = rmxi->Order; + if (iO < 0 && iO % 2) iO *= 2; + nO_1 = abs(iO) - 1; + + smxab = &BufMx2; + smxb = lsmx; + + for (iO = 1; iO < nO_1; iO++) + { + SeitzMxMultiply(smxab, lsmx, smxb); + + for (jL_iL = iL_iL; jL_iL < nList; jL_iL++) + { + smxb = &SgInfo->ListSeitzMx[List_iList[jL_iL]]; + if (CompareSeitzMx(SgInfo->LatticeInfo, smxab, smxb) == 0) + break; + } + + if (jL_iL < nList) + { + save = List_iList[jL_iL]; + + for (i = i_ = jL_iL; i > iL_iL; i = i_) + List_iList[i] = List_iList[--i_]; + + List_iList[iL_iL++] = save; + } + + smxb = smxab; + if (iO % 2) smxab = &BufMx1; + else smxab = &BufMx2; + } + } + + return 0; +} + + +static void SortSgInfoList(T_SgInfo *SgInfo, int *List_iList) +{ + int i, j, refi; + int nList; + T_RTMx *lsmx; + T_RotMxInfo *lrmxi; + + + if (SgError != NULL) return; + + nList = SgInfo->nList; + lsmx = SgInfo->ListSeitzMx; + lrmxi = SgInfo->ListRotMxInfo; + Pt_SgInfo_ListSortFunction = SgInfo; + + for (i = 0; i < nList; i++) List_iList[i] = i; + + qsort((void *) List_iList, nList, sizeof (*List_iList), + (int (*)(const void *, const void *)) SgInfoListSortFunction); + + Pt_SgInfo_ListSortFunction = NULL; + if (SgError != NULL) return; + + if (PostSortSgInfoList(SgInfo, List_iList) != 0) + return; + + for (i = 0; i < nList; i++) + { + j = List_iList[i]; + + if (j != i) + { + for (refi = i + 1; refi < nList; refi++) + if (List_iList[refi] == i) break; + + if (refi >= nList) { + SetSgError("Internal Error: SortSgInfoList(): Corrupt List_iList"); + return; + } + + SwapRTMx(&lsmx[i], &lsmx[j]); + if (lrmxi != NULL) + SwapRotMxInfo(&lrmxi[i], &lrmxi[j]); + + List_iList[refi] = j; + } + } +} + + +int FindSeitzMx(const T_SgInfo *SgInfo, + int Order, int HonorSign, int RefAxis, int DirCode) +{ + int iList; + int MatchingOrder; + T_RTMx *lsmx; + T_RotMxInfo *lrmxi, RotMxInfo; + + + lsmx = SgInfo->ListSeitzMx; + lrmxi = SgInfo->ListRotMxInfo; + + if (lrmxi == NULL) lrmxi = &RotMxInfo; + + for (iList = 0; iList < SgInfo->nList; iList++, lsmx++) + { + if (lrmxi == &RotMxInfo) + { + if (GetRotMxInfo(lsmx->s.R, lrmxi) == 0) { + SetSgError(Err_Ill_SMx_in_List); + return -1; + } + } + + if (HonorSign == 0) + MatchingOrder = (abs(Order) == abs(lrmxi->Order)); + else + MatchingOrder = (Order == lrmxi->Order); + + if ( MatchingOrder + && lrmxi->Inverse == 0 + && (RefAxis == 0 || RefAxis == lrmxi->RefAxis) + && (DirCode == 0 || DirCode == lrmxi->DirCode)) + { + if (DirCode != '*') return iList; + + if ( lrmxi->EigenVector[0] == 1 + && lrmxi->EigenVector[1] == 1 + && lrmxi->EigenVector[2] == 1) return iList; + } + + if (lrmxi != &RotMxInfo) lrmxi++; + } + + return -1; +} + + +static int FindXtalSystem(T_SgInfo *SgInfo) +{ + int iList, i; + int HonorSign = 0, CheckEnantiomorph; + const T_RTMx *lsmx; + T_RotMxInfo RotMxInfo; + const T_RotMxInfo *lrmxi; + + enum Axis { N1 = 0, N2, N3, N4, N6, EndOfAxis }; + int N_count[EndOfAxis]; + + + SgInfo->XtalSystem = XS_Unknown; + SgInfo->UniqueRefAxis = 0; + SgInfo->UniqueDirCode = 0; + SgInfo->ExtraInfo = EI_Unknown; + + CheckEnantiomorph = 0; + + for (i = 0; i < EndOfAxis; i++) N_count[i] = 0; + + lsmx = SgInfo->ListSeitzMx; + lrmxi = SgInfo->ListRotMxInfo; + + if (lrmxi == NULL) lrmxi = &RotMxInfo; + + for (iList = 0; iList < SgInfo->nList; iList++, lsmx++) + { + if (lrmxi == &RotMxInfo) + { + if (GetRotMxInfo(lsmx->s.R, &RotMxInfo) == 0) { + SetSgError(Err_Ill_SMx_in_List); + return XS_Unknown; + } + } + + switch(abs(lrmxi->Order)) + { + case 1: i = N1; break; + case 2: i = N2; break; + case 3: i = N3; break; + case 4: i = N4; break; + case 6: i = N6; break; + default: + SetSgError("Internal Error: FindXtalSystem(): Corrupt ListRotMxInfo"); + return XS_Unknown; + } + + if (lrmxi->Inverse == 0) /* skip N^-1 */ + N_count[i]++; + + if (lrmxi != &RotMxInfo) lrmxi++; + } + + i = EndOfAxis; + + if (SgInfo->InversionOffOrigin == 1) + { + for (i = 0; i < EndOfAxis; i++) + { + if (N_count[i] % 2) break; + N_count[i] /= 2; + } + } + + if (i == EndOfAxis) + { + if (N_count[N3] == 4) SgInfo->XtalSystem = XS_Cubic; + else if (N_count[N3] > 1) SgInfo->XtalSystem = XS_Unknown; + else if (N_count[N6] == 1) SgInfo->XtalSystem = XS_Hexagonal; + else if (N_count[N6] > 0) SgInfo->XtalSystem = XS_Unknown; + else if (N_count[N3] == 1) SgInfo->XtalSystem = XS_Trigonal; + else if (N_count[N4] == 1) SgInfo->XtalSystem = XS_Tetragonal; + else if (N_count[N4] > 0) SgInfo->XtalSystem = XS_Unknown; + else if (N_count[N2] > 2) SgInfo->XtalSystem = XS_Orthorhombic; + else if (N_count[N2] > 0) SgInfo->XtalSystem = XS_Monoclinic; + else if (N_count[N1] > 0) SgInfo->XtalSystem = XS_Triclinic; + + HonorSign = 1; + iList = FindSeitzMx(SgInfo, -1, HonorSign, 'o', '.'); + if (iList < 0) HonorSign = 0; + + switch(SgInfo->XtalSystem) + { + case XS_Monoclinic: + iList = FindSeitzMx(SgInfo, 2, HonorSign, 0, '='); + if (iList < 0) SgInfo->XtalSystem = XS_Unknown; + break; + case XS_Tetragonal: + CheckEnantiomorph = 1; + iList = FindSeitzMx(SgInfo, 4, HonorSign, 0, '='); + if (iList < 0) SgInfo->XtalSystem = XS_Unknown; + break; + case XS_Trigonal: + CheckEnantiomorph = 1; + iList = FindSeitzMx(SgInfo, 3, HonorSign, 0, '='); + if (iList < 0) + iList = FindSeitzMx(SgInfo, 3, HonorSign, 0, '*'); + if (iList < 0) SgInfo->XtalSystem = XS_Unknown; + break; + case XS_Hexagonal: + CheckEnantiomorph = 1; + iList = FindSeitzMx(SgInfo, 6, HonorSign, 0, '='); + if (iList < 0) SgInfo->XtalSystem = XS_Unknown; + break; + case XS_Cubic: + iList = FindSeitzMx(SgInfo, 4, HonorSign, 0, '='); + if (iList >= 0) CheckEnantiomorph = 1; + break; + default: + iList = -1; + break; + } + } + + if (SgInfo->XtalSystem == XS_Unknown) { + SetSgError("Error: Can't determine crystal system"); + } + else if (iList >= 0) + { + lrmxi = ListOrBufRotMxInfo(SgInfo, iList, &RotMxInfo); + if (lrmxi == NULL) { + SgInfo->XtalSystem = XS_Unknown; + return XS_Unknown; + } + + if (SgInfo->XtalSystem != XS_Cubic) + { + SgInfo->UniqueRefAxis = lrmxi->RefAxis; + SgInfo->UniqueDirCode = lrmxi->DirCode; + + if (SgInfo->XtalSystem == XS_Trigonal && lrmxi->DirCode == '=') + { + switch (lrmxi->RefAxis) + { + case 'z': + switch (SgInfo->LatticeInfo->Code) + { + case 'R': SgInfo->ExtraInfo = EI_Obverse; break; + case 'T': SgInfo->ExtraInfo = EI_Reverse; break; + } + break; + case 'y': + switch (SgInfo->LatticeInfo->Code) + { + case 'S': SgInfo->ExtraInfo = EI_Obverse; break; + case 'R': SgInfo->ExtraInfo = EI_Reverse; break; + } + break; + case 'x': + switch (SgInfo->LatticeInfo->Code) + { + case 'T': SgInfo->ExtraInfo = EI_Obverse; break; + case 'S': SgInfo->ExtraInfo = EI_Reverse; break; + } + break; + } + } + } + + if ( HonorSign == 0 /* no inversion matrix */ + && SgInfo->LatticeInfo->Code == 'P' + && CheckEnantiomorph == 1) + { + lsmx = &SgInfo->ListSeitzMx[iList]; + + if (GetRotMxOrder(lsmx->s.R) > 1) + { + i = lsmx->s.T[0] * lrmxi->EigenVector[0]; + i += lsmx->s.T[1] * lrmxi->EigenVector[1]; + i += lsmx->s.T[2] * lrmxi->EigenVector[2]; + + if (i % (STBF / 2)) SgInfo->ExtraInfo = EI_Enantiomorphic; + } + } + } + + return SgInfo->XtalSystem; +} + + +static int BuildGenerator_iList(T_SgInfo *SgInfo) +{ + int iList, iList_1, nG; + int SgInfo_CI, HonorSign, Flag3asterisk, FlagPG; + + + SgInfo_CI = (SgInfo->Centric || SgInfo->InversionOffOrigin); + + SgInfo->PointGroup = PG_Unknown; + + nG = SgInfo->nGenerator = 0; +#define G_iL SgInfo->Generator_iList + + HonorSign = 1; + iList_1 = FindSeitzMx(SgInfo, -1, HonorSign, 'o', '.'); + if (iList_1 < 0) HonorSign = 0; + + if (SgInfo->XtalSystem == XS_Unknown) + FindXtalSystem(SgInfo); + + switch(SgInfo->XtalSystem) + { + case XS_Triclinic: + if (iList_1 < 0) + iList_1 = FindSeitzMx(SgInfo, 1, HonorSign, 'o', '.'); + if (iList_1 >= 0) G_iL[nG++] = iList_1; + + if (SgInfo_CI) + SgInfo->PointGroup = PG_1b; + else + SgInfo->PointGroup = PG_1; + + SgInfo->nGenerator = nG; + return 0; + + case XS_Monoclinic: + iList = FindSeitzMx(SgInfo, 2, HonorSign, 0, '='); + if (iList < 0) break; + G_iL[nG++] = iList; + + if (SgInfo_CI) + SgInfo->PointGroup = PG_2_m; + else if (deterRotMx(SgInfo->ListSeitzMx[iList].s.R) == -1) + SgInfo->PointGroup = PG_m; + else + SgInfo->PointGroup = PG_2; + + if (iList_1 >= 0) G_iL[nG++] = iList_1; + + SgInfo->nGenerator = nG; + return 0; + + case XS_Orthorhombic: + iList = FindSeitzMx(SgInfo, 2, HonorSign, 'z', '='); + if (iList >= 0) G_iL[nG++] = iList; + + iList = FindSeitzMx(SgInfo, 2, HonorSign, 'x', '='); + if (iList >= 0) G_iL[nG++] = iList; + + if (nG < 2) + { + iList = FindSeitzMx(SgInfo, 2, HonorSign, 'y', '='); + if (iList >= 0) G_iL[nG++] = iList; + } + + if (nG != 2) break; + + if (SgInfo_CI) + SgInfo->PointGroup = PG_mmm; + else if ( deterRotMx(SgInfo->ListSeitzMx[G_iL[0]].s.R) == -1 + || deterRotMx(SgInfo->ListSeitzMx[G_iL[1]].s.R) == -1) + SgInfo->PointGroup = PG_mm2; + else + SgInfo->PointGroup = PG_222; + + if (iList_1 >= 0) G_iL[nG++] = iList_1; + + SgInfo->nGenerator = nG; + return 0; + + case XS_Tetragonal: + iList = FindSeitzMx(SgInfo, 4, HonorSign, 0, '='); + if (iList < 0) break; + G_iL[nG++] = iList; + + if ( SgInfo->UniqueRefAxis != 'x') + { + iList = FindSeitzMx(SgInfo, 2, HonorSign, 'x', '='); + if (iList >= 0) G_iL[nG++] = iList; + } + if (nG < 2 && SgInfo->UniqueRefAxis != 'z') + { + iList = FindSeitzMx(SgInfo, 2, HonorSign, 'z', '='); + if (iList >= 0) G_iL[nG++] = iList; + } + if (nG < 2 && SgInfo->UniqueRefAxis != 'y') + { + iList = FindSeitzMx(SgInfo, 2, HonorSign, 'y', '='); + if (iList >= 0) G_iL[nG++] = iList; + } + + if (nG < 2) + { + if (SgInfo_CI) + SgInfo->PointGroup = PG_4_m; + else if (deterRotMx(SgInfo->ListSeitzMx[G_iL[0]].s.R) == -1) + SgInfo->PointGroup = PG_4b; + else + SgInfo->PointGroup = PG_4; + } + else + { + if (SgInfo_CI) + SgInfo->PointGroup = PG_4_mmm; + else if (deterRotMx(SgInfo->ListSeitzMx[G_iL[0]].s.R) == -1) + { + if (deterRotMx(SgInfo->ListSeitzMx[G_iL[1]].s.R) == -1) + SgInfo->PointGroup = PG_4bm2; + else + SgInfo->PointGroup = PG_4b2m; + } + else + { + if (deterRotMx(SgInfo->ListSeitzMx[G_iL[1]].s.R) == -1) + SgInfo->PointGroup = PG_4mm; + else + SgInfo->PointGroup = PG_422; + } + } + + if (iList_1 >= 0) G_iL[nG++] = iList_1; + + SgInfo->nGenerator = nG; + return 0; + + case XS_Trigonal: + case XS_Hexagonal: + Flag3asterisk = 0; + + if (SgInfo->XtalSystem == XS_Trigonal) + { + iList = FindSeitzMx(SgInfo, 3, HonorSign, 0, '='); + if (iList < 0) + { + iList = FindSeitzMx(SgInfo, 3, HonorSign, 0, '*'); + Flag3asterisk = 1; + } + } + else + iList = FindSeitzMx(SgInfo, 6, HonorSign, 0, '='); + + if (iList < 0) break; + G_iL[nG++] = iList; + + iList = FindSeitzMx(SgInfo, 2, HonorSign, 0, '\''); + if (iList >= 0) G_iL[nG++] = iList; + + FlagPG = -1; + + if (nG < 2) + { + iList = FindSeitzMx(SgInfo, 2, HonorSign, 0, '"'); + if (iList >= 0) G_iL[nG++] = iList; + FlagPG = 1; + } + + if (SgInfo->XtalSystem == XS_Trigonal) + { + if (nG < 2) + { + if (SgInfo_CI) SgInfo->PointGroup = PG_3b; + else SgInfo->PointGroup = PG_3; + } + else + { + if (Flag3asterisk == 1) + { + if (SgInfo_CI) + SgInfo->PointGroup = PG_3bm; + else + { FlagPG = deterRotMx(SgInfo->ListSeitzMx[G_iL[1]].s.R); + if (FlagPG == -1) SgInfo->PointGroup = PG_3m; + else SgInfo->PointGroup = PG_32; + } + } + else if (FlagPG == -1) + { + if (SgInfo_CI) + SgInfo->PointGroup = PG_3b1m; + else + { FlagPG = deterRotMx(SgInfo->ListSeitzMx[G_iL[1]].s.R); + if (FlagPG == -1) SgInfo->PointGroup = PG_31m; + else SgInfo->PointGroup = PG_312; + } + } + else + { + if (SgInfo_CI) + SgInfo->PointGroup = PG_3bm1; + else + { FlagPG = deterRotMx(SgInfo->ListSeitzMx[G_iL[1]].s.R); + if (FlagPG == -1) SgInfo->PointGroup = PG_3m1; + else SgInfo->PointGroup = PG_321; + } + } + } + } + else + { + if (nG < 2) + { + if (SgInfo_CI) + SgInfo->PointGroup = PG_6_m; + else if (deterRotMx(SgInfo->ListSeitzMx[G_iL[0]].s.R) == -1) + SgInfo->PointGroup = PG_6b; + else + SgInfo->PointGroup = PG_6; + } + else + { + if (SgInfo_CI) + SgInfo->PointGroup = PG_6_mmm; + else if (deterRotMx(SgInfo->ListSeitzMx[G_iL[0]].s.R) == -1) + { + if (deterRotMx(SgInfo->ListSeitzMx[G_iL[1]].s.R) == FlagPG) + SgInfo->PointGroup = PG_6b2m; + else + SgInfo->PointGroup = PG_6bm2; + } + else if (deterRotMx(SgInfo->ListSeitzMx[G_iL[1]].s.R) == -1) + SgInfo->PointGroup = PG_6mm; + else + SgInfo->PointGroup = PG_622; + } + } + + if (iList_1 >= 0) G_iL[nG++] = iList_1; + + SgInfo->nGenerator = nG; + return 0; + + case XS_Cubic: + FlagPG = 0; + + iList = FindSeitzMx(SgInfo, 4, HonorSign, 'z', '='); + if (iList < 0) { + iList = FindSeitzMx(SgInfo, 2, HonorSign, 'z', '='); + FlagPG = 1; + } + if (iList < 0) break; + G_iL[nG++] = iList; + + iList = FindSeitzMx(SgInfo, 2, HonorSign, 'x', '='); + if (iList < 0) break; + G_iL[nG++] = iList; + + iList = FindSeitzMx(SgInfo, 3, HonorSign, 'o', '*'); + if (iList < 0) break; + G_iL[nG++] = iList; + + if (FlagPG) + { + if (SgInfo_CI) SgInfo->PointGroup = PG_m3b; + else SgInfo->PointGroup = PG_23; + } + else + { + if (SgInfo_CI) + SgInfo->PointGroup = PG_m3bm; + else if (deterRotMx(SgInfo->ListSeitzMx[G_iL[0]].s.R) == -1) + SgInfo->PointGroup = PG_4b3m; + else + SgInfo->PointGroup = PG_432; + } + + if (iList_1 >= 0) G_iL[nG++] = iList_1; + + SgInfo->nGenerator = nG; + return 0; + + default: + break; + } + +#undef G_iL + + return -1; +} + + +static int BuildHSym(T_SgInfo *SgInfo) +{ + int NeedDash, HaveOrSh, nGRT, iList, iG, ip, os, i; + int AbsOrder, RefAxis, DirCode, ScrewPrimitive, Screw; + int PreviousRotation, PreviousRefAxis, PreviousDirCode; + int nTrV, iTrV, OrSh[3], RO[3], Transl[3]; + const int *TrV, *ht; + T_RTMx SMx_1; + const T_RTMx *SMx; + const T_RotMxInfo *rmxi; + char *hsym, *hsym_mark; + + struct + { + T_RotMxInfo RMxI_Buf; + const T_RotMxInfo *RMxI; + int Transl[3]; + } + GRT[sizeof SgInfo->Generator_iList / sizeof (*SgInfo->Generator_iList) + 1]; + + const char *Digits = "0123456"; + + + if (SgInfo->nGenerator == 0) { + SetSgError("Internal Error: BuildHSym(): Empty generator list"); + return -1; + } + + HaveOrSh = 0; + + for (i = 0; i < 3; i++) { + OrSh[i] = SgInfo->OriginShift[i] * (STBF / 12); + if (OrSh[i]) HaveOrSh = 1; + } + + NeedDash = 0; + nGRT = 0; + + for (iG = 0; iG < SgInfo->nGenerator; iG++) + { + iList = SgInfo->Generator_iList[iG]; + + GRT[nGRT].RMxI = ListOrBufRotMxInfo(SgInfo, iList, &GRT[nGRT].RMxI_Buf); + if (GRT[nGRT].RMxI == NULL) + return -1; + + SMx = &SgInfo->ListSeitzMx[iList]; + + RotMx_t_Vector(RO, SMx->s.R, OrSh, STBF); + + for (i = 0; i < 3; i++) + GRT[nGRT].Transl[i] = iModPositive(SMx->s.T[i] + RO[i] - OrSh[i], STBF); + + if (GRT[nGRT].RMxI->Order == -1) + { + for (i = 0; i < 3; i++) + if (GRT[nGRT].Transl[i] != 0) break; + + if (i == 3) NeedDash = 1; + else nGRT++; + } + else + nGRT++; + } + + if (SgInfo->Centric) + { + if (HaveOrSh == 0) + NeedDash = 1; + else + { + for (iG = 0; iG < nGRT; iG++) + if (GRT[iG].RMxI->Order == 1) break; + + InitSeitzMx(&SMx_1, -1); + + if (GetRotMxInfo(SMx_1.s.R, &GRT[iG].RMxI_Buf) != -1) { + SetSgError("Internal Error: BuildHSym(): Corrupt GetRotMxInfo()"); + return -1; + } + + GRT[iG].RMxI = &GRT[iG].RMxI_Buf; + + for (i = 0; i < 3; i++) + GRT[iG].Transl[i] = iModPositive(-2 * OrSh[i], STBF); + + if (iG == nGRT) + nGRT++; + } + } + + hsym = SgInfo->HallSymbol; + + for (i = 0; i <= MaxLenHallSymbol; i++) + *hsym++ = '\0'; + + PreviousRotation = 0; + PreviousRefAxis = 0; + PreviousDirCode = 0; + + hsym = SgInfo->HallSymbol; + + if (NeedDash) + *hsym++ = '-'; + else + *hsym++ = ' '; + + *hsym++ = SgInfo->LatticeInfo->Code; + + nTrV = SgInfo->LatticeInfo->nTrVector; + + for (iG = 0; iG < nGRT; iG++) + { + rmxi = GRT[iG].RMxI; + + AbsOrder = abs(rmxi->Order); + RefAxis = rmxi->RefAxis; + DirCode = rmxi->DirCode; + if (RefAxis == 'o') RefAxis = 0; + if (DirCode == '=' || DirCode == '.') DirCode = 0; + + if (iG == 0) + { + if (RefAxis == 'z') RefAxis = 0; + } + else + { + if (AbsOrder == 2) + { + if (PreviousRotation == 2 || PreviousRotation == 4) + { + if (RefAxis == 'x') RefAxis = 0; + } + else if (PreviousRotation == 3 || PreviousRotation == 6) + { + if ( PreviousDirCode == '*' + || RefAxis == PreviousRefAxis) RefAxis = 0; + if (DirCode == '\'') DirCode = 0; + } + } + else if (AbsOrder == 3) + { + if (DirCode == '*') DirCode = 0; + } + } + + PreviousRotation = AbsOrder; + PreviousRefAxis = rmxi->RefAxis; + PreviousDirCode = rmxi->DirCode; + + *hsym++ = ' '; + if (rmxi->Order < 0) *hsym++ = '-'; + *hsym++ = Digits[AbsOrder]; + if (RefAxis) *hsym++ = RefAxis; + if (DirCode) *hsym++ = DirCode; + + TrV = SgInfo->LatticeInfo->TrVector; + + for (iTrV = 0; iTrV < nTrV; iTrV++, TrV += 3) + { + for (i = 0; i < 3; i++) + if ((GRT[iG].Transl[i] + TrV[i]) % STBF != 0) + break; + + if (i == 3) + break; + } + + if (iTrV < nTrV) + continue; /* next iG */ + + hsym_mark = hsym; + + TrV = SgInfo->LatticeInfo->TrVector; + + for (iTrV = 0; iTrV < nTrV; iTrV++, TrV += 3, hsym = hsym_mark) + { + for (i = 0; i < 3; i++) + Transl[i] = iModPositive(GRT[iG].Transl[i] + TrV[i], STBF); + + Screw = 0; + + for (ip = 0; ip < 3; ip++) + if (rmxi->EigenVector[ip] != 0) break; + + if (ip < 3 && rmxi->EigenVector[ip] == 1) + { + for (i = ip + 1; i < 3; i++) + if (rmxi->EigenVector[i] != 0) break; + + if (i == 3) + { + ScrewPrimitive = STBF / AbsOrder; + Screw = Transl[ip] / ScrewPrimitive; + i = Screw * ScrewPrimitive; + if (i % 3) + { + *hsym++ = Digits[Screw]; + Transl[ip] -= i; + } + } + } + + ht = HallTranslations; + + while (*ht) + { + for (i = 0; i < 3; i++) + if (Transl[i] < ht[i + 1]) break; + + if (i == 3) + { + for (i = 0; i < 3; i++) + Transl[i] -= ht[i + 1]; + + *hsym++ = (char) *ht; + } + + ht += 4; + } + + for (i = 0; i < 3; i++) + if (Transl[i] != 0) + break; + + if (i == 3) + break; + } + + if (iTrV == nTrV) + return 0; + } + + if (nGRT == 0) + { + *hsym++ = ' '; + *hsym++ = '1'; + } + + if (HaveOrSh) + { + *hsym++ = ' '; + *hsym++ = '('; + + for (i = 0; i < 3; i++) + { + if (i) *hsym++ = ' '; + + os = iModPositive(SgInfo->OriginShift[i], 12); + if (os > 6) + { + *hsym++ = '-'; + os = 12 - os; + } + + *hsym++ = Digits[os]; + } + + *hsym++ = ')'; + } + + *hsym = '\0'; + + if (SgInfo->HallSymbol[MaxLenHallSymbol] != '\0') { + SetSgError("Internal Error: BuildHSym(): MaxLenHallSymbol too small"); + return -1; + } + + return 1; +} + + +static int BuildHallSymbol(T_SgInfo *SgInfo, int FixedOriginShift) +{ + int ix, iy, iz; + int status; + + static const int ShiftTable[] = { 0, 1, -1, 2, -2, 3 }; + + + if (SgError != NULL) return -1; + + if (SgInfo->nGenerator == 0) + { + if (BuildGenerator_iList(SgInfo) != 0) + { + SetSgError("Error: Can't build generator list"); + return -1; + } + } + + if (FixedOriginShift) + { + status = BuildHSym(SgInfo); + if (status == 1) + return 0; + } + else + { + for (ix = 0; ix < 6; ix++) + { + SgInfo->OriginShift[0] = ShiftTable[ix]; + + for (iy = 0; iy < 6; iy++) + { + SgInfo->OriginShift[1] = ShiftTable[iy]; + + for (iz = 0; iz < 6; iz++) + { + SgInfo->OriginShift[2] = ShiftTable[iz]; + + status = BuildHSym(SgInfo); + if (status < 0) + return -1; + + if (status == 1) + return 0; + } + } + } + } + + SetSgError("Error: Can't build Hall Symbol"); + return -1; +} + + +void InitSgInfo(T_SgInfo *SgInfo) +{ + int i; + + + SgInfo->GenOption = 0; + SgInfo->Centric = 0; + SgInfo->InversionOffOrigin = 0; + SgInfo->LatticeInfo = LI_P; + SgInfo->StatusLatticeTr = 0; + for (i = 0; i < 3; i++) + SgInfo->OriginShift[i] = 0; + SgInfo->nList = 0; + + SgInfo->OrderL = 0; + SgInfo->OrderP = 0; + SgInfo->XtalSystem = XS_Unknown; + SgInfo->UniqueRefAxis = 0; + SgInfo->UniqueDirCode = 0; + SgInfo->ExtraInfo = EI_Unknown; + SgInfo->PointGroup = PG_Unknown; + SgInfo->nGenerator = 0; + SgInfo->HallSymbol[0] = '\0'; + SgInfo->TabSgName = NULL; + SgInfo->CCMx_LP = NULL; + SgInfo->n_si_Vector = -1; +} + + +int CompleteSgInfo(T_SgInfo *SgInfo) +{ + int List_iList[192]; + const T_TabSgName *tsgn; + + + if (SgInfo->StatusLatticeTr == -1) + { + if (AddLatticeTr2ListSeitzMx(SgInfo, SgInfo->LatticeInfo) < 0) + return -1; + } + + if (ApplyOriginShift(SgInfo) < 0) + return -1; + + if (SgInfo->nList > sizeof List_iList / sizeof (*List_iList)) { + SetSgError("Internal Error: CompleteSgInfo()"); + return -1; + } + + if (SgInfo->nList > 1) + { + SortSgInfoList(SgInfo, List_iList); + if (SgError != NULL) return -1; + } + + if (RemoveLatticeTr(SgInfo) != 0) + return -1; + + if (RemoveInversion(SgInfo) != 0) + return -1; + + TidyTranslation(SgInfo); + + if (SgInfo->nList > 1) + { + SortSgInfoList(SgInfo, List_iList); + if (SgError != NULL) return -1; + } + SgInfo->OrderP = SgInfo->nList; + if (SgInfo->Centric == -1) SgInfo->OrderP *= 2; + + SgInfo->OrderL = SgInfo->OrderP * SgInfo->LatticeInfo->nTrVector; + + if (BuildHallSymbol(SgInfo, 0) != 0) + return -1; + + for (tsgn = TabSgName; tsgn->HallSymbol; tsgn++) + if ( strcmp(tsgn->HallSymbol, SgInfo->HallSymbol) == 0 + && ( SgInfo->TabSgName == NULL + || SgInfo->TabSgName == tsgn)) + break; + + if (SgInfo->TabSgName != NULL && tsgn->HallSymbol == NULL) + { + if (SgError) return -1; + + sprintf(SgErrorBuffer, + "Internal Error: Input/Output HallSymbol mismatch: %s <> %s", + SgInfo->TabSgName->HallSymbol, SgInfo->HallSymbol); + + SetSgError(SgErrorBuffer); + return -1; + } + + if (tsgn->HallSymbol) + SgInfo->TabSgName = tsgn; + + SgInfo->CCMx_LP = NULL; + + switch (SgInfo->LatticeInfo->Code) + { + case 'P': SgInfo->CCMx_LP = CCMx_PP; break; + case 'A': SgInfo->CCMx_LP = CCMx_AP; break; + case 'B': SgInfo->CCMx_LP = CCMx_BP; break; + case 'C': SgInfo->CCMx_LP = CCMx_CP; break; + case 'I': SgInfo->CCMx_LP = CCMx_IP; break; + case 'R': + switch (SgInfo->UniqueRefAxis) { + case 0: + case 'z': SgInfo->CCMx_LP = CCMx_RP_z; break; + case 'y': SgInfo->CCMx_LP = CCMx_RP_y; break; + default: break; + } + break; + case 'S': + switch (SgInfo->UniqueRefAxis) { + case 0: + case 'y': SgInfo->CCMx_LP = CCMx_SP_y; break; + case 'x': SgInfo->CCMx_LP = CCMx_SP_x; break; + default: break; + } + break; + case 'T': + switch (SgInfo->UniqueRefAxis) { + case 0: + case 'x': SgInfo->CCMx_LP = CCMx_TP_x; break; + case 'z': SgInfo->CCMx_LP = CCMx_TP_z; break; + default: break; + } + break; + case 'F': SgInfo->CCMx_LP = CCMx_FP; break; + default: + break; + } + + if (SgInfo->CCMx_LP == NULL) { + SetSgError("Internal Error: Illegal lattice code"); + return -1; + } + + return 0; +} + + +int CB_SMx(T_RTMx *CSiC, + const T_RTMx *CBMx, const T_RTMx *SMx, const T_RTMx *InvCBMx) +{ + int i; + T_RTMx BufMx; + + + RTMxMultiply(&BufMx, SMx, InvCBMx, CTBF / STBF, CTBF); + RTMxMultiply(CSiC, CBMx, &BufMx, CRBF, CRBF * CTBF); + + for (i = 0; i < 9; i++) + { + if (CSiC->s.R[i] % (CRBF * CRBF)) { + SetSgError("Internal Error: Corrupt CBMx/SMx/InvCBMx"); + return -1; + } + + CSiC->s.R[i] /= (CRBF * CRBF); + } + + for (i = 0; i < 3; i++) + { + if (CSiC->s.T[i] % (CRBF * (CTBF / STBF))) { + SetSgError("Internal Error: Out of STBF range"); + return -1; + } + + CSiC->s.T[i] /= (CRBF * (CTBF / STBF)); + } + + return 0; +} + + +int TransformSgInfo(const T_SgInfo *SgInfo, + const T_RTMx *CBMx, const T_RTMx *InvCBMx, + T_SgInfo *BC_SgInfo) +{ + int iList, f, i; + int nTrV, iTrV, nLoopInv, iLoopInv; + const int *TrV; + T_RTMx SMx, BC_SMx; + const T_RTMx *lsmx; + + + nLoopInv = Sg_nLoopInv(SgInfo); + + nTrV = SgInfo->LatticeInfo->nTrVector; + TrV = SgInfo->LatticeInfo->TrVector; + + for (iTrV = 0; iTrV < nTrV; iTrV++, TrV += 3) + { + for (iLoopInv = 0; iLoopInv < nLoopInv; iLoopInv++) + { + if (iLoopInv == 0) f = 1; + else f = -1; + + lsmx = SgInfo->ListSeitzMx; + + for (iList = 0; iList < SgInfo->nList; iList++, lsmx++) + { + for (i = 0; i < 9; i++) + SMx.s.R[i] = f * lsmx->s.R[i]; + + for (i = 0; i < 3; i++) + SMx.s.T[i] = f * lsmx->s.T[i] + TrV[i]; + + if (CB_SMx(&BC_SMx, CBMx, &SMx, InvCBMx) != 0) + return -1; + + if (Add2ListSeitzMx(BC_SgInfo, &BC_SMx) < 0) + return -1; + } + } + } + + return 0; +} + + +#undef SGCLIB_C__ diff --git a/sgfind.c b/sgfind.c new file mode 100644 index 00000000..ea58fe5a --- /dev/null +++ b/sgfind.c @@ -0,0 +1,1174 @@ +/* + Space Group Info's (c) 1994-96 Ralf W. Grosse-Kunstleve + */ + +#include +#include + + +#define SGCOREDEF__ +#include "sginfo.h" + + +static int InitialCBMxR(T_SgInfo *SgInfo, + const T_LatticeInfo **NewLatticeInfo, + int *NewPointGroup, + int *IniCBMxR, int *IniInvCBMxR) +{ + int Code, NewPG, deterCCMx, fac, i; + const T_LatticeInfo *NewLI; + const int *CCMx; + + + Code = SgInfo->LatticeInfo->Code; + NewLI = SgInfo->LatticeInfo; + NewPG = SgInfo->PointGroup; + CCMx = CCMx_PP; + + switch(SgInfo->XtalSystem) + { + case XS_Triclinic: + NewLI = LI_P; + CCMx = SgInfo->CCMx_LP; + break; + + case XS_Monoclinic: + case XS_Tetragonal: + switch (SgInfo->UniqueRefAxis) + { + case 'z': if (Code == 'C') { + NewLI = LI_P; CCMx = SgInfo->CCMx_LP; } + else if (Code == 'F') { + NewLI = LI_I; CCMx = CCMx_FI_z; } + break; + case 'y': if (Code == 'B') { + NewLI = LI_P; CCMx = SgInfo->CCMx_LP; } + else if (Code == 'F') { + NewLI = LI_I; CCMx = CCMx_FI_y; } + break; + case 'x': if (Code == 'A') { + NewLI = LI_P; CCMx = SgInfo->CCMx_LP; } + else if (Code == 'F') { + NewLI = LI_I; CCMx = CCMx_FI_x; } + break; + default: + goto ReturnError; + } + + if ( SgInfo->XtalSystem == XS_Tetragonal + && SgInfo->LatticeInfo != NewLI) + { + if (NewPG == PG_4b2m) NewPG = PG_4bm2; + else if (NewPG == PG_4bm2) NewPG = PG_4b2m; + } + + break; + + case XS_Orthorhombic: + break; + + case XS_Trigonal: + NewLI = LI_P; + CCMx = SgInfo->CCMx_LP; + + if (Code == 'R' || Code == 'S' || Code == 'T') + { + if (NewPG == PG_321) NewPG = PG_32; + else if (NewPG == PG_3m1) NewPG = PG_3m; + else if (NewPG == PG_3bm1) NewPG = PG_3bm; + } + + break; + + case XS_Hexagonal: + break; + + case XS_Cubic: + break; + + default: + goto ReturnError; + } + + deterCCMx = deterRotMx(CCMx); + if (deterCCMx < 1 || CRBF % deterCCMx) + goto ReturnError; + + fac = CRBF / deterCCMx; + + InverseRotMx(CCMx, IniInvCBMxR); + + for (i = 0; i < 9; i++) { + IniCBMxR[i] = CRBF * CCMx[i]; + IniInvCBMxR[i] *= fac; + } + + *NewLatticeInfo = NewLI; + *NewPointGroup = NewPG; + + return deterCCMx; + + ReturnError: + + SetSgError("Internal Error: InitialCBMxR()"); + return -1; +} + + +static int CBR_RMx(int *RRMx, + const int *CBMxR, const int *RMx, const int *InvCBMxR) +{ + int i, BufMx[9]; + + + RotMxMultiply(BufMx, RMx, InvCBMxR); + RotMxMultiply(RRMx, CBMxR, BufMx); + + for (i = 0; i < 9; i++) + { + if (RRMx[i] % (CRBF * CRBF)) { + SetSgError("Internal Error: CBR_SMx()"); + return -1; + } + + RRMx[i] /= (CRBF * CRBF); + } + + return 0; +} + + +static void RotateCBMxR(const int *RMx, const int *InvRMx, + int *CBMxR, int *InvCBMxR) +{ + int i, BufMx[9]; + + + RotMxMultiply(BufMx, RMx, CBMxR); + for (i = 0; i < 9; i++) CBMxR[i] = BufMx[i]; + + /* matrix algebra: (A * B)^-1 = B^-1 * A^-1 */ + + RotMxMultiply(BufMx, InvCBMxR, InvRMx); + for (i = 0; i < 9; i++) InvCBMxR[i] = BufMx[i]; +} + + +static int AlignUniqueAxis(const T_SgInfo *SgInfo, + const T_SgInfo *GenSgI, + int *CBMxR, int *InvCBMxR, + const int **AlignRMx) +{ + int i, iListS, DirCode; + int UAMx[9], RotEV[3]; + const int *RMx, *InvRMx, *lsmxR; + T_RotMxInfo RMxI_S, *RMxI_G; + + + if (GenSgI->nList < 2) + goto ReturnError; + + RMxI_G = &GenSgI->ListRotMxInfo[1]; + + if (abs(RMxI_G->Order) == 3) DirCode = 0; + else DirCode = '='; + + iListS = FindSeitzMx(SgInfo, RMxI_G->Order, 1, 0, DirCode); + if (iListS < 0) + { + if (SgInfo->Centric == 0) + return 0; + + iListS = FindSeitzMx(SgInfo, -RMxI_G->Order, 1, 0, DirCode); + if (iListS < 0) + goto ReturnError; + + for (i = 0; i < 9; i++) + UAMx[i] = -SgInfo->ListSeitzMx[iListS].s.R[i]; + + lsmxR = UAMx; + } + else + lsmxR = SgInfo->ListSeitzMx[iListS].s.R; + + if (CBR_RMx(UAMx, CBMxR, lsmxR, InvCBMxR) != 0) + goto ReturnError; + + if (GetRotMxInfo(UAMx, &RMxI_S) != RMxI_G->Order) + goto ReturnError; + + if (RMxI_S.DirCode != RMxI_G->DirCode) + return 0; + + RMx = InvRMx = RMx_1_000; + + for (;;) + { + RotMx_t_Vector(RotEV, RMx, RMxI_S.EigenVector, 0); + + for (i = 0; i < 3; i++) + if (RotEV[i] != RMxI_G->EigenVector[i]) break; + + if (i == 3) + break; + + if (RMxI_S.DirCode == '=') + { + if (RMx == RMx_1_000) { + RMx = RMx_3_111; InvRMx = RMx_3i111; } + else if (RMx == RMx_3_111) { + RMx = RMx_3i111; InvRMx = RMx_3_111; } + else + goto ReturnError; + } + else if (RMxI_S.DirCode == '*') + { + if (RMx == RMx_1_000) { + RMx = RMx_4_001; InvRMx = RMx_4i001; } + else if (RMx == RMx_4_001) { + RMx = RMx_2_001; InvRMx = RMx_2_001; } + else if (RMx == RMx_2_001) { + RMx = RMx_4i001; InvRMx = RMx_4_001; } + else + goto ReturnError; + } + else + goto ReturnError; + } + + if (RMx != RMx_1_000) + RotateCBMxR(RMx, InvRMx, CBMxR, InvCBMxR); + + if (AlignRMx) + *AlignRMx = RMx; + + return 1; + + ReturnError: + + SetSgError("Internal Error: AlignUniqueAxis()"); + return -1; +} + + +static const T_RTMx *GetSMxWithSameRot(const int *WtdRotMx, + const T_SgInfo *SgInfo, T_RTMx *BufMx) +{ + int iList, i; + const T_RTMx *lsmx; + + + lsmx = SgInfo->ListSeitzMx; + + for (iList = 0; iList < SgInfo->nList; iList++, lsmx++) + { + for (i = 0; i < 9; i++) + if (WtdRotMx[i] != lsmx->s.R[i]) + break; + + if (i == 9) + return lsmx; + + if (SgInfo->Centric != -1) + continue; + + for (i = 0; i < 9; i++) + if (WtdRotMx[i] != -lsmx->s.R[i]) + break; + + if (i == 9) + { + for (i = 0; i < 9; i++) + BufMx->s.R[i] = -lsmx->s.R[i]; + + for (i = 0; i < 3; i++) { + BufMx->s.T[i] = -lsmx->s.T[i] % STBF; + if (BufMx->s.T[i] < 0) + BufMx->s.T[i] += STBF; + } + + return BufMx; + } + } + + return NULL; +} + + +static int BuildFreeMx(const int *EigenVector, int Order, int *FreeMx) +{ + static const int GeneratorEigenVectors[] = + { + 001, 0, 0, 1, + 010, 0, 1, 0, + 100, 1, 0, 0, + 110, 1, 1, 0, + -110, 1, -1, 0, + 111, 1, 1, 1, + 0 + }; + + int i; + const int *gev; + + + for (i = 0; i < 9; i++) + FreeMx[i] = 0; + + if (Order == -1 || Order == -3 || Order == -4 || Order == -6) + return 0; + + for (gev = GeneratorEigenVectors; *gev++ != 0; gev += 3) + { + for (i = 0; i < 3; i++) + if (EigenVector[i] != gev[i]) + break; + + if (i == 3) + break; + } + + gev--; + + if (Order == -2) + { + switch (*gev) + { + case 001: FreeMx[0] = 1; FreeMx[4] = 1; return 0; + case 010: FreeMx[8] = 1; FreeMx[0] = 1; return 0; + case 100: FreeMx[4] = 1; FreeMx[8] = 1; return 0; + case 110: FreeMx[1] = 1; FreeMx[4] = -1; FreeMx[8] = 1; return 1; + case -110: FreeMx[1] = 1; FreeMx[4] = 1; FreeMx[8] = 1; return 1; + default: + break; + } + } + else if (Order > 1) + { + switch (*gev) + { + case 001: FreeMx[8] = 1; return 0; + case 010: FreeMx[4] = 1; return 0; + case 100: FreeMx[0] = 1; return 0; + case 110: FreeMx[0] = 1; FreeMx[3] = 1; return 1; + case -110: FreeMx[0] = 1; FreeMx[3] = -1; return 1; + case 111: FreeMx[0] = 1; FreeMx[3] = 1; FreeMx[6] = 1; return 1; + default: + break; + } + } + + SetSgError("Internal Error: BuildFreeMx()"); + return -1; +} + + +static int StartFixAxes(const T_SgInfo *SgInfo, + const T_SgInfo *GenSgI, const int *iGen, + T_RTMx *CBMx, T_RTMx *InvCBMx, + T_RTMx *SMxG, T_RTMx *SMxS_G, + int *FreeMx, int *TryAgain) +{ + int iG, Order, i; + const int *EV; + T_RTMx SMxG_S, BufMx; + const T_RTMx *SMx; + const T_RotMxInfo *RMxI_G; + + + if (*iGen == -3) + iG = 1; + else + iG = *iGen; + + if (iG == -1) + { + Order = -1; + EV = NULL; + } + else + { + if (iG < 1 || iG >= GenSgI->nList) + goto ReturnError; + + RMxI_G = &GenSgI->ListRotMxInfo[iG]; + Order = RMxI_G->Order; + EV = RMxI_G->EigenVector; + + if (iG != *iGen) + { + Order *= -1; + if (Order != *iGen) + goto ReturnError; + } + } + + if (Order == -1) + { + if (GenSgI->Centric == -1) { + InitSeitzMx(SMxG, -1); + } + else + { + for (iG = 1; iG < GenSgI->nList; iG++) + if (GenSgI->ListRotMxInfo[iG].Order == -1) + break; + + if (iG == GenSgI->nList) + goto ReturnError; + + SMx = &GenSgI->ListSeitzMx[iG]; + + for (i = 0; i < 12; i++) SMxG->a[i] = SMx->a[i]; + } + } + else + { + SMx = &GenSgI->ListSeitzMx[iG]; + + if (iG == *iGen) + for (i = 0; i < 12; i++) SMxG->a[i] = SMx->a[i]; + else + { + for (i = 0; i < 9; i++) + SMxG->s.R[i] = -SMx->s.R[i]; + + for (i = 0; i < 3; i++) { + SMxG->s.T[i] = -SMx->s.T[i] % STBF; + if (SMxG->s.T[i] < 0) + SMxG->s.T[i] += STBF; + } + } + } + + if (CB_SMx(&SMxG_S, InvCBMx, SMxG, CBMx) != 0) + return -1; + + SMx = GetSMxWithSameRot(SMxG_S.s.R, SgInfo, &BufMx); + if (SMx == NULL) + return 0; + + if (CB_SMx(SMxS_G, CBMx, SMx, InvCBMx) != 0) + return -1; + + for (i = 0; i < 9; i++) + if (SMxS_G->s.R[i] != SMxG->s.R[i]) + goto ReturnError; + + *TryAgain = BuildFreeMx(EV, Order, FreeMx); + if (*TryAgain < 0) + return -1; + + return 1; + + ReturnError: + + SetSgError("Internal Error: StartFixAxes()"); + return -1; +} + + +static int FindInvertableMx(const int *Mx, int *InvMx, + int *nActive, int *irActive, int *icActive) +{ + int Init, deterMx, i; + + + if (*nActive == 0 || *nActive == 3) + return 0; + + if (*nActive == -1) + { + Init = 1; + + deterMx = deterRotMx(Mx); + if (deterMx) + { + InverseRotMx(Mx, InvMx); + + *nActive = 3; + return deterMx; + } + } + else + Init = 0; + + if (Init || *nActive == 2) + { + for (;;) + { + if (Init) + { + irActive[0] = 0; + irActive[1] = 1; + icActive[0] = 0; + icActive[1] = 1; + Init = 0; + } + else + { + if (++icActive[1] == 3) { + if (++icActive[0] == 2) { + if (++irActive[1] == 3) { + if (++irActive[0] == 2) { + Init = 1; + break; + } + else { + irActive[1] = irActive[0] + 1; + icActive[0] = 0; + icActive[1] = 1; + } + } + else { + icActive[0] = 0; + icActive[1] = 1; + } + } + else { + icActive[1] = icActive[0] + 1; + } + } + } + + InvMx[0] = Mx[irActive[1] * 3 + icActive[1]]; + InvMx[1] = - Mx[irActive[0] * 3 + icActive[1]]; + InvMx[2] = - Mx[irActive[1] * 3 + icActive[0]]; + InvMx[3] = Mx[irActive[0] * 3 + icActive[0]]; + + deterMx = InvMx[3] * InvMx[0] - InvMx[1] * InvMx[2]; + if (deterMx) { + *nActive = 2; + return deterMx; + } + } + } + + if (*nActive == 2) + return 0; + + if (Init) i = 0; + else i = irActive[0] * 3 + icActive[0] + 1; + + for ( ; i < 9; i++) + { + if (Mx[i]) { + irActive[0] = i / 3; + icActive[0] = i % 3; + *nActive = 1; + return Mx[i]; + } + } + + if (*nActive == 1) + return 0; + + *nActive = 0; + return 1; +} + + +static int SetInvCBMxT(const int *CBMxT, const int *InvCBMxR, int *InvCBMxT) +{ + int i; + + + RotMx_t_Vector(InvCBMxT, InvCBMxR, CBMxT, CRBF * CTBF); + + for (i = 0; i < 3; i++) + { + if (InvCBMxT[i] % CRBF) { + SetSgError("Internal Error: SetInvCBMxT()"); + return -1; + } + + if (InvCBMxT[i]) + InvCBMxT[i] = CTBF - InvCBMxT[i] / CRBF; + } + + return 0; +} + + +static int FixAxes(const T_SgInfo *SgInfo, + const T_SgInfo *GenSgI, const int *iGen, + T_RTMx *CBMx, T_RTMx *InvCBMx, + int *FreeMx, int TryAgain) +{ + int i, NextTryAgain; + int IniCBMxT[3], SingleFreeMx[9]; + T_RTMx SMxG, SMxS_G; + int NextFreeMxBuf[9], R_I_FMxBuf[9]; + int R_I[9], *R_I_FMx, InvR_I_FMx[9], deterR_I_FMx; + int S_G[3], CmpS_G[3], RedSh[3], Sh[3], *NextFreeMx; + int nActive, irActive[3], icActive[3]; + int nTrV, iTrV; + const int *TrV; + + + if (FreeMx == NULL) { + for (i = 0; i < 3; i++) { + CBMx->s.T[i] = 0; + InvCBMx->s.T[i] = 0; + } + } + + i = StartFixAxes(SgInfo, GenSgI, iGen, CBMx, InvCBMx, + &SMxG, &SMxS_G, SingleFreeMx, &NextTryAgain); + if (i != 1) + return i; + + if (FreeMx) { + RotMxMultiply(NextFreeMxBuf, SingleFreeMx, FreeMx); + NextFreeMx = NextFreeMxBuf; + } + else + NextFreeMx = SingleFreeMx; + + for (i = 0; i < 9; i++) + R_I[i] = SMxG.s.R[i]; + + for (i = 0; i < 9; i += 4) + R_I[i] -= 1; + + if (FreeMx) { + RotMxMultiply(R_I_FMxBuf, R_I, FreeMx); + R_I_FMx = R_I_FMxBuf; + } + else + R_I_FMx = R_I; + + for (i = 0; i < 3; i++) + IniCBMxT[i] = CBMx->s.T[i]; + + nActive = -1; + + for (;;) + { + deterR_I_FMx = FindInvertableMx(R_I_FMx, InvR_I_FMx, + &nActive, irActive, icActive); + if (deterR_I_FMx == 0) + break; + + nTrV = GenSgI->LatticeInfo->nTrVector; + TrV = GenSgI->LatticeInfo->TrVector; + + for (iTrV = 0; iTrV < nTrV; iTrV++, TrV += 3) + { + for (i = 0; i < 3; i++) { + S_G[i] = (CTBF / STBF) + * ((SMxS_G.s.T[i] - SMxG.s.T[i] - TrV[i]) % STBF); + RedSh[i] = 0; + } + + switch(nActive) + { + case 1: + RedSh[icActive[0]] = S_G[irActive[0]]; + break; + case 2: + RedSh[icActive[0]] = InvR_I_FMx[0] * S_G[irActive[0]] + + InvR_I_FMx[1] * S_G[irActive[1]]; + RedSh[icActive[1]] = InvR_I_FMx[2] * S_G[irActive[0]] + + InvR_I_FMx[3] * S_G[irActive[1]]; + break; + case 3: + RotMx_t_Vector(RedSh, InvR_I_FMx, S_G, 0); + break; + default: + break; + } + + if (FreeMx) + { + RotMx_t_Vector(Sh, FreeMx, RedSh, 0); + + for (i = 0; i < 3; i++) + Sh[i] %= (CTBF * abs(deterR_I_FMx)); + } + else + { + for (i = 0; i < 3; i++) + Sh[i] = RedSh[i] % (CTBF * abs(deterR_I_FMx)); + } + + RotMx_t_Vector(CmpS_G, R_I, Sh, 0); + + for (i = 0; i < 3; i++) + if ((CmpS_G[i] - S_G[i] * deterR_I_FMx) % (CTBF * abs(deterR_I_FMx))) + break; + + if (i < 3) + continue; + + if (deterR_I_FMx != 1) + { + for (i = 0; i < 3; i++) + { + if (Sh[i] % abs(deterR_I_FMx)) + goto ReturnError; + + Sh[i] /= deterR_I_FMx; + } + } + + for (i = 0; i < 3; i++) { + CBMx->s.T[i] = IniCBMxT[i] + Sh[i] % CTBF; + if (CBMx->s.T[i] < 0) + CBMx->s.T[i] += CTBF; + } + + if (SetInvCBMxT(CBMx->s.T, InvCBMx->s.R, InvCBMx->s.T) != 0) + return -1; + + if (iGen[1] == 0) + return 1; + + i = FixAxes(SgInfo, GenSgI, &iGen[1], CBMx, InvCBMx, + NextFreeMx, NextTryAgain); + if (i != 0) + return i; + } + + if (TryAgain == 0) + break; + } + + return 0; + + ReturnError: + + SetSgError("Internal Error: FixAxes()"); + return -1; +} + + +static int CompleteCBMx(const T_SgInfo *SgInfo, const T_LatticeInfo *NewLI, + const T_SgInfo *GenSgI, + const int *IniCBMxR, const int *IniInvCBMxR, + T_RTMx *CBMx, T_RTMx *InvCBMx) +{ + int iGen[5], i; + + + if (SgInfo->XtalSystem == XS_Triclinic) + { + for (i = 0; i < 9; i++) { + CBMx->s.R[i] = IniCBMxR[i]; + InvCBMx->s.R[i] = IniInvCBMxR[i]; + } + + if (GenSgI->PointGroup == PG_1) + { + for (i = 0; i < 3; i++) { + CBMx->s.T[i] = 0; + InvCBMx->s.T[i] = 0; + } + return 1; + } + + iGen[0] = -1; + iGen[1] = 0; + + return FixAxes(SgInfo, GenSgI, iGen, CBMx, InvCBMx, NULL, 0); + } + + if (SgInfo->XtalSystem == XS_Monoclinic) + { + int iCCs, BufRMx[9]; + int RMxCCs_Buf[9], RMxCCn_Buf[9], InvRMxCCn_Buf[9], RotLTrV[3]; + const int *RMxAA, *RMxCCs, *RMxCCn, *InvRMxCCn, *TrV; + T_RTMx BufCBMx, BufInvCBMx; + + + if (NewLI->nTrVector != 1 && NewLI->nTrVector != 2) + goto ReturnError; + + for (i = 0; i < 9; i++) { + BufCBMx.s.R[i] = IniCBMxR[i]; + BufInvCBMx.s.R[i] = IniInvCBMxR[i]; + } + + i = AlignUniqueAxis(SgInfo, GenSgI, + BufCBMx.s.R, BufInvCBMx.s.R, &RMxAA); + if (i != 1) + return i; + + if (GenSgI->nList < 2) + goto ReturnError; + + for (i = 0; i < 9; i++) { + RMxCCs_Buf[i] = RMx_2_110[i]; + RMxCCn_Buf[i] = RMx_3_001[i]; + } + + switch (GenSgI->ListRotMxInfo[1].RefAxis) + { + case 'z': break; + case 'x': RotateRotMx(RMxCCs_Buf, RMx_3_111, RMx_3i111); + RotateRotMx(RMxCCn_Buf, RMx_3_111, RMx_3i111); + break; + case 'y': RotateRotMx(RMxCCs_Buf, RMx_3i111, RMx_3_111); + RotateRotMx(RMxCCn_Buf, RMx_3i111, RMx_3_111); + break; + default: + goto ReturnError; + } + + InverseRotMx(RMxCCn_Buf, InvRMxCCn_Buf); + + i = 0; + iGen[i++] = 1; + if (GenSgI->PointGroup == PG_2_m) iGen[i++] = -1; + iGen[i ] = 0; + + RMxCCs = RMx_1_000; + + for (iCCs = 0; iCCs < 2; iCCs++, RMxCCs = RMxCCs_Buf) + { + RMxCCn = InvRMxCCn = RMx_1_000; + + for (;;) + { + if (NewLI->nTrVector == 2) + { + RotMx_t_Vector(RotLTrV, RMxAA, &NewLI->TrVector[3], STBF); + RotMx_t_Vector(BufRMx, RMxCCn, RotLTrV, STBF); + RotMx_t_Vector(RotLTrV, RMxCCs, BufRMx, STBF); + + TrV = &GenSgI->LatticeInfo->TrVector[3]; + + for (i = 0; i < 3; i++) + if (RotLTrV[i] != TrV[i]) + break; + } + + if (NewLI->nTrVector == 1 || i == 3) + { + RotMxMultiply(BufRMx, RMxCCn, BufCBMx.s.R); + RotMxMultiply(CBMx->s.R, RMxCCs, BufRMx); + + RotMxMultiply(BufRMx, BufInvCBMx.s.R, InvRMxCCn); + RotMxMultiply(InvCBMx->s.R, BufRMx, RMxCCs); + + i = FixAxes(SgInfo, GenSgI, iGen, CBMx, InvCBMx, NULL, 0); + if (i != 0) + return i; + } + + if (RMxCCn == RMx_1_000) { + RMxCCn = RMxCCn_Buf; InvRMxCCn = InvRMxCCn_Buf; } + else if (RMxCCn == RMxCCn_Buf) { + RMxCCn = InvRMxCCn_Buf; InvRMxCCn = RMxCCn_Buf; } + else { + RMxCCn = NULL; + break; + } + } + } + + return 0; + } + + for (i = 0; i < 9; i++) { + CBMx->s.R[i] = IniCBMxR[i]; + InvCBMx->s.R[i] = IniInvCBMxR[i]; + } + + if (SgInfo->XtalSystem == XS_Orthorhombic) + { + int iNextBasis; + int BufCBMxR[9], BufInvCBMxR[9]; + int NLTrV_Buf1[3], NLTrV_Buf2[3]; + const int *NLTrV, *GLTrV; + + + if ((GenSgI->LatticeInfo->Code == 'I') != (NewLI->Code == 'I')) + return 0; + + if ( NewLI->Code == 'A' + || NewLI->Code == 'B' + || NewLI->Code == 'C') { + NLTrV = &NewLI->TrVector[3]; + GLTrV = &GenSgI->LatticeInfo->TrVector[3]; } + else { + NLTrV = NULL; + GLTrV = NULL; } + i = 0; + iGen[i++] = 1; + iGen[i++] = 2; + if (GenSgI->PointGroup == PG_mmm) iGen[i++] = -1; + iGen[i ] = 0; + + for (iNextBasis = 0; iNextBasis < 6; iNextBasis++) + { + if (iNextBasis % 2) + { + RotMxMultiply( BufCBMxR, RMx_2_110, CBMx->s.R); + RotMxMultiply(BufInvCBMxR, InvCBMx->s.R, RMx_2_110); + + for (i = 0; i < 9; i++) { + CBMx->s.R[i] = BufCBMxR[i]; + InvCBMx->s.R[i] = BufInvCBMxR[i]; + } + } + else if (iNextBasis == 2) { + RotMxMultiply( CBMx->s.R, RMx_3_111, IniCBMxR); + RotMxMultiply(InvCBMx->s.R, IniInvCBMxR, RMx_3i111); + } + else if (iNextBasis) { + RotMxMultiply( CBMx->s.R, RMx_3i111, IniCBMxR); + RotMxMultiply(InvCBMx->s.R, IniInvCBMxR, RMx_3_111); + } + + if (NLTrV) + { + if (iNextBasis % 2) { + RotMx_t_Vector(NLTrV_Buf1, RMx_2_110, NLTrV, STBF); + NLTrV = NLTrV_Buf1; + } + else if (iNextBasis == 2) { + RotMx_t_Vector(NLTrV_Buf2, RMx_3_111, &NewLI->TrVector[3], STBF); + NLTrV = NLTrV_Buf2; + } + else if (iNextBasis) { + RotMx_t_Vector(NLTrV_Buf2, RMx_3i111, &NewLI->TrVector[3], STBF); + NLTrV = NLTrV_Buf2; + } + + for (i = 0; i < 3; i++) + if (NLTrV[i] != GLTrV[i]) + break; + + if (i < 3) + continue; + } + + i = FixAxes(SgInfo, GenSgI, iGen, CBMx, InvCBMx, NULL, 0); + if (i != 0) + return i; + } + } + + if (SgInfo->XtalSystem == XS_Tetragonal) + { + i = AlignUniqueAxis(SgInfo, GenSgI, CBMx->s.R, InvCBMx->s.R, NULL); + if (i != 1) + return -1; + i = 0; + iGen[i++] = 1; + + switch (GenSgI->PointGroup) { + case PG_422: + case PG_4mm: + case PG_4b2m: + case PG_4bm2: + case PG_4_mmm: iGen[i++] = 2; + } + + switch (GenSgI->PointGroup) { + case PG_4_m: + case PG_4_mmm: iGen[i++] = -1; + } + iGen[i ] = 0; + + return FixAxes(SgInfo, GenSgI, iGen, CBMx, InvCBMx, NULL, 0); + } + + if (SgInfo->XtalSystem == XS_Trigonal) + { + i = AlignUniqueAxis(SgInfo, GenSgI, CBMx->s.R, InvCBMx->s.R, NULL); + if (i != 1) + return i; + i = 0; + + switch (GenSgI->PointGroup) { + case PG_3: + case PG_312: + case PG_32: + case PG_3m1: + case PG_3m: iGen[i++] = 1; + break; + case PG_3b: + case PG_3bm1: + case PG_3b1m: + case PG_3bm: iGen[i++] = -3; + } + + switch (GenSgI->PointGroup) { + case PG_321: + case PG_312: + case PG_32: + case PG_3m1: + case PG_31m: + case PG_3m: + case PG_3bm1: + case PG_3b1m: + case PG_3bm: iGen[i++] = 2; + } + + switch (GenSgI->PointGroup) { + case PG_321: + case PG_31m: iGen[i++] = 1; + } + iGen[i ] = 0; + + return FixAxes(SgInfo, GenSgI, iGen, CBMx, InvCBMx, NULL, 0); + } + + if (SgInfo->XtalSystem == XS_Hexagonal) + { + i = AlignUniqueAxis(SgInfo, GenSgI, CBMx->s.R, InvCBMx->s.R, NULL); + if (i != 1) + return -1; + i = 0; + + switch (GenSgI->PointGroup) { + case PG_6bm2: + case PG_6b2m: iGen[i++] = 2; + } + iGen[i++] = 1; + + switch (GenSgI->PointGroup) { + case PG_622: + case PG_6mm: + case PG_6_mmm: iGen[i++] = 2; + } + + switch (GenSgI->PointGroup) { + case PG_6_m: + case PG_6_mmm: iGen[i++] = -1; + } + iGen[i ] = 0; + + return FixAxes(SgInfo, GenSgI, iGen, CBMx, InvCBMx, NULL, 0); + } + + if (SgInfo->XtalSystem == XS_Cubic) + { i = 0; + iGen[i++] = 3; + iGen[i++] = 1; + iGen[i++] = 2; + if ( GenSgI->PointGroup == PG_m3b + || GenSgI->PointGroup == PG_m3bm) iGen[i++] = -1; + iGen[i ] = 0; + + return FixAxes(SgInfo, GenSgI, iGen, CBMx, InvCBMx, NULL, 0); + } + + return 0; + + ReturnError: + + SetSgError("Internal Error: CompleteCBMx()"); + return -1; +} + + +const T_TabSgName *FindReferenceSpaceGroup(T_SgInfo *SgInfo, + T_RTMx *CBMx, T_RTMx *InvCBMx) +{ + int stat, NewPG, SgInfo_CI, OL_SgInfo, OL_GenSgI; + const T_TabSgName *tsgn; + T_SgInfo GenSgI; + T_RTMx GenSgI_ListSeitzMx[5]; + T_RotMxInfo GenSgI_ListRotMxInfo[5]; + int iList, PrevSgNumber; + int FacIniCBMxR; + T_RotMxInfo *lrmxi; + const T_LatticeInfo *NewLI; + int IniCBMxR[9], IniInvCBMxR[9]; + + + GenSgI.MaxList = 5; + GenSgI.ListSeitzMx = GenSgI_ListSeitzMx; + GenSgI.ListRotMxInfo = GenSgI_ListRotMxInfo; + + FacIniCBMxR = InitialCBMxR(SgInfo, &NewLI, &NewPG, IniCBMxR, IniInvCBMxR); + if (FacIniCBMxR < 0) + return NULL; + + OL_SgInfo = SgInfo->OrderL; + if (OL_SgInfo % FacIniCBMxR) + goto ReturnError; + + OL_SgInfo /= FacIniCBMxR; + + SgInfo_CI = (SgInfo->Centric || SgInfo->InversionOffOrigin); + + PrevSgNumber = 0; + + for (tsgn = TabSgName; tsgn->HallSymbol; tsgn++) + { + if (tsgn->HallSymbol[1] == 'R') + continue; + + if (VolAPointGroups[tsgn->SgNumber] != NewPG) + continue; + + if (tsgn->SgNumber == PrevSgNumber) + continue; + + PrevSgNumber = tsgn->SgNumber; + + InitSgInfo(&GenSgI); + GenSgI.GenOption = -1; + + ParseHallSymbol(tsgn->HallSymbol, &GenSgI); + + if (SgError != NULL) + return NULL; + + if (ApplyOriginShift(&GenSgI) < 0) + return NULL; + + if (SgInfo_CI != (GenSgI.Centric || GenSgI.InversionOffOrigin)) + goto ReturnError; + + OL_GenSgI = GenSgI.LatticeInfo->nTrVector; + + if (SgInfo_CI) + OL_GenSgI *= 2; + + lrmxi = &GenSgI.ListRotMxInfo[1]; + + for (iList = 1; iList < GenSgI.nList; iList++, lrmxi++) + { + OL_GenSgI *= abs(lrmxi->Order); + + if ( (lrmxi->Order == -1 || lrmxi->Order == -3) + && GenSgI.Centric == 0 && GenSgI.InversionOffOrigin == 0) + goto ReturnError; + } + + if (OL_GenSgI == OL_SgInfo) + { + if (NewLI->nTrVector != GenSgI.LatticeInfo->nTrVector) + goto ReturnError; + + GenSgI.PointGroup = NewPG; + +#if DEBUG_FindConventionalSetting + fprintf(stdout, "%s ?= %s (%d)\n", + SgInfo->HallSymbol, tsgn->HallSymbol, tsgn->SgNumber); +#endif + + stat = CompleteCBMx(SgInfo, NewLI, &GenSgI, + IniCBMxR, IniInvCBMxR, + CBMx, InvCBMx); + if (stat < 0) + return NULL; + + if (stat) + return tsgn; + } + } + + SetSgError("Internal Error: Space Group not found"); + return NULL; + + ReturnError: + + SetSgError("Internal Error: FindReferenceSpaceGroup()"); + return NULL; +} diff --git a/sghkl.c b/sghkl.c new file mode 100644 index 00000000..db3f2e06 --- /dev/null +++ b/sghkl.c @@ -0,0 +1,280 @@ +/* + Space Group Info's (c) 1994-96 Ralf W. Grosse-Kunstleve + */ + +#include +#include + + +#include "sginfo.h" + + +static const char *IErr_Inc_SymMx = + "Internal Error: Inconsistent symmetry matrices"; + + +int IsSysAbsent_hkl(const T_SgInfo *SgInfo, + int h, int k, int l, int *TH_Restriction) +{ + int iTrV, nTrV; + const int *TrV; + int iList, mh, mk, ml, hm, km, lm; + int TH, THr, FlagMismatch; + const T_RTMx *lsmx; + + + mh = -h; + mk = -k; + ml = -l; + + /* check list of symmetry operations + take care of lattice type and "centric" flag */ + + THr = -1; + if (TH_Restriction != NULL) *TH_Restriction = THr; + FlagMismatch = 0; + + nTrV = SgInfo->LatticeInfo->nTrVector; + lsmx = SgInfo->ListSeitzMx; + + for (iList = 0; iList < SgInfo->nList; iList++, lsmx++) + { + hm = lsmx->s.R[0] * h + lsmx->s.R[3] * k + lsmx->s.R[6] * l; + km = lsmx->s.R[1] * h + lsmx->s.R[4] * k + lsmx->s.R[7] * l; + lm = lsmx->s.R[2] * h + lsmx->s.R[5] * k + lsmx->s.R[8] * l; + + TrV = SgInfo->LatticeInfo->TrVector; + + for (iTrV = 0; iTrV < nTrV; iTrV++) + { + TH = (lsmx->s.T[0] + *TrV++) * h; + TH += (lsmx->s.T[1] + *TrV++) * k; + TH += (lsmx->s.T[2] + *TrV++) * l; + TH %= STBF; if (TH < 0) TH += STBF; + + if (mh == hm && mk == km && ml == lm) + { + if (TH != 0 && SgInfo->Centric == -1) + return -(iList + 1 + iTrV * SgInfo->nList); + + if (THr < 0) + THr = TH; + else if (THr != TH) + FlagMismatch = 1; /* must be systematic absent */ + /* will check later ... */ + } + else if ( h == hm && k == km && l == lm) + { + if (TH != 0) + return (iList + 1 + iTrV * SgInfo->nList); + } + else + break; + } + } + + if (THr >= 0 && FlagMismatch) /* ... consistency check */ + SetSgError(IErr_Inc_SymMx); + + if (TH_Restriction != NULL) + { + if (SgInfo->Centric == -1) *TH_Restriction = 0; + else *TH_Restriction = THr; + } + + return 0; +} + + +int BuildEq_hkl(const T_SgInfo *SgInfo, T_Eq_hkl *Eq_hkl, int h, int k, int l) +{ + int iList, hm, km, lm, i; + T_RTMx *lsmx; + T_Eq_hkl BufEq_hkl; + + + if (Eq_hkl == NULL) + Eq_hkl = &BufEq_hkl; + + Eq_hkl->M = 1; + Eq_hkl->N = 1; + Eq_hkl->h[0] = h; + Eq_hkl->k[0] = k; + Eq_hkl->l[0] = l; + Eq_hkl->TH[0] = 0; + + if (! (h || k || l)) + return Eq_hkl->M; /* this is 000 */ + + Eq_hkl->M++; + + /* check list of symmetry operations */ + + lsmx = &SgInfo->ListSeitzMx[1]; /* skip first = identity matrix */ + + for (iList = 1; iList < SgInfo->nList; iList++, lsmx++) + { + hm = lsmx->s.R[0] * h + lsmx->s.R[3] * k + lsmx->s.R[6] * l; + km = lsmx->s.R[1] * h + lsmx->s.R[4] * k + lsmx->s.R[7] * l; + lm = lsmx->s.R[2] * h + lsmx->s.R[5] * k + lsmx->s.R[8] * l; + + for (i = 0; i < Eq_hkl->N; i++) + { + if ( ( hm == Eq_hkl->h[i] && km == Eq_hkl->k[i] && lm == Eq_hkl->l[i]) + || (-hm == Eq_hkl->h[i] && -km == Eq_hkl->k[i] && -lm == Eq_hkl->l[i])) + break; + } + + if (i == Eq_hkl->N) + { + if (Eq_hkl->N >= 24) { + SetSgError(IErr_Inc_SymMx); + return 0; + } + + Eq_hkl->h[i] = hm; + Eq_hkl->k[i] = km; + Eq_hkl->l[i] = lm; + + Eq_hkl->TH[i] = ( lsmx->s.T[0] * h + + lsmx->s.T[1] * k + + lsmx->s.T[2] * l) % STBF; + if (Eq_hkl->TH[i] < 0) + Eq_hkl->TH[i] += STBF; + + Eq_hkl->M += 2; + Eq_hkl->N++; + } + } + + if (SgInfo->nList % Eq_hkl->N) /* another error trap */ { + SetSgError(IErr_Inc_SymMx); + return 0; + } + + return Eq_hkl->M; +} + + +int AreSymEquivalent_hkl(const T_SgInfo *SgInfo, int h1, int k1, int l1, + int h2, int k2, int l2) +{ + int iList, mh2, mk2, ml2, hm, km, lm; + T_RTMx *lsmx; + + + mh2 = -h2; + mk2 = -k2; + ml2 = -l2; + + /* check list of symmetry operations */ + + lsmx = SgInfo->ListSeitzMx; + + for (iList = 0; iList < SgInfo->nList; iList++, lsmx++) + { + hm = lsmx->s.R[0] * h1 + lsmx->s.R[3] * k1 + lsmx->s.R[6] * l1; + km = lsmx->s.R[1] * h1 + lsmx->s.R[4] * k1 + lsmx->s.R[7] * l1; + lm = lsmx->s.R[2] * h1 + lsmx->s.R[5] * k1 + lsmx->s.R[8] * l1; + + if ( h2 == hm && k2 == km && l2 == lm) + return (iList + 1); + + else if (mh2 == hm && mk2 == km && ml2 == lm) + return -(iList + 1); + } + + return 0; +} + + +void SetListMin_hkl(const T_SgInfo *SgInfo, int Maxk, int Maxl, + int *Minh, int *Mink, int *Minl) +{ + *Minh = 0; + + switch(SgInfo->XtalSystem) + { + case XS_Triclinic: + *Mink = -Maxk; + *Minl = -Maxl; + break; + case XS_Monoclinic: + if (SgInfo->UniqueRefAxis == 'z') + { + *Mink = -Maxk; + *Minl = 0; + } + else + { + *Mink = 0; + *Minl = -Maxl; + } + break; + default: + if (SgInfo->XtalSystem == XS_Trigonal && SgInfo->UniqueDirCode == '*') + *Mink = -Maxk; + else + *Mink = 0; + *Minl = 0; + break; + } +} + + +int IsSuppressed_hkl(const T_SgInfo *SgInfo, int Minh, int Mink, int Minl, + int Maxk, int Maxl, + int h, int k, int l) +{ + int iList, mate, hm, km, lm; + T_RTMx *lsmx; + + + /* check for Friedel mate first */ + + hm = -h, km = -k, lm = -l; + + if ( (Minh <= hm && hm <= h) + && (Mink <= km && km <= Maxk) + && (Minl <= lm && lm <= Maxl)){ + if (hm < h) return -1; + else /* if (h == 0) */ + if (km < k) return -1; + else if (k == 0) + if (lm < l) return -1; + } + + lsmx = &SgInfo->ListSeitzMx[1]; /* skip first = identity matrix */ + + for (iList = 1; iList < SgInfo->nList; iList++, lsmx++) + { + /* check if equivalent hm, km, lm are inside loop range ... */ + + hm = lsmx->s.R[0] * h + lsmx->s.R[3] * k + lsmx->s.R[6] * l; + km = lsmx->s.R[1] * h + lsmx->s.R[4] * k + lsmx->s.R[7] * l; + lm = lsmx->s.R[2] * h + lsmx->s.R[5] * k + lsmx->s.R[8] * l; + + for (mate = 0; mate < 2; mate++) + { + if (mate) hm = -hm, km = -km, lm = -lm; /* ... or friedel mate */ + + if ( Minh <= hm && hm <= h + && Mink <= km && km <= Maxk + && Minl <= lm && lm <= Maxl) + { + /* ... and were processed before */ + + if (hm < h) + return (mate ? -(iList + 1) : iList + 1); + else /* if (hm == h) */ + if (km < k) + return (mate ? -(iList + 1) : iList + 1); + else if (km == k) + if (lm < l) + return (mate ? -(iList + 1) : iList + 1); + } + } + } + + return 0; +} diff --git a/sginfo.c b/sginfo.c new file mode 100644 index 00000000..1c6f02e4 --- /dev/null +++ b/sginfo.c @@ -0,0 +1,1966 @@ +/* + Space Group Info's (c) 1994-96 Ralf W. Grosse-Kunstleve + */ + +#include +#include +#include +#include + + +/* + Macintosh extras (Courtesy Jon Tischler ) + */ +#if defined(__THINK__) || defined(__MWERKS__) +#include +#define CONSOLE_LINES 36 /* number of lines to use for console */ +#define CONSOLE_COLUMNS 90 /* number of columns to use for console */ +#ifdef __MWERKS__ +#include +#endif +#endif + + +#define AppMalloc(ptr, n) (ptr) = malloc((n) * sizeof (*(ptr))) +#define AppFree(ptr, n) free(ptr) + + +#define SGCOREDEF__ +#include "sginfo.h" + + +#if USE_GS_SI + +static int PrimitiveRotMx(const int *CCMx_LP, int *RotMx, const int *CCMx_PL, + int deterCCMx_LP) +{ + int i; + int BufMx[9]; + + + /* Mp = Tlp . Mz . Tpl */ + + RotMxMultiply(BufMx, RotMx, CCMx_PL); + RotMxMultiply(RotMx, CCMx_LP, BufMx); + + for (i = 0; i < 9; i++) + { + if (RotMx[i] % deterCCMx_LP) { + SetSgError("Internal Error: PrimitiveRotMx()"); + return -1; + } + } + + for (i = 0; i < 9; i++) + RotMx[i] /= deterCCMx_LP; + + return 0; +} + + +static int Find_si(T_SgInfo *SgInfo) +{ + static const int Tab_si_Vector[] = + { + 1, 0, 0, 0, /* h */ + 0, 1, 0, 1, /* k */ + 0, 0, 1, 2, /* l */ + 1, 1, 0, 0, /* h+k */ + 1, -1, 0, 0, /* h-k */ + 0, 1, 1, 1, /* k+l */ + 0, 1, -1, 1, /* k-l */ + 1, 0, 1, 1, /* h+l */ + 1, 0, -1, 1, /* h-l */ + 1, 1, 1, 0, /* h+k+l */ + 1, 1, -1, 0, /* h+k-l */ + 1, -1, 1, 0, /* h-k+l */ + -1, 1, 1, 0, /* -h+k+l */ + 2, 1, -1, 0, /* 2h+k-l */ + 2, -1, 1, 0, /* 2h-k+l */ + -1, 2, 1, 0, /* -h+2k+l */ + 1, 2, -1, 0, /* h+2k-l */ + -1, 1, 2, 0, /* -h+k+2l */ + 1, -1, 2, 0 /* h-k+2l */ + }; + + static int nTab_si_Vector + = sizeof Tab_si_Vector / sizeof (*Tab_si_Vector) / 4; + + int deterCCMx_LP, CCMx_PL[9]; + int i, itabsiv; + int nLoopInv, iLoopInv, n_si_v, i_si_v; + int n, m, l; + int IsFine; + int item[3]; + int R_I[9], si_Buf[9]; + int iList; + T_RTMx *lsmx; + const int *tabsiv; + + + if (SgInfo->LatticeInfo->Code != 'P') + { + deterCCMx_LP = deterRotMx(SgInfo->CCMx_LP); + InverseRotMx(SgInfo->CCMx_LP, CCMx_PL); + + if (deterCCMx_LP < 1) + goto ReturnError; + } + + nLoopInv = Sg_nLoopInv(SgInfo); + + SgInfo->n_si_Vector = n_si_v = 0; + + for (i = 0; i < 9; i++) + SgInfo->si_Vector[i] = 0; + + for (i = 0; i < 3; i++) + { + SgInfo->si_Modulus[i] = 1; + item[i] = 1; + } + + tabsiv = Tab_si_Vector; + + for (itabsiv = 0; itabsiv < nTab_si_Vector; itabsiv++, tabsiv += 4) + { + IsFine = 1; + m = -1; + + for (iList = 0; IsFine && iList < SgInfo->nList; iList++) + { + lsmx = &SgInfo->ListSeitzMx[iList]; + + for (iLoopInv = 0; IsFine && iLoopInv < nLoopInv; iLoopInv++) + { + if (iLoopInv == 0) + for (i = 0; i < 9; i++) + { + if (i % 4) R_I[i] = lsmx->s.R[i]; + else R_I[i] = lsmx->s.R[i] - 1; + } + else + for (i = 0; i < 9; i++) + { + if (i % 4) R_I[i] = -lsmx->s.R[i]; + else R_I[i] = -lsmx->s.R[i] - 1; + } + + if (SgInfo->LatticeInfo->Code != 'P') + { + if (PrimitiveRotMx(SgInfo->CCMx_LP, R_I, CCMx_PL, + deterCCMx_LP) < 0) + return -1; + } + + for (i = 0; IsFine && i < 3; i++) + { + n = tabsiv[0] * R_I[i * 3 + 0]; + n += tabsiv[1] * R_I[i * 3 + 1]; + n += tabsiv[2] * R_I[i * 3 + 2]; + n = abs(n); + + if (n == 1) + IsFine = 0; + else if (m < 2) + m = n; + else if (n > 0 && n != m) + IsFine = 0; + } + } + } + + if (IsFine) + { +#if DEBUG_Find_si + fprintf(stdout, "H-Kt %2d %2d %2d %d\n", + tabsiv[0], tabsiv[1], tabsiv[2], m); +#endif + + l = tabsiv[3]; + + while (item[l] > 1) /* just "if", see break's */ + { + if (m == item[l]) break; + + if (m == 3 && ( SgInfo->XtalSystem != XS_Trigonal + || SgInfo->UniqueDirCode != '=')) break; + + if (m == 4 && ( SgInfo->XtalSystem == XS_Triclinic + || SgInfo->XtalSystem == XS_Monoclinic)) break; + + if (m == 2) break; + + /* if (m > 1 || m != 4) break; */ + + n_si_v--; + item[l] = 1; + break; + } + + if (item[l] == 1) + { + if (itabsiv > 12) + n_si_v = 0; + + item[l] = m; + SgInfo->si_Modulus[n_si_v] = m; + + n = n_si_v * 3; + for (i = 0; i < 3; i++) + SgInfo->si_Vector[n++] = tabsiv[i]; + + n_si_v++; + } + } + } + +#if DEBUG_Find_si + fprintf(stdout, "H-Kt\n"); +#endif + + if (SgInfo->LatticeInfo->Code != 'P') + { +#if DEBUG_Find_si + for (i = 0; i < n_si_v; i++) + fprintf(stdout, "H-Kp %2d %2d %2d %d\n", + SgInfo->si_Vector[i * 3 + 0], + SgInfo->si_Vector[i * 3 + 1], + SgInfo->si_Vector[i * 3 + 2], + SgInfo->si_Modulus[i]); + fprintf(stdout, "H-Kp\n"); +#endif + + for (i_si_v = 0; i_si_v < n_si_v; i_si_v++) + { + for (i = 0; i < 3; i++) + { + si_Buf[i_si_v * 3 + i] + = SgInfo->si_Vector[i_si_v * 3 + 0] * CCMx_PL[i * 3 + 0] + + SgInfo->si_Vector[i_si_v * 3 + 1] * CCMx_PL[i * 3 + 1] + + SgInfo->si_Vector[i_si_v * 3 + 2] * CCMx_PL[i * 3 + 2]; + } + } + + for (i = 0; i < i_si_v * 3; i++) + { + if (si_Buf[i] % deterCCMx_LP) + { + n = i / 3; n *= 3; + fprintf(stdout, " %3d %3d %3d\n", + si_Buf[n + 0], si_Buf[n + 1], si_Buf[n + 2]); + goto ReturnError; + } + + SgInfo->si_Vector[i] = si_Buf[i] / deterCCMx_LP; + } + } + + SgInfo->n_si_Vector = n_si_v; + return n_si_v; + + ReturnError: + + SetSgError("Internal Error: Find_si()"); + return -1; +} + + +static int Try_GS_si(T_SgInfo *SgInfo) +{ + int h, k, l, iList; + int Maxh, Maxk, Maxl; + int Minh, Mink, Minl; + int nTestField, *TestField; + int nProperty, *Property, *pp; + int IsFine, would_be, is; + + + SgInfo->n_si_Vector = -1; + + nTestField = 12 * 12 * 12; + AppMalloc(TestField, nTestField); + if (TestField == NULL) { + SetSgError("Not enough core"); + return -1; + } + + MarkLegalOrigins(SgInfo, TestField); + + Maxh = Maxk = Maxl = 7; + SetListMin_hkl(SgInfo, Maxk, Maxl, &Minh, &Mink, &Minl); + + nProperty = (Maxh - Minh + 1) + * (Maxk - Mink + 1) + * (Maxl - Minl + 1); + + AppMalloc(Property, nProperty); + if (Property == NULL) { + SetSgError("Not enough core"); + AppFree(TestField, nTestField); + return -1; + } + + pp = Property; + for (h = Minh; h <= Maxh; h++) + for (k = Mink; k <= Maxk; k++) + for (l = Minl; l <= Maxl; l++) + { + iList = IsSysAbsent_hkl(SgInfo, h, k, l, NULL); + if (SgError != NULL) + { + AppFree(Property, nProperty); + AppFree(TestField, nTestField); + return -1; + } + + if (iList == 0) + *pp++ = Verify_si(h, k, l, TestField); + else + *pp++ = -1; + } + + if (Find_si(SgInfo) >= 0) + { + IsFine = 1; + + pp = Property; + for (h = Minh; IsFine && h <= Maxh; h++) + for (k = Mink; IsFine && k <= Maxk; k++) + for (l = Minl; IsFine && l <= Maxl; l++) + { + is = *pp++; + + if (is >= 0) + { + would_be = Is_si(SgInfo, h, k, l); + if (is != would_be) + IsFine = 0; + } + } + + if (IsFine) + { + AppFree(Property, nProperty); + AppFree(TestField, nTestField); + return 0; + } + } + + SetSgError("Internal Error: Can't determine s.i. vectors and moduli"); + + AppFree(Property, nProperty); + AppFree(TestField, nTestField); + + return -1; +} + +#endif /* USE_GS_SI */ + + +static const char *progn = "sginfo"; + + +static void progerror(const char *message) +{ + fflush(stdout); + fprintf(stderr, "%s: %s\n", progn, message); + exit(1); +} + + +static void NotEnoughCore(void) +{ + progerror("Not enough core"); +} + + +static void PrintClearSgError(int ClearError, int CertainSgError) +{ + if (CertainSgError && SgError == NULL) + SetSgError("Internal Error: SgError not set but should be"); + + if (SgError) + { + fprintf(stdout, "%s: %s\n", progn, SgError); + if (ClearError == 0) exit(1); + SgError = NULL; + } +} + + +static int str_icmp(const char *s, const char *t) +{ + char cs, ct; + + while (*s || *t) + { cs = toupper(*s++); + ct = toupper(*t++); + if (cs < ct) return -1; + if (cs > ct) return 1; + } + return 0; +} + + +static int str_ibegin(const char *s1, const char *s2) /* string ignore-case */ +{ /* begin */ + char u1, u2; + + while (*s1 && *s2) + { + u1 = toupper(*s1++); + u2 = toupper(*s2++); + if (u1 < u2) return -1; + else if (u1 > u2) return 1; + } + if (*s2) return -1; + return 0; +} + + +static const char *LegendTabSgName[] = + { + "", + " Extensions", + " ----------", + " Monoclinic unique axis b unique axis c unique axis a", + " abc c-ba abc ba-c abc -acb", + " ------------ ------------ ------------", + " cell choice 1 :b1 :-b1 :c1 :-c1 :a1 :-a1", + " 2 :b2 :-b2 :c2 :-c2 :a2 :-a2", + " 3 :b3 :-b3 :c3 :-c3 :a3 :-a3", + "", + " Orthorhombic :ba-c change of basis abc -> ba-c", + " :1 origin choice 1", + " :2ba-c origin choice 2, change of basis abc -> ba-c", + "", + " Tetragonal :1 origin choice 1", + " Cubic :2 origin choice 2", + "", + " Trigonal :H hexagonal axes", + " :R rhombohedral axes", + "", + " Number Schoenflies Hermann-Mauguin Hall", + " ------ ----------- --------------- ----", + NULL, + }; + + +static void ListTabSgName(int WantedSgNumber, int VolLetter, FILE *fpout) +{ + int i; + const char *sgl, *ext, **ltsgn; + const T_TabSgName *tsgn, *show, *show_later; + + + if (WantedSgNumber == -1) + for (ltsgn = LegendTabSgName; *ltsgn; ltsgn++) + fprintf(fpout, "%s\n", *ltsgn); + + if (VolLetter == '1') + VolLetter = 'I'; + else + VolLetter = toupper(VolLetter); + + show = show_later = NULL; + + for (tsgn = TabSgName; tsgn->HallSymbol; tsgn++) + { + if ( WantedSgNumber == -1 + || WantedSgNumber == tsgn->SgNumber) + { + if (tsgn->SgNumber >= 3 && tsgn->SgNumber < 16) + { + if (VolLetter == 'I') + { + ext = tsgn->Extension; + if (*ext == '-') + ext++; + + if ( tsgn->Extension[0] == 'b' + && ( tsgn->Extension[1] == '\0' + || tsgn->Extension[1] == '1')) + show_later = tsgn; + else if ( ext[0] == 'c') + { + if (ext[1] == '\0') + show = tsgn; + else + { + i = 0; + for (sgl = tsgn->SgLabels; *sgl; sgl++) + if (*sgl == '=') i++; + + if (i == 2) + show = tsgn; + } + } + } + else if (VolLetter == 'A') + { + if ( tsgn->Extension[0] != '-' + && tsgn->Extension[0] != 'a') + show = tsgn; + } + else + show = tsgn; + } + else if ( tsgn->Extension[0] == 'H' + && VolLetter == 'I') + show_later = tsgn; + else if ( VolLetter == 'A' + || VolLetter == 'I') + { + if ( tsgn->Extension[0] == '\0' + || tsgn->Extension[1] == '\0') + show = tsgn; + } + else + show = tsgn; + + if (show) + { + putc(' ', fpout); + PrintTabSgNameEntry(show, 1, 0, fpout); + putc('\n', fpout); + show = NULL; + + if (show_later) + { + putc(' ', fpout); + PrintTabSgNameEntry(show_later, 1, 0, fpout); + putc('\n', fpout); + show_later = NULL; + } + } + } + } +} + + +static void ListCIF(FILE *fpout) +{ + int n; + const char **loop, *lbl; + const T_TabSgName *tsgn; + + static const char *loop_monoclinic_extensions[] = + { + "_monoclinic_extension # cf. _symmetry_space_group_id", + "_monoclinic_axis # cf. IT Vol. A 1983 sec. 2.16.", + "_monoclinic_setting # cf. IT Vol. A 1983 tab. 2.16.1.", + "_monoclinic_cellchoice # cf. IT Vol. A 1983 sec. 2.16.(i) & fig. 2.6.4.", + "", + " b b abc 1", + " b1 b abc 1", + " b2 b abc 2", + " b3 b abc 3", + "-b b c-ba 1", + "-b1 b c-ba 1", + "-b2 b c-ba 2", + "-b3 b c-ba 3", + " c c abc 1", + " c1 c abc 1", + " c2 c abc 2", + " c3 c abc 3", + "-c c ba-c 1", + "-c1 c ba-c 1", + "-c2 c ba-c 2", + "-c3 c ba-c 3", + " a a abc 1", + " a1 a abc 1", + " a2 a abc 2", + " a3 a abc 3", + "-a a -acb 1", + "-a1 a -acb 1", + "-a2 a -acb 2", + "-a3 a -acb 3", + NULL + }; + + static const char *loop_symmetry_space_group[] = + { + "_symmetry_space_group_id", + "_symmetry_space_group_name_sch", + "_symmetry_space_group_name_h-m # recognised IUCr CIF data names", + "_symmetry_space_group_name_hall # recognised IUCr CIF data names", + NULL + }; + + + fprintf(fpout, "data_ notation\n\n"); + + fprintf(fpout, "loop_\n"); + + for (loop = loop_monoclinic_extensions; *loop; loop++) { + if ((*loop)[0]) fprintf(fpout, " %s", *loop); + putc('\n', fpout); + } + + putc('\n', fpout); + putc('\n', fpout); + + fprintf(fpout, "loop_\n"); + + for (loop = loop_symmetry_space_group; *loop; loop++) { + if ((*loop)[0]) fprintf(fpout, " %s", *loop); + putc('\n', fpout); + } + + putc('\n', fpout); + + for (tsgn = TabSgName; tsgn->HallSymbol; tsgn++) + { + n = fprintf(fpout, " %3d", tsgn->SgNumber); + + if (tsgn->Extension[0]) + n += fprintf(fpout, ":%s", tsgn->Extension); + + if (tsgn->SgNumber < 1 || tsgn->SgNumber > 230) { + SetSgError("Internal Error: ListCIF()"); + return; + } + + while (n < 14) { putc(' ', fpout); n++; } + putc(' ', fpout); n++; + + n += fprintf(fpout, "%s", SchoenfliesSymbols[tsgn->SgNumber]); + + while (n < 22) { putc(' ', fpout); n++; } + putc(' ', fpout); n++; + + n += PrintFullHM_SgName(tsgn, '_', fpout); + + while (n < 36) { putc(' ', fpout); n++; } + putc(' ', fpout); + + for (lbl = tsgn->HallSymbol; *lbl; lbl++) + { + if (*lbl == ' ' && lbl != tsgn->HallSymbol) + putc('_', fpout); + else + putc(*lbl, fpout); + } + + putc('\n', fpout); + } +} + + +static void PutAllXYZ(const T_SgInfo *SgInfo, FILE *fpout) +{ + int iList, f, i; + int nTrV, iTrV, nLoopInv, iLoopInv; + const int *TrV; + T_RTMx SMx; + const T_RTMx *lsmx; + const char *xyz; + char buf0[8], buf1[8], buf2[8]; + + + nLoopInv = Sg_nLoopInv(SgInfo); + + nTrV = SgInfo->LatticeInfo->nTrVector; + TrV = SgInfo->LatticeInfo->TrVector; + + for (iTrV = 0; iTrV < nTrV; iTrV++, TrV += 3) + { + for (iLoopInv = 0; iLoopInv < nLoopInv; iLoopInv++) + { + if (iLoopInv == 0) f = 1; + else f = -1; + + lsmx = SgInfo->ListSeitzMx; + + if (nLoopInv > 1 || nTrV > 1) + putc('#', fpout); + + if (nTrV > 1) + fprintf(fpout, " +(%s %s %s)", + FormatFraction(TrV[0], STBF, 0, buf0, sizeof buf0 / sizeof (*buf0)), + FormatFraction(TrV[1], STBF, 0, buf1, sizeof buf1 / sizeof (*buf1)), + FormatFraction(TrV[2], STBF, 0, buf2, sizeof buf2 / sizeof (*buf2))); + + if (nLoopInv > 1) + fprintf(fpout, " Inversion-Flag = %d", iLoopInv); + + if (nLoopInv > 1 || nTrV > 1) + putc('\n', fpout); + + for (iList = 0; iList < SgInfo->nList; iList++, lsmx++) + { + for (i = 0; i < 9; i++) + SMx.s.R[i] = f * lsmx->s.R[i]; + + for (i = 0; i < 3; i++) + SMx.s.T[i] = iModPositive(f * lsmx->s.T[i] + TrV[i], STBF); + + xyz = RTMx2XYZ(&SMx, 1, STBF, 0, 0, 1, ", ", NULL, 0); + if (xyz) + fprintf(fpout, "%s\n", xyz); + else + { + SetSgError("Internal Error: PutAllXYZ()"); + return; + } + } + } + } + + putc('\n', fpout); +} + + +static void PutMaple(const T_SgInfo *SgInfo, FILE *fpout) +{ + int iList, f, i; + int nTrV, iTrV, nLoopInv, iLoopInv; + const int *TrV; + T_RTMx SMx; + const T_RTMx *lsmx; + int iMatrix; + char buf0[8], buf1[8], buf2[8]; + + + iMatrix = 0; + + nLoopInv = Sg_nLoopInv(SgInfo); + + nTrV = SgInfo->LatticeInfo->nTrVector; + TrV = SgInfo->LatticeInfo->TrVector; + + for (iTrV = 0; iTrV < nTrV; iTrV++, TrV += 3) + { + for (iLoopInv = 0; iLoopInv < nLoopInv; iLoopInv++) + { + if (iLoopInv == 0) f = 1; + else f = -1; + + lsmx = SgInfo->ListSeitzMx; + + if (nLoopInv > 1 || nTrV > 1) + putc('#', fpout); + + if (nTrV > 1) + fprintf(fpout, " +(%s %s %s)", + FormatFraction(TrV[0], STBF, 0, buf0, sizeof buf0 / sizeof (*buf0)), + FormatFraction(TrV[1], STBF, 0, buf1, sizeof buf1 / sizeof (*buf1)), + FormatFraction(TrV[2], STBF, 0, buf2, sizeof buf2 / sizeof (*buf2))); + + if (nLoopInv > 1) + fprintf(fpout, " Inversion-Flag = %d", iLoopInv); + + if (nLoopInv > 1 || nTrV > 1) + putc('\n', fpout); + + for (iList = 0; iList < SgInfo->nList; iList++, lsmx++) + { + for (i = 0; i < 9; i++) + SMx.s.R[i] = f * lsmx->s.R[i]; + + for (i = 0; i < 3; i++) + SMx.s.T[i] = iModPositive(f * lsmx->s.T[i] + TrV[i], STBF); + + fprintf(fpout, "m%d", ++iMatrix); + PrintMapleRTMx(&SMx, 1, STBF, NULL, fpout); + } + } + } + + putc('\n', fpout); +} + + +static void PutSpaceSymFile(const T_SgInfo *SgInfo, FILE *fpout) +{ + unsigned int SgID; + int iList, SuppressMx, f, i; + int nTrV, iTrV, nLoopInv, iLoopInv; + const int *TrV; + const T_RTMx *lsmx; + const T_TabSgName *tsgn; + + + tsgn = SgInfo->TabSgName; + if (tsgn && tsgn->SgLabels == NULL) tsgn = NULL; + + SgID = 0; + + if (tsgn != NULL) + SgID = SgID_Number(tsgn); + + fprintf(fpout, "%u '", SgID); + + if (tsgn != NULL) + PrintFullHM_SgName(tsgn, 0, fpout); + else if (SgInfo->HallSymbol[0]) + fprintf(fpout, "%s", SgInfo->HallSymbol); + else + fprintf(fpout, "Unknown"); + + putc('\'', fpout); + putc('\n', fpout); + + nLoopInv = Sg_nLoopInv(SgInfo); + + nTrV = SgInfo->LatticeInfo->nTrVector; + TrV = SgInfo->LatticeInfo->TrVector; + + iList = SgInfo->OrderL; + if (iList > 1) + { + iList--; + SuppressMx = 1; + } + else + SuppressMx = 0; + + fprintf(fpout, "%d\n", iList); + + for (iTrV = 0; iTrV < nTrV; iTrV++, TrV += 3) + { + for (iLoopInv = 0; iLoopInv < nLoopInv; iLoopInv++) + { + if (iLoopInv == 0) f = 1; + else f = -1; + + lsmx = SgInfo->ListSeitzMx; + + for (iList = 0; iList < SgInfo->nList; iList++, lsmx++) + { + if (SuppressMx == 0) + { + for (i = 0; i < 3; i++) + fprintf(fpout, " %12.8f %12.8f %12.8f %12.8f\n", + (double) f * lsmx->s.R[3 * i + 0], + (double) f * lsmx->s.R[3 * i + 1], + (double) f * lsmx->s.R[3 * i + 2], + (double) iModPositive(f * lsmx->s.T[i] + TrV[i], STBF) / STBF); + + putc(':', fpout); + putc('\n', fpout); + } + + SuppressMx = 0; + } + } + } +} + + +static void PutShelx(const T_SgInfo *SgInfo, FILE *fpout) +{ + int Latt_N = 0, iList; + const T_RTMx *lsmx; + const char *xyz; + + + if (SgInfo->InversionOffOrigin != 0) + fprintf(fpout, "***WARNING***: %s\n", + "Shelx manual: the origin MUST lie on a center of symmetry"); + + switch (SgInfo->LatticeInfo->Code) + { + case 'P': Latt_N = 1; break; + case 'A': Latt_N = 5; break; + case 'B': Latt_N = 6; break; + case 'C': Latt_N = 7; break; + case 'I': Latt_N = 2; break; + case 'R': + if (SgInfo->ExtraInfo == EI_Obverse) + Latt_N = 3; break; + case 'S': + case 'T': + SetSgError("Shelx supports R-obverse only"); + return; + case 'F': Latt_N = 4; break; + default: + goto ReturnError; + } + + /* N must be made negative if the structure is non-centrosymmetric + */ + if (SgInfo->Centric != -1) + Latt_N = -Latt_N; + + fprintf(fpout, "LATT %2d\n", Latt_N); + + lsmx = &SgInfo->ListSeitzMx[1]; /* skip first = identity matrix */ + + for (iList = 1; iList < SgInfo->nList; iList++, lsmx++) + { + xyz = RTMx2XYZ(lsmx, 1, STBF, 1, 1, 0, ", ", NULL, 0); + if (xyz) + fprintf(fpout, "SYMM %s\n", xyz); + else + goto ReturnError; + } + + putc('\n', fpout); + + return; + + ReturnError: + + SetSgError("Internal Error: PutShelx()"); + return; +} + + +static void PutSchakal(const T_SgInfo *SgInfo, FILE *fpout) +{ + int iList, nMx, i; + int nTrV, iTrV; + const int *TrV; + T_RTMx SMx; + const T_RTMx *lsmx; + const char *xyz; + + + if (Sg_nLoopInv(SgInfo) == 2) + fprintf(fpout, "DU -x,-y,-z\n"); + + nTrV = SgInfo->LatticeInfo->nTrVector; + TrV = SgInfo->LatticeInfo->TrVector; + + if (nTrV > 1) + { + fprintf(fpout, "DU"); + + InitRotMx(SMx.s.R, 1); + + TrV += 3; + + for (iTrV = 1; iTrV < nTrV; iTrV++, TrV += 3) + { + for (i = 0; i < 3; i++) + SMx.s.T[i] = TrV[i]; + + xyz = RTMx2XYZ(&SMx, 1, STBF, 0, 0, 1, ",", NULL, 0); + if (xyz) + { + if (iTrV > 1) + fprintf(fpout, " ;"); + + fprintf(fpout, " %s", xyz); + } + else + { + putc('\n', fpout); + goto ReturnError; + } + } + + putc('\n', fpout); + } + + nMx = 0; + + lsmx = &SgInfo->ListSeitzMx[1]; + + for (iList = 1; iList < SgInfo->nList; iList++, lsmx++) + { + xyz = RTMx2XYZ(lsmx, 1, STBF, 0, 0, 1, ",", NULL, 0); + if (xyz) + { + if (nMx % 4 == 0) + { + if (nMx) putc('\n', fpout); + fprintf(fpout, "SY %s", xyz); + } + else + fprintf(fpout, " ; %s", xyz); + } + else + { + putc('\n', fpout); + goto ReturnError; + } + + nMx++; + } + + if (nMx) + putc('\n', fpout); + + putc('\n', fpout); + + return; + + ReturnError: + + SetSgError("Internal Error: PutSchakal()"); + return; +} + + +static void Simple_hklList(T_SgInfo *SgInfo, int Maxh, int Maxk, int Maxl, + int ListSysAbsent) +{ + int h, k, l, iList, restriction, M, n, i; + int Minh, Mink, Minl; + int uvw[3]; + int CCMx_PL[9], deterCCMx_LP = 0, hP, kP, lP; + + + if (SgInfo->LatticeInfo->Code != 'P') + { + deterCCMx_LP = deterRotMx(SgInfo->CCMx_LP); + InverseRotMx(SgInfo->CCMx_LP, CCMx_PL); + + if (deterCCMx_LP < 1) + goto ReturnError; + } + + SetListMin_hkl(SgInfo, Maxk, Maxl, &Minh, &Mink, &Minl); + + fprintf(stdout, ">Begin hklList\n"); + + for (h = Minh; h <= Maxh; h++) + for (k = Mink; k <= Maxk; k++) + for (l = Minl; l <= Maxl; l++) + { + iList = IsSysAbsent_hkl(SgInfo, h, k, l, &restriction); + if (SgError != NULL) + return; + + M = BuildEq_hkl(SgInfo, NULL, h, k, l); + if (SgError != NULL) + return; + + if (iList == 0) + { + if ((iList = IsSuppressed_hkl(SgInfo, Minh, Mink, Minl, + Maxk, Maxl, + h, k, l)) != 0) + n = fprintf(stdout, "# %3d %3d %3d %3d [%d]", + h, k, l, M, iList); + else + n = fprintf(stdout, " %3d %3d %3d %3d", + h, k, l, M); + + if (restriction >= 0) + { + while (n < 27) { n++; putc(' ', stdout); } + n += fprintf(stdout, " %2d/%d", restriction, STBF); + } + + while (n < 34) { n++; putc(' ', stdout); } + if (Is_si(SgInfo, h, k, l) == 1) + n += fprintf(stdout, " s.i."); + + while (n < 41) { n++; putc(' ', stdout); } + Set_uvw(SgInfo, h, k, l, uvw); + for (i = 0; i < SgInfo->n_si_Vector; i++) + n += fprintf(stdout, " %3d", uvw[i]); + + if (SgInfo->LatticeInfo->Code != 'P') + { + hP = h * CCMx_PL[0] + k * CCMx_PL[3] + l * CCMx_PL[6]; + kP = h * CCMx_PL[1] + k * CCMx_PL[4] + l * CCMx_PL[7]; + lP = h * CCMx_PL[2] + k * CCMx_PL[5] + l * CCMx_PL[8]; + + if (hP % deterCCMx_LP || kP % deterCCMx_LP || lP % deterCCMx_LP) + goto ReturnError; + + hP /= deterCCMx_LP; + kP /= deterCCMx_LP; + lP /= deterCCMx_LP; + + while (n < 55) { n++; putc(' ', stdout); } + n += fprintf(stdout, " P %3d %3d %3d", + hP, kP, lP); + } + + putc('\n', stdout); + } + else if (ListSysAbsent) + fprintf(stdout, "# %3d %3d %3d %3d (%d)\n", + h, k, l, M, iList); + } + + fprintf(stdout, ">End hklList\n"); + + return; + + ReturnError: + + SetSgError("Internal Error: Simple_hklList()"); + return; +} + + +/* **************************************************************************** + some code for the handling of lattice constants + */ + + +#include + + +typedef struct { + double a, b, c; + double alpha, beta, gamma; + double sa, sb, sg; + double ca, cb, cg; + double v; + char calcs, calcc; + } + T_LatticeConstants; + + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_PI_2 +#define M_PI_2 1.57079632679489661923 +#endif + +#define PIover180 (M_PI / 180.) + +#define EpsPI (1.e-6) /* ARBITRARY */ + + +static double sinC(double arg) +{ + if (M_PI_2 - EpsPI <= arg && arg <= M_PI_2 + EpsPI) + return 1.; + else + return sin(arg); +} + + +static double cosC(double arg) +{ + if (M_PI_2 - EpsPI <= arg && arg <= M_PI_2 + EpsPI) + return 0.; + else + return cos(arg); +} + + +static int Lc2RLc(T_LatticeConstants *lc, T_LatticeConstants *rlc) +{ + /* Transformation Lattice Constants -> Reciprocal Lattice Constants + after Kleber, W., 17. Aufl., Verlag Technik GmbH Berlin 1990, P.352 + */ + + double D; + + + if (lc->calcs) + { lc->sa = sinC(lc->alpha); lc->sb = sinC(lc->beta); lc->sg = sinC(lc->gamma); + lc->calcs = 0; + } + + if (lc->calcc) + { lc->ca = cosC(lc->alpha); lc->cb = cosC(lc->beta); lc->cg = cosC(lc->gamma); + lc->calcc = 0; + } + + D = 1. - lc->ca * lc->ca - lc->cb * lc->cb - lc->cg * lc->cg + + 2. * lc->ca * lc->cb * lc->cg; + if (D < 0.) return -1; + + lc->v = lc->a * lc->b * lc->c * sqrt(D); + if (lc->v == 0.) return -1; + + if (lc->sa == 0. || lc->sb == 0. || lc->sg == 0.) return -1; + + if (rlc != NULL) + { + rlc->a = lc->b * lc->c * lc->sa / lc->v; + rlc->b = lc->c * lc->a * lc->sb / lc->v; + rlc->c = lc->a * lc->b * lc->sg / lc->v; + rlc->ca = (lc->cb * lc->cg - lc->ca) / (lc->sb * lc->sg); + rlc->cb = (lc->cg * lc->ca - lc->cb) / (lc->sg * lc->sa); + rlc->cg = (lc->ca * lc->cb - lc->cg) / (lc->sa * lc->sb); + rlc->alpha = acos(rlc->ca); + rlc->beta = acos(rlc->cb); + rlc->gamma = acos(rlc->cg); + rlc->sa = sinC(rlc->alpha); + rlc->sb = sinC(rlc->beta); + rlc->sg = sinC(rlc->gamma); + rlc->v = 1. / lc->v; + rlc->calcs = 0; + rlc->calcc = 0; + } + + return 0; +} + + +static void Lc2MetricalMx(T_LatticeConstants *lc, double *G) +{ + G[0] = lc->a * lc->a; + G[1] = G[3] = lc->a * lc->b * lc->cg; + G[2] = G[6] = lc->a * lc->c * lc->cb; + + G[4] = lc->b * lc->b; + G[5] = G[7] = lc->b * lc->c * lc->ca; + + G[8] = lc->c * lc->c; +} + + +static int HarmonizeSgLatCon(T_SgInfo *SgInfo, T_LatticeConstants *lc, int np) +{ + switch(SgInfo->XtalSystem) + { + case XS_Triclinic: + if (np != 6) goto IllUnitCell; + break; + case XS_Monoclinic: + if (np != 4 && np != 6) goto IllUnitCell; + switch (SgInfo->UniqueRefAxis) + { + case 'x': lc->beta = lc->gamma = 90. * PIover180; break; + case 'y': if (np != 6) lc->beta = lc->alpha; + lc->alpha = lc->gamma = 90. * PIover180; break; + case 'z': if (np != 6) lc->gamma = lc->alpha; + lc->alpha = lc->beta = 90. * PIover180; break; + default: + goto IntErr; + } + break; + case XS_Orthorhombic: + if (np != 3 && np != 6) goto IllUnitCell; + lc->alpha = lc->beta = lc->gamma = 90. * PIover180; + break; + case XS_Tetragonal: + if (np != 2 && np != 6) goto IllUnitCell; + switch (SgInfo->UniqueRefAxis) + { + case 'x': lc->c = lc->b; break; + case 'y': lc->c = lc->a; break; + case 'z': if (np != 6) lc->c = lc->b; + lc->b = lc->a; break; + default: + goto IntErr; + } + lc->alpha = lc->beta = lc->gamma = 90. * PIover180; + break; + case XS_Trigonal: + if (np != 2 && np != 6) goto IllUnitCell; + if (SgInfo->UniqueDirCode == '*') + { + if (np != 6) lc->alpha = lc->b * PIover180; + lc->c = lc->b = lc->a; + lc->gamma = lc->beta = lc->alpha; + break; + } + case XS_Hexagonal: + if (np != 2 && np != 6) goto IllUnitCell; + switch (SgInfo->UniqueRefAxis) + { + case 'x': lc->c = lc->b; + lc->alpha = 120. * PIover180; + lc->beta = lc->gamma = 90. * PIover180; break; + case 'y': lc->c = lc->a; + lc->beta = 120. * PIover180; + lc->alpha = lc->gamma = 90. * PIover180; break; + case 'z': if (np != 6) lc->c = lc->b; + lc->b = lc->a; + lc->gamma = 120. * PIover180; + lc->alpha = lc->beta = 90. * PIover180; break; + default: + goto IntErr; + } + break; + case XS_Cubic: + if (np != 1 && np != 6) goto IllUnitCell; + lc->c = lc->b = lc->a; + lc->alpha = lc->beta = lc->gamma = 90. * PIover180; + break; + default: + goto IntErr; + } + + return 0; + + IntErr: SetSgError("Internal Error: HarmonizeSgLatCon()"); + return -1; + + IllUnitCell: SetSgError("Error: Illegal UnitCell or SpaceGroup"); + return -1; +} + + +static void MxMultiply(double *ab, double *a, double *b, int ma, int na, int nb) +{ + int i, j, k; + double *ai, *aij, *bk, *bkj; + + ai = a; + + for (i = 0; i < ma; i++) + { + bk = b; + + for (k = 0; k < nb; k++) + { + aij = ai; + bkj = bk; + + *ab = 0.; + + for (j = 0; j < na; j++) + { + *ab += (*aij) * (*bkj); + + aij++; + bkj += nb; + } + + ab++; + bk++; + } + + ai += na; + } +} + + +static int TransformLatticeConstants(T_LatticeConstants *LatConA, + int np, + T_LatticeConstants *LatConB, + T_SgInfo *SgInfo, + int *InvCBMxR) +{ + int i, j; + double GA[9], GB[9], GAR[9], R[9], Rt[9]; + + + if (HarmonizeSgLatCon(SgInfo, LatConA, np) != 0) + return -1; + + LatConA->calcs = 1; + LatConA->calcc = 1; + + /* just to check LatConA and to compute sin and cos of angles + */ + if (Lc2RLc(LatConA, LatConB) != 0) { + SetSgError("Error: Illegal UnitCell"); + return -1; + } + + Lc2MetricalMx(LatConA, GA); + + for (i = 0; i < 3; i++) + for (j = 0; j < 3; j++) { + R[i * 3 + j] = InvCBMxR[i * 3 + j] / (double) CRBF; + Rt[i * 3 + j] = InvCBMxR[j * 3 + i] / (double) CRBF; + } + + MxMultiply(GAR, GA, R, 3, 3, 3); + MxMultiply(GB, Rt, GAR, 3, 3, 3); + + if (GB[0] < 0. || GB[4] < 0. || GB[8] < 0.) + goto ReturnError; + + LatConB->a = sqrt(GB[0]); + LatConB->b = sqrt(GB[4]); + LatConB->c = sqrt(GB[8]); + + LatConB->alpha = GB[5] / LatConB->b / LatConB->c; + LatConB->beta = GB[2] / LatConB->c / LatConB->a; + LatConB->gamma = GB[1] / LatConB->a / LatConB->b; + + if ( LatConB->alpha < -1. || LatConB->alpha > 1. + || LatConB->beta < -1. || LatConB->beta > 1. + || LatConB->gamma < -1. || LatConB->gamma > 1.) + goto ReturnError; + + LatConB->alpha = acos(LatConB->alpha); + LatConB->beta = acos(LatConB->beta ); + LatConB->gamma = acos(LatConB->gamma); + + LatConB->calcs = 1; + LatConB->calcc = 1; + + return 0; + + ReturnError: + + SetSgError("InternalError: Corrupt InvCBMxR"); + return -1; +} + + +/* **************************************************************************** + */ + + +static void usage(void) +{ + static const char *quick_help[] = + { + "-Hall|VolA|VolI select conventions", + "-ListTable[=#] print [parts of] internal table", + "-CIF print internal table in CIF format", + "-XYZ print something like \"-x, y+1/2, z\"", + "-AllXYZ print all symmetry operations", + "-Maple print symmetry matrices in Maple format", + "-Space print symmetry file for AVS SpaceModule", + "-Shelx print Shelx LATT & SYMM cards", + "-Schakal print Schakal DU & SY cards", + "-hklList print simple hkl listing", + "-Standard compute transformation to \"standard\" setting", + "-UnitCell=\"a..g\" unit cell constants a, b, c, alpha, beta, gamma", + "-v be more verbose", + "-Verify debug option: verify transformations", + "-ClearError debug option: clear errors and continue", + NULL + }; + + const char **qh; + + + fprintf(stderr, + "usage: %s [options] [SpaceGroupName_or_# [SpaceGroupName_or_#]]\n", + progn); + + for (qh = quick_help; *qh; qh++) + fprintf(stderr, " %s\n", *qh); + + putc('\n', stderr); + + fprintf(stderr, "examples: %s 68\n", progn); + fprintf(stderr, " %s C2/m:c2 -XYZ\n", progn); + fprintf(stderr, " %s \"Oh^3\" -Shelx\n", progn); + fprintf(stderr, " %s -Hall \"-F 4y 2\" -Standard\n", progn); + fprintf(stderr, " %s -VolI 15 -VolA 15\n", progn); + fprintf(stderr, " %s -ListTable=68\n", progn); + + exit(1); +} + + +static void ShowCBMx(T_RTMx *CBMx, T_RTMx *InvCBMx, int F_Maple) +{ + if (F_Maple) { + PrintMapleRTMx( CBMx, CRBF, CTBF, " CBMx", stdout); + PrintMapleRTMx(InvCBMx, CRBF, CTBF, "InvCBMx", stdout); + } + else { + fprintf(stdout, " CBMx = %s\n", + RTMx2XYZ( CBMx, CRBF, CTBF, 0, 0, 1, ", ", NULL, 0)); + fprintf(stdout, "InvCBMx = %s\n", + RTMx2XYZ(InvCBMx, CRBF, CTBF, 0, 0, 1, ", ", NULL, 0)); + } +} + + +typedef struct + { + int Convention; + const char *SgName; + const T_TabSgName *InpTSgN; + const T_TabSgName *RefTSgN; + T_RTMx CBMx, InvCBMx; + } + T_SgList; + + +int main(int argc, char *argv[]) +{ + int i, n, HaveSpace, pos_hsym; + int F_Convention, Last_F_Convention; + int F_ListTable, F_CIF; + int F_XYZ, F_AllXYZ, F_Maple; + int F_Space, F_Shelx, F_Schakal; + int F_hklList; + int F_Standard, F_UnitCell; + int F_Verbose, F_Verify, F_ClearError; + T_LatticeConstants LatConA, LatConB; + char *cp, xtrac; + const char *SgName; + const T_TabSgName *tsgn; + T_SgInfo SpgrInfo[2], BC_SgInfo, *SgInfo; + int nSgList, iSgList; + T_SgList SgList[2]; + T_RTMx *CBMx, *InvCBMx; + T_RTMx CCBMx, CInvCBMx; + + +/* + Macintosh extras (Courtesy Jon Tischler ) + */ +#ifdef __THINK__ + console_options.nrows = CONSOLE_LINES; + console_options.ncols = CONSOLE_COLUMNS; + console_options.title = "\psgInfo version 1.0.1"; +#endif +#ifdef __MWERKS__ + SIOUXSettings.autocloseonquit = FALSE; + SIOUXSettings.asktosaveonclose = TRUE; + SIOUXSettings.columns = CONSOLE_COLUMNS; + SIOUXSettings.rows = CONSOLE_LINES; +#endif +#if defined(__THINK__) || defined(__MWERKS__) + argc = ccommand(&argv); +#endif + + + nSgList = 0; + + F_Convention = 'A'; Last_F_Convention = 0; + F_ListTable = 0; + F_CIF = 0; + F_XYZ = 0; + F_AllXYZ = 0; + F_Maple = 0; + F_Space = 0; + F_Shelx = 0; + F_Schakal = 0; + F_hklList = 0; + F_Standard = 0; + F_UnitCell = 0; + F_Verbose = 0; + F_Verify = 0; + F_ClearError = 0; + + for (i = 1; i < argc; i++) + { + if (str_icmp(argv[i], "-Hall") == 0) { + F_Convention = 'H'; + Last_F_Convention = 0; + } + else if (str_icmp(argv[i], "-VolA") == 0) { + F_Convention = 'A'; + Last_F_Convention = 'A'; + } + else if ( str_icmp(argv[i], "-VolI") == 0 + || str_icmp(argv[i], "-Vol1") == 0) { + F_Convention = 'I'; + Last_F_Convention = 'I'; + } + else if (str_ibegin(argv[i], "-ListTable") == 0) + { + cp = argv[i] + 10; + if (*cp == '\0') + F_ListTable = -1; + else if (*cp++ == '=') + { + n = sscanf(cp, "%d%c", &F_ListTable, &xtrac); + if (n != 1 || F_ListTable < 1 + || F_ListTable > 230) usage(); + } + else + usage(); + } + else if (str_icmp(argv[i], "-CIF") == 0) + F_CIF = 1; + + else if (str_icmp(argv[i], "-XYZ") == 0) + F_XYZ = 1; + + else if (str_icmp(argv[i], "-AllXYZ") == 0) + F_AllXYZ = 1; + + else if (str_icmp(argv[i], "-Maple") == 0) + F_Maple = 1; + + else if (str_icmp(argv[i], "-Space") == 0) + F_Space = 1; + + else if (str_icmp(argv[i], "-Shelx") == 0) + F_Shelx = 1; + + else if (str_icmp(argv[i], "-Schakal") == 0) + F_Schakal = 1; + + else if (str_icmp(argv[i], "-hklList") == 0) + F_hklList = 1; + + else if (str_icmp(argv[i], "-Standard") == 0) + F_Standard = 1; + + else if (str_ibegin(argv[i], "-UnitCell=") == 0) + { + F_UnitCell = sscanf(&argv[i][10], "%lf%lf%lf%lf%lf%lf", + &LatConA.a, &LatConA.b, &LatConA.c, + &LatConA.alpha, &LatConA.beta, &LatConA.gamma); + + if (F_UnitCell < 1) + usage(); + + if (F_UnitCell > 3) LatConA.alpha *= PIover180; + if (F_UnitCell > 4) LatConA.beta *= PIover180; + if (F_UnitCell > 5) LatConA.gamma *= PIover180; + } + else if (str_icmp(argv[i], "-v") == 0) + F_Verbose = 1; + + else if (str_icmp(argv[i], "-Verify") == 0) + F_Verify = 1; + + else if (str_icmp(argv[i], "-ClearError") == 0) + F_ClearError = 1; + + else if (nSgList < 2) + { + SgName = argv[i]; + + while (*SgName == ' ' || *SgName == '\t') SgName++; + + if (F_Convention == 'H' && isdigit(*SgName)) + SgList[nSgList].Convention = 'A'; + else + SgList[nSgList].Convention = F_Convention; + + SgList[nSgList].SgName = SgName; + SgList[nSgList].InpTSgN = NULL; + SgList[nSgList].RefTSgN = NULL; + + nSgList++; + } + else + usage(); + } + + if (F_ListTable) + { + ListTabSgName(F_ListTable, Last_F_Convention, stdout); + PrintClearSgError(1, 0); + putc('\n', stdout); + } + + if (F_CIF) + { + ListCIF(stdout); + PrintClearSgError(1, 0); + putc('\n', stdout); + } + + if (nSgList == 0) + { + if (F_ListTable == 0 && F_CIF == 0) + usage(); + else + exit(0); + } + + if (F_Space == 0) + { + putc('#', stdout); + + for (i = 0; i < argc; i++) + { + putc(' ', stdout); + + HaveSpace = 0; + + if (i) { + for (n = 0; argv[i][n]; n++) { + if (isspace(argv[i][n])) { + HaveSpace = 1; + break; + } + } + } + + if (HaveSpace == 0) + fprintf(stdout, "%s", argv[i]); + else + { + putc('"', stdout); + + for (n = 0; argv[i][n]; n++) + if (argv[i][n] == '"') putc('+', stdout); + else putc(argv[i][n], stdout); + + putc('"', stdout); + } + } + + putc('\n', stdout); + } + + BC_SgInfo.MaxList = 0; + BC_SgInfo.ListSeitzMx = NULL; + BC_SgInfo.ListRotMxInfo = NULL; + + for (iSgList = 0; iSgList < nSgList; iSgList++) + { + if (iSgList) putc('\n', stdout); + + if (nSgList > 1 || F_Standard) + fprintf(stdout, "Setting %c:\n\n", "AB"[iSgList]); + + SgInfo = &SpgrInfo[iSgList]; + + SgInfo->MaxList = 192; + + SgInfo->ListSeitzMx + = malloc(SgInfo->MaxList * sizeof (*SgInfo->ListSeitzMx)); + if (SgInfo->ListSeitzMx == NULL) NotEnoughCore(); + +#ifndef No_ListRotMxInfo + SgInfo->ListRotMxInfo + = malloc(SgInfo->MaxList * sizeof (*SgInfo->ListRotMxInfo)); + if (SgInfo->ListRotMxInfo == NULL) NotEnoughCore(); +#else + SgInfo->ListRotMxInfo = NULL; +#endif + + F_Convention = SgList[iSgList].Convention; + SgName = SgList[iSgList].SgName; + + tsgn = NULL; + + if (F_Convention == 'A' || F_Convention == 'I') + { + tsgn = FindTabSgNameEntry(SgName, F_Convention); + if (tsgn == NULL) + { + PrintClearSgError(1, 0); + progerror("Error: Unknown Space Group Symbol"); + } + + if (F_Space == 0) + { + fprintf(stdout, "Space Group "); + PrintTabSgNameEntry(tsgn, 0, 0, stdout); + putc('\n', stdout); + } + + SgName = tsgn->HallSymbol; + } + + SgList[iSgList].InpTSgN = tsgn; + + InitSgInfo(SgInfo); + + SgInfo->TabSgName = tsgn; + if (tsgn) SgInfo->GenOption = 1; + + pos_hsym = ParseHallSymbol(SgName, SgInfo); + + if (SgError != NULL) + { + fprintf(stdout, " %s\n", SgName); + for (i = 0; i < pos_hsym; i++) putc('-', stdout); + fprintf(stdout, "---^\n"); + fprintf(stdout, "%s\n", SgError); + exit(1); + } + + if (CompleteSgInfo(SgInfo) != 0) + PrintClearSgError(F_ClearError, 1); + + if (tsgn == NULL && F_Space == 0) + { + if (SgInfo->TabSgName) + { + fprintf(stdout, "Space Group "); + PrintTabSgNameEntry(SgInfo->TabSgName, 0, 0, stdout); + putc('\n', stdout); + } + else + fprintf(stdout, "Hall Symbol %s\n", SgInfo->HallSymbol); + } + + PrintClearSgError(F_ClearError, 0); + +#if USE_GS_SI + if (Try_GS_si(SgInfo) < 0) +#else + if (Set_si(SgInfo) < 0) +#endif + PrintClearSgError(F_ClearError, 1); + + if (F_Space == 0) { + ListSgInfo(SgInfo, F_XYZ, F_Verbose, stdout); + PrintClearSgError(F_ClearError, 0); + } + + if (F_AllXYZ) { + PutAllXYZ(SgInfo, stdout); + PrintClearSgError(F_ClearError, 0); + } + + if (F_Maple) { + PutMaple(SgInfo, stdout); + PrintClearSgError(F_ClearError, 0); + } + + if (F_Space) { + PutSpaceSymFile(SgInfo, stdout); + PrintClearSgError(F_ClearError, 0); + } + + if (F_Shelx) { + PutShelx(SgInfo, stdout); + PrintClearSgError(F_ClearError, 0); + } + + if (F_Schakal) { + PutSchakal(SgInfo, stdout); + PrintClearSgError(F_ClearError, 0); + } + + if (F_hklList) { + Simple_hklList(SgInfo, 4, 4, 4, F_Verbose); + PrintClearSgError(F_ClearError, 0); + } + + if (nSgList > 1 || F_Standard) + { + CBMx = &SgList[iSgList].CBMx; + InvCBMx = &SgList[iSgList].InvCBMx; + + SgList[iSgList].RefTSgN = FindReferenceSpaceGroup(SgInfo, + CBMx, InvCBMx); + PrintClearSgError(F_ClearError, 0); + + if (SgList[iSgList].RefTSgN) + { + if (F_Verbose || F_Verify) + { + fprintf(stdout, "Change of Basis => Reference Setting "); + PrintTabSgNameEntry(SgList[iSgList].RefTSgN, 0, 0, stdout); + putc('\n', stdout); + + ShowCBMx(CBMx, InvCBMx, F_Maple); + PrintClearSgError(F_ClearError, 0); + } + + if (F_Verify) + { + if (BC_SgInfo.MaxList == 0) + { + BC_SgInfo.MaxList = 192; + + BC_SgInfo.ListSeitzMx + = malloc(BC_SgInfo.MaxList * sizeof (*BC_SgInfo.ListSeitzMx)); + if (BC_SgInfo.ListSeitzMx == NULL) NotEnoughCore(); + + BC_SgInfo.ListRotMxInfo + = malloc(BC_SgInfo.MaxList * sizeof (*BC_SgInfo.ListRotMxInfo)); + if (BC_SgInfo.ListRotMxInfo == NULL) NotEnoughCore(); + } + + InitSgInfo(&BC_SgInfo); + + if (TransformSgInfo(SgInfo, CBMx, InvCBMx, &BC_SgInfo) == 0) + CompleteSgInfo(&BC_SgInfo); + + if (SgError) + { + PrintClearSgError(F_ClearError, 0); + SgList[iSgList].RefTSgN = NULL; + } + else if (BC_SgInfo.TabSgName != SgList[iSgList].RefTSgN) + { + fprintf(stdout, "Hall Symbol %s\n", BC_SgInfo.HallSymbol); + SetSgError("Verify Error: Wrong CBMx/InvCBMx"); + PrintClearSgError(F_ClearError, 0); + SgList[iSgList].RefTSgN = NULL; + } + else + fprintf(stdout, "Verify O.K.\n\n"); + } + } + + tsgn = SgList[iSgList].RefTSgN; + if (tsgn && F_Standard && nSgList == 1) + { + if (Last_F_Convention == 'A' || Last_F_Convention == 'I') + SgList[nSgList].Convention = Last_F_Convention; + else + SgList[nSgList].Convention = 'A'; + + SgList[nSgList].SgName = SchoenfliesSymbols[tsgn->SgNumber]; + SgList[nSgList].InpTSgN = NULL; + SgList[nSgList].RefTSgN = NULL; + + nSgList++; + } + } + } + + if ( nSgList == 2 + && SgList[0].RefTSgN && SgList[1].RefTSgN + && SgList[0].RefTSgN->SgNumber == SgList[1].RefTSgN->SgNumber) + { + putc('\n', stdout); + fprintf(stdout, "Change of Basis Setting A -> Setting B:\n"); + + RTMxMultiply( &CCBMx, &SgList[1].InvCBMx, &SgList[0].CBMx, + CRBF, CRBF * CTBF); + RTMxMultiply(&CInvCBMx, &SgList[0].InvCBMx, &SgList[1].CBMx, + CRBF, CRBF * CTBF); + + for (i = 0; i < 12; i++) + { + if ( CCBMx.a[i] % CRBF) break; + if (CInvCBMx.a[i] % CRBF) break; + + CCBMx.a[i] /= CRBF; + CInvCBMx.a[i] /= CRBF; + } + + if (i < 12) + { + SetSgError("Internal Error: Can't combine CBMx's"); + PrintClearSgError(1, 1); + } + else + { + ShowCBMx(&CCBMx, &CInvCBMx, F_Maple); + PrintClearSgError(F_ClearError, 0); + + if (F_Verify) + { + InitSgInfo(&BC_SgInfo); + + if (TransformSgInfo(&SpgrInfo[0], &CCBMx, &CInvCBMx, &BC_SgInfo) == 0) + CompleteSgInfo(&BC_SgInfo); + + if (SgError) + PrintClearSgError(F_ClearError, 1); + + else if (strcmp(SpgrInfo[1].HallSymbol, BC_SgInfo.HallSymbol) != 0) + { + fprintf(stdout, "Hall Symbol %s\n", SpgrInfo[1].HallSymbol); + fprintf(stdout, "Hall Symbol %s\n", BC_SgInfo.HallSymbol); + SetSgError("Verify Error: Wrong CBMx/InvCBMx"); + PrintClearSgError(F_ClearError, 1); + } + else + fprintf(stdout, "Verify O.K.\n"); + } + + if (F_UnitCell) + { + putc('\n', stdout); + + if (TransformLatticeConstants(&LatConA, F_UnitCell, + &LatConB, &SpgrInfo[0], + CInvCBMx.s.R) != 0) + PrintClearSgError(0, 1); + + fprintf(stdout, + "Setting A UnitCell %.6g %.6g %.6g %.6g %.6g %.6g\n", + LatConA.a, LatConA.b, LatConA.c, + LatConA.alpha / PIover180, + LatConA.beta / PIover180, + LatConA.gamma / PIover180); + + fprintf(stdout, + "Setting B UnitCell %.6g %.6g %.6g %.6g %.6g %.6g\n", + LatConB.a, LatConB.b, LatConB.c, + LatConB.alpha / PIover180, + LatConB.beta / PIover180, + LatConB.gamma / PIover180); + } + } + + putc('\n', stdout); + } + + exit(0); /* old VAX didn't like "return 0;" */ + return 0; +} diff --git a/sginfo.h b/sginfo.h new file mode 100644 index 00000000..7266458c --- /dev/null +++ b/sginfo.h @@ -0,0 +1,1789 @@ +/* + Space Group Info's (c) 1994-96 Ralf W. Grosse-Kunstleve + */ + +#ifndef SGINFO_H__ +#define SGINFO_H__ + + +#ifndef SGCLIB_C__ +extern +const char *SgError; +#ifdef SGCOREDEF__ +extern +char SgErrorBuffer[128]; +#endif +#else +const char *SgError = NULL; +char SgErrorBuffer[128]; +#endif + + +#define STBF 12 /* Seitz Matrix Translation Base Factor */ + +#define CRBF 12 /* Change of Basis Matrix Rotation Base Factor */ +#define CTBF 72 /* Change of Basis Matrix Translation Base Factor */ + +/* CAUTION: (CTBF / STBF) has to be an INTEGER */ + + +typedef struct + { + int Code; + int nTrVector; + int *TrVector; + } + T_LatticeInfo; + + +typedef union + { + struct { int R[9], T[3]; } s; + int a[12]; + } + T_RTMx; + + +typedef struct + { + int EigenVector[3]; + int Order; + int Inverse; + int RefAxis; + int DirCode; + } + T_RotMxInfo; + + +typedef struct + { + const char *HallSymbol; + int SgNumber; + const char *Extension; + const char *SgLabels; + } + T_TabSgName; + + +#define MaxLenHallSymbol 39 + + +typedef struct + { + int GenOption; + int Centric; + int InversionOffOrigin; + const T_LatticeInfo *LatticeInfo; + int StatusLatticeTr; + int OriginShift[3]; + int nList; + int MaxList; + T_RTMx *ListSeitzMx; + T_RotMxInfo *ListRotMxInfo; + int OrderL; + int OrderP; + int XtalSystem; + int UniqueRefAxis; + int UniqueDirCode; + int ExtraInfo; + int PointGroup; + int nGenerator; + int Generator_iList[4]; + char HallSymbol[MaxLenHallSymbol + 1]; + const T_TabSgName *TabSgName; + const int *CCMx_LP; + int n_si_Vector; + int si_Vector[9]; + int si_Modulus[3]; + } + T_SgInfo; + +/* T_Sginfo.GenOption: 0 = full group generation + 1 = trusted: + set Centric/InversionOffOrigin/LatticeInfo only + -1 = no group generation + + T_Sginfo.Centric: 0 = acentric + 1 = inversion in list + -1 = inversion removed from list + + T_Sginfo.StatusLatticeTr: 0 = removed from list + 1 = all translation vectors in list + -1 = some translation vectors could be + missing in list + */ + + +typedef struct + { + int M; /* Multiplicity */ + int N; /* Number of equivalent hkl to follow */ + int h[24]; /* If hkl == 000 M = N = 1 */ + int k[24]; /* If hkl != 000 M = 2 * N */ + int l[24]; /* List of hkl does not contain friedel mates */ + int TH[24]; /* Phase shift relative to h[0], k[0], l[0] */ + } + T_Eq_hkl; + + +#define EI_Unknown 0 +#define EI_Enantiomorphic 1 +#define EI_Obverse 2 +#define EI_Reverse 3 + +#ifndef SGCLIB_C__ +extern +const char *EI_Name[]; +#else +const char *EI_Name[] = + { + "Unknown", + "Enantiomorphic", + "Obverse", + "Reverse" + }; +#endif + + +#define XS_Unknown 0 +#define XS_Triclinic 1 +#define XS_Monoclinic 2 +#define XS_Orthorhombic 3 +#define XS_Tetragonal 4 +#define XS_Trigonal 5 +#define XS_Hexagonal 6 +#define XS_Cubic 7 + +#ifndef SGCLIB_C__ +extern +const char *XS_Name[]; +#else +const char *XS_Name[] = + { + "Unknown", + "Triclinic", + "Monoclinic", + "Orthorhombic", + "Tetragonal", + "Trigonal", + "Hexagonal", + "Cubic" + }; +#endif + + +#define Make_PG_Code( i, p, l) (((i) * 33 + (p)) * 12 + (l)) +#define PG_Unknown Make_PG_Code( 0, 0, 0) +#define PG_1 Make_PG_Code( 1, 1, 1) +#define PG_1b Make_PG_Code( 2, 2, 1) +#define PG_2 Make_PG_Code( 3, 3, 2) +#define PG_m Make_PG_Code( 4, 4, 2) +#define PG_2_m Make_PG_Code( 5, 5, 2) +#define PG_222 Make_PG_Code( 6, 6, 3) +#define PG_mm2 Make_PG_Code( 7, 7, 3) +#define PG_mmm Make_PG_Code( 8, 8, 3) +#define PG_4 Make_PG_Code( 9, 9, 4) +#define PG_4b Make_PG_Code(10, 10, 4) +#define PG_4_m Make_PG_Code(11, 11, 4) +#define PG_422 Make_PG_Code(12, 12, 5) +#define PG_4mm Make_PG_Code(13, 13, 5) +#define PG_4b2m Make_PG_Code(14, 14, 5) +#define PG_4bm2 Make_PG_Code(15, 14, 5) +#define PG_4_mmm Make_PG_Code(16, 15, 5) +#define PG_3 Make_PG_Code(17, 16, 6) +#define PG_3b Make_PG_Code(18, 17, 6) +#define PG_321 Make_PG_Code(19, 18, 7) +#define PG_312 Make_PG_Code(20, 18, 7) +#define PG_32 Make_PG_Code(21, 18, 7) +#define PG_3m1 Make_PG_Code(22, 19, 7) +#define PG_31m Make_PG_Code(23, 19, 7) +#define PG_3m Make_PG_Code(24, 19, 7) +#define PG_3bm1 Make_PG_Code(25, 20, 7) +#define PG_3b1m Make_PG_Code(26, 20, 7) +#define PG_3bm Make_PG_Code(27, 20, 7) +#define PG_6 Make_PG_Code(28, 21, 8) +#define PG_6b Make_PG_Code(29, 22, 8) +#define PG_6_m Make_PG_Code(30, 23, 8) +#define PG_622 Make_PG_Code(31, 24, 9) +#define PG_6mm Make_PG_Code(32, 25, 9) +#define PG_6bm2 Make_PG_Code(33, 26, 9) +#define PG_6b2m Make_PG_Code(34, 26, 9) +#define PG_6_mmm Make_PG_Code(35, 27, 9) +#define PG_23 Make_PG_Code(36, 28, 10) +#define PG_m3b Make_PG_Code(37, 29, 10) +#define PG_432 Make_PG_Code(38, 30, 11) +#define PG_4b3m Make_PG_Code(39, 31, 11) +#define PG_m3bm Make_PG_Code(40, 32, 11) + +#define PG_Index(PG_Code) ((PG_Code) / (33 * 12)) +#define PG_Number(PG_Code) (((PG_Code) / 12) % 33) +#define LG_Number(PG_Code) ((PG_Code) % (33 * 12)) + +#ifndef SGCLIB_C__ +extern +const int LG_Code_of_PG_Index[]; +#else +const int LG_Code_of_PG_Index[] = + { + PG_Unknown, + PG_1b, + PG_1b, + PG_2_m, + PG_2_m, + PG_2_m, + PG_mmm, + PG_mmm, + PG_mmm, + PG_4_m, + PG_4_m, + PG_4_m, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_3b, + PG_3b, + PG_3bm1, + PG_3b1m, + PG_3bm, + PG_3bm1, + PG_3b1m, + PG_3bm, + PG_3bm1, + PG_3b1m, + PG_3bm, + PG_6_m, + PG_6_m, + PG_6_m, + PG_6_mmm, + PG_6_mmm, + PG_6_mmm, + PG_6_mmm, + PG_6_mmm, + PG_m3b, + PG_m3b, + PG_m3bm, + PG_m3bm, + PG_m3bm + }; +#endif /* SGCLIB_C__ */ + +#ifndef SGCLIB_C__ +extern +const char *PG_Names[]; +#else +const char *PG_Names[] = + { + "Unknown", + "1", + "-1", + "2", + "m", + "2/m", + "222", + "mm2", + "mmm", + "4", + "-4", + "4/m", + "422", + "4mm", + "-42m", + "-4m2", + "4/mmm", + "3", + "-3", + "321", + "312", + "32", + "3m1", + "31m", + "3m", + "-3m1", + "-31m", + "-3m", + "6", + "-6", + "6/m", + "622", + "6mm", + "-6m2", + "-62m", + "6/mmm", + "23", + "m-3", + "432", + "-43m", + "m-3m" + }; +#endif /* SGCLIB_C__ */ + + +#ifndef SGCLIB_C__ +#ifdef SGCOREDEF__ +extern const T_LatticeInfo LI_P[]; +extern const T_LatticeInfo LI_A[]; +extern const T_LatticeInfo LI_B[]; +extern const T_LatticeInfo LI_C[]; +extern const T_LatticeInfo LI_I[]; +extern const T_LatticeInfo LI_R[]; +extern const T_LatticeInfo LI_S[]; +extern const T_LatticeInfo LI_T[]; +extern const T_LatticeInfo LI_F[]; +#endif +#else +#define T(i) ((i) * (STBF / 12)) +static int LTr_P[] = { T(0), T(0), T(0) + }; +const T_LatticeInfo LI_P[] = {{ 'P', 1, LTr_P + }}; +static int LTr_A[] = { T(0), T(0), T(0), + T(0), T(6), T(6) + }; +const T_LatticeInfo LI_A[] = {{ 'A', 2, LTr_A + }}; +static int LTr_B[] = { T(0), T(0), T(0), + T(6), T(0), T(6) + }; +const T_LatticeInfo LI_B[] = {{ 'B', 2, LTr_B + }}; +static int LTr_C[] = { T(0), T(0), T(0), + T(6), T(6), T(0) + }; +const T_LatticeInfo LI_C[] = {{ 'C', 2, LTr_C + }}; +static int LTr_I[] = { T(0), T(0), T(0), + T(6), T(6), T(6) + }; +const T_LatticeInfo LI_I[] = {{ 'I', 2, LTr_I + }}; +static int LTr_R[] = { T(0), T(0), T(0), + T(8), T(4), T(4), + T(4), T(8), T(8) + }; +const T_LatticeInfo LI_R[] = {{ 'R', 3, LTr_R + }}; +static int LTr_S[] = { T(0), T(0), T(0), + T(4), T(4), T(8), + T(8), T(8), T(4) + }; +const T_LatticeInfo LI_S[] = {{ 'S', 3, LTr_S + }}; +static int LTr_T[] = { T(0), T(0), T(0), + T(4), T(8), T(4), + T(8), T(4), T(8) + }; +const T_LatticeInfo LI_T[] = {{ 'T', 3, LTr_T + }}; +static int LTr_F[] = { T(0), T(0), T(0), + T(0), T(6), T(6), + T(6), T(0), T(6), + T(6), T(6), T(0) + }; +const T_LatticeInfo LI_F[] = {{ 'F', 4, LTr_F + }}; +#undef T +#endif /* SGCLIB_C__ */ + +/* + lattice code + R S T + unique axis + 3z obv - rev + 3y rev obv - + 3x - rev obv + */ + + +#ifndef SGCLIB_C__ +#ifdef SGCOREDEF__ +extern +const int CCMx_PP[]; +extern +const int CCMx_AP[]; +extern +const int CCMx_BP[]; +extern +const int CCMx_CP[]; +extern +const int CCMx_IP[]; +extern +const int CCMx_RP_z[]; +extern +const int CCMx_SP_y[]; +extern +const int CCMx_TP_x[]; +extern +const int CCMx_TP_z[]; +extern +const int CCMx_RP_y[]; +extern +const int CCMx_SP_x[]; +extern +const int CCMx_FI_z[]; +extern +const int CCMx_FI_y[]; +extern +const int CCMx_FI_x[]; +extern +const int CCMx_FP[]; +#endif +#else +const int CCMx_PP[] = { 1, 0, 0, /* Change of Basis Matrices */ + 0, 1, 0, /* (coordinate transformations) */ + 0, 0, 1 + }; +const int CCMx_AP[] = { -1, 0, 0, + 0, -1, 1, + 0, 1, 1 + }; +const int CCMx_BP[] = { -1, 0, 1, + 0, -1, 0, + 1, 0, 1 + }; +const int CCMx_CP[] = { 1, 1, 0, + 1, -1, 0, + 0, 0, -1 + }; +const int CCMx_IP[] = { 0, 1, 1, + 1, 0, 1, + 1, 1, 0 + }; +const int CCMx_RP_z[] = { 1, 0, 1, + -1, 1, 1, + 0, -1, 1 + }; +const int CCMx_SP_y[] = { 1, 1, -1, + -1, 1, 0, + 0, 1, 1 + }; +const int CCMx_TP_x[] = { 1, 0, -1, + 1, 1, 0, + 1, -1, 1 + }; +const int CCMx_TP_z[] = { -1, 0, 1, + 1, -1, 1, + 0, 1, 1 + }; +const int CCMx_RP_y[] = { -1, 1, 1, + 1, 1, 0, + 0, 1, -1 + }; +const int CCMx_SP_x[] = { 1, 0, 1, + 1, -1, 0, + 1, 1, -1 + }; +const int CCMx_FI_z[] = { 1, 1, 0, + -1, 1, 0, + 0, 0, 1 + }; +const int CCMx_FI_y[] = { 1, 0, -1, + 0, 1, 0, + 1, 0, 1 + }; +const int CCMx_FI_x[] = { 1, 0, 0, + 0, 1, 1, + 0, -1, 1 + }; +const int CCMx_FP[] = { -1, 1, 1, + 1, -1, 1, + 1, 1, -1 + }; +#endif /* SGCLIB_C__ */ + + +#if defined(SGCLIB_C__) || defined(SGCOREDEF__) +typedef struct + { + int Order; + int EigenVector[3]; + int DirCode; + int RMx[9]; + } + T_TabXtalRotMx; +#endif + + +#ifndef SGCLIB_C__ +#ifdef SGCOREDEF__ +extern +const T_TabXtalRotMx TabXtalRotMx[]; +#endif +#else +const T_TabXtalRotMx TabXtalRotMx[] = + { + /* # EigenVector DirCode */ + + { /* [ 0] */ 1, { 0, 0, 0 }, '.', /* CAUTION: */ + { 1, 0, 0, /* Reorganizing this table */ + 0, 1, 0, /* affects RMx_????? below. */ + 0, 0, 1 } + }, + { /* [ 1] */ 2, { 0, 0, 1 }, '=', + {-1, 0, 0, + 0, -1, 0, + 0, 0, 1 } + }, + { /* [ 2] */ 2, { 1, 0, 0 }, '=', /* hexagonal */ + { 1, -1, 0, + 0, -1, 0, + 0, 0, -1 } + }, + { /* [ 3] */ 2, { 0, 1, 0 }, '=', /* hexagonal */ + {-1, 0, 0, + -1, 1, 0, + 0, 0, -1 } + }, + { /* [ 4] */ 2, { 1, 1, 0 }, '"', + { 0, 1, 0, + 1, 0, 0, + 0, 0, -1 } + }, + { /* [ 5] */ 2, { 1, -1, 0 }, '\'', + { 0, -1, 0, + -1, 0, 0, + 0, 0, -1 } + }, + { /* [ 6] */ 2, { 2, 1, 0 }, '|', /* hexagonal */ + { 1, 0, 0, + 1, -1, 0, + 0, 0, -1 } + }, + { /* [ 7] */ 2, { 1, 2, 0 }, '\\', /* hexagonal */ + {-1, 1, 0, + 0, 1, 0, + 0, 0, -1 } + }, + { /* [ 8] */ 3, { 0, 0, 1 }, '=', + { 0, -1, 0, + 1, -1, 0, + 0, 0, 1 } + }, + { /* [ 9] */ 3, { 1, 1, 1 }, '*', + { 0, 0, 1, + 1, 0, 0, + 0, 1, 0 } + }, + { /* [10] */ 4, { 0, 0, 1 }, '=', + { 0, -1, 0, + 1, 0, 0, + 0, 0, 1 } + }, + { /* [11] */ 6, { 0, 0, 1 }, '=', + { 1, -1, 0, + 1, 0, 0, + 0, 0, 1 } + }, + { 0, { 0, 0, 0 }, 0, + { 0, 0, 0, + 0, 0, 0, + 0, 0, 0 } + } + }; +#endif /* SGCLIB_C__ */ + + +#ifndef SGCLIB_C__ +#ifdef SGCOREDEF__ +extern +const int *RMx_1_000; +extern +const int *RMx_2_001; +extern +const int *RMx_2_110; +extern +const int *RMx_3_001; +extern +const int *RMx_3_111; +extern +const int RMx_3i111[]; +extern +const int *RMx_4_001; +extern +const int RMx_4i001[]; +#endif +#else +const int *RMx_1_000 = TabXtalRotMx[ 0].RMx; +const int *RMx_2_001 = TabXtalRotMx[ 1].RMx; +const int *RMx_2_110 = TabXtalRotMx[ 4].RMx; +const int *RMx_3_001 = TabXtalRotMx[ 8].RMx; +const int *RMx_3_111 = TabXtalRotMx[ 9].RMx; +const int RMx_3i111[] = + { + 0, 1, 0, + 0, 0, 1, + 1, 0, 0 + }; +const int *RMx_4_001 = TabXtalRotMx[10].RMx; +const int RMx_4i001[] = + { + 0, 1, 0, + -1, 0, 0, + 0, 0, 1 + }; +#endif /* SGCLIB_C__ */ + + +#ifndef SGCLIB_C__ +#ifdef SGCOREDEF__ +extern +const int HallTranslations[]; +#endif +#else +#define T(i) ((i) * (STBF / 12)) +const int HallTranslations[] = + { + 'n', T(6), T(6), T(6), + 'a', T(6), T(0), T(0), + 'b', T(0), T(6), T(0), + 'c', T(0), T(0), T(6), + 'd', T(3), T(3), T(3), + 'u', T(3), T(0), T(0), + 'v', T(0), T(3), T(0), + 'w', T(0), T(0), T(3), + 0 + }; +#undef T +#endif + + +#ifndef SGCLIB_C__ +#ifdef SGCOREDEF__ +extern +const int VolAPointGroups[]; +#endif +#else +const int VolAPointGroups[] = + { + PG_Unknown, + PG_1, + PG_1b, + PG_2, + PG_2, + PG_2, + PG_m, + PG_m, + PG_m, + PG_m, + PG_2_m, + PG_2_m, + PG_2_m, + PG_2_m, + PG_2_m, + PG_2_m, + PG_222, + PG_222, + PG_222, + PG_222, + PG_222, + PG_222, + PG_222, + PG_222, + PG_222, + PG_mm2, + PG_mm2, + PG_mm2, + PG_mm2, + PG_mm2, + PG_mm2, + PG_mm2, + PG_mm2, + PG_mm2, + PG_mm2, + PG_mm2, + PG_mm2, + PG_mm2, + PG_mm2, + PG_mm2, + PG_mm2, + PG_mm2, + PG_mm2, + PG_mm2, + PG_mm2, + PG_mm2, + PG_mm2, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_mmm, + PG_4, + PG_4, + PG_4, + PG_4, + PG_4, + PG_4, + PG_4b, + PG_4b, + PG_4_m, + PG_4_m, + PG_4_m, + PG_4_m, + PG_4_m, + PG_4_m, + PG_422, + PG_422, + PG_422, + PG_422, + PG_422, + PG_422, + PG_422, + PG_422, + PG_422, + PG_422, + PG_4mm, + PG_4mm, + PG_4mm, + PG_4mm, + PG_4mm, + PG_4mm, + PG_4mm, + PG_4mm, + PG_4mm, + PG_4mm, + PG_4mm, + PG_4mm, + PG_4b2m, + PG_4b2m, + PG_4b2m, + PG_4b2m, + PG_4bm2, + PG_4bm2, + PG_4bm2, + PG_4bm2, + PG_4bm2, + PG_4bm2, + PG_4b2m, + PG_4b2m, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_4_mmm, + PG_3, + PG_3, + PG_3, + PG_3, + PG_3b, + PG_3b, + PG_312, + PG_321, + PG_312, + PG_321, + PG_312, + PG_321, + PG_32, + PG_3m1, + PG_31m, + PG_3m1, + PG_31m, + PG_3m, + PG_3m, + PG_3b1m, + PG_3b1m, + PG_3bm1, + PG_3bm1, + PG_3bm, + PG_3bm, + PG_6, + PG_6, + PG_6, + PG_6, + PG_6, + PG_6, + PG_6b, + PG_6_m, + PG_6_m, + PG_622, + PG_622, + PG_622, + PG_622, + PG_622, + PG_622, + PG_6mm, + PG_6mm, + PG_6mm, + PG_6mm, + PG_6bm2, + PG_6bm2, + PG_6b2m, + PG_6b2m, + PG_6_mmm, + PG_6_mmm, + PG_6_mmm, + PG_6_mmm, + PG_23, + PG_23, + PG_23, + PG_23, + PG_23, + PG_m3b, + PG_m3b, + PG_m3b, + PG_m3b, + PG_m3b, + PG_m3b, + PG_m3b, + PG_432, + PG_432, + PG_432, + PG_432, + PG_432, + PG_432, + PG_432, + PG_432, + PG_4b3m, + PG_4b3m, + PG_4b3m, + PG_4b3m, + PG_4b3m, + PG_4b3m, + PG_m3bm, + PG_m3bm, + PG_m3bm, + PG_m3bm, + PG_m3bm, + PG_m3bm, + PG_m3bm, + PG_m3bm, + PG_m3bm, + PG_m3bm + }; +#endif /* SGCLIB_C__ */ + + +#ifndef SGCLIB_C__ +#ifdef SGCOREDEF__ +extern +const char *SchoenfliesSymbols[]; +#endif +#else +const char *SchoenfliesSymbols[] = + { + NULL, + "C1^1", + "Ci^1", + "C2^1", + "C2^2", + "C2^3", + "Cs^1", + "Cs^2", + "Cs^3", + "Cs^4", + "C2h^1", + "C2h^2", + "C2h^3", + "C2h^4", + "C2h^5", + "C2h^6", + "D2^1", + "D2^2", + "D2^3", + "D2^4", + "D2^5", + "D2^6", + "D2^7", + "D2^8", + "D2^9", + "C2v^1", + "C2v^2", + "C2v^3", + "C2v^4", + "C2v^5", + "C2v^6", + "C2v^7", + "C2v^8", + "C2v^9", + "C2v^10", + "C2v^11", + "C2v^12", + "C2v^13", + "C2v^14", + "C2v^15", + "C2v^16", + "C2v^17", + "C2v^18", + "C2v^19", + "C2v^20", + "C2v^21", + "C2v^22", + "D2h^1", + "D2h^2", + "D2h^3", + "D2h^4", + "D2h^5", + "D2h^6", + "D2h^7", + "D2h^8", + "D2h^9", + "D2h^10", + "D2h^11", + "D2h^12", + "D2h^13", + "D2h^14", + "D2h^15", + "D2h^16", + "D2h^17", + "D2h^18", + "D2h^19", + "D2h^20", + "D2h^21", + "D2h^22", + "D2h^23", + "D2h^24", + "D2h^25", + "D2h^26", + "D2h^27", + "D2h^28", + "C4^1", + "C4^2", + "C4^3", + "C4^4", + "C4^5", + "C4^6", + "S4^1", + "S4^2", + "C4h^1", + "C4h^2", + "C4h^3", + "C4h^4", + "C4h^5", + "C4h^6", + "D4^1", + "D4^2", + "D4^3", + "D4^4", + "D4^5", + "D4^6", + "D4^7", + "D4^8", + "D4^9", + "D4^10", + "C4v^1", + "C4v^2", + "C4v^3", + "C4v^4", + "C4v^5", + "C4v^6", + "C4v^7", + "C4v^8", + "C4v^9", + "C4v^10", + "C4v^11", + "C4v^12", + "D2d^1", + "D2d^2", + "D2d^3", + "D2d^4", + "D2d^5", + "D2d^6", + "D2d^7", + "D2d^8", + "D2d^9", + "D2d^10", + "D2d^11", + "D2d^12", + "D4h^1", + "D4h^2", + "D4h^3", + "D4h^4", + "D4h^5", + "D4h^6", + "D4h^7", + "D4h^8", + "D4h^9", + "D4h^10", + "D4h^11", + "D4h^12", + "D4h^13", + "D4h^14", + "D4h^15", + "D4h^16", + "D4h^17", + "D4h^18", + "D4h^19", + "D4h^20", + "C3^1", + "C3^2", + "C3^3", + "C3^4", + "C3i^1", + "C3i^2", + "D3^1", + "D3^2", + "D3^3", + "D3^4", + "D3^5", + "D3^6", + "D3^7", + "C3v^1", + "C3v^2", + "C3v^3", + "C3v^4", + "C3v^5", + "C3v^6", + "D3d^1", + "D3d^2", + "D3d^3", + "D3d^4", + "D3d^5", + "D3d^6", + "C6^1", + "C6^2", + "C6^3", + "C6^4", + "C6^5", + "C6^6", + "C3h^1", + "C6h^1", + "C6h^2", + "D6^1", + "D6^2", + "D6^3", + "D6^4", + "D6^5", + "D6^6", + "C6v^1", + "C6v^2", + "C6v^3", + "C6v^4", + "D3h^1", + "D3h^2", + "D3h^3", + "D3h^4", + "D6h^1", + "D6h^2", + "D6h^3", + "D6h^4", + "T^1", + "T^2", + "T^3", + "T^4", + "T^5", + "Th^1", + "Th^2", + "Th^3", + "Th^4", + "Th^5", + "Th^6", + "Th^7", + "O^1", + "O^2", + "O^3", + "O^4", + "O^5", + "O^6", + "O^7", + "O^8", + "Td^1", + "Td^2", + "Td^3", + "Td^4", + "Td^5", + "Td^6", + "Oh^1", + "Oh^2", + "Oh^3", + "Oh^4", + "Oh^5", + "Oh^6", + "Oh^7", + "Oh^8", + "Oh^9", + "Oh^10" + }; +#endif /* SGCLIB_C__ */ + + +#ifndef SGCLIB_C__ +#ifdef SGCOREDEF__ +extern +const T_TabSgName TabSgName[]; +#endif +#else +const T_TabSgName TabSgName[] = + { + { " P 1", 1, "", "P_1" }, + { "-P 1", 2, "", "P_-1" }, + { " P 2y", 3, "b", "P_2 = P_1_2_1" }, + { " P 2", 3, "c", "P_2 = P_1_1_2" }, + { " P 2x", 3, "a", "P_2 = P_2_1_1" }, + { " P 2yb", 4, "b", "P_21 = P_1_21_1" }, + { " P 2c", 4, "c", "P_21 = P_1_1_21" }, + { " P 2xa", 4, "a", "P_21 = P_21_1_1" }, + { " C 2y", 5, "b1", "C_2 = C_1_2_1" }, + { " A 2y", 5, "b2", "C_2 = A_1_2_1" }, + { " I 2y", 5, "b3", "C_2 = I_1_2_1" }, + { " A 2", 5, "c1", "C_2 = A_1_1_2" }, + { " B 2", 5, "c2", "C_2 = B_1_1_2 = B_2" }, + { " I 2", 5, "c3", "C_2 = I_1_1_2" }, + { " B 2x", 5, "a1", "C_2 = B_2_1_1" }, + { " C 2x", 5, "a2", "C_2 = C_2_1_1" }, + { " I 2x", 5, "a3", "C_2 = I_2_1_1" }, + { " P -2y", 6, "b", "P_m = P_1_m_1" }, + { " P -2", 6, "c", "P_m = P_1_1_m" }, + { " P -2x", 6, "a", "P_m = P_m_1_1" }, + { " P -2yc", 7, "b1", "P_c = P_1_c_1" }, + { " P -2yac", 7, "b2", "P_c = P_1_n_1" }, + { " P -2ya", 7, "b3", "P_c = P_1_a_1" }, + { " P -2a", 7, "c1", "P_c = P_1_1_a" }, + { " P -2ab", 7, "c2", "P_c = P_1_1_n" }, + { " P -2b", 7, "c3", "P_c = P_1_1_b = P_b" }, + { " P -2xb", 7, "a1", "P_c = P_b_1_1" }, + { " P -2xbc", 7, "a2", "P_c = P_n_1_1" }, + { " P -2xc", 7, "a3", "P_c = P_c_1_1" }, + { " C -2y", 8, "b1", "C_m = C_1_m_1" }, + { " A -2y", 8, "b2", "C_m = A_1_m_1" }, + { " I -2y", 8, "b3", "C_m = I_1_m_1" }, + { " A -2", 8, "c1", "C_m = A_1_1_m" }, + { " B -2", 8, "c2", "C_m = B_1_1_m = B_m" }, + { " I -2", 8, "c3", "C_m = I_1_1_m" }, + { " B -2x", 8, "a1", "C_m = B_m_1_1" }, + { " C -2x", 8, "a2", "C_m = C_m_1_1" }, + { " I -2x", 8, "a3", "C_m = I_m_1_1" }, + { " C -2yc", 9, "b1", "C_c = C_1_c_1" }, + { " A -2yac", 9, "b2", "C_c = A_1_n_1" }, + { " I -2ya", 9, "b3", "C_c = I_1_a_1" }, + { " A -2ya", 9, "-b1", "C_c = A_1_a_1" }, + { " C -2ybc", 9, "-b2", "C_c = C_1_n_1" }, + { " I -2yc", 9, "-b3", "C_c = I_1_c_1" }, + { " A -2a", 9, "c1", "C_c = A_1_1_a" }, + { " B -2bc", 9, "c2", "C_c = B_1_1_n" }, + { " I -2b", 9, "c3", "C_c = I_1_1_b" }, + { " B -2b", 9, "-c1", "C_c = B_1_1_b = B_b" }, + { " A -2ac", 9, "-c2", "C_c = A_1_1_n" }, + { " I -2a", 9, "-c3", "C_c = I_1_1_a" }, + { " B -2xb", 9, "a1", "C_c = B_b_1_1" }, + { " C -2xbc", 9, "a2", "C_c = C_n_1_1" }, + { " I -2xc", 9, "a3", "C_c = I_c_1_1" }, + { " C -2xc", 9, "-a1", "C_c = C_c_1_1" }, + { " B -2xbc", 9, "-a2", "C_c = B_n_1_1" }, + { " I -2xb", 9, "-a3", "C_c = I_b_1_1" }, + { "-P 2y", 10, "b", "P_2/m = P_1_2/m_1" }, + { "-P 2", 10, "c", "P_2/m = P_1_1_2/m" }, + { "-P 2x", 10, "a", "P_2/m = P_2/m_1_1" }, + { "-P 2yb", 11, "b", "P_21/m = P_1_21/m_1" }, + { "-P 2c", 11, "c", "P_21/m = P_1_1_21/m" }, + { "-P 2xa", 11, "a", "P_21/m = P_21/m_1_1" }, + { "-C 2y", 12, "b1", "C_2/m = C_1_2/m_1" }, + { "-A 2y", 12, "b2", "C_2/m = A_1_2/m_1" }, + { "-I 2y", 12, "b3", "C_2/m = I_1_2/m_1" }, + { "-A 2", 12, "c1", "C_2/m = A_1_1_2/m" }, + { "-B 2", 12, "c2", "C_2/m = B_1_1_2/m = B_2/m" }, + { "-I 2", 12, "c3", "C_2/m = I_1_1_2/m" }, + { "-B 2x", 12, "a1", "C_2/m = B_2/m_1_1" }, + { "-C 2x", 12, "a2", "C_2/m = C_2/m_1_1" }, + { "-I 2x", 12, "a3", "C_2/m = I_2/m_1_1" }, + { "-P 2yc", 13, "b1", "P_2/c = P_1_2/c_1" }, + { "-P 2yac", 13, "b2", "P_2/c = P_1_2/n_1" }, + { "-P 2ya", 13, "b3", "P_2/c = P_1_2/a_1" }, + { "-P 2a", 13, "c1", "P_2/c = P_1_1_2/a" }, + { "-P 2ab", 13, "c2", "P_2/c = P_1_1_2/n" }, + { "-P 2b", 13, "c3", "P_2/c = P_1_1_2/b = P_2/b" }, + { "-P 2xb", 13, "a1", "P_2/c = P_2/b_1_1" }, + { "-P 2xbc", 13, "a2", "P_2/c = P_2/n_1_1" }, + { "-P 2xc", 13, "a3", "P_2/c = P_2/c_1_1" }, + { "-P 2ybc", 14, "b1", "P_21/c = P_1_21/c_1" }, + { "-P 2yn", 14, "b2", "P_21/c = P_1_21/n_1" }, + { "-P 2yab", 14, "b3", "P_21/c = P_1_21/a_1" }, + { "-P 2ac", 14, "c1", "P_21/c = P_1_1_21/a" }, + { "-P 2n", 14, "c2", "P_21/c = P_1_1_21/n" }, + { "-P 2bc", 14, "c3", "P_21/c = P_1_1_21/b = P_21/b" }, + { "-P 2xab", 14, "a1", "P_21/c = P_21/b_1_1" }, + { "-P 2xn", 14, "a2", "P_21/c = P_21/n_1_1" }, + { "-P 2xac", 14, "a3", "P_21/c = P_21/c_1_1" }, + { "-C 2yc", 15, "b1", "C_2/c = C_1_2/c_1" }, + { "-A 2yac", 15, "b2", "C_2/c = A_1_2/n_1" }, + { "-I 2ya", 15, "b3", "C_2/c = I_1_2/a_1" }, + { "-A 2ya", 15, "-b1", "C_2/c = A_1_2/a_1" }, + { "-C 2ybc", 15, "-b2", "C_2/c = C_1_2/n_1" }, + { "-I 2yc", 15, "-b3", "C_2/c = I_1_2/c_1" }, + { "-A 2a", 15, "c1", "C_2/c = A_1_1_2/a" }, + { "-B 2bc", 15, "c2", "C_2/c = B_1_1_2/n" }, + { "-I 2b", 15, "c3", "C_2/c = I_1_1_2/b" }, + { "-B 2b", 15, "-c1", "C_2/c = B_1_1_2/b = B_2/b" }, + { "-A 2ac", 15, "-c2", "C_2/c = A_1_1_2/n" }, + { "-I 2a", 15, "-c3", "C_2/c = I_1_1_2/a" }, + { "-B 2xb", 15, "a1", "C_2/c = B_2/b_1_1" }, + { "-C 2xbc", 15, "a2", "C_2/c = C_2/n_1_1" }, + { "-I 2xc", 15, "a3", "C_2/c = I_2/c_1_1" }, + { "-C 2xc", 15, "-a1", "C_2/c = C_2/c_1_1" }, + { "-B 2xbc", 15, "-a2", "C_2/c = B_2/n_1_1" }, + { "-I 2xb", 15, "-a3", "C_2/c = I_2/b_1_1" }, + { " P 2 2", 16, "", "P_2_2_2" }, + { " P 2c 2", 17, "", "P_2_2_21" }, + { " P 2a 2a", 17, "cab", "P_21_2_2" }, + { " P 2 2b", 17, "bca", "P_2_21_2" }, + { " P 2 2ab", 18, "", "P_21_21_2" }, + { " P 2bc 2", 18, "cab", "P_2_21_21" }, + { " P 2ac 2ac", 18, "bca", "P_21_2_21" }, + { " P 2ac 2ab", 19, "", "P_21_21_21" }, + { " C 2c 2", 20, "", "C_2_2_21" }, + { " A 2a 2a", 20, "cab", "A_21_2_2" }, + { " B 2 2b", 20, "bca", "B_2_21_2" }, + { " C 2 2", 21, "", "C_2_2_2" }, + { " A 2 2", 21, "cab", "A_2_2_2" }, + { " B 2 2", 21, "bca", "B_2_2_2" }, + { " F 2 2", 22, "", "F_2_2_2" }, + { " I 2 2", 23, "", "I_2_2_2" }, + { " I 2b 2c", 24, "", "I_21_21_21" }, + { " P 2 -2", 25, "", "P_m_m_2" }, + { " P -2 2", 25, "cab", "P_2_m_m" }, + { " P -2 -2", 25, "bca", "P_m_2_m" }, + { " P 2c -2", 26, "", "P_m_c_21" }, + { " P 2c -2c", 26, "ba-c", "P_c_m_21" }, + { " P -2a 2a", 26, "cab", "P_21_m_a" }, + { " P -2 2a", 26, "-cba", "P_21_a_m" }, + { " P -2 -2b", 26, "bca", "P_b_21_m" }, + { " P -2b -2", 26, "a-cb", "P_m_21_b" }, + { " P 2 -2c", 27, "", "P_c_c_2" }, + { " P -2a 2", 27, "cab", "P_2_a_a" }, + { " P -2b -2b", 27, "bca", "P_b_2_b" }, + { " P 2 -2a", 28, "", "P_m_a_2" }, + { " P 2 -2b", 28, "ba-c", "P_b_m_2" }, + { " P -2b 2", 28, "cab", "P_2_m_b" }, + { " P -2c 2", 28, "-cba", "P_2_c_m" }, + { " P -2c -2c", 28, "bca", "P_c_2_m" }, + { " P -2a -2a", 28, "a-cb", "P_m_2_a" }, + { " P 2c -2ac", 29, "", "P_c_a_21" }, + { " P 2c -2b", 29, "ba-c", "P_b_c_21" }, + { " P -2b 2a", 29, "cab", "P_21_a_b" }, + { " P -2ac 2a", 29, "-cba", "P_21_c_a" }, + { " P -2bc -2c", 29, "bca", "P_c_21_b" }, + { " P -2a -2ab", 29, "a-cb", "P_b_21_a" }, + { " P 2 -2bc", 30, "", "P_n_c_2" }, + { " P 2 -2ac", 30, "ba-c", "P_c_n_2" }, + { " P -2ac 2", 30, "cab", "P_2_n_a" }, + { " P -2ab 2", 30, "-cba", "P_2_a_n" }, + { " P -2ab -2ab", 30, "bca", "P_b_2_n" }, + { " P -2bc -2bc", 30, "a-cb", "P_n_2_b" }, + { " P 2ac -2", 31, "", "P_m_n_21" }, + { " P 2bc -2bc", 31, "ba-c", "P_n_m_21" }, + { " P -2ab 2ab", 31, "cab", "P_21_m_n" }, + { " P -2 2ac", 31, "-cba", "P_21_n_m" }, + { " P -2 -2bc", 31, "bca", "P_n_21_m" }, + { " P -2ab -2", 31, "a-cb", "P_m_21_n" }, + { " P 2 -2ab", 32, "", "P_b_a_2" }, + { " P -2bc 2", 32, "cab", "P_2_c_b" }, + { " P -2ac -2ac", 32, "bca", "P_c_2_a" }, + { " P 2c -2n", 33, "", "P_n_a_21" }, + { " P 2c -2ab", 33, "ba-c", "P_b_n_21" }, + { " P -2bc 2a", 33, "cab", "P_21_n_b" }, + { " P -2n 2a", 33, "-cba", "P_21_c_n" }, + { " P -2n -2ac", 33, "bca", "P_c_21_n" }, + { " P -2ac -2n", 33, "a-cb", "P_n_21_a" }, + { " P 2 -2n", 34, "", "P_n_n_2" }, + { " P -2n 2", 34, "cab", "P_2_n_n" }, + { " P -2n -2n", 34, "bca", "P_n_2_n" }, + { " C 2 -2", 35, "", "C_m_m_2" }, + { " A -2 2", 35, "cab", "A_2_m_m" }, + { " B -2 -2", 35, "bca", "B_m_2_m" }, + { " C 2c -2", 36, "", "C_m_c_21" }, + { " C 2c -2c", 36, "ba-c", "C_c_m_21" }, + { " A -2a 2a", 36, "cab", "A_21_m_a" }, + { " A -2 2a", 36, "-cba", "A_21_a_m" }, + { " B -2 -2b", 36, "bca", "B_b_21_m" }, + { " B -2b -2", 36, "a-cb", "B_m_21_b" }, + { " C 2 -2c", 37, "", "C_c_c_2" }, + { " A -2a 2", 37, "cab", "A_2_a_a" }, + { " B -2b -2b", 37, "bca", "B_b_2_b" }, + { " A 2 -2", 38, "", "A_m_m_2" }, + { " B 2 -2", 38, "ba-c", "B_m_m_2" }, + { " B -2 2", 38, "cab", "B_2_m_m" }, + { " C -2 2", 38, "-cba", "C_2_m_m" }, + { " C -2 -2", 38, "bca", "C_m_2_m" }, + { " A -2 -2", 38, "a-cb", "A_m_2_m" }, + { " A 2 -2c", 39, "", "A_b_m_2" }, + { " B 2 -2c", 39, "ba-c", "B_m_a_2" }, + { " B -2c 2", 39, "cab", "B_2_c_m" }, + { " C -2b 2", 39, "-cba", "C_2_m_b" }, + { " C -2b -2b", 39, "bca", "C_m_2_a" }, + { " A -2c -2c", 39, "a-cb", "A_c_2_m" }, + { " A 2 -2a", 40, "", "A_m_a_2" }, + { " B 2 -2b", 40, "ba-c", "B_b_m_2" }, + { " B -2b 2", 40, "cab", "B_2_m_b" }, + { " C -2c 2", 40, "-cba", "C_2_c_m" }, + { " C -2c -2c", 40, "bca", "C_c_2_m" }, + { " A -2a -2a", 40, "a-cb", "A_m_2_a" }, + { " A 2 -2ac", 41, "", "A_b_a_2" }, + { " B 2 -2bc", 41, "ba-c", "B_b_a_2" }, + { " B -2bc 2", 41, "cab", "B_2_c_b" }, + { " C -2bc 2", 41, "-cba", "C_2_c_b" }, + { " C -2bc -2bc", 41, "bca", "C_c_2_a" }, + { " A -2ac -2ac", 41, "a-cb", "A_c_2_a" }, + { " F 2 -2", 42, "", "F_m_m_2" }, + { " F -2 2", 42, "cab", "F_2_m_m" }, + { " F -2 -2", 42, "bca", "F_m_2_m" }, + { " F 2 -2d", 43, "", "F_d_d_2" }, + { " F -2d 2", 43, "cab", "F_2_d_d" }, + { " F -2d -2d", 43, "bca", "F_d_2_d" }, + { " I 2 -2", 44, "", "I_m_m_2" }, + { " I -2 2", 44, "cab", "I_2_m_m" }, + { " I -2 -2", 44, "bca", "I_m_2_m" }, + { " I 2 -2c", 45, "", "I_b_a_2" }, + { " I -2a 2", 45, "cab", "I_2_c_b" }, + { " I -2b -2b", 45, "bca", "I_c_2_a" }, + { " I 2 -2a", 46, "", "I_m_a_2" }, + { " I 2 -2b", 46, "ba-c", "I_b_m_2" }, + { " I -2b 2", 46, "cab", "I_2_m_b" }, + { " I -2c 2", 46, "-cba", "I_2_c_m" }, + { " I -2c -2c", 46, "bca", "I_c_2_m" }, + { " I -2a -2a", 46, "a-cb", "I_m_2_a" }, + { "-P 2 2", 47, "", "P_m_m_m" }, + { " P 2 2 -1n", 48, "1", "P_n_n_n" }, + { "-P 2ab 2bc", 48, "2", "P_n_n_n" }, + { "-P 2 2c", 49, "", "P_c_c_m" }, + { "-P 2a 2", 49, "cab", "P_m_a_a" }, + { "-P 2b 2b", 49, "bca", "P_b_m_b" }, + { " P 2 2 -1ab", 50, "1", "P_b_a_n" }, + { "-P 2ab 2b", 50, "2", "P_b_a_n" }, + { " P 2 2 -1bc", 50, "1cab", "P_n_c_b" }, + { "-P 2b 2bc", 50, "2cab", "P_n_c_b" }, + { " P 2 2 -1ac", 50, "1bca", "P_c_n_a" }, + { "-P 2a 2c", 50, "2bca", "P_c_n_a" }, + { "-P 2a 2a", 51, "", "P_m_m_a" }, + { "-P 2b 2", 51, "ba-c", "P_m_m_b" }, + { "-P 2 2b", 51, "cab", "P_b_m_m" }, + { "-P 2c 2c", 51, "-cba", "P_c_m_m" }, + { "-P 2c 2", 51, "bca", "P_m_c_m" }, + { "-P 2 2a", 51, "a-cb", "P_m_a_m" }, + { "-P 2a 2bc", 52, "", "P_n_n_a" }, + { "-P 2b 2n", 52, "ba-c", "P_n_n_b" }, + { "-P 2n 2b", 52, "cab", "P_b_n_n" }, + { "-P 2ab 2c", 52, "-cba", "P_c_n_n" }, + { "-P 2ab 2n", 52, "bca", "P_n_c_n" }, + { "-P 2n 2bc", 52, "a-cb", "P_n_a_n" }, + { "-P 2ac 2", 53, "", "P_m_n_a" }, + { "-P 2bc 2bc", 53, "ba-c", "P_n_m_b" }, + { "-P 2ab 2ab", 53, "cab", "P_b_m_n" }, + { "-P 2 2ac", 53, "-cba", "P_c_n_m" }, + { "-P 2 2bc", 53, "bca", "P_n_c_m" }, + { "-P 2ab 2", 53, "a-cb", "P_m_a_n" }, + { "-P 2a 2ac", 54, "", "P_c_c_a" }, + { "-P 2b 2c", 54, "ba-c", "P_c_c_b" }, + { "-P 2a 2b", 54, "cab", "P_b_a_a" }, + { "-P 2ac 2c", 54, "-cba", "P_c_a_a" }, + { "-P 2bc 2b", 54, "bca", "P_b_c_b" }, + { "-P 2b 2ab", 54, "a-cb", "P_b_a_b" }, + { "-P 2 2ab", 55, "", "P_b_a_m" }, + { "-P 2bc 2", 55, "cab", "P_m_c_b" }, + { "-P 2ac 2ac", 55, "bca", "P_c_m_a" }, + { "-P 2ab 2ac", 56, "", "P_c_c_n" }, + { "-P 2ac 2bc", 56, "cab", "P_n_a_a" }, + { "-P 2bc 2ab", 56, "bca", "P_b_n_b" }, + { "-P 2c 2b", 57, "", "P_b_c_m" }, + { "-P 2c 2ac", 57, "ba-c", "P_c_a_m" }, + { "-P 2ac 2a", 57, "cab", "P_m_c_a" }, + { "-P 2b 2a", 57, "-cba", "P_m_a_b" }, + { "-P 2a 2ab", 57, "bca", "P_b_m_a" }, + { "-P 2bc 2c", 57, "a-cb", "P_c_m_b" }, + { "-P 2 2n", 58, "", "P_n_n_m" }, + { "-P 2n 2", 58, "cab", "P_m_n_n" }, + { "-P 2n 2n", 58, "bca", "P_n_m_n" }, + { " P 2 2ab -1ab", 59, "1", "P_m_m_n" }, + { "-P 2ab 2a", 59, "2", "P_m_m_n" }, + { " P 2bc 2 -1bc", 59, "1cab", "P_n_m_m" }, + { "-P 2c 2bc", 59, "2cab", "P_n_m_m" }, + { " P 2ac 2ac -1ac", 59, "1bca", "P_m_n_m" }, + { "-P 2c 2a", 59, "2bca", "P_m_n_m" }, + { "-P 2n 2ab", 60, "", "P_b_c_n" }, + { "-P 2n 2c", 60, "ba-c", "P_c_a_n" }, + { "-P 2a 2n", 60, "cab", "P_n_c_a" }, + { "-P 2bc 2n", 60, "-cba", "P_n_a_b" }, + { "-P 2ac 2b", 60, "bca", "P_b_n_a" }, + { "-P 2b 2ac", 60, "a-cb", "P_c_n_b" }, + { "-P 2ac 2ab", 61, "", "P_b_c_a" }, + { "-P 2bc 2ac", 61, "ba-c", "P_c_a_b" }, + { "-P 2ac 2n", 62, "", "P_n_m_a" }, + { "-P 2bc 2a", 62, "ba-c", "P_m_n_b" }, + { "-P 2c 2ab", 62, "cab", "P_b_n_m" }, + { "-P 2n 2ac", 62, "-cba", "P_c_m_n" }, + { "-P 2n 2a", 62, "bca", "P_m_c_n" }, + { "-P 2c 2n", 62, "a-cb", "P_n_a_m" }, + { "-C 2c 2", 63, "", "C_m_c_m" }, + { "-C 2c 2c", 63, "ba-c", "C_c_m_m" }, + { "-A 2a 2a", 63, "cab", "A_m_m_a" }, + { "-A 2 2a", 63, "-cba", "A_m_a_m" }, + { "-B 2 2b", 63, "bca", "B_b_m_m" }, + { "-B 2b 2", 63, "a-cb", "B_m_m_b" }, + { "-C 2bc 2", 64, "", "C_m_c_a" }, + { "-C 2bc 2bc", 64, "ba-c", "C_c_m_b" }, + { "-A 2ac 2ac", 64, "cab", "A_b_m_a" }, + { "-A 2 2ac", 64, "-cba", "A_c_a_m" }, + { "-B 2 2bc", 64, "bca", "B_b_c_m" }, + { "-B 2bc 2", 64, "a-cb", "B_m_a_b" }, + { "-C 2 2", 65, "", "C_m_m_m" }, + { "-A 2 2", 65, "cab", "A_m_m_m" }, + { "-B 2 2", 65, "bca", "B_m_m_m" }, + { "-C 2 2c", 66, "", "C_c_c_m" }, + { "-A 2a 2", 66, "cab", "A_m_a_a" }, + { "-B 2b 2b", 66, "bca", "B_b_m_b" }, + { "-C 2b 2", 67, "", "C_m_m_a" }, + { "-C 2b 2b", 67, "ba-c", "C_m_m_b" }, + { "-A 2c 2c", 67, "cab", "A_b_m_m" }, + { "-A 2 2c", 67, "-cba", "A_c_m_m" }, + { "-B 2 2c", 67, "bca", "B_m_c_m" }, + { "-B 2c 2", 67, "a-cb", "B_m_a_m" }, + { " C 2 2 -1bc", 68, "1", "C_c_c_a" }, + { "-C 2b 2bc", 68, "2", "C_c_c_a" }, + { " C 2 2 -1bc", 68, "1ba-c", "C_c_c_b" }, + { "-C 2b 2c", 68, "2ba-c", "C_c_c_b" }, + { " A 2 2 -1ac", 68, "1cab", "A_b_a_a" }, + { "-A 2a 2c", 68, "2cab", "A_b_a_a" }, + { " A 2 2 -1ac", 68, "1-cba", "A_c_a_a" }, + { "-A 2ac 2c", 68, "2-cba", "A_c_a_a" }, + { " B 2 2 -1bc", 68, "1bca", "B_b_c_b" }, + { "-B 2bc 2b", 68, "2bca", "B_b_c_b" }, + { " B 2 2 -1bc", 68, "1a-cb", "B_b_a_b" }, + { "-B 2b 2bc", 68, "2a-cb", "B_b_a_b" }, + { "-F 2 2", 69, "", "F_m_m_m" }, + { " F 2 2 -1d", 70, "1", "F_d_d_d" }, + { "-F 2uv 2vw", 70, "2", "F_d_d_d" }, + { "-I 2 2", 71, "", "I_m_m_m" }, + { "-I 2 2c", 72, "", "I_b_a_m" }, + { "-I 2a 2", 72, "cab", "I_m_c_b" }, + { "-I 2b 2b", 72, "bca", "I_c_m_a" }, + { "-I 2b 2c", 73, "", "I_b_c_a" }, + { "-I 2a 2b", 73, "ba-c", "I_c_a_b" }, + { "-I 2b 2", 74, "", "I_m_m_a" }, + { "-I 2a 2a", 74, "ba-c", "I_m_m_b" }, + { "-I 2c 2c", 74, "cab", "I_b_m_m" }, + { "-I 2 2b", 74, "-cba", "I_c_m_m" }, + { "-I 2 2a", 74, "bca", "I_m_c_m" }, + { "-I 2c 2", 74, "a-cb", "I_m_a_m" }, + { " P 4", 75, "", "P_4" }, + { " P 4w", 76, "", "P_41" }, + { " P 4c", 77, "", "P_42" }, + { " P 4cw", 78, "", "P_43" }, + { " I 4", 79, "", "I_4" }, + { " I 4bw", 80, "", "I_41" }, + { " P -4", 81, "", "P_-4" }, + { " I -4", 82, "", "I_-4" }, + { "-P 4", 83, "", "P_4/m" }, + { "-P 4c", 84, "", "P_42/m" }, + { " P 4ab -1ab", 85, "1", "P_4/n" }, + { "-P 4a", 85, "2", "P_4/n" }, + { " P 4n -1n", 86, "1", "P_42/n" }, + { "-P 4bc", 86, "2", "P_42/n" }, + { "-I 4", 87, "", "I_4/m" }, + { " I 4bw -1bw", 88, "1", "I_41/a" }, + { "-I 4ad", 88, "2", "I_41/a" }, + { " P 4 2", 89, "", "P_4_2_2" }, + { " P 4ab 2ab", 90, "", "P_42_1_2" }, + { " P 4w 2c", 91, "", "P_41_2_2" }, + { " P 4abw 2nw", 92, "", "P_41_21_2" }, + { " P 4c 2", 93, "", "P_42_2_2" }, + { " P 4n 2n", 94, "", "P_42_21_2" }, + { " P 4cw 2c", 95, "", "P_43_2_2" }, + { " P 4nw 2abw", 96, "", "P_43_21_2" }, + { " I 4 2", 97, "", "I_4_2_2" }, + { " I 4bw 2bw", 98, "", "I_41_2_2" }, + { " P 4 -2", 99, "", "P_4_m_m" }, + { " P 4 -2ab", 100, "", "P_4_b_m" }, + { " P 4c -2c", 101, "", "P_42_c_m" }, + { " P 4n -2n", 102, "", "P_42_n_m" }, + { " P 4 -2c", 103, "", "P_4_c_c" }, + { " P 4 -2n", 104, "", "P_4_n_c" }, + { " P 4c -2", 105, "", "P_42_m_c" }, + { " P 4c -2ab", 106, "", "P_42_b_c" }, + { " I 4 -2", 107, "", "I_4_m_m" }, + { " I 4 -2c", 108, "", "I_4_c_m" }, + { " I 4bw -2", 109, "", "I_41_m_d" }, + { " I 4bw -2c", 110, "", "I_41_c_d" }, + { " P -4 2", 111, "", "P_-4_2_m" }, + { " P -4 2c", 112, "", "P_-4_2_c" }, + { " P -4 2ab", 113, "", "P_-4_21_m" }, + { " P -4 2n", 114, "", "P_-4_21_c" }, + { " P -4 -2", 115, "", "P_-4_m_2" }, + { " P -4 -2c", 116, "", "P_-4_c_2" }, + { " P -4 -2ab", 117, "", "P_-4_b_2" }, + { " P -4 -2n", 118, "", "P_-4_n_2" }, + { " I -4 -2", 119, "", "I_-4_m_2" }, + { " I -4 -2c", 120, "", "I_-4_c_2" }, + { " I -4 2", 121, "", "I_-4_2_m" }, + { " I -4 2bw", 122, "", "I_-4_2_d" }, + { "-P 4 2", 123, "", "P_4/m_m_m" }, + { "-P 4 2c", 124, "", "P_4/m_c_c" }, + { " P 4 2 -1ab", 125, "1", "P_4/n_b_m" }, + { "-P 4a 2b", 125, "2", "P_4/n_b_m" }, + { " P 4 2 -1n", 126, "1", "P_4/n_n_c" }, + { "-P 4a 2bc", 126, "2", "P_4/n_n_c" }, + { "-P 4 2ab", 127, "", "P_4/m_b_m" }, + { "-P 4 2n", 128, "", "P_4/m_n_c" }, + { " P 4ab 2ab -1ab", 129, "1", "P_4/n_m_m" }, + { "-P 4a 2a", 129, "2", "P_4/n_m_m" }, + { " P 4ab 2n -1ab", 130, "1", "P_4/n_c_c" }, + { "-P 4a 2ac", 130, "2", "P_4/n_c_c" }, + { "-P 4c 2", 131, "", "P_42/m_m_c" }, + { "-P 4c 2c", 132, "", "P_42/m_c_m" }, + { " P 4n 2c -1n", 133, "1", "P_42/n_b_c" }, + { "-P 4ac 2b", 133, "2", "P_42/n_b_c" }, + { " P 4n 2 -1n", 134, "1", "P_42/n_n_m" }, + { "-P 4ac 2bc", 134, "2", "P_42/n_n_m" }, + { "-P 4c 2ab", 135, "", "P_42/m_b_c" }, + { "-P 4n 2n", 136, "", "P_42/m_n_m" }, + { " P 4n 2n -1n", 137, "1", "P_42/n_m_c" }, + { "-P 4ac 2a", 137, "2", "P_42/n_m_c" }, + { " P 4n 2ab -1n", 138, "1", "P_42/n_c_m" }, + { "-P 4ac 2ac", 138, "2", "P_42/n_c_m" }, + { "-I 4 2", 139, "", "I_4/m_m_m" }, + { "-I 4 2c", 140, "", "I_4/m_c_m" }, + { " I 4bw 2bw -1bw", 141, "1", "I_41/a_m_d" }, + { "-I 4bd 2", 141, "2", "I_41/a_m_d" }, + { " I 4bw 2aw -1bw", 142, "1", "I_41/a_c_d" }, + { "-I 4bd 2c", 142, "2", "I_41/a_c_d" }, + { " P 3", 143, "", "P_3" }, + { " P 31", 144, "", "P_31" }, + { " P 32", 145, "", "P_32" }, + { " R 3", 146, "H", "R_3" }, + { " P 3*", 146, "R", "R_3" }, + { "-P 3", 147, "", "P_-3" }, + { "-R 3", 148, "H", "R_-3" }, + { "-P 3*", 148, "R", "R_-3" }, + { " P 3 2", 149, "", "P_3_1_2" }, + { " P 3 2\"", 150, "", "P_3_2_1" }, + { " P 31 2c (0 0 1)", 151, "", "P_31_1_2" }, + { " P 31 2\"", 152, "", "P_31_2_1" }, + { " P 32 2c (0 0 -1)", 153, "", "P_32_1_2" }, + { " P 32 2\"", 154, "", "P_32_2_1" }, + { " R 3 2\"", 155, "H", "R_32" }, + { " P 3* 2", 155, "R", "R_32" }, + { " P 3 -2\"", 156, "", "P_3_m_1" }, + { " P 3 -2", 157, "", "P_3_1_m" }, + { " P 3 -2\"c", 158, "", "P_3_c_1" }, + { " P 3 -2c", 159, "", "P_3_1_c" }, + { " R 3 -2\"", 160, "H", "R_3_m" }, + { " P 3* -2", 160, "R", "R_3_m" }, + { " R 3 -2\"c", 161, "H", "R_3_c" }, + { " P 3* -2n", 161, "R", "R_3_c" }, + { "-P 3 2", 162, "", "P_-3_1_m" }, + { "-P 3 2c", 163, "", "P_-3_1_c" }, + { "-P 3 2\"", 164, "", "P_-3_m_1" }, + { "-P 3 2\"c", 165, "", "P_-3_c_1" }, + { "-R 3 2\"", 166, "H", "R_-3_m" }, + { "-P 3* 2", 166, "R", "R_-3_m" }, + { "-R 3 2\"c", 167, "H", "R_-3_c" }, + { "-P 3* 2n", 167, "R", "R_-3_c" }, + { " P 6", 168, "", "P_6" }, + { " P 61", 169, "", "P_61" }, + { " P 65", 170, "", "P_65" }, + { " P 62", 171, "", "P_62" }, + { " P 64", 172, "", "P_64" }, + { " P 6c", 173, "", "P_63" }, + { " P -6", 174, "", "P_-6" }, + { "-P 6", 175, "", "P_6/m" }, + { "-P 6c", 176, "", "P_63/m" }, + { " P 6 2", 177, "", "P_6_2_2" }, + { " P 61 2 (0 0 -1)", 178, "", "P_61_2_2" }, + { " P 65 2 (0 0 1)", 179, "", "P_65_2_2" }, + { " P 62 2c (0 0 1)", 180, "", "P_62_2_2" }, + { " P 64 2c (0 0 -1)", 181, "", "P_64_2_2" }, + { " P 6c 2c", 182, "", "P_63_2_2" }, + { " P 6 -2", 183, "", "P_6_m_m" }, + { " P 6 -2c", 184, "", "P_6_c_c" }, + { " P 6c -2", 185, "", "P_63_c_m" }, + { " P 6c -2c", 186, "", "P_63_m_c" }, + { " P -6 2", 187, "", "P_-6_m_2" }, + { " P -6c 2", 188, "", "P_-6_c_2" }, + { " P -6 -2", 189, "", "P_-6_2_m" }, + { " P -6c -2c", 190, "", "P_-6_2_c" }, + { "-P 6 2", 191, "", "P_6/m_m_m" }, + { "-P 6 2c", 192, "", "P_6/m_c_c" }, + { "-P 6c 2", 193, "", "P_63/m_c_m" }, + { "-P 6c 2c", 194, "", "P_63/m_m_c" }, + { " P 2 2 3", 195, "", "P_2_3" }, + { " F 2 2 3", 196, "", "F_2_3" }, + { " I 2 2 3", 197, "", "I_2_3" }, + { " P 2ac 2ab 3", 198, "", "P_21_3" }, + { " I 2b 2c 3", 199, "", "I_21_3" }, + { "-P 2 2 3", 200, "", "P_m_-3" }, + { " P 2 2 3 -1n", 201, "1", "P_n_-3" }, + { "-P 2ab 2bc 3", 201, "2", "P_n_-3" }, + { "-F 2 2 3", 202, "", "F_m_-3" }, + { " F 2 2 3 -1d", 203, "1", "F_d_-3" }, + { "-F 2uv 2vw 3", 203, "2", "F_d_-3" }, + { "-I 2 2 3", 204, "", "I_m_-3" }, + { "-P 2ac 2ab 3", 205, "", "P_a_-3" }, + { "-I 2b 2c 3", 206, "", "I_a_-3" }, + { " P 4 2 3", 207, "", "P_4_3_2" }, + { " P 4n 2 3", 208, "", "P_42_3_2" }, + { " F 4 2 3", 209, "", "F_4_3_2" }, + { " F 4d 2 3", 210, "", "F_41_3_2" }, + { " I 4 2 3", 211, "", "I_4_3_2" }, + { " P 4acd 2ab 3", 212, "", "P_43_3_2" }, + { " P 4bd 2ab 3", 213, "", "P_41_3_2" }, + { " I 4bd 2c 3", 214, "", "I_41_3_2" }, + { " P -4 2 3", 215, "", "P_-4_3_m" }, + { " F -4 2 3", 216, "", "F_-4_3_m" }, + { " I -4 2 3", 217, "", "I_-4_3_m" }, + { " P -4n 2 3", 218, "", "P_-4_3_n" }, + { " F -4c 2 3", 219, "", "F_-4_3_c" }, + { " I -4bd 2c 3", 220, "", "I_-4_3_d" }, + { "-P 4 2 3", 221, "", "P_m_-3_m" }, + { " P 4 2 3 -1n", 222, "1", "P_n_-3_n" }, + { "-P 4a 2bc 3", 222, "2", "P_n_-3_n" }, + { "-P 4n 2 3", 223, "", "P_m_-3_n" }, + { " P 4n 2 3 -1n", 224, "1", "P_n_-3_m" }, + { "-P 4bc 2bc 3", 224, "2", "P_n_-3_m" }, + { "-F 4 2 3", 225, "", "F_m_-3_m" }, + { "-F 4c 2 3", 226, "", "F_m_-3_c" }, + { " F 4d 2 3 -1d", 227, "1", "F_d_-3_m" }, + { "-F 4vw 2vw 3", 227, "2", "F_d_-3_m" }, + { " F 4d 2 3 -1cd", 228, "1", "F_d_-3_c" }, + { "-F 4cvw 2vw 3", 228, "2", "F_d_-3_c" }, + { "-I 4 2 3", 229, "", "I_m_-3_m" }, + { "-I 4bd 2c 3", 230, "", "I_a_-3_d" }, + { NULL, 0, NULL, NULL } + }; +#endif /* SGCLIB_C__ */ + + +#define Sg_nLoopInv(SgInfo_)\ + ((SgInfo_)->Centric == -1 ? 2 : 1) + + +#define InitRotMx(RotMx, diagonal)\ + {\ + int private_i_;\ + for (private_i_ = 0; private_i_ < 9; private_i_++)\ + (RotMx)[private_i_] = (private_i_ % 4 ? 0 : diagonal);\ + } + +#define InitSeitzMx(SeitzMx_, diagonal)\ + {\ + int private_i_;\ + for (private_i_ = 0; private_i_ < 12; private_i_++)\ + (SeitzMx_)->a[private_i_] = (private_i_ % 4 ? 0 : diagonal);\ + } + + +#if defined(SGCLIB_C__) || defined(SGCOREDEF__) +#define SpecialSMx_Identity 0x01 +#define SpecialSMx_Inversion 0x02 +#define SpecialSMx_Transl0 0x04 +#endif + + +/* sgclib.c */ + +void SetSgError(const char *msg); +int iModPositive(int ix, int iy); +int traceRotMx(const int *RotMx); +int deterRotMx(const int *RotMx); +void RotMx_t_Vector(int *R_t_V, const int *RotMx, const int *Vector, int FacTr); +void RotMxMultiply(int *rmxab, const int *rmxa, const int *rmxb); +void RotateRotMx(int *RotMx, const int *RMx, const int *InvRMx); +void SeitzMxMultiply(T_RTMx *smxab, const T_RTMx *smxa, const T_RTMx *smxb); +void RTMxMultiply(T_RTMx *rtmxab, const T_RTMx *rtmxa, const T_RTMx *rtmxb, + int FacAug, int FacTr); +void InverseRotMx(const int *RotMx, int *InvRotMx); +void InverseRTMx(const T_RTMx *RTMx, T_RTMx *InvRTMx); +int IsSMxTransl0(const T_LatticeInfo *LatticeInfo, const int *SeitzMxT); +int CompareSeitzMx(const T_LatticeInfo *LatticeInfo, + const T_RTMx *SeitzMxA, const T_RTMx *SeitzMxB); +int GetRotMxOrder(const int *RotMx); +int GetRotMxInfo(const int *RotMx, T_RotMxInfo *RotMxInfo); +const T_RotMxInfo *ListOrBufRotMxInfo(const T_SgInfo *SgInfo, int iList, + T_RotMxInfo *BufRotMxInfo); +int Add2ListSeitzMx(T_SgInfo *SgInfo, const T_RTMx *NewSMx); +int AddInversion2ListSeitzMx(T_SgInfo *SgInfo); +int AddLatticeTr2ListSeitzMx(T_SgInfo *SgInfo, + const T_LatticeInfo *LatticeInfo); +int ApplyOriginShift(T_SgInfo *SgInfo); +int FindSeitzMx(const T_SgInfo *SgInfo, + int Order, int HonorSign, int RefAxis, int DirCode); +void InitSgInfo(T_SgInfo *SgInfo); +int CompleteSgInfo(T_SgInfo *SgInfo); +int CB_SMx(T_RTMx *CSiC, + const T_RTMx *CBMx, const T_RTMx *SMx, const T_RTMx *InvCBMx); +int TransformSgInfo(const T_SgInfo *SgInfo, + const T_RTMx *CBMx, const T_RTMx *InvCBMx, + T_SgInfo *BC_SgInfo); + +/* sgio.c */ + +const T_TabSgName *FindTabSgNameEntry(const char *UserSgName, int VolLetter); +unsigned int SgID_Number(const T_TabSgName *tsgn); +int ParseSymXYZ(const char *SymXYZ, T_RTMx *SeitzMx, int FacTr); +int ParseHallSymbol(const char *hsym, T_SgInfo *SgInfo); +int PrintFullHM_SgName(const T_TabSgName *tsgn, int space, FILE *fpout); +void PrintTabSgNameEntry(const T_TabSgName *tsgn, int Style, int space, + FILE *fpout); +const char *FormatFraction(int nume, int deno, int Decimal, + char *Buffer, int SizeBuffer); +const char *RTMx2XYZ(const T_RTMx *RTMx, int FacRo, int FacTr, + int Decimal, int TrFirst, int Low, + const char *Seperator, + char *BufferXYZ, int SizeBufferXYZ); +void PrintMapleRTMx(const T_RTMx *RTMx, int FacRo, int FacTr, + const char *Label, FILE *fpout); +void ListSgInfo(const T_SgInfo *SgInfo, int F_XYZ, int F_Verbose, FILE *fpout); + + +/* sgfind.c */ + +const T_TabSgName *FindReferenceSpaceGroup(T_SgInfo *SgInfo, + T_RTMx *CBMx, T_RTMx *InvCBMx); + +/* sghkl.c */ + +int IsSysAbsent_hkl(const T_SgInfo *SgInfo, + int h, int k, int l, int *TH_Restriction); +int BuildEq_hkl(const T_SgInfo *SgInfo, T_Eq_hkl *Eq_hkl, int h, int k, int l); +int AreSymEquivalent_hkl(const T_SgInfo *SgInfo, int h1, int k1, int l1, + int h2, int k2, int l2); +void SetListMin_hkl(const T_SgInfo *SgInfo, int Maxk, int Maxl, + int *Minh, int *Mink, int *Minl); +int IsSuppressed_hkl(const T_SgInfo *SgInfo, int Minh, int Mink, int Minl, + int Maxk, int Maxl, + int h, int k, int l); + +/* sgsi.c */ + +void MarkLegalOrigins(const T_SgInfo *SgInfo, int *TestField); +int Verify_si(int h, int k, int l, const int *TestField); +int Is_si(const T_SgInfo *SgInfo, int h, int k, int l); +int Set_si(T_SgInfo *SgInfo); +void Set_uvw(const T_SgInfo *SgInfo, int h, int k, int l, int *uvw); + + +#endif /* SGINFO_H__ */ diff --git a/sgio.c b/sgio.c new file mode 100644 index 00000000..e323fedb --- /dev/null +++ b/sgio.c @@ -0,0 +1,1790 @@ +/* + Space Group Info's (c) 1994-96 Ralf W. Grosse-Kunstleve + */ + +#include +#include +#include +#include + + +#define SGCOREDEF__ +#include "sginfo.h" + + +typedef struct + { + int OriginChoice; + int CellChoice; + int BasisChoice; + const char *BT_or_UA; + } + T_ExtInfo; + + +static const char *Ext_BT_or_UA[] = + { + /* 0 */ "abc", + /* 1 */ "ba-c", + /* 2 */ "cab", + /* 3 */ "-cba", + /* 4 */ "bca", + /* 5 */ "a-cb", + /* 6 */ "bac", /* 6 -> 1 */ + /* 7 */ "cba", /* 7 -> 3 */ + /* 8 */ "acb", /* 8 -> 5 */ + /* 9 */ "-b", "b-", "bb", "bb", /* 10, 11, 12 -> 9 */ + /* 13 */ "-c", "c-", "bc", "cb", /* 14, 15, 16 -> 13 */ + /* 17 */ "-a", "a-", "ba", "ab", /* 18, 19, 20 -> 17 */ + /* 21 */ "b", + /* 22 */ "c", + /* 23 */ "a", + NULL + }; + + +typedef struct + { + int Improper, Rotation, RefAxis, DirCode, Screw; + T_RTMx SeitzMx; + } + T_HallGenerator; + + +#define SkipWhite(cp) while (*(cp) && (*(cp) == '_' || isspace(*(cp)))) (cp)++ + + +static const char *IErr_Corrupt_TabSgName = + "Internal Error: Corrupt TabSgName"; + + +static int FindSchoenfliesSymbol(const char *SfSymbol) +{ + int SgNumber; + const char **TabSymbol; + const char *s, *t; + + + TabSymbol = SchoenfliesSymbols + 1; + + for (SgNumber = 1; SgNumber <= 230; SgNumber++) + { + t = *TabSymbol; + s = SfSymbol; + + while (*t && *s) + { + if ( toupper(*t) != toupper(*s) + && (*t != '^' || isalpha(*s) || isdigit(*s))) + break; + + t++; + s++; + } + + if (*t == *s) + return SgNumber; + + TabSymbol++; + } + + return -1; +} + + +static int SgLabelCmp(const int SgNumber, + const char *SgLabel, const char *WtdLbl) +{ + const char *sgl, *wl; + + + /* first try: plain strcmp + */ + sgl = SgLabel; + + for (wl = WtdLbl; ; wl++) + { + SkipWhite(wl); + SkipWhite(sgl); + + if (*sgl == '\0' || *sgl == '=') + { + if (*wl == '\0') return 0; + break; + } + + if (*sgl == '-') + { + if (*wl != '-' && toupper(*wl) != 'B') + break; + } + else if (toupper(*sgl) != toupper(*wl)) + break; + + sgl++; + } + + /* second try: swap the dash (there should be only one) + */ + sgl = SgLabel; + + for (wl = WtdLbl; ; wl++) + { + SkipWhite(wl); + SkipWhite(sgl); + + if (*sgl == '-') + { + if (wl[1] != '-' && toupper(wl[1]) != 'B') + break; + if (toupper(sgl[1]) != toupper(*wl)) + break; + + sgl++; + wl++; + } + else + { + if (*sgl == '\0' || *sgl == '=') + { + if (*wl == '\0') return 0; + break; + } + + if (toupper(*sgl) != toupper(*wl)) + break; + } + + sgl++; + } + + if (SgNumber >= 195) /* cubic space groups only */ + { + /* third try: ignore the "-3" dash + */ + sgl = SgLabel; + + for (wl = WtdLbl; ; wl++) + { + SkipWhite(wl); + SkipWhite(sgl); + + if (*sgl == '-' && sgl[1] == '3') + sgl++; + + if (*sgl == '\0' || *sgl == '=') + { + if (*wl == '\0') return 0; + break; + } + + if (toupper(*sgl) != toupper(*wl)) + break; + + sgl++; + } + } + + return -1; +} + + +static int ParseExtension(const char *Ext, T_ExtInfo *ExtInfo) +{ + int i, mode; + const char *e, *t; + + + ExtInfo->OriginChoice = + ExtInfo->CellChoice = + ExtInfo->BasisChoice = ' '; + ExtInfo->BT_or_UA = ""; + + mode = 0; + + while (*Ext) + { + if (strchr("12", *Ext) != NULL) + { + ExtInfo->CellChoice = + ExtInfo->OriginChoice = *Ext++; + } + else if (strchr("3", *Ext) != NULL) + { + ExtInfo->CellChoice = *Ext++; + } + else if (strchr("Ss", *Ext) != NULL) + { + ExtInfo->OriginChoice = '1'; + Ext++; + } + else if (strchr("Zz", *Ext) != NULL) + { + ExtInfo->OriginChoice = '2'; + Ext++; + } + else if (strchr("Hh", *Ext) != NULL) + { + ExtInfo->BasisChoice = 'H'; + Ext++; + } + else if (strchr("Rr", *Ext) != NULL) + { + ExtInfo->BasisChoice = 'R'; + Ext++; + } + else if (mode == 0) + mode = 1; + + if (mode == 2) + break; + + for (i = 0; Ext_BT_or_UA[i]; i++) + { + for (e = Ext, t = Ext_BT_or_UA[i]; *t; e++, t++) + if (toupper(*e) != toupper(*t)) + break; + + if (*t == '\0') + { + if (6 <= i && i <= 8) + i = 2 * i - 11; + else if (9 <= i && i <= 20) + i = 9 + ((i - 9) / 4) * 4; + + ExtInfo->BT_or_UA = Ext_BT_or_UA[i]; + Ext = e; + break; + } + } + + if (mode == 0) + break; + + mode = 2; + } + + if (*Ext) + return -1; + + return 0; +} + + +static void ExpandMonoclinic(int unique_axis, const char *o, char *m) +{ + if (*o) *m++ = *o++; + + switch (tolower(unique_axis)) + { + case 'a': + while (*o) *m++ = *o++; + *m++ = '1'; + *m++ = '1'; + break; + case 'c': + *m++ = '1'; + *m++ = '1'; + while (*o) *m++ = *o++; + break; + default: + *m++ = '1'; + while (*o) *m++ = *o++; + *m++ = '1'; + break; + } + + *m = '\0'; +} + + +const T_TabSgName *FindTabSgNameEntry(const char *UserSgName, int VolLetter) +{ +#define MaxWtdLbl 20 + char WtdLblOriginal[MaxWtdLbl + 1]; + char WtdLblModified[MaxWtdLbl + 1]; + char *WtdLbl; +#define MaxWtdExt 5 + char WtdExt[MaxWtdExt + 1]; + int WtdSgNumber; + int WtdLblOriginChoice; + int WtdLblBasisChoice; + int iwl, iwe; + char *wl, *we; + + int i, IsExpanded, lbl_match; + const char *sgl; + const T_TabSgName *tsgn; + int WtdCC; + const char *WtdUA; + char WtdUA_Buf[2]; + T_ExtInfo ExtInfo, WtdExtInfo; + + + if (VolLetter == 0 || isspace(VolLetter)) + VolLetter = 'A'; + else if (VolLetter == '1') + VolLetter = 'I'; + else + { + VolLetter = toupper(VolLetter); + if ( VolLetter != 'I' + && VolLetter != 'A') + return NULL; + } + + WtdLbl = WtdLblOriginal; + + wl = WtdLbl; + iwl = 0; + + while (*UserSgName && *UserSgName != ':') + { + if (isspace(*UserSgName) == 0 && *UserSgName != '_') + { + if (iwl >= MaxWtdLbl) + return NULL; + + *wl++ = *UserSgName; + iwl++; + } + + UserSgName++; + } + + *wl = '\0'; + + if (iwl == 0) + return NULL; + + we = WtdExt; + iwe = 0; + *we = '\0'; + + if (*UserSgName) + { + UserSgName++; + + while (*UserSgName) + { + if (isspace(*UserSgName) == 0 && *UserSgName != '_') + { + if (iwe >= MaxWtdExt) + return NULL; + + *we++ = *UserSgName; + iwe++; + } + + UserSgName++; + } + } + + *we = '\0'; + + WtdLblOriginChoice = ' '; + WtdLblBasisChoice = ' '; + + if (iwl > 1) + { + wl = &WtdLbl[iwl - 1]; + + if (*wl == 'S' || *wl == 's') + { WtdLblOriginChoice = '1'; *wl = '\0'; iwl--; } + else if (*wl == 'Z' || *wl == 'z') + { WtdLblOriginChoice = '2'; *wl = '\0'; iwl--; } + else if (*wl == 'H' || *wl == 'h') + { WtdLblBasisChoice = 'H'; *wl = '\0'; iwl--; } + else if (*wl == 'R' || *wl == 'r') + { WtdLblBasisChoice = 'R'; *wl = '\0'; iwl--; } + } + + if (isalpha(WtdLbl[0])) + WtdSgNumber = FindSchoenfliesSymbol(WtdLbl); + else + { + for (wl = WtdLbl; *wl; wl++) + if (isdigit(*wl) == 0) + return NULL; + + if ( sscanf(WtdLbl, "%d", &WtdSgNumber) != 1 + || WtdSgNumber < 1 + || WtdSgNumber > 230) + return NULL; + } + + if (ParseExtension(WtdExt, &WtdExtInfo) != 0) + return NULL; + + if (WtdExtInfo.OriginChoice == ' ') + WtdExtInfo.OriginChoice = WtdLblOriginChoice; + else if (WtdExtInfo.OriginChoice != WtdLblOriginChoice + && WtdLblOriginChoice != ' ') + return NULL; + + if (WtdExtInfo.BasisChoice == ' ') + WtdExtInfo.BasisChoice = WtdLblBasisChoice; + else if (WtdExtInfo.BasisChoice != WtdLblBasisChoice + && WtdLblBasisChoice != ' ') + return NULL; + + if ( WtdExtInfo.OriginChoice != ' ' + && WtdExtInfo.BasisChoice != ' ') + return NULL; + + for (IsExpanded = 0; IsExpanded < 4; IsExpanded++) + { + for (tsgn = TabSgName; tsgn->HallSymbol; tsgn++) + { + if ( IsExpanded != 0 + && tsgn->SgNumber > 15) + break; + + lbl_match = 0; + + if (WtdSgNumber == -1) + { + i = 1; + sgl = tsgn->SgLabels; + while (*sgl && i <= 2) + { + while (*sgl && strchr(" =\t", *sgl) != NULL) sgl++; + + if (SgLabelCmp(tsgn->SgNumber, sgl, WtdLbl) == 0) + { + lbl_match = i; + break; + } + + while (*sgl && strchr(" =\t", *sgl) == NULL) sgl++; + + i++; + } + } + + if (ParseExtension(tsgn->Extension, &ExtInfo) != 0) { + SetSgError(IErr_Corrupt_TabSgName); + return NULL; + } + + if (WtdSgNumber == tsgn->SgNumber || lbl_match != 0) + { + if ( tsgn->SgNumber >= 3 + && tsgn->SgNumber < 16) + { + if ( WtdLblOriginChoice != ' ' + || WtdExtInfo.BasisChoice != ' ' + || (int) strlen(WtdExtInfo.BT_or_UA) > 2) + continue; /* next tsgn */ + + if (WtdSgNumber == tsgn->SgNumber) + { + if (WtdExtInfo.BT_or_UA[0]) + WtdUA = WtdExtInfo.BT_or_UA; + else if (VolLetter == 'I') + { + if ( ExtInfo.BT_or_UA[0] != 'c' + && ExtInfo.BT_or_UA[1] != 'c') + continue; /* next tsgn */ + + if ( ExtInfo.CellChoice == ' ' + && ( WtdExtInfo.CellChoice == ' ' + || WtdExtInfo.CellChoice == '1')) + return tsgn; + + i = 0; + for (sgl = tsgn->SgLabels; *sgl; sgl++) + if (*sgl == '=') i++; + + if ( i == 2 + && ( WtdExtInfo.CellChoice == ' ' + || WtdExtInfo.CellChoice == ExtInfo.CellChoice)) + return tsgn; + + continue; /* next tsgn */ + } + else + WtdUA = "b"; + } + else /* if (lbl_match != 0) */ + { + if (WtdExtInfo.BT_or_UA[0]) + WtdUA = WtdExtInfo.BT_or_UA; + else if (lbl_match > 1) + WtdUA = ExtInfo.BT_or_UA; + else if ( VolLetter == 'I' + && ExtInfo.CellChoice == ' ') + WtdUA = "c"; + else + WtdUA = "b"; + } + + if (WtdExtInfo.CellChoice != ' ') + WtdCC = WtdExtInfo.CellChoice; + else if (ExtInfo.CellChoice == '1') + WtdCC = ExtInfo.CellChoice; + else + WtdCC = ' '; + + if (strcmp(ExtInfo.BT_or_UA, WtdUA) == 0) + { + if (WtdCC == ' ' && lbl_match > 1) + return tsgn; + if (ExtInfo.CellChoice == WtdCC) + return tsgn; + if (ExtInfo.CellChoice == ' ' && WtdCC == '1') + return tsgn; + if (ExtInfo.CellChoice == '1' && WtdCC == ' ') + return tsgn; + } + } + else if (ExtInfo.BasisChoice != ' ') + { + if ( WtdExtInfo.OriginChoice != ' ' + || WtdExtInfo.CellChoice != ' ' + || WtdExtInfo.BT_or_UA[0] != '\0') + continue; /* next tsgn */ + + if (ExtInfo.BasisChoice == WtdExtInfo.BasisChoice) + return tsgn; + + if (WtdExtInfo.BasisChoice == ' ') + { + if (ExtInfo.BasisChoice == 'R' && VolLetter == 'I') + return tsgn; + if (ExtInfo.BasisChoice == 'H' && VolLetter != 'I') + return tsgn; + } + } + else if (WtdExtInfo.BasisChoice == ' ') + { + if ( (WtdExtInfo.OriginChoice == ' ' && ExtInfo.OriginChoice == '1') + || (WtdExtInfo.OriginChoice == '1' && ExtInfo.OriginChoice == ' ') + || WtdExtInfo.OriginChoice == ExtInfo.OriginChoice) + { + if (WtdExtInfo.BT_or_UA[0]) + { + if (WtdExtInfo.BT_or_UA == ExtInfo.BT_or_UA) + return tsgn; + if ( WtdExtInfo.BT_or_UA == Ext_BT_or_UA[0] + && ExtInfo.BT_or_UA[0] == '\0') + return tsgn; + } + else + { + if (lbl_match != 0) + return tsgn; + if (ExtInfo.BT_or_UA[0] == '\0') + return tsgn; + } + } + } + } + } + + if (WtdSgNumber != -1) + return NULL; + + if ((int) strlen(WtdExtInfo.BT_or_UA) > 2) + return NULL; + + if (IsExpanded == 0) + { + iwl += 2; + + if (iwl > MaxWtdLbl) + IsExpanded = 2; + else + { + if (WtdExtInfo.BT_or_UA[0]) + WtdUA = WtdExtInfo.BT_or_UA; + else + { + if (VolLetter == 'I') + WtdUA = "c"; + else + WtdUA = "b"; + } + + ExpandMonoclinic(WtdUA[0], WtdLblOriginal, WtdLblModified); + + WtdLbl = WtdLblModified; + } + } + else if (IsExpanded == 1) + { + if (WtdExtInfo.BT_or_UA[0]) + return NULL; + + if (VolLetter == 'I') + WtdUA = "b"; + else + WtdUA = "c"; + + ExpandMonoclinic(WtdUA[0], WtdLblOriginal, WtdLblModified); + } + + if (IsExpanded == 2) + { + if (WtdExtInfo.BT_or_UA[0]) + return NULL; + + iwl -= 2; + + if (iwl < 2) + return NULL; + iwl--; + WtdUA_Buf[0] = tolower(WtdLblOriginal[iwl]); + WtdLblOriginal[iwl] = '\0'; + WtdUA_Buf[1] = '\0'; + + if (strchr("abc", WtdUA_Buf[0]) == NULL) + return NULL; + + WtdUA = WtdUA_Buf; + + iwl += 2; + + if (iwl > MaxWtdLbl) + return NULL; + + ExpandMonoclinic(WtdUA[0], WtdLblOriginal, WtdLblModified); + + WtdLbl = WtdLblModified; + } + } + + return NULL; +} + + +unsigned int SgID_Number(const T_TabSgName *tsgn) +{ + unsigned int ID; + int iBT; + const char *UA; + T_ExtInfo ExtInfo; + + + ID = tsgn->SgNumber; + + if (ParseExtension(tsgn->Extension, &ExtInfo) != 0) + ID = 0; + + if (ID >= 3 && ID < 16) + { + UA = ExtInfo.BT_or_UA; + + if ( *UA != 'b' + || ( ExtInfo.CellChoice != ' ' + && ExtInfo.CellChoice != '1')) + { + if (*UA == '-') + { + ID += 3000; + UA++; + } + + switch (*UA) + { + case 'b': ID += 10000; break; + case 'c': ID += 20000; break; + case 'a': ID += 30000; break; + default: ID = 0; break; + } + + if (ID != 0) + { + switch (ExtInfo.CellChoice) + { + case ' ': break; + case '1': ID += 1000; break; + case '2': ID += 2000; break; + case '3': ID += 3000; break; + default: ID = 0; break; + } + } + } + } + else + { + if (ExtInfo.BasisChoice == 'R') + ID += 20000; + else + { + if (ExtInfo.BT_or_UA[0]) + { + for (iBT = 0; iBT < 6; iBT++) + if (ExtInfo.BT_or_UA == Ext_BT_or_UA[iBT]) + break; + } + else + iBT = 0; + + if (iBT < 6) + { + if (ExtInfo.OriginChoice == '2') ID += 20000; + else if (iBT) ID += 10000; + + if (iBT) + ID += (iBT + 1) * 1000; + } + else + ID = 0; + } + } + + if (ID == 0) + SetSgError(IErr_Corrupt_TabSgName); + + return ID; +} + + +int ParseSymXYZ(const char *SymXYZ, T_RTMx *SeitzMx, int FacTr) +{ + unsigned int P_mode; + int Row, Column, Sign, GotXYZ, i; + double Value, Value1, Value2, Delta; + + + for (i = 0; i < 12; i++) SeitzMx->a[i] = 0; + +#define P_Blank 0x01u +#define P_Comma 0x02u +#define P_Plus 0x04u +#define P_Dash 0x08u +#define P_Slash 0x10u +#define P_Value1 0x20u +#define P_Value2 0x40u +#define P_XYZ 0x80u + + Value1 = 0.; + + Row = 0; + Sign = 1; + Value = 0.; + GotXYZ = 0; + P_mode = P_Blank | P_Plus | P_Dash | P_Value1 | P_XYZ; + + do + { + switch (*SymXYZ) + { + case ' ': + case '\t': + case '_': + if ((P_mode & P_Blank) == 0) return -1; + break; + case ',': + case ';': + if (Row == 2) return -1; + case '\0': + if ((P_mode & P_Comma) == 0) return -1; + if (GotXYZ == 0) return -1; + if (P_mode & P_Slash) Value += Value1; + Value *= FacTr; + if (Value < 0.) i = Value - .5; + else i = Value + .5; + Delta = Value - i; + if (Delta < 0.) Delta = -Delta; + if (Delta > .01 * FacTr) return -1; + i %= FacTr; if (i < 0) i += FacTr; + SeitzMx->s.T[Row] = i; + Row++; + Sign = 1; + Value = 0.; + P_mode = P_Blank | P_Plus | P_Dash | P_Value1 | P_XYZ; + GotXYZ = 0; + break; + case '+': + if ((P_mode & P_Plus) == 0) return -1; + if (P_mode & P_Slash) Value += Value1; + Sign = 1; + if (P_mode & P_Value2) + P_mode = P_Value2; + else + P_mode = P_Blank | P_Value1 | P_XYZ; + break; + case '-': + if ((P_mode & P_Dash) == 0) return -1; + if (P_mode & P_Slash) Value += Value1; + Sign = -1; + if (P_mode & P_Value2) + P_mode = P_Value2; + else + P_mode = P_Blank | P_Value1 | P_XYZ; + break; + case '/': + case ':': + if ((P_mode & P_Slash) == 0) return -1; + Sign = 1; + P_mode = P_Blank | P_Plus | P_Dash | P_Value2; + break; + case '.': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (P_mode & P_Value1) + { + if (sscanf(SymXYZ, "%lf%n", &Value1, &i) != 1) return -1; + if (Sign == -1) Value1 = -Value1; + P_mode = P_Blank | P_Comma | P_Plus | P_Dash | P_Slash; + } + else if (P_mode & P_Value2) + { + if (sscanf(SymXYZ, "%lf%n", &Value2, &i) != 1) return -1; + if (Sign == -1) Value2 = -Value2; + if (Value1 != 0.) + { + if (Value2 == 0.) return -1; + Value += Value1 / Value2; + } + P_mode = P_Blank | P_Comma | P_Plus | P_Dash; + } + else + return -1; + SymXYZ += (i - 1); + break; + case 'X': + case 'x': Column = 0; goto Process_XYZ; + case 'Y': + case 'y': Column = 1; goto Process_XYZ; + case 'Z': + case 'z': Column = 2; + Process_XYZ: + if ((P_mode & P_XYZ) == 0) return -1; + i = Row * 3 + Column; + if (SeitzMx->s.R[i] != 0) return -1; + SeitzMx->s.R[i] = Sign; + GotXYZ = 1; + P_mode = P_Blank | P_Comma | P_Plus | P_Dash; + break; + } + } + while (*SymXYZ++); + + if (Row != 3) return -1; + + return 0; + +#undef P_Blank +#undef P_Comma +#undef P_Plus +#undef P_Dash +#undef P_Slash +#undef P_Value1 +#undef P_Value2 +#undef P_XYZ +} + + +static int LookupRotMx(T_HallGenerator *HG) +{ + int i, f, refaxis, dircode; + int iNextBasis, nNextBasis; + const T_TabXtalRotMx *txrmx; + + + if (HG->Rotation <= 0) return 0; + + refaxis = HG->RefAxis; + dircode = HG->DirCode; + + if (HG->Rotation == 1) + { + refaxis = 'o'; + dircode = '.'; + nNextBasis = 0; + } + else if (dircode == '*') + { + if (refaxis == 0) refaxis = 'o'; + nNextBasis = 0; + } + else + { + if (dircode == 0) dircode = '='; + + switch (refaxis) + { + case 'z': nNextBasis = 0; break; + case 'x': nNextBasis = 1; break; + case 'y': nNextBasis = 2; break; + default: + return 0; + } + } + + for (txrmx = TabXtalRotMx; txrmx->Order; txrmx++) + if (txrmx->Order == HG->Rotation) break; + + while (txrmx->Order == HG->Rotation) + { + if (txrmx->DirCode == dircode) + { + if (HG->Improper == 0) f = 1; + else f = -1; + + for (i = 0; i < 9; i++) + HG->SeitzMx.s.R[i] = txrmx->RMx[i] * f; + + for (iNextBasis = 0; iNextBasis < nNextBasis; iNextBasis++) + RotateRotMx(HG->SeitzMx.s.R, RMx_3_111, RMx_3i111); + + return 1; + } + + txrmx++; + } + + return 0; +} + + +int ParseHallSymbol(const char *hsym, T_SgInfo *SgInfo) +{ + int c, i, pos_hsym; + const int *ht; + int Centric; + const T_LatticeInfo *LatticeInfo; + int FieldType, PreviousFT; + int iOriginShift, SignOriginShift; + int digit, rotation, refaxis, dircode; + const int *translation; + int PreviousRotation, PreviousRefAxis; + int nHG, ClearHG; + T_HallGenerator HG; + + enum ListOfFieldTypes + { + FT_Delimiter, + FT_Improper, + FT_Digit, + FT_Rotation, + FT_RefAxis, + FT_DirCode, + FT_Translation, + FT_OriginShift + }; + + static const char *Err_Ill_ori_shi_val = + "Error: Illegal origin shift value"; + + static const char *Err_Too_ori_shi_val = + "Error: Too much origin shift values"; + + + Centric = 0; + LatticeInfo = NULL; + + HG.Rotation = HG.RefAxis = HG.DirCode = HG.Screw = 0; + + nHG = 0; + ClearHG = 1; + FieldType = FT_Delimiter; + PreviousRotation = 0; + PreviousRefAxis = 0; + iOriginShift = 0; + SignOriginShift = 0; + + pos_hsym = 0; + + do + { + if (*hsym == '_' || *hsym == '.' || *hsym == '\t' || *hsym == '\0') + c = ' '; + else + c = *hsym; + + pos_hsym++; + + if (LatticeInfo == NULL) + { + if (Centric == 0 && c == '-') + { + if (AddInversion2ListSeitzMx(SgInfo) < 0) + return pos_hsym; + Centric = 1; + } + else if (c != ' ') + { + c = toupper(c); + + switch (c) + { + case 'P': LatticeInfo = LI_P; break; + case 'A': LatticeInfo = LI_A; break; + case 'B': LatticeInfo = LI_B; break; + case 'C': LatticeInfo = LI_C; break; + case 'I': LatticeInfo = LI_I; break; + case 'R': LatticeInfo = LI_R; break; + case 'S': LatticeInfo = LI_S; break; + case 'T': LatticeInfo = LI_T; break; + case 'F': LatticeInfo = LI_F; break; + default: + SetSgError("Error: Illegal lattice code"); + return pos_hsym; + } + + if (AddLatticeTr2ListSeitzMx(SgInfo, LatticeInfo) < 0) + return pos_hsym; + } + } + else if (FieldType != FT_OriginShift) + { + c = tolower(c); + if (c == 'q') c = '\''; + else if (c == '+') c = '"'; + + PreviousFT = FieldType; + digit = rotation = refaxis = dircode = 0; + translation = NULL; + + ht = HallTranslations; + + while (*ht) + { + if (c == *ht) + { + translation = ht; + FieldType = FT_Translation; + break; + } + ht += 4; + } + + if (translation == NULL) + { + switch (c) + { + case ' ': FieldType = FT_Delimiter; break; + + case '-': FieldType = FT_Improper; break; + + case '1': digit = 1; FieldType = FT_Digit; break; + case '2': digit = 2; FieldType = FT_Digit; break; + case '3': digit = 3; FieldType = FT_Digit; break; + case '4': digit = 4; FieldType = FT_Digit; break; + case '5': digit = 5; FieldType = FT_Digit; break; + case '6': digit = 6; FieldType = FT_Digit; break; + + case 'x': + case 'y': + case 'z': refaxis = c; FieldType = FT_RefAxis; break; + + case '"': + case '\'': + case '*': dircode = c; FieldType = FT_DirCode; break; + + case '(': FieldType = FT_OriginShift; break; + + default: + SetSgError("Error: Illegal character in Hall symbol"); + return pos_hsym; + } + + if (FieldType == FT_Digit) + { + if ( ClearHG == 0 + && HG.Rotation > digit + && HG.Screw == 0 + && HG.DirCode == 0) + { + HG.Screw = digit; + FieldType = FT_Translation; + } + else if (digit == 5) + { + SetSgError("Error: Illegal 5-fold rotation"); + return pos_hsym; + } + else + { + rotation = digit; + FieldType = FT_Rotation; + } + } + } + + if ( ClearHG == 0 + && ( FieldType == FT_Delimiter + || FieldType == FT_OriginShift + || FieldType < PreviousFT + || (FieldType == PreviousFT && FieldType != FT_Translation)) + && ! ( FieldType == FT_RefAxis && HG.RefAxis == 0 + && PreviousFT == FT_DirCode)) + { + if (HG.RefAxis == 0) + { + if (nHG == 0) + HG.RefAxis = 'z'; + else + { + if (HG.Rotation == 2) + { + if (PreviousRotation == 2 || PreviousRotation == 4) + HG.RefAxis = 'x'; + else if (PreviousRotation == 3 || PreviousRotation == 6) + { + HG.RefAxis = PreviousRefAxis; + if (HG.DirCode == 0) HG.DirCode = '\''; + } + } + else if (HG.Rotation == 3) + { + if (HG.DirCode == 0) HG.DirCode = '*'; + } + } + } + + PreviousRefAxis = HG.RefAxis; + PreviousRotation = HG.Rotation; + + if (LookupRotMx(&HG) == 0) + { + SetSgError("Error: Illegal generator or need explicit axis symbol"); + return pos_hsym - 1; + } + + if (HG.Screw) + { + switch (HG.RefAxis) + { + case 'x': i = 0; break; + case 'y': i = 1; break; + case 'z': i = 2; break; + default: i = -1; break; + } + + if (HG.DirCode != 0 || i < 0) + { + SetSgError("Error: Screw for non-principal direction"); + return pos_hsym - 1; + } + + HG.SeitzMx.s.T[i] += STBF * HG.Screw / HG.Rotation; + } + + for (i = 0; i < 3; i++) + HG.SeitzMx.s.T[i] %= STBF; + + if (Add2ListSeitzMx(SgInfo, &HG.SeitzMx) < 0) + return pos_hsym - 1; + + if (SgInfo->StatusLatticeTr == -1) + { + if (AddLatticeTr2ListSeitzMx(SgInfo, SgInfo->LatticeInfo) < 0) + return pos_hsym - 1; + } + + nHG++; + ClearHG = 1; + } + + if (FieldType != FT_Delimiter && FieldType != FT_OriginShift) + { + if (ClearHG) + { + HG.Improper = 0; + HG.Rotation = 1; + HG.RefAxis = 0; + HG.DirCode = 0; + HG.Screw = 0; + for (i = 0; i < 12; i++) HG.SeitzMx.a[i] = 0; + + ClearHG = 0; + } + + switch (FieldType) + { + case FT_Improper: HG.Improper = 1; break; + case FT_Rotation: HG.Rotation = rotation; break; + case FT_RefAxis: HG.RefAxis = refaxis; break; + case FT_DirCode: HG.DirCode = dircode; break; + case FT_Translation: + if (translation != NULL) + { + for (i = 0; i < 3; i++) + HG.SeitzMx.s.T[i] += *(++translation); + } + break; + } + } + } + else /* FieldType == FT_OriginShift */ + { + if (iOriginShift > 3) { + SetSgError(Err_Too_ori_shi_val); + return pos_hsym; + } + + if (*hsym == '\0') c = ')'; + + digit = -1; + + switch (c) + { + case ' ': break; + + case ')': + if (iOriginShift != 3) + { + SetSgError("Error: Missing origin shift values"); + return pos_hsym; + } + iOriginShift++; + FieldType = FT_Delimiter; + break; + + case '-': + if (SignOriginShift != 0) { + SetSgError(Err_Ill_ori_shi_val); + return pos_hsym; + } + SignOriginShift = 1; + break; + + case '0': digit = 0; break; + case '1': digit = 1; break; + case '2': digit = 2; break; + case '3': digit = 3; break; + case '4': digit = 4; break; + case '5': digit = 5; break; + case '6': digit = 6; break; + + default: + SetSgError(Err_Ill_ori_shi_val); + return pos_hsym; + } + + if (digit >= 0) + { + if (iOriginShift >= 3) { + SetSgError(Err_Too_ori_shi_val); + return pos_hsym; + } + if (SignOriginShift) digit *= -1; + SignOriginShift = 0; + SgInfo->OriginShift[iOriginShift++] = digit; + } + } + } + while (*hsym++ != '\0'); + + if (LatticeInfo == NULL) { + SetSgError("Error: Lattice type not specified"); + return pos_hsym; + } + + return pos_hsym; +} + + +static const char *PrintSgLabel(const char *lbl, int space, int *n, + FILE *fpout) +{ + while (*lbl && *lbl != ' ') + { + if (*lbl == '_') + { + if (space) + { + putc(space, fpout); + if (n) (*n)++; + } + } + else + { + putc(*lbl, fpout); + if (n) (*n)++; + } + + lbl++; + } + + return lbl; +} + + +int PrintFullHM_SgName(const T_TabSgName *tsgn, int space, FILE *fpout) +{ + int n; + const char *lbl; + + + lbl = tsgn->SgLabels; + + if (tsgn->SgNumber >= 3 && tsgn->SgNumber < 16) + while (*lbl) if (*lbl++ == '=') break; + + SkipWhite(lbl); + + n = 0; + + PrintSgLabel(lbl, space, &n, fpout); + + lbl = tsgn->Extension; + + if (*lbl && strchr("12HhRr", *lbl)) + { + putc(':', fpout); + putc(*lbl, fpout); + n += 2; + } + + return n; +} + + +void PrintTabSgNameEntry(const T_TabSgName *tsgn, int Style, int space, + FILE *fpout) +{ + int n; + const char *lbl, *SfSymbol; + + + if (Style) + n = fprintf(fpout, "%3d", tsgn->SgNumber); + else + n = fprintf(fpout, "%d", tsgn->SgNumber); + + if (tsgn->Extension[0]) + n += fprintf(fpout, ":%s", tsgn->Extension); + + if (Style) + while (n < 9) { putc(' ', fpout); n++; } + + putc(' ', fpout); n++; + putc(' ', fpout); n++; + + if (tsgn->SgNumber >= 1 && tsgn->SgNumber <= 230) + SfSymbol = SchoenfliesSymbols[tsgn->SgNumber]; + else + SfSymbol = ""; + + n += fprintf(fpout, "%s", SfSymbol); + + if (Style) + while (n < 23) { putc(' ', fpout); n++; } + + putc(' ', fpout); n++; + putc(' ', fpout); n++; + + if (tsgn->SgNumber >= 3 && tsgn->SgNumber < 16) + { + lbl = PrintSgLabel(tsgn->SgLabels, space, &n, fpout); + + if (tsgn->Extension[0]) + n += fprintf(fpout, ":%s", tsgn->Extension); + + putc(' ', fpout); putc('=', fpout); putc(' ', fpout); n += 3; + + n += PrintFullHM_SgName(tsgn, space, fpout); + + while (*lbl) if (*lbl++ == '=') break; + while (*lbl) if (*lbl++ == '=') break; + SkipWhite(lbl); + + if (*lbl) + { + putc(' ', fpout); putc('=', fpout); putc(' ', fpout); n += 3; + + PrintSgLabel(lbl, space, &n, fpout); + } + } + else + n += PrintFullHM_SgName(tsgn, space, fpout); + + if (Style) + while (n < 51) { putc(' ', fpout); n++; } + + putc(' ', fpout); + putc(' ', fpout); + + fprintf(fpout, "%s", tsgn->HallSymbol); +} + + +static int FindGCD2(int ri, int rj) +{ + int rk; + + + if (ri < 0) ri = -ri; + + if (rj) + { + for (;;) + { + rk = ri % rj; if (rk == 0) { ri = rj; break; } + ri = rj % rk; if (ri == 0) { ri = rk; break; } + rj = rk % ri; if (rj == 0) { break; } + } + + if (ri < 0) ri = -ri; + } + + return ri; +} + + +static void SimplifyFraction(int nume, int deno, int *o_nume, int *o_deno) +{ + int gcd = FindGCD2(nume, deno); + if (gcd) + { + *o_nume = nume / gcd; + *o_deno = deno / gcd; + + if (*o_deno < 0) { + *o_nume *= -1; + *o_deno *= -1; + } + } +} + + +const char *FormatFraction(int nume, int deno, int Decimal, + char *Buffer, int SizeBuffer) +{ + int n, d; + char *cp, *cpp; + static char StaticBuffer[40]; + + + if (NULL == Buffer) { + Buffer = StaticBuffer; + SizeBuffer = sizeof StaticBuffer / sizeof (*StaticBuffer); + } + + Buffer[SizeBuffer - 1] = '\0'; + + if (nume == 0) + { + Buffer[0] = '0'; + Buffer[1] = '\0'; + } + if (Decimal) + { + sprintf(Buffer, "%.6g", (double) nume / deno); + + cp = Buffer; + if (*cp == '-') cp++; + if (*cp == '0') { + cpp = cp + 1; while (*cp) *cp++ = *cpp++; + } + } + else + { + SimplifyFraction(nume, deno, &n, &d); + + if (d == 1) + sprintf(Buffer, "%d", n); + else + sprintf(Buffer, "%d/%d", n, d); + } + + if (Buffer[SizeBuffer - 1] != '\0') { + Buffer[SizeBuffer - 1] = '\0'; + SetSgError("Internal Error: FormatFraction(): Buffer too small"); + return NULL; + } + + return Buffer; +} + + +const char *RTMx2XYZ(const T_RTMx *RTMx, int FacRo, int FacTr, + int Decimal, int TrFirst, int Low, + const char *Seperator, + char *BufferXYZ, int SizeBufferXYZ) +{ + static const char *UpperXYZ = "XYZ"; + static const char *LowerXYZ = "xyz"; + + int i, j, p, iRo, iTr; + char *xyz, buf_tr[32]; + const char *sep, *LetterXYZ, *ro, *tr; + + static char StaticBufferXYZ[80]; + + + if (NULL == BufferXYZ) { + BufferXYZ = StaticBufferXYZ; + SizeBufferXYZ = sizeof StaticBufferXYZ / sizeof (*StaticBufferXYZ); + } + + BufferXYZ[SizeBufferXYZ - 1] = '\0'; + + if (Low) + LetterXYZ = LowerXYZ; + else + LetterXYZ = UpperXYZ; + + if (Seperator == NULL) + Seperator = ","; + + xyz = BufferXYZ; + + for (i = 0; i < 3; i++) + { + if (i != 0) + for (sep = Seperator; *sep; sep++) *xyz++ = *sep; + + iTr = iModPositive(RTMx->s.T[i], FacTr); + if (iTr > FacTr / 2) + iTr -= FacTr; + + tr = FormatFraction(iTr, FacTr, Decimal, + buf_tr, sizeof buf_tr / sizeof (*buf_tr)); + if (tr == NULL) + return NULL; + + p = 0; + + if ( TrFirst && iTr) { + if (*tr) p = 1; + while (*tr) *xyz++ = *tr++; + } + + for (j = 0; j < 3; j++) + { + iRo = RTMx->s.R[i * 3 + j]; + if (iRo) + { + ro = FormatFraction(iRo, FacRo, Decimal, NULL, 0); + if (ro == NULL) + return NULL; + + if (*ro == '-') + *xyz++ = *ro++; + else if (*ro && p) + *xyz++ = '+'; + + if (ro[0] != '1' || ro[1] != '\0') { + while (*ro) *xyz++ = *ro++; + *xyz++ = '*'; + } + + *xyz++ = LetterXYZ[j]; + + p = 1; + } + } + + if (! TrFirst && iTr) + { + if (*tr && *tr != '-' && p) + *xyz++ = '+'; + + while (*tr) *xyz++ = *tr++; + } + } + + *xyz = '\0'; + + if (BufferXYZ[SizeBufferXYZ - 1] != '\0') { + BufferXYZ[SizeBufferXYZ - 1] = '\0'; + SetSgError("Internal Error: RTMx2XYZ(): BufferXYZ too small"); + return NULL; + } + + return BufferXYZ; +} + + +void PrintMapleRTMx(const T_RTMx *RTMx, int FacRo, int FacTr, + const char *Label, FILE *fpout) +{ + int i, j, nt; + const int *r, *t; + const char *ff; + + + if (Label) + fprintf(fpout, "%s", Label); + + fprintf(fpout, " := matrix(4,4, ["); + + r = RTMx->s.R; + t = RTMx->s.T; + + for (i = 0; i < 3; i++, t++) + { + putc(' ', fpout); + + for (j = 0; j < 3; j++, r++) + { + ff = FormatFraction(*r, FacRo, 0, NULL, 0); + if (ff == NULL) + return; + + fprintf(fpout, "%s,", ff); + } + + nt = iModPositive(*t, FacTr); + if (nt > FacTr / 2) + nt -= FacTr; + + ff = FormatFraction(nt, FacTr, 0, NULL, 0); + if (ff == NULL) + return; + + fprintf(fpout, "%s,", ff); + } + + fprintf(fpout, " 0,0,0,1]);\n"); +} + + +static void PrintSeitzMx(const T_RTMx *SMx, FILE *fpout) +{ + int i, nt; + const char *ff; + const int *r, *t; + + + r = SMx->s.R; + t = SMx->s.T; + + for (i = 0; i < 3; i++) + { + fprintf(fpout, " %2d", *r++); + fprintf(fpout, " %2d", *r++); + fprintf(fpout, " %2d", *r++); + + nt = iModPositive(*t++, STBF); + if (nt > STBF / 2) + nt -= STBF; + + ff = FormatFraction(nt, STBF, 0, NULL, 0); + if (ff == NULL) + return; + + fprintf(fpout, " %6s\n", ff); + } + + putc('\n', fpout); +} + + +void ListSgInfo(const T_SgInfo *SgInfo, int F_XYZ, int F_Verbose, FILE *fpout) +{ + int iList, i_si_v; + char buf[8]; + const char *xyz; + const T_RTMx *lsmx; + T_RotMxInfo *rmxi, RotMxInfo; + + + iList = PG_Index(SgInfo->PointGroup); + + fprintf(fpout, "Point Group %s\n", PG_Names[iList]); + fprintf(fpout, "Laue Group %s\n", + PG_Names[PG_Index(LG_Code_of_PG_Index[iList])]); + + fprintf(fpout, "%s\n", XS_Name[SgInfo->XtalSystem]); + + if (SgInfo->UniqueRefAxis != 0 || SgInfo->UniqueDirCode != 0) + { + fprintf(fpout, "Unique Axis "); + if (SgInfo->UniqueRefAxis != 0 && SgInfo->UniqueRefAxis != 'o') + fprintf(fpout, "%c", SgInfo->UniqueRefAxis); + if (SgInfo->UniqueDirCode != 0 && SgInfo->UniqueDirCode != '=') + fprintf(fpout, "%c", SgInfo->UniqueDirCode); + fprintf(fpout, "\n"); + } + + if (SgInfo->ExtraInfo != EI_Unknown) + fprintf(fpout, "%s\n", EI_Name[SgInfo->ExtraInfo]); + + if (SgInfo->InversionOffOrigin) + fprintf(fpout, "Note: Inversion operation off origin\n"); + + putc('\n', fpout); + + fprintf(fpout, "Order %3d\n", SgInfo->OrderL); + fprintf(fpout, "Order P %3d\n", SgInfo->OrderP); + putc('\n', fpout); + + if (SgInfo->n_si_Vector >= 0) + { + fprintf(fpout, "s.i.Vector Modulus\n"); + for (i_si_v = 0; i_si_v < SgInfo->n_si_Vector; i_si_v++) + fprintf(fpout, " %2d %2d %2d %d\n", + SgInfo->si_Vector[i_si_v * 3 + 0], + SgInfo->si_Vector[i_si_v * 3 + 1], + SgInfo->si_Vector[i_si_v * 3 + 2], + SgInfo->si_Modulus[i_si_v]); + putc('\n', fpout); + } + + if (F_XYZ || F_Verbose) + { + fprintf(fpout, "#List %3d\n", SgInfo->nList); + putc('\n', fpout); + + lsmx = SgInfo->ListSeitzMx; + rmxi = SgInfo->ListRotMxInfo; + + if (rmxi == NULL) rmxi = &RotMxInfo; + + for (iList = 0; iList < SgInfo->nList; iList++, lsmx++) + { + if (rmxi == &RotMxInfo) + { + if (GetRotMxInfo(lsmx->s.R, &RotMxInfo) == 0) { + SetSgError("Error: Illegal SeitzMx in list"); + return; + } + } + + if (F_Verbose) + { + sprintf(buf, "(%d)", iList + 1); + fprintf(fpout, "%-4s", buf); + + fprintf(fpout, " %2d", rmxi->Order); + if (rmxi->Inverse) fprintf(fpout, "^-1"); + else fprintf(fpout, " "); + + fprintf(fpout, " [%2d %2d %2d]", + rmxi->EigenVector[0], + rmxi->EigenVector[1], + rmxi->EigenVector[2]); + + if (rmxi->RefAxis) fprintf(fpout, " '%c'", rmxi->RefAxis); + else fprintf(fpout, " "); + if (rmxi->DirCode) fprintf(fpout, " '%c'", rmxi->DirCode); + else fprintf(fpout, " "); + + fprintf(fpout, " "); + } + + xyz = RTMx2XYZ(lsmx, 1, STBF, 0, 0, 1, ", ", NULL, 0); + if (xyz) + fprintf(fpout, "%s", xyz); + + putc('\n', fpout); + + if (xyz == NULL) + return; + + if (F_Verbose) + PrintSeitzMx(lsmx, fpout); + + if (rmxi != &RotMxInfo) rmxi++; + } + + if (iList && F_Verbose == 0) + putc('\n', fpout); + } +} diff --git a/sgsi.c b/sgsi.c new file mode 100644 index 00000000..aaf13f02 --- /dev/null +++ b/sgsi.c @@ -0,0 +1,445 @@ +/* + Space Group Info's (c) 1994-96 Ralf W. Grosse-Kunstleve + */ + +#include +#include + + +#ifdef APP_INCLUDE +#include APP_INCLUDE +#endif + +#ifndef AppMalloc +#define AppMalloc(ptr, n) (ptr) = malloc((n) * sizeof (*(ptr))) +#endif +#ifndef AppFree +#define AppFree(ptr, n) free(ptr) +#endif + + +#include "sginfo.h" + + +/* Non elegant way to get s.i. vectors and moduli: + 1. Build field with legal reference points marked (TestField) + 2. Go through list of possible s.i. vects and mods: + Verify with TestField + */ + + +void MarkLegalOrigins(const T_SgInfo *SgInfo, int *TestField) +{ + int O[3], V[3], lx, ly, lz, mx, my, mz, i; + int IsFine, iList, iLoopInv, nLoopInv; + int BufMx[9]; + const T_RTMx *lsmx; + int nTrV, iTrV; + const int *TrV; + + + nLoopInv = Sg_nLoopInv(SgInfo); + + nTrV = SgInfo->LatticeInfo->nTrVector; + + switch (SgInfo->LatticeInfo->Code) + { + default: + case 'P': lx = ly = lz = 12; break; + case 'A': lx = ly = 12; lz = 6; break; + case 'B': ly = lz = 12; lx = 6; break; + case 'C': lz = lx = 12; ly = 6; break; + case 'I': lx = ly = 12; lz = 6; break; + case 'R': lx = ly = 12; lz = 4; break; + case 'S': lz = lx = 12; ly = 4; break; + case 'T': ly = lz = 12; lx = 4; break; + case 'F': lx = 12; ly = lz = 6; break; + } + + for (O[0] = 0; O[0] < 12; O[0]++) + for (O[1] = 0; O[1] < 12; O[1]++) + for (O[2] = 0; O[2] < 12; O[2]++) + { + IsFine = 1; + + for (iList = 0; IsFine && iList < SgInfo->nList; iList++) + { + lsmx = &SgInfo->ListSeitzMx[iList]; + + for (iLoopInv = 0; IsFine && iLoopInv < nLoopInv; iLoopInv++) + { + if (iLoopInv == 0) + for (i = 0; i < 9; i++) + { + if (i % 4) BufMx[i] = lsmx->s.R[i]; + else BufMx[i] = lsmx->s.R[i] - 1; + } + else + for (i = 0; i < 9; i++) + { + if (i % 4) BufMx[i] = -lsmx->s.R[i]; + else BufMx[i] = -lsmx->s.R[i] - 1; + } + + RotMx_t_Vector(V, BufMx, O, 12); + + TrV = SgInfo->LatticeInfo->TrVector; + + for (iTrV = 0; iTrV < nTrV; iTrV++) + { + mx = (V[0] * (STBF / 12) + *TrV++) % STBF; + my = (V[1] * (STBF / 12) + *TrV++) % STBF; + mz = (V[2] * (STBF / 12) + *TrV++) % STBF; + + if (mx == 0 && my == 0 && mz == 0) + break; + } + + if (iTrV == nTrV) IsFine = 0; + } + } + + if (! (O[0] < lx && O[1] < ly && O[2] < lz)) + IsFine = -IsFine; + + *TestField++ = IsFine; + +#if DEBUG_MarkLegalOrigins + if (IsFine == 1) putc(' ', stdout); + else if (IsFine == -1) putc('#', stdout); + if (IsFine != 0) + fprintf(stdout, " %2d %2d %2d\n", O[0], O[1], O[2]); +#endif + } +} + + +#define IsArbitraryShift(iShift) \ + ( (iShift) == 1 || (iShift) == 5 \ + || (iShift) == 7 || (iShift) == 11) + + +int Verify_si(int h, int k, int l, const int *TestField) +{ + int O[3], TH; + + + for (O[0] = 0; O[0] < 12; O[0]++) + for (O[1] = 0; O[1] < 12; O[1]++) + for (O[2] = 0; O[2] < 12; O[2]++) + { + if (*TestField++) + { + TH = h * O[0] + k * O[1] + l * O[2]; + TH %= 12; + if (TH) return 0; + + if (IsArbitraryShift(O[0])) TH += h; + if (IsArbitraryShift(O[1])) TH += k; + if (IsArbitraryShift(O[2])) TH += l; + if (TH) return 0; + } + } + + return 1; +} + + +int Is_si(const T_SgInfo *SgInfo, int h, int k, int l) +{ + int i_si_v, u; + const int *si_v, *si_m; + + + si_v = SgInfo->si_Vector; + si_m = SgInfo->si_Modulus; + + for (i_si_v = 0; i_si_v < SgInfo->n_si_Vector; i_si_v++) + { + u = *si_v++ * h; + u += *si_v++ * k; + u += *si_v++ * l; + + if (*si_m) { + if (u % (*si_m)) return 0; } + else { + if (u) return 0; } + + si_m++; + } + + return 1; +} + + +int Set_si(T_SgInfo *SgInfo) +{ + static const int TabTrial_si[] = + { + 0, + + 1, 0, 2, -1, 4, /* I -4 */ + 1, 2, -1, 0, 4, + 1, -1, 0, 2, 4, + + 1, 2, 4, 3, 6, /* P 3 2 */ + 1, 4, 3, 2, 6, + 1, 3, 2, 4, 6, + + 1, 1, 1, 1, 4, + 1, 1, 1, 1, 2, + 1, 1, 1, 1, 0, + + 1, 0, 0, 1, 2, + 1, 0, 1, 0, 2, + 1, 1, 0, 0, 2, + + 1, 0, 0, 1, 0, + 1, 0, 1, 0, 0, + 1, 1, 0, 0, 0, + + 2, 1, -1, 0, 3, + 0, 0, 1, 0, + 2, -1, 0, 1, 3, + 0, 1, 0, 0, + 2, 0, 1, -1, 3, + 1, 0, 0, 0, + + 2, 0, 1, 1, 4, /* F 2x */ + 1, 0, 0, 0, + 2, 1, 0, 1, 4, /* F 2y */ + 0, 1, 0, 0, + 2, 1, 1, 0, 4, /* F 2z */ + 0, 0, 1, 0, + + 2, 1, 0, 0, 2, + 0, 0, 1, 2, + 2, 0, 1, 0, 2, + 0, 0, 1, 2, + 2, 1, 0, 0, 2, + 0, 1, 0, 2, + + 2, 1, 1, 0, 2, + 0, 0, 1, 2, + 2, 1, 0, 1, 2, + 0, 1, 0, 2, + 2, 0, 1, 1, 2, + 1, 0, 0, 2, + + 2, 1, 0, 0, 2, + 0, 0, 1, 0, + 2, 0, 1, 0, 2, + 0, 0, 1, 0, + 2, 1, 0, 0, 2, + 0, 1, 0, 0, + + 2, 1, 0, 0, 0, + 0, 0, 1, 2, + 2, 0, 1, 0, 0, + 0, 0, 1, 2, + 2, 1, 0, 0, 0, + 0, 1, 0, 2, + + 2, 1, 1, 0, 2, + 0, 0, 1, 0, + 2, 1, 0, 1, 2, + 0, 1, 0, 0, + 2, 0, 1, 1, 2, + 1, 0, 0, 0, + + 2, 1, 0, 0, 0, + 0, 0, 1, 0, + 2, 0, 1, 0, 0, + 0, 0, 1, 0, + 2, 1, 0, 0, 0, + 0, 1, 0, 0, + + 3, 1, 0, 0, 2, + 0, 1, 0, 2, + 0, 0, 1, 2, + + 3, 1, 0, 0, 0, + 0, 1, 0, 2, + 0, 0, 1, 2, + + 3, 1, 0, 0, 2, + 0, 1, 0, 0, + 0, 0, 1, 2, + + 3, 1, 0, 0, 2, + 0, 1, 0, 2, + 0, 0, 1, 0, + + 3, 1, 0, 0, 2, + 0, 1, 0, 0, + 0, 0, 1, 0, + + 3, 1, 0, 0, 0, + 0, 1, 0, 2, + 0, 0, 1, 0, + + 3, 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 2, + + 3, 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + + 3, -1, 0, 0, 2, /* -A 1 */ + 0, -1, 1, 4, + 0, 1, 1, 4, + + 3, -1, 0, 1, 4, /* -B 1 */ + 0, -1, 0, 2, + 1, 0, 1, 4, + + 3, 1, 1, 0, 4, /* -C 1 */ + 1, -1, 0, 4, + 0, 0, -1, 2, + + 3, -1, 1, 1, 4, /* -I 1 */ + 1, -1, 1, 4, + 1, 1, -1, 4, + + 3, 0, 1, 1, 4, /* -F 1 */ + 1, 0, 1, 4, + 1, 1, 0, 4, + + 3, -1, 0, 0, 0, /* A 2x */ + 0, -1, 1, 4, + 0, 1, 1, 4, + + 3, -1, 0, 1, 4, /* B 2y */ + 0, -1, 0, 0, + 1, 0, 1, 4, + + 3, 1, 1, 0, 4, /* C 2z */ + 1, -1, 0, 4, + 0, 0, -1, 0, + + -1 + }; + + int h, k, l, iList; + int Maxh, Maxk, Maxl; + int Minh, Mink, Minl; + int nTestField, *TestField; + int nProperty, *Property, *pp; + int IsFine, would_be, is; + int i_si, *si_v; + const int *trial_si; + + + SgInfo->n_si_Vector = -1; + + nTestField = 12 * 12 * 12; + AppMalloc(TestField, nTestField); + if (TestField == NULL) { + SetSgError("Not enough core"); + return -1; + } + + MarkLegalOrigins(SgInfo, TestField); + + Maxh = Maxk = Maxl = 7; + SetListMin_hkl(SgInfo, Maxk, Maxl, &Minh, &Mink, &Minl); + + nProperty = (Maxh - Minh + 1) + * (Maxk - Mink + 1) + * (Maxl - Minl + 1); + AppMalloc(Property, nProperty); + if (Property == NULL) { + SetSgError("Not enough core"); + AppFree(TestField, nTestField); + return -1; + } + + pp = Property; + for (h = Minh; h <= Maxh; h++) + for (k = Mink; k <= Maxk; k++) + for (l = Minl; l <= Maxl; l++) + { + iList = IsSysAbsent_hkl(SgInfo, h, k, l, NULL); + if (SgError != NULL) + { + AppFree(Property, nProperty); + AppFree(TestField, nTestField); + return -1; + } + + if (iList == 0) + *pp++ = Verify_si(h, k, l, TestField); + else + *pp++ = -1; + } + + trial_si = TabTrial_si; + while (*trial_si >= 0) + { + SgInfo->n_si_Vector = *trial_si++; + si_v = SgInfo->si_Vector; + for (i_si = 0; i_si < SgInfo->n_si_Vector; i_si++) + { + *si_v++ = *trial_si++; + *si_v++ = *trial_si++; + *si_v++ = *trial_si++; + SgInfo->si_Modulus[i_si] = *trial_si++; + } + + IsFine = 1; + + pp = Property; + for (h = Minh; IsFine && h <= Maxh; h++) + for (k = Mink; IsFine && k <= Maxk; k++) + for (l = Minl; IsFine && l <= Maxl; l++) + { + is = *pp++; + + if (is >= 0) + { + would_be = Is_si(SgInfo, h, k, l); + if (is != would_be) + IsFine = 0; + } + } + + if (IsFine) + { + AppFree(Property, nProperty); + AppFree(TestField, nTestField); + return 0; + } + } + + SgInfo->n_si_Vector = -1; + SetSgError("Internal Error: Can't determine s.i. vectors and moduli"); + + AppFree(Property, nProperty); + AppFree(TestField, nTestField); + + return -1; +} + + +void Set_uvw(const T_SgInfo *SgInfo, int h, int k, int l, int *uvw) +{ + int i_si_v, u; + const int *si_v, *si_m; + + + si_v = SgInfo->si_Vector; + si_m = SgInfo->si_Modulus; + + for (i_si_v = 0; i_si_v < SgInfo->n_si_Vector; i_si_v++) + { + u = *si_v++ * h; + u += *si_v++ * k; + u += *si_v++ * l; + + if (*si_m) u %= (*si_m); + si_m++; + + uvw[i_si_v] = u; + } +} diff --git a/sicscron.c b/sicscron.c index 38585f38..dcb34795 100644 --- a/sicscron.c +++ b/sicscron.c @@ -78,7 +78,7 @@ StatisticsEnd(old); MacroPop(); if (iRet != TCL_OK) { - SCPrintf(self->pCon, eStatus, + SCPrintf(self->pCon, eLogError, "ERROR in sicscron script: %s", pTcl->result); self->iEnd = 0; return 0; @@ -114,12 +114,12 @@ if (self->iEnd == 2 && data->dolater) { tm = *localtime(&self->tNext); strftime(datim, sizeof datim, "%Y-%m-%d %T", &tm); - SCPrintf(data->pCon, eStatus, "%s %s", datim, + SCPrintf(data->pCon, eLog, "%s %s", datim, self->pCommand); } else if (self->iEnd == 1 && !data->dolater) { tm = *localtime(&self->tNext); strftime(datim, sizeof datim, "%Y-%m-%d %T", &tm); - SCPrintf(data->pCon, eStatus, "%s %8d %s", datim, + SCPrintf(data->pCon, eLog, "%s %8d %s", datim, self->iInterval, self->pCommand); } } diff --git a/sicshdbadapter.c b/sicshdbadapter.c index ba287ea7..bc0f59c0 100644 --- a/sicshdbadapter.c +++ b/sicshdbadapter.c @@ -53,8 +53,7 @@ static void AddPrivProperty(pHdb node, int priv){ SetHdbProperty(node,PRIVNAM,pPriv); } /*=================== motor code =======================================*/ -static int MoveCallback(int iEvent, void *eventData, void *userData, - commandContext cc){ +static int MoveCallback(int iEvent, void *eventData, void *userData){ MotCallback *motData = (MotCallback *)eventData; pHdb motor = (pHdb)userData; pHdb pos = NULL; @@ -71,8 +70,7 @@ static int MoveCallback(int iEvent, void *eventData, void *userData, return 1; } /*---------------------------------------------------------------------*/ -static int MotorValueCallback(int iEvent, void *eventData, void *userData, - commandContext cc){ +static int MotorValueCallback(int iEvent, void *eventData, void *userData){ pHdb motor = (pHdb)userData; pMotor pMot = (pMotor)eventData; pHdb current = NULL; @@ -280,9 +278,9 @@ static pHdb CreateMotorAdapter(char *name, pMotor pMot){ */ strncpy(comCom.deviceID,name,255); comCom.transID = -77; - RegisterCallback(pMot->pCall,comCom, MOTDRIVE, MoveCallback, + RegisterCallback(pMot->pCall,MOTDRIVE, MoveCallback, result,NULL); - RegisterCallback(pMot->pCall,comCom, HDBVAL, MotorValueCallback, + RegisterCallback(pMot->pCall,HDBVAL, MotorValueCallback, result,NULL); if(!AddStdMotorPar(result,pMot)){ @@ -396,8 +394,7 @@ static hdbCallbackReturn SicsVarSetCallback(pHdb currentNode, void *userData, return hdbContinue; } /*----------------------------------------------------------------------*/ -static int ValueCallback(int iEvent, void *eventData, void *userData, - commandContext cc){ +static int ValueCallback(int iEvent, void *eventData, void *userData){ pSicsVariable pVar = (pSicsVariable)eventData; pHdb node = (pHdb)userData; hdbValue v; @@ -451,10 +448,8 @@ static pHdb MakeSicsVarNode(pSicsVariable pVar, char *name){ if(pCall == NULL){ return NULL; } - strncpy(comCom.deviceID,name,255); - comCom.transID = -77; AppendHipadabaCallback(node,pCall); - RegisterCallback(pVar->pCall,comCom, VALUECHANGE, ValueCallback, + RegisterCallback(pVar->pCall,VALUECHANGE, ValueCallback, node,NULL); snprintf(command,1023,"%s ", pVar->name); SetHdbProperty(node,"sicscommand",command); @@ -503,8 +498,7 @@ static void updateCountList(){ SCDeleteConnection(pDummy); } /*---------------------------------------------------------------------------*/ -static int CounterCallback(int iEvent, void *eventData, void *userData, - commandContext cc){ +static int CounterCallback(int iEvent, void *eventData, void *userData){ if(iEvent == MONITOR || iEvent == COUNTEND){ updateCountList(); } @@ -714,13 +708,13 @@ int SICSHdbAdapter(SConnection *pCon, SicsInterp *pSics, void *pData, hugo.node = path; if(countList < 0){ countList = LLDcreate(sizeof(CountEntry)); - RegisterCallback(pCount->pCall, SCGetContext(pCon), + RegisterCallback(pCount->pCall, COUNTSTART, CounterCallback, NULL, NULL); - RegisterCallback(pCount->pCall, SCGetContext(pCon), + RegisterCallback(pCount->pCall, COUNTEND, CounterCallback, NULL, NULL); - RegisterCallback(pCount->pCall, SCGetContext(pCon), + RegisterCallback(pCount->pCall, MONITOR, CounterCallback, NULL, NULL); } diff --git a/sicshdbfactory.c b/sicshdbfactory.c index aca0ed08..b1856f78 100644 --- a/sicshdbfactory.c +++ b/sicshdbfactory.c @@ -175,6 +175,7 @@ static int MakeLinkNode(pHdb parent, char *name, SConnection *pCon, assert(pInter); /* print command to log files */ + /* for( i = 0; i < self->iFiles; i++) { if(self->pFiles[i]) @@ -182,7 +183,8 @@ static int MakeLinkNode(pHdb parent, char *name, SConnection *pCon, fprintf(self->pFiles[i],"SICS>> %s\n",pCommand); } } - + */ + /* print to command log if user or manager */ if(SCGetRights(self) <= usUser) { @@ -218,7 +220,7 @@ static hdbCallbackReturn CommandSetCallback(pHdb node, void *userData, if((mm = GetHdbSetMessage(message)) == NULL){ return hdbContinue; } - pCon = (SConnection *)pCon; + pCon = (SConnection *)mm->callData; v = *(mm->v); if(pCon == NULL){ @@ -245,7 +247,9 @@ static hdbCallbackReturn CommandSetCallback(pHdb node, void *userData, } current = current->next; } + SendHdbStatusMessage(node,"start"); status = HDBInvoke(pCon,pServ->pSics, GetCharArray(cmd)); + SendHdbStatusMessage(node,"stop"); DeleteDynString(cmd); if(status == 1){ return hdbContinue; diff --git a/sicshipadaba.c b/sicshipadaba.c index 8aca6d6c..22c9dfe0 100644 --- a/sicshipadaba.c +++ b/sicshipadaba.c @@ -17,6 +17,8 @@ * interpreter interface. * * Refactored to new callback system, Markus Zolliker, Mark Koennecke, March 2008 + * + * Added start and finished messages to commands. Mark Koennecke, November 2008 */ #include #include @@ -47,6 +49,8 @@ char *trim(char *str); static char killID[] = {"killID"}; static char killInternalID[] = {"killInternalID"}; static char killPtr[] = {"killPtr"}; +static char startID[] = {"start"}; +static char stopID[] = {"stop"}; /*----------------------------------------------------------------------------------*/ pHdbIDMessage GetKillIDMessage(pHdbMessage message){ if(message->type == killID){ @@ -68,7 +72,38 @@ pHdbPtrMessage GetKillPtrMessage(pHdbMessage message){ } return NULL; } - +/*-----------------------------------------------------------------------------------*/ +pHdbMessage GetHdbStartMessage(pHdbMessage message){ + if(message->type == startID){ + return (pHdbMessage)message; + } + return NULL; +} +/*-----------------------------------------------------------------------------------*/ +pHdbMessage GetHdbStopMessage(pHdbMessage message){ + if(message->type == stopID){ + return (pHdbMessage)message; + } + return NULL; +} +/*-----------------------------------------------------------------------------------*/ +void SendHdbStatusMessage(pHdb node, char *status){ + pHdbMessage pRes = NULL; + pRes = malloc(sizeof(hdbMessage)); + if(pRes == NULL){ + return; + } + if(strcmp(status,"start") == 0){ + pRes->type = startID; + } else if(strcmp(status,"stop") == 0){ + pRes->type = stopID; + } else { + /* someone is trying to create an non existent message */ + assert(0); + } + InvokeCallbackChain(node,pRes); + free(pRes); +} /*=============== common callback functions used for SICS ===========================*/ static hdbCallbackReturn SICSCheckPermissionCallback(pHdb node, void *userData, pHdbMessage message){ @@ -274,8 +309,10 @@ static hdbCallbackReturn SICSFuncCallback(pHdb node, void *userData, } func = (SICSOBJFunc)node->value.v.func; if(func != NULL){ + SendHdbStatusMessage(node, "start"); status = func((pSICSOBJ)userData,(SConnection *)mm->callData, node, par,nPar); + SendHdbStatusMessage(node, "stop"); } else { printf("Great Badness in calling SICSFuncCallback\n"); return hdbAbort; @@ -297,7 +334,6 @@ pHdbCallback MakeSICSReadDriveCallback(void *sicsObject){ /*---------------------------------------------------------------------------------------*/ typedef struct { SConnection *pCon; - commandContext context; int ID; int internalID; }HdbCBInfo; @@ -438,6 +474,7 @@ static hdbCallbackReturn SICSNotifyCallback(pHdb node, void *userData, pHdbIDMessage idm = NULL; pHdbPtrMessage cmm = NULL; pHdbDataMessage mm = NULL; + SConnection *tstCon; cbInfo = (HdbCBInfo *)userData; @@ -459,15 +496,41 @@ static hdbCallbackReturn SICSNotifyCallback(pHdb node, void *userData, } } if((cmm = GetKillPtrMessage(message)) != NULL){ - if(cmm->pPtr == cbInfo->pCon){ + tstCon = cmm->pPtr; + if(tstCon != NULL && tstCon->ident == cbInfo->pCon->ident){ return hdbKill; } else { return hdbContinue; } } + /** + * handle start and stop messages + */ + if(GetHdbStartMessage(message) != NULL){ + pPath = GetHipadabaPath(node); + result = CreateDynString(128,128); + DynStringConcat(result, pPath); + DynStringConcat(result," STARTED"); + SCWrite(cbInfo->pCon, GetCharArray(result), eEvent); + DeleteDynString(result); + free(pPath); + return hdbContinue; + } + + if(GetHdbStopMessage(message) != NULL){ + pPath = GetHipadabaPath(node); + result = CreateDynString(128,128); + DynStringConcat(result, pPath); + DynStringConcat(result," FINISHED"); + SCWrite(cbInfo->pCon, GetCharArray(result), eEvent); + DeleteDynString(result); + free(pPath); + return hdbContinue; + } + /* - * react only on update messages + * Deal with update messages */ if((mm = GetHdbUpdateMessage(message)) == NULL){ return hdbContinue; @@ -481,20 +544,12 @@ static hdbCallbackReturn SICSNotifyCallback(pHdb node, void *userData, outCode = eEvent; - /* - * we want our notifications to come even when called from a macro - */ - macro = SCinMacro(cbInfo->pCon); - SCsetMacro(cbInfo->pCon,0); /** * if transfer = zip always transfer data in zipped form */ if(GetHdbProperty(node,"transfer",value,80) == 1){ if(strstr(value,"zip") != NULL){ - SCPushContext2(cbInfo->pCon,cbInfo->context); status = sendZippedNodeData(node, cbInfo->pCon); - SCPopContext(cbInfo->pCon); - SCsetMacro(cbInfo->pCon,macro); free(pPath); DeleteDynString(result); return hdbContinue; @@ -503,9 +558,8 @@ static hdbCallbackReturn SICSNotifyCallback(pHdb node, void *userData, if(mm->v->arrayLength < 100){ printedData = formatValue(*(mm->v), node); if(pPath == NULL || printedData == NULL || result == NULL){ - SCWriteInContext(cbInfo->pCon,"ERROR: out of memory formatting data" , - eEvent,cbInfo->context); - SCsetMacro(cbInfo->pCon,macro); + SCWrite(cbInfo->pCon,"ERROR: out of memory formatting data" , + eEvent); /* * no need to interrupt something because writing data to a client does * not work @@ -514,33 +568,46 @@ static hdbCallbackReturn SICSNotifyCallback(pHdb node, void *userData, } formatNameValue(protocol, pPath, GetCharArray(printedData), result, mm->v->dataType); - SCWriteInContext(cbInfo->pCon,GetCharArray(result), - outCode,cbInfo->context); + SCWrite(cbInfo->pCon,GetCharArray(result), + outCode); DeleteDynString(printedData); } else { formatNameValue(protocol, pPath,"!!datachange!!", result, HIPTEXT); - SCWriteInContext(cbInfo->pCon,GetCharArray(result), - outCode,cbInfo->context); + SCWrite(cbInfo->pCon,GetCharArray(result), + outCode); } - SCsetMacro(cbInfo->pCon,macro); free(pPath); DeleteDynString(result); return hdbContinue; } /*-----------------------------------------------------------------------------------------*/ +static void cbKill(void *pData){ + HdbCBInfo *cbInfo = (HdbCBInfo *)pData; + if(cbInfo == NULL){ + return; + } + if(cbInfo->pCon != NULL){ + SCDeleteConnection(cbInfo->pCon); + } + free(cbInfo); +} +/*-----------------------------------------------------------------------------------------*/ pHdbCallback MakeNotifyCallback(SConnection *pCon, int id){ - HdbCBInfo *cbInfo = NULL; + HdbCBInfo *cbInfo = NULL; cbInfo = malloc(sizeof(HdbCBInfo)); if(cbInfo == NULL){ return NULL; } - cbInfo->pCon = pCon; - cbInfo->context = SCGetContext(pCon); + cbInfo->pCon = SCCopyConnection(pCon); + if(cbInfo->pCon == NULL){ + return NULL; + } + SCsetMacro(cbInfo->pCon,0); cbInfo->ID = id; cbInfo->internalID = -1; - return MakeHipadabaCallback(SICSNotifyCallback, cbInfo,free); + return MakeHipadabaCallback(SICSNotifyCallback, cbInfo,cbKill); } /*-------------------------------------------------------------------------*/ static hdbCallbackReturn TreeChangeCallback(pHdb node, void *userData, @@ -553,6 +620,7 @@ static hdbCallbackReturn TreeChangeCallback(pHdb node, void *userData, pHdbIDMessage idm = NULL; pHdbPtrMessage cmm = NULL; pHdbTreeChangeMessage tm = NULL; + SConnection *tstCon = NULL; HdbCBInfo *cbInfo = (HdbCBInfo *)userData; @@ -574,7 +642,8 @@ static hdbCallbackReturn TreeChangeCallback(pHdb node, void *userData, } } if((cmm = GetKillPtrMessage(message)) != NULL){ - if(cmm->pPtr == cbInfo->pCon){ + tstCon = cmm->pPtr; + if(tstCon != NULL && tstCon->ident == cbInfo->pCon->ident){ return hdbKill; } else { return hdbContinue; @@ -588,7 +657,7 @@ static hdbCallbackReturn TreeChangeCallback(pHdb node, void *userData, if(cbInfo != NULL && cbInfo->pCon != NULL){ result = CreateDynString(128,128); if(result == NULL){ - SCWriteInContext(cbInfo->pCon,"ERROR: out of memory in TreeChangeCallback",outCode,cbInfo->context); + SCWrite(cbInfo->pCon,"ERROR: out of memory in TreeChangeCallback",outCode); return hdbAbort; } path = GetHipadabaPath(node); @@ -597,7 +666,7 @@ static hdbCallbackReturn TreeChangeCallback(pHdb node, void *userData, else outCode = eEvent; formatNameValue(protocol, "treechange", path, result, node->value.dataType); - SCWriteInContext(cbInfo->pCon,GetCharArray(result),outCode,cbInfo->context); + SCWrite(cbInfo->pCon,GetCharArray(result),outCode); DeleteDynString(result); free(path); } @@ -611,10 +680,12 @@ pHdbCallback MakeTreeChangeCallback(SConnection *pCon, int id){ if(cbInfo == NULL){ return NULL; } - cbInfo->pCon = pCon; - cbInfo->context = SCGetContext(pCon); + cbInfo->pCon = SCCopyConnection(pCon); + if(cbInfo->pCon == NULL){ + return NULL; + } cbInfo->ID = id; - return MakeHipadabaCallback(TreeChangeCallback, cbInfo,free); + return MakeHipadabaCallback(TreeChangeCallback, cbInfo,cbKill); } /*----------------------------------------------------------------------------------------*/ static hdbCallbackReturn SICSScriptWriteCallback(pHdb node, void *userData, @@ -1740,7 +1811,13 @@ pDynString formatValue(hdbValue v, pHdb node){ snprintf(number,30,format, v.v.floatArray[i]); DynStringConcat(result,number); } - break; + break; + case HIPFUNC: + DynStringConcat(result,"FUNCTION"); + break; + case HIPOBJ: + DynStringConcat(result,"OBJECT"); + break; } return result; } @@ -2281,7 +2358,7 @@ static int GetHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData, if ((protocol = isJSON(pCon)) == 1) outCode = eHdbEvent; else - outCode = eEvent; + outCode = eValue; result = CreateDynString(128,128); formatNameValue(protocol, oriPath, GetCharArray(parData), result, newValue.dataType); @@ -2322,7 +2399,7 @@ static int GetHdbVal(SConnection *pCon, SicsInterp *pSics, void *pData, if ((protocol = isJSON(pCon)) == 1) outCode = eHdbEvent; else - outCode = eEvent; + outCode = eValue; SCWrite(pCon,GetCharArray(parData), outCode); DeleteDynString(parData); ReleaseHdbValue(&newValue); @@ -2610,7 +2687,7 @@ static int ListHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData, outCode = eHdbEvent; } else { listData = formatPlainList(node); - outCode = eEvent; + outCode = eValue; } } if(listData == NULL){ @@ -2801,6 +2878,7 @@ static int ChainHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData, assert(pInter); /* print command to log files */ + /* for( i = 0; i < self->iFiles; i++) { if(self->pFiles[i]) @@ -2808,7 +2886,8 @@ static int ChainHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData, fprintf(self->pFiles[i],"SICS>> %s\n",pCommand); } } - + */ + /* print to command log if user or manager */ if(SCGetRights(self) <= usUser) { @@ -2841,10 +2920,14 @@ static hdbCallbackReturn CommandSetCallback(pHdb node, void *userData, pHdbDataMessage mm = NULL; hdbValue v; + /** + * TODO: this is a duplicate: resolve. It is still here because the old + * Hipadaba configuration commands still work + */ if((mm = GetHdbSetMessage(message)) == NULL){ return hdbContinue; } - pCon = (SConnection *)pCon; + pCon = (SConnection *)mm->callData; v = *(mm->v); if(pCon == NULL){ @@ -2871,7 +2954,9 @@ static hdbCallbackReturn CommandSetCallback(pHdb node, void *userData, } current = current->next; } + SendHdbStatusMessage(node,"start"); status = HDBInvoke(pCon,pServ->pSics, GetCharArray(cmd)); + SendHdbStatusMessage(node,"stop"); DeleteDynString(cmd); if(status == 1){ return hdbContinue; diff --git a/sicshipadaba.h b/sicshipadaba.h index e998a1e3..f4f770a5 100644 --- a/sicshipadaba.h +++ b/sicshipadaba.h @@ -34,6 +34,9 @@ typedef struct { }hdbPtrMessage, *pHdbPtrMessage; /*-----------------------------------------------------------------------------*/ pHdbPtrMessage GetKillPtrMessage(pHdbMessage message); +pHdbMessage GetHdbStartMessage(pHdbMessage message); +pHdbMessage GetHdbStopMessage(pHdbMessage message); +void SendHdbStatusMessage(pHdb node, char *status); /*======================== data structure for automatic parameter update =======*/ typedef struct { SConnection *pCon; @@ -299,7 +302,7 @@ int SICSHdbGetPar(void *obj, SConnection *pCon, char *path, hdbValue *v); int SICSHdbUpdatePar(void *obj, SConnection *pCon, char *path, hdbValue v); /** * SICSHdbSetPar sets the value of a parameter. - * @param obj The object for which to get a parameter. + * @param obj The object for which to set a parameter. * @param pCon The optional connection object to use for reporting errors. * @param path The path to the parameter. * @param v the value diff --git a/sicsobj.c b/sicsobj.c index 0eaabcdd..f291db97 100644 --- a/sicsobj.c +++ b/sicsobj.c @@ -5,6 +5,7 @@ * * Mark Koennecke, July 2007 */ +#include #include #include #include "assert.h" @@ -21,6 +22,50 @@ extern int decodeSICSPriv(char *txt); /* from access.c */ void DefaultKill(void *data){ return; } +/*--------------------------------------------------------------------------*/ +void DefaultFree(void *data){ + if(data != NULL){ + free(data); + } +} +/*---------------------------------------------------------------------------*/ +static void saveSICSNode(pHdb node, char *prefix, FILE *fd){ + char newprefix[1024], val[20]; + pHdb child; + hdbValue v; + pDynString data = NULL; + + if(GetHdbProperty(node,"__save",val,20) == 1){ + GetHipadabaPar(node,&v,NULL); + data = formatValue(v,node); + if(data != NULL){ + fprintf(fd,"%s %s\n", prefix, GetCharArray(data)); + DeleteDynString(data); + } + child = node->child; + while(child != NULL){ + snprintf(newprefix,1024,"%s/%s", prefix,child->name); + saveSICSNode(child,newprefix,fd); + child = child->next; + } + } +} +/*---------------------------------------------------------------------------*/ +int SaveSICSOBJ(void *data, char *name, FILE *fd){ + pSICSOBJ self = (pSICSOBJ)data; + char prefix[1024]; + pHdb node; + + if(self != NULL && self->objectNode != NULL){ + node = self->objectNode->child; + while(node != NULL){ + snprintf(prefix, 1024,"%s %s", name, node->name); + saveSICSNode(node, prefix, fd); + node = node->next; + } + } + return 1; +} /*---------------------------------------------------------------------------*/ pSICSOBJ MakeSICSOBJv(char *name, char *class, int type, int priv){ pSICSOBJ pNew = NULL; @@ -32,12 +77,13 @@ pSICSOBJ MakeSICSOBJv(char *name, char *class, int type, int priv){ } memset(pNew,0,sizeof(SICSOBJ)); pNew->pDes = CreateDescriptor(class); + pNew->pDes->SaveStatus = SaveSICSOBJ; if (type == HIPNONE) { pNew->objectNode = MakeHipadabaNode(name, HIPNONE, 1); } else { - val = makeHdbValue(type,0); - pNew->objectNode = MakeSICSHdbPar(name, priv, val); - ReleaseHdbValue(&val); + val = makeHdbValue(type,0); + pNew->objectNode = MakeSICSHdbPar(name, priv, val); + ReleaseHdbValue(&val); } if(pNew->pDes == NULL || pNew->objectNode == NULL){ free(pNew); @@ -87,7 +133,21 @@ static int invokeOBJFunction(pSICSOBJ object, pHdb commandNode, SConnection *pCo pHdb currentPar = NULL; SICSOBJFunc pFunc = NULL; pHdb parArray[64]; - + char buffer[1024]; + + /* + * If the first argument has the special name args, concatenate all arguments + * and put the result as text into this parameter. This allows for the + * object function to parse and interpret the arguments itself. + */ + if(commandNode->child != NULL && strcmp(commandNode->child->name,"args") == 0) { + Arg2Text(argc,argv,buffer,1024); + assignPar(commandNode->child,pCon,buffer); + parArray[0] = commandNode->child; + count = 1; + goto invoke; + } + /* * assign parameters and fill parameter array for function at the same * time. Be lenient about missing parameters: Then the old values will @@ -106,12 +166,14 @@ static int invokeOBJFunction(pSICSOBJ object, pHdb commandNode, SConnection *pCo count++; } - pFunc = (SICSOBJFunc)commandNode->value.v.func; +invoke: pFunc = (SICSOBJFunc)commandNode->value.v.func; if(pFunc == NULL){ SCWrite(pCon,"ERROR: internal error, function not found",eError); return 0; } + SendHdbStatusMessage(commandNode,"start"); status = pFunc(object, pCon, commandNode, parArray,count); + SendHdbStatusMessage(commandNode,"stop"); return status; } /*---------------------------------------------------------------------------*/ @@ -128,7 +190,7 @@ static int ScriptObjFunc(pSICSOBJ obj, SConnection *pCon, pHdb commandNode, GetHdbProperty(commandNode,"priv",value,256); status = decodeSICSPriv(value); if(!SCMatchRights(pCon,status)){ - return 0; + return 0; } if(GetHdbProperty(commandNode,"script",value,256) != 1){ @@ -219,6 +281,42 @@ static int isNodePrintable(pHdb node){ } } /*---------------------------------------------------------------------------*/ +static void objFormatNode(pHdb node, pDynString data){ + char par[40]; + pDynString val = NULL; + + snprintf(par,40,"%-20s = ",node->name); + DynStringConcat(data,par); + val = formatValue(node->value,node); + if(val != NULL){ + DynStringConcat(data,GetCharArray(val)); + DynStringConcatChar(data,'\n'); + DeleteDynString(val); + } +} +/*---------------------------------------------------------------------------*/ +static int ListObj(pSICSOBJ self, SConnection *pCon, int argc, char *argv[]){ + pHdb node = NULL; + pDynString data; + + data = CreateDynString(128,128); + if(data == NULL){ + return 0; + } + node = self->pDes->parNode; + if(node != NULL){ + objFormatNode(node,data); + node = node->child; + while(node != NULL){ + objFormatNode(node,data); + node = node->next; + } + } + SCWrite(pCon,GetCharArray(data),eValue); + DeleteDynString(data); + return 1; +} +/*---------------------------------------------------------------------------*/ int InvokeSICSOBJ(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]){ pSICSOBJ self = NULL; @@ -263,6 +361,8 @@ int InvokeSICSOBJ(SConnection *pCon, SicsInterp *pSics, void *pData, if(status == -1){ if(strcmp(argv[1],"makescriptfunc") == 0) { return MakeScriptFunc(self,pCon,argc,argv); + } else if(strcmp(argv[1],"list") == 0){ + return ListObj(self,pCon,argc,argv); } SCPrintf(pCon, eError, "ERROR: %s %s not found", argv[0], argv[1]); } diff --git a/sicsobj.h b/sicsobj.h index a095d52a..6512146e 100644 --- a/sicsobj.h +++ b/sicsobj.h @@ -29,7 +29,9 @@ pSICSOBJ MakeSICSOBJ(char *name, char *class); pSICSOBJ MakeSICSOBJv(char *name, char *class, int type, int priv); void KillSICSOBJ(void *data); void DefaultKill(void *data); +void DefaultFree(void *data); +int SaveSICSOBJ(void *data, char *name, FILE *fd); /** * This creates a new SICS object and installs it in the interpreter. It returns diff --git a/sicvar.c b/sicvar.c index 5b8af4c9..34ec3102 100644 --- a/sicvar.c +++ b/sicvar.c @@ -345,8 +345,7 @@ } } /*--------------------------------------------------------------------*/ - static int VarInterestCallback(int iEvent, void *pEvent, void *pUser, - commandContext cc) + static int VarInterestCallback(int iEvent, void *pEvent, void *pUser) { SConnection *pCon; char pBueffel[512]; @@ -360,7 +359,13 @@ pVar = (pSicsVariable)pEvent; pCon = (SConnection *)pUser; - SCPushContext2(pCon,cc); + + /* check kill conditions */ + if(pCon == NULL || !SCisConnected(pCon)) + { + return -1; + } + switch(pVar->eType) { case veInt: @@ -386,7 +391,6 @@ status = 1; break; } - SCPopContext(pCon); return status; } /*----------------------------------------------------------------------*/ @@ -536,17 +540,16 @@ static int VarSetFromText(pSicsVariable self, SConnection *pCon, char *text) } else if(strcmp(pCurrent->text,"interest") == 0) /* interest */ { - lID = RegisterCallback(pVar->pCall, SCGetContext(pCon), + lID = RegisterCallback(pVar->pCall, VALUECHANGE, VarInterestCallback, - pCon, NULL); - SCRegister(pCon,pInterp, pVar->pCall,lID); + SCCopyConnection(pCon), SCDeleteConnection); DeleteTokenList(pList); SCSendOK(pCon); return 1; } else if(strcmp(pCurrent->text,"uninterest") == 0) { - RemoveCallback2(pVar->pCall,pCon); + RemoveCallbackCon(pVar->pCall,pCon); DeleteTokenList(pList); SCSendOK(pCon); return 1; diff --git a/simchop.c b/simchop.c index 9a54deb3..b2e4e33b 100644 --- a/simchop.c +++ b/simchop.c @@ -20,8 +20,8 @@ #define RANDOMWARNING -7003 #define STOPPED -7004 -#define FAILRATE 0.05 -#define WARNRATE 0.1 +#define FAILRATE 0.00005 +#define WARNRATE 0.00001 /*-----------------------------------------------------------------------*/ typedef struct { time_t tTarget; diff --git a/simidx.c b/simidx.c new file mode 100644 index 00000000..87c7d7ac --- /dev/null +++ b/simidx.c @@ -0,0 +1,679 @@ +/** + * This is the simple reflection indexer. The algorithm is simple: + * - Three non coplanar reflections at low two theta are selected. + * - Candidate indices are calculated from the lattice constants + * - Permutations of the generated indices are changed for a couple + * of conditions: + * -- Does the angle between the reflections matches the expectaions + * -- Do the reflections form a right handed set + * UB matrics matching these conditions are calculated and stored + * for later retrieval. + * + * The software is organized such that this is a standalone module. + * For reasons of laziness I use statically sized arrays for + * candidate indices and for the reflection list. This is simple and + * this code is for small problems anyway. + * + * Mark Koennecke, August 2008 + */ +#include +#include +#include +#include +#include +#include "simidx.h" +#include "cell.h" +#include "vector.h" +#include "ubfour.h" +#include "fourlib.h" +/*======================== defines ===========================*/ +#define MAXCANDIDATES 20 +#define MAXREF 20 +#define MAXIDX 20 +#define MAXSOLUTION 20 +#define ABS(x) (x < 0 ? -(x) : (x)) +/*======================== types =============================*/ +typedef struct { + int h,k,l; + double diff; +} HKL, *pHKL; + +typedef struct { + double uvw[3]; + MATRIX UVW; + HKL indices[MAXCANDIDATES]; + int nHKL; + int currentIDX; + double twotheta; + int originalID; +} IndexVector, *pIndexVector; + + +/*================== module parameters ========================*/ +static lattice direct; +static double lambda; +static T_SgInfo *spgrp = NULL; +static IndexVector reflections[MAXREF]; +static int nReflections = 0; +static double sttlim = .5, anglim = 2.; +static OutFunc outFunc = NULL; +static void *userData; +static int outLevel = 10; +static IndexSolution solutions[MAXSOLUTION]; +static int nSolutions; +/*------------------------------------------------------------*/ +void SimIdxInit(){ + int i; + for(i = 0; i < MAXREF; i++){ + reflections[i].UVW = mat_creat(3,1,ZERO_MATRIX); + } +} +/*=============== configuration functions =====================*/ +void SimIdxSetCell(double cell[6]){ + direct.a = cell[0]; + direct.b = cell[1]; + direct.c = cell[2]; + direct.alpha = cell[3]; + direct.beta = cell[4]; + direct.gamma = cell[5]; +} +/*-------------------------------------------------------------*/ +void SimIdxSetLambda(double lmda){ + lambda = lmda; +} +/*-------------------------------------------------------------*/ +void SimIdxSetSttLim(double lmda){ + sttlim = lmda; +} +/*-------------------------------------------------------------*/ +void SimIdxSetAngLim(double lmda){ + anglim = lmda; +} +/*-------------------------------------------------------------*/ +void SimIdxSetSpacegroup(T_SgInfo *sg){ + spgrp = sg; +} +/*-------------------------------------------------------------*/ +void SimIdxClearReflection(){ + nReflections = 0; +} +/*-------------------------------------------------------------*/ +void SimIdxAddReflection(double uvw[3]){ + int i; + if(nReflections < MAXREF){ + memcpy(&reflections[nReflections].uvw, uvw, 3*sizeof(double)); + reflections[nReflections].nHKL = 0; + reflections[nReflections].currentIDX = 0; + reflections[nReflections].originalID = nReflections; + for(i = 0; i < 3; i++){ + reflections[nReflections].UVW[i][0] = uvw[i]; + } + nReflections++; + } +} +/*-------------------------------------------------------------*/ +void SimIdxOutput(void *data, OutFunc out, int level){ + userData = data; + outFunc = out; + outLevel = level; +} +/*-------------------------------------------------------------*/ +static void SimIdxPrint(int level, char *fmt, ...){ + va_list ap; + char buf[1024]; + int l; + + if(level > outLevel){ + return; + } + + va_start(ap, fmt); + l = vsnprintf(buf, sizeof buf, fmt, ap); + va_end(ap); + if(outFunc != NULL){ + outFunc(userData,buf); + } else { + printf("%s\n",buf); + } +} +/*=============== The alkoholism ===============================*/ +static int thetaCompare(const void *d1, const void *d2){ + pIndexVector iv1, iv2; + + iv1 = (pIndexVector)d1; + iv2 = (pIndexVector)d2; + + if(iv1->twotheta == iv2->twotheta) { + return 0; + } + if(iv1->twotheta < iv2->twotheta){ + return -1; + } else { + return 1; + } +} +/*--------------------------------------------------------------*/ +static void calcRefTheta(){ + int i; + double theta, d; + + for(i = 0; i < nReflections; i++){ + calcTheta(lambda, reflections[i].UVW, &d, &theta); + reflections[i].twotheta = 2.* theta; + } + qsort(reflections,nReflections, sizeof(IndexVector), + thetaCompare); + + SimIdxPrint(10,"%d Reflections", nReflections); +} +/*---------------------------------------------------------------*/ +double calcIdxTwoTheta(int h, int k, int l, MATRIX B){ + MATRIX H, Z1; + double om, d; + + H = mat_creat(3,1,ZERO_MATRIX); + if(H == NULL){ + SimIdxPrint(1,"ERROR: out of memory calculating H matrix"); + return 0.; + } + H[0][0] = (double)h; + H[1][0] = (double)k; + H[2][0] = (double)l; + Z1 = mat_mul(B,H); + calcTheta(lambda,Z1,&d,&om); + om *= 2.; + mat_free(Z1); + mat_free(H); + + return om; +} +/*---------------------------------------------------------------*/ +static void AddCandidate(int n, int h, int k, int l, + double diff){ + int cur = reflections[n].nHKL; + if(cur < MAXCANDIDATES){ + reflections[n].indices[cur].h = h; + reflections[n].indices[cur].k = k; + reflections[n].indices[cur].l = l; + reflections[n].indices[cur].diff = diff ; + reflections[n].nHKL++; + } +} +/*---------------------------------------------------------------*/ +static int calcIndexes(){ + int h, k, l, i, status; + int minh, mink, minl; + MATRIX B; + double twotheta; + + B = mat_creat(3,3,UNIT_MATRIX); + if(B == NULL){ + SimIdxPrint(1,"ERROR: out of memory calculating B matrix"); + return 0; + } + + status = calculateBMatrix(direct,B); + if(status < 0) { + SimIdxPrint(1,"ERROR: invalid cell constants, failed to calculate B matrix"); + return 0; + } + + minh = -MAXIDX; + mink = -MAXIDX; + minl = -MAXIDX; + SetListMin_hkl(spgrp,MAXIDX, MAXIDX,&minh, &mink, &minl); + + for(h = MAXIDX; h > -MAXIDX; h--){ + for(k = MAXIDX; k > -MAXIDX; k--){ + for(l = MAXIDX; l > -MAXIDX; l--){ + if(IsSysAbsent_hkl(spgrp,h,k,l,NULL) != 0) { + continue; + } + twotheta = calcIdxTwoTheta(h,k,l,B); + for(i = 0; i < nReflections; i++){ + if(reflections[i].twotheta > twotheta - sttlim && + reflections[i].twotheta < twotheta + sttlim){ + AddCandidate(i, h,k,l, ABS(twotheta - reflections[i].twotheta)); + } + } + } + } + } + mat_free(B); + return 1; +} +/*-------------------------------------------------------------*/ +static double angleBetweenScatVec(MATRIX v1, MATRIX v2){ + double angle; + + angle = angleBetween(v1,v2); + return angle; +} +/*---------------------------------------------------------------*/ +static void printRefDiagnostic(){ + int i, j; + double angle; + + SimIdxPrint(10,"Reflection List and Candidate Indices"); + SimIdxPrint(10," N STT U V W"); + + for(i = 0; i < nReflections; i++){ + SimIdxPrint(10,"%3.3d %8.4f %8.4f %8.4f %8.4f", i, + reflections[i].twotheta, + reflections[i].uvw[0], + reflections[i].uvw[1], reflections[i].uvw[2]); + for(j = 0; j < reflections[i].nHKL; j++){ + SimIdxPrint(10,"\t%4d %4d %4d", + reflections[i].indices[j].h, + reflections[i].indices[j].k, + reflections[i].indices[j].l); + } + } + SimIdxPrint(10,"Angles between reflections"); + SimIdxPrint(10,"IDX1 IDX2 Angle"); + for(i = 0; i < nReflections; i++){ + for(j = i; j < nReflections; j++){ + if(i != j){ + angle = angleBetweenScatVec(reflections[i].UVW, reflections[j].UVW); + SimIdxPrint(10,"%3d %3d %8.2f",i,j,angle); + } + } + } +} +/*-------------------------------------------------------------*/ +static double calculateVolume(double v1[3], double v2[3], + double v3[3]){ + MATRIX m; + int i; + double vol; + + m = mat_creat(3,3,ZERO_MATRIX); + for(i = 0; i < 3; i++){ + m[i][0] = v1[i]; + m[i][1] = v2[i]; + m[i][2] = v3[i]; + } + vol = mat_det(m); + mat_free(m); + return vol; +} +/*-------------------------------------------------------------*/ +static int areCoplanar(MATRIX v1, MATRIX v2, + MATRIX v3){ + MATRIX norm; + double dot; + + norm = vectorCrossProduct(v1,v2); + if(norm != NULL){ + dot = vectorDotProduct(norm,v3); + mat_free(norm); + } else { + dot = .0; + } + if(ABS(dot) > .00001){ + return 0; + } else { + return 1; + } +} +/*-------------------------------------------------------------- + * - We want the shortest vectors + * - We do not want vectors at 180 to each other + * - We do not want the three vectors to be coplanar + *-------------------------------------------------------------*/ +static int chooseTriplet(int triplet[3]){ + double angle, vol; + int idx = 1; + + triplet[0] = 0; + /* + * test for 180 + */ + while(idx < nReflections){ + angle = angleBetweenScatVec(reflections[0].UVW, + reflections[idx].UVW); + if(angle < 160 && angle > -160){ + triplet[1] = idx; + break; + } + idx++; + } + if(idx >= nReflections){ + SimIdxPrint(1,"ERROR: no second index found"); + return 0; + } + + for(idx = 1; idx < nReflections; idx++){ + if(idx != triplet[1]) { + if(!areCoplanar(reflections[triplet[0]].UVW, + reflections[triplet[1]].UVW, + reflections[idx].UVW)){ + triplet[2] = idx; + return 1; + } + } + } + SimIdxPrint(1,"ERROR: no three non coplanar reflections found"); + return 0; +} +/*------------------------------------------------------------*/ +static double reflectionsAngle(MATRIX B, int hkl1[3], +int hkl2[3]){ + double angle; + reflection r1, r2; + + r1.h = hkl1[0]; + r1.k = hkl1[1]; + r1.l = hkl1[2]; + + r2.h = hkl2[0]; + r2.k = hkl2[1]; + r2.l = hkl2[2]; + + return angleBetweenReflections(B,r1,r2); +} +/*-------------------------------------------------------------*/ +static int findAngleMatch(MATRIX B, int idxr1, int r1, + int r2start, int r2, double *diff){ + double scatAngle, hklAngle; + MATRIX H1, H2; + int i, r, hkl1[3], hkl2[3]; + + scatAngle = angleBetweenScatVec(reflections[r1].UVW, + reflections[r2].UVW); + hkl1[0] = reflections[r1].indices[idxr1].h; + hkl1[1] = reflections[r1].indices[idxr1].k; + hkl1[2] = reflections[r1].indices[idxr1].l; + + for(i = r2start; i < reflections[r2].nHKL; i++){ + hkl2[0] = reflections[r2].indices[i].h; + hkl2[1] = reflections[r2].indices[i].k; + hkl2[2] = reflections[r2].indices[i].l; + hklAngle = reflectionsAngle(B,hkl1, hkl2); + *diff = ABS(scatAngle - hklAngle); + if(*diff < anglim){ + return i; + } + } + return -1; +} +/*------------------------------------------------------------- + * If the system is right handed the determinat of the + * matrix having the indices as columns must be positive + -------------------------------------------------------------*/ +static int testRightHandedness(int r1, int r1idx, + int r2, int r2idx, + int r3, int r3idx){ + MATRIX T; + double vol; + + T = mat_creat(3,3,ZERO_MATRIX); + if(T == NULL){ + return 0; + } + T[0][0] = reflections[r1].indices[r1idx].h; + T[1][0] = reflections[r1].indices[r1idx].k; + T[2][0] = reflections[r1].indices[r1idx].l; + T[0][1] = reflections[r2].indices[r2idx].h; + T[1][1] = reflections[r2].indices[r2idx].k; + T[2][1] = reflections[r2].indices[r2idx].l; + T[0][2] = reflections[r3].indices[r3idx].h; + T[1][2] = reflections[r3].indices[r3idx].k; + T[2][2] = reflections[r3].indices[r3idx].l; + vol = mat_det(T); + mat_free(T); + if(vol > .0){ + return 1; + } else { + return 0; + } +} +/*-------------------------------------------------------------*/ +static void storeSolution(int r1, int r1idx, + int r2, int r2idx, + int r3, int r3idx, double diff){ + IndexSolution is; + is.h[0] = reflections[r1].indices[r1idx].h; + is.k[0] = reflections[r1].indices[r1idx].k; + is.l[0] = reflections[r1].indices[r1idx].l; + is.originalID[0] = reflections[r1].originalID; + is.diff = reflections[r1].indices[r1idx].diff; + + is.h[1] = reflections[r2].indices[r2idx].h; + is.k[1] = reflections[r2].indices[r2idx].k; + is.l[1] = reflections[r2].indices[r2idx].l; + is.originalID[1] = reflections[r2].originalID; + is.diff += reflections[r2].indices[r2idx].diff; + + if(r3 != 999){ + is.h[2] = reflections[r3].indices[r3idx].h; + is.k[2] = reflections[r3].indices[r3idx].k; + is.l[2] = reflections[r3].indices[r3idx].l; + is.diff += reflections[r3].indices[r3idx].diff; + is.originalID[2] = reflections[r3].originalID; + } else { + is.h[2] = 0; + is.k[2] = 0; + is.l[2] = 0; + is.originalID[2] = 999; + } + is.diff += diff; + + solutions[nSolutions] = is; + nSolutions++; +} +/*----------------------------------------------------------------------*/ +static int compareSolution(const void *d1, const void *d2){ + IndexSolution *iv1, *iv2; + + iv1 = (IndexSolution *)d1; + iv2 = (IndexSolution *)d2; + + if(iv1->diff == iv2->diff) { + return 0; + } + if(iv1->diff < iv2->diff){ + return -1; + } else { + return 1; + } +} + +/*--------------------------------------------------------------*/ +static int findSolutionsForTriplet(int triplet[3], int testRight){ + int r1, r2, r3, i, status; + int match1, match2, r2start, r3start; + double diff1, diff2; + MATRIX B; + + r1 = triplet[0]; + r2 = triplet[1]; + r3 = triplet[2]; + + B = mat_creat(3,3,UNIT_MATRIX); + if(B == NULL){ + SimIdxPrint(1,"ERROR: out of memory calculating B matrix"); + return 0; + } + + status = calculateBMatrix(direct,B); + if(status < 0) { + SimIdxPrint(1,"ERROR: invalid cell constants, failed to calculate B matrix"); + return 0; + } + + for(i = 0; i < reflections[r1].nHKL; i++){ + r2start = 0; + while((match1 = findAngleMatch(B, i, r1, r2start, r2,&diff1)) >=0){ + r3start = 0; + while((match2 = findAngleMatch(B, i, r1, r3start, r3,&diff2)) >= 0){ + if(testRight == 1){ + if(testRightHandedness(r1, i, r2, match1, r3, match2)){ + storeSolution(r1,i,r2,match1, r3,match2, diff1 + diff2); + } + } else { + storeSolution(r1,i,r2,match1, r3,match2, diff1 + diff2); + } + r3start = match2 + 1; + } + r2start = match1 + 1; + } + } + qsort(solutions,nSolutions, sizeof(IndexSolution), + compareSolution); + + return 1; +} +/*------------------------------------------------------------- + * If the system is right handed the determinat of the + * matrix having the indices as columns must be positive. + * As I have only two vectors, I simulate the third by + * using the nromal on the other two. + -------------------------------------------------------------*/ +static int testDuoRightHandedness(int r1, int r1idx, + int r2, int r2idx){ + MATRIX T; + double vol; + int r3, r3idx; + + T = mat_creat(3,3,ZERO_MATRIX); + if(T == NULL){ + return 0; + } + T[0][0] = reflections[r1].indices[r1idx].h; + T[1][0] = reflections[r1].indices[r1idx].k; + T[2][0] = reflections[r1].indices[r1idx].l; + T[0][1] = reflections[r2].indices[r2idx].h; + T[1][1] = reflections[r2].indices[r2idx].k; + T[2][1] = reflections[r2].indices[r2idx].l; + T[0][2] = reflections[r3].indices[r3idx].h; + T[1][2] = reflections[r3].indices[r3idx].k; + T[2][2] = reflections[r3].indices[r3idx].l; + vol = mat_det(T); + mat_free(T); + if(vol > .0){ + return 1; + } else { + return 0; + } +} +/*--------------------------------------------------------------*/ +static int findSolutionsForDuett(int triplet[3]){ + MATRIX B; + int r1, r2, r2start, i, status, match1; + double diff; + + if(triplet[1] == 999){ + SimIdxPrint(1,"ERROR: No suitable reflection set found"); + return 0; + } + + r1 = triplet[0]; + r2 = triplet[1]; + + B = mat_creat(3,3,UNIT_MATRIX); + if(B == NULL){ + SimIdxPrint(1,"ERROR: out of memory calculating B matrix"); + return 0; + } + + status = calculateBMatrix(direct,B); + if(status < 0) { + SimIdxPrint(1,"ERROR: invalid cell constants, failed to calculate B matrix"); + return 0; + } + + for(i = 0; i < reflections[r1].nHKL; i++){ + r2start = 0; + while((match1 = findAngleMatch(B, i, r1, r2start, r2,&diff)) >=0){ + storeSolution(r1,i,r2,match1,999,0,diff); + r2start = match1 + 1; + } + } + qsort(solutions,nSolutions, sizeof(IndexSolution), + compareSolution); + return 1; +} +/*-------------------------------------------------------------- + * This is used if we cannot find a solution for a triplet. + * Then we try to reduce to a duett. So we look for a second + * reflection in the original triplett which is closest + * to 90 degree in angle. + */ +static int secondForDuett(int triplet[3]){ + double diff1, diff2; + + diff1 = ABS(90. - angleBetweenScatVec( + reflections[triplet[0]].UVW,reflections[triplet[1]].UVW)); + diff2 = ABS(90. - angleBetweenScatVec( + reflections[triplet[0]].UVW,reflections[triplet[2]].UVW)); + if(diff1 < diff2){ + return triplet[1]; + } else { + return triplet[2]; + } +} +/*--------------------------------------------------------------*/ +int SimIdxRun(){ + int triplet[3] = {999,999,999}, status; + + SimIdxPrint(10,"SimIdx calculating with parameters:"); + SimIdxPrint(10, "Cell = %f %f %f %f %f %f", direct.a, direct.b, direct.c, + direct.alpha, direct.beta, direct.gamma); + SimIdxPrint(10,"Lambda = %f", lambda); + SimIdxPrint(10,"Sttlim, anglim = %f %f", sttlim, anglim); + + nSolutions = 0; + + calcRefTheta(); + + if(!calcIndexes()){ + return 0; + } + + if(outLevel >= 10){ + printRefDiagnostic(); + } + + if(nReflections >= 3){ + if(!chooseTriplet(triplet)){ + return findSolutionsForDuett(triplet); + } + } else { + triplet[0] = 0; + triplet[1] = 1; + return findSolutionsForDuett(triplet); + } + + SimIdxPrint(10,"Choosen triplet: %d, %d, %d\n", triplet[0], + triplet[1], triplet[2]); + + status = findSolutionsForTriplet(triplet,1); + if(nSolutions == 0){ + SimIdxPrint(1,"WARNING: found no right handed solution set, trying to find lefthanded"); + status = findSolutionsForTriplet(triplet,0); + } + if(nSolutions == 0){ + SimIdxPrint(10,"Failed to find solution for triplet, trying duett"); + status = secondForDuett(triplet); + triplet[1] = status; + status = findSolutionsForDuett(triplet); + } + return status; +} +/*=========================== solution retrieval ===================*/ +int SimIdxGetNSolutions(){ + return nSolutions; +} +/*------------------------------------------------------------------*/ +IndexSolution SimIdxGetSolution(int id){ + IndexSolution broken; + if(id >= 0 && id < nSolutions){ + return solutions[id]; + } + broken.h[0] = -999; + broken.h[1] = -999; + broken.h[2] = -999; + return broken; +} + diff --git a/simidx.h b/simidx.h new file mode 100644 index 00000000..6f45c31a --- /dev/null +++ b/simidx.h @@ -0,0 +1,104 @@ +/** + * This is the simple reflection indexer. The algorithm is simple: + * - Three non coplanar reflections at low two theta are selected. + * - Candidate indices are calculated from the lattice constants + * - Permutations of the generated indices are changed for a couple + * of conditions: + * -- Does the angle between the reflections matches the expectaions + * -- Do the reflections form a right handed set + * UB matrics matching these conditions are calculated and stored + * for later retrieval. + * + * The software is organized such that this is a standalone module. + * + * Mark Koennecke, August 2008 + */ +#ifndef __SIMIDX +#define __SIMIDX +#include +#include "sginfo.h" + +typedef struct { + int h[3], k[3], l[3]; + int originalID[3]; + double diff; +}IndexSolution; + +/** + * \brief To be called before using simidx + */ +void SimIdxInit(); + +/** + * \brief Set the cell constants + * \param cell The cell constants: a,b,c alpha, beta, gamma + */ +void SimIdxSetCell(double cell[6]); +/** + * \brief set the wavelength + * \param lambda The wavelength + */ +void SimIdxSetLambda(double lambda); +/** + * \brief set the two-theta limit for considering a + * valid set of indices + * \param limit The two theta limit + */ +void SimIdxSetSttLim(double limit); +/** + * \brief set the allowd angular dieviation for + * a two combination. + * \param limit The angle limit limit + */ +void SimIdxSetAngLim(double limit); +/** + * \brief set the spacegroup + * \param spgrp The new spacegroup + */ +void SimIdxSetSpacegroup(T_SgInfo *spgrp); +/** + * \brief clear the reflection list + * */ +void SimIdxClearReflection(); +/** + *\brief add a reflection already reduced to a scattering vector + * \param uvw The coordinates of the scattering vector + */ +void SimIdxAddReflection(double uvw[3]); +typedef void (*OutFunc)(void *userData, char *text); +/** + * \brief configure the output for the algorithm + * \param userData A pointer to user data which is passed to the + * output function unchanged + * \param out An output function + * \param level the vebosity level for output + */ +void SimIdxOutput(void *userData, OutFunc out, int level); + +/** + * \brief Run the algorithm + * \return 1 on success, 0 on error + */ +int SimIdxRun(); +/** + * \brief get the last error description + * \param errCode pointer to an integer error code + * \param error A text buffer to hold a description of the error + * \param errLen The length of error +void SimIdxGetError(int *errCode, char *error, int errLen); + +/** + * \brief get the number of solutions + * \return The number of solutions + */ +int SimIdxGetNSolutions(); +/** + * get the solution number idx + * \param id The id of the solution + * \return A IndexSolution structure + */ +IndexSolution SimIdxGetSolution(int id); + +#endif + + diff --git a/sinfox.c b/sinfox.c index e4c6b449..280ad819 100644 --- a/sinfox.c +++ b/sinfox.c @@ -175,13 +175,17 @@ static int SinfoxInit(SicsInterp *pSics, char *infofile) { return 0; } + /* pCon->iFiles = 1; pCon->pFiles[0] = stdout; - + */ + /* evaluate the file */ sprintf(pBuf,"fileeval %s",infofile); iRet = InterpExecute(pSics,pCon,pBuf); + /* pCon->iFiles = 0; + */ SCDeleteConnection(pCon); return iRet; diff --git a/singletas.c b/singletas.c new file mode 100644 index 00000000..a03cdb42 --- /dev/null +++ b/singletas.c @@ -0,0 +1,269 @@ +/** + * This is an implementation of the polymorphic single crystal calculation module + * for the triple axis mode. In this mode the tilt angles of a standard sample + * cradle are used to orient the sample. The math behind this has been decribed by + * Mark Lumsden in his paper. + * + * copyright: see file COPYRIGHT + * + * Mark Koennecke, November 2008 + */ +#include +#include +#include +#include "singlediff.h" +#include "motor.h" +#include "singlex.h" +#include "motorlist.h" +#include "lld.h" +#include "tasublib.h" +#include "fourlib.h" + +/*---------------------------------------------------------------------*/ +static int calculateTASSettings(pSingleDiff self, + double *hkl, double *settings){ + tasQEPosition qe; + tasAngles angles; + double e, *normal; + int status; + MATRIX mn; + char error[132]; + float fHard; + + e = 9.045/self->lambda; + e = e*e; + qe.ki = energyToK(e); + qe.kf = energyToK(e); + qe.qh = hkl[0]; + qe.qk = hkl[1]; + qe.ql = hkl[2]; + + normal = SXGetPlanenormal(); + if(normal == NULL){ + return 0; + } + mn = vectorToMatrix(normal); + if(mn == NULL){ + return 0; + } + + status = calcTasQAngles(self->UB, mn, 1, qe, &angles); + if(status < 0) { + status = 0; + } else { + status = 1; + } + settings[0] = angles.a3; + settings[1] = angles.sample_two_theta; + settings[2] = angles.sgu; + settings[3] = angles.sgl; + if(!MotorCheckBoundary(SXGetMotor(Omega), (float)settings[0],&fHard, + error, 132)){ + status = 0; + } + if(!MotorCheckBoundary(SXGetMotor(TwoTheta), (float)settings[1],&fHard, + error, 132)){ + status = 0; + } + if(!MotorCheckBoundary(SXGetMotor(Sgu), (float)settings[2],&fHard, + error, 132)){ + status = 0; + } + if(!MotorCheckBoundary(SXGetMotor(Sgl), (float)settings[3],&fHard, + error, 132)){ + status = 0; + } + free(normal); + mat_free(mn); + return status; +} +/*-------------------------------------------------------------------*/ +static int settingsToTasList(struct __SingleDiff *self, double *settings){ + + setNewMotorTarget(self->motList, (char *)SXGetMotorName(Omega), + (float)settings[0]); + setNewMotorTarget(self->motList, (char *)SXGetMotorName(TwoTheta), + (float)settings[1]); + setNewMotorTarget(self->motList, (char *)SXGetMotorName(Sgu), + (float)settings[2]); + setNewMotorTarget(self->motList, (char *)SXGetMotorName(Sgl), + (float)settings[3]); + return 1; +} +/*--------------------------------------------------------------------*/ +static int hklFromTasAngles(struct __SingleDiff *self, double *hkl){ + pIDrivable pDriv; + double e, stt, om, sgu, sgl; + tasQEPosition qe; + tasAngles angles; + int status = 1; + + e = 9.045/self->lambda; + e = e*e; + qe.ki = energyToK(e); + qe.kf = energyToK(e); + + pDriv = makeMotListInterface(); + pDriv->GetValue(&self->motList, pServ->dummyCon); + + stt = getListMotorPosition(self->motList, + (char *)SXGetMotorName(TwoTheta)); + om = getListMotorPosition(self->motList, + (char *)SXGetMotorName(Omega)); + sgu = getListMotorPosition(self->motList, + (char *)SXGetMotorName(Sgu)); + sgl = getListMotorPosition(self->motList, + (char *)SXGetMotorName(Sgl)); + + angles.a3 = om; + angles.sample_two_theta = stt; + angles.sgu = sgu; + angles.sgl = sgl; + + status = calcTasQH(self->UB, angles, &qe); + if(status < 0){ + status = 0; + } + hkl[0] = qe.qh; + hkl[1] = qe.qk; + hkl[2] = qe.ql; + + return status; +} +/*-------------------------------------------------------------------------*/ +static int hklFromTasAnglesGiven(struct __SingleDiff *self, + double *settings, double *hkl){ + double e; + tasQEPosition qe; + tasAngles angles; + int status = 1; + + e = 9.045/self->lambda; + e = e*e; + qe.ki = energyToK(e); + qe.kf = energyToK(e); + + angles.a3 = settings[0]; + angles.sample_two_theta = settings[1]; + angles.sgu = settings[2]; + angles.sgl = settings[3]; + + status = calcTasQH(self->UB, angles, &qe); + if(status < 0){ + status = 0; + } + hkl[0] = qe.qh; + hkl[1] = qe.qk; + hkl[2] = qe.ql; + + return status; +} +/*------------------------------------------------------------------*/ +static int getTasReflection(char *id, tasReflection *r){ + pSICSOBJ refList; + double hkl[3], angles[4]; + double lambda, e; + + lambda = SXGetLambda(); + e = 9.045/lambda; + e = e*e; + + refList = SXGetReflectionList(); + if(!GetRefIndexID(refList,id,hkl)){ + return 0; + } else { + r->qe.qh = hkl[0]; + r->qe.qk = hkl[1]; + r->qe.ql = hkl[2]; + r->qe.ki = energyToK(e); + r->qe.kf = energyToK(e); + GetRefAnglesID(refList,id,angles); + r->angles.a3 = angles[0]; + r->angles.sample_two_theta = angles[1]; + r->angles.sgu = angles[2]; + r->angles.sgl = angles[3]; + } + return 1; +} +/*--------------------------------------------------------------------------*/ +MATRIX calcTasUBFromTwo(pSingleDiff self, + char *refid1, char *refid2, int *err){ + MATRIX ub = NULL, pl = NULL; + tasReflection r1, r2; + lattice direct; + double p[3]; + + direct.a = self->cell[0]; + direct.b = self->cell[1]; + direct.c = self->cell[2]; + direct.alpha = self->cell[3]; + direct.beta = self->cell[4]; + direct.gamma = self->cell[5]; + + if(!getTasReflection(refid1,&r1)){ + *err = REFERR; + return NULL; + } + if(!getTasReflection(refid2,&r2)){ + *err = REFERR; + return NULL; + } + + ub = calcTasUBFromTwoReflections(direct,r1,r2,err); + pl = calcPlaneNormal(r1,r2); + if(pl != NULL){ + matrixToVector(pl,p); + SXSetPlanenormal(p); + mat_free(pl); + } + return ub; +} +/*--------------------------------------------------------------------------*/ +MATRIX calcTasUBFromThree(pSingleDiff self, + char *refid1, char *refid2, char *refid3, int *err){ + /* + * not implemented yet + * There is also a problem: if I have three reflections, which + * defines the plane normal? This also does not make much sense anyway: + * we usually will not have a reflection out of plane: thus the three + * will be coplanar and the results may not be useful at all! + */ + return NULL; +} +/*--------------------------------------------------------------------*/ +static int calcTasZ1(pSingleDiff self, char *refid, double z1[3]){ + tasReflection r1; + MATRIX u = NULL; + + if(!getTasReflection(refid,&r1)){ + return 0; + } + u = calcTasUVectorFromAngles(r1); + if(u == NULL){ + return 0; + } else { + matrixToVector(u,z1); + mat_free(u); + } + return 1; +} +/*--------------------------------------------------------------------*/ +void initializeSingleTas(pSingleDiff diff){ + + if(diff->motList >= 0){ + LLDdelete(diff->motList); + } + diff->motList = LLDcreate(sizeof(MotControl)); + addMotorToList(diff->motList, (char *)SXGetMotorName(TwoTheta), .0); + addMotorToList(diff->motList, (char *)SXGetMotorName(Omega), .0); + addMotorToList(diff->motList, (char *)SXGetMotorName(Sgu), .0); + addMotorToList(diff->motList, (char *)SXGetMotorName(Sgl), .0); + + diff->calculateSettings = calculateTASSettings; + diff->settingsToList = settingsToTasList; + diff->hklFromAngles = hklFromTasAngles; + diff->hklFromAnglesGiven = hklFromTasAnglesGiven; + diff->calcUBFromTwo = calcTasUBFromTwo; + diff->calcUBFromThree = calcTasUBFromThree; + diff->calcZ1 = calcTasZ1; +} diff --git a/singletas.h b/singletas.h new file mode 100644 index 00000000..b3ad0248 --- /dev/null +++ b/singletas.h @@ -0,0 +1,18 @@ +/** + * This is an implementation of the polymorphic single crystal calculation module + * for the triple axis mode. In this mode the tilt angles of a standard sample + * cradle are used to orient the sample. The math behind this has been decribed by + * Mark Lumsden in his paper. + * + * copyright: see file COPYRIGHT + * + * Mark Koennecke, November 2008 + */ +#ifndef SINGLETAS_H_ +#define SINGLETAS_H_ +#include "singlediff.h" + +void initializeSingleTas(pSingleDiff diff); + + +#endif /*SINGLETAS_H_*/ diff --git a/statemon.c b/statemon.c index 8141e5bf..db5f4c1c 100644 --- a/statemon.c +++ b/statemon.c @@ -22,8 +22,7 @@ typedef struct __STATEMON { pICallBack pCall; }StateMon; /*============================ Callbacks =================================*/ - static int DevexecCallback(int iEvent, void *text, void *pData, - commandContext cc){ + static int DevexecCallback(int iEvent, void *text, void *pData){ char pDevice[132]; int eventCode; pStateMon self = (pStateMon)pData; @@ -47,8 +46,7 @@ typedef struct __STATEMON { return 1; } /*---------------------------------------------------------------------------*/ -static int StateMonScanInterest(int iEvent, void *pEventData, void *pUser, - commandContext cc){ +static int StateMonScanInterest(int iEvent, void *pEventData, void *pUser){ pScanData pScan = NULL; pStateMon self = (pStateMon)pUser; @@ -69,8 +67,7 @@ static int StateMonScanInterest(int iEvent, void *pEventData, void *pUser, return 1; } /*--------------------------------------------------------------------------*/ -static int ExeCallback(int iEvent, void *pEvent, void *pUser, - commandContext cc){ +static int ExeCallback(int iEvent, void *pEvent, void *pUser){ pStateMon self = (pStateMon)pUser; char *name = (char *)pEvent; char pBueffel[131]; @@ -93,23 +90,26 @@ static int ExeCallback(int iEvent, void *pEvent, void *pUser, return 0; } /*=============== user callbacks ============================================*/ -static int StateInterest(int iEvent, void *pEvent, void *pUser, - commandContext cc){ +static int StateInterest(int iEvent, void *pEvent, void *pUser){ SConnection *pCon = (SConnection *)pUser; char *device = (char *)pEvent; char buffer[256]; + if(pCon == NULL || !SCisConnected(pCon)){ + return -1; + } + if(pCon == NULL || device == NULL){ printf("Bad StateInterest in statemon\n"); return 0; } if(iEvent == STSTART){ snprintf(buffer,255,"STARTED = %s", device); - SCWriteInContext(pCon,buffer,eWarning,cc); + SCWrite(pCon,buffer,eWarning); } if(iEvent == STEND){ snprintf(buffer,255,"FINISH = %s", device); - SCWriteInContext(pCon,buffer,eWarning,cc); + SCWrite(pCon,buffer,eWarning); } return 1; } @@ -172,14 +172,17 @@ static pHdb locateInterestNode(char *device){ return recurseInterestNode(current,pDevice); } /*--------------------------------------------------------------------------*/ -static int StateHdbInterest(int iEvent, void *pEvent, void *pUser, - commandContext cc){ +static int StateHdbInterest(int iEvent, void *pEvent, void *pUser){ SConnection *pCon = (SConnection *)pUser; char *device = (char *)pEvent, *path = NULL; char buffer[1024]; pHdb node = NULL; - if(pCon == NULL || device == NULL){ + if(pCon == NULL || !SCisConnected(pCon)){ + return -1; + } + + if(device == NULL){ printf("Bad StateHdbInterest in statemon\n"); return 0; } @@ -188,11 +191,11 @@ static int StateHdbInterest(int iEvent, void *pEvent, void *pUser, path = GetHipadabaPath(node); if(iEvent == STSTART){ snprintf(buffer,1024,"%s STARTED", path); - SCWriteInContext(pCon,buffer,eWarning,cc); + SCWrite(pCon,buffer,eWarning); } if(iEvent == STEND){ snprintf(buffer,1024,"%s FINISH", path); - SCWriteInContext(pCon,buffer,eWarning,cc); + SCWrite(pCon,buffer,eWarning); } if(path != NULL){ free(path); @@ -254,11 +257,11 @@ int StateMonFactory(SConnection *pCon, SicsInterp *pSics, void *pData, */ target = GetCallbackInterface(pDevexec); assert(target != NULL); - RegisterCallback(target,cc,DRIVSTAT,DevexecCallback,pNew,NULL); + RegisterCallback(target,DRIVSTAT,DevexecCallback,pNew,NULL); target = GetCallbackInterface(exe); assert(target != NULL); - RegisterCallback(target,cc,BATCHSTART,ExeCallback,pNew,NULL); - RegisterCallback(target,cc,BATCHEND,ExeCallback,pNew,NULL); + RegisterCallback(target,BATCHSTART,ExeCallback,pNew,NULL); + RegisterCallback(target,BATCHEND,ExeCallback,pNew,NULL); if(argc > 1) { pPtr = FindCommandData(pSics,argv[1],"ScanObject"); @@ -267,13 +270,10 @@ int StateMonFactory(SConnection *pCon, SicsInterp *pSics, void *pData, } else { target = GetCallbackInterface(pPtr); assert(target != NULL); - RegisterCallback(target,cc,SCANSTART,StateMonScanInterest,pNew,NULL); - RegisterCallback(target,cc,SCANEND,StateMonScanInterest,pNew,NULL); + RegisterCallback(target,SCANSTART,StateMonScanInterest,pNew,NULL); + RegisterCallback(target,SCANEND,StateMonScanInterest,pNew,NULL); } } - /* - * TODO: add kill functions - */ AddCommand(pSics,"statemon",StateMonAction,killStateMon,pNew); return 1; } @@ -283,6 +283,7 @@ int StateMonAction(SConnection *pCon, SicsInterp *pSics, void *pData, long lID; int i; pStateMon self = NULL; + SConnection *callCon = NULL; self = (pStateMon)pData; assert(self != NULL); @@ -293,11 +294,16 @@ int StateMonAction(SConnection *pCon, SicsInterp *pSics, void *pData, } strtolower(argv[1]); if(strcmp(argv[1],"interest") == 0){ - lID = RegisterCallback(self->pCall, SCGetContext(pCon),STSTART, StateInterest, - pCon, NULL); + callCon = SCCopyConnection(pCon); + if(callCon == NULL){ + SCWrite(pCon,"ERROR: out of memory registering interest",eError); + return 0; + } + lID = RegisterCallback(self->pCall, STSTART, StateInterest, + callCon, SCDeleteConnection); SCRegister(pCon,pSics, self->pCall,lID); - lID = RegisterCallback(self->pCall, SCGetContext(pCon),STEND, StateInterest, - pCon, NULL); + lID = RegisterCallback(self->pCall, STEND, StateInterest, + callCon, NULL); SCRegister(pCon,pSics, self->pCall,lID); SCSendOK(pCon); return 1; @@ -306,18 +312,20 @@ int StateMonAction(SConnection *pCon, SicsInterp *pSics, void *pData, lID = SCgetCallbackID(pCon,self->pCall); if(lID >= 0){ RemoveCallback(self->pCall,lID); - SCUnregisterID(pCon,lID); } } SCSendOK(pCon); return 1; } else if(strcmp(argv[1],"hdbinterest") == 0){ - lID = RegisterCallback(self->pCall, SCGetContext(pCon),STSTART, StateHdbInterest, - pCon, NULL); - SCRegister(pCon,pSics, self->pCall,lID); - lID = RegisterCallback(self->pCall, SCGetContext(pCon),STEND, StateHdbInterest, - pCon, NULL); - SCRegister(pCon,pSics, self->pCall,lID); + callCon = SCCopyConnection(pCon); + if(callCon == NULL){ + SCWrite(pCon,"ERROR: out of memory registering interest",eError); + return 0; + } + lID = RegisterCallback(self->pCall, STSTART, StateHdbInterest, + callCon, SCDeleteConnection); + lID = RegisterCallback(self->pCall, STEND, StateHdbInterest, + callCon, NULL); SCSendOK(pCon); return 1; } else if(strcmp(argv[1],"start") == 0) { diff --git a/statistics.c b/statistics.c index cfbfefb9..decfafde 100644 --- a/statistics.c +++ b/statistics.c @@ -51,8 +51,8 @@ int StatisticsCommand(SConnection *con, SicsInterp *pSics, void *pData, gettimeofday(&now, 0); dif = timeFloat(timeDif(lastStat, now)); - SCPrintf(con, eStatus, "calls/s time[%] full[%] mean[ms] command"); - SCPrintf(con, eStatus, "----------------------------------------------"); + SCPrintf(con, eValue, "calls/s time[%] full[%] mean[ms] command"); + SCPrintf(con, eValue, "----------------------------------------------"); for (p = list; p != NULL; p = p->next) { if (dif > 0) { calls = p->cnt / dif; @@ -64,7 +64,7 @@ int StatisticsCommand(SConnection *con, SicsInterp *pSics, void *pData, } else { dt = 0; } - SCPrintf(con, eStatus, "%7.1f %7.1f %7.1f %8.2f %s", calls, + SCPrintf(con, eValue, "%7.1f %7.1f %7.1f %8.2f %s", calls, percent, full, dt, p->name); } } @@ -74,8 +74,8 @@ int StatisticsCommand(SConnection *con, SicsInterp *pSics, void *pData, p->total.tv_sec = 0; p->total.tv_usec = 0; } - SCPrintf(con, eStatus, "----------------------------------------------"); - SCPrintf(con, eStatus, "total time %.2f", dif); + SCPrintf(con, eValue, "----------------------------------------------"); + SCPrintf(con, eValue, "total time %.2f", dif); lastStat = now; return 1; } diff --git a/status.c b/status.c index b88b60ca..2813aabd 100644 --- a/status.c +++ b/status.c @@ -184,8 +184,7 @@ return 1; } /*------------------- The CallBack function for interest ------------------*/ - static int StatusCallback(int iEvent, void *pEvent, void *pUser, - commandContext cc) + static int StatusCallback(int iEvent, void *pEvent, void *pUser) { SConnection *pCon; char pBueffel[80]; @@ -193,16 +192,17 @@ assert(pUser); pCon = (SConnection *)pUser; - + if(pCon == NULL || !SCisConnected(pCon)) + { + return -1; + } + sprintf(pBueffel,"status = %s", pText[(int)eCode]); - SCPushContext2(pCon,cc); - SCWrite(pCon,pBueffel,eWarning); - SCPopContext(pCon); + SCWrite(pCon,pBueffel,eLog); return 1; } /*------------------- The CallBack function for interest ------------------*/ - static int StatusHDBCallback(int iEvent, void *pEvent, void *pUser, - commandContext cc) + static int StatusHDBCallback(int iEvent, void *pEvent, void *pUser) { pHdb node = NULL; hdbValue v; @@ -210,7 +210,7 @@ assert(pUser); node = (pHdb)pUser; - v = MakeHdbText(strdup(pText[eCode])); + v = MakeHdbText(pText[eCode]); if(node != NULL && iEvent == VALUECHANGE){ UpdateHipadabaPar(node,v,NULL); } @@ -239,10 +239,9 @@ strtolower(argv[1]); if(strcmp(argv[1],"interest") == 0) { - lID = RegisterCallback(pCall, SCGetContext(pCon), + lID = RegisterCallback(pCall, VALUECHANGE, StatusCallback, - pCon, NULL); - SCRegister(pCon,pSics, pCall,lID); + SCCopyConnection(pCon), SCDeleteConnection); SCSendOK(pCon); return 1; } @@ -251,11 +250,10 @@ if(argc > 2){ node = GetHipadabaNode(GetHipadabaRoot(),argv[2]); if(node != NULL){ - lID = RegisterCallback(pCall, SCGetContext(pCon), + lID = RegisterCallback(pCall, VALUECHANGE, StatusHDBCallback, node, NULL); - /* SCRegister(pCon,pSics, pCall,lID); */ - SCSendOK(pCon); + SCSendOK(pCon); return 1; } else { SCWrite(pCon,"ERROR: Hipadaba node not found",eError); @@ -333,7 +331,7 @@ } /* check if the connection is dead at all */ - if(pCon->pSock) + if(pCon->sockHandle < 0) { SCWrite(pCon, "GOTCHA!!! Control still lives! You CANNOT grab it! FUCK OFF", @@ -342,6 +340,6 @@ } /* now the wizardry */ - pOwner->pSock = pCon->pSock; + pOwner->sockHandle = pCon->sockHandle; return 1; } diff --git a/stdscan.c b/stdscan.c index 2f1ae4d1..53949e12 100644 --- a/stdscan.c +++ b/stdscan.c @@ -99,14 +99,14 @@ void WriteTemplate(FILE *fd, FILE *temp, char *filename, pScanData pScan, if(!pCom) { sprintf(pError,"ERROR: variable %s NOT found",pName); - SCWrite(pCon,pError,eError); + SCWrite(pCon,pError,eLogError); continue; } pVar = (pSicsVariable)pCom->pData; if(!pVar) { sprintf(pError,"ERROR: variable %s NOT found",pName); - SCWrite(pCon,pError,eError); + SCWrite(pCon,pError,eLogError); continue; } switch(pVar->eType) @@ -143,21 +143,21 @@ void WriteTemplate(FILE *fd, FILE *temp, char *filename, pScanData pScan, if(!pCom) { sprintf(pError,"ERROR: variable %s NOT found",pName); - SCWrite(pCon,pError,eError); + SCWrite(pCon,pError,eLogError); continue; } pDum = (pDummy)pCom->pData; if(!pDum) { sprintf(pError,"ERROR: variable %s is NOT drivable",pName); - SCWrite(pCon,pError,eError); + SCWrite(pCon,pError,eLogError); continue; } pDriv = (pIDrivable)pDum->pDescriptor->GetInterface(pDum,DRIVEID); if(!pDriv) { sprintf(pError,"ERROR: variable %s is NOT drivable",pName); - SCWrite(pCon,pError,eError); + SCWrite(pCon,pError,eLogError); continue; } fVal = pDriv->GetValue(pDum,pCon); @@ -182,13 +182,13 @@ void WriteTemplate(FILE *fd, FILE *temp, char *filename, pScanData pScan, if(!pMot) { sprintf(pError,"ERROR: motor %s NOT found",pName); - SCWrite(pCon,pError,eError); + SCWrite(pCon,pError,eLogError); continue; } iRet = MotorGetPar(pMot,"softzero",&fVal); if(!iRet) { - SCWrite(pCon,"ERROR: failed to read zero point",eError); + SCWrite(pCon,"ERROR: failed to read zero point",eLogError); continue; } fprintf(fd,"%s %f\n",pBuffer,fVal); @@ -215,7 +215,7 @@ void WriteTemplate(FILE *fd, FILE *temp, char *filename, pScanData pScan, { SCWrite(pCon,"ERROR: failed to execute Tcl command",eError); strncpy(pBuffer, Tcl_GetStringResult(InterpGetTcl(pSics)), 511); - SCWrite(pCon,pBuffer,eError); + SCWrite(pCon,pBuffer,eLogError); continue; } } @@ -273,7 +273,7 @@ void WriteTemplate(FILE *fd, FILE *temp, char *filename, pScanData pScan, self->fd = fopen(self->pFile,"w"); if(!self->fd) { - SCWrite(self->pCon,"ERROR: cannot write data file",eError); + SCWrite(self->pCon,"ERROR: cannot write data file",eLogError); return 0; } @@ -281,7 +281,7 @@ void WriteTemplate(FILE *fd, FILE *temp, char *filename, pScanData pScan, fd = fopen(self->pHeaderFile,"r"); if(!fd) { - SCWrite(self->pCon,"ERROR: cannot open header description file",eError); + SCWrite(self->pCon,"ERROR: cannot open header description file",eLogError); return 0; } @@ -513,7 +513,7 @@ void WriteTemplate(FILE *fd, FILE *temp, char *filename, pScanData pScan, { SCWrite(self->pCon, "ERROR: Failed to reopen scan file, aborting scan", - eError); + eLogError); return 0; } @@ -615,13 +615,13 @@ int prepareDataFile(pScanData self){ { SCWrite(self->pCon, "ERROR: cannot allocate new data filename, Scan aborted", - eError); + eLogError); self->pCon = NULL; self->pSics = NULL; return 0; } snprintf(pBueffel,511,"Writing data file: %s ...",pPtr); - SCWrite(self->pCon,pBueffel,eWarning); + SCWrite(self->pCon,pBueffel,eLog); strcpy(self->pFile,pPtr); free(pPtr); return 1; @@ -657,7 +657,7 @@ int prepareDataFile(pScanData self){ { SCWrite(self->pCon, "WARNING: Internal error, no scan variable, I try to continue", - eWarning); + eLog); } pVar = NULL; } /* end for */ @@ -705,7 +705,7 @@ int prepareDataFile(pScanData self){ { SCWrite(self->pCon, "WARNING: Internal error, no scan variable, I try to continue", - eWarning); + eLog); } pVar = NULL; } /* end for */ @@ -743,7 +743,7 @@ int prepareDataFile(pScanData self){ { SCWrite(self->pCon, "WARNING: Internal error, no scan variable, I try to continue", - eWarning); + eLog); } pVar = NULL; } /* end for */ @@ -824,8 +824,8 @@ int prepareDataFile(pScanData self){ strcat(pHead,"\r\n"); strcat(pStatus,"\r\n"); */ - SCWrite(self->pCon,pHead,eWarning); - SCWrite(self->pCon,pStatus,eWarning); + SCWrite(self->pCon,pHead,eLog); + SCWrite(self->pCon,pStatus,eLog); return 1; } @@ -904,7 +904,7 @@ int prepareDataFile(pScanData self){ iRet = StartToDrive(self,iPoint); if(!iRet) { - SCWrite(self->pCon,"ERROR: Cannot Drive, Scan aborted",eError); + SCWrite(self->pCon,"ERROR: Cannot Drive, Scan aborted",eLogError); status = 0; } else @@ -939,7 +939,7 @@ int prepareDataFile(pScanData self){ iRet = StartToDrive(self,iPoint); if(!iRet) { - SCWrite(self->pCon,"ERROR: Cannot Drive, Scan aborted",eError); + SCWrite(self->pCon,"ERROR: Cannot Drive, Scan aborted",eLogError); status = 0; } else @@ -964,7 +964,7 @@ int prepareDataFile(pScanData self){ self->fPreset); if(!iRet) { - SCWrite(self->pCon,"ERROR: Cannot Count, Scan aborted",eError); + SCWrite(self->pCon,"ERROR: Cannot Count, Scan aborted",eLogError); return 0; } SetStatus(eCounting); @@ -983,12 +983,12 @@ static pDynString GetStandardInvocation(pScanData self, char *function){ result = CreateDynString(80,80); if(result == NULL){ - SCWrite(self->pCon,"ERROR: out of memory in scan invocation",eError); + SCWrite(self->pCon,"ERROR: out of memory in scan invocation",eLogError); return NULL; } if(StringDictGet(self->scanFunctions,function,value,131) != 1){ snprintf(value,131,"ERROR: scan function %s not found",function); - SCWrite(self->pCon,value,eError); + SCWrite(self->pCon,value,eLogError); DeleteDynString(result); return NULL; } diff --git a/tasscanub.c b/tasscanub.c index e8b8e24d..2b0fbbaf 100644 --- a/tasscanub.c +++ b/tasscanub.c @@ -200,7 +200,7 @@ static int TASUBHeader(pScanData self) self->fd = fopen(self->pFile,"w"); if(!self->fd) { - SCWrite(self->pCon,"ERROR: cannot write data file",eError); + SCWrite(self->pCon,"ERROR: cannot write data file",eLogError); return 0; } @@ -221,7 +221,7 @@ static int TASUBHeader(pScanData self) } else { - SCWrite(self->pCon,"WARNING: failed to decode file number",eWarning); + SCWrite(self->pCon,"WARNING: failed to decode file number",eLog); } /* the bizarre R, A, V header */ @@ -561,7 +561,7 @@ static int TASUBHeader(pScanData self) /* write header to screen as well */ - SCWrite(self->pCon,pHeader,eWarning); + SCWrite(self->pCon,pHeader,eLog); /* close the file, we will reopen later with append for the data @@ -598,7 +598,7 @@ static int TASUBScanPoint(pScanData self, int iPoint) self->fd = fopen(self->pFile,"a"); if(!self->fd) { - SCWrite(self->pCon,"ERROR: cannot append to data file",eError); + SCWrite(self->pCon,"ERROR: cannot append to data file",eLogError); return 0; } @@ -660,7 +660,7 @@ static int TASUBScanPoint(pScanData self, int iPoint) write both to file and onto screen */ fprintf(self->fd,"%s\n",pBueffel); - SCWrite(self->pCon,pBueffel,eWarning); + SCWrite(self->pCon,pBueffel,eLog); /* close the file @@ -785,12 +785,12 @@ static int TASUBScanCount(pScanData self, int iPoint) iRet = Wait4Success(GetExecutor()); if(iRet == DEVINT) { - SCWrite(self->pCon,"Counting aborted due to Interrupt",eStatus); + SCWrite(self->pCon,"Counting aborted due to Interrupt",eLog); status = 0; } else if(iRet == DEVERROR) { - SCWrite(self->pCon,"Counting finished with Problems",eStatus); + SCWrite(self->pCon,"Counting finished with Problems",eLog); status = 0; } else @@ -833,7 +833,7 @@ static int TASUBScanCount(pScanData self, int iPoint) { snprintf(pError,131,"WARNING: failed to read %s", ScanVarName(pVar)); - SCWrite(self->pCon,pError,eWarning); + SCWrite(self->pCon,pError,eLog); } AppendScanVar(pVar,fVal); } @@ -972,7 +972,7 @@ int TASUBPrepare(pScanData self) GetVarText("instrument"), pTAS->pScan->iNP, pTAS->pScan->iScanVar, pWork); - SCWrite(self->pCon,pLine,eWarning); + SCWrite(self->pCon,pLine,eLog); if(GetCounterMode(pTAS->pScan->pCounterData) == eTimer) { @@ -985,9 +985,9 @@ int TASUBPrepare(pScanData self) GetCounterPreset(pTAS->pScan->pCounterData)); } - SCWrite(self->pCon,pLine,eWarning); - SCWrite(self->pCon," ",eWarning); - SCWrite(self->pCon," ",eWarning); + SCWrite(self->pCon,pLine,eLog); + SCWrite(self->pCon," ",eLog); + SCWrite(self->pCon," ",eLog); /* snprintf(pLine,1023, @@ -1016,7 +1016,7 @@ int TASUBPrepare(pScanData self) getTasPar(pTAS->ub->current,KF), getTasPar(pTAS->ub->current,EF)); } - SCWrite(self->pCon,pLine,eWarning); + SCWrite(self->pCon,pLine,eLog); return status; } diff --git a/tasublib.c b/tasublib.c index eee5a650..6ceebb29 100644 --- a/tasublib.c +++ b/tasublib.c @@ -186,7 +186,7 @@ static MATRIX uFromAngles(double om, double sgu, double sgl){ return u; } /*---------------------------------------------------------------*/ -static MATRIX calcTasUVectorFromAngles(tasReflection r){ +MATRIX calcTasUVectorFromAngles(tasReflection r){ double theta, om; theta = calcTheta(r.qe.ki,r.qe.kf,r.angles.sample_two_theta); diff --git a/tasublib.h b/tasublib.h index fa8ee5bf..d41c9987 100644 --- a/tasublib.h +++ b/tasublib.h @@ -137,6 +137,13 @@ double maCalcK(maCrystal data, double two_theta); */ int makeAuxReflection(MATRIX B, tasReflection r1, tasReflection *r2, int ss); +/** + * calculate the scattering vector + * @param r The reflection for which to calculate the scattering vector. + * @return The scattering vector as a matrix + */ +MATRIX calcTasUVectorFromAngles(tasReflection r); + /** * calculate two theta for the reflection ref * @param B the metric matrix, or the UB diff --git a/telnet.c b/telnet.c index c4eca379..d845cfef 100644 --- a/telnet.c +++ b/telnet.c @@ -91,7 +91,7 @@ NETWrite(pCon->pSock,pReply,2); } /*--------------------------------------------------------------------------*/ - int TelnetTask(void *pData) + int TelnetTaskOld(void *pData) { pTelTask self = NULL; char *pPtr = NULL; @@ -204,6 +204,134 @@ } + /* check for end */ + if(self->pCon->iEnd) + { + if(SCActive(self->pCon)) + { + return 1; + } + else + { + return 0; + } + } + + return 1; + } +/*--------------------------------------------------------------------------*/ + int TelnetTask(void *pData) + { + pTelTask self = NULL; + char *pPtr = NULL; + char *pLogin = NULL; + char *pUser = NULL, *pPasswd = NULL; + char pBuffer[512], pHost[131]; + int iRet; + time_t shit; + + self = (pTelTask)pData; + assert(self); + + if(self->pCon->iEnd) + { + if(SCActive(self->pCon)) + { + return 1; + } + else + { + return 0; + } + } + + /* pop and execute */ + iRet = CostaPop(self->pCon->pStack,&pPtr); + if(iRet) + { + if(pPtr) + { + if(self->iLogin) /* handle normal command */ + { + /* check for logoff */ + if(strstr(pPtr,"logoff") != NULL) + { + ANETclose(self->pCon->sockHandle); + free(pPtr); + self->pCon->iEnd = 1; + return 0; + } + /* invoke command */ + CostaLock(self->pCon->pStack); + SCInvoke(self->pCon,pServ->pSics,pPtr); + CostaUnlock(self->pCon->pStack); + SendGA(self->pCon); + free(pPtr); + } + else /* handle login messages */ + { + pLogin = strstr(pPtr,self->pLoginWord); + if(!pLogin) + { + SCWrite(self->pCon, + "------------------- Get Lost -------------------", + eError); + if(time(&shit) > self->tStart + LOGINWAIT) + { + SCWrite(self->pCon, + "I cannot stand your login attempts anymore!", + eError); + ANETclose(self->pCon->sockHandle); + self->pCon->iEnd = 1; + free(pPtr); + return 0; + } + free(pPtr); + return 1; + } + else /* check username / password */ + { + pLogin += strlen(self->pLoginWord); + pUser = strtok(pLogin," \t"); + pPasswd = strtok(NULL," \t\r\n"); + iRet = IsValidUser(pUser,pPasswd); + if(iRet < 0) + { + sprintf(pBuffer,"SYSTEM ATTACK by %s / %s",pUser, + pPasswd); + SICSLogWrite(pBuffer,eInternal); + SCWrite(self->pCon, + "I do not know you, I do not let you in",eError); + SendGA(self->pCon); + free(pPtr); + return 1; + } + else + { + sprintf(pBuffer,"Accepted telnet connection on handle %d", + self->pCon->sockHandle); + SICSLogWrite(pBuffer,eInternal); + WriteToCommandLog("SYS >", pBuffer); + SendWelcome(self->pCon); + SCSetRights(self->pCon,iRet); + self->iLogin = 1; + SendGA(self->pCon); + free(pPtr); + return 1; + } + } + } + } + } + /* check for no commands but timeout on telnet */ + if( !self->iLogin && (time(&shit) > self->tStart + LOGINWAIT) ) + { + self->pCon->iEnd = 1; + ANETclose(self->pCon->sockHandle); + return 0; + } + + /* check for end */ if(self->pCon->iEnd) { @@ -273,16 +401,20 @@ return; } i = sscanf(pPtr,"%d",&iPort); + /* if(i > 0) { pTelnet = NETOpenPort(iPort); } - /* when we have a port have the NetReader listen and handle it */ if(pTelnet) { NetReadRegister(pServ->pReader,pTelnet, taccept, NULL); } + */ + /* when we have a port have the NetReader listen and handle it */ + NetReadInstallANETPort(pServ->pReader,taccept, iPort); + } /*---------------------------------------------------------------------------*/ void KillTelnet(void) @@ -296,3 +428,27 @@ } } +/*------------------------------------------------------------------------ + Telnet is fully described in RFC-854. This implementation is very simple. + It just supports the NVT and no options. Implementation is via a state + machine with the state tStatus in the pItem structure. This is necessary + as single characters may be sent by telnet clients. +-------------------------------------------------------------------------*/ +/* Telnet codes */ +#define SE 240 +#define NOP 241 +#define DM 242 /* data mark */ +#define BRK 243 +#define IP 244 +#define AO 245 +#define AYT 246 +#define EC 247 +#define EL 248 +#define GA 249 +#define SB 250 +#define WILL 251 +#define WONT 252 +#define DO 253 +#define DONT 254 +#define IAC 255 +#define EOR 239 diff --git a/ubcalc.c b/ubcalc.c index 6948264f..02054166 100644 --- a/ubcalc.c +++ b/ubcalc.c @@ -6,6 +6,10 @@ copyright: see file COPYRIGHT Mark Koennecke, March 2005 + + Heavily reworked to fit into the new four circle system + + Mark Koennecke, July 2008 -----------------------------------------------------------------------*/ #include #include @@ -17,6 +21,9 @@ #include "ubcalc.h" #include "motor.h" #include "hkl.h" +#include "singlex.h" +#include "reflist.h" +#include "singlediff.h" /*----------------------------------------------------------------------*/ static void killUBCALC(void *pData){ pUBCALC self = (pUBCALC)pData; @@ -37,18 +44,6 @@ static int SaveUBCalc(void *data, char *name, FILE *fd){ if(self == NULL){ return 0; } - fprintf(fd,"%s cell %f %f %f %f %f %f\n", name, self->direct.a, - self->direct.b, self->direct.c, self->direct.alpha, - self->direct.beta, self->direct.gamma); - fprintf(fd,"%s ref1 %f %f %f %f %f %f %f\n",name, - self->r1.h, self->r1.k, self->r1.l, - self->r1.s2t, self->r1.om, self->r1.chi, self->r1.phi); - fprintf(fd,"%s ref2 %f %f %f %f %f %f %f\n",name, - self->r2.h, self->r2.k, self->r2.l, - self->r2.s2t, self->r2.om, self->r2.chi, self->r2.phi); - fprintf(fd,"%s ref3 %f %f %f %f %f %f %f\n",name, - self->r3.h, self->r3.k, self->r3.l, - self->r3.s2t, self->r3.om, self->r3.chi, self->r3.phi); fprintf(fd,"%s difftheta %f\n", name, self->allowedDeviation); fprintf(fd, "%s maxindex %d\n", name, self->indexSearchLimit); fprintf(fd ,"%s maxlist %d\n", name, self->maxSuggestions); @@ -76,190 +71,41 @@ static pUBCALC makeUBCALC(pHKL hkl){ return pNew; } /*----------------------------------------------------------------------*/ +int CreateUBCalc(SConnection *pCon, SicsInterp *pSics, char *name, + char *hklname){ + pUBCALC pNew = NULL; + int status; + pHKL hkl = NULL; + + + hkl = FindCommandData(pSics,hklname,"4-Circle-Calculus"); + if(hkl == NULL){ + SCWrite(pCon,"ERROR: HKL object not found or wrong type",eError); + return 0; + } + + pNew = makeUBCALC(hkl); + if(pNew == NULL){ + SCWrite(pCon,"ERROR: out of memory creating UBCALC",eError); + return 0; + } + status = AddCommand(pSics,name,UBCalcWrapper,killUBCALC,pNew); + if(status != 1){ + SCWrite(pCon,"ERROR: failed to create duplicate UBCALC module",eError); + } + return status; +} +/*----------------------------------------------------------------------*/ int MakeUBCalc(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]){ - pUBCALC pNew = NULL; - int status; - pHKL hkl = NULL; - if(argc < 3){ - SCWrite(pCon,"ERROR: missing argument to MakeUBCalc: MakeUBCalc name hklobject",eError); - return 0; - } - - hkl = FindCommandData(pSics,argv[2],"4-Circle-Calculus"); - if(hkl == NULL){ - SCWrite(pCon,"ERROR: HKL object not found or wrong type",eError); - return 0; - } - - pNew = makeUBCALC(hkl); - if(pNew == NULL){ - SCWrite(pCon,"ERROR: out of memory creating UBCALC",eError); - return 0; - } - status = AddCommand(pSics,argv[1],UBCalcWrapper,killUBCALC,pNew); - if(status != 1){ - SCWrite(pCon,"ERROR: failed to create duplicate UBCALC module",eError); - } - return status; + if(argc < 3){ + SCWrite(pCon,"ERROR: missing argument to MakeUBCalc: MakeUBCalc name hklobject",eError); + return 0; + } + return CreateUBCalc(pCon,pSics,argv[1], argv[2]); } /*---------------------------------------------------------------------*/ -static int readCell(SConnection *pCon, pUBCALC self, int argc, char *argv[]){ - int status; - Tcl_Interp *pTcl = InterpGetTcl(pServ->pSics); - char pBueffel[256]; - - if(argc < 8){ - SCWrite(pCon,"ERROR: insufficient number of arguments to ubcalc cell", - eError); - return 0; - } - status = Tcl_GetDouble(pTcl,argv[2],&self->direct.a); - if(status != TCL_OK){ - snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - status = Tcl_GetDouble(pTcl,argv[3],&self->direct.b); - if(status != TCL_OK){ - snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[3]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - status = Tcl_GetDouble(pTcl,argv[4],&self->direct.c); - if(status != TCL_OK){ - snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[4]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - status = Tcl_GetDouble(pTcl,argv[5],&self->direct.alpha); - if(status != TCL_OK){ - snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[5]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - status = Tcl_GetDouble(pTcl,argv[6],&self->direct.beta); - if(status != TCL_OK){ - snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[6]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - status = Tcl_GetDouble(pTcl,argv[7],&self->direct.gamma); - if(status != TCL_OK){ - snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[7]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - SCparChange(pCon); - SCSendOK(pCon); - return 1; -} -/*--------------------------------------------------------------------*/ -static int readRefMotors(SConnection *pCon, SicsInterp *pSics, - reflection *r){ - pMotor pMot = NULL; - float val; - - pMot = FindMotor(pSics,"stt"); - if(pMot == NULL){ - SCWrite(pCon,"ERROR: cannot find stt motor",eError); - return 0; - } - MotorGetSoftPosition(pMot,pCon,&val); - r->s2t = val; - - pMot = FindMotor(pSics,"om"); - if(pMot == NULL){ - SCWrite(pCon,"ERROR: cannot find om motor",eError); - return 0; - } - MotorGetSoftPosition(pMot,pCon,&val); - r->om = val; - - pMot = FindMotor(pSics,"chi"); - if(pMot == NULL){ - SCWrite(pCon,"ERROR: cannot find chi motor",eError); - return 0; - } - MotorGetSoftPosition(pMot,pCon,&val); - r->chi = val; - - pMot = FindMotor(pSics,"phi"); - if(pMot == NULL){ - SCWrite(pCon,"ERROR: cannot find phi motor",eError); - return 0; - } - MotorGetSoftPosition(pMot,pCon,&val); - r->phi = val; - - SCparChange(pCon); - SCSendOK(pCon); - return 1; -} -/*---------------------------------------------------------------------*/ -static int readReflection(SConnection *pCon, SicsInterp *pSics, reflection *r, - int argc, char *argv[]){ - char pBueffel[255]; - int status; - Tcl_Interp *pTcl = InterpGetTcl(pSics); - - if(argc < 5){ - SCWrite(pCon,"ERROR: not enough arguments to ubcalc ref1,2",eError); - return 0; - } - status = Tcl_GetDouble(pTcl,argv[2],&r->h); - if(status != TCL_OK){ - snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[2]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - status = Tcl_GetDouble(pTcl,argv[3],&r->k); - if(status != TCL_OK){ - snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[3]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - status = Tcl_GetDouble(pTcl,argv[4],&r->l); - if(status != TCL_OK){ - snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[4]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - if(argc >= 9){ - status = Tcl_GetDouble(pTcl,argv[5],&r->s2t); - if(status != TCL_OK){ - snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[5]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - status = Tcl_GetDouble(pTcl,argv[6],&r->om); - if(status != TCL_OK){ - snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[6]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - status = Tcl_GetDouble(pTcl,argv[7],&r->chi); - if(status != TCL_OK){ - snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[7]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - status = Tcl_GetDouble(pTcl,argv[8],&r->phi); - if(status != TCL_OK){ - snprintf(pBueffel,255,"ERROR: failed to convert %s to number",argv[8]); - SCWrite(pCon,pBueffel,eError); - return 0; - } - SCparChange(pCon); - SCSendOK(pCon); - return 1; - } else { - return readRefMotors(pCon,pSics,r); - } -} -/*---------------------------------------------------------------------*/ static void listUB(SConnection *pCon, MATRIX UB){ Tcl_DString list; char pBueffel[255]; @@ -281,13 +127,90 @@ static void listUB(SConnection *pCon, MATRIX UB){ Tcl_DStringFree(&list); } /*---------------------------------------------------------------------*/ -static int calcUB(pUBCALC self, SConnection *pCon){ +static int updateUBCALC(pUBCALC self, SConnection *pCon, + char *id1, char *id2, char *id3){ + const double *cell; + double hkl[3], angles[4]; + pSICSOBJ refList; + + cell = SXGetCell(); + self->direct.a = cell[0]; + self->direct.b = cell[1]; + self->direct.c = cell[2]; + self->direct.alpha = cell[3]; + self->direct.beta = cell[4]; + self->direct.gamma = cell[5]; + + refList = SXGetReflectionList(); + if(id1 != NULL){ + if(!GetRefIndexID(refList,id1,hkl)){ + SCPrintf(pCon,eError,"ERROR: reflection with id %s not found",id1); + return 0; + } else { + self->r1.h = hkl[0]; + self->r1.k = hkl[1]; + self->r1.l = hkl[2]; + GetRefAnglesID(refList,id1,angles); + self->r1.s2t = angles[0]; + self->r1.om = angles[1]; + self->r1.chi = angles[2]; + self->r1.phi = angles[3]; + } + } + + if(id2 != NULL){ + if(!GetRefIndexID(refList,id2,hkl)){ + SCPrintf(pCon,eError,"ERROR: reflection with id %s not found",id2); + return 0; + } else { + self->r2.h = hkl[0]; + self->r2.k = hkl[1]; + self->r2.l = hkl[2]; + GetRefAnglesID(refList,id2,angles); + self->r2.s2t = angles[0]; + self->r2.om = angles[1]; + self->r2.chi = angles[2]; + self->r2.phi = angles[3]; + } + } + if(id3 != NULL){ + if(!GetRefIndexID(refList,id3,hkl)){ + SCPrintf(pCon,eError,"ERROR: reflection with id %s not found",id3); + return 0; + } else { + self->r3.h = hkl[0]; + self->r3.k = hkl[1]; + self->r3.l = hkl[2]; + GetRefAnglesID(refList,id3,angles); + self->r3.s2t = angles[0]; + self->r3.om = angles[1]; + self->r3.chi = angles[2]; + self->r3.phi = angles[3]; + } + } + return 1; +} +/*---------------------------------------------------------------------*/ +static int calcUB(pUBCALC self, SConnection *pCon, + char *ref1, char *ref2){ MATRIX newUB = NULL; int err = 1; - - newUB = calcUBFromCellAndReflections(self->direct, self->r1, self->r2, &err); + pSingleDiff single = NULL; + + if(!updateUBCALC(self,pCon,ref1,ref2,NULL)){ + return 0; + } + + single = SXGetDiffractometer(); + assert(single != NULL); + + newUB = single->calcUBFromTwo(single,ref1, ref2, &err); if(newUB == NULL){ switch(err){ + case REFERR: + SCWrite(pCon,"ERROR: one of reflections ID's is invalid",eError); + return 0; + break; case UBNOMEMORY: SCWrite(pCon,"ERROR: out of memory while calculating UB",eError); return 0; @@ -310,25 +233,6 @@ static int calcUB(pUBCALC self, SConnection *pCon){ } } /*---------------------------------------------------------------------*/ -static void listCell(SConnection *pCon, char *name, lattice direct){ - char pBueffel[255]; - - snprintf(pBueffel,255,"%s.cell = %f %f %f %f %f %f", - name,direct.a, direct.b,direct.c, - direct.alpha,direct.beta,direct.gamma); - SCWrite(pCon,pBueffel,eValue); - -} -/*---------------------------------------------------------------------*/ -static void listReflection(SConnection *pCon, char *name, - char *refName, reflection r){ - char pBueffel[255]; - - snprintf(pBueffel,255,"%s.%s = %f %f %f %f %f %f %f", - name,refName, r.h, r.k, r.l, r.s2t, r.om, r.chi, r.phi); - SCWrite(pCon,pBueffel,eValue); -} -/*---------------------------------------------------------------------*/ static int sendUBToHKL(SConnection *pCon, SicsInterp *pSics, pHKL hkl, MATRIX UB){ float ub[9]; @@ -346,7 +250,8 @@ static int sendUBToHKL(SConnection *pCon, SicsInterp *pSics, return 1; } /*---------------------------------------------------------------------*/ -static int setUBCalcParameters(pUBCALC self, SConnection *pCon, char *name, char *value){ +static int setUBCalcParameters(pUBCALC self, SConnection *pCon, + char *name, char *value){ if(strcmp(name,"difftheta") == 0){ if(!SCMatchRights(pCon,usUser)){ @@ -412,26 +317,27 @@ static void listPar(pUBCALC self, char *name, SConnection *pCon){ /*---------------------------------------------------------------------*/ static int findIndex(pUBCALC self, SConnection *pCon, SicsInterp *pSics, int argc, char *argv[]){ - float two_theta, lambda; + float two_theta; pMotor pMot = NULL; int status, numRef, i; refIndex *index = NULL; Tcl_DString list; char pLine[255]; - + double lambda; + if(argc > 2){ two_theta = atof(argv[2]); } else { - pMot = FindMotor(pSics,"stt"); + pMot = SXGetMotor(TwoTheta); if(pMot == NULL){ SCWrite(pCon,"ERROR: cannot find stt motor",eError); return 0; } MotorGetSoftPosition(pMot,pCon,&two_theta); } - - GetLambda(self->hkl,&lambda); - + lambda = SXGetLambda(); + updateUBCALC(self,pCon,NULL,NULL,NULL); + numRef = self->maxSuggestions; index = (refIndex *)malloc(numRef*sizeof(refIndex)); if(index == NULL){ @@ -476,18 +382,29 @@ static int findIndex(pUBCALC self, SConnection *pCon, SicsInterp *pSics, return 1; } /*---------------------------------------------------------------------*/ -static int calcUB3Ref(pUBCALC self, SConnection *pCon){ - float lambda; +static int calcUB3Ref(pUBCALC self, SConnection *pCon, + char *id1, char *id2, char *id3){ + double lambda; MATRIX newUB = NULL; int errCode = 1; char pBueffel[256]; - - GetLambda(self->hkl,&lambda); + pSingleDiff single = NULL; - newUB = calcUBFromThreeReflections(self->r1, self->r2, self->r3, - lambda, &errCode); + lambda = SXGetLambda(); + if(!updateUBCALC(self, pCon, id1, id2, id3)){ + return 0; + } + + single = SXGetDiffractometer(); + assert(single != NULL); + + newUB = single->calcUBFromThree(single,id1, id2, id3, &errCode); if(newUB == NULL){ switch(errCode){ + case REFERR: + SCWrite(pCon,"ERROR: one of reflections ID's is invalid",eError); + return 0; + break; case UBNOMEMORY: SCWrite(pCon,"ERROR: out of memory calculating UB",eError); break; @@ -517,8 +434,21 @@ static int cellFromUBWrapper(pUBCALC self, SConnection *pCon){ int status; char pBueffel[256]; lattice direct; - - status = cellFromUB(self->UB,&direct); + const double *ub; + MATRIX UB; + int i; + + UB = mat_creat(3,3,UNIT_MATRIX); + ub = SXGetUB(); + for(i = 0; i < 3; i++){ + UB[0][i] = ub[i]; + UB[1][i] = ub[i+3]; + UB[2][i] = ub[i+6]; + } + + status = cellFromUB(UB,&direct); + mat_free(UB); + if(status < 0){ switch(status){ case CELLNOMEMORY: @@ -530,7 +460,7 @@ static int cellFromUBWrapper(pUBCALC self, SConnection *pCon){ } return 0; } else { - snprintf(pBueffel,255," %8.4f %8.4f %8.4f %6.2f %6.2f %6.2f", + snprintf(pBueffel,255,"%f %f %f %f %f %f", direct.a, direct.b, direct.c, direct.alpha, direct.beta, direct.gamma); SCWrite(pCon,pBueffel,eValue); @@ -545,53 +475,29 @@ int UBCalcWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, assert(self); if(argc < 2){ - SCWrite(pCon,"Insuffcient number of arguments to ubcalc",eError); - return 0; + SCWrite(pCon,"Insuffcient number of arguments to ubcalc",eError); + return 0; } strtolower(argv[1]); - if(strcmp(argv[1],"cell") == 0){ - 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){ - return readReflection(pCon,pSics, &self->r2,argc,argv); - } else if(strcmp(argv[1],"ref3") == 0){ - return readReflection(pCon,pSics, &self->r3,argc,argv); - } else if(strcmp(argv[1],"listub") == 0){ + if(strcmp(argv[1],"listub") == 0){ listUB(pCon,self->UB); return 1; } else if(strcmp(argv[1],"ub2ref") == 0){ - return calcUB(self,pCon); + if(argc < 4){ + SCWrite(pCon,"Insuffcient number of arguments to ubcalc ub2ref",eError); + return 0; + } + return calcUB(self,pCon, argv[2], argv[3]); } else if(strcmp(argv[1],"ub3ref") == 0){ - return calcUB3Ref(self,pCon); + if(argc < 5){ + SCWrite(pCon,"Insuffcient number of arguments to ubcalc ub3ref",eError); + return 0; + } + return calcUB3Ref(self,pCon,argv[2],argv[3],argv[4]); } else if(strcmp(argv[1],"cellub") == 0){ return cellFromUBWrapper(self,pCon); - } else if(strcmp(argv[1],"listcell") == 0){ - listCell(pCon,argv[0],self->direct); - return 1; - } else if(strcmp(argv[1],"listref1") == 0){ - listReflection(pCon,argv[0],"ref1",self->r1); - return 1; - } else if(strcmp(argv[1],"listref2") == 0){ - listReflection(pCon,argv[0],"ref2",self->r2); - return 1; - } else if(strcmp(argv[1],"listref3") == 0){ - listReflection(pCon,argv[0],"ref3",self->r3); - return 1; - } else if(strcmp(argv[1],"list") == 0){ - listCell(pCon,argv[0],self->direct); - listReflection(pCon,argv[0],"ref1",self->r1); - listReflection(pCon,argv[0],"ref2",self->r2); - listReflection(pCon,argv[0],"ref3",self->r3); + }else if(strcmp(argv[1],"list") == 0){ listUB(pCon,self->UB); listPar(self,argv[0],pCon); return 1; diff --git a/ubcalc.h b/ubcalc.h index d83f94fe..2cea5157 100644 --- a/ubcalc.h +++ b/ubcalc.h @@ -29,6 +29,7 @@ typedef struct { /*-------------------------------------------------------------------*/ int MakeUBCalc(SConnection *pCon,SicsInterp *pSics, void *pData, int argc, char *argv[]); +int CreateUBCalc(SConnection *pCon,SicsInterp *pSics, char *name, char *hkl); int UBCalcWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); diff --git a/ubcalc.w b/ubcalc.w index a8d78d9d..7d2e56ff 100644 --- a/ubcalc.w +++ b/ubcalc.w @@ -36,6 +36,7 @@ typedef struct { /*-------------------------------------------------------------------*/ int MakeUBCalc(SConnection *pCon,SicsInterp *pSics, void *pData, int argc, char *argv[]); +int CreateUBCalc(SConnection *pCon,SicsInterp *pSics, char *name, char *hkl); int UBCalcWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); diff --git a/userscan.c b/userscan.c index 7b2a8c54..c40116d8 100644 --- a/userscan.c +++ b/userscan.c @@ -42,7 +42,7 @@ static int UserCount(pScanData self, int iPoint) { SCWrite(self->pCon, "ERROR: configuration error, need procedure to run for user scan", - eError); + eLogError); SCSetInterrupt(self->pCon,eAbortScan); return 0; } @@ -54,7 +54,7 @@ static int UserCount(pScanData self, int iPoint) { sprintf(pBueffel,"ERROR in count script: %s", Tcl_GetStringResult(self->pSics->pTcl)); - SCWrite(self->pCon,pBueffel,eError); + SCWrite(self->pCon,pBueffel,eLogError); return 0; } return 1; diff --git a/vector.c b/vector.c index baab347b..c8754240 100644 --- a/vector.c +++ b/vector.c @@ -69,7 +69,7 @@ void normalizeVector(MATRIX v){ double norm; norm = vectorLength(v); - if(norm > .001) { + if(norm > .00001) { for(i = 0; i < 3; i++){ v[i][0] /= norm; } diff --git a/velo.c b/velo.c index 75c9465d..184f6876 100644 --- a/velo.c +++ b/velo.c @@ -180,7 +180,7 @@ static void VSListForbidden(pVelSel self, SConnection *pCon){ self->pDriv->GetError(self->pDriv, &iCode, pError, 131); sprintf(pBueffel,"WARNING: trying to fix: %s", pError); - SCWrite(pCon,pBueffel,eStatus); + SCWrite(pCon,pBueffel,eLog); iTest = self->pDriv->TryAndFixIt(self->pDriv,iCode); switch(iTest) { @@ -291,7 +291,7 @@ static void VSListForbidden(pVelSel self, SConnection *pCon){ case VELOOK: case VELOREDO: sprintf(pBueffel,"WARNING: problem %s fixed",pError); - SCWrite(pCon,pBueffel,eStatus); + SCWrite(pCon,pBueffel,eLog); break; case VELOFAIL: sprintf(pBueffel,"ERROR: %s", pError); @@ -923,12 +923,15 @@ static void VSListForbidden(pVelSel self, SConnection *pCon){ { free(pCB->pName); } + if(pCB->pCon) + { + SCDeleteConnection(pCB->pCon); + } free(pCB); } } /*------------------------------------------------------------------------*/ - static int RotationInterest(int iEvent, void *pData, void *pUser, - commandContext cc) + static int RotationInterest(int iEvent, void *pData, void *pUser) { CBData *pDat = NULL; float *fVal = NULL; @@ -938,16 +941,20 @@ static void VSListForbidden(pVelSel self, SConnection *pCon){ pDat = (CBData *)pUser; assert(fVal); assert(pData); - + + if(!SCisConnected(pDat->pCon)){ + return -1; + } + if(iEvent == ROTSTART) { sprintf(pBueffel,"%s Starting",pDat->pName); - SCWriteInContext(pDat->pCon,pBueffel,eWarning,cc); + SCWrite(pDat->pCon,pBueffel,eWarning); } else if(iEvent == ROTMOVE) { sprintf(pBueffel,"%s.rpm = %f",pDat->pName, *fVal); - SCWriteInContext(pDat->pCon,pBueffel,eWarning,cc); + SCWrite(pDat->pCon,pBueffel,eWarning); } return 1; } @@ -1013,14 +1020,12 @@ static void VSListForbidden(pVelSel self, SConnection *pCon){ SCWrite(pCon,"ERROR: no memory in velo.c ",eError); return 0; } - pCB->pCon = pCon; + pCB->pCon = SCCopyConnection(pCon); pCB->pName = strdup(argv[0]); - lID = RegisterCallback(self->pCall, SCGetContext(pCon), ROTSTART, RotationInterest, + lID = RegisterCallback(self->pCall,ROTSTART, RotationInterest, pCB, KillCB); - SCRegister(pCon,pSics, self->pCall,lID); - lID = RegisterCallback(self->pCall, SCGetContext(pCon), ROTMOVE, RotationInterest, + lID = RegisterCallback(self->pCall, ROTMOVE, RotationInterest, pCB, NULL); - SCRegister(pCon,pSics, self->pCall,lID); SCSendOK(pCon); return 1; }