/*----------------------------------------------------------------------- N X S C R I P T This is a class for scripting the contents of NeXus files from SICS. copyright: see file COPYRIGHT Mark Koennecke, February 2003 Mark Koennecke, January 2004 added putHdb and putHdbSlab, Mark Koennecke, December 2008 ------------------------------------------------------------------------*/ #include #include #include #include #include #include #include #include #include #include "fortify.h" #include "sics.h" #include "splitter.h" #include "HistMem.h" #include "motor.h" #include "counter.h" #include "sicsvar.h" #include "danu.h" #include "udpquieck.h" #include "nxdict.h" #include "nxscript.h" #include "sicsdata.h" #include "sicshipadaba.h" extern char *trim(char *str); /* missing in nxdict.h: */ NXstatus NXDdefget(NXdict handle, char *pKey, char *pBuffer, int iBufLen); /*------------------------------------------------------------------------*/ char *makeFilename(SicsInterp * pSics, SConnection * pCon) { pSicsVariable pPath = NULL, pPref = NULL, pEnd = NULL; char *pRes = NULL; int iLen, iNum, iYear, thousand; char pNumText[10], pBueffel[256]; CommandList *pCom = NULL; DIR *dir = NULL; /* Try, get all the Variables */ pPath = FindVariable(pSics, "sicsdatapath"); pPref = FindVariable(pSics, "sicsdataprefix"); pCom = FindCommand(pSics, "sicsdatanumber"); pEnd = FindVariable(pSics, "sicsdatapostfix"); if ((!pPath) || (!pPref) || (!pCom) || (!pEnd)) { SCWrite(pCon, "ERROR: cannot read variables for automatic data file name creation", eError); SCWrite(pCon, "ERROR: This is a VERY, VERY, VERY serious installation problem", eError); SCWrite(pCon, "ERROR: your data will be dumped into emergency.hdf", eError); return NULL; } /* find length */ iLen = strlen(pPath->text) + 4; /* extra 4 for dir number */ iLen += strlen(pPref->text); iLen += 10; /* for number + year */ iLen += strlen(pEnd->text); iLen += 10; /* safety margin */ /* allocate memory */ pRes = (char *) malloc(iLen * sizeof(char)); if (!pRes) { SCWrite(pCon, "ERROR: no memory in makeFilename", eError); return NULL; } memset(pRes, 0, iLen); /* increment the data file number */ iNum = IncrementDataNumber(pCom->pData, &iYear); if (iNum < 0) { SCWrite(pCon, "ERROR: cannot increment data number!", eError); SCWrite(pCon, "ERROR: your data will be dumped to emergency.hdf", eError); free(pRes); return NULL; } strcpy(pRes, pPath->text); thousand = (int) floor(iNum / 1000.); snprintf(pNumText, 9, "%3.3d", thousand); strcat(pRes, pNumText); /* check for existence of directory and create if neccessary */ dir = opendir(pRes); if (dir == NULL) { mkdir(pRes, S_IRWXU | S_IRGRP | S_IXGRP); snprintf(pBueffel, 255, "Creating dir: %s", pRes); SCWrite(pCon, pBueffel, eLog); } else { closedir(dir); } /* build the rest of the filename */ strcat(pRes, "/"); strcat(pRes, pPref->text); snprintf(pNumText,sizeof(pNumText)-1, "%4.4d", iYear); strcat(pRes, pNumText); strcat(pRes, "n"); snprintf(pNumText,sizeof(pNumText)-1, "%6.6d", iNum); strcat(pRes, pNumText); strcat(pRes, pEnd->text); return pRes; } /*---------------------------------------------------------------------*/ void changeExtension(char *filename, char *newExtension) { char *pPtr = NULL; pPtr = strrchr(filename, (int) '.'); assert(pPtr != NULL); pPtr++; 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[]) { int status, i, iVal; NXaccess access; char buffer[512]; if (strcmp(argv[1], "close") == 0) { /* close everything! and send a message to trigger file synchronisation to the central server */ if (self->fileHandle == NULL) { SCSendOK(pCon); return 1; } i = 511; iVal = NX_CHAR; NXgetattr(self->fileHandle, "file_name", buffer, &i, &iVal); NXclose(&self->fileHandle); NXDclose(self->dictHandle, NULL); self->fileHandle = NULL; self->dictHandle = NULL; SendQuieck(QUIECK, buffer); SCSendOK(pCon); return 1; } else if (strcmp(argv[1], "reopen") == 0) { access = NXACC_RDWR; } else if (strcmp(argv[1], "create4") == 0) { access = NXACC_CREATE4; unlink(argv[2]); /* kill file for overwrite */ } else if (strcmp(argv[1], "create5") == 0) { access = NXACC_CREATE5; unlink(argv[2]); /* kill file for overwrite */ } else if (strcmp(argv[1], "createxml") == 0) { access = NXACC_CREATEXML; } else { return 0; } if (argc < 4) { SCWrite(pCon, "ERROR: insufficient number of arguments for file operation", eError); return -1; } /* be considerate: close files left open */ if (self->fileHandle != NULL) { NXclose(&self->fileHandle); self->fileHandle = NULL; } if (self->dictHandle != NULL) { NXDclose(self->dictHandle, NULL); self->dictHandle = NULL; } /* now initialize ourselves */ status = NXopen(argv[2], access, &self->fileHandle); if (status != NX_OK) { snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to open %s", argv[2]); SCWrite(pCon, buffer, eError); return -1; } status = NXDinitfromfile(argv[3], &self->dictHandle); if (status != NX_OK) { snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to open dictionary %s", argv[3]); SCWrite(pCon, buffer, eError); return -1; } SCSendOK(pCon); return 1; } /*----------------------------------------------------------------------*/ static void putMotor(SConnection * pCon, SicsInterp * pSics, pNXScript self, int argc, char *argv[]) { int status; pMotor brumm = NULL; float fVal; char buffer[132], dummy[256]; if (argc < 4) { SCWrite(pCon, "ERROR: insufficient number of arguments to putmotor", eLogError); return; } /* find motor */ brumm = (pMotor) FindCommandData(pSics, argv[3], "Motor"); if (!brumm) { snprintf(buffer,sizeof(buffer)-1, "ERROR: motor %s not found!", argv[3]); SCWrite(pCon, buffer, eLogError); return; } /* do position */ status = MotorGetSoftPosition(brumm, pCon, &fVal); if (!status) { snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to read position of %s", argv[3]); SCWrite(pCon, buffer, eLogError); return; } status = NXDputalias(self->fileHandle, self->dictHandle, argv[2], &fVal); if (status != NX_OK) { snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to write %s with alias %s", argv[3], argv[2]); SCWrite(pCon, buffer, eLogError); return; } /* if alias_null is available: write zero point */ strlcpy(buffer, argv[2],131); strlcat(buffer, "_null",131); if (NXDdefget(self->dictHandle, buffer, dummy, 255)) { MotorGetPar(brumm, "softzero", &fVal); status = NXDputalias(self->fileHandle, self->dictHandle, buffer, &fVal); if (status != NX_OK) { snprintf(buffer,131, "ERROR: failed to write %s zero with alias %s", argv[3], argv[2]); SCWrite(pCon, buffer, eLogError); return; } } } /*---------------------------------------------------------------------*/ static void putCounter(SConnection * pCon, SicsInterp * pSics, pNXScript self, int argc, char *argv[]) { pCounter cter = NULL; float fVal; long counts; char buffer[256], newAlias[256], dummy[80]; int status, i, icounts; CounterMode eMode; if (argc < 4) { SCWrite(pCon, "ERROR: insufficient number of arguments to putcounter", eLogError); return; } memset(dummy, 0, 80 * sizeof(char)); /* find counter */ cter = (pCounter) FindCommandData(pSics, argv[3], "SingleCounter"); if (!cter) { snprintf(buffer,sizeof(buffer)-1, "ERROR: counter %s not found!", argv[3]); SCWrite(pCon, buffer, eLogError); return; } /* do preset */ fVal = GetCounterPreset(cter); strlcpy(newAlias, argv[2],255); strlcat(newAlias, "_preset",255); status = NXDputalias(self->fileHandle, self->dictHandle, newAlias, &fVal); if (status != NX_OK) { snprintf(buffer,255, "ERROR: failed to write preset to %s", newAlias); SCWrite(pCon, buffer, eLogError); } /* do countmode */ eMode = GetCounterMode(cter); strcpy(newAlias, argv[2]); strcat(newAlias, "_mode"); if (eMode == eTimer) { strcpy(dummy, "timer"); } else { strcpy(dummy, "monitor"); } status = NXDputalias(self->fileHandle, self->dictHandle, newAlias, dummy); if (status != NX_OK) { snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to write counter mode to %s", newAlias); SCWrite(pCon, buffer, eLogError); } /* do time */ fVal = GetCountTime(cter, pCon); strlcpy(newAlias, argv[2],255); strlcat(newAlias, "_time",255); if (NXDdefget(self->dictHandle, newAlias, dummy, 79)) { status = NXDputalias(self->fileHandle, self->dictHandle, newAlias, &fVal); if (status != NX_OK) { snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to write count time to %s", newAlias); SCWrite(pCon, buffer, eLogError); } } /* do counter and monitors */ for (i = 0; i < 10; i++) { snprintf(newAlias,255, "%s_%2.2d", argv[2], i); if (NXDdefget(self->dictHandle, newAlias, dummy, 79)) { counts = GetMonitor(cter, i, pCon); icounts = (int) counts; status = NXDputalias(self->fileHandle, self->dictHandle, newAlias, &icounts); } } return; } /*----------------------------------------------------------------------*/ static void putSicsData(SConnection * pCon, SicsInterp * pSics, pNXScript self, int argc, char *argv[]) { pSICSData data = NULL; int status; char buffer[256]; if (argc < 4) { SCWrite(pCon, "ERROR: insufficient number of arguments to putSicsData", eLogError); return; } /* find data */ data = (pSICSData) FindCommandData(pSics, argv[3], "SICSData"); if (data == NULL) { snprintf(buffer, 255, "ERROR: sicsdata %s not found!", argv[3]); SCWrite(pCon, buffer, eLogError); return; } status = NXDputalias(self->fileHandle, self->dictHandle, argv[2], data->data); if (status != NX_OK) { snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to write sicsdata to %s", argv[2]); SCWrite(pCon, buffer, eLogError); } } /*----------------------------------------------------------------------*/ static void putAttribute(SConnection * pCon, SicsInterp * pSics, pNXScript self, int argc, char *argv[]) { int status, type = NX_CHAR; char buffer[256]; if (argc < 5) { SCWrite(pCon, "ERROR: insufficient number of arguments to putAttribute", eLogError); return; } status = NXDopenalias(self->fileHandle, self->dictHandle, argv[2]); if (status != NX_OK) { snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to open alias %s", argv[2]); SCWrite(pCon, buffer, eLogError); return; } status = NXputattr(self->fileHandle, argv[3], (void *) argv[4], strlen(argv[4]) + 1, type); if (status != NX_OK) { snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to write attribute %s", argv[3]); 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; int start[5], size[5]; 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 { strlcpy(alias, argv[3], 512); } } GetHipadabaPar(node, &v, pCon); if (argc > 3 && strcmp(argv[3], "point") == 0) { NXDopenalias(self->fileHandle, self->dictHandle, alias); start[0] = atoi(argv[4]); size[0] = 1; switch (v.dataType) { case HIPINT: NXputslab(self->fileHandle, &v.v.intValue, start, size); break; case HIPFLOAT: fVal = v.v.doubleValue; NXputslab(self->fileHandle, &fVal, start, size); break; } ReleaseHdbValue(&v); NXopenpath(self->fileHandle, "/"); return; } 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] = (float)v.v.floatArray[i]; } NXDputalias(self->fileHandle, self->dictHandle, alias, floatAr); free(floatAr); break; } ReleaseHdbValue(&v); } /*----------------------------------------------------------------------*/ static void putHdbOff(SConnection * pCon, SicsInterp * pSics, pNXScript self, int argc, char *argv[]) { pHdb node = NULL; char alias[512]; hdbValue v; float fVal, *floatAr = NULL; int i, offset; if (argc < 4) { SCWrite(pCon, "ERROR: putHdbOff needs at least a node name and an offset", 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 < 5) { SCPrintf(pCon, eLogError, "ERROR: neither nxalias property nor alias on command line found for %s", argv[2]); return; } else { strlcpy(alias, argv[4], 512); } } offset = atoi(argv[3]); GetHipadabaPar(node, &v, pCon); if(offset < 0 || offset > v.arrayLength){ SCPrintf(pCon,eLogError,"ERROR: invalid offset %d specified", offset ); return; } switch (v.dataType) { case HIPNONE: return; break; case HIPINTAR: case HIPINTVARAR: NXDputalias(self->fileHandle, self->dictHandle, alias, v.v.intArray+offset); 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+offset); free(floatAr); break; default: SCPrintf(pCon,eLogError,"ERROR: offsets can only be used with array data types"); return; } 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; char dummy[40], value[20]; const float *timeBin; /* update the dimension variables in the dictionary */ GetHistDim(mem, iDim, &rank); for (i = 0; i < rank; i++) { snprintf(dummy,sizeof(dummy)-1, "dim%1.1d", i); snprintf(value,sizeof(value)-1, "%d", iDim[i]); status = NXDupdate(self->dictHandle, dummy, value); if (status == 0) { NXDadd(self->dictHandle, dummy, value); } } timeBin = GetHistTimeBin(mem, &timeLength); if (timeLength > 2) { snprintf(dummy,sizeof(dummy)-1, "%d", timeLength); } else { snprintf(dummy,sizeof(dummy)-1, "%d", 1); } status = NXDupdate(self->dictHandle, "timedim", dummy); if (status == 0) { NXDadd(self->dictHandle, "timedim", dummy); } } /*---------------------------------------------------------------------- The sequence of things is important in here: The code for updating the dimensions variables also applies the time binning to the length. Thus subsets can only be checked for after that. And then we can allocate memory. -------------------------------------------------------------------------*/ static void putHistogramMemory(SConnection * pCon, SicsInterp * pSics, pNXScript self, int argc, char *argv[]) { pHistMem mem = NULL; int status, start, length, i, subset = 0, bank = 0; HistInt *iData = NULL; char buffer[256]; if (argc < 4) { SCWrite(pCon, "ERROR: insufficient number of arguments to puthm", eLogError); return; } /* find Histogram Memory */ mem = (pHistMem) FindCommandData(pSics, argv[3], "HistMem"); if (!mem) { snprintf(buffer,sizeof(buffer)-1, "ERROR: HistMem %s not found!", argv[3]); SCWrite(pCon, buffer, eLogError); return; } /* default: everything */ start = 0; length = GetHistLength(mem); updateHMDim(self, mem); /* check for further arguments specifying a subset */ if (argc > 5) { subset = 1; status = Tcl_GetInt(InterpGetTcl(pSics), argv[4], &start); if (status != TCL_OK) { snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to convert %s to integer", argv[4]); SCWrite(pCon, buffer, eLogError); return; } status = Tcl_GetInt(InterpGetTcl(pSics), argv[5], &length); if (status != TCL_OK) { snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to convert %s to integer", argv[5]); SCWrite(pCon, buffer, eLogError); return; } } /* * check for additional bank number */ if (argc > 6) { status = Tcl_GetInt(InterpGetTcl(pSics), argv[6], &bank); if (status != TCL_OK) { snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to convert %s to integer", argv[6]); SCWrite(pCon, buffer, eLogError); return; } } /* read HM */ if (subset) { iData = (HistInt *) malloc(length * sizeof(HistInt)); if (!iData) { SCWrite(pCon, "ERROR: out of memory for reading histogram memory", eLogError); return; } memset(iData, 0, length * sizeof(HistInt)); status = GetHistogramDirect(mem, pCon, bank, start, start + length, iData, length * sizeof(HistInt)); } else { /* status = GetHistogram(mem,pCon,0,start,length,iData, length*sizeof(HistInt)); */ iData = GetHistogramPointer(mem, pCon); if (iData == NULL) { status = 0; } else { status = 1; } } if (!status) { SCWrite(pCon, "ERROR: failed to read histogram memory", eLogError); if (subset) { free(iData); } return; } /* finally: write */ status = NXDputalias(self->fileHandle, self->dictHandle, argv[2], iData); if (status != NX_OK) { snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to write histogram memory data"); SCWrite(pCon, buffer, eLogError); } if (subset) { free(iData); } SCSendOK(pCon); return; } /*--------------------------------------------------------------------- defunct as of december 2003 */ static void putHistogramMemoryChunked(SConnection * pCon, SicsInterp * pSics, pNXScript self, int argc, char *argv[]) { pHistMem mem = NULL; int status, start, length, i, noChunks, chunkDim[MAXDIM], rank; HistInt *iData = NULL; char buffer[256]; int subset =0; if (argc < 5) { SCWrite(pCon, "ERROR: insufficient number of arguments to puthmchunked", eLogError); return; } /* find Histogram Memory */ mem = (pHistMem) FindCommandData(pSics, argv[3], "HistMem"); if (!mem) { snprintf(buffer,sizeof(buffer)-1, "ERROR: HistMem %s not found!", argv[3]); SCWrite(pCon, buffer, eLogError); return; } /* default: everything */ start = 0; length = GetHistLength(mem); updateHMDim(self, mem); /* check for an argument defining the number of chunks */ status = Tcl_GetInt(InterpGetTcl(pSics), argv[4], &noChunks); if (status != TCL_OK) { snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to convert %s to integer", argv[4]); SCWrite(pCon, buffer, eLogError); return; } /* read HM */ if (subset) { iData = (HistInt *) malloc(length * sizeof(HistInt)); if (!iData) { SCWrite(pCon, "ERROR: out of memory for reading histogram memory", eLogError); return; } memset(iData, 0, length * sizeof(HistInt)); status = GetHistogramDirect(mem, pCon, 0, start, start + length, iData, length * sizeof(HistInt)); } else { /* status = GetHistogram(mem,pCon,0,start,length,iData, length*sizeof(HistInt)); */ iData = GetHistogramPointer(mem, pCon); if (iData == NULL) { status = 0; } else { status = 1; } } if (!status) { SCWrite(pCon, "ERROR: failed to read histogram memory", eLogError); if (subset) { free(iData); } return; } /* finally: write */ status = NXDputalias(self->fileHandle, self->dictHandle, argv[2], iData); if (status != NX_OK) { snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to write histogram memory data"); SCWrite(pCon, buffer, eLogError); } if (subset) { free(iData); } SCSendOK(pCon); return; } /*----------------------------------------------------------------------*/ #define HANUM 3 static void putSlab(SConnection * pCon, SicsInterp * pSics, pNXScript self, int argc, char *argv[]) { int start[NX_MAXRANK], size[NX_MAXRANK]; int status, written = 0; pHistMem mem = NULL; HistInt *histData = NULL; pSICSData data = NULL; pCounter memsec = NULL; pHdb node = NULL; char buffer[256]; enum histargs { haStart, haLength, haBank }; int i, haIndex, hpars[HANUM], haFirst = 6; if (argc < 6) { SCWrite(pCon, "ERROR: insufficient number of arguments to putslab", eLogError); return; } status = NXDopenalias(self->fileHandle, self->dictHandle, argv[2]); if (status != NX_OK) { 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", eLogError); return; } status = listToArray(pSics, argv[4], size); if (status != TCL_OK) { SCWrite(pCon, "ERROR: failed to convert size value list", eLogError); return; } /* * try to write HM data */ mem = (pHistMem) FindCommandData(pSics, argv[5], "HistMem"); if (mem != NULL) { if (argc == 6) { histData = GetHistogramPointer(mem, pCon); } else if (argc > 6) { for (i = 0, haIndex = haFirst; i < HANUM; i++, haIndex++) { status = Tcl_GetInt(InterpGetTcl(pSics), argv[haIndex], &hpars[i]); if (status != TCL_OK) { sprintf(buffer, "ERROR: failed to convert %s to integer", argv[haIndex]); SCWrite(pCon, buffer, eError); return; } } histData = (HistInt *) malloc(hpars[haLength] * sizeof(HistInt)); if (!histData) { SCWrite(pCon, "ERROR: out of memory for reading histogram memory", eError); return; } memset(histData, 0, hpars[haLength] * sizeof(HistInt)); status = GetHistogramDirect(mem, pCon, hpars[haBank], hpars[haStart], hpars[haStart] + hpars[haLength], histData, hpars[haLength] * sizeof(HistInt)); } if (histData) { status = NXputslab(self->fileHandle, histData, start, size); if (status == NX_OK) { written = 1; } if (argc > 6) free(histData); } } /* * try to write second gen histogram data */ memsec = (pCounter) FindCommandData(pSics, argv[5], "HistMemSec"); if(memsec != NULL){ node = GetHipadabaNode(memsec->pDes->parNode,"data"); if(node == NULL){ SCWrite(pCon,"ERROR: ?? data node to second gen HM not found", eError); return; } status = NXputslab(self->fileHandle, node->value.v.intArray, start, size); if (status == NX_OK) { written = 1; } } /* * try to look for sicsdata */ data = (pSICSData) FindCommandData(pSics, argv[5], "SICSData"); if (data != NULL) { status = NXputslab(self->fileHandle, data->data, start, size); if (status == NX_OK) { written = 1; } } /* * drop out of hierarchy */ NXopenpath(self->fileHandle, "/"); if (written == 0) { SCWrite(pCon, "ERROR: failed to write data, data not recognised", eLogError); } } /*----------------------------------------------------------------------*/ static short *HistInt2Short(HistInt *data, int length) { int i; int16_t *shdata = NULL; shdata = malloc(length*sizeof(int16_t)); if(shdata == NULL){ return NULL; } memset(shdata,0,length*sizeof(int16_t)); for(i = 0; i < length; i++){ shdata[i] = (short)data[i]; } return shdata; } /*----------------------------------------------------------------------*/ static void putSlab16(SConnection * pCon, SicsInterp * pSics, pNXScript self, int argc, char *argv[]) { int start[NX_MAXRANK], size[NX_MAXRANK], dim[MAXDIM]; int status, written = 0, rank, i; pHistMem mem = NULL; HistInt *histData = NULL; int16_t *shortData = NULL; pHdb node = NULL; unsigned int length; pCounter memsec = NULL; if (argc < 6) { SCWrite(pCon, "ERROR: insufficient number of arguments to putslab", eLogError); return; } status = NXDopenalias(self->fileHandle, self->dictHandle, argv[2]); if (status != NX_OK) { 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", eLogError); return; } status = listToArray(pSics, argv[4], size); if (status != TCL_OK) { SCWrite(pCon, "ERROR: failed to convert size value list", eLogError); return; } /* * try to write HM data */ mem = (pHistMem) FindCommandData(pSics, argv[5], "HistMem"); if (mem != NULL) { histData = GetHistogramPointer(mem, pCon); if (histData) { GetHistDim(mem, dim,&rank); for(i = 0, length = 1; i < rank; i++){ length *= dim[i]; } shortData = HistInt2Short(histData,length); if(shortData != NULL){ status = NXputslab(self->fileHandle, shortData, start, size); free(shortData); } if (status == NX_OK) { written = 1; } } } /* * try to write second gen histogram data */ memsec = (pCounter) FindCommandData(pSics, argv[5], "HistMemSec"); if(memsec != NULL){ node = GetHipadabaNode(memsec->pDes->parNode,"data"); if(node == NULL){ SCWrite(pCon,"ERROR: ?? data node to second gen HM not found", eError); return; } GetHistDim((pHistMem)memsec, dim,&rank); for(i = 0, length = 1; i < rank; i++){ length *= dim[i]; } shortData = HistInt2Short(node->value.v.intArray,length); if(shortData != NULL){ status = NXputslab(self->fileHandle, shortData, start, size); free(shortData); } if (status == NX_OK) { written = 1; } } /* * drop out of hierarchy */ NXopenpath(self->fileHandle, "/"); if (written == 0) { SCWrite(pCon, "ERROR: failed to write data, data not recognised", eLogError); } } /*-------------------------------------------------------------------*/ static void putTimeBinning(SConnection * pCon, SicsInterp * pSics, pNXScript self, int argc, char *argv[]) { pHistMem mem = NULL; int i, status, timeLength; char buffer[256], defString[512], dummy[40]; const float *timeBin; float *timeCopy = NULL; if (argc < 4) { SCWrite(pCon, "ERROR: insufficient number of arguments to puttimebinning", eLogError); return; } /* find Histogram Memory */ mem = (pHistMem) FindCommandData(pSics, argv[3], "HistMem"); if (!mem) { snprintf(buffer,sizeof(buffer)-1, "ERROR: HistMem %s not found!", argv[3]); SCWrite(pCon, buffer, eLogError); return; } /* build definition string */ status = NXDdefget(self->dictHandle, argv[2], buffer, 254); if (!status) { snprintf(buffer,sizeof(buffer)-1, "ERROR: alias %s for time binning not found", argv[2]); SCWrite(pCon, buffer, eLogError); return; } timeBin = GetHistTimeBin(mem, &timeLength); snprintf(defString,sizeof(defString)-1, "%s -dim {%d} ", buffer, timeLength); /* Divide the time binning when appropriate and write */ if (self->timeDivisor != 1) { timeCopy = (float *) malloc(timeLength * sizeof(float)); if (timeCopy == NULL) { SCWrite(pCon, "ERROR: out of memory writing time binning", eLogError); return; } for (i = 0; i < timeLength; i++) { timeCopy[i] = timeBin[i] / self->timeDivisor; } status = NXDputdef(self->fileHandle, self->dictHandle, defString, (void *) timeCopy); free(timeCopy); } else { status = NXDputdef(self->fileHandle, self->dictHandle, defString, (void *) timeBin); } if (status != NX_OK) { snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to write time binning"); SCWrite(pCon, buffer, eLogError); } SCSendOK(pCon); return; } /*----------------------------------------------------------------------*/ static void putArray(SConnection * pCon, SicsInterp * pSics, pNXScript self, int argc, char *argv[]) { float *data = NULL; int length, i, status; char num[20]; char buffer[256], defString[512], *varData; Tcl_Interp *tcl = NULL; double dVal; if (argc < 5) { SCWrite(pCon, "ERROR: insufficient number of arguments to array", eLogError); return; } tcl = InterpGetTcl(pSics); assert(tcl != NULL); /* get array length */ status = Tcl_GetInt(tcl, argv[4], &length); if (status != TCL_OK) { snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to convert %s to integer in putarray", argv[4]); SCWrite(pCon, buffer, eLogError); return; } /* allocate */ if (length > 0) { data = (float *) malloc(length * sizeof(float)); } if (data == NULL) { snprintf(buffer, 255, "ERROR: out of memory or invalid length in putarray at %s, length = %s", argv[2], argv[4]); SCWrite(pCon, buffer, eLogError); return; } memset(data, 0, length * sizeof(float)); /* try getting data */ for (i = 0; i < length; i++) { snprintf(num,sizeof(num)-1, "%d", i); varData = (char *) Tcl_GetVar2(tcl, argv[3], num, 0); if (varData != NULL) { status = Tcl_GetDouble(tcl, varData, &dVal); if (status != TCL_OK) { snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to convert %s to double in putarray", varData); SCWrite(pCon, buffer, eLogError); } data[i] = (float) dVal; } else { snprintf(buffer, 254, "WARNING: failed to find array element %d in putarray", i); SCWrite(pCon, buffer, eLogError); } } /* build definition string */ status = NXDdefget(self->dictHandle, argv[2], buffer, 254); if (!status) { snprintf(buffer,sizeof(buffer)-1, "ERROR: alias %s for array not found in putarray", argv[2]); SCWrite(pCon, buffer, eLogError); free(data); return; } snprintf(defString, 511, "%s -dim {%d} ", buffer, length); /* write it! */ status = NXDputdef(self->fileHandle, self->dictHandle, defString, data); if (status != NX_OK) { snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to write array in putarray"); SCWrite(pCon, buffer, eLogError); } free(data); SCSendOK(pCon); } /*----------------------------------------------------------------------*/ static void putIntArray(SConnection * pCon, SicsInterp * pSics, pNXScript self, int argc, char *argv[]) { int *data = NULL; int length, i, status; char num[20]; char buffer[256], defString[512], *varData; Tcl_Interp *tcl = NULL; int iVal; if (argc < 5) { SCWrite(pCon, "ERROR: insufficient number of arguments to array", eLogError); return; } tcl = InterpGetTcl(pSics); assert(tcl != NULL); /* get array length */ status = Tcl_GetInt(tcl, argv[4], &length); if (status != TCL_OK) { snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to convert %s to integer", argv[4]); SCWrite(pCon, buffer, eLogError); return; } /* allocate */ if (length > 0) { data = (int *) malloc(length * sizeof(int)); } if (data == NULL) { SCWrite(pCon, "ERROR: out of memory or invalid length", eLogError); return; } memset(data, 0, length * sizeof(int)); /* try getting data */ for (i = 0; i < length; i++) { snprintf(num,sizeof(num)-1, "%d", i); varData = (char *) Tcl_GetVar2(tcl, argv[3], num, 0); if (varData != NULL) { status = Tcl_GetInt(tcl, varData, &iVal); if (status != TCL_OK) { snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to convert %s to int", varData); SCWrite(pCon, buffer, eLogError); } data[i] = iVal; } else { snprintf(buffer, 254, "WARNING: failed to find array element %d", i); SCWrite(pCon, buffer, eLogError); } } /* build definition string */ status = NXDdefget(self->dictHandle, argv[2], buffer, 254); if (!status) { snprintf(buffer,sizeof(buffer)-1, "ERROR: alias %s for array not found", argv[2]); SCWrite(pCon, buffer, eLogError); free(data); return; } snprintf(defString, 511, "%s -dim {%d} ", buffer, length); /* write it! */ status = NXDputdef(self->fileHandle, self->dictHandle, defString, data); if (status != NX_OK) { snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to write array"); SCWrite(pCon, buffer, eLogError); } free(data); SCSendOK(pCon); } /*----------------------------------------------------------------------*/ static void putGlobal(SConnection * pCon, SicsInterp * pSics, pNXScript self, int argc, char *argv[]) { char value[1024]; int status; if (argc < 4) { SCWrite(pCon, "ERROR: insufficient number of arguments to putglobal", eLogError); return; } Arg2Text(argc - 3, &argv[3], value, 1023); status = NXputattr(self->fileHandle, argv[2], value, strlen(value), NX_CHAR); if (status != NX_OK) { SCWrite(pCon, "ERROR: failed to write attribute", eLogError); } SCSendOK(pCon); } /*-----------------------------------------------------------------------*/ static int handlePut(SConnection * pCon, SicsInterp * pSics, pNXScript self, int argc, char *argv[]) { int status, iVal; char buffer[1024], defString[1024], numBuf[25]; double dVal; float fVal; /*============ */ if (strcmp(argv[1], "putfloat") == 0) { if (argc < 4) { SCWrite(pCon, "ERROR: insufficient number of arguments to putfloat", eLogError); return 1; } status = Tcl_GetDouble(InterpGetTcl(pSics), argv[3], &dVal); if (status != TCL_OK) { snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to convert %s to float", argv[3]); SCWrite(pCon, buffer, eLogError); return 1; } fVal = (float) dVal; status = NXDputalias(self->fileHandle, self->dictHandle, argv[2], &fVal); if (status != NX_OK) { snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to write %f to alias %s", fVal, argv[2]); 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", eLogError); return 1; } status = Tcl_GetInt(InterpGetTcl(pSics), argv[3], &iVal); if (status != TCL_OK) { snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to convert %s to int", argv[3]); SCWrite(pCon, buffer, eLogError); return 1; } status = NXDputalias(self->fileHandle, self->dictHandle, argv[2], &iVal); if (status != NX_OK) { snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to write %d to alias %s", iVal, argv[2]); 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", eLogError); return 1; } Arg2Text(argc - 3, &argv[3], buffer, 1023); trim(buffer); status = NXDdefget(self->dictHandle, argv[2], defString, 1023); if (status != NX_OK) { snprintf(buffer,sizeof(buffer)-1, "ERROR: alias %s not found in puttext", argv[2]); SCWrite(pCon, buffer, eLogError); return 1; } if (strlen(defString) < 900) { strlcat(defString, " -dim {",1024); snprintf(numBuf,sizeof(numBuf)-1, "%d", (int) strlen(buffer) + 1); strlcat(defString, numBuf,1024); strlcat(defString, " }",1024); } else { SCWrite(pCon, "ERROR: out of definition string space in puttext", eLogError); return 1; } status = NXDputdef(self->fileHandle, self->dictHandle, defString, buffer); if (status != NX_OK) { snprintf(buffer,sizeof(buffer)-1, "ERROR: failed to write alias %s", argv[2]); SCWrite(pCon, buffer, eLogError); } return 1; } else if (strcmp(argv[1], "putmot") == 0) { /*=========== */ putMotor(pCon, pSics, self, argc, argv); return 1; } else if (strcmp(argv[1], "putcounter") == 0) { /* ================ */ 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], "puthdboff") == 0) { /* ================ */ putHdbOff(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); return 1; } else if (strcmp(argv[1], "puttimebinning") == 0) { /*=================*/ putTimeBinning(pCon, pSics, self, argc, argv); } else if (strcmp(argv[1], "putarray") == 0) { /*================*/ putArray(pCon, pSics, self, argc, argv); } else if (strcmp(argv[1], "putintarray") == 0) { /*================*/ putIntArray(pCon, pSics, self, argc, argv); } else if (strcmp(argv[1], "putglobal") == 0) { /*===============*/ putGlobal(pCon, pSics, self, argc, argv); } else if (strcmp(argv[1], "putsicsdata") == 0) { /*===============*/ putSicsData(pCon, pSics, self, argc, argv); } else if (strcmp(argv[1], "putattribute") == 0) { /*===============*/ putAttribute(pCon, pSics, self, argc, argv); } else if (strcmp(argv[1], "putslab") == 0) { /*===============*/ putSlab(pCon, pSics, self, argc, argv); } else if (strcmp(argv[1], "putslab16") == 0) { /*===============*/ putSlab16(pCon, pSics, self, argc, argv); } else { SCPrintf(pCon, eLogError, "ERROR: put command %s not recognised", argv[1] ); } return 1; } /*----------------------------------------------------------------------*/ static void makeLink(SConnection * pCon, SicsInterp * pSics, pNXScript self, int argc, char *argv[]) { int status; char pBueffel[256]; if (argc < 4) { SCWrite(pCon, "ERROR: insufficient number of arguments to makelink", eLogError); return; } status = NXDaliaslink(self->fileHandle, self->dictHandle, argv[2], argv[3]); if (status != NX_OK) { snprintf(pBueffel, 255, "ERROR: linking %s against %s failed", argv[2], argv[3]); SCWrite(pCon, pBueffel, eLogError); return; } SCSendOK(pCon); } /*----------------------------------------------------------------------*/ static void makeNamedLink(SConnection * pCon, SicsInterp * pSics, pNXScript self, int argc, char *argv[]) { int status; char pBueffel[256]; if (argc < 5) { SCWrite(pCon, "ERROR: insufficient number of arguments to makenamedlink", eLogError); return; } status = NXDaliasnamedlink(self->fileHandle, self->dictHandle, argv[2], argv[3], argv[4]); if (status != NX_OK) { snprintf(pBueffel, 255, "ERROR: linking %s against %s as %s failed", argv[2], argv[3], argv[4]); SCWrite(pCon, pBueffel, eLogError); return; } SCSendOK(pCon); } /*----------------------------------------------------------------------*/ static void updateDictVar(SConnection * pCon, pNXScript self, int argc, char *argv[]) { int status; if (self->dictHandle == NULL) { SCWrite(pCon, "ERROR: cannot update variable, dictionary not open", eLogError); return; } if (argc < 4) { SCWrite(pCon, "ERROR: insufficient number of arguments to updateDictVar", eLogError); return; } NXDupdate(self->dictHandle, argv[2], argv[3]); } /*-----------------------------------------------------------------------*/ int NXScriptAction(SConnection * pCon, SicsInterp * pSics, void *pData, int argc, char *argv[]) { pNXScript self = (pNXScript) pData; char *pFile = NULL; int status; char buffer[132]; /* preliminary checks */ assert(self); if (!SCMatchRights(pCon, usUser)) { return 1; } if (argc < 2) { SCWrite(pCon, "ERROR: no keyword found", eLogError); return 1; } strtolower(argv[1]); if (strcmp(argv[1], "makefilename") == 0) { pFile = makeFilename(pSics, pCon); if (pFile != NULL) { SCWrite(pCon, pFile, eValue); free(pFile); return 1; } else { SCWrite(pCon, "ERROR: failed to create filename", eError); return 0; } } else if (strcmp(argv[1], "divisor") == 0) { if (argc < 3) { SCWrite(pCon, "ERROR: no divisor found", eLogError); return 1; } if (!SCMatchRights(pCon, usMugger)) { return 1; } self->timeDivisor = atoi(argv[2]); return 1; } status = handleFileOperations(pCon, self, argc, argv); if (status < 0) { return 0; } else if (status == 1) { return 1; } /* 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", eLogError); return 1; } if (strcmp(argv[1], "updatedictvar") == 0) { updateDictVar(pCon, self, argc, argv); return 1; } if (strstr(argv[1], "put") != NULL) { handlePut(pCon, pSics, self, argc, argv); return 1; } if (strcmp(argv[1], "isalias") == 0) { if (argc < 3) { SCWrite(pCon, "ERROR: need alias to test", eLogError); return 1; } if (NXDget(self->dictHandle, argv[2], buffer, 131) == NX_OK) { snprintf(buffer, 131, "%s = 1", argv[2]); } else { snprintf(buffer, 131, "%s = 0", argv[2]); } SCWrite(pCon, buffer, eValue); return 1; } if (strcmp(argv[1], "makelink") == 0) { makeLink(pCon, pSics, self, argc, argv); return 1; } if (strcmp(argv[1], "makenamedlink") == 0) { makeNamedLink(pCon, pSics, self, argc, argv); return 1; } return 1; } /*=============== make it ==============================================*/ static void KillNXScript(void *pData) { pNXScript self = (pNXScript) pData; if (self == NULL) { return; } if (self->pDes) { DeleteDescriptor(self->pDes); } if (self->fileHandle) { NXclose(&self->fileHandle); } if (self->dictHandle) { NXDclose(self->dictHandle, NULL); } free(self); } /*----------------------------------------------------------------------*/ int MakeNXScript(SConnection * pCon, SicsInterp * pSics, void *pData, int argc, char *argv[]) { pNXScript self = NULL; int status; self = (pNXScript) malloc(sizeof(NXScript)); if (self == NULL) { SCWrite(pCon, "ERROR: no memory for NXscript creation", eError); return 0; } memset(self, 0, sizeof(NXScript)); self->pDes = CreateDescriptor("NXScript"); if (self->pDes == NULL) { SCWrite(pCon, "ERROR: no memory for NXscript creation", eError); free(self); return 0; } self->timeDivisor = 1; /* create with with a default name if none specified */ if (argc > 1) { status = AddCommand(pSics, argv[1], NXScriptAction, KillNXScript, self); } else { status = AddCommand(pSics, "nxscript", NXScriptAction, KillNXScript, self); } if (!status) { SCWrite(pCon, "ERROR: duplicate NXScript object not created", eError); KillNXScript(self); return 0; } return 1; }