/*--------------------------------------------------------------------------- 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 #include #include #include #include #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; }