3054 lines
126 KiB
TeX
3054 lines
126 KiB
TeX
%
|
|
%
|
|
% This software is distributed in the hope that it will be useful,
|
|
% but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
% GNU General Public License for more details.
|
|
%
|
|
% You may already have a copy of the GNU General Public License; if
|
|
% not, write to the Free Software Foundation, Inc., 675 Mass Ave,
|
|
% Cambridge, MA 02139, USA.
|
|
%
|
|
|
|
\documentclass[12pt]{article}
|
|
|
|
\setlength{\oddsidemargin}{-.1in}
|
|
\setlength{\evensidemargin}{0in}
|
|
\setlength{\topmargin}{0in}
|
|
\addtolength{\topmargin}{-\headheight}
|
|
\addtolength{\topmargin}{-\headsep}
|
|
\setlength{\textheight}{8.9in}
|
|
\setlength{\textwidth}{6.2in}
|
|
\setlength{\marginparwidth}{0.5in}
|
|
|
|
\begin{document}
|
|
\title{The NEXUS Dictionary API}
|
|
|
|
\author{Mark K\"onnecke\\
|
|
Labor f\"ur Neutronenstreuung\\
|
|
Paul Scherrer Institut\\
|
|
CH-5232 Villigen PSI\\
|
|
Switzerland\\
|
|
Mark.Koennecke@psi.ch \\
|
|
}
|
|
|
|
|
|
|
|
\maketitle
|
|
|
|
\vskip.3in
|
|
\centerline{\large\bf Abstract}
|
|
\vskip.2in
|
|
\begin{center}
|
|
\parbox{.8\textwidth}{
|
|
There is a proposed portable data exchange format for neutron and
|
|
X-ray scattering communities, NEXUS (described in a separate
|
|
publication). Another document describes an application programmers
|
|
interface to NEXUS. This is a base level API which hides many of the
|
|
hideous details of the HDF interface from the NeXus programmer. The
|
|
present document introduces a higher level application programmers
|
|
interface sitting on top of the NeXus API. This API (the NEXDICT-API),
|
|
reads all file structure data from a dictionary data file and creates
|
|
the structure automatically from that information. The NEXDICT user only
|
|
needs to specify the data to write or read.
|
|
}
|
|
\end{center}
|
|
|
|
\clearpage
|
|
|
|
\section{Introduction}
|
|
There exists a proposal for a portable data exchange format for neutron and
|
|
X--ray scattering communities, NeXus. NeXus is fully described
|
|
elsewhere$^{1}$. NeXus sits on top of the hierarchical data format (HDF) as
|
|
defined and specified by the National Center for Supercomputer Applications,
|
|
NCSA, USA. HDF comes with a library of access functions. On top of the
|
|
HDF-library an application programmers interface (API) for NeXus was
|
|
defined which hides many of the low level details and ideosyncracies of
|
|
the HDF interface form the NeXus programmer. However, writing NeXus files stays
|
|
hideous even with this interface due to the amount of repetitive code
|
|
required to implement the NeXus structure. Now, repetitive tasks is one
|
|
area a computer is good at. So, why not have the computer take care of all
|
|
the structure associated with the NeXus format? Such an approach has the
|
|
additional benefit that changes in the file structure just require to edit
|
|
the dictionary data file with no changes to the source code writing or
|
|
reading the data. In order to do all this two
|
|
components are needed:
|
|
\begin{itemize}
|
|
\item A language which describes the NeXus file structure to the computer.
|
|
This language will be called the NeXus Data Definition Language (NXDDL).
|
|
NXDLL might also be used as a tool for discussing and defining NeXus
|
|
data structures.
|
|
\item A application programmers interface which works with the NeXus Data
|
|
Definition Language.
|
|
\end{itemize}
|
|
Both of the above will be detailed in this document.
|
|
|
|
\section{The NeXus Data Definition Language}
|
|
The NeXus Data Definition Language's(NXDDL) purpose is to define the structure
|
|
and data items in a NeXus file in a form which can be understood by a human
|
|
programmer and which can be parsed by the computer in order to create the
|
|
structure.
|
|
For this a dictionary based approach will be used. This dictionary
|
|
will contain pairs of short aliases for data items and definition strings
|
|
which hold the structure information. This dictionary will
|
|
be initialized from a data file, the NXDDL-file. Such a dictionary can be
|
|
used in the following way: Given an appropriate API function, a NXDICT
|
|
programmer needs to specify only the alias and the data to write and
|
|
everything else is taken care of by the API: vGroup creation, opening,
|
|
SDS definition etc. Another use may involve the creation of definition
|
|
strings
|
|
completely or partly at run time which can then be used by an API function
|
|
in order to create the structures defined by the definition string. The same
|
|
holds for writing as well.
|
|
|
|
|
|
A NXDDL dictionary is preferably initialized from a file.
|
|
Such a NXDDL file has to follow these general structure guidelines:
|
|
\begin{itemize}
|
|
\item All input is in US--ASCII.
|
|
\item The first line must read: ##NXDICT-1.0. This is in order to
|
|
automatically identify the file.
|
|
\item A \verb+#+ in the first column denotes a comment and will be ignored.
|
|
\item A \verb+\+ at the end of the line means that the current text will be
|
|
continued with the next non-blank character for the next line.
|
|
\item All other entries follow the form: alias = definition string.
|
|
This defines \verb+alias+ as a short form for the definition string after the
|
|
equality sign.
|
|
\item There is a text replacement facility similar to shell variables under
|
|
Unix: The sequence $(alias) anywhere in a definition string will be replaced
|
|
by the value of the alias specified between the braces. This scheme allows
|
|
to cater for multiple entries in a file or changing data descriptions as a
|
|
function of instrument modes.
|
|
\end{itemize}
|
|
It might be considered to add a special global vGroup of class NXdict to the
|
|
NexUs API which holds the dictionary information within a NeXus file.
|
|
|
|
The next thing to define is the content of the definition string. A
|
|
definition string will have the general form: \\
|
|
\centerline{\bf PATH/TerminalSymbol}
|
|
This means a definition string will consist of a path specifier which
|
|
describes the position of a data item in the vGroup hierarchy and a
|
|
terminal symbol which describes the nature of the data item.
|
|
|
|
The path through the vGroup hierarchy to a data item will be described in a
|
|
manner analog to a Unix directory hierarchy. However, NeXus requires two
|
|
pieces of data in order to fully qualify a vGroup. This is it's name and
|
|
class. Consequently, both name and classname will be given for each vGroup,
|
|
separated by a komma. A valid path string then looks like: \\
|
|
\begin{verbatim}
|
|
/scan1,NXentry/DMC,NXinstrument/big_detector,NXdetector/TerminalSymbol
|
|
\end{verbatim}
|
|
This translates into: TerminalSymbol in vGroup big\_detector, class
|
|
NXdetector, which resides in vGroup DMC of class NXinstrument, which in
|
|
turn is situated in the vGroup scan1 of class NXentry.
|
|
|
|
The terminal symbol in a definition string is used to define the data item
|
|
at the end of the definition. NeXus currently supports only three types of
|
|
data items at the end of the chain: these are scientific data sets (SDS),
|
|
vGroups and links to other data items or vGroups. The terminal symbol for a link
|
|
is specified by the keyword \verb+NXLINK+
|
|
followed
|
|
by a valid alias of another data item or vGroup. For example the terminal
|
|
symbol: \\
|
|
\centerline{\bf SDS counts}
|
|
would define a SDS with name counts.
|
|
|
|
A vGroup would be denoted by the keyword VGROUP. By then, the vGroup has
|
|
already been defined by the path string. This form of alias is only useful
|
|
for the definition of links to vGroups.
|
|
|
|
A SDS is more involved. The definition of an SDS starts with the keyword
|
|
\verb+SDS+. This keyword must then be followed by the name of the SDS.
|
|
Following the name there are option value pairs which define the
|
|
details of the SDS. The following option exist:
|
|
\begin{itemize}
|
|
\item {\bf -rank} defines the rank of the SDS.
|
|
\item {\bf -dim \{dim0,dim1,dim2,...., dimn\} } defines the dimensions of the
|
|
SDS. Exactly the number of rank numbers defining the dimensions
|
|
length is required inside the curly braces.
|
|
\item {\bf -type} defines the data type of the SDS as a string corresponding
|
|
to the HDF data types.
|
|
\item {\bf -attr \{name,value\} } defines an attribute. In the curly braces
|
|
there must be the name and value of the attribute separated by a comma.
|
|
\end{itemize}
|
|
If no options are given a default is used. This will be a single floating
|
|
point number, as this is the most frequently written data item. As an
|
|
example see the definition of a 3d array of 32 bit integers:
|
|
\begin{verbatim}
|
|
PATHSTRING/SDS counts -rank 3 -dim {64,64,712} -type DFNT_INT32 \
|
|
-attr {Units,Counts}
|
|
|
|
\end{verbatim}
|
|
|
|
\section{The NXDICT--API}
|
|
In order to interface with the NeXus dictionary API a set of
|
|
API--functions is needed. All functions and data types belonging to
|
|
this API start with the letters: NXD. The functions belonging to this API
|
|
fall into three groups:
|
|
\begin{itemize}
|
|
\item Dictionary maintainance functions.
|
|
\item Data writing and reading functions.
|
|
\item Utility functions.
|
|
\end{itemize}
|
|
|
|
One additional data type is needed for this API:
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap1}
|
|
$\langle$tata {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ typedef struct __NXdict *NXdict;@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
NXdict will be used as a handle for the dictionary currently in use.
|
|
|
|
\subsubsection{Dictionary Maintainance Function}
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap2}
|
|
$\langle$dicman {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ NXstatus NXDinitfromfile(char *filename, NXdict *pDict);@\\
|
|
\mbox{}\verb@ NXstatus NXDclose(NXdict handle, char *filename);@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ NXstatus NXDadd(NXdict handle, char *alias, char *DefString);@\\
|
|
\mbox{}\verb@ NXstatus NXDget(NXdict handle, char *alias, char *pBuffer, int iBufLen);@\\
|
|
\mbox{}\verb@ NXstatus NXDupdate(NXdict handle, char *alias, char *pNewVal);@\\
|
|
\mbox{}\verb@ NXstatus NXDtextreplace(NXdict handle, char *pDefString, char *pBuffer,@\\
|
|
\mbox{}\verb@ int iBuflen);@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
{\bf NXDinitfromfile} creates a new NeXus dictionary. If filename is NULL, this
|
|
is all that happens. If filename is not NULL, it will be opened and the
|
|
dictionary will be initialized from the file specified. The return value
|
|
is either 0 for failure or non zero for success.
|
|
|
|
{\bf NXDclose} deletes and writes a NeXus dictionary. If filename is not NULL,
|
|
the dictionary specified by handle is written to the file specified by
|
|
filename. In any case the dictionary specified by handle will be deleted.
|
|
|
|
{\bf NXDadd} adds a new alias -- Definition String pair to the dictionary
|
|
specified by handle.
|
|
|
|
{\bf NXDget} retrieves the definition string for the alias specified as
|
|
the second parameter from the dictionary handle. The definition string
|
|
is copied to pBuffer. Maximum iBufLen characters will be copied.
|
|
|
|
{\bf NXDupdate} replaces the definition for the alias specified as second
|
|
parameter with the new value supplied as last parameter.
|
|
|
|
If a special dictionary vGroup as extension to NeXus would be accepted,
|
|
two more functions need to be defined which read and write the dictionary
|
|
from the NeXus file.
|
|
|
|
{\bf NXDtextreplace} resolves any text replacements in the definition
|
|
string pDefString. Maximum iBuflen characters of replacement results will
|
|
be copied into the buffer variable.
|
|
|
|
\subsubsection{Data Handling functions}
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap3}
|
|
$\langle$dicdata {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ NXstatus NXDputalias(NXhandle file, NXdict dict, @\\
|
|
\mbox{}\verb@ char *alias, void *pData);@\\
|
|
\mbox{}\verb@ NXstatus NXDputdef(NXhandle file, NXdict dict, char *pDefString, void *pData);@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ NXstatus NXDgetalias(NXhandle file, NXdict dict, @\\
|
|
\mbox{}\verb@ char *alias, void *pData);@\\
|
|
\mbox{}\verb@ NXstatus NXDgetdef(NXhandle file, NXdict dict, char *pDefString, void *pData);@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ NXstatus NXDaliaslink(NXhandle file, NXdict dict, @\\
|
|
\mbox{}\verb@ char *pAlias1, char *pAlias2);@\\
|
|
\mbox{}\verb@ NXstatus NXDdeflink(NXhandle file, NXdict dict, @\\
|
|
\mbox{}\verb@ char *pDef1, char *pDef2);@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ NXstatus NXDopenalias(NXhandle file, NXdict dict, @\\
|
|
\mbox{}\verb@ char *alias);@\\
|
|
\mbox{}\verb@ NXstatus NXDopendef(NXhandle file, NXdict dict, char *pDefString);@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
The NXDICT data handling functions go in pairs. The version ending in
|
|
alias expects an NXdict and an alias as input. These routines work
|
|
out the pass from that. These routines also resolve all text replacement
|
|
operations automatically. The other version ending on def acts upon
|
|
a definition string specified as second parameter. Using this scheme
|
|
both full dictionary operation is possible, as well as operation with
|
|
program generated definition strings. All routines return the
|
|
usual NeXus status returns. All these routines start at the current vGroup
|
|
level and return back to it.
|
|
|
|
NXDputalias, NXDputdef write the data element specified by the alias or
|
|
the definition string to the NeXus file specified as first parameter.
|
|
pData is a pointer to the data to be written. These routines will check for
|
|
the existence of all vGroups required in the path part of the definition
|
|
string. If a vGroup is missing it will be created. These routines step
|
|
back to the same vGroup level from which they were called.
|
|
|
|
NXDgetalias, NXDgetdef read a data item from file. pData MUST point to a
|
|
data area large enough to hold the data read. If a vGroup is missing in
|
|
the path for one of these routines an error is generated because it is
|
|
assumed that the data is present if a program wants to read it. These
|
|
routines step
|
|
back to the same vGroup level from which they were called.
|
|
|
|
NXDaliaslink, NXDdeflink links the alias or definition given as fourth
|
|
parameter to the vGroup specified by the third parameter. pAlias1 or
|
|
pDef1 MUST refer to a vGroup (we cannot link to a SDS, can't we?). The
|
|
item being linked against MUST exist, otherwise the software will complain.
|
|
The vGroup into which the link is installed will be created on the fly,
|
|
if not present.
|
|
Please note, that bot aliases or definition strings specified need to
|
|
start from the same vGroup position. These routines step
|
|
back to the same vGroup level from which they were called.
|
|
|
|
NXDopenalias, NXDopendef open the specified data items specified by the
|
|
alias or the definition string. Then the usual NeXus functions can be
|
|
used to interact with the data. These routines use the same scheme for
|
|
creating vGroups on the fly as the put routines above. The status in the
|
|
vGroup hierarchy after this call is dependent on the nature of the terminal
|
|
symbol. If it is a SDS, the vGroup hierarchy will be stepped back to the
|
|
level from which the call occurred. The SDS will be left open. If the
|
|
terminal symbol is a vGroup, then the this vGroup will be made the current
|
|
vGroup. No back stepping occurs.
|
|
|
|
|
|
|
|
\subsection{NeXus Utility Functions}
|
|
This section list a couple of functions which either perform common
|
|
tasks on NeXus files or relate
|
|
to aspects of error handling and debugging.
|
|
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap4}
|
|
$\langle$dicutil {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ NXstatus NXUwriteglobals(NXhandle file, @\\
|
|
\mbox{}\verb@ char *filename,@\\
|
|
\mbox{}\verb@ char *owner,@\\
|
|
\mbox{}\verb@ char *adress,@\\
|
|
\mbox{}\verb@ char *phone,@\\
|
|
\mbox{}\verb@ char *email,@\\
|
|
\mbox{}\verb@ char *fax,@\\
|
|
\mbox{}\verb@ char *thing);@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ NXstatus NXUentergroup(NXhandle hFil, char *name, char *class);@\\
|
|
\mbox{}\verb@ NXstatus NXUenterdata (NXhandle fileid, char* label, int datatype, @\\
|
|
\mbox{}\verb@ int rank, int dim[], char *pUnits);@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ NXstatus NXUallocSDS(NXhandle hFil, void **pData);@\\
|
|
\mbox{}\verb@ NXstatus NXUfreeSDS(void **pData);@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
{\bf NXUwriteglobals} writes the global attributes to a newly opened
|
|
NeXus file. The parameters should be self explaining. In addition
|
|
the file creation date is automatically written.
|
|
|
|
|
|
{\bf NXUentergroup} tries to open the group specified by name and class.
|
|
If it not present, it will be created and opened.
|
|
|
|
{\bf NXUenterdata} tries to open the SDS specified by label.
|
|
If it not present, it will be created and opened.
|
|
|
|
{\bf NXUallocSDS} allocates enough space for the currently open SDS. The
|
|
pointer created is returned in pData.
|
|
|
|
{\bf NXUfreeSDS} returns memory allocated by NXUallocSDS to the system.
|
|
|
|
|
|
\section{Implementation}
|
|
\subsection{The NXDICT Data Structure}
|
|
The NXDICT--API is based on a dictionary which maps an alias to a definition
|
|
string in NXDDL. Clearly, the first thing needed is a dictionary which maps
|
|
key string to value strings. It was chosen to use an existing string
|
|
dictionary (developed for SICS) as the dictionary for the NXDICT--API. This
|
|
is realised and documented in files stringdict.*. This string dictionary is
|
|
based on a linked list implementation available in the public domain (Files
|
|
lld.*). This is not the most efficient approach as any search requires
|
|
searching at maximum the whole linked list via strcmp. More efficient
|
|
dictionaries would use hash tables or binary trees. However, implementation
|
|
of a more efficient dictionary will be delayed until it is proven that
|
|
the current approach poses a serious performance problem.
|
|
|
|
Thus, the NXdict data structure looks like this:
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap5}
|
|
$\langle$dicdat {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ typedef struct __NXdict@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ int iID;@\\
|
|
\mbox{}\verb@ pStringDict pDictionary;@\\
|
|
\mbox{}\verb@ } sNXdict;@\\
|
|
\mbox{}\verb@/*------------------ verbosity level -------------------------------------*/@\\
|
|
\mbox{}\verb@ static int iVerbosity = 0 ;@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
The first data member is a magic ID number which will be used for testing
|
|
pointers passed in as NXdict pointers. C permits any pointer to be passed
|
|
here. But only those with the correct magic number will be accepted. The
|
|
next data member is a pointer to the string dictionary used for implementing
|
|
the dictionary.
|
|
|
|
Another feature is the verbosity level. This one is declared as a file
|
|
static in order to be available generally.
|
|
|
|
\subsection{The Dictionary Maintainance Functions}
|
|
\subsubsection{NXDinitfromfile}
|
|
This routine starts off by creating and initializing a new NXdict structure:
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap6}
|
|
$\langle$iniini {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* allocate a new NXdict structure */@\\
|
|
\mbox{}\verb@ if(iVerbosity == NXalot)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData, "Allocating new NXdict structure ");@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ pNew = (NXdict)malloc(sizeof(sNXdict));@\\
|
|
\mbox{}\verb@ if(!pNew)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData, "Insufficient memory for creation of NXdict");@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ /* initialise it */@\\
|
|
\mbox{}\verb@ pNew->iID = NXDMAGIC;@\\
|
|
\mbox{}\verb@ pNew->pDictionary = CreateStringDict();@\\
|
|
\mbox{}\verb@ if(!pNew->pDictionary)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData, "Insufficient memory for creation of NXdict");@\\
|
|
\mbox{}\verb@ free(pNew);@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
The next step is to check for the existence of a filename. If filename is
|
|
NULL we are done:
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap7}
|
|
$\langle$inicheck {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* is there a file name argument */@\\
|
|
\mbox{}\verb@ if(filename == NULL)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ if(iVerbosity == NXalot)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData, "NXDinitfrom file finished without data");@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ *pData = pNew;@\\
|
|
\mbox{}\verb@ return NX_OK;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
The next step is to open the file:
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap8}
|
|
$\langle$inifil {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ fd = fopen(filename,"rb");@\\
|
|
\mbox{}\verb@ if(!fd)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ sprintf(pError,"ERROR: file %s NOT found ",filename);@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData, pError);@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData, "NXDinitfrom file finished without data");@\\
|
|
\mbox{}\verb@ *pData = pNew;@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
Now this file needs to be parsed and the alias -- definition string pairs to
|
|
be extracted. This is done in two steps: First the file contents is copied
|
|
in a buffer. Then this buffer is parsed. This aproach has the advantage that
|
|
the parsing code can be reused if another source for the dictionary
|
|
definition shows up. For instance if it is decided to include it with the
|
|
NeXus file in a special vGroup.
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap9}
|
|
$\langle$iniparse {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* read the file contents */@\\
|
|
\mbox{}\verb@ if(iVerbosity == NXalot)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData, "NXDinitfrom: reading file");@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ pBuffer = NXDIReadFile(fd);@\\
|
|
\mbox{}\verb@ fclose(fd); /* we are done with it then */@\\
|
|
\mbox{}\verb@ if(!pBuffer)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ sprintf(pError,"ERROR: reading file %s or no memory",filename);@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData, pError);@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData, "NXDinitfrom file finished without data");@\\
|
|
\mbox{}\verb@ *pData = pNew;@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* parse it */@\\
|
|
\mbox{}\verb@ if(iVerbosity == NXalot)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData, "NXDinitfrom: parsing dictionary definitions");@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ NXDIParse(pBuffer, pNew->pDictionary);@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
Once this has been done, the task left is to clean up and exit.
|
|
|
|
\paragraph{NXDIReadFile}
|
|
This is an internal function which determines the length of the file,
|
|
allocates a suitable buffer for it and then reads the file in the buffer.
|
|
Please note, that the code for determining the length of the file works
|
|
nicely on a Unix or DOS. On a VMS however, there might be a few rubbish
|
|
characters at the end of the buffer. This is due to the record structure of
|
|
files under VMS.
|
|
|
|
\paragraph{NXDIParse}
|
|
NXDIParse is an internal function which parses a buffer into aliases and
|
|
values. It is one of two parsers in the nxdict system. Later on there will
|
|
be a definition string parser. This file reading parser uses a
|
|
Tokenizer.
|
|
|
|
The Tokenizer does not need to recognize a lot of
|
|
tokens, so it is rather simple. NXDIfNextToken returns a pointer pointing to
|
|
the character after the last token read. pPtr is the current position in
|
|
the buffer. The value of the last token read will be returned in the buffer
|
|
pToken. iToken will be set to the type of token recognized.
|
|
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap10}
|
|
$\langle$ftoken {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@#define FWORD 1@\\
|
|
\mbox{}\verb@#define FHASH 2@\\
|
|
\mbox{}\verb@#define FEOL 3@\\
|
|
\mbox{}\verb@#define FEOB 4@\\
|
|
\mbox{}\verb@#define FEQUAL 5@\\
|
|
\mbox{}\verb@#define FSLASH 6@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ static char *NXDIfNextToken(char *pPtr, char *pToken, int *iToken)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ pToken[0] = '\0';@\\
|
|
\mbox{}\verb@ /* skip whitespace */@\\
|
|
\mbox{}\verb@ while( (*pPtr == ' ') || (*pPtr == '\t') )@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ pPtr++;@\\
|
|
\mbox{}\verb@ } @\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* check for special characters */@\\
|
|
\mbox{}\verb@ if(*pPtr == '#')@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ *iToken = FHASH;@\\
|
|
\mbox{}\verb@ pToken[0] = *pPtr;@\\
|
|
\mbox{}\verb@ pPtr++;@\\
|
|
\mbox{}\verb@ return pPtr;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ else if(*pPtr == '\n')@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ *iToken = FEOL;@\\
|
|
\mbox{}\verb@ pToken[0] = *pPtr;@\\
|
|
\mbox{}\verb@ pPtr++;@\\
|
|
\mbox{}\verb@ return pPtr;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ else if(*pPtr == '\0')@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ *iToken = FEOB;@\\
|
|
\mbox{}\verb@ pToken[0] = *pPtr;@\\
|
|
\mbox{}\verb@ pPtr++;@\\
|
|
\mbox{}\verb@ return pPtr;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ else if(*pPtr == '=')@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ *iToken = FEQUAL;@\\
|
|
\mbox{}\verb@ pToken[0] = *pPtr;@\\
|
|
\mbox{}\verb@ pPtr++;@\\
|
|
\mbox{}\verb@ return pPtr;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ else if(*pPtr == '\\')@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ *iToken = FSLASH;@\\
|
|
\mbox{}\verb@ pToken[0] = *pPtr;@\\
|
|
\mbox{}\verb@ pPtr++;@\\
|
|
\mbox{}\verb@ return pPtr;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ else @\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ *iToken = FWORD;@\\
|
|
\mbox{}\verb@ /* copy word to pToken */@\\
|
|
\mbox{}\verb@ while( (*pPtr != ' ') && (*pPtr != '\t') && @\\
|
|
\mbox{}\verb@ (*pPtr != '\n') && (*pPtr != '\0') && (*pPtr != '=') )@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ *pToken = *pPtr;@\\
|
|
\mbox{}\verb@ pPtr++;@\\
|
|
\mbox{}\verb@ pToken++;@\\
|
|
\mbox{}\verb@ } @\\
|
|
\mbox{}\verb@ *pToken = '\0';@\\
|
|
\mbox{}\verb@ return pPtr;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ /* not reached */@\\
|
|
\mbox{}\verb@ return pPtr;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
NXDIParse has two modes: parsing an alias or parsing a definition string.
|
|
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap11}
|
|
$\langle$fparse {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@#define AMODE 0@\\
|
|
\mbox{}\verb@#define DMODE 1@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ static void NXDIParse(char *pBuffer, pStringDict pDict)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ char *pPtr;@\\
|
|
\mbox{}\verb@ int iToken;@\\
|
|
\mbox{}\verb@ int iMode;@\\
|
|
\mbox{}\verb@ char pAlias[132];@\\
|
|
\mbox{}\verb@ char pDefinition[1024]; /* this is > 10 lines of definition */@\\
|
|
\mbox{}\verb@ char pWord[132];@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ assert(pBuffer);@\\
|
|
\mbox{}\verb@ assert(pDict);@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ iMode = AMODE;@\\
|
|
\mbox{}\verb@ pPtr = pBuffer;@\\
|
|
\mbox{}\verb@ iToken = -1;@\\
|
|
\mbox{}\verb@ pDefinition[0] = '\0';@\\
|
|
\mbox{}\verb@ pAlias[0] = '\0';@\\
|
|
\mbox{}\verb@ pWord[0] = '\0';@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ while(iToken != FEOB)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ pPtr = NXDIfNextToken(pPtr,pWord,&iToken);@\\
|
|
\mbox{}\verb@ switch(iToken)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ case FHASH:@\\
|
|
\mbox{}\verb@ case FSLASH: /* skip over \n to next non blank */@\\
|
|
\mbox{}\verb@ while(*pPtr != '\n')@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ pPtr++;@\\
|
|
\mbox{}\verb@ /* check for end of file */@\\
|
|
\mbox{}\verb@ if(*pPtr == '\0')@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ return;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ pPtr++;@\\
|
|
\mbox{}\verb@ break;@\\
|
|
\mbox{}\verb@ case FEQUAL: /* do a mode change */@\\
|
|
\mbox{}\verb@ iMode = DMODE;@\\
|
|
\mbox{}\verb@ pDefinition[0] = '\0';@\\
|
|
\mbox{}\verb@ break;@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ case FWORD:@\\
|
|
\mbox{}\verb@ if(iMode == AMODE)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ strcpy(pAlias,pWord);@\\
|
|
\mbox{}\verb@ } @\\
|
|
\mbox{}\verb@ else@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ strcat(pDefinition,pWord);@\\
|
|
\mbox{}\verb@ strcat(pDefinition," ");@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ break;@\\
|
|
\mbox{}\verb@ case FEOL:@\\
|
|
\mbox{}\verb@ if(iMode == DMODE)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ /* enter in dictionary */@\\
|
|
\mbox{}\verb@ StringDictAddPair(pDict,pAlias,pDefinition);@\\
|
|
\mbox{}\verb@ iMode = AMODE;@\\
|
|
\mbox{}\verb@ pAlias[0] = '\0';@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ break;@\\
|
|
\mbox{}\verb@ case FEOB:@\\
|
|
\mbox{}\verb@ if(iMode == AMODE) @\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ /* empty line or a problem */@\\
|
|
\mbox{}\verb@ } @\\
|
|
\mbox{}\verb@ else@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ /* enter in dictionary */@\\
|
|
\mbox{}\verb@ StringDictAddPair(pDict,pAlias,pDefinition);@\\
|
|
\mbox{}\verb@ iMode = AMODE;@\\
|
|
\mbox{}\verb@ pAlias[0] = '\0';@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ return;@\\
|
|
\mbox{}\verb@ default:@\\
|
|
\mbox{}\verb@ assert(0); /* unrecognized token is a programming@\\
|
|
\mbox{}\verb@ error@\\
|
|
\mbox{}\verb@ */@\\
|
|
\mbox{}\verb@ break;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
\subsubsection{NXDClose}
|
|
This routine will just write the dictionary to file if requested and clean
|
|
up afterwards. Prior to defining NXDClose anohter internal function is
|
|
needed which checks the validity of the handle passed into the routine.
|
|
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap12}
|
|
$\langle$dassert {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ NXdict NXDIAssert(NXdict handle)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ NXdict self = NULL;@\\
|
|
\mbox{}\verb@ assert(handle);@\\
|
|
\mbox{}\verb@ self = (NXdict)handle;@\\
|
|
\mbox{}\verb@ assert(self->iID == NXDMAGIC);@\\
|
|
\mbox{}\verb@ return self;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap13}
|
|
$\langle$dclose {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ NXstatus NXDclose(NXdict handle, char *filename)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ NXdict self;@\\
|
|
\mbox{}\verb@ const char *pKey = NULL;@\\
|
|
\mbox{}\verb@ char pValue[1024];@\\
|
|
\mbox{}\verb@ FILE *fd = NULL;@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ self = NXDIAssert(handle);@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ if(filename) /* we must write a file */@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ if(iVerbosity == NXalot)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ sprintf(pValue,"Writing file %s",filename);@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData, pValue);@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ fd = fopen(filename,"w");@\\
|
|
\mbox{}\verb@ if(!fd)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ sprintf(pValue,"ERROR: opening file %s for write",filename);@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData, pValue);@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ } @\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ /* write our magic recognition header */@\\
|
|
\mbox{}\verb@ fprintf(fd,"##NXDICT-1.0\n");@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* write all our keys */@\\
|
|
\mbox{}\verb@ pKey = StringDictGetNext(self->pDictionary, pValue,1023);@\\
|
|
\mbox{}\verb@ while(pKey != NULL)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ fprintf(fd,"%s = %s\n",pKey,pValue);@\\
|
|
\mbox{}\verb@ pKey = StringDictGetNext(self->pDictionary,pValue,1023);@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ fclose(fd);@\\
|
|
\mbox{}\verb@ if(iVerbosity == NXalot)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ sprintf(pValue,"File %s written",filename);@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData, pValue);@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* now we send the cleaners in */@\\
|
|
\mbox{}\verb@ DeleteStringDict(self->pDictionary);@\\
|
|
\mbox{}\verb@ free(self);@\\
|
|
\mbox{}\verb@ return NX_OK;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
\subsubsection{NXDadd, NXDget, NXDupdate}
|
|
These are very much only wrapper function around the corresponding functions
|
|
for maintaining StringDicts. Accordingly, they are fairly simple.
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap14}
|
|
$\langle$dmaintain {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ NXstatus NXDadd(NXdict handle, char *alias, char *pDef)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ NXdict self;@\\
|
|
\mbox{}\verb@ int iRet;@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ self = NXDIAssert(handle);@\\
|
|
\mbox{}\verb@ iRet = StringDictAddPair(self->pDictionary,alias,pDef);@\\
|
|
\mbox{}\verb@ if(!iRet)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ return NX_OK;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@/*---------------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@ NXstatus NXDget(NXdict handle, char *pKey, char *pBuffer, int iBufLen)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ NXdict self;@\\
|
|
\mbox{}\verb@ int iRet;@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ self = NXDIAssert(handle);@\\
|
|
\mbox{}\verb@ iRet = StringDictGet(self->pDictionary,pKey,pBuffer,iBufLen);@\\
|
|
\mbox{}\verb@ if(!iRet)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@#ifdef DEFDEBUG@\\
|
|
\mbox{}\verb@ printf("Resolved: %s to %s\n",pKey,pBuffer);@\\
|
|
\mbox{}\verb@#endif@\\
|
|
\mbox{}\verb@ return NX_OK;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@/*-------------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@ NXstatus NXDupdate(NXdict handle, char *pKey, char *pNewVal)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ NXdict self;@\\
|
|
\mbox{}\verb@ int iRet;@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ self = NXDIAssert(handle);@\\
|
|
\mbox{}\verb@ iRet = StringDictUpdate(self->pDictionary,pKey,pNewVal);@\\
|
|
\mbox{}\verb@ if(!iRet)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ return NX_OK;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
\subsubsection{Text replacement}
|
|
A definition string as retrieved from the string dictionary may still
|
|
contain text replacement items. The next function, NXDtextreplace resolves
|
|
these text replacements.
|
|
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap15}
|
|
$\langle$textrep {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@#define NORMAL 1@\\
|
|
\mbox{}\verb@#define ALIAS 2@\\
|
|
\mbox{}\verb@ pDynString NXDItextreplace(NXdict handle, char *pDefString)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ NXdict self;@\\
|
|
\mbox{}\verb@ int iRet, iPos, i;@\\
|
|
\mbox{}\verb@ pDynString pReplaced = NULL;@\\
|
|
\mbox{}\verb@ char pBueffel[1024];@\\
|
|
\mbox{}\verb@ char pBuffer2[1024];@\\
|
|
\mbox{}\verb@ char *pPtr;@\\
|
|
\mbox{}\verb@ int iState;@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ self = NXDIAssert(handle);@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ /* create a dynamic string */@\\
|
|
\mbox{}\verb@ pReplaced = CreateDynString(strlen(pDefString),512);@\\
|
|
\mbox{}\verb@ if(!pReplaced)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData,"ERROR: out of memory in NXDtextreplace");@\\
|
|
\mbox{}\verb@ return NULL;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* the loop */@\\
|
|
\mbox{}\verb@ iState = NORMAL;@\\
|
|
\mbox{}\verb@ for(i = 0, pPtr = pDefString; i < strlen(pDefString); i++,pPtr++)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ if(iState == NORMAL)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ if(*pPtr == '$')@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ iState = ALIAS;@\\
|
|
\mbox{}\verb@ memset(pBueffel,0,1024);@\\
|
|
\mbox{}\verb@ iPos = 0;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ else@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ DynStringConcatChar(pReplaced,*pPtr);@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ else if(iState == ALIAS)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ switch(*pPtr)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ case '(': /* ignore */@\\
|
|
\mbox{}\verb@ break;@\\
|
|
\mbox{}\verb@ case ')': @\\
|
|
\mbox{}\verb@ /* do the replacement */@\\
|
|
\mbox{}\verb@ memset(pBuffer2,0,1023);@\\
|
|
\mbox{}\verb@ iRet = NXDget(handle, pBueffel,pBuffer2,1023);@\\
|
|
\mbox{}\verb@ if(iRet != NX_OK)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ DeleteDynString(pReplaced);@\\
|
|
\mbox{}\verb@ return NULL;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ DynStringConcat(pReplaced,pBuffer2);@\\
|
|
\mbox{}\verb@ iState = NORMAL;@\\
|
|
\mbox{}\verb@ break;@\\
|
|
\mbox{}\verb@ default:@\\
|
|
\mbox{}\verb@ pBueffel[iPos] = *pPtr;@\\
|
|
\mbox{}\verb@ iPos++;@\\
|
|
\mbox{}\verb@ if(iPos >= 1024)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData,@\\
|
|
\mbox{}\verb@ "ERROR: buffer overrun in NXDItextreplace");@\\
|
|
\mbox{}\verb@ DeleteDynString(pReplaced);@\\
|
|
\mbox{}\verb@ return NULL;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ break;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@#ifdef DEFDEBUG@\\
|
|
\mbox{}\verb@ printf("Replacement result: %s\n",GetCharArray(pReplaced));@\\
|
|
\mbox{}\verb@#endif@\\
|
|
\mbox{}\verb@ return pReplaced;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@/*--------------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@ NXstatus NXDtextreplace(NXdict handle, char *pDefString, @\\
|
|
\mbox{}\verb@ char *pBuffer, int iBufLen)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ pDynString pResult = NULL;@\\
|
|
\mbox{}\verb@ char *pPtr = NULL;@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ pResult = NXDItextreplace(handle,pDefString);@\\
|
|
\mbox{}\verb@ if(!pResult)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* copy results home */@\\
|
|
\mbox{}\verb@ pPtr = GetCharArray(pResult);@\\
|
|
\mbox{}\verb@ strncpy(pBuffer,pPtr,iBufLen); @\\
|
|
\mbox{}\verb@ DeleteDynString(pResult);@\\
|
|
\mbox{}\verb@ return NX_OK;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
\subsection{Dictionary Added Data Transfer}
|
|
The heart of these routines is the NXDopendef function which opens the data
|
|
item specified. Most of the other routines can be defined as wrappers to
|
|
this one. That is why it is discussed as the first function. Again a parser
|
|
is needed for parsing and interpreting the definition string.
|
|
|
|
\subsubsection{The Definition String Parser}
|
|
The definition string parser is implemented as a classic recursive descent
|
|
parser. And once
|
|
more again a Tokenizer is needed. The Tokenizer has an own datastructure for
|
|
holding token information in a static array:
|
|
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap16}
|
|
$\langle$tokdat {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ typedef struct {@\\
|
|
\mbox{}\verb@ char pText[20];@\\
|
|
\mbox{}\verb@ int iCode;@\\
|
|
\mbox{}\verb@ } TokDat;@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
In order to do the parsing a data structure for holding parsing information
|
|
is necessary:
|
|
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap17}
|
|
$\langle$padef {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@#define TERMSDS 100@\\
|
|
\mbox{}\verb@#define TERMVG 200@\\
|
|
\mbox{}\verb@#define TERMLINK 300@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ typedef struct {@\\
|
|
\mbox{}\verb@ char *pPtr;@\\
|
|
\mbox{}\verb@ char pToken[256];@\\
|
|
\mbox{}\verb@ int iToken;@\\
|
|
\mbox{}\verb@ int iDepth;@\\
|
|
\mbox{}\verb@ int iMayCreate;@\\
|
|
\mbox{}\verb@ int iTerminal;@\\
|
|
\mbox{}\verb@ } ParDat;@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
In this structure pPtr is the current position in the buffer, iToken the ID
|
|
of the current token, pToken the text of the current token, iDepth gets
|
|
incremented whenever a vGroup is opened. This is needed in order to roll the
|
|
vGroups back in the hierarchy after finishing operations. iMayCreate will be
|
|
set if the path parsing function may create new vGroups if the one requested
|
|
can not be found.
|
|
|
|
This is the tokenizer:
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap18}
|
|
$\langle$deftok {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@/*---------------- Token name defines ---------------------------*/@\\
|
|
\mbox{}\verb@#define DSLASH 0@\\
|
|
\mbox{}\verb@#define DKOMMA 1@\\
|
|
\mbox{}\verb@#define DSDS 2@\\
|
|
\mbox{}\verb@#define DLINK 3@\\
|
|
\mbox{}\verb@#define DGROUP 4@\\
|
|
\mbox{}\verb@#define DRANK 5@\\
|
|
\mbox{}\verb@#define DDIM 6@\\
|
|
\mbox{}\verb@#define DTYPE 7@\\
|
|
\mbox{}\verb@#define DWORD 9@\\
|
|
\mbox{}\verb@#define DOPEN 10@\\
|
|
\mbox{}\verb@#define DCLOSE 11@\\
|
|
\mbox{}\verb@#define DATTR 12@\\
|
|
\mbox{}\verb@#define DEND 13@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@/*----------------- Keywords ----------------------------------------*/@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ static TokDat TokenList[8] = { @\\
|
|
\mbox{}\verb@ {"SDS",DSDS},@\\
|
|
\mbox{}\verb@ {"NXLINK",DLINK},@\\
|
|
\mbox{}\verb@ {"NXVGROUP",DGROUP},@\\
|
|
\mbox{}\verb@ {"-dim",DDIM},@\\
|
|
\mbox{}\verb@ {"-type",DTYPE},@\\
|
|
\mbox{}\verb@ {"-rank",DRANK},@\\
|
|
\mbox{}\verb@ {"-attr",DATTR},@\\
|
|
\mbox{}\verb@ {"",0} };@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@/*-----------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@ static void NXDIDefToken(ParDat *sStat)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ int i;@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ sStat->pToken[0] = '\0';@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* skip whitespace */@\\
|
|
\mbox{}\verb@ while( (*(sStat->pPtr) == ' ') || (*(sStat->pPtr) == '\t') )@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ sStat->pPtr++;@\\
|
|
\mbox{}\verb@ } @\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* check for special characters */@\\
|
|
\mbox{}\verb@ if(*(sStat->pPtr) == '/')@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ sStat->iToken = DSLASH;@\\
|
|
\mbox{}\verb@ sStat->pToken[0] = *(sStat->pPtr);@\\
|
|
\mbox{}\verb@ sStat->pPtr++;@\\
|
|
\mbox{}\verb@ return;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ else if(*(sStat->pPtr) == ',')@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ sStat->iToken = DKOMMA;@\\
|
|
\mbox{}\verb@ sStat->pToken[0] = *(sStat->pPtr);@\\
|
|
\mbox{}\verb@ sStat->pPtr++;@\\
|
|
\mbox{}\verb@ return;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ else if(*(sStat->pPtr) == '\0')@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ sStat->iToken = DEND;@\\
|
|
\mbox{}\verb@ sStat->pToken[0] = *(sStat->pPtr);@\\
|
|
\mbox{}\verb@ sStat->pPtr++;@\\
|
|
\mbox{}\verb@ return;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ else if(*(sStat->pPtr) == '{')@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ sStat->iToken = DOPEN;@\\
|
|
\mbox{}\verb@ sStat->pToken[0] = *(sStat->pPtr);@\\
|
|
\mbox{}\verb@ sStat->pPtr++;@\\
|
|
\mbox{}\verb@ return;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ else if(*(sStat->pPtr) == '}')@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ sStat->iToken = DCLOSE;@\\
|
|
\mbox{}\verb@ sStat->pToken[0] = *(sStat->pPtr);@\\
|
|
\mbox{}\verb@ sStat->pPtr++;@\\
|
|
\mbox{}\verb@ return;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ else @\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ sStat->iToken = DWORD;@\\
|
|
\mbox{}\verb@ /* copy word to pToken */@\\
|
|
\mbox{}\verb@ i = 0;@\\
|
|
\mbox{}\verb@ while( (*(sStat->pPtr) != ' ') && (*(sStat->pPtr) != '\t') && @\\
|
|
\mbox{}\verb@ (*(sStat->pPtr) != '/') && (*(sStat->pPtr) != '\0') &&@\\
|
|
\mbox{}\verb@ (*(sStat->pPtr) != ',') && (*(sStat->pPtr) != '}') )@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ sStat->pToken[i] = *(sStat->pPtr);@\\
|
|
\mbox{}\verb@ sStat->pPtr++;@\\
|
|
\mbox{}\verb@ i++;@\\
|
|
\mbox{}\verb@ } @\\
|
|
\mbox{}\verb@ sStat->pToken[i] = '\0';@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /*--------- try to find word in Tokenlist */@\\
|
|
\mbox{}\verb@ for(i = 0; i < 7; i++)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ if(strcmp(sStat->pToken,TokenList[i].pText) == 0)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ sStat->iToken = TokenList[i].iCode;@\\
|
|
\mbox{}\verb@ break;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ return;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ /* not reached */@\\
|
|
\mbox{}\verb@ return;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
Now, finally we can define the parser! This parser is universally used by
|
|
all the data transfer functions. Input is the file handle of the NeXus file
|
|
and a pointer to an initialised ParDat structure. It is expected, that the
|
|
pPtr field points to the start of the definition string, that iMayCreate is
|
|
properly defined and that iDepth is 0.
|
|
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap19}
|
|
$\langle$defpar {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ static int NXDIDefParse(NXhandle hFil, NXdict pDict, ParDat *pParse)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ int iRet;@\\
|
|
\mbox{}\verb@ char pError[256];@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ pParse->iToken = -1;@\\
|
|
\mbox{}\verb@ while(pParse->iToken != DEND)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ NXDIDefToken(pParse); /* next token */@\\
|
|
\mbox{}\verb@ switch(pParse->iToken)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ case DEND:@\\
|
|
\mbox{}\verb@ break;@\\
|
|
\mbox{}\verb@ case DSLASH:@\\
|
|
\mbox{}\verb@ iRet = NXDIParsePath(hFil, pParse);@\\
|
|
\mbox{}\verb@ if(iRet == NX_ERROR)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ break;@\\
|
|
\mbox{}\verb@ case DSDS:@\\
|
|
\mbox{}\verb@ iRet = NXDIParseSDS(hFil, pParse);@\\
|
|
\mbox{}\verb@ if(iRet == NX_ERROR)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ pParse->iTerminal = TERMSDS;@\\
|
|
\mbox{}\verb@ break;@\\
|
|
\mbox{}\verb@ case DLINK:@\\
|
|
\mbox{}\verb@ iRet = NXDIParseLink(hFil,pDict, pParse); @\\
|
|
\mbox{}\verb@ if(iRet == NX_ERROR)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ pParse->iTerminal = TERMLINK;@\\
|
|
\mbox{}\verb@ break;@\\
|
|
\mbox{}\verb@ case DGROUP:@\\
|
|
\mbox{}\verb@ pParse->iTerminal = TERMVG;@\\
|
|
\mbox{}\verb@ return NX_OK;@\\
|
|
\mbox{}\verb@ default:@\\
|
|
\mbox{}\verb@ sprintf(pError,@\\
|
|
\mbox{}\verb@ "ERROR: Definition String parse error: %s not permitted here",@\\
|
|
\mbox{}\verb@ pParse->pToken);@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData,pError);@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ break;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ return NX_OK;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
The next thing to do is to implement ParsePath. This will try to interpret a
|
|
path string and initiate the apropriate actions, i.e. opening vGroups or
|
|
creating them. However, there is a small problem here. The code needs to
|
|
know if the vGroup exists. This can be checked by trying to open the group
|
|
with NXopengroup. This will return an error if this group does not exist.
|
|
NXopengroup will also print an error message saying so. This is not what is
|
|
wanted here, as we might choose to create the missing group silently.
|
|
In order to suppress
|
|
that one, it is needed to replace the current error handler by a dummy which
|
|
just prints nothing anywhere and to step back to the original handler once
|
|
we are done. The other option would be to use internals of the NeXus API
|
|
implementation. However, the aim is to keep the original NeXus API and this
|
|
as independent as possible. Consequently, here is the definition of the
|
|
dummy error handler:
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap20}
|
|
$\langle$dummyerr {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ static void DummyError(void *pData, char *pError)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ return;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
When NXDIParsePath has been called the / has already been read.
|
|
NXDIParsePath has to read the name and class of the vGroup separated by a
|
|
komma. Then it has either to open the vGroup, and if this fails create it if
|
|
the create flag in pParse is set.
|
|
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap21}
|
|
$\langle$defpath {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ int NXDIParsePath(NXhandle hfil, ParDat *pParse)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ int iRet, iToken;@\\
|
|
\mbox{}\verb@ void (*ErrFunc)(void *pData, char *pErr); @\\
|
|
\mbox{}\verb@ char pName[132], pClass[132];@\\
|
|
\mbox{}\verb@ char pError[256];@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* get the name */@\\
|
|
\mbox{}\verb@ NXDIDefToken(pParse); /* next token */@\\
|
|
\mbox{}\verb@ if( (pParse->iToken == DSDS) || (pParse->iToken == DGROUP)@\\
|
|
\mbox{}\verb@ || (pParse->iToken == DLINK) )@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ /* put back & OK */@\\
|
|
\mbox{}\verb@ pParse->pPtr -= strlen(pParse->pToken);@\\
|
|
\mbox{}\verb@ return NX_OK;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ if(pParse->iToken != DWORD)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ sprintf(pError,"ERROR: parse error at %s, expected vGroup name",@\\
|
|
\mbox{}\verb@ pParse->pToken);@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData, pError);@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ } @\\
|
|
\mbox{}\verb@ strcpy(pName,pParse->pToken);@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ /* now we expect a komma */@\\
|
|
\mbox{}\verb@ NXDIDefToken(pParse); /* next token */@\\
|
|
\mbox{}\verb@ if(pParse->iToken != DKOMMA)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ sprintf(pError,"ERROR: parse error at %s, expected komma",@\\
|
|
\mbox{}\verb@ pParse->pToken);@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData, pError);@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ } @\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* next must be the class */@\\
|
|
\mbox{}\verb@ NXDIDefToken(pParse); /* next token */@\\
|
|
\mbox{}\verb@ if(pParse->iToken != DWORD)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ sprintf(pError,"ERROR: parse error at %s, expected vGroup class",@\\
|
|
\mbox{}\verb@ pParse->pToken);@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData, pError);@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ } @\\
|
|
\mbox{}\verb@ strcpy(pClass,pParse->pToken);@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* done reading, ACTION, first install dummy error handler */@\\
|
|
\mbox{}\verb@ ErrFunc = NXIReportError;@\\
|
|
\mbox{}\verb@ NXMSetError(NXpData, DummyError);@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ /* try opening vGroup */@\\
|
|
\mbox{}\verb@ iRet = NXopengroup(hfil, pName, pClass);@\\
|
|
\mbox{}\verb@ NXMSetError(NXpData,ErrFunc);@\\
|
|
\mbox{}\verb@ if(iRet == NX_OK)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ pParse->iDepth++;@\\
|
|
\mbox{}\verb@ return NX_OK;@\\
|
|
\mbox{}\verb@ } @\\
|
|
\mbox{}\verb@ else@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ /* we need to create it, if we may */@\\
|
|
\mbox{}\verb@ if(pParse->iMayCreate)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ iRet = NXmakegroup(hfil,pName,pClass);@\\
|
|
\mbox{}\verb@ if(iRet != NX_OK)@\\
|
|
\mbox{}\verb@ { @\\
|
|
\mbox{}\verb@ /* a comment on this one has already been written! */@\\
|
|
\mbox{}\verb@ return iRet;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ iRet = NXopengroup(hfil,pName,pClass);@\\
|
|
\mbox{}\verb@ if(iRet != NX_OK)@\\
|
|
\mbox{}\verb@ { @\\
|
|
\mbox{}\verb@ /* a comment on this one has already been written! */@\\
|
|
\mbox{}\verb@ return iRet;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ pParse->iDepth++;@\\
|
|
\mbox{}\verb@ return NX_OK; @\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ else@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ /* this is an error */@\\
|
|
\mbox{}\verb@ sprintf(pError,"ERROR: vGroup %s, %s NOT found",pName, pClass);@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData,pError);@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ /* not reached */@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
NXDIParseSDS is more involved, as we have to deal with all the extras an SDS
|
|
can have: dimensions, types etc. Each of these options can be present or
|
|
not, and these options can go in any order. Particularly troublesome are
|
|
attributes which can only be written after opening or creating an SDS. this
|
|
implies that attributes have to be stored in a list during parsing in order
|
|
to have them available after creation or opening of the SDS. This requires
|
|
another private data structure for holding attribute information during
|
|
parsing:
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap22}
|
|
$\langle$attitem {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ typedef struct {@\\
|
|
\mbox{}\verb@ char name[256];@\\
|
|
\mbox{}\verb@ char value[256];@\\
|
|
\mbox{}\verb@ }AttItem;@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap23}
|
|
$\langle$nxpasds {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ static int NXDIParseSDS(NXhandle hfil, ParDat *pParse)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ int iType = DFNT_FLOAT32;@\\
|
|
\mbox{}\verb@ int iRank = 1;@\\
|
|
\mbox{}\verb@ int32 iDim[MAX_VAR_DIMS];@\\
|
|
\mbox{}\verb@ int iList;@\\
|
|
\mbox{}\verb@ int iRet, iStat;@\\
|
|
\mbox{}\verb@ char pError[256];@\\
|
|
\mbox{}\verb@ char pName[MAX_NC_NAME];@\\
|
|
\mbox{}\verb@ void (*ErrFunc)(void *pData, char *pErr);@\\
|
|
\mbox{}\verb@ AttItem sAtt; @\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ iDim[0] = 1;@\\
|
|
\mbox{}\verb@ /* first find the name */@\\
|
|
\mbox{}\verb@ NXDIDefToken(pParse);@\\
|
|
\mbox{}\verb@ if(pParse->iToken != DWORD)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ sprintf(pError,"ERROR: parsing, expected name, got %s",@\\
|
|
\mbox{}\verb@ pParse->pToken);@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData,pError);@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ strcpy(pName,pParse->pToken);@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* create the attribute list */@\\
|
|
\mbox{}\verb@ iList = LLDcreate(sizeof(AttItem));@\\
|
|
\mbox{}\verb@ if(iList < 0)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData, "ERROR: cannot create list in NXDIParseSDS");@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ NXDIDefToken(pParse);@\\
|
|
\mbox{}\verb@ while(pParse->iToken != DEND)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ switch(pParse->iToken)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ case DRANK: /* rank */@\\
|
|
\mbox{}\verb@ NXDIDefToken(pParse); /* advance */@\\
|
|
\mbox{}\verb@ if(pParse->iToken != DWORD)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ sprintf(pError,@\\
|
|
\mbox{}\verb@ "ERROR: expected int, got %s", pParse->pToken);@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData,pError);@\\
|
|
\mbox{}\verb@ LLDdelete(iList);@\\
|
|
\mbox{}\verb@ return NX_ERROR; @\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ iRank = atoi(pParse->pToken);@\\
|
|
\mbox{}\verb@ break;@\\
|
|
\mbox{}\verb@ case DDIM:@\\
|
|
\mbox{}\verb@ iRet = NXDIParseDim (pParse, (int *) iDim);@\\
|
|
\mbox{}\verb@ if(iRet == NX_ERROR)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ LLDdelete(iList);@\\
|
|
\mbox{}\verb@ return iRet;@\\
|
|
\mbox{}\verb@ } @\\
|
|
\mbox{}\verb@ break;@\\
|
|
\mbox{}\verb@ case DTYPE:@\\
|
|
\mbox{}\verb@ iRet = NXDIParseType(pParse, &iType);@\\
|
|
\mbox{}\verb@ if(iRet == NX_ERROR)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ LLDdelete(iList);@\\
|
|
\mbox{}\verb@ return iRet;@\\
|
|
\mbox{}\verb@ } @\\
|
|
\mbox{}\verb@ break;@\\
|
|
\mbox{}\verb@ case DATTR:@\\
|
|
\mbox{}\verb@ iRet = NXDIParseAttr(pParse, iList);@\\
|
|
\mbox{}\verb@ if(iRet == NX_ERROR)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ LLDdelete(iList);@\\
|
|
\mbox{}\verb@ return iRet;@\\
|
|
\mbox{}\verb@ } @\\
|
|
\mbox{}\verb@ break;@\\
|
|
\mbox{}\verb@ case DEND:@\\
|
|
\mbox{}\verb@ break;@\\
|
|
\mbox{}\verb@ default:@\\
|
|
\mbox{}\verb@ sprintf(pError,"ERROR: cannot identify token %s",@\\
|
|
\mbox{}\verb@ pParse->pToken);@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData, pError);@\\
|
|
\mbox{}\verb@ LLDdelete(iList);@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ NXDIDefToken(pParse);@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ /* whew! got all information for doing the SDS */@\\
|
|
\mbox{}\verb@ /* first install dummy error handler, try open it, then@\\
|
|
\mbox{}\verb@ deinstall again and create if allowed @\\
|
|
\mbox{}\verb@ */@\\
|
|
\mbox{}\verb@ ErrFunc = NXIReportError;@\\
|
|
\mbox{}\verb@ NXMSetError(NXpData, DummyError);@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ /* try opening SDS */@\\
|
|
\mbox{}\verb@ iRet = NXopendata(hfil, pName);@\\
|
|
\mbox{}\verb@ NXMSetError(NXpData,ErrFunc);@\\
|
|
\mbox{}\verb@ if(iRet == NX_OK)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ LLDdelete(iList);@\\
|
|
\mbox{}\verb@ return NX_OK;@\\
|
|
\mbox{}\verb@ } @\\
|
|
\mbox{}\verb@ else@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ /* we need to create it, if we may */@\\
|
|
\mbox{}\verb@ if(pParse->iMayCreate)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ iRet = NXmakedata (hfil, pName, iType, iRank, (int *) iDim);@\\
|
|
\mbox{}\verb@ if(iRet != NX_OK)@\\
|
|
\mbox{}\verb@ { @\\
|
|
\mbox{}\verb@ /* a comment on this one has already been written! */@\\
|
|
\mbox{}\verb@ LLDdelete(iList);@\\
|
|
\mbox{}\verb@ return iRet;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ iRet = NXopendata(hfil,pName);@\\
|
|
\mbox{}\verb@ if(iRet != NX_OK)@\\
|
|
\mbox{}\verb@ { @\\
|
|
\mbox{}\verb@ /* a comment on this one has already been written! */@\\
|
|
\mbox{}\verb@ LLDdelete(iList);@\\
|
|
\mbox{}\verb@ return iRet;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ /* put attributes in */@\\
|
|
\mbox{}\verb@ iRet = LLDnodePtr2First(iList);@\\
|
|
\mbox{}\verb@ while(iRet != 0)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ LLDnodeDataTo(iList,&sAtt);@\\
|
|
\mbox{}\verb@ iStat = NXputattr(hfil,sAtt.name,@\\
|
|
\mbox{}\verb@ sAtt.value,strlen(sAtt.value),NX_CHAR);@\\
|
|
\mbox{}\verb@ if(iStat != NX_OK)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ /* NeXus already complained bitterly */@\\
|
|
\mbox{}\verb@ LLDdelete(iList);@\\
|
|
\mbox{}\verb@ return iStat;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ iRet = LLDnodePtr2Next(iList);@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ LLDdelete(iList);@\\
|
|
\mbox{}\verb@ return NX_OK; @\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ else@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ /* this is an error */@\\
|
|
\mbox{}\verb@ sprintf(pError,"ERROR: SDS %s NOT found",pName);@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData,pError);@\\
|
|
\mbox{}\verb@ LLDdelete(iList);@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ return NX_OK;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
NXDIParseType is fairly straightforward: read a word and try to interpret it
|
|
as one of the standard NeXus data types.
|
|
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap24}
|
|
$\langle$parsetype {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ static TokDat tDatType[] = {@\\
|
|
\mbox{}\verb@ {"DFNT_FLOAT32",DFNT_FLOAT32}, @\\
|
|
\mbox{}\verb@ {"DFNT_FLOAT64",DFNT_FLOAT64}, @\\
|
|
\mbox{}\verb@ {"DFNT_INT8",DFNT_INT8}, @\\
|
|
\mbox{}\verb@ {"DFNT_UINT8",DFNT_UINT8},@\\
|
|
\mbox{}\verb@ {"DFNT_INT16",DFNT_INT16}, @\\
|
|
\mbox{}\verb@ {"DFNT_UINT16",DFNT_UINT16},@\\
|
|
\mbox{}\verb@ {"DFNT_INT32",DFNT_INT32},@\\
|
|
\mbox{}\verb@ {"DFNT_UINT32",DFNT_UINT32},@\\
|
|
\mbox{}\verb@ {"",0} };@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ static int NXDIParseType(ParDat *pParse, int *iType)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ char pError[256];@\\
|
|
\mbox{}\verb@ int i = 0;@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ NXDIDefToken(pParse);@\\
|
|
\mbox{}\verb@ if(pParse->iToken != DWORD)@\\
|
|
\mbox{}\verb@ { @\\
|
|
\mbox{}\verb@ sprintf(pError,"ERROR: expected data type, got %s", pParse->pToken);@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData,pError);@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ /* try to interpret data type */@\\
|
|
\mbox{}\verb@ while(tDatType[i].iCode > 0) {@\\
|
|
\mbox{}\verb@ if(strcmp(tDatType[i].pText,pParse->pToken) == 0)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ *iType = tDatType[i].iCode;@\\
|
|
\mbox{}\verb@ return NX_OK;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ i++;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ /* if we are here, the data type has not been recognized. Reason for@\\
|
|
\mbox{}\verb@ some boring error reporting code@\\
|
|
\mbox{}\verb@ */@\\
|
|
\mbox{}\verb@ sprintf(pError,"ERROR: %s not recognized as valid data type",@\\
|
|
\mbox{}\verb@ pParse->pToken);@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData,pError);@\\
|
|
\mbox{}\verb@ return NX_ERROR; @\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
NXDIParseDim tries to read dimension information. This starts with a {
|
|
followed by numbers and kommas until there is a closing curly brace.
|
|
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap25}
|
|
$\langle$parsedim {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ static int NXDIParseDim(ParDat *pParse, int *iDim)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ char pError[256];@\\
|
|
\mbox{}\verb@ int iRet, i;@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* initialise dimensions to 0 */@\\
|
|
\mbox{}\verb@ for(i = 0; i < MAX_VAR_DIMS; i++)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ iDim[i] = 0;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ NXDIDefToken(pParse);@\\
|
|
\mbox{}\verb@ if(pParse->iToken != DOPEN)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ sprintf(pError,"ERROR: expected {, got %s",pParse->pToken);@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData,pError);@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ i = 0; @\\
|
|
\mbox{}\verb@ while(pParse->iToken != DCLOSE)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ /* get a number */@\\
|
|
\mbox{}\verb@ NXDIDefToken(pParse);@\\
|
|
\mbox{}\verb@ if(pParse->iToken != DWORD)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ sprintf(pError,"ERROR: expected number, got %s",pParse->pToken);@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData,pError);@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ iDim[i] = atoi(pParse->pToken);@\\
|
|
\mbox{}\verb@ i++;@\\
|
|
\mbox{}\verb@ /* next must be close of komma */@\\
|
|
\mbox{}\verb@ NXDIDefToken(pParse);@\\
|
|
\mbox{}\verb@ if( (pParse->iToken != DKOMMA) && (pParse->iToken != DCLOSE) )@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ sprintf(pError,"ERROR: expected , or }, got %s",pParse->pToken);@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData,pError);@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ if(pParse->iToken == DCLOSE)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ break;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ return NX_OK;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
NXDIParseAttr tries to parse an attribute and enters it into the attribute
|
|
list.
|
|
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap26}
|
|
$\langle$parseatt {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ static int NXDIParseAttr(ParDat *pParse, int iList)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ char pError[256];@\\
|
|
\mbox{}\verb@ int iRet;@\\
|
|
\mbox{}\verb@ AttItem sAtt;@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* a { is expected */@\\
|
|
\mbox{}\verb@ NXDIDefToken(pParse);@\\
|
|
\mbox{}\verb@ if(pParse->iToken != DOPEN)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ sprintf(pError,"ERROR: expected {, got %s",pParse->pToken);@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData,pError);@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* a word is expected */@\\
|
|
\mbox{}\verb@ NXDIDefToken(pParse);@\\
|
|
\mbox{}\verb@ if(pParse->iToken != DWORD)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ sprintf(pError,"ERROR: expected attribute name, got %s",pParse->pToken);@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData,pError);@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ strcpy(sAtt.name,pParse->pToken);@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* a , is expected */@\\
|
|
\mbox{}\verb@ NXDIDefToken(pParse);@\\
|
|
\mbox{}\verb@ if(pParse->iToken != DKOMMA)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ sprintf(pError,"ERROR: expected , , got %s",pParse->pToken);@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData,pError);@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* a word is expected */@\\
|
|
\mbox{}\verb@ NXDIDefToken(pParse);@\\
|
|
\mbox{}\verb@ if(pParse->iToken != DWORD)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ sprintf(pError,"ERROR: expected attribute value, got %s",pParse->pToken);@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData,pError);@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ strcpy(sAtt.value,pParse->pToken);@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* a } is expected */@\\
|
|
\mbox{}\verb@ NXDIDefToken(pParse);@\\
|
|
\mbox{}\verb@ if(pParse->iToken != DCLOSE)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ sprintf(pError,"ERROR: expected }, got %s",pParse->pToken);@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData,pError);@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* enter into list */@\\
|
|
\mbox{}\verb@ LLDnodeAppendFrom(iList,&sAtt);@\\
|
|
\mbox{}\verb@ return NX_OK;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
The last part of the definition string parser is NXDIParseLink. This
|
|
function parses and handles a link to another data item in the file.
|
|
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap27}
|
|
$\langle$parselink {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ static int NXDIParseLink(NXhandle hfil, NXdict pDict,ParDat *pParse)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ char pError[256];@\\
|
|
\mbox{}\verb@ int i, iRet;@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* need one word of alias */ @\\
|
|
\mbox{}\verb@ NXDIDefToken(pParse);@\\
|
|
\mbox{}\verb@ if(pParse->iToken != DCLOSE)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ sprintf(pError,"ERROR: expected alias , got %s",pParse->pToken);@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData,pError);@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ /* move back in hierarchy */@\\
|
|
\mbox{}\verb@ for(i = 0; i < pParse->iDepth; i++)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ iRet = NXclosegroup(hfil);@\\
|
|
\mbox{}\verb@ if(iRet == NX_ERROR)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ /* open the link instead */ @\\
|
|
\mbox{}\verb@ return NXDopenalias(hfil, pDict, pParse->pToken);@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
Another helper function unwinds the vGroup hierarchy.
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap28}
|
|
$\langle$unwind {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ static NXstatus NXDIUnwind(NXhandle hFil, int iDepth)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ int i, iRet;@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ for(i = 0; i < iDepth; i++)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ iRet = NXclosegroup(hFil);@\\
|
|
\mbox{}\verb@ if(iRet != NX_OK)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ return NX_OK;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
\subsubsection{NXDopendef}
|
|
NXDopendef calls the definiton string parser and then just steps back in the
|
|
vGroup hierarchy and stays there.
|
|
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap29}
|
|
$\langle$nxddefopen {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ NXstatus NXDopendef(NXhandle hfil, NXdict dict, char *pDef)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ NXdict pDict;@\\
|
|
\mbox{}\verb@ ParDat pParse;@\\
|
|
\mbox{}\verb@ int iRet, i, iStat;@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ pDict = NXDIAssert(dict);@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ /* parse and act on definition string */@\\
|
|
\mbox{}\verb@ pParse.iMayCreate = 1;@\\
|
|
\mbox{}\verb@ pParse.pPtr = pDef;@\\
|
|
\mbox{}\verb@ pParse.iDepth = 0;@\\
|
|
\mbox{}\verb@ iRet = NXDIDefParse(hfil,pDict,&pParse);@\\
|
|
\mbox{}\verb@ if(iRet == NX_ERROR)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ /* unwind and throw up */@\\
|
|
\mbox{}\verb@ iRet = NXDIUnwind(hfil,pParse.iDepth);@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ /* try rewinding the hierarchy */@\\
|
|
\mbox{}\verb@ if(pParse.iTerminal == TERMSDS)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ iStat = NXDIUnwind(hfil,pParse.iDepth);@\\
|
|
\mbox{}\verb@ if(iStat != NX_OK)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ /* do not rewind on links */@\\
|
|
\mbox{}\verb@ return iRet;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
\subsubsection{NXDopenalias}
|
|
NXDOpenalias is just a wrapper around NXDopendef which retrieves a
|
|
definition string from the directory first.
|
|
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap30}
|
|
$\langle$nxdaliasopen {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ NXstatus NXDopenalias(NXhandle hfil, NXdict dict, char *pAlias)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ NXdict pDict;@\\
|
|
\mbox{}\verb@ int iRet;@\\
|
|
\mbox{}\verb@ char pDefinition[1024];@\\
|
|
\mbox{}\verb@ pDynString pReplaced = NULL;@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ pDict = NXDIAssert(dict);@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ /* get Definition String */@\\
|
|
\mbox{}\verb@ iRet = NXDget(pDict,pAlias,pDefinition,1023);@\\
|
|
\mbox{}\verb@ if(iRet != NX_OK)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ sprintf(pDefinition,"ERROR: alias %s not recognized",pAlias);@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData,pDefinition);@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ /* do the text replacement */@\\
|
|
\mbox{}\verb@ pReplaced = NXDItextreplace(dict,pDefinition);@\\
|
|
\mbox{}\verb@ if(!pReplaced)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* call NXDopendef */@\\
|
|
\mbox{}\verb@ iRet = NXDopendef(hfil,dict,GetCharArray(pReplaced));@\\
|
|
\mbox{}\verb@ DeleteDynString(pReplaced);@\\
|
|
\mbox{}\verb@ return iRet;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
\subsubsection{NXDputdef}
|
|
This routine puts a data item into a NeXus file using a definition string.
|
|
This naturally can work only, if there is an SDS at the end.
|
|
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap31}
|
|
$\langle$nxput {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ NXstatus NXDputdef(NXhandle hFil, NXdict dict, char *pDef, void *pData)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ NXdict pDict;@\\
|
|
\mbox{}\verb@ ParDat pParse;@\\
|
|
\mbox{}\verb@ int iRet, i, iStat;@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ pDict = NXDIAssert(dict);@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ /* parse and act on definition string */@\\
|
|
\mbox{}\verb@ pParse.iMayCreate = 1;@\\
|
|
\mbox{}\verb@ pParse.pPtr = pDef;@\\
|
|
\mbox{}\verb@ pParse.iDepth = 0;@\\
|
|
\mbox{}\verb@#ifdef DEFDEBUG@\\
|
|
\mbox{}\verb@ printf("Putting: %s\n",pDef);@\\
|
|
\mbox{}\verb@#endif@\\
|
|
\mbox{}\verb@ iRet = NXDIDefParse(hFil,pDict,&pParse);@\\
|
|
\mbox{}\verb@ if(iRet == NX_ERROR)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ NXDIUnwind(hFil,pParse.iDepth);@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ /* only SDS can be written */@\\
|
|
\mbox{}\verb@ if(pParse.iTerminal != TERMSDS)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData,@\\
|
|
\mbox{}\verb@ "ERROR: can only write to an SDS!");@\\
|
|
\mbox{}\verb@ iStat = NX_ERROR;@\\
|
|
\mbox{}\verb@ } @\\
|
|
\mbox{}\verb@ else @\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ /* the SDS should be open by now, write it */@\\
|
|
\mbox{}\verb@ iStat = NXputdata(hFil, pData);@\\
|
|
\mbox{}\verb@ iRet = NXclosedata(hFil);@\\
|
|
\mbox{}\verb@ } @\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* rewind the hierarchy */@\\
|
|
\mbox{}\verb@ iRet = NXDIUnwind(hFil,pParse.iDepth);@\\
|
|
\mbox{}\verb@ if(iRet != NX_OK)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ return iStat;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
\subsubsection{NXDputalias}
|
|
Just finds the definition string and calls NXputdef then.
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap32}
|
|
$\langle$nxdputalias {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ NXstatus NXDputalias(NXhandle hFil, NXdict dict, char *pAlias, void *pData)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ NXdict pDict;@\\
|
|
\mbox{}\verb@ int iRet;@\\
|
|
\mbox{}\verb@ char pDefinition[1024];@\\
|
|
\mbox{}\verb@ pDynString pReplaced = NULL;@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ pDict = NXDIAssert(dict);@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ /* get Definition String */@\\
|
|
\mbox{}\verb@ iRet = NXDget(pDict,pAlias,pDefinition,1023);@\\
|
|
\mbox{}\verb@ if(iRet != NX_OK)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ sprintf(pDefinition,"ERROR: alias %s not recognized",pAlias);@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData,pDefinition);@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ /* do text replacement */@\\
|
|
\mbox{}\verb@ pReplaced = NXDItextreplace(dict,pDefinition);@\\
|
|
\mbox{}\verb@ if(!pReplaced)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* call NXDputdef */@\\
|
|
\mbox{}\verb@ iRet = NXDputdef(hFil,dict,GetCharArray(pReplaced),pData);@\\
|
|
\mbox{}\verb@ DeleteDynString(pReplaced);@\\
|
|
\mbox{}\verb@ return iRet;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
\subsubsection{NXDgetdef}
|
|
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap33}
|
|
$\langle$nxget {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ NXstatus NXDgetdef(NXhandle hFil, NXdict dict, char *pDef, void *pData)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ NXdict pDict;@\\
|
|
\mbox{}\verb@ ParDat pParse;@\\
|
|
\mbox{}\verb@ int iRet, i, iStat;@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ pDict = NXDIAssert(dict);@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ /* parse and act on definition string */@\\
|
|
\mbox{}\verb@ pParse.iMayCreate = 0;@\\
|
|
\mbox{}\verb@ pParse.pPtr = pDef;@\\
|
|
\mbox{}\verb@ pParse.iDepth = 0;@\\
|
|
\mbox{}\verb@#ifdef DEFDEBUG@\\
|
|
\mbox{}\verb@ printf("Getting: %s\n",pDef);@\\
|
|
\mbox{}\verb@#endif@\\
|
|
\mbox{}\verb@ iRet = NXDIDefParse(hFil,pDict,&pParse);@\\
|
|
\mbox{}\verb@ if(iRet == NX_ERROR)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ /* unwind and throw up */@\\
|
|
\mbox{}\verb@ NXDIUnwind(hFil,pParse.iDepth);@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* only SDS can be written */@\\
|
|
\mbox{}\verb@ if(pParse.iTerminal != TERMSDS)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData,@\\
|
|
\mbox{}\verb@ "ERROR: can only write to an SDS!");@\\
|
|
\mbox{}\verb@ iStat = NX_ERROR;@\\
|
|
\mbox{}\verb@ } @\\
|
|
\mbox{}\verb@ else @\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ /* the SDS should be open by now, read it */@\\
|
|
\mbox{}\verb@ iStat = NXgetdata(hFil, pData);@\\
|
|
\mbox{}\verb@ iRet = NXclosedata(hFil);@\\
|
|
\mbox{}\verb@ } @\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* rewind the hierarchy */@\\
|
|
\mbox{}\verb@ iRet = NXDIUnwind(hFil,pParse.iDepth);@\\
|
|
\mbox{}\verb@ if(iRet != NX_OK)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ return iStat;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
\subsubsection{NXgetalias}
|
|
Just finds the definition string and calls NXgetdef then.
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap34}
|
|
$\langle$nxdgetalias {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ NXstatus NXDgetalias(NXhandle hFil, NXdict dict, char *pAlias, void *pData)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ NXdict pDict;@\\
|
|
\mbox{}\verb@ int iRet;@\\
|
|
\mbox{}\verb@ char pDefinition[1024];@\\
|
|
\mbox{}\verb@ pDynString pReplaced = NULL;@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ pDict = NXDIAssert(dict);@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ /* get Definition String */@\\
|
|
\mbox{}\verb@ iRet = NXDget(pDict,pAlias,pDefinition,1023);@\\
|
|
\mbox{}\verb@ if(iRet != NX_OK)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ sprintf(pDefinition,"ERROR: alias %s not recognized",pAlias);@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData,pDefinition);@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ /* do text replacement */@\\
|
|
\mbox{}\verb@ pReplaced = NXDItextreplace(dict,pDefinition);@\\
|
|
\mbox{}\verb@ if(!pReplaced)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ /* call NXDgetdef */@\\
|
|
\mbox{}\verb@ iRet = NXDgetdef(hFil,dict,GetCharArray(pReplaced),pData);@\\
|
|
\mbox{}\verb@ DeleteDynString(pReplaced);@\\
|
|
\mbox{}\verb@ return iRet;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
\subsubsection{NXDdeflink, NXDaliaslink}
|
|
The first alias/definition string must be a vGroup, the other can be a
|
|
vGroup or a SDS.
|
|
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap35}
|
|
$\langle$nxlink {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ NXstatus NXDdeflink(NXhandle hFil, NXdict dict, @\\
|
|
\mbox{}\verb@ char *pTarget, char *pVictim)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ NXdict pDict;@\\
|
|
\mbox{}\verb@ ParDat pParseT, pParseV;@\\
|
|
\mbox{}\verb@ int iRet, i, iStat;@\\
|
|
\mbox{}\verb@ NXlink sLink;@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ pDict = NXDIAssert(dict);@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@#ifdef DEFDEBUG@\\
|
|
\mbox{}\verb@ printf("Linking: %s\n",pVictim);@\\
|
|
\mbox{}\verb@ printf("To: %s\n", pTarget);@\\
|
|
\mbox{}\verb@#endif@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* parse Victim */@\\
|
|
\mbox{}\verb@ pParseV.iMayCreate = 0;@\\
|
|
\mbox{}\verb@ pParseV.pPtr = pVictim;@\\
|
|
\mbox{}\verb@ pParseV.iDepth = 0;@\\
|
|
\mbox{}\verb@ iRet = NXDIDefParse(hFil,pDict,&pParseV);@\\
|
|
\mbox{}\verb@ if(iRet == NX_ERROR)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ /* unwind and throw up */@\\
|
|
\mbox{}\verb@ NXDIUnwind(hFil,pParseV.iDepth);@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ /* get link data */@\\
|
|
\mbox{}\verb@ if(pParseV.iTerminal == TERMSDS)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ NXgetdataID(hFil,&sLink);@\\
|
|
\mbox{}\verb@ iRet = NXclosedata(hFil);@\\
|
|
\mbox{}\verb@ if(iRet != NX_OK)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ /* unwind and throw up */@\\
|
|
\mbox{}\verb@ NXDIUnwind(hFil,pParseV.iDepth);@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ else if(pParseV.iTerminal == TERMVG)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ NXgetgroupID(hFil,&sLink);@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ else@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ assert(0); /* serious programming error */@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ /* Unwind */@\\
|
|
\mbox{}\verb@ iRet = NXDIUnwind(hFil,pParseV.iDepth);@\\
|
|
\mbox{}\verb@ if(iRet != NX_OK)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* parse Target */@\\
|
|
\mbox{}\verb@ pParseT.iMayCreate = 1;@\\
|
|
\mbox{}\verb@ pParseT.pPtr = pTarget;@\\
|
|
\mbox{}\verb@ pParseT.iDepth = 0;@\\
|
|
\mbox{}\verb@ iRet = NXDIDefParse(hFil,pDict,&pParseT);@\\
|
|
\mbox{}\verb@ if(iRet == NX_ERROR)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ /* unwind and throw up */@\\
|
|
\mbox{}\verb@ NXDIUnwind(hFil,pParseT.iDepth);@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ /* check it being a vGroup! */@\\
|
|
\mbox{}\verb@ if(pParseT.iTerminal != TERMVG)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData,"ERROR: can link only into a vGroup");@\\
|
|
\mbox{}\verb@ NXDIUnwind(hFil,pParseT.iDepth);@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ /* link, finally */@\\
|
|
\mbox{}\verb@ iRet = NXmakelink(hFil,&sLink);@\\
|
|
\mbox{}\verb@ /* Unwind anyway */@\\
|
|
\mbox{}\verb@ iStat = NXDIUnwind(hFil,pParseT.iDepth);@\\
|
|
\mbox{}\verb@ if(iStat != NX_OK)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ return iStat;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@/*--------------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@ NXstatus NXDaliaslink(NXhandle hFil, NXdict dict, @\\
|
|
\mbox{}\verb@ char *pTarget, char *pVictim)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ char pTargetDef[1024], pVictimDef[1024];@\\
|
|
\mbox{}\verb@ int iRet;@\\
|
|
\mbox{}\verb@ NXdict pDict;@\\
|
|
\mbox{}\verb@ pDynString pRep1 = NULL, pRep2 = NULL;@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ pDict = NXDIAssert(dict);@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ /* get Target Definition String */@\\
|
|
\mbox{}\verb@ iRet = NXDget(pDict,pTarget,pTargetDef,1023);@\\
|
|
\mbox{}\verb@ if(iRet != NX_OK)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ sprintf(pTargetDef,"ERROR: alias %s not recognized",pTarget);@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData,pTargetDef);@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ } @\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* get Victim definition string */@\\
|
|
\mbox{}\verb@ iRet = NXDget(pDict,pVictim,pVictimDef,1023);@\\
|
|
\mbox{}\verb@ if(iRet != NX_OK)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ sprintf(pTargetDef,"ERROR: alias %s not recognized",pTarget);@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData,pTargetDef);@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* do replacements */@\\
|
|
\mbox{}\verb@ pRep1 = NXDItextreplace(dict,pTargetDef);@\\
|
|
\mbox{}\verb@ pRep2 = NXDItextreplace(dict,pVictimDef);@\\
|
|
\mbox{}\verb@ if( (!pRep1) || (!pRep2) )@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ if(pRep1)@\\
|
|
\mbox{}\verb@ DeleteDynString(pRep1);@\\
|
|
\mbox{}\verb@ if(pRep2)@\\
|
|
\mbox{}\verb@ DeleteDynString(pRep2);@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* call NXdeflin */@\\
|
|
\mbox{}\verb@ iRet = NXDdeflink(hFil,pDict,GetCharArray(pRep1),GetCharArray(pRep2));@\\
|
|
\mbox{}\verb@ DeleteDynString(pRep1);@\\
|
|
\mbox{}\verb@ DeleteDynString(pRep2);@\\
|
|
\mbox{}\verb@ return iRet;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
\subsection{Utility functions}
|
|
\subsubsection{NXUwriteglobals}
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap36}
|
|
$\langle$global {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@/*-------------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@ static void SNXFormatTime(char *pBuffer, int iBufLen)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ time_t iDate;@\\
|
|
\mbox{}\verb@ struct tm *psTime;@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* make time string */@\\
|
|
\mbox{}\verb@ iDate = time(NULL);@\\
|
|
\mbox{}\verb@ psTime = localtime(&iDate);@\\
|
|
\mbox{}\verb@ memset(pBuffer,0,iBufLen); @\\
|
|
\mbox{}\verb@ strftime(pBuffer,iBufLen,"%Y-%d-%m %H:%M:%S",psTime);@\\
|
|
\mbox{}\verb@ } @\\
|
|
\mbox{}\verb@/*--------------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@ NXstatus NXUwriteglobals(NXhandle pFile, @\\
|
|
\mbox{}\verb@ char *filename,@\\
|
|
\mbox{}\verb@ char *owner,@\\
|
|
\mbox{}\verb@ char *adress,@\\
|
|
\mbox{}\verb@ char *phone,@\\
|
|
\mbox{}\verb@ char *email,@\\
|
|
\mbox{}\verb@ char *fax,@\\
|
|
\mbox{}\verb@ char *instrument)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ char pBueffel[512];@\\
|
|
\mbox{}\verb@ int iStat;@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ /* store global attributes */@\\
|
|
\mbox{}\verb@ iStat = NXputattr(pFile,"file_name",filename, @\\
|
|
\mbox{}\verb@ strlen(filename)+1,DFNT_INT8);@\\
|
|
\mbox{}\verb@ if(iStat == NX_ERROR)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ /* write creation time */@\\
|
|
\mbox{}\verb@ SNXFormatTime(pBueffel,512);@\\
|
|
\mbox{}\verb@ iStat = NXputattr(pFile,"file_time",pBueffel,@\\
|
|
\mbox{}\verb@ strlen(pBueffel)+1,DFNT_INT8);@\\
|
|
\mbox{}\verb@ if(iStat == NX_ERROR)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* instrument name */@\\
|
|
\mbox{}\verb@ iStat = NXputattr(pFile,"instrument",instrument,@\\
|
|
\mbox{}\verb@ strlen(instrument)+1,DFNT_INT8);@\\
|
|
\mbox{}\verb@ if(iStat == NX_ERROR)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ return iStat;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* owner */@\\
|
|
\mbox{}\verb@ iStat = NXputattr(pFile,"owner",owner,@\\
|
|
\mbox{}\verb@ strlen(owner)+1,DFNT_INT8);@\\
|
|
\mbox{}\verb@ if(iStat == NX_ERROR)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ return iStat;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* Adress */@\\
|
|
\mbox{}\verb@ iStat = NXputattr(pFile,"owner_adress",adress,@\\
|
|
\mbox{}\verb@ strlen(adress)+1,DFNT_INT8);@\\
|
|
\mbox{}\verb@ if(iStat == NX_ERROR)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ return iStat;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* phone */@\\
|
|
\mbox{}\verb@ iStat = NXputattr(pFile,"owner_telephone_number",phone,@\\
|
|
\mbox{}\verb@ strlen(phone)+1,DFNT_INT8);@\\
|
|
\mbox{}\verb@ if(iStat == NX_ERROR)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ return iStat;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* fax */@\\
|
|
\mbox{}\verb@ iStat = NXputattr(pFile,"owner_fax_number",fax,@\\
|
|
\mbox{}\verb@ strlen(fax)+1,DFNT_INT8);@\\
|
|
\mbox{}\verb@ if(iStat == NX_ERROR)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ return iStat;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* email */@\\
|
|
\mbox{}\verb@ iStat = NXputattr(pFile,"owner_email",email,@\\
|
|
\mbox{}\verb@ strlen(email)+1,DFNT_INT8);@\\
|
|
\mbox{}\verb@ if(iStat == NX_ERROR)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ return iStat;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ return NX_OK;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
\subsubsection{NXUentergroup}
|
|
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap37}
|
|
$\langle$enterg {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ NXstatus NXUentergroup(NXhandle hFil, char *name, char *class)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ void (*ErrFunc)(void *pData, char *pErr); @\\
|
|
\mbox{}\verb@ int iRet;@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* ACTION, first install dummy error handler */@\\
|
|
\mbox{}\verb@ ErrFunc = NXIReportError;@\\
|
|
\mbox{}\verb@ NXMSetError(NXpData, DummyError);@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ /* try opening vGroup */@\\
|
|
\mbox{}\verb@ iRet = NXopengroup(hFil, name, class);@\\
|
|
\mbox{}\verb@ NXMSetError(NXpData,ErrFunc);@\\
|
|
\mbox{}\verb@ if(iRet == NX_OK)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ return NX_OK;@\\
|
|
\mbox{}\verb@ } @\\
|
|
\mbox{}\verb@ else@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ /* we need to create it */@\\
|
|
\mbox{}\verb@ iRet = NXmakegroup(hFil,name,class);@\\
|
|
\mbox{}\verb@ if(iRet != NX_OK)@\\
|
|
\mbox{}\verb@ { @\\
|
|
\mbox{}\verb@ /* a comment on this one has already been written! */@\\
|
|
\mbox{}\verb@ return iRet;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ iRet = NXopengroup(hFil,name,class);@\\
|
|
\mbox{}\verb@ if(iRet != NX_OK)@\\
|
|
\mbox{}\verb@ { @\\
|
|
\mbox{}\verb@ /* a comment on this one has already been written! */@\\
|
|
\mbox{}\verb@ return iRet;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ return NX_OK;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
\subsubsection{NXUenterdata}
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap38}
|
|
$\langle$enterd {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ NXstatus NXUenterdata(NXhandle hFil, char *label, int datatype,@\\
|
|
\mbox{}\verb@ int rank, int dim[], char *pUnits)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ void (*ErrFunc)(void *pData, char *pErr); @\\
|
|
\mbox{}\verb@ int iRet;@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* ACTION, first install dummy error handler */@\\
|
|
\mbox{}\verb@ ErrFunc = NXIReportError;@\\
|
|
\mbox{}\verb@ NXMSetError(NXpData, DummyError);@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ /* try opening SDS */@\\
|
|
\mbox{}\verb@ iRet = NXopendata(hFil, label);@\\
|
|
\mbox{}\verb@ NXMSetError(NXpData,ErrFunc);@\\
|
|
\mbox{}\verb@ if(iRet == NX_OK)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ return NX_OK;@\\
|
|
\mbox{}\verb@ } @\\
|
|
\mbox{}\verb@ else@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ /* we need to create it */@\\
|
|
\mbox{}\verb@ iRet = NXmakedata(hFil,label, datatype, rank,dim);@\\
|
|
\mbox{}\verb@ if(iRet != NX_OK)@\\
|
|
\mbox{}\verb@ { @\\
|
|
\mbox{}\verb@ /* a comment on this one has already been written! */@\\
|
|
\mbox{}\verb@ return iRet;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ iRet = NXopendata(hFil,label);@\\
|
|
\mbox{}\verb@ if(iRet != NX_OK)@\\
|
|
\mbox{}\verb@ { @\\
|
|
\mbox{}\verb@ /* a comment on this one has already been written! */@\\
|
|
\mbox{}\verb@ return iRet;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ iRet = NXputattr(hFil, "Units",pUnits,@\\
|
|
\mbox{}\verb@ strlen(pUnits) + 1,DFNT_INT8);@\\
|
|
\mbox{}\verb@ if(iRet != NX_OK)@\\
|
|
\mbox{}\verb@ { @\\
|
|
\mbox{}\verb@ /* a comment on this one has already been written! */@\\
|
|
\mbox{}\verb@ return iRet;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ return NX_OK;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
\subsubsection{NXUallocSDS}
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap39}
|
|
$\langle$allocs {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ NXstatus NXUallocSDS(NXhandle hFil, void **pData)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ int iDIM[MAX_VAR_DIMS];@\\
|
|
\mbox{}\verb@ int iRank,iType;@\\
|
|
\mbox{}\verb@ int iRet, i;@\\
|
|
\mbox{}\verb@ long lLength;@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* get info */@\\
|
|
\mbox{}\verb@ iRet = NXgetinfo(hFil,&iRank, iDIM, &iType);@\\
|
|
\mbox{}\verb@ if(iRet != NX_OK)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ return iRet;@\\
|
|
\mbox{}\verb@ } @\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* calculate Size */@\\
|
|
\mbox{}\verb@ lLength = iDIM[0];@\\
|
|
\mbox{}\verb@ for(i = 1; i < iRank; i++)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ lLength *= iDIM[i];@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ switch(iType)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ case DFNT_FLOAT32:@\\
|
|
\mbox{}\verb@ lLength *= sizeof(float32);@\\
|
|
\mbox{}\verb@ break;@\\
|
|
\mbox{}\verb@ case DFNT_FLOAT64:@\\
|
|
\mbox{}\verb@ lLength *= sizeof(float64);@\\
|
|
\mbox{}\verb@ break;@\\
|
|
\mbox{}\verb@ case DFNT_INT8:@\\
|
|
\mbox{}\verb@ lLength *= sizeof(int8);@\\
|
|
\mbox{}\verb@ break;@\\
|
|
\mbox{}\verb@ case DFNT_UINT8:@\\
|
|
\mbox{}\verb@ lLength *= sizeof(uint8);@\\
|
|
\mbox{}\verb@ break;@\\
|
|
\mbox{}\verb@ case DFNT_INT16:@\\
|
|
\mbox{}\verb@ lLength *= sizeof(int16);@\\
|
|
\mbox{}\verb@ break;@\\
|
|
\mbox{}\verb@ case DFNT_UINT16:@\\
|
|
\mbox{}\verb@ lLength *= sizeof(uint16);@\\
|
|
\mbox{}\verb@ break;@\\
|
|
\mbox{}\verb@ case DFNT_INT32:@\\
|
|
\mbox{}\verb@ lLength *= sizeof(int32);@\\
|
|
\mbox{}\verb@ break;@\\
|
|
\mbox{}\verb@ case DFNT_UINT32:@\\
|
|
\mbox{}\verb@ lLength *= sizeof(uint32);@\\
|
|
\mbox{}\verb@ break;@\\
|
|
\mbox{}\verb@ default:@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData,"ERROR: Internal: number type not recoginized");@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* time to malloc */@\\
|
|
\mbox{}\verb@ *pData = NULL;@\\
|
|
\mbox{}\verb@ *pData = malloc(lLength);@\\
|
|
\mbox{}\verb@ if(*pData == NULL)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData,"ERROR: memory exhausted in NXUallocSDS");@\\
|
|
\mbox{}\verb@ return NX_ERROR;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ return NX_OK;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap40}
|
|
$\langle$free {\footnotesize ?}$\rangle\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ NXstatus NXUfreeSDS(void **pData)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ free(*pData);@\\
|
|
\mbox{}\verb@ *pData = NULL;@\\
|
|
\mbox{}\verb@ return NX_OK;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-1ex}
|
|
\footnotesize\addtolength{\baselineskip}{-1ex}
|
|
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
|
\item Macro referenced in scrap ?.
|
|
\end{list}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
\section{Files}
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap41}
|
|
\verb@"nxdict.h"@ {\footnotesize ? }$\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@/*---------------------------------------------------------------------------@\\
|
|
\mbox{}\verb@ NXDICT API header file@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ copyleft: Mark Koennecke, March 1997 at LNS,PSI, Switzerland@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ No warranties of any kind taken.@\\
|
|
\mbox{}\verb@----------------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@#ifndef NXDICTAPI@\\
|
|
\mbox{}\verb@#define NXDICTAPI@\\
|
|
\mbox{}\verb@#include "napi.h" /* make sure, napi is included */@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@/*-------------------- NXDict data types & defines ----------------------*/@\\
|
|
\mbox{}\verb@@$\langle$tata {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@#define NXquiet 0@\\
|
|
\mbox{}\verb@#define NXalot 1@\\
|
|
\mbox{}\verb@/*-------------------- Dictionary Maintainance ----------------------------*/@\\
|
|
\mbox{}\verb@@$\langle$dicman {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@/*----------------- Dictionary added data transfer -----------------------*/ @\\
|
|
\mbox{}\verb@@$\langle$dicdata {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@/*-------------------- Utility Functions --------------------------------*/@\\
|
|
\mbox{}\verb@@$\langle$dicutil {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@#endif@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-2ex}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap42}
|
|
\verb@"nxdict.c"@ {\footnotesize ? }$\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@/*---------------------------------------------------------------------------@\\
|
|
\mbox{}\verb@ Nexus Dictionary API implementation file.@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ For documentation see the nxdict.tex file which comes with this @\\
|
|
\mbox{}\verb@ distribution.@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ copyleft: Mark Koennecke@\\
|
|
\mbox{}\verb@ Labor fuer Neutronenstreuung@\\
|
|
\mbox{}\verb@ Paul Scherrer Institut@\\
|
|
\mbox{}\verb@ CH-5232 Villigen-PSI@\\
|
|
\mbox{}\verb@ Switzerland@\\
|
|
\mbox{}\verb@ Mark.Koennecke@{\tt @}\verb@psi.ch@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ No warranties of any kind, whether explicit or implied, taken.@\\
|
|
\mbox{}\verb@ Distributed under the GNU copyleft license as documented elsewhere.@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ August, 1997@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ Version: 1.0@\\
|
|
\mbox{}\verb@-----------------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@#include <stdlib.h>@\\
|
|
\mbox{}\verb@#include <stdio.h>@\\
|
|
\mbox{}\verb@#include <assert.h>@\\
|
|
\mbox{}\verb@#include <string.h>@\\
|
|
\mbox{}\verb@#include <time.h>@\\
|
|
\mbox{}\verb@#include <mfhdf.h>@\\
|
|
\mbox{}\verb@#include "lld.h"@\\
|
|
\mbox{}\verb@#include "napi.h"@\\
|
|
\mbox{}\verb@#include "stringdict.h"@\\
|
|
\mbox{}\verb@#include "dynstring.h"@\\
|
|
\mbox{}\verb@#include "nxdict.h"@\\
|
|
\mbox{}\verb@/*------------------ The magic number used for pointer checking */@\\
|
|
\mbox{}\verb@#define NXDMAGIC 260558@\\
|
|
\mbox{}\verb@/*--------------------------------------------------------------------------@\\
|
|
\mbox{}\verb@ Things defined in napi.c for error reporting @\\
|
|
\mbox{}\verb@---------------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@ extern void *NXpData;@\\
|
|
\mbox{}\verb@ extern void (*NXIReportError)(void *pData, char *pBuffer); @\\
|
|
\mbox{}\verb@/*--------------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@#define DEFDEBUG 1@\\
|
|
\mbox{}\verb@/* define DEFDEBUG when you wish to print your definition strings before@\\
|
|
\mbox{}\verb@ action. This can help a lot to resolve mysteries when working with@\\
|
|
\mbox{}\verb@ dictionaries.@\\
|
|
\mbox{}\verb@*/@\\
|
|
\mbox{}\verb@/*-------------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@@$\langle$dicdat {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@/*-------------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@ static char *NXDIReadFile(FILE *fd)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ char *pNew = NULL;@\\
|
|
\mbox{}\verb@ long lLength = 0;@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ assert(fd); @\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* determine length of file */@\\
|
|
\mbox{}\verb@ fseek(fd,0L,SEEK_END);@\\
|
|
\mbox{}\verb@ lLength = ftell(fd);@\\
|
|
\mbox{}\verb@ if(lLength <= 0)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ return NULL;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ fseek(fd,0L,SEEK_SET);@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* allocate buffer */@\\
|
|
\mbox{}\verb@ lLength += 3;@\\
|
|
\mbox{}\verb@ pNew = (char *)malloc(lLength*sizeof(char));@\\
|
|
\mbox{}\verb@ if(!pNew)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ return NULL;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ memset(pNew,0,lLength); /* this ensures a 0 at the end */@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* read file */@\\
|
|
\mbox{}\verb@ fread(pNew,sizeof(char),lLength-3,fd);@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ /* check for existence of the NXDICT string in the file */@\\
|
|
\mbox{}\verb@ if(strncmp(pNew,"##NXDICT-1.0",12) != 0 )@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData,"ERROR: This is NO NXdict file");@\\
|
|
\mbox{}\verb@ free(pNew);@\\
|
|
\mbox{}\verb@ return NULL;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ return pNew;@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@/*--------------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@@$\langle$ftoken {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@/*------------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@@$\langle$fparse {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@/*--------------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@ NXstatus NXDinitfromfile(char *filename, NXdict *pData)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ NXdict pNew = NULL;@\\
|
|
\mbox{}\verb@ FILE *fd = NULL;@\\
|
|
\mbox{}\verb@ char *pBuffer = NULL;@\\
|
|
\mbox{}\verb@ char pError[512];@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@@$\langle$iniini {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@@$\langle$inicheck {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@@$\langle$inifil {\footnotesize ?}$\rangle$\verb@ @\\
|
|
\mbox{}\verb@@$\langle$iniparse {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ if(iVerbosity == NXalot)@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ NXIReportError(NXpData, "NXDinitfrom: performed successfully");@\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@ free(pBuffer);@\\
|
|
\mbox{}\verb@ *pData = pNew;@\\
|
|
\mbox{}\verb@ return NX_OK;@\\
|
|
\mbox{}\verb@ } @\\
|
|
\mbox{}\verb@/*--------------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@@$\langle$dassert {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@/*-------------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@@$\langle$dclose {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@/*------------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@@$\langle$dmaintain {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@/*-----------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@@$\langle$textrep {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@/*------------------- The Defintion String Parser -----------------------*/@\\
|
|
\mbox{}\verb@/*------- Data structures */@\\
|
|
\mbox{}\verb@@$\langle$tokdat {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@@$\langle$padef {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@@$\langle$dummyerr {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@@$\langle$attitem {\footnotesize ?}$\rangle$\verb@ @\\
|
|
\mbox{}\verb@/*------------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@@$\langle$deftok {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@/*------------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@@$\langle$defpath {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@/*------------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@@$\langle$parseatt {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@/*------------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@@$\langle$parsedim {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@/*------------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@@$\langle$parsetype {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@/*-------------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@@$\langle$nxpasds {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@/*------------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@@$\langle$parselink {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@/*------------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@@$\langle$defpar {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@/*----------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@@$\langle$unwind {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@/*-------------------- The Data Transfer Functions ----------------------*/@\\
|
|
\mbox{}\verb@@$\langle$nxddefopen {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@/*------------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@@$\langle$nxdaliasopen {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@/*------------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@@$\langle$nxput {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@/*------------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@@$\langle$nxdputalias {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@/*------------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@@$\langle$nxget {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@/*------------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@@$\langle$nxdgetalias {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@/*------------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@@$\langle$nxlink {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@/*-----------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@@$\langle$global {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@/*-----------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@@$\langle$enterg {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@/*-----------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@@$\langle$enterd {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@/*-----------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@@$\langle$allocs {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@/*----------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@@$\langle$free {\footnotesize ?}$\rangle$\verb@@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-2ex}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap43}
|
|
\verb@"dict.c"@ {\footnotesize ? }$\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@/*--------------------------------------------------------------------------@\\
|
|
\mbox{}\verb@ D I C T @\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ This file exercises some of the NXDICT functionality for test purposes.@\\
|
|
\mbox{}\verb@ It can also serve as an example for the usage of the API.@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ Mark Koennecke, August 1997@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ Upgraded to support file idetification and text replacement@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ Mark Koennecke, April 1998@\\
|
|
\mbox{}\verb@----------------------------------------------------------------------------*/@\\
|
|
\mbox{}\verb@#include <stdlib.h>@\\
|
|
\mbox{}\verb@#include <stdio.h>@\\
|
|
\mbox{}\verb@#include <assert.h>@\\
|
|
\mbox{}\verb@#include <mfhdf.h>@\\
|
|
\mbox{}\verb@#include "dynstring.h"@\\
|
|
\mbox{}\verb@#include "napi.h"@\\
|
|
\mbox{}\verb@#include "nxdict.h"@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ int main(int argc, char *argv[])@\\
|
|
\mbox{}\verb@ {@\\
|
|
\mbox{}\verb@ NXdict pDict = NULL;@\\
|
|
\mbox{}\verb@ NXhandle hfil;@\\
|
|
\mbox{}\verb@ void *pData = NULL;@\\
|
|
\mbox{}\verb@ float fTina[3] = { 0.123, 0.234, 0.456};@\\
|
|
\mbox{}\verb@ float fTest[3], fDelta;@\\
|
|
\mbox{}\verb@ float fTust[20*20];@\\
|
|
\mbox{}\verb@ char pBuffer[132];@\\
|
|
\mbox{}\verb@ int i;@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* test nxdict */@\\
|
|
\mbox{}\verb@ NXDinitfromfile("test.dict",&pDict);@\\
|
|
\mbox{}\verb@ NXopen("test.hdf",NXACC_CREATE,&hfil);@\\
|
|
\mbox{}\verb@ NXDadd(pDict,"Gundula",@\\
|
|
\mbox{}\verb@ "/entry1,NXentry/SphereOmeter,NXinstrument/SDS");@\\
|
|
\mbox{}\verb@ NXDupdate(pDict,"Bea","/entry1,NXentry/SDS");@\\
|
|
\mbox{}\verb@ NXDget(pDict,"Bea",pBuffer,131);@\\
|
|
\mbox{}\verb@ printf("Bea = %s\n",pBuffer);@\\
|
|
\mbox{}\verb@ NXDget(pDict,"Linda",pBuffer,131);@\\
|
|
\mbox{}\verb@ NXDopendef(hfil,pDict,pBuffer);@\\
|
|
\mbox{}\verb@ NXDputalias(hfil,pDict,"Tina",fTina);@\\
|
|
\mbox{}\verb@ NXDputalias(hfil,pDict,"Gina",fTina);@\\
|
|
\mbox{}\verb@ NXDgetalias(hfil,pDict,"Tina",fTest);@\\
|
|
\mbox{}\verb@ NXDgetalias(hfil,pDict,"Gina",fTest);@\\
|
|
\mbox{}\verb@ NXDputalias(hfil,pDict,"Linda",fTust);@\\
|
|
\mbox{}\verb@ NXDaliaslink(hfil,pDict,"Eva","Linda");@\\
|
|
\mbox{}\verb@ NXDclose(pDict,"close.dict");@\\
|
|
\mbox{}\verb@ NXclose(&hfil);@\\
|
|
\mbox{}\verb@ printf("NXDICT seemed to have worked \n");@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ /* test Utility functions */@\\
|
|
\mbox{}\verb@ printf(" Proceeding to test of utility functions \n");@\\
|
|
\mbox{}\verb@ NXopen("test2.hdf",NXACC_CREATE,&hfil);@\\
|
|
\mbox{}\verb@ NXUwriteglobals(hfil,@\\
|
|
\mbox{}\verb@ "test2.hdf",@\\
|
|
\mbox{}\verb@ "Willibald Wuergehals",@\\
|
|
\mbox{}\verb@ "Rue des Martyrs, 26505 Timbuktu, Legoland ",@\\
|
|
\mbox{}\verb@ "+41-56-3102512",@\\
|
|
\mbox{}\verb@ "Nobody@{\tt @}\verb@nowhere.edu",@\\
|
|
\mbox{}\verb@ " 755-898767",@\\
|
|
\mbox{}\verb@ "Dingsbums");@\\
|
|
\mbox{}\verb@ NXUentergroup(hfil, "TestGroup", "NXtest");@\\
|
|
\mbox{}\verb@ NXclosegroup(hfil);@\\
|
|
\mbox{}\verb@ NXUentergroup(hfil, "TestGroup", "NXtest");@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ i = 120;@\\
|
|
\mbox{}\verb@ NXUenterdata(hfil,"TestData",DFNT_INT8, 1,&i,"Testis");@\\
|
|
\mbox{}\verb@ NXclosedata(hfil);@\\
|
|
\mbox{}\verb@ NXUenterdata(hfil,"TestData",DFNT_INT8, 1,&i,"Testis");@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ NXUallocSDS(hfil,&pData);@\\
|
|
\mbox{}\verb@ NXUfreeSDS(&pData);@\\
|
|
\mbox{}\verb@ NXclose(&hfil);@\\
|
|
\mbox{}\verb@ printf("All tests seem to have worked OK, %s %s\n",@\\
|
|
\mbox{}\verb@ "but the test is pathetic\n", @\\
|
|
\mbox{}\verb@ "Do not rely, in any circumstances, on this test alone");@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@ @\\
|
|
\mbox{}\verb@ }@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-2ex}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
\begin{flushleft} \small
|
|
\begin{minipage}{\linewidth} \label{scrap44}
|
|
\verb@"test.dict"@ {\footnotesize ? }$\equiv$
|
|
\vspace{-1ex}
|
|
\begin{list}{}{} \item
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@##NXDICT-1.0@\\
|
|
\mbox{}\verb@#----------------------------------------------------------------------------@\\
|
|
\mbox{}\verb@# A dictionary file for test purposes@\\
|
|
\mbox{}\verb@# Mark Koennecke, August 1997@\\
|
|
\mbox{}\verb@#----------------------------------------------------------------------------@\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@Linda = /entry1,NXentry/Wuerfelometer,NXinstrument/SDS Counts \@\\
|
|
\mbox{}\verb@ -type DFNT_INT32 -rank 2 -dim {20,20} -attr {Units,Wuerfel} \@\\
|
|
\mbox{}\verb@ -attr {axis,1}@\\
|
|
\mbox{}\verb@Eva = \@\\
|
|
\mbox{}\verb@ /entry1,NXentry/NXVGROUP@\\
|
|
\mbox{}\verb@Chloe = /entry1,NXentry/NXLINK Linda@\\
|
|
\mbox{}\verb@Bea =@\\
|
|
\mbox{}\verb@Tina = /entry1,NXentry/InvertedTOPSI,NXinstrument/SDS Tina \@\\
|
|
\mbox{}\verb@ -type DFNT_FLOAT32 -rank 1 -dim {3} -attr {Units,Fahrenheit} @\\
|
|
\mbox{}\verb@Reptil = Alligator,NXanimal/@\\
|
|
\mbox{}\verb@Gina = /entry1,NXentry/$(Reptil)SDS Tina \@\\
|
|
\mbox{}\verb@ -type DFNT_FLOAT32 -rank 1 -dim {3} -attr {Units,Fahrenheit} @\\
|
|
\mbox{}\verb@@\\
|
|
\mbox{}\verb@@$\diamond$
|
|
\end{list}
|
|
\vspace{-2ex}
|
|
\end{minipage}\\[4ex]
|
|
\end{flushleft}
|
|
\end{document}
|