From 361ee9ebeaeb60dd704a061c77b323513c27a54e Mon Sep 17 00:00:00 2001 From: koennecke Date: Tue, 3 Feb 2009 08:05:39 +0000 Subject: [PATCH] - Reworked the connection object and the IO system - Reworked the support for TRICS - Added a second generation motor --- SCinter.c | 29 +- Scommon.h | 28 +- ascon.c | 18 +- ascon.h | 4 + asyncqueue.c | 6 +- background.c | 87 ++ background.h | 26 + callback.c | 255 +++-- cone.c | 300 +++--- cone.h | 11 +- confvirtualmot.c | 24 +- conman.c | 1045 ++++++++---------- conman.h | 166 ++- counter.c | 57 +- danu.c | 20 +- devexec.c | 288 ++--- devser.c | 11 +- devser.h | 8 +- diffscan.c | 4 +- drive.c | 8 +- dynstring.c | 13 + dynstring.h | 6 +- evcontroller.c | 49 +- evcontroller.i | 2 +- evcontroller.tex | 2 +- evcontroller.w | 2 +- exe.w | 1 + exebuf.c | 11 +- exebuf.h | 4 +- exebuf.i | 4 +- exeman.c | 104 +- exeman.i | 5 +- fitcenter.c | 4 +- fourlib.c | 4 +- fourlib.h | 4 +- fourmess.c | 778 ++++++++++++++ fourmess.h | 25 + fourtable.c | 2 +- genericcontroller.c | 11 +- histmem.c | 97 +- hkl.c | 1276 +++++----------------- hkl.h | 8 +- hkl.i | 9 +- hkl.tex | 38 +- hkl.w | 26 +- hklmot.c | 59 +- hmcontrol.c | 7 + initializer.c | 4 +- interface.c | 24 + interface.h | 36 +- interface.tex | 44 +- interface.w | 26 +- macro.c | 86 +- make_gen | 9 +- maximize.c | 10 +- mesure.c | 26 +- moregress.c | 6 + motor.c | 649 +++++------ motor.h | 14 +- motorsec.c | 749 +++++++++++++ motorsec.h | 14 + multicounter.c | 7 + nintf.c | 21 + nread.c | 392 ++++++- nread.h | 2 + nread.tex | 19 +- nread.w | 15 +- nserver.c | 7 +- nxscript.c | 370 +++++-- nxupdate.c | 10 +- obdes.h | 4 +- ofac.c | 26 +- optimise.c | 16 +- outcode.c | 2 + perfmon.c | 15 +- protocol.c | 47 +- remob.c | 49 +- rs232controller.c | 4 +- scan.c | 134 +-- script.c | 4 +- scriptcontext.c | 102 +- selector.c | 14 +- selvar.c | 22 +- servlog.c | 4 +- sgclib.c | 2505 +++++++++++++++++++++++++++++++++++++++++++ sgfind.c | 1174 ++++++++++++++++++++ sghkl.c | 280 +++++ sginfo.c | 1966 +++++++++++++++++++++++++++++++++ sginfo.h | 1789 ++++++++++++++++++++++++++++++ sgio.c | 1790 +++++++++++++++++++++++++++++++ sgsi.c | 445 ++++++++ sicscron.c | 6 +- sicshdbadapter.c | 26 +- sicshdbfactory.c | 8 +- sicshipadaba.c | 157 ++- sicshipadaba.h | 5 +- sicsobj.c | 112 +- sicsobj.h | 2 + sicvar.c | 19 +- simchop.c | 4 +- simidx.c | 679 ++++++++++++ simidx.h | 104 ++ sinfox.c | 6 +- singletas.c | 269 +++++ singletas.h | 18 + statemon.c | 76 +- statistics.c | 10 +- status.c | 32 +- stdscan.c | 46 +- tasscanub.c | 26 +- tasublib.c | 2 +- tasublib.h | 7 + telnet.c | 160 ++- ubcalc.c | 440 +++----- ubcalc.h | 1 + ubcalc.w | 1 + userscan.c | 4 +- vector.c | 2 +- velo.c | 29 +- 119 files changed, 16455 insertions(+), 3674 deletions(-) create mode 100644 background.c create mode 100644 background.h create mode 100644 fourmess.c create mode 100644 fourmess.h create mode 100644 motorsec.c create mode 100644 motorsec.h create mode 100644 sgclib.c create mode 100644 sgfind.c create mode 100644 sghkl.c create mode 100644 sginfo.c create mode 100644 sginfo.h create mode 100644 sgio.c create mode 100644 sgsi.c create mode 100644 simidx.c create mode 100644 simidx.h create mode 100644 singletas.c create mode 100644 singletas.h 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; }