Files
sics/nxdict.c
cvs f3853c20f0 - Fixed bug with ECB not stopping when no beam
- Fixed synchronisation issues
- Fixed hsitogram memory writing from nxscript
- Started module for writing SICS interfaces in Tcl
- Fixed a bug in scan, which allowed to corrupt files
- Fixed memory problems in napi5
2003-05-23 15:06:47 +00:00

1919 lines
51 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 <mfhdf.h>
#include "fortify.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
---------------------------------------------------------------------------*/
extern void *NXpData;
extern void (*NXIReportError)(void *pData, char *pBuffer);
/*--------------------------------------------------------------------------*/
/* #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 )
{
NXIReportError(NXpData,"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[132];
char pDefinition[1024]; /* this is > 10 lines of definition */
char pWord[132];
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)
{
NXIReportError(NXpData, "Allocating new NXdict structure ");
}
pNew = (NXdict)malloc(sizeof(sNXdict));
if(!pNew)
{
NXIReportError(NXpData, "Insufficient memory for creation of NXdict");
return NX_ERROR;
}
/* initialise it */
pNew->iID = NXDMAGIC;
pNew->pDictionary = CreateStringDict();
if(!pNew->pDictionary)
{
NXIReportError(NXpData, "Insufficient memory for creation of NXdict");
free(pNew);
return NX_ERROR;
}
/* is there a file name argument */
if(filename == NULL)
{
if(iVerbosity == NXalot)
{
NXIReportError(NXpData, "NXDinitfrom file finished without data");
}
*pData = pNew;
return NX_OK;
}
fd = fopen(filename,"rb");
if(!fd)
{
sprintf(pError,"ERROR: file %s NOT found ",filename);
NXIReportError(NXpData, pError);
NXIReportError(NXpData, "NXDinitfrom file finished without data");
*pData = pNew;
return NX_ERROR;
}
/* read the file contents */
if(iVerbosity == NXalot)
{
NXIReportError(NXpData, "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);
NXIReportError(NXpData, pError);
NXIReportError(NXpData, "NXDinitfrom file finished without data");
*pData = pNew;
return NX_ERROR;
}
/* parse it */
if(iVerbosity == NXalot)
{
NXIReportError(NXpData, "NXDinitfrom: parsing dictionary definitions");
}
NXDIParse(pBuffer, pNew->pDictionary);
if(iVerbosity == NXalot)
{
NXIReportError(NXpData, "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);
NXIReportError(NXpData, pValue);
}
fd = fopen(filename,"w");
if(!fd)
{
sprintf(pValue,"ERROR: opening file %s for write",filename);
NXIReportError(NXpData, 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);
NXIReportError(NXpData, 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)
{
NXIReportError(NXpData,"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)
{
NXIReportError(NXpData,
"ERROR: buffer overrun in NXDItextreplace");
DeleteDynString(pReplaced);
return NULL;
}
break;
}
}
}
#ifdef DEFDEBUG
printf("Replacement result: %s\n",GetCharArray(pReplaced));
#endif
return pReplaced;
}
/*--------------------------------------------------------------------------*/
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[20];
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 *pData, 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 < 10; i++)
{
if(strcmp(sStat->pToken,TokenList[i].pText) == 0)
{
sStat->iToken = TokenList[i].iCode;
break;
}
}
return;
}
/* not reached */
return;
}
/*------------------------------------------------------------------------*/
int NXDIParsePath(NXhandle hfil, ParDat *pParse)
{
int iRet, iToken;
void (*ErrFunc)(void *pData, char *pErr);
char pName[132], pClass[132];
char pError[256];
/* 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);
NXIReportError(NXpData, 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);
NXIReportError(NXpData, 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);
NXIReportError(NXpData, pError);
return NX_ERROR;
}
strcpy(pClass,pParse->pToken);
/* done reading, ACTION, first install dummy error handler */
ErrFunc = NXIReportError;
NXMSetError(NXpData, DummyError);
/* try opening vGroup */
iRet = NXopengroup(hfil, pName, pClass);
NXMSetError(NXpData,ErrFunc);
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);
NXIReportError(NXpData,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);
NXIReportError(NXpData,pError);
return NX_ERROR;
}
/* a word is expected */
NXDIDefToken(pParse);
if(pParse->iToken != DWORD)
{
sprintf(pError,"ERROR: expected attribute name, got %s",pParse->pToken);
NXIReportError(NXpData,pError);
return NX_ERROR;
}
strcpy(sAtt.name,pParse->pToken);
/* a , is expected */
NXDIDefToken(pParse);
if(pParse->iToken != DKOMMA)
{
sprintf(pError,"ERROR: expected , , got %s",pParse->pToken);
NXIReportError(NXpData,pError);
return NX_ERROR;
}
/* a word is expected */
NXDIDefToken(pParse);
if(pParse->iToken != DWORD)
{
sprintf(pError,"ERROR: expected attribute value, got %s",pParse->pToken);
NXIReportError(NXpData,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);
NXIReportError(NXpData,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 < MAX_VAR_DIMS; i++)
{
iDim[i] = 0;
}
NXDIDefToken(pParse);
if(pParse->iToken != DOPEN)
{
sprintf(pError,"ERROR: expected {, got %s",pParse->pToken);
NXIReportError(NXpData,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);
NXIReportError(NXpData,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);
NXIReportError(NXpData,pError);
return NX_ERROR;
}
if(pParse->iToken == DCLOSE)
{
break;
}
}
return NX_OK;
}
/*------------------------------------------------------------------------*/
static TokDat tDatType[] = {
{"DFNT_FLOAT32",DFNT_FLOAT32},
{"DFNT_FLOAT64",DFNT_FLOAT64},
{"DFNT_INT8",DFNT_INT8},
{"DFNT_UINT8",DFNT_UINT8},
{"DFNT_INT16",DFNT_INT16},
{"DFNT_UINT16",DFNT_UINT16},
{"DFNT_INT32",DFNT_INT32},
{"DFNT_UINT32",DFNT_UINT32},
{"DFNT_CHAR",DFNT_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);
NXIReportError(NXpData,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);
NXIReportError(NXpData,pError);
return NX_ERROR;
}
/*-------------------------------------------------------------------------*/
static int NXDIParseSDS(NXhandle hfil, ParDat *pParse)
{
int iType = DFNT_FLOAT32;
int iRank = 1;
int iCompress = NX_COMP_NONE;
int32 iDim[MAX_VAR_DIMS], iChunk[MAX_VAR_DIMS];
int iList, iChunkDefined = 0 ;
int iRet, iStat, i;
char pError[256];
char pName[MAX_NC_NAME];
void (*ErrFunc)(void *pData, char *pErr);
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);
NXIReportError(NXpData,pError);
return NX_ERROR;
}
strcpy(pName,pParse->pToken);
/* create the attribute list */
iList = LLDcreate(sizeof(AttItem));
if(iList < 0)
{
NXIReportError(NXpData, "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);
NXIReportError(NXpData,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);
NXIReportError(NXpData, 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];
}
}
/* first install dummy error handler, try open it, then
deinstall again and create if allowed
*/
ErrFunc = NXIReportError;
NXMSetError(NXpData, DummyError);
/* try opening SDS */
iRet = NXopendata(hfil, pName);
NXMSetError(NXpData,ErrFunc);
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);
NXIReportError(NXpData,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);
NXIReportError(NXpData,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);
NXIReportError(NXpData,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;
}
/* try rewinding the hierarchy */
if(pParse.iTerminal == TERMSDS)
{
iStat = NXDIUnwind(hfil,pParse.iDepth);
if(iStat != NX_OK)
{
return NX_ERROR;
}
}
/* do not rewind on links */
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);
NXIReportError(NXpData,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)
{
NXIReportError(NXpData,
"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);
NXIReportError(NXpData,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)
{
NXIReportError(NXpData,
"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);
NXIReportError(NXpData,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)
{
NXIReportError(NXpData,
"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);
NXIReportError(NXpData,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 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)
{
NXIReportError(NXpData,"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);
NXIReportError(NXpData,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);
NXIReportError(NXpData,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)
{
void (*ErrFunc)(void *pData, char *pErr);
int iRet;
/* ACTION, first install dummy error handler */
ErrFunc = NXIReportError;
NXMSetError(NXpData, DummyError);
/* try opening vGroup */
iRet = NXopengroup(hFil, name, class);
NXMSetError(NXpData,ErrFunc);
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)
{
void (*ErrFunc)(void *pData, char *pErr);
int iRet;
/* ACTION, first install dummy error handler */
ErrFunc = NXIReportError;
NXMSetError(NXpData, DummyError);
/* try opening SDS */
iRet = NXopendata(hFil, label);
NXMSetError(NXpData,ErrFunc);
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,DFNT_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[MAX_VAR_DIMS];
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 DFNT_FLOAT32:
lLength *= sizeof(float32);
break;
case DFNT_FLOAT64:
lLength *= sizeof(float64);
break;
case DFNT_INT8:
case DFNT_CHAR:
case DFNT_UCHAR8:
lLength *= sizeof(int8);
break;
case DFNT_UINT8:
lLength *= sizeof(uint8);
break;
case DFNT_INT16:
lLength *= sizeof(int16);
break;
case DFNT_UINT16:
lLength *= sizeof(uint16);
break;
case DFNT_INT32:
lLength *= sizeof(int32);
break;
case DFNT_UINT32:
lLength *= sizeof(uint32);
break;
default:
NXIReportError(NXpData,"ERROR: Internal: number type not recoginized");
return NX_ERROR;
}
/* time to malloc */
*pData = NULL;
*pData = malloc(lLength);
if(*pData == NULL)
{
NXIReportError(NXpData,"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;
}