First merge with ANSTO which compiles Conflicts: SICSmain.c asynnet.c confvirtualmot.c counter.c devexec.c drive.c exebuf.c hipadaba.c interface.h make_gen motor.c nserver.c nwatch.c ofac.c protocol.c sicshipadaba.c
1952 lines
46 KiB
C
1952 lines
46 KiB
C
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
Nexus Dictionary API implementation file.
|
|
|
|
For documentation see the nxdict.tex file which comes with this
|
|
distribution.
|
|
|
|
copyleft: Mark Koennecke
|
|
Labor fuer Neutronenstreuung
|
|
Paul Scherrer Institut
|
|
CH-5232 Villigen-PSI
|
|
Switzerland
|
|
Mark.Koennecke@psi.ch
|
|
|
|
No warranties of any kind, whether explicit or implied, taken.
|
|
Distributed under the GNU copyleft license as documented elsewhere.
|
|
|
|
August, 1997
|
|
|
|
Version: 1.0
|
|
|
|
Version 1.1
|
|
|
|
Updated to use the combined HDF4 HDF5 API. New keyword -chunk which
|
|
defines the chunk buffer size for a SDS.
|
|
|
|
Mark Koennecke, August 2001
|
|
|
|
-----------------------------------------------------------------------------*/
|
|
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <assert.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
#include "lld.h"
|
|
#include "napi.h"
|
|
#include "stringdict.h"
|
|
#include "dynstring.h"
|
|
#include "nxdict.h"
|
|
/*------------------ The magic number used for pointer checking */
|
|
#define NXDMAGIC 260558
|
|
/*--------------------------------------------------------------------------
|
|
Things defined in napi.c for error reporting
|
|
---------------------------------------------------------------------------*/
|
|
void *NXpData = NULL;
|
|
/*--------------------------------------------------------------------------*/
|
|
/* #define DEFDEBUG 1 */
|
|
/* define DEFDEBUG when you wish to print your definition strings before
|
|
action. This can help a lot to resolve mysteries when working with
|
|
dictionaries.
|
|
*/
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
|
|
typedef struct __NXdict {
|
|
int iID;
|
|
pStringDict pDictionary;
|
|
} sNXdict;
|
|
/*------------------ verbosity level -------------------------------------*/
|
|
static int iVerbosity = 0;
|
|
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
static char *NXDIReadFile(FILE * fd)
|
|
{
|
|
char *pNew = NULL;
|
|
long lLength = 0;
|
|
|
|
assert(fd);
|
|
|
|
/* determine length of file */
|
|
fseek(fd, 0L, SEEK_END);
|
|
lLength = ftell(fd);
|
|
if (lLength <= 0) {
|
|
return NULL;
|
|
}
|
|
fseek(fd, 0L, SEEK_SET);
|
|
|
|
/* allocate buffer */
|
|
lLength += 3;
|
|
pNew = (char *) malloc(lLength * sizeof(char));
|
|
if (!pNew) {
|
|
return NULL;
|
|
}
|
|
memset(pNew, 0, lLength); /* this ensures a 0 at the end */
|
|
|
|
/* read file */
|
|
fread(pNew, sizeof(char), lLength - 3, fd);
|
|
|
|
/* check for existence of the NXDICT string in the file */
|
|
if (strncmp(pNew, "##NXDICT-1.0", 12) != 0) {
|
|
NXReportError("ERROR: This is NO NXdict file");
|
|
free(pNew);
|
|
return NULL;
|
|
}
|
|
return pNew;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
|
|
#define FWORD 1
|
|
#define FHASH 2
|
|
#define FEOL 3
|
|
#define FEOB 4
|
|
#define FEQUAL 5
|
|
#define FSLASH 6
|
|
|
|
static char *NXDIfNextToken(char *pPtr, char *pToken, int *iToken)
|
|
{
|
|
pToken[0] = '\0';
|
|
/* skip whitespace */
|
|
while ((*pPtr == ' ') || (*pPtr == '\t')) {
|
|
pPtr++;
|
|
}
|
|
|
|
/* check for special characters */
|
|
if (*pPtr == '#') {
|
|
*iToken = FHASH;
|
|
pToken[0] = *pPtr;
|
|
pPtr++;
|
|
return pPtr;
|
|
} else if (*pPtr == '\n') {
|
|
*iToken = FEOL;
|
|
pToken[0] = *pPtr;
|
|
pPtr++;
|
|
return pPtr;
|
|
} else if (*pPtr == '\0') {
|
|
*iToken = FEOB;
|
|
pToken[0] = *pPtr;
|
|
pPtr++;
|
|
return pPtr;
|
|
} else if (*pPtr == '=') {
|
|
*iToken = FEQUAL;
|
|
pToken[0] = *pPtr;
|
|
pPtr++;
|
|
return pPtr;
|
|
} else if (*pPtr == '\\') {
|
|
*iToken = FSLASH;
|
|
pToken[0] = *pPtr;
|
|
pPtr++;
|
|
return pPtr;
|
|
} else {
|
|
*iToken = FWORD;
|
|
/* copy word to pToken */
|
|
while ((*pPtr != ' ') && (*pPtr != '\t') &&
|
|
(*pPtr != '\n') && (*pPtr != '\0') && (*pPtr != '=')) {
|
|
*pToken = *pPtr;
|
|
pPtr++;
|
|
pToken++;
|
|
}
|
|
*pToken = '\0';
|
|
return pPtr;
|
|
}
|
|
/* not reached */
|
|
return pPtr;
|
|
}
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
|
|
#define AMODE 0
|
|
#define DMODE 1
|
|
|
|
static void NXDIParse(char *pBuffer, pStringDict pDict)
|
|
{
|
|
char *pPtr;
|
|
int iToken;
|
|
int iMode;
|
|
char pAlias[1024];
|
|
char pDefinition[8192]; /* this is > 10 lines of definition */
|
|
char pWord[1024];
|
|
|
|
assert(pBuffer);
|
|
assert(pDict);
|
|
|
|
iMode = AMODE;
|
|
pPtr = pBuffer;
|
|
iToken = -1;
|
|
pDefinition[0] = '\0';
|
|
pAlias[0] = '\0';
|
|
pWord[0] = '\0';
|
|
|
|
while (iToken != FEOB) {
|
|
pPtr = NXDIfNextToken(pPtr, pWord, &iToken);
|
|
switch (iToken) {
|
|
case FHASH:
|
|
case FSLASH: /* skip over \n to next non blank */
|
|
while (*pPtr != '\n') {
|
|
pPtr++;
|
|
/* check for end of file */
|
|
if (*pPtr == '\0') {
|
|
return;
|
|
}
|
|
}
|
|
pPtr++;
|
|
break;
|
|
case FEQUAL: /* do a mode change */
|
|
iMode = DMODE;
|
|
pDefinition[0] = '\0';
|
|
break;
|
|
|
|
case FWORD:
|
|
if (iMode == AMODE) {
|
|
strcpy(pAlias, pWord);
|
|
} else {
|
|
strcat(pDefinition, pWord);
|
|
strcat(pDefinition, " ");
|
|
}
|
|
break;
|
|
case FEOL:
|
|
if (iMode == DMODE) {
|
|
/* enter in dictionary */
|
|
StringDictAddPair(pDict, pAlias, pDefinition);
|
|
iMode = AMODE;
|
|
pAlias[0] = '\0';
|
|
}
|
|
break;
|
|
case FEOB:
|
|
if (iMode == AMODE) {
|
|
/* empty line or a problem */
|
|
} else {
|
|
/* enter in dictionary */
|
|
StringDictAddPair(pDict, pAlias, pDefinition);
|
|
iMode = AMODE;
|
|
pAlias[0] = '\0';
|
|
}
|
|
return;
|
|
default:
|
|
assert(0); /* unrecognized token is a programming
|
|
error
|
|
*/
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
NXstatus NXDinitfromfile(char *filename, NXdict * pData)
|
|
{
|
|
NXdict pNew = NULL;
|
|
FILE *fd = NULL;
|
|
char *pBuffer = NULL;
|
|
char pError[512];
|
|
|
|
|
|
|
|
/* allocate a new NXdict structure */
|
|
if (iVerbosity == NXalot) {
|
|
NXReportError("Allocating new NXdict structure ");
|
|
}
|
|
pNew = (NXdict) malloc(sizeof(sNXdict));
|
|
if (!pNew) {
|
|
NXReportError("Insufficient memory for creation of NXdict");
|
|
return NX_ERROR;
|
|
}
|
|
|
|
/* initialise it */
|
|
pNew->iID = NXDMAGIC;
|
|
pNew->pDictionary = CreateStringDict();
|
|
if (!pNew->pDictionary) {
|
|
NXReportError("Insufficient memory for creation of NXdict");
|
|
free(pNew);
|
|
return NX_ERROR;
|
|
}
|
|
|
|
|
|
|
|
/* is there a file name argument */
|
|
if (filename == NULL) {
|
|
if (iVerbosity == NXalot) {
|
|
NXReportError("NXDinitfrom file finished without data");
|
|
}
|
|
*pData = pNew;
|
|
return NX_OK;
|
|
}
|
|
|
|
|
|
fd = fopen(filename, "rb");
|
|
if (!fd) {
|
|
sprintf(pError, "ERROR: file %s NOT found ", filename);
|
|
NXReportError(pError);
|
|
NXReportError("NXDinitfrom file finished without data");
|
|
*pData = pNew;
|
|
return NX_ERROR;
|
|
}
|
|
|
|
|
|
/* read the file contents */
|
|
if (iVerbosity == NXalot) {
|
|
NXReportError("NXDinitfrom: reading file");
|
|
}
|
|
pBuffer = NXDIReadFile(fd);
|
|
fclose(fd); /* we are done with it then */
|
|
if (!pBuffer) {
|
|
sprintf(pError, "ERROR: reading file %s or no memory", filename);
|
|
NXReportError(pError);
|
|
NXReportError("NXDinitfrom file finished without data");
|
|
*pData = pNew;
|
|
return NX_ERROR;
|
|
}
|
|
|
|
/* parse it */
|
|
if (iVerbosity == NXalot) {
|
|
NXReportError("NXDinitfrom: parsing dictionary definitions");
|
|
}
|
|
NXDIParse(pBuffer, pNew->pDictionary);
|
|
|
|
|
|
if (iVerbosity == NXalot) {
|
|
NXReportError("NXDinitfrom: performed successfully");
|
|
}
|
|
free(pBuffer);
|
|
*pData = pNew;
|
|
return NX_OK;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
NXdict NXDIAssert(NXdict handle)
|
|
{
|
|
NXdict self = NULL;
|
|
assert(handle);
|
|
self = (NXdict) handle;
|
|
assert(self->iID == NXDMAGIC);
|
|
return self;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
NXstatus NXDclose(NXdict handle, char *filename)
|
|
{
|
|
NXdict self;
|
|
const char *pKey = NULL;
|
|
char pValue[1024];
|
|
FILE *fd = NULL;
|
|
|
|
self = NXDIAssert(handle);
|
|
|
|
if (filename) { /* we must write a file */
|
|
if (iVerbosity == NXalot) {
|
|
sprintf(pValue, "Writing file %s", filename);
|
|
NXReportError(pValue);
|
|
}
|
|
fd = fopen(filename, "w");
|
|
if (!fd) {
|
|
sprintf(pValue, "ERROR: opening file %s for write", filename);
|
|
NXReportError(pValue);
|
|
return NX_ERROR;
|
|
}
|
|
|
|
/* write our magic recognition header */
|
|
fprintf(fd, "##NXDICT-1.0\n");
|
|
|
|
/* write all our keys */
|
|
pKey = StringDictGetNext(self->pDictionary, pValue, 1023);
|
|
while (pKey != NULL) {
|
|
fprintf(fd, "%s = %s\n", pKey, pValue);
|
|
pKey = StringDictGetNext(self->pDictionary, pValue, 1023);
|
|
}
|
|
fclose(fd);
|
|
if (iVerbosity == NXalot) {
|
|
sprintf(pValue, "File %s written", filename);
|
|
NXReportError(pValue);
|
|
}
|
|
}
|
|
|
|
/* now we send the cleaners in */
|
|
DeleteStringDict(self->pDictionary);
|
|
free(self);
|
|
return NX_OK;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
NXstatus NXDadd(NXdict handle, char *alias, char *pDef)
|
|
{
|
|
NXdict self;
|
|
int iRet;
|
|
|
|
self = NXDIAssert(handle);
|
|
iRet = StringDictAddPair(self->pDictionary, alias, pDef);
|
|
if (!iRet) {
|
|
return NX_ERROR;
|
|
}
|
|
return NX_OK;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
NXstatus NXDget(NXdict handle, char *pKey, char *pBuffer, int iBufLen)
|
|
{
|
|
NXdict self;
|
|
int iRet;
|
|
|
|
self = NXDIAssert(handle);
|
|
iRet = StringDictGet(self->pDictionary, pKey, pBuffer, iBufLen);
|
|
if (!iRet) {
|
|
return NX_ERROR;
|
|
}
|
|
#ifdef DEFDEBUG
|
|
printf("Resolved: %s to %s\n", pKey, pBuffer);
|
|
#endif
|
|
return NX_OK;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
NXstatus NXDupdate(NXdict handle, char *pKey, char *pNewVal)
|
|
{
|
|
NXdict self;
|
|
int iRet;
|
|
|
|
self = NXDIAssert(handle);
|
|
iRet = StringDictUpdate(self->pDictionary, pKey, pNewVal);
|
|
if (!iRet) {
|
|
return NX_ERROR;
|
|
}
|
|
return NX_OK;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
#define NORMAL 1
|
|
#define ALIAS 2
|
|
pDynString NXDItextreplace(NXdict handle, char *pDefString)
|
|
{
|
|
NXdict self;
|
|
int iRet, iPos, i;
|
|
pDynString pReplaced = NULL;
|
|
char pBueffel[1024];
|
|
char pBuffer2[1024];
|
|
char *pPtr;
|
|
int iState;
|
|
|
|
self = NXDIAssert(handle);
|
|
|
|
/* create a dynamic string */
|
|
pReplaced = CreateDynString(strlen(pDefString), 512);
|
|
if (!pReplaced) {
|
|
NXReportError("ERROR: out of memory in NXDtextreplace");
|
|
return NULL;
|
|
}
|
|
|
|
/* the loop */
|
|
iState = NORMAL;
|
|
for (i = 0, pPtr = pDefString; i < strlen(pDefString); i++, pPtr++) {
|
|
if (iState == NORMAL) {
|
|
if (*pPtr == '$') {
|
|
iState = ALIAS;
|
|
memset(pBueffel, 0, 1024);
|
|
iPos = 0;
|
|
} else {
|
|
DynStringConcatChar(pReplaced, *pPtr);
|
|
}
|
|
} else if (iState == ALIAS) {
|
|
switch (*pPtr) {
|
|
case '(': /* ignore */
|
|
break;
|
|
case ')':
|
|
/* do the replacement */
|
|
memset(pBuffer2, 0, 1023);
|
|
iRet = NXDget(handle, pBueffel, pBuffer2, 1023);
|
|
if (iRet != NX_OK) {
|
|
DeleteDynString(pReplaced);
|
|
return NULL;
|
|
}
|
|
DynStringConcat(pReplaced, pBuffer2);
|
|
iState = NORMAL;
|
|
break;
|
|
default:
|
|
pBueffel[iPos] = *pPtr;
|
|
iPos++;
|
|
if (iPos >= 1024) {
|
|
NXReportError("ERROR: buffer overrun in NXDItextreplace");
|
|
DeleteDynString(pReplaced);
|
|
return NULL;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#ifdef DEFDEBUG
|
|
printf("Replacement result: %s\n", GetCharArray(pReplaced));
|
|
#endif
|
|
return pReplaced;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
NXstatus NXDdefget(NXdict handle, char *pKey, char *pBuffer, int iBufLen)
|
|
{
|
|
int status;
|
|
pDynString pRep = NULL;
|
|
|
|
status = NXDget(handle, pKey, pBuffer, iBufLen);
|
|
if (status != NX_OK) {
|
|
return status;
|
|
}
|
|
|
|
pRep = NXDItextreplace(handle, pBuffer);
|
|
if (pRep) {
|
|
strncpy(pBuffer, GetCharArray(pRep), iBufLen);
|
|
status = NX_OK;
|
|
DeleteDynString(pRep);
|
|
} else {
|
|
status = NX_ERROR;
|
|
}
|
|
return status;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
NXstatus NXDtextreplace(NXdict handle, char *pDefString,
|
|
char *pBuffer, int iBufLen)
|
|
{
|
|
pDynString pResult = NULL;
|
|
char *pPtr = NULL;
|
|
|
|
pResult = NXDItextreplace(handle, pDefString);
|
|
if (!pResult) {
|
|
return NX_ERROR;
|
|
}
|
|
|
|
/* copy results home */
|
|
pPtr = GetCharArray(pResult);
|
|
strncpy(pBuffer, pPtr, iBufLen);
|
|
DeleteDynString(pResult);
|
|
return NX_OK;
|
|
}
|
|
|
|
/*------------------- The Defintion String Parser -----------------------*/
|
|
/*------- Data structures */
|
|
typedef struct {
|
|
char *pText;
|
|
int iCode;
|
|
} TokDat;
|
|
|
|
#define TERMSDS 100
|
|
#define TERMVG 200
|
|
#define TERMLINK 300
|
|
|
|
typedef struct {
|
|
char *pPtr;
|
|
char pToken[256];
|
|
int iToken;
|
|
int iDepth;
|
|
int iMayCreate;
|
|
int iTerminal;
|
|
} ParDat;
|
|
|
|
static void DummyError(void *p, char *pError)
|
|
{
|
|
return;
|
|
}
|
|
typedef struct {
|
|
char name[256];
|
|
char value[256];
|
|
} AttItem;
|
|
|
|
/*---------------- Token name defines ---------------------------*/
|
|
#define DSLASH 0
|
|
#define DKOMMA 1
|
|
#define DSDS 2
|
|
#define DLINK 3
|
|
#define DGROUP 4
|
|
#define DRANK 5
|
|
#define DDIM 6
|
|
#define DTYPE 7
|
|
#define DWORD 9
|
|
#define DOPEN 10
|
|
#define DCLOSE 11
|
|
#define DATTR 12
|
|
#define DEND 13
|
|
#define DLZW 14
|
|
#define DHUF 15
|
|
#define DRLE 16
|
|
#define CHUNK 17
|
|
|
|
/*----------------- Keywords ----------------------------------------*/
|
|
|
|
static TokDat TokenList[12] = {
|
|
{"SDS", DSDS},
|
|
{"NXLINK", DLINK},
|
|
{"NXVGROUP", DGROUP},
|
|
{"-dim", DDIM},
|
|
{"-type", DTYPE},
|
|
{"-rank", DRANK},
|
|
{"-attr", DATTR},
|
|
{"-chunk", CHUNK},
|
|
{"-LZW", DLZW},
|
|
{"-HUF", DHUF},
|
|
{"-RLE", DRLE},
|
|
{NULL, 0}
|
|
};
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
static void NXDIDefToken(ParDat * sStat)
|
|
{
|
|
int i;
|
|
|
|
|
|
sStat->pToken[0] = '\0';
|
|
|
|
/* skip whitespace */
|
|
while ((*(sStat->pPtr) == ' ') || (*(sStat->pPtr) == '\t')) {
|
|
sStat->pPtr++;
|
|
}
|
|
|
|
/* check for special characters */
|
|
if (*(sStat->pPtr) == '/') {
|
|
sStat->iToken = DSLASH;
|
|
sStat->pToken[0] = *(sStat->pPtr);
|
|
sStat->pPtr++;
|
|
return;
|
|
} else if (*(sStat->pPtr) == ',') {
|
|
sStat->iToken = DKOMMA;
|
|
sStat->pToken[0] = *(sStat->pPtr);
|
|
sStat->pPtr++;
|
|
return;
|
|
} else if (*(sStat->pPtr) == '\0') {
|
|
sStat->iToken = DEND;
|
|
sStat->pToken[0] = *(sStat->pPtr);
|
|
sStat->pPtr++;
|
|
return;
|
|
} else if (*(sStat->pPtr) == '{') {
|
|
sStat->iToken = DOPEN;
|
|
sStat->pToken[0] = *(sStat->pPtr);
|
|
sStat->pPtr++;
|
|
return;
|
|
} else if (*(sStat->pPtr) == '}') {
|
|
sStat->iToken = DCLOSE;
|
|
sStat->pToken[0] = *(sStat->pPtr);
|
|
sStat->pPtr++;
|
|
return;
|
|
} else {
|
|
sStat->iToken = DWORD;
|
|
/* copy word to pToken */
|
|
i = 0;
|
|
while ((*(sStat->pPtr) != ' ') && (*(sStat->pPtr) != '\t') &&
|
|
(*(sStat->pPtr) != '/') && (*(sStat->pPtr) != '\0') &&
|
|
(*(sStat->pPtr) != ',') && (*(sStat->pPtr) != '}')) {
|
|
sStat->pToken[i] = *(sStat->pPtr);
|
|
sStat->pPtr++;
|
|
i++;
|
|
}
|
|
sStat->pToken[i] = '\0';
|
|
|
|
/*--------- try to find word in Tokenlist */
|
|
for (i = 0; i < 11; i++) {
|
|
if (strcmp(sStat->pToken, TokenList[i].pText) == 0) {
|
|
sStat->iToken = TokenList[i].iCode;
|
|
break;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
/* not reached */
|
|
return;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
static void NXDIAttValue(ParDat * sStat)
|
|
{
|
|
int i;
|
|
|
|
|
|
sStat->pToken[0] = '\0';
|
|
|
|
/* skip whitespace */
|
|
while ((*(sStat->pPtr) == ' ') || (*(sStat->pPtr) == '\t')) {
|
|
sStat->pPtr++;
|
|
}
|
|
|
|
if (*(sStat->pPtr) == ',') {
|
|
sStat->iToken = DKOMMA;
|
|
sStat->pToken[0] = *(sStat->pPtr);
|
|
sStat->pPtr++;
|
|
return;
|
|
} else if (*(sStat->pPtr) == '\0') {
|
|
sStat->iToken = DEND;
|
|
sStat->pToken[0] = *(sStat->pPtr);
|
|
sStat->pPtr++;
|
|
return;
|
|
} else if (*(sStat->pPtr) == '{') {
|
|
sStat->iToken = DOPEN;
|
|
sStat->pToken[0] = *(sStat->pPtr);
|
|
sStat->pPtr++;
|
|
return;
|
|
} else if (*(sStat->pPtr) == '}') {
|
|
sStat->iToken = DCLOSE;
|
|
sStat->pToken[0] = *(sStat->pPtr);
|
|
sStat->pPtr++;
|
|
return;
|
|
} else if(*(sStat->pPtr) == '"') {
|
|
sStat->pPtr++;
|
|
sStat->iToken = DWORD;
|
|
i= 0;
|
|
while(*(sStat->pPtr) != '"') {
|
|
sStat->pToken[i] = *(sStat->pPtr);
|
|
sStat->pPtr++;
|
|
i++;
|
|
}
|
|
sStat->pToken[i] = '\0';
|
|
sStat->pPtr++;
|
|
return;
|
|
} else {
|
|
sStat->iToken = DWORD;
|
|
/* copy word to pToken */
|
|
i = 0;
|
|
while ((*(sStat->pPtr) != ' ') && (*(sStat->pPtr) != '\t') &&
|
|
(*(sStat->pPtr) != '\0') &&
|
|
(*(sStat->pPtr) != ',') && (*(sStat->pPtr) != '}')) {
|
|
sStat->pToken[i] = *(sStat->pPtr);
|
|
sStat->pPtr++;
|
|
i++;
|
|
}
|
|
sStat->pToken[i] = '\0';
|
|
return;
|
|
}
|
|
/* not reached */
|
|
return;
|
|
}
|
|
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
int NXDIParsePath(NXhandle hfil, ParDat * pParse)
|
|
{
|
|
int iRet, iToken;
|
|
char pName[132], pClass[132];
|
|
char pError[256];
|
|
void *pData = NULL;
|
|
|
|
/* get the name */
|
|
NXDIDefToken(pParse); /* next token */
|
|
if ((pParse->iToken == DSDS) || (pParse->iToken == DGROUP)
|
|
|| (pParse->iToken == DLINK)) {
|
|
/* put back & OK */
|
|
pParse->pPtr -= strlen(pParse->pToken);
|
|
return NX_OK;
|
|
}
|
|
if (pParse->iToken != DWORD) {
|
|
sprintf(pError, "ERROR: parse error at %s, expected vGroup name",
|
|
pParse->pToken);
|
|
NXReportError(pError);
|
|
return NX_ERROR;
|
|
}
|
|
strcpy(pName, pParse->pToken);
|
|
|
|
/* now we expect a komma */
|
|
NXDIDefToken(pParse); /* next token */
|
|
if (pParse->iToken != DKOMMA) {
|
|
sprintf(pError, "ERROR: parse error at %s, expected komma",
|
|
pParse->pToken);
|
|
NXReportError(pError);
|
|
return NX_ERROR;
|
|
}
|
|
|
|
/* next must be the class */
|
|
NXDIDefToken(pParse); /* next token */
|
|
if (pParse->iToken != DWORD) {
|
|
sprintf(pError, "ERROR: parse error at %s, expected vGroup class",
|
|
pParse->pToken);
|
|
NXReportError(pError);
|
|
return NX_ERROR;
|
|
}
|
|
strcpy(pClass, pParse->pToken);
|
|
|
|
/* done reading, ACTION, first install dummy error handler */
|
|
NXMDisableErrorReporting();
|
|
|
|
/* try opening vGroup */
|
|
iRet = NXopengroup(hfil, pName, pClass);
|
|
NXMEnableErrorReporting();
|
|
if (iRet == NX_OK) {
|
|
pParse->iDepth++;
|
|
return NX_OK;
|
|
} else {
|
|
/* we need to create it, if we may */
|
|
if (pParse->iMayCreate) {
|
|
iRet = NXmakegroup(hfil, pName, pClass);
|
|
if (iRet != NX_OK) {
|
|
/* a comment on this one has already been written! */
|
|
return iRet;
|
|
}
|
|
iRet = NXopengroup(hfil, pName, pClass);
|
|
if (iRet != NX_OK) {
|
|
/* a comment on this one has already been written! */
|
|
return iRet;
|
|
}
|
|
pParse->iDepth++;
|
|
return NX_OK;
|
|
} else {
|
|
/* this is an error */
|
|
sprintf(pError, "ERROR: vGroup %s, %s NOT found", pName, pClass);
|
|
NXReportError(pError);
|
|
return NX_ERROR;
|
|
}
|
|
}
|
|
/* not reached */
|
|
return NX_ERROR;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
static int NXDIParseAttr(ParDat * pParse, int iList)
|
|
{
|
|
char pError[256];
|
|
int iRet;
|
|
AttItem sAtt;
|
|
|
|
/* a { is expected */
|
|
NXDIDefToken(pParse);
|
|
if (pParse->iToken != DOPEN) {
|
|
sprintf(pError, "ERROR: expected {, got %s", pParse->pToken);
|
|
NXReportError(pError);
|
|
return NX_ERROR;
|
|
}
|
|
|
|
/* a word is expected */
|
|
NXDIDefToken(pParse);
|
|
if (pParse->iToken != DWORD) {
|
|
sprintf(pError, "ERROR: expected attribute name, got %s",
|
|
pParse->pToken);
|
|
NXReportError(pError);
|
|
return NX_ERROR;
|
|
}
|
|
strcpy(sAtt.name, pParse->pToken);
|
|
|
|
if(strstr(sAtt.name,"offset") != NULL){
|
|
printf("%s \n",sAtt.name);
|
|
}
|
|
|
|
/* a , is expected */
|
|
NXDIDefToken(pParse);
|
|
if (pParse->iToken != DKOMMA) {
|
|
sprintf(pError, "ERROR: expected , , got %s", pParse->pToken);
|
|
NXReportError(pError);
|
|
return NX_ERROR;
|
|
}
|
|
|
|
/* a word is expected */
|
|
NXDIAttValue(pParse);
|
|
if (pParse->iToken != DWORD) {
|
|
sprintf(pError, "ERROR: expected attribute value, got %s",
|
|
pParse->pToken);
|
|
NXReportError(pError);
|
|
return NX_ERROR;
|
|
}
|
|
strcpy(sAtt.value, pParse->pToken);
|
|
|
|
/* a } is expected */
|
|
NXDIDefToken(pParse);
|
|
if (pParse->iToken != DCLOSE) {
|
|
sprintf(pError, "ERROR: expected }, got %s", pParse->pToken);
|
|
NXReportError(pError);
|
|
return NX_ERROR;
|
|
}
|
|
|
|
/* enter into list */
|
|
LLDnodeAppendFrom(iList, &sAtt);
|
|
return NX_OK;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
static int NXDIParseDim(ParDat * pParse, int *iDim)
|
|
{
|
|
char pError[256];
|
|
int iRet, i;
|
|
|
|
/* initialise dimensions to 0 */
|
|
for (i = 0; i < NX_MAXRANK; i++) {
|
|
iDim[i] = 0;
|
|
}
|
|
|
|
NXDIDefToken(pParse);
|
|
if (pParse->iToken != DOPEN) {
|
|
sprintf(pError, "ERROR: expected {, got %s", pParse->pToken);
|
|
NXReportError(pError);
|
|
return NX_ERROR;
|
|
}
|
|
|
|
i = 0;
|
|
while (pParse->iToken != DCLOSE) {
|
|
/* get a number */
|
|
NXDIDefToken(pParse);
|
|
if (pParse->iToken != DWORD) {
|
|
sprintf(pError, "ERROR: expected number, got %s", pParse->pToken);
|
|
NXReportError(pError);
|
|
return NX_ERROR;
|
|
}
|
|
iDim[i] = atoi(pParse->pToken);
|
|
i++;
|
|
/* next must be close of komma */
|
|
NXDIDefToken(pParse);
|
|
if ((pParse->iToken != DKOMMA) && (pParse->iToken != DCLOSE)) {
|
|
sprintf(pError, "ERROR: expected , or }, got %s", pParse->pToken);
|
|
NXReportError( pError);
|
|
return NX_ERROR;
|
|
}
|
|
if (pParse->iToken == DCLOSE) {
|
|
break;
|
|
}
|
|
}
|
|
return NX_OK;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
static TokDat tDatType[] = {
|
|
{"DFNT_FLOAT32", NX_FLOAT32},
|
|
{"DFNT_FLOAT64", NX_FLOAT64},
|
|
{"DFNT_INT8", NX_INT8},
|
|
{"DFNT_UINT8", NX_UINT8},
|
|
{"DFNT_INT16", NX_INT16},
|
|
{"DFNT_UINT16", NX_UINT16},
|
|
{"DFNT_INT32", NX_INT32},
|
|
{"DFNT_UINT32", NX_UINT32},
|
|
{"DFNT_CHAR", NX_CHAR},
|
|
{"NX_FLOAT32", NX_FLOAT32},
|
|
{"NX_FLOAT64", NX_FLOAT64},
|
|
{"NX_INT8", NX_INT8},
|
|
{"NX_UINT8", NX_UINT8},
|
|
{"NX_INT16", NX_INT16},
|
|
{"NX_UINT16", NX_UINT16},
|
|
{"NX_INT32", NX_INT32},
|
|
{"NX_UINT32", NX_UINT32},
|
|
{"NX_CHAR", NX_CHAR},
|
|
{NULL, -122}
|
|
};
|
|
|
|
|
|
|
|
static int NXDIParseType(ParDat * pParse, int *iType)
|
|
{
|
|
char pError[256];
|
|
int i = 0;
|
|
|
|
NXDIDefToken(pParse);
|
|
if (pParse->iToken != DWORD) {
|
|
sprintf(pError, "ERROR: expected data type, got %s", pParse->pToken);
|
|
NXReportError(pError);
|
|
return NX_ERROR;
|
|
}
|
|
|
|
/* try to interpret data type */
|
|
while (tDatType[i].iCode > 0) {
|
|
if (strcmp(tDatType[i].pText, pParse->pToken) == 0) {
|
|
*iType = tDatType[i].iCode;
|
|
return NX_OK;
|
|
}
|
|
i++;
|
|
}
|
|
/* if we are here, the data type has not been recognized. Reason for
|
|
some boring error reporting code
|
|
*/
|
|
sprintf(pError, "ERROR: %s not recognized as valid data type",
|
|
pParse->pToken);
|
|
NXReportError(pError);
|
|
return NX_ERROR;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
static int NXDIParseSDS(NXhandle hfil, ParDat * pParse)
|
|
{
|
|
int iType = NX_FLOAT32;
|
|
int iRank = 1;
|
|
int iCompress = NX_COMP_NONE;
|
|
int iDim[NX_MAXRANK], iChunk[NX_MAXRANK];
|
|
int iList, iChunkDefined = 0;
|
|
int iRet, iStat, i;
|
|
char pError[256];
|
|
char pName[NX_MAXNAMELEN];
|
|
AttItem sAtt;
|
|
|
|
|
|
iDim[0] = 1;
|
|
/* first find the name */
|
|
NXDIDefToken(pParse);
|
|
if (pParse->iToken != DWORD) {
|
|
sprintf(pError, "ERROR: parsing, expected name, got %s",
|
|
pParse->pToken);
|
|
NXReportError(pError);
|
|
return NX_ERROR;
|
|
}
|
|
strcpy(pName, pParse->pToken);
|
|
|
|
/* create the attribute list */
|
|
iList = LLDcreate(sizeof(AttItem));
|
|
if (iList < 0) {
|
|
NXReportError("ERROR: cannot create list in NXDIParseSDS");
|
|
return NX_ERROR;
|
|
}
|
|
|
|
NXDIDefToken(pParse);
|
|
while (pParse->iToken != DEND) {
|
|
switch (pParse->iToken) {
|
|
case DRANK: /* rank */
|
|
NXDIDefToken(pParse); /* advance */
|
|
if (pParse->iToken != DWORD) {
|
|
sprintf(pError, "ERROR: expected int, got %s", pParse->pToken);
|
|
NXReportError(pError);
|
|
LLDdelete(iList);
|
|
return NX_ERROR;
|
|
}
|
|
iRank = atoi(pParse->pToken);
|
|
break;
|
|
case CHUNK: /* chunk size for compression */
|
|
iRet = NXDIParseDim(pParse, iChunk);
|
|
if (iRet == NX_ERROR) {
|
|
LLDdelete(iList);
|
|
return iRet;
|
|
}
|
|
iChunkDefined = 1;
|
|
break;
|
|
case DDIM:
|
|
iRet = NXDIParseDim(pParse, iDim);
|
|
if (iRet == NX_ERROR) {
|
|
LLDdelete(iList);
|
|
return iRet;
|
|
}
|
|
break;
|
|
case DTYPE:
|
|
iRet = NXDIParseType(pParse, &iType);
|
|
if (iRet == NX_ERROR) {
|
|
LLDdelete(iList);
|
|
return iRet;
|
|
}
|
|
break;
|
|
case DATTR:
|
|
iRet = NXDIParseAttr(pParse, iList);
|
|
if (iRet == NX_ERROR) {
|
|
LLDdelete(iList);
|
|
return iRet;
|
|
}
|
|
break;
|
|
case DLZW:
|
|
iCompress = NX_COMP_LZW;
|
|
break;
|
|
case DRLE:
|
|
iCompress = NX_COMP_RLE;
|
|
break;
|
|
case DHUF:
|
|
iCompress = NX_COMP_HUF;
|
|
break;
|
|
case DEND:
|
|
break;
|
|
default:
|
|
sprintf(pError, "ERROR: cannot identify token %s", pParse->pToken);
|
|
NXReportError(pError);
|
|
LLDdelete(iList);
|
|
return NX_ERROR;
|
|
|
|
}
|
|
NXDIDefToken(pParse);
|
|
}
|
|
|
|
/* whew! got all information for doing the SDS
|
|
However, if the chunk sizes for compression have not
|
|
been set, default them to the dimensions of the data set
|
|
*/
|
|
if (iChunkDefined == 0) {
|
|
for (i = 0; i < iRank; i++) {
|
|
iChunk[i] = iDim[i];
|
|
}
|
|
}
|
|
if (iChunk[0] < 0) {
|
|
iChunk[0] = 1;
|
|
}
|
|
|
|
/* first install dummy error handler, try open it, then
|
|
deinstall again and create if allowed
|
|
*/
|
|
NXMDisableErrorReporting();
|
|
|
|
/* try opening SDS */
|
|
iRet = NXopendata(hfil, pName);
|
|
NXMEnableErrorReporting();
|
|
if (iRet == NX_OK) {
|
|
LLDdelete(iList);
|
|
return NX_OK;
|
|
} else {
|
|
/* we need to create it, if we may */
|
|
if (pParse->iMayCreate) {
|
|
iRet = NXcompmakedata(hfil, pName, iType, iRank, iDim,
|
|
iCompress, iChunk);
|
|
if (iRet != NX_OK) {
|
|
/* a comment on this one has already been written! */
|
|
LLDdelete(iList);
|
|
return iRet;
|
|
}
|
|
iRet = NXopendata(hfil, pName);
|
|
if (iRet != NX_OK) {
|
|
/* a comment on this one has already been written! */
|
|
LLDdelete(iList);
|
|
return iRet;
|
|
}
|
|
|
|
/* put attributes in */
|
|
iRet = LLDnodePtr2First(iList);
|
|
while (iRet != 0) {
|
|
LLDnodeDataTo(iList, &sAtt);
|
|
iStat = NXputattr(hfil, sAtt.name,
|
|
sAtt.value, strlen(sAtt.value), NX_CHAR);
|
|
if (iStat != NX_OK) {
|
|
/* NeXus already complained bitterly */
|
|
LLDdelete(iList);
|
|
return iStat;
|
|
}
|
|
iRet = LLDnodePtr2Next(iList);
|
|
}
|
|
LLDdelete(iList);
|
|
return NX_OK;
|
|
} else {
|
|
/* this is an error */
|
|
sprintf(pError, "ERROR: SDS %s NOT found", pName);
|
|
NXReportError(pError);
|
|
LLDdelete(iList);
|
|
return NX_ERROR;
|
|
}
|
|
}
|
|
return NX_OK;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
static int NXDIParseLink(NXhandle hfil, NXdict pDict, ParDat * pParse)
|
|
{
|
|
char pError[256];
|
|
int i, iRet;
|
|
|
|
/* need one word of alias */
|
|
NXDIDefToken(pParse);
|
|
if (pParse->iToken != DCLOSE) {
|
|
sprintf(pError, "ERROR: expected alias , got %s", pParse->pToken);
|
|
NXReportError(pError);
|
|
return NX_ERROR;
|
|
}
|
|
|
|
/* move back in hierarchy */
|
|
for (i = 0; i < pParse->iDepth; i++) {
|
|
iRet = NXclosegroup(hfil);
|
|
if (iRet == NX_ERROR) {
|
|
return NX_ERROR;
|
|
}
|
|
}
|
|
|
|
/* open the link instead */
|
|
return NXDopenalias(hfil, pDict, pParse->pToken);
|
|
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
int NXDIDefParse(NXhandle hFil, NXdict pDict, ParDat * pParse)
|
|
{
|
|
int iRet;
|
|
char pError[256];
|
|
|
|
pParse->iToken = -1;
|
|
while (pParse->iToken != DEND) {
|
|
NXDIDefToken(pParse); /* next token */
|
|
switch (pParse->iToken) {
|
|
case DEND:
|
|
break;
|
|
case DSLASH:
|
|
iRet = NXDIParsePath(hFil, pParse);
|
|
if (iRet == NX_ERROR) {
|
|
return NX_ERROR;
|
|
}
|
|
break;
|
|
case DSDS:
|
|
iRet = NXDIParseSDS(hFil, pParse);
|
|
if (iRet == NX_ERROR) {
|
|
return NX_ERROR;
|
|
}
|
|
pParse->iTerminal = TERMSDS;
|
|
break;
|
|
case DLINK:
|
|
iRet = NXDIParseLink(hFil, pDict, pParse);
|
|
if (iRet == NX_ERROR) {
|
|
return NX_ERROR;
|
|
}
|
|
pParse->iTerminal = TERMLINK;
|
|
break;
|
|
case DGROUP:
|
|
pParse->iTerminal = TERMVG;
|
|
return NX_OK;
|
|
default:
|
|
sprintf(pError,
|
|
"ERROR: Definition String parse error: %s not permitted here",
|
|
pParse->pToken);
|
|
NXReportError(pError);
|
|
return NX_ERROR;
|
|
break;
|
|
}
|
|
}
|
|
return NX_OK;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
NXstatus NXDIUnwind(NXhandle hFil, int iDepth)
|
|
{
|
|
int i, iRet;
|
|
|
|
for (i = 0; i < iDepth; i++) {
|
|
iRet = NXclosegroup(hFil);
|
|
if (iRet != NX_OK) {
|
|
return NX_ERROR;
|
|
}
|
|
}
|
|
return NX_OK;
|
|
}
|
|
|
|
/*-------------------- The Data Transfer Functions ----------------------*/
|
|
NXstatus NXDopendef(NXhandle hfil, NXdict dict, char *pDef)
|
|
{
|
|
NXdict pDict;
|
|
ParDat pParse;
|
|
int iRet, i, iStat;
|
|
|
|
pDict = NXDIAssert(dict);
|
|
|
|
/* parse and act on definition string */
|
|
pParse.iMayCreate = 1;
|
|
pParse.pPtr = pDef;
|
|
pParse.iDepth = 0;
|
|
iRet = NXDIDefParse(hfil, pDict, &pParse);
|
|
if (iRet == NX_ERROR) {
|
|
/* unwind and throw up */
|
|
iRet = NXDIUnwind(hfil, pParse.iDepth);
|
|
return NX_ERROR;
|
|
}
|
|
|
|
return iRet;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
NXstatus NXDopenalias(NXhandle hfil, NXdict dict, char *pAlias)
|
|
{
|
|
NXdict pDict;
|
|
int iRet;
|
|
char pDefinition[2048];
|
|
pDynString pReplaced = NULL;
|
|
|
|
pDict = NXDIAssert(dict);
|
|
|
|
/* get Definition String */
|
|
iRet = NXDget(pDict, pAlias, pDefinition, 2047);
|
|
if (iRet != NX_OK) {
|
|
sprintf(pDefinition, "ERROR: alias %s not recognized", pAlias);
|
|
NXReportError(pDefinition);
|
|
return NX_ERROR;
|
|
}
|
|
|
|
/* do the text replacement */
|
|
pReplaced = NXDItextreplace(dict, pDefinition);
|
|
if (!pReplaced) {
|
|
return NX_ERROR;
|
|
}
|
|
|
|
/* call NXDopendef */
|
|
iRet = NXDopendef(hfil, dict, GetCharArray(pReplaced));
|
|
DeleteDynString(pReplaced);
|
|
return iRet;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
NXstatus NXDputdef(NXhandle hFil, NXdict dict, char *pDef, void *pData)
|
|
{
|
|
NXdict pDict;
|
|
ParDat pParse;
|
|
int iRet, i, iStat;
|
|
|
|
pDict = NXDIAssert(dict);
|
|
|
|
/* parse and act on definition string */
|
|
pParse.iMayCreate = 1;
|
|
pParse.pPtr = pDef;
|
|
pParse.iDepth = 0;
|
|
#ifdef DEFDEBUG
|
|
printf("Putting: %s\n", pDef);
|
|
#endif
|
|
iRet = NXDIDefParse(hFil, pDict, &pParse);
|
|
if (iRet == NX_ERROR) {
|
|
NXDIUnwind(hFil, pParse.iDepth);
|
|
return NX_ERROR;
|
|
}
|
|
|
|
|
|
/* only SDS can be written */
|
|
if (pParse.iTerminal != TERMSDS) {
|
|
NXReportError("ERROR: can only write to an SDS!");
|
|
iStat = NX_ERROR;
|
|
} else {
|
|
/* the SDS should be open by now, write it */
|
|
iStat = NXputdata(hFil, pData);
|
|
iRet = NXclosedata(hFil);
|
|
}
|
|
|
|
|
|
/* rewind the hierarchy */
|
|
iRet = NXDIUnwind(hFil, pParse.iDepth);
|
|
if (iRet != NX_OK) {
|
|
return NX_ERROR;
|
|
}
|
|
return iStat;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
NXstatus NXDputalias(NXhandle hFil, NXdict dict, char *pAlias, void *pData)
|
|
{
|
|
NXdict pDict;
|
|
int iRet;
|
|
char pDefinition[2048];
|
|
pDynString pReplaced = NULL;
|
|
|
|
pDict = NXDIAssert(dict);
|
|
|
|
/* get Definition String */
|
|
iRet = NXDget(pDict, pAlias, pDefinition, 2047);
|
|
if (iRet != NX_OK) {
|
|
sprintf(pDefinition, "ERROR: alias %s not recognized", pAlias);
|
|
NXReportError( pDefinition);
|
|
return NX_ERROR;
|
|
}
|
|
|
|
/* do text replacement */
|
|
pReplaced = NXDItextreplace(dict, pDefinition);
|
|
if (!pReplaced) {
|
|
return NX_ERROR;
|
|
}
|
|
|
|
/* call NXDputdef */
|
|
iRet = NXDputdef(hFil, dict, GetCharArray(pReplaced), pData);
|
|
DeleteDynString(pReplaced);
|
|
return iRet;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
NXstatus NXDgetdef(NXhandle hFil, NXdict dict, char *pDef, void *pData)
|
|
{
|
|
NXdict pDict;
|
|
ParDat pParse;
|
|
int iRet, i, iStat;
|
|
|
|
pDict = NXDIAssert(dict);
|
|
|
|
/* parse and act on definition string */
|
|
pParse.iMayCreate = 0;
|
|
pParse.pPtr = pDef;
|
|
pParse.iDepth = 0;
|
|
#ifdef DEFDEBUG
|
|
printf("Getting: %s\n", pDef);
|
|
#endif
|
|
iRet = NXDIDefParse(hFil, pDict, &pParse);
|
|
if (iRet == NX_ERROR) {
|
|
/* unwind and throw up */
|
|
NXDIUnwind(hFil, pParse.iDepth);
|
|
return NX_ERROR;
|
|
}
|
|
|
|
|
|
/* only SDS can be written */
|
|
if (pParse.iTerminal != TERMSDS) {
|
|
NXReportError("ERROR: can only write to an SDS!");
|
|
iStat = NX_ERROR;
|
|
} else {
|
|
/* the SDS should be open by now, read it */
|
|
iStat = NXgetdata(hFil, pData);
|
|
iRet = NXclosedata(hFil);
|
|
}
|
|
|
|
|
|
/* rewind the hierarchy */
|
|
iRet = NXDIUnwind(hFil, pParse.iDepth);
|
|
if (iRet != NX_OK) {
|
|
return NX_ERROR;
|
|
}
|
|
return iStat;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
NXstatus NXDgetalias(NXhandle hFil, NXdict dict, char *pAlias, void *pData)
|
|
{
|
|
NXdict pDict;
|
|
int iRet;
|
|
char pDefinition[2048];
|
|
pDynString pReplaced = NULL;
|
|
|
|
pDict = NXDIAssert(dict);
|
|
|
|
/* get Definition String */
|
|
iRet = NXDget(pDict, pAlias, pDefinition, 2047);
|
|
if (iRet != NX_OK) {
|
|
sprintf(pDefinition, "ERROR: alias %s not recognized", pAlias);
|
|
NXReportError(pDefinition);
|
|
return NX_ERROR;
|
|
}
|
|
|
|
/* do text replacement */
|
|
pReplaced = NXDItextreplace(dict, pDefinition);
|
|
if (!pReplaced) {
|
|
return NX_ERROR;
|
|
}
|
|
|
|
/* call NXDgetdef */
|
|
iRet = NXDgetdef(hFil, dict, GetCharArray(pReplaced), pData);
|
|
DeleteDynString(pReplaced);
|
|
return iRet;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
NXstatus NXDinfodef(NXhandle hFil, NXdict dict, char *pDef, int *rank,
|
|
int dimension[], int *iType)
|
|
{
|
|
NXdict pDict;
|
|
ParDat pParse;
|
|
int iRet, i, iStat;
|
|
|
|
pDict = NXDIAssert(dict);
|
|
|
|
/* parse and act on definition string */
|
|
pParse.iMayCreate = 0;
|
|
pParse.pPtr = pDef;
|
|
pParse.iDepth = 0;
|
|
#ifdef DEFDEBUG
|
|
printf("Getting: %s\n", pDef);
|
|
#endif
|
|
iRet = NXDIDefParse(hFil, pDict, &pParse);
|
|
if (iRet == NX_ERROR) {
|
|
/* unwind and throw up */
|
|
NXDIUnwind(hFil, pParse.iDepth);
|
|
return NX_ERROR;
|
|
}
|
|
|
|
|
|
/* only SDS can be written */
|
|
if (pParse.iTerminal != TERMSDS) {
|
|
NXReportError("ERROR: can only write to an SDS!");
|
|
iStat = NX_ERROR;
|
|
} else {
|
|
/* the SDS should be open by now, read it */
|
|
iStat = NXgetinfo(hFil, rank, dimension, iType);
|
|
iRet = NXclosedata(hFil);
|
|
}
|
|
|
|
|
|
/* rewind the hierarchy */
|
|
iRet = NXDIUnwind(hFil, pParse.iDepth);
|
|
if (iRet != NX_OK) {
|
|
return NX_ERROR;
|
|
}
|
|
return iStat;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
NXstatus NXDinfoalias(NXhandle hFil, NXdict dict, char *pAlias, int *rank,
|
|
int dimension[], int *iType)
|
|
{
|
|
NXdict pDict;
|
|
int iRet;
|
|
char pDefinition[2048];
|
|
pDynString pReplaced = NULL;
|
|
|
|
pDict = NXDIAssert(dict);
|
|
|
|
/* get Definition String */
|
|
iRet = NXDget(pDict, pAlias, pDefinition, 2047);
|
|
if (iRet != NX_OK) {
|
|
sprintf(pDefinition, "ERROR: alias %s not recognized", pAlias);
|
|
NXReportError(pDefinition);
|
|
return NX_ERROR;
|
|
}
|
|
|
|
/* do text replacement */
|
|
pReplaced = NXDItextreplace(dict, pDefinition);
|
|
if (!pReplaced) {
|
|
return NX_ERROR;
|
|
}
|
|
|
|
/* call NXDgetdef */
|
|
iRet =
|
|
NXDinfodef(hFil, dict, GetCharArray(pReplaced), rank, dimension,
|
|
iType);
|
|
DeleteDynString(pReplaced);
|
|
return iRet;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
NXstatus NXDdefnamedlink(NXhandle hFil, NXdict dict,
|
|
char *pTarget, char *pVictim, char *newname)
|
|
{
|
|
NXdict pDict;
|
|
ParDat pParseT, pParseV;
|
|
int iRet, i, iStat;
|
|
NXlink sLink;
|
|
|
|
pDict = NXDIAssert(dict);
|
|
|
|
|
|
#ifdef DEFDEBUG
|
|
printf("Linking: %s\n", pVictim);
|
|
printf("To: %s\n", pTarget);
|
|
#endif
|
|
|
|
|
|
/* parse Victim */
|
|
pParseV.iMayCreate = 0;
|
|
pParseV.pPtr = pVictim;
|
|
pParseV.iDepth = 0;
|
|
iRet = NXDIDefParse(hFil, pDict, &pParseV);
|
|
if (iRet == NX_ERROR) {
|
|
/* unwind and throw up */
|
|
NXDIUnwind(hFil, pParseV.iDepth);
|
|
return NX_ERROR;
|
|
}
|
|
/* get link data */
|
|
if (pParseV.iTerminal == TERMSDS) {
|
|
NXgetdataID(hFil, &sLink);
|
|
iRet = NXclosedata(hFil);
|
|
if (iRet != NX_OK) {
|
|
/* unwind and throw up */
|
|
NXDIUnwind(hFil, pParseV.iDepth);
|
|
return NX_ERROR;
|
|
}
|
|
} else if (pParseV.iTerminal == TERMVG) {
|
|
NXgetgroupID(hFil, &sLink);
|
|
} else {
|
|
assert(0); /* serious programming error */
|
|
}
|
|
/* Unwind */
|
|
iRet = NXDIUnwind(hFil, pParseV.iDepth);
|
|
if (iRet != NX_OK) {
|
|
return NX_ERROR;
|
|
}
|
|
|
|
/* parse Target */
|
|
pParseT.iMayCreate = 1;
|
|
pParseT.pPtr = pTarget;
|
|
pParseT.iDepth = 0;
|
|
iRet = NXDIDefParse(hFil, pDict, &pParseT);
|
|
if (iRet == NX_ERROR) {
|
|
/* unwind and throw up */
|
|
NXDIUnwind(hFil, pParseT.iDepth);
|
|
return NX_ERROR;
|
|
}
|
|
/* check it being a vGroup! */
|
|
if (pParseT.iTerminal != TERMVG) {
|
|
NXReportError("ERROR: can link only into a vGroup");
|
|
NXDIUnwind(hFil, pParseT.iDepth);
|
|
return NX_ERROR;
|
|
}
|
|
|
|
/* link, finally */
|
|
iRet = NXmakenamedlink(hFil, newname, &sLink);
|
|
/* Unwind anyway */
|
|
iStat = NXDIUnwind(hFil, pParseT.iDepth);
|
|
if (iStat != NX_OK) {
|
|
return NX_ERROR;
|
|
}
|
|
return iStat;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
NXstatus NXDaliasnamedlink(NXhandle hFil, NXdict dict,
|
|
char *pTarget, char *pVictim, char *newname)
|
|
{
|
|
char pTargetDef[2048], pVictimDef[2048];
|
|
int iRet;
|
|
NXdict pDict;
|
|
pDynString pRep1 = NULL, pRep2 = NULL;
|
|
|
|
pDict = NXDIAssert(dict);
|
|
|
|
/* get Target Definition String */
|
|
iRet = NXDget(pDict, pTarget, pTargetDef, 2047);
|
|
if (iRet != NX_OK) {
|
|
sprintf(pTargetDef, "ERROR: alias %s not recognized", pTarget);
|
|
NXReportError(pTargetDef);
|
|
return NX_ERROR;
|
|
}
|
|
|
|
/* get Victim definition string */
|
|
iRet = NXDget(pDict, pVictim, pVictimDef, 2047);
|
|
if (iRet != NX_OK) {
|
|
sprintf(pTargetDef, "ERROR: alias %s not recognized", pTarget);
|
|
NXReportError(pTargetDef);
|
|
return NX_ERROR;
|
|
}
|
|
|
|
/* do replacements */
|
|
pRep1 = NXDItextreplace(dict, pTargetDef);
|
|
pRep2 = NXDItextreplace(dict, pVictimDef);
|
|
if ((!pRep1) || (!pRep2)) {
|
|
if (pRep1)
|
|
DeleteDynString(pRep1);
|
|
if (pRep2)
|
|
DeleteDynString(pRep2);
|
|
return NX_ERROR;
|
|
}
|
|
|
|
/* call NXdeflin */
|
|
iRet = NXDdefnamedlink(hFil, pDict, GetCharArray(pRep1), GetCharArray(pRep2), newname);
|
|
DeleteDynString(pRep1);
|
|
DeleteDynString(pRep2);
|
|
return iRet;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
NXstatus NXDdeflink(NXhandle hFil, NXdict dict,
|
|
char *pTarget, char *pVictim)
|
|
{
|
|
NXdict pDict;
|
|
ParDat pParseT, pParseV;
|
|
int iRet, i, iStat;
|
|
NXlink sLink;
|
|
|
|
pDict = NXDIAssert(dict);
|
|
|
|
|
|
#ifdef DEFDEBUG
|
|
printf("Linking: %s\n", pVictim);
|
|
printf("To: %s\n", pTarget);
|
|
#endif
|
|
|
|
|
|
/* parse Victim */
|
|
pParseV.iMayCreate = 0;
|
|
pParseV.pPtr = pVictim;
|
|
pParseV.iDepth = 0;
|
|
iRet = NXDIDefParse(hFil, pDict, &pParseV);
|
|
if (iRet == NX_ERROR) {
|
|
/* unwind and throw up */
|
|
NXDIUnwind(hFil, pParseV.iDepth);
|
|
return NX_ERROR;
|
|
}
|
|
/* get link data */
|
|
if (pParseV.iTerminal == TERMSDS) {
|
|
NXgetdataID(hFil, &sLink);
|
|
iRet = NXclosedata(hFil);
|
|
if (iRet != NX_OK) {
|
|
/* unwind and throw up */
|
|
NXDIUnwind(hFil, pParseV.iDepth);
|
|
return NX_ERROR;
|
|
}
|
|
} else if (pParseV.iTerminal == TERMVG) {
|
|
NXgetgroupID(hFil, &sLink);
|
|
} else {
|
|
assert(0); /* serious programming error */
|
|
}
|
|
/* Unwind */
|
|
iRet = NXDIUnwind(hFil, pParseV.iDepth);
|
|
if (iRet != NX_OK) {
|
|
return NX_ERROR;
|
|
}
|
|
|
|
/* parse Target */
|
|
pParseT.iMayCreate = 1;
|
|
pParseT.pPtr = pTarget;
|
|
pParseT.iDepth = 0;
|
|
iRet = NXDIDefParse(hFil, pDict, &pParseT);
|
|
if (iRet == NX_ERROR) {
|
|
/* unwind and throw up */
|
|
NXDIUnwind(hFil, pParseT.iDepth);
|
|
return NX_ERROR;
|
|
}
|
|
/* check it being a vGroup! */
|
|
if (pParseT.iTerminal != TERMVG) {
|
|
NXReportError("ERROR: can link only into a vGroup");
|
|
NXDIUnwind(hFil, pParseT.iDepth);
|
|
return NX_ERROR;
|
|
}
|
|
|
|
/* link, finally */
|
|
iRet = NXmakelink(hFil, &sLink);
|
|
/* Unwind anyway */
|
|
iStat = NXDIUnwind(hFil, pParseT.iDepth);
|
|
if (iStat != NX_OK) {
|
|
return NX_ERROR;
|
|
}
|
|
return iStat;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
NXstatus NXDaliaslink(NXhandle hFil, NXdict dict,
|
|
char *pTarget, char *pVictim)
|
|
{
|
|
char pTargetDef[2048], pVictimDef[2048];
|
|
int iRet;
|
|
NXdict pDict;
|
|
pDynString pRep1 = NULL, pRep2 = NULL;
|
|
|
|
pDict = NXDIAssert(dict);
|
|
|
|
/* get Target Definition String */
|
|
iRet = NXDget(pDict, pTarget, pTargetDef, 2047);
|
|
if (iRet != NX_OK) {
|
|
sprintf(pTargetDef, "ERROR: alias %s not recognized", pTarget);
|
|
NXReportError(pTargetDef);
|
|
return NX_ERROR;
|
|
}
|
|
|
|
/* get Victim definition string */
|
|
iRet = NXDget(pDict, pVictim, pVictimDef, 2047);
|
|
if (iRet != NX_OK) {
|
|
sprintf(pTargetDef, "ERROR: alias %s not recognized", pTarget);
|
|
NXReportError(pTargetDef);
|
|
return NX_ERROR;
|
|
}
|
|
|
|
/* do replacements */
|
|
pRep1 = NXDItextreplace(dict, pTargetDef);
|
|
pRep2 = NXDItextreplace(dict, pVictimDef);
|
|
if ((!pRep1) || (!pRep2)) {
|
|
if (pRep1)
|
|
DeleteDynString(pRep1);
|
|
if (pRep2)
|
|
DeleteDynString(pRep2);
|
|
return NX_ERROR;
|
|
}
|
|
|
|
/* call NXdeflin */
|
|
iRet = NXDdeflink(hFil, pDict, GetCharArray(pRep1), GetCharArray(pRep2));
|
|
DeleteDynString(pRep1);
|
|
DeleteDynString(pRep2);
|
|
return iRet;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
static void SNXFormatTime(char *pBuffer, int iBufLen)
|
|
{
|
|
time_t iDate;
|
|
struct tm *psTime;
|
|
|
|
/* make time string */
|
|
iDate = time(NULL);
|
|
psTime = localtime(&iDate);
|
|
memset(pBuffer, 0, iBufLen);
|
|
strftime(pBuffer, iBufLen, "%Y-%m-%d %H:%M:%S", psTime);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
NXstatus NXUwriteglobals(NXhandle pFile,
|
|
char *filename,
|
|
char *owner,
|
|
char *adress,
|
|
char *phone,
|
|
char *email, char *fax, char *instrument)
|
|
{
|
|
char pBueffel[512];
|
|
int iStat;
|
|
|
|
/* store global attributes, now done by NXopen
|
|
iStat = NXputattr(pFile,"file_name",filename,
|
|
strlen(filename)+1,NX_CHAR);
|
|
if(iStat == NX_ERROR)
|
|
{
|
|
return NX_ERROR;
|
|
}
|
|
*/
|
|
|
|
/* write creation time, now done by NXopen
|
|
SNXFormatTime(pBueffel,512);
|
|
iStat = NXputattr(pFile,"file_time",pBueffel,
|
|
strlen(pBueffel)+1,NX_CHAR);
|
|
if(iStat == NX_ERROR)
|
|
{
|
|
return NX_ERROR;
|
|
}
|
|
*/
|
|
|
|
/* instrument name */
|
|
iStat = NXputattr(pFile, "instrument", instrument,
|
|
strlen(instrument) + 1, NX_CHAR);
|
|
if (iStat == NX_ERROR) {
|
|
return iStat;
|
|
}
|
|
|
|
/* owner */
|
|
iStat = NXputattr(pFile, "owner", owner, strlen(owner) + 1, NX_CHAR);
|
|
if (iStat == NX_ERROR) {
|
|
return iStat;
|
|
}
|
|
|
|
/* Adress */
|
|
iStat = NXputattr(pFile, "owner_adress", adress,
|
|
strlen(adress) + 1, NX_CHAR);
|
|
if (iStat == NX_ERROR) {
|
|
return iStat;
|
|
}
|
|
|
|
/* phone */
|
|
iStat = NXputattr(pFile, "owner_telephone_number", phone,
|
|
strlen(phone) + 1, NX_CHAR);
|
|
if (iStat == NX_ERROR) {
|
|
return iStat;
|
|
}
|
|
|
|
/* fax */
|
|
iStat = NXputattr(pFile, "owner_fax_number", fax,
|
|
strlen(fax) + 1, NX_CHAR);
|
|
if (iStat == NX_ERROR) {
|
|
return iStat;
|
|
}
|
|
|
|
/* email */
|
|
iStat = NXputattr(pFile, "owner_email", email,
|
|
strlen(email) + 1, NX_CHAR);
|
|
if (iStat == NX_ERROR) {
|
|
return iStat;
|
|
}
|
|
return NX_OK;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
NXstatus NXUentergroup(NXhandle hFil, char *name, char *class)
|
|
{
|
|
int iRet;
|
|
|
|
/* ACTION, first install dummy error handler */
|
|
NXMDisableErrorReporting();
|
|
|
|
|
|
/* try opening vGroup */
|
|
iRet = NXopengroup(hFil, name, class);
|
|
NXMEnableErrorReporting();
|
|
if (iRet == NX_OK) {
|
|
return NX_OK;
|
|
} else {
|
|
/* we need to create it */
|
|
iRet = NXmakegroup(hFil, name, class);
|
|
if (iRet != NX_OK) {
|
|
/* a comment on this one has already been written! */
|
|
return iRet;
|
|
}
|
|
iRet = NXopengroup(hFil, name, class);
|
|
if (iRet != NX_OK) {
|
|
/* a comment on this one has already been written! */
|
|
return iRet;
|
|
}
|
|
}
|
|
return NX_OK;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
NXstatus NXUenterdata(NXhandle hFil, char *label, int datatype,
|
|
int rank, int dim[], char *pUnits)
|
|
{
|
|
int iRet;
|
|
|
|
/* ACTION, first install dummy error handler */
|
|
NXMDisableErrorReporting();
|
|
|
|
/* try opening SDS */
|
|
iRet = NXopendata(hFil, label);
|
|
NXMEnableErrorReporting();
|
|
if (iRet == NX_OK) {
|
|
return NX_OK;
|
|
} else {
|
|
/* we need to create it */
|
|
iRet = NXmakedata(hFil, label, datatype, rank, dim);
|
|
if (iRet != NX_OK) {
|
|
/* a comment on this one has already been written! */
|
|
return iRet;
|
|
}
|
|
iRet = NXopendata(hFil, label);
|
|
if (iRet != NX_OK) {
|
|
/* a comment on this one has already been written! */
|
|
return iRet;
|
|
}
|
|
iRet = NXputattr(hFil, "Units", pUnits, strlen(pUnits) + 1, NX_INT8);
|
|
if (iRet != NX_OK) {
|
|
/* a comment on this one has already been written! */
|
|
return iRet;
|
|
}
|
|
}
|
|
return NX_OK;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
NXstatus NXUallocSDS(NXhandle hFil, void **pData)
|
|
{
|
|
int iDIM[NX_MAXRANK];
|
|
int iRank, iType;
|
|
int iRet, i;
|
|
long lLength;
|
|
|
|
/* get info */
|
|
iRet = NXgetinfo(hFil, &iRank, iDIM, &iType);
|
|
if (iRet != NX_OK) {
|
|
return iRet;
|
|
}
|
|
|
|
/* calculate Size */
|
|
lLength = iDIM[0];
|
|
for (i = 1; i < iRank; i++) {
|
|
lLength *= iDIM[i];
|
|
}
|
|
switch (iType) {
|
|
case NX_FLOAT32:
|
|
lLength *= sizeof(float);
|
|
break;
|
|
case NX_FLOAT64:
|
|
lLength *= sizeof(double);
|
|
break;
|
|
case NX_INT8:
|
|
case NX_CHAR:
|
|
lLength *= sizeof(char);
|
|
break;
|
|
case NX_UINT8:
|
|
lLength *= sizeof(unsigned char);
|
|
break;
|
|
case NX_INT16:
|
|
lLength *= sizeof(short);
|
|
break;
|
|
case NX_UINT16:
|
|
lLength *= sizeof(unsigned short);
|
|
break;
|
|
case NX_INT32:
|
|
lLength *= sizeof(int);
|
|
break;
|
|
case NX_UINT32:
|
|
lLength *= sizeof(int);
|
|
break;
|
|
default:
|
|
NXReportError("ERROR: Internal: number type not recoginized");
|
|
return NX_ERROR;
|
|
}
|
|
|
|
/* time to malloc */
|
|
*pData = NULL;
|
|
*pData = malloc(lLength);
|
|
if (*pData == NULL) {
|
|
NXReportError("ERROR: memory exhausted in NXUallocSDS");
|
|
return NX_ERROR;
|
|
}
|
|
memset(*pData, 0, lLength);
|
|
return NX_OK;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
NXstatus NXUfreeSDS(void **pData)
|
|
{
|
|
free(*pData);
|
|
*pData = NULL;
|
|
return NX_OK;
|
|
}
|