The specific goals for this library are:
This document is divided into several sections. The next section gives an overview of the use of PDBLib and describes some programming practices which are necessary to the successful use of the library. It is followed by a section summarizing the C interface routines in PDBLib and a section giving a more formal and complete description of the C interface with information about normal and error return values, functionality, and rationale. Next are similar sections for the FORTRAN interface routines. Subsequent sections discuss PDBLib design philosophy, data structures, examples, and related documentation.
Since C doesnt have the needed type handling facilities, data structures must be described to PDBLib. Therefore, in addition to the basic I/O functions mentioned above, there is a function in PDBLib to be used when a C data structure or a FORTRAN common block must be described in a file.
Next, to give the user the most flexibility and efficiency regarding data conversions, PDBLib has a function which lets the user specify the binary data format of the file. In this way, a file can be targeted for a particular machine type. A common use for this might be when a powerful machine produces some data which is going to be reprocessed on a less powerful machine. The more powerful machine which writes the file might target the file for the less powerful one so that the conversions are done by the faster machine and not the slower one.
Finally, in some applications with structures, some members of a structure may be pointers, and the actual type to which a pointer points may be changed by a cast depending on some other members value. PDBLib supports the notion of a cast in that it can be told to ignore the type of a structure member and get the actual type from another member when it writes out the structure.
Because all of the information about files and their contents is contained in PDBLib structures and hash tables, the C API (Application Program Interface) has no inquiry functions. Users can extract information directly from the PDBfile structure and they can use the hash table lookup function, SC_def_lookup, to get access to the syment and defstr structures which describe variables and types, respectively.
The FORTRAN API to PDBLib has many of the same functions as the C API plus several more inquiry functions. These functions are necessary because FORTRAN cannot easily work with structures.
There are also routines to manage data attributes. An attribute table will be created for a PDB file the first time PD_def_attribute is called. The attribute table is kept in the PDBfile structure. Variables can be added to PDB files solely for their attribute values. Attributes can be given to entire variables or any part of them. This works because the attribute table is a separate hash table, like the symbol table, which associates names with attribute values. It also is used to manage the attributes themselves. It is not exactly clear why one should use these attributes. Most of the utility of attributes is already inherent in the structures or records which can by built with PDBLibs mechanism for defining derived types. Since the structure handling mechanisms are much more efficient, the reason for using attributes instead of structures should be very clear in the mind of the application programmer.
2.1
Compiling and Loading
To compile your C programs you must use #include <pdb.h>
in the source files which deal with the interpreter.
Each system has different naming conventions for its libraries and the reader is assumed to understand the appropriate naming conventions as well as knowing how to tell the linker to find the installed PACT libraries on each system that they use.
A brief discussion of the procedure for writing and reading indirectly referenced data follows. Although the discussion will use integers as an example, the ideas apply to all data types, primitive or derived.
Consider the following:
PDBLib uses this idea to be able to trace down arbitrary layers of indirection and obtain at each level the exact number of bytes to write out to a file. Of course, it also writes this information out so that the correct amount of space can be allocated by read operations as well as re-creating the correct connectivity of data structures.
Great care must be taken that pointers to fixed arrays not be imbedded in a chain of indirects unless their dimension specifications are included either in the I/O request or the definition of a structure. This point cannot be over-emphasized! The extra memory management layer may fail to detect a statically allocated array and return an erroneous byte count. This in turn will cause very obscure incorrect behavior (in the worst of circumstances) or a direct crash (the best outcome possible).
Also, note that subsets of dynamically allocated arrays cannot know how many bytes they contain and hence care should be taken in their use.
The example on the following page shows the different ways that statically allocated arrays, dynamically allocated arrays, statically allocated arrays of pointers, and dynamically allocated arrays of pointers are handled by PDBLib. Note: The function SC_strsave invokes the MAKE_N macro.
/* define variables in pairs - one to write and one to read into */
PDBfile *strm;
char *a, *b;
char c[10], d[10];
char *e[3], *f[3];
char **s, **t;
s =
MAKE_N(char *, 2);
/* fill
statically and dynamically allocated arrays */
strcpy(c, bar);
a =
SC_strsave(foo);
/* fill
statically and dynamically allocated arrays of pointers */
e[0] = SC_strsave(Foo);
e[1] = NULL;
e[2] = SC_strsave(Bar);
s[0] = SC_strsave(Hello);
s[1] = SC_strsave(world);
/* write these variables out
* note the dimension specifications and the type
*/
PD_write(strm, c(10), char, c);
PD_write(strm, a, char *, &a);
PD_write(strm, e(3), char *, e);
PD_write(strm, s, char **, &s);
/* read the file variables into fresh memory spaces
* note that the pointers to the pointers are passed in since the
* space is to be allocated and the value of the pointer here must
* be set to point to the new space
*/
PD_read(strm, c, d);
PD_read(strm, a, &b);
PD_read(strm, e, f);
PD_read(strm, s, &t);
2.3 PDB Syntax
This section contains discussion of some PDB concepts that are used elsewhere in this manual.
The following reserved characters are not allowed in variable names or defstr member names: ., (, ), [, and ]. They are reserved by the grammar of the data description language which follows some C and some FORTRAN conventions.
int *a, *b;
.
.
PD_write(strm, a, integer *, &a);
PD_read(strm, a, &b);
.
.When using pointers and dynamically allocated memory with PDBLib, use SC_alloc, SC_realloc, SC_strsave, MAKE, MAKE_N, REMAKE, or REMAKE_N to allocate memory. These functions and macros are documented in the SCORE Users Manual.
char **s, c;
/* fill s so that s[0] = Hello and s[1] = World */
.
.
PD_write(strm, s, char **, &s);
/* read the o in Hello */
PD_read(strm, s[0][4], &c);
/* read the o in World */
PD_read(strm, s[1][1], &c);
.
.
The high level PDBLib routines have a strict naming convention. All high level routines begin with PD_. Some routines have several related forms. These are referred to as families of functions. For example the PD_write family.
Most of these routines put an error message into a global variable called PD_err. The error messages include the name of the routine in which they are made thus eliminating the need for error codes which must be cross referenced with some other document. In this way application programs can check for error conditions themselves and decide in what manner to use the PDBLib error messages instead of having error messages printed by the system routines. Error messages are not stacked and must be processed by the application before any other PDBLib calls are made in order to avoid potential overwrites. See the descriptions of individual routines for more information about error handling and messages.
Programs written in C must include a header which makes certain declarations and definitions needed to use the library. Much in the same spirit as one includes stdio.h to use printf and others, include pdb.h as follows:
#include pdb.h
The file pdb.h #includes some other files which must either be in your directory space or pointed to in some manner which your compiler can recognize. The auxiliary #include files are schash.c, scstd.h, and score.h. These files are a part of the SCORE package which you must have to use PDBLib.
3.1 Some Guidance in Using the C API to PDBLib
PDBLib offers a great deal of flexibility to its users. In some cases the flexibility results in a bewildering assortment of function calls from which the application developer must choose. This section is intended to offer some guidance and enable developers to home in on the functions they need to use.3.1.1 Opening, Creating and Closing PDB Files
These are the most fundamental operations involving PDBLib. The function PD_open is used to either open an existing file or create a new one. PD_close is used to close a PDB file so that it can be recognized by PDBLib for future operations.
PDBLib allows applications to specify the binary format in which a newly created file will be written. PD_target does this work. It is not necessary to invoke PD_target before creating a new PDB file. In this case the binary format is that appropriate for the host system.
3.1.2 Writing Data to PDB Files
The following paragraphs describe a sequence of increasingly more elaborate output operations for PDB files. They are all compatible with one another so users can select the ones which match their needs best. The most straightforward operations are first.
Finally, PDBLib allows applications to reserve space on disk and then let subsequent writes fill in that space with values. This is handy in instances where an application knows a logical structure for a data set but needs to write it out in smaller pieces and not necessarily in the order implied by its logical structure. The functions which let applications reserve space are PD_defent and PD_defent_alt. Reserved spaces may be written to with any of the PD_write family of commands.
3.1.3 Reading Data from PDB Files
Since data in a file has a definite size and shape, the reading operations in PDBLib are somewhat simpler than the writing operation. The PD_read family of operations which is the counterpart of the PD_write family does all of the work in reading data from files.
3.1.4 Defining New Data Types
To aid application developers in using structured data PDBLib lets applications define new data types in a PDBfile. New data types may either be derived from other existing data types or they may be primitive (integer types, floating point types, or byte sequences). To define derived types applications should use PD_defstr or PD_defstr_alt. To define primitive types use PD_defix, PD_defloat, or PD_defncv.
Since PDBLib supports pointered data types, it is often the case that a pointer in a derived type may point to data of any kind. In C, casts are used to control this behavior. PDBLib permits a member of a struct which is of type char * specify the actual type of another pointered member. The function PD_cast is used to set up this behavior.
3.1.5 Defining Attributes
PDBLib supports a general mechanism for managing a class of data which is variously referred to as attributes or meta data. In a great many cases, the careful design of data structures obviates the need for this kind of data. Nevertheless, PDBLib supplies four functions to manage attributive data: PD_def_attribute, PD_rem_attribute, PD_get_attribute, PD_set_attribute.
3.1.6 Using Pointers
The ability to use pointers with PDBLib is very powerful. It is unfortunate perhaps that it can also be a little bit tricky. Application developers should be aware of a key issue when using pointers with PDBLib. In general, when you want to write a data tree, you want to faithfully reproduce the connectivity of the tree. That means that if many pointers refer to the same chunk of memory then the file will exhibit that same pattern. To do this, PDBLib remembers the pointers that it has written and if handed a pointer that it has already written it does NOT write that memory into the file again. It instead makes note of the connection to an already existing region of disk. These same considerations apply to reading with the requisite changes in sense.3.2 Terms
A few definitions must be given first to keep the following summary concise. Some of these will be elaborated upon in the next section.
PDBfile: for the purposes of a program this is a collection of all the relevant information about one of these data files (in the actual coding it is a C struct). See the section on
Data Structures for more information.
ASCII: a string
TRUE: a value of 1 (defined by PDBLib)
FALSE: a value of 0 (defined by PDBLib)
VOID: any C data type
LAST: a pointer to 0 (declared and defined by PDBLib)
ENTRY: for the purposes of a program this is a collection of all the relevant information about a variable written to a PDB file (in the actual coding it is a C struct). See the
discussion of syment in the section on Data Structures.
DEFSTR: for the purposes of a program this is a collection of all the relevant information about a data type in a PDB file (in the actual coding it is a C struct). See the discussion of defstr in the section on Data Structures.
3.3
Function Summary
These routines form the interface between C application programs and the PDBLib system.
PD_append(file, name, var)
Append the data pointed to by var to an existing entry under name in PDB file file.
PD_append_alt(file, name, var, nd, ind)
PD_append_as(file, name, intype, var)
PD_append_as_alt(file, name, intype, var, nd, ind)
PD_cast(file, type, memb, contr)
PD_cd(file, dirname)
PD_close(file)
PD_def_attribute(file, attr, type)
PD_defent(file, name, outtype)
PD_defent_alt(file, name, outtype, nd, ind)
PD_defix(file, name, bytespitem, align, flg)
Define an entry in the symbol table of the PDB file file. This function reserves space on
disk but writes no data. The data can be written with later PDBLib calls.
Define an entry in the symbol table of the PDB file file. This function reserves space on
disk but writes no data. The data can be written with later calls.
Define a primitive integral type (fixed point type) in the PDB file file.
PD_defloat(file, name, bytespitem, align, ordr, expb, mantb, sbs, sbe, sbm, hmb,
bias)
PD_defncv(file, name, bytespitem, align)
PD_defstr(file, name, mem1, ..., memn, LAST)
PD_defstr_alt(file, name, nmemb, memb)
PD_family(file, flag)
PD_flush(file)
PD_get_attribute(file, var, attr)
PD_get_max_file_size(file)
PD_get_mode(file)
PD_get_offset(file)
PD_ln(file, var, link)
PD_ls(file, path, type, num)
PD_make_image(name, type, data, dx, dy, bpp, xmin, xmax, ymin, ymax, zmin,
zmax)
PD_mkdir(file, dirname)
PD_open(filename, mode)
PD_put_image(file, image, index)
Define a new floating point type to the PDB file file.
Define a primitive type that will not undergo format conversion from platform to platform in the PDB file file.
Define a data structure called name with members mem1, ..., memn. LAST must terminate the list of members. This uses a C-like syntax for the member definition and name
is used in subsequent writes to refer to this type of data structure.
Define a data structure called name with members specified by memb.. This uses a C-
like syntax for the member definition and name is used in subsequent writes to refer to
this type of data structure.
If the file, file, has exceeded its size limit, open and return a new member of the file
family. If flag is TRUE close the old file.
Flush the file file. This function is used to write the descriptive information of a PDB
file to disk.
Get the value of the attr attribute of variable var in PDB file file. Variables only have
values for attributes which are explicitly given.
Get the current mode of PDB file file: 2 (append - a), 3 (open - r), 4 (create - w).
Get the current default offset for PDB file file.
Create a link to a variable in PDB file file.
Return a list of names of entries (variables and/or directories) in PDB file file that are of
a type type and that are in the directory and match the variable name pattern specified
by path.
Create and initialize a PD_image data structure.
Create a directory dirname in PDB file file.
Open a PDB file on disk named filename in one of three modes:
Write image image to file file with index index.
PD_put_mapping(file, mapping, index)
Write mapping mapping to file file with index index.
PD_put_set(file, set)
Write set set to file file.
PD_pwd(file)
PD_read(file, name, var)
PD_read_alt(file, name, var, ind)
PD_read_as(file, name, type, var)
PD_read_as_alt(file, name, type, var, ind)
PD_rel_image(image)
PD_rem_attribute(file, attr)
PD_reset_ptr_list(file)
PD_set_attribute(file, var, attr, val)
PD_set_max_file_size(file, v)
PD_set_offset(file, v)
PD_target(std, align)
PD_typedef(file, oname, tname)
PD_write(file, name, type, var)
PD_write_alt(file, name, type, var, nd, ind)
PD_write_as(file, name, intype, outtype, var)
PD_write_as_alt(file, name, intype, outtype, var, nd, ind)
Return the current directory in PDB file file.
Read a variable name from PDB file file and put it in var.
Read part of a variable name from PDB file file and put it in var.
Read a variable name from PDB file file and put it in var as data of type type.
Read part of a variable name from PDB file file and put it in var as data of type type.
Release the space associated with a PD_image data structure.
Remove an attribute named attr from the attribute table in PDB file file. All attribute
values are removed simultaneously with the attribute.
Free the list of pointers which the PDB file file knows about. This includes both pointers in memory acquired during write operations and pointers in the file acquired during read operations.
Set the value of an attribute attr of the var in PDB file file to val. Variables can be added
to PDB files solely for their attributes; that is, var need not be a variable in file.
Set the default offset for PDB file file.
Set up the next PDB file as if written by a machine of type defined by the given
data_standard and data_alignment information. This function must be called before
the PD_open call which creates the file.
Define an alias for an existing type in the specified file.
Write the data pointed to by var under name and with type to PDB file file.
Write the data pointed to by var under name and with type to PDB file file. In this alternate to PD_write dimension information is provided in arguments nd and ind.
Write the data pointed to by var under name and with intype to PDB file file as data of
outtype.
Write the data pointed to by var under name and with intype to PDB file file as data of
outtype. In this alternate to PD_write_as dimension information is provided in arguments nd and ind.
4.1 PD_APPEND
int
PD_append(PDBfile *file
char *name,
void *vr)
Append data to an entry in the specified file. The type is assumed to be the same as for the original entry. The dimensions of the appended data are specified in name. They must match the original entry except for the most slowly varying one. The specification of the most slowly varying dimension must be one of the following:
The shape or dimensional information of the entry is a part of the name string. In this respect PD_append behaves just like PD_write.
Input to this function is: file, a pointer to a PDBfile, name, an ASCII string containing the name of the variable and any dimensional information, and vr, a pointer to the data to be appended.
int
PD_append(PDBfile *file
char *name,
void *vr)
#include pdb.h
PDBfile *file;
float *fv;
.
.
.
if (
PD_append(file, x(20), fv)) == FALSE)
printf(%s, PD_err);
.
.
.
Compare this with the example of PD_write.
intPD_append_alt(PDBfile *file
char *name,
void *vr,
int nd,
long *ind)Append data to an entry in the specified file. The type is assumed to be the same as for the original entry. The dimensions of the appended data are specified in the ind array. They must match the original entry except for the most slowly varying one. The specification of the most slowly varying dimension must be one of the following;
Input to this function is: file, a pointer to a PDBfile, name, an ASCII string containing the name of the variable; vr, a pointer to the data to be appended; nd, an integer number of dimensions; and ind, an array of longs with triples (start, stop, step) defining dimension information.
int
PD_append_alt(PDBfile *file
char *name,
void *vr,
int nd,
long *ind)
#include pdb.h
PDBfile *file;
float *fv;
long ind[3]
.
.
.
ind[0] = 0L;
ind[1] = 20L;
ind[2] = 1L;
if (
PD_append_alt(file, x, fv, 1, ind)) == FALSE)
printf(%s, PD_err);
.
.
.
Compare this with the example of PD_write_alt.
intPD_append_as(PDBfile *file
char *name,
char *intype,
void *vr)Append data to an entry in the specified file. The output type is assumed to be the same as for the original entry. The dimensions of the appended data are specified in the name. They must match the original entry except for the most slowly varying one. The specification of the most slowly varying dimension must be one of the following;
The shape or dimensional information of the entry is a part of the name string. In this respect PD_append_as behaves just like PD_write_as.
Input to this function is: file, a pointer to a PDBfile, name, an ASCII string containing the name of the variable and any dimensional information, intype, an ASCII string specifying the type of the data to which vr points; and vr, a pointer to the data to be appended.
int
PD_append_as(PDBfile *file
char *name,
char *intype,
void *vr)
#include pdb.h
PDBfile *file;
double *dv;
.
.
.
if (
PD_append_as(file, x(20), float, dv)) == FALSE)
printf(%s, PD_err);
.
.
.
Compare this with the example of PD_write_as.
int PD_append_as_alt(PDBfile *file
char *name,
char *intype,
void *vr,
int nd,
long *ind)Append data to an entry in the specified file. The output type is assumed to be the same as for the original entry. The dimensions of the appended data are specified in the ind array. They must match the original entry except for the most slowly varying one. The specification of the most slowly varying dimension must be one of the following;
Input to this function is: file, a pointer to a PDBfile, name, an ASCII string containing the name of the variable; intype, an ASCII string specifying the type of data to which vr points; vr, a pointer to the data to be appended; nd, an integer number of dimensions; and ind, an array of longs with triples (start, stop, step) defining dimension information.
int PD_append_as_alt(PDBfile *file
char *name,
char *intype,
void *vr,
int nd,
long *ind)
#include pdb.h
PDBfile *file;
float *fv;
long ind[3]
.
.
.
ind[0] = 0L;
ind[1] = 20L;
ind[2] = 1L;
if (
PD_append_as_alt(file, x, double, fv, 1, ind)) == FALSE)
printf(%s, PD_err);
.
.
.
Compare this with the example of PD_write_as_alt.
intPD_cast(PDBfile *file,
char *type,
char *memb,
char *contr)Dynamically change the type of a structure member. PDBLib supports an extended data typing mechanism called a structure. A structure is a set of declarations of members. Each member is in turn a data type known to the system. In some applications, a structure member is used to point to data of a type which is specified by another member. In the C coding a cast is used to obtain a pointer to the desired data type.
PDBLib supports this same practice by allowing the programmer to override the type of a member as given in the structure definition (see PD_defstr) by supplying the name of a member, whose type must be char *, which will contain an ASCII string specifying the actual type of the data to which the first member points.
The arguments to PD_cast are: file, a pointer to a PDBfile; type, an ASCII string containing the name of the data structure type in the PDB file; memb, an ASCII string containing the name of the member whose type is to be overridden; and contr, an ASCII string containing the name of the member (whose type must be char *) which will provide the actual type for memb.
The return value is a TRUE if the cast is successful; otherwise, FALSE is returned and the ASCII string PD_err contains any error message that was generated.
char *type,
#include pdb.h
PDBfile *file;
struct sample
{char *type;
int *a;};
.
.
.
PD_defstr(file, sample, char *type, int *a, LAST);
PD_cast(file, sample, a, type);
.
.
.
4.6 PD_CD
int
PD_cd(PDBfile *file,
char *dirname)
Change the current directory in the specified PDB file.
PDBLib supports an optional hierarchical directory structure inside PDB files. A directory or a variable in a directory may be specified by either a relative path or an absolute path. Slashes separate nodes in a path name. Absolute paths begin with a slash. Nodes consisting of two periods, .., refer to the next higher level directory.
The arguments to PD_cd are: file, a pointer to a PDBfile; and dirname, an ASCII string containing the path name of the directory to change to.
If dirname is NULL or an empty string or a slash, it refers to the top level or root directory.
The return value is a TRUE if successful; otherwise, FALSE is returned and the ASCII string PD_err contains any error message that was generated.
char *dirname)
#include pdb.h
PDBfile *file;
.
.
.
if (
PD_cd(file, /animals/mammals) == FALSE)
printf(%s, PD_err);
.
.
.
if (
PD_cd(file, ../reptiles) == FALSE)
printf(%s, PD_err);
.
.
.
4.7 PD_CLOSE
int
PD_close(PDBfile *file)
Close a PDB file. After all data is written to the PDB file, the structure chart and symbol table must be written out to the file and their disk addresses recorded in the file header. Without these operations the file cannot be read back in by PDBLib and all data is lost. All open PDB files must be PD_closed before exiting the program.
A pointer, file, to the PDBfile associated with the PDB file must be passed to PD_close.
The function returns TRUE if the PDB file is correctly written and closed; otherwise, FALSE is returned and the ASCII string PD_err contains any error message that was generated.
#include pdb.h
PDBfile *file;
.
.
.
if (
PD_close(file) == FALSE)
printf(%s, PD_err);
.
.
.
4.8 PD_DEF_ATTRIBUTE
int
PD_def_attribute(PDBfile *file,
char *attr,
char *type)
Define an attribute to the given PDB file. The model of an attribute in PDBLib is an entity that has a name and type. The two supported operations on attributes are to create them and to remove them. An entity in a PDB file can be assigned an attribute value simply by making a call which specifies the entity name, the attribute name, and the attribute value (which is determined by the type). The only association between an entry in a PDB file and any attribute is made by the name in the attribute table and the entry in the symbol table. In particular, this mechanism allows the application developer to define and use entities in a PDB file solely in terms of attributes.
The arguments to this function are: file, a pointer to a PDBfile; name, an ASCII string containing the name of the attribute being defined; and type, an ASCII string containing the name of the data type in the PDB file.
int
PD_def_attribute(PDBfile *file,
char *attr,
char *type)
#include pdb.h
PDBfile *file;
.
.
.
if (
PD_def_attribute(file, date, char *) == FALSE)
printf(%s, PD_err);
.
.
.
4.9 PD_DEFENT
syment *
PD_defent(PDBfile *file,
char *name,
char *outtype)
Define an entry in the symbol table of the PDB file specified by file. This function reserves space on disk but writes no data. The data can be written with later calls to PD_write, PD_write_alt, PD_write_as, or PD_write_as_alt.
The rationale for this function is to block out space in a PDB file corresponding to some logical layout of a piece of data. The data may not exist at the time the space is reserved or for some reason it may be desirable to write out the data in pieces. In any case if the type and shape of a variable is known at some point, an entry may be made in the PDB file without writing any data. The space may filled with other PDBLib calls at some later time.
The shape or dimensional information of the entry is a part of the name string. In this respect PD_defent behaves just like PD_write.
Input to this function is: file, a pointer to a PDBfile, name, an ASCII string containing the name of the variable and any dimensional information, and outtype, an ASCII string specifying the type of data in the file.
char *name,
#include pdb.h
PDBfile *file;
syment *ep;
.
.
.
if ((ep =
PD_defent(file, x(20), float)) == NULL)
printf(%s, PD_err);
.
.
.
Compare this with the example of PD_write.
4.10 PD_DEFENT_ALT
syment *
PD_defent_alt(PDBfile *file,
char *name,
char *outtype,
int nd,
long *ind)
Define an entry in the symbol table of the PDB file specified by file. This function reserves space on disk but writes no data. The data can be written with later calls to PD_write, PD_write_alt, PD_write_as, or PD_write_as_alt.
This is an alternate form of PD_defent. The difference is that the dimension information is supplied via the nd and ind arguments instead of being a part of the name string. In this respect it behaves as PD_write_alt does.
The rationale for this function is to block out space in a PDB file corresponding to some logical layout of a piece of data. The data may not exist at the time the space is reserved or for some reason it may be desirable to write out the data in pieces. In any case if the type and shape of a variable is known at some point, an entry may be made in the PDB file without writing any data. The space may filled with other PDBLib calls at some later time.
Input to this function is: file, a pointer to a PDBfile, name, an ASCII string containing the name of the variable only, outtype, an ASCII string specifying the type of data in the file; nd, an integer specifying the number of dimensions; and ind, an array of long integers containing the minimum and maximum values of the index for each dimension pairwise.
char *name,
#include pdb.h
PDBfile *file;
syment *ep;
long ind[4];
.
.
.
ind[0] = 0L;
ind[1] = 19L;
ind[2] = -2L;
ind[3] = 2L;
if ((ep =
PD_defent_alt(file, x, float, 2, ind)) == NULL)
printf(%s, PD_err);
.
.
.
Compare this with the example of PD_write_alt and note the absence of a two dimensional array in this call.
4.11 PD_DEFIX
defstr *
PD_defix(PDBfile *file,
char *name,
long bytespitem,
int align,
int flg)
Define a primitive integral type (fixed point type) in the PDB file specified by file.
Input to PD_defix is: file, a pointer to a PDBfile; name, an ASCII string containing the name of the new data type; bytespitem, the number of bytes required for 1 item of the new type; align, the byte alignment for the type; and flg, a flag indicating whether the byte ordering of the type is normal or reverse ordered.
Compare this information with that found in the discussion of data conversion later in this manual.
defstr *
PD_defix(PDBfile *file,
char *name,
long bytespitem,
int align,
int flg) #include pdb.h
PDBfile *file;
defstr *ptr;
.
.
.
ptr =
PD_defix(file, int40, 5, 1, NORMAL_ORDER);
.
.
.
4.12 PD_DEFLOAT
defstr *
PD_defloat(PDBfile *file,
char *name,
long bytespitem,
int align,
int *ordr,
long expb,
long mantb,
long sbs,
long sbe,
long sbm,
long hmb,
long bias)
Define a new floating point type to the PDB file specified by file.
Input to PD_defloat is: file, a pointer to a PDBfile; name, an ASCII string containing the name of the variable in the PDB file; bytespitem, the number of bytes required for an item of the new type; align, the byte alignment for this type; ordr, an array of bytespitem integers specifying the byte order; expb, the number of exponent bits; mantb, the number of mantissa bits; sbs, the position of the sign bit; sbe, the starting bit of the exponent; sbm, the starting bit of the mantissa; hmb, the value of the high order mantissa bit; and bias, the bias of the exponent.
Compare this information with that found in the discussion of data conversion later in this manual.
defstr *
PD_defloat(PDBfile *file,
char *name,
long bytespitem,
int align,
int *ordr,
long expb,
long mantb,
long sbs,
long sbe,
long sbm,
long hmb,
long bias)
#include pdb.h
int ord_int24[] = {1, 3, 2};
PDBfile *file;
defstr *ptr;
.
.
.
ptr =
PD_defloat(file, fp24, 3, 1, ord_int24,
7L, 16L, 0L, 1L, 8L, 0L, 0x3F)
.
.
.
4.13 PD_DEFNCV
defstr *
PD_defncv(PDBfile *file,
char *name,
long bytespitem,
int align)
Define a primitive type that will not undergo format conversion from platform to platform in the PDB file specified by file. Certain data types commonly defined in C programs are used as flags or character holders. With such data types the actual bit pattern contains the meaningful information. This information would be lost under a data conversion operation. This function provides users with a means to define primitive types which will not be converted under any circumstances and therefore preserve the meaningful bit patterns which constitute the intended data.
Input to PD_defncv is: file, a pointer to a PDBfile; name, an ASCII string containing the name of the new data type; bytespitem, the number of bytes required for 1 item of the new type; and align, the byte alignment for the type.
Compare this information with that found in the discussion of data conversion later in this manual.
defstr *PD_defncv(PDBfile *file,
char *name,
long bytespitem,
int align) #include pdb.h
PDBfile *file;
defstr *ptr;
.
.
.
/* define a type like the FORTRAN character*8 */
ptr =
PD_defncv(file, char_8, 8, 1);
.
.
.
4.14 PD_DEFSTR
defstr *
PD_defstr(PDBfile *file,
char *name,
char *mem1, ..., memn,
int *LAST)
Define a data structure for a PDB file. As a matter of programming efficiency and clarity it is useful to be able to refer to more complex structural units than the primitive types: short integers, integers, long integers, floating point numbers, double precision floating point numbers, and characters. Arrays do this in a very simple-minded way. Many modern languages support extended types or structures which allow the programmer to group diverse types of data together in a very sophisticated way.
PDBLib supports an extended data typing mechanism called a structure. A structure is a set of declarations of members. Each member is in turn a data type known to the system. Much of the style and usage of structures comes from the C struct. Because of the memory management features upon which PDBLib now depends, even members whose types are pointers are allowed. The only restrictions on member types are that they not be function pointers and that they be expressible without parentheses. Again any member which is a pointer must have its memory allocated by a SCORE memory management function or macro. See the Memory Management section near the beginning of this manual.
PD_defstr defines structures to the PDB system so that they can be read and written as a whole in a single statement. The members of the structure are processed and an entry in the structure chart is made. Then subsequent references to the new structure type are processed using information from the structure chart. The syntax by which members of a structure are specified is like that for C structs. The formal definition is given below ([ ] enclose optional elements). Self-referential structures are allowed providing the reference is through pointers (like C). The actual type name is used in the reference since PDBLib checks that all member types are already known or are the type being defined.
The return value is a pointer to the entry made in the structure chart if the call is successful; otherwise, NULL is returned and the ASCII string PD_err contains any error message that was generated.
#include pdb.h
PDBfile *file;
defstr *ptr;
struct sample
{float x[20];
float y[20];
int number;};
.
.
.
ptr =
PD_defstr(file, sample, float x(20), float y(20),
int number, LAST);
.
.
.
defstr *PD_defstr_alt(PDBfile *file,
char *name,
PDBLib supports an extended data typing mechanism called a structure. A structure is a set of declarations of members. Each member is in turn a data type known to the system. Much of the style and usage of structures comes from the C struct. Because of the memory management features upon which PDBLib now depends, even members whose types are pointers are allowed. The only restrictions on member types are that they not be function pointers and that they be expressible without parentheses. Again any member which is a pointer must have its memory allocated by a SCORE memory management function or macro. See the Memory Management section near the beginning of this manual.
PD_defstr defines structures to the PDB system so that they can be read and written as a whole in a single statement. The members of the structure are processed and an entry in the structure chart is made. Then subsequent references to the new structure type are processed using information from the structure chart. The syntax by which members of a structure are specified is like that for C structs. The formal definition is given below ([ ] enclose optional elements). Self-referential structures are allowed providing the reference is through pointers (like C). The actual type name is used in the reference since PDBLib checks that all member types are already known or are the type being defined.
The return value is a pointer to the entry made in the structure chart if the call is successful; otherwise, NULL is returned and the ASCII string PD_err contains any error message that was generated.
char *name,
#include pdb.h
PDBfile *file;
defstr *ptr;
char **members;
struct sample
{float x[20];
float y[20];
int number;};
.
.
.
members = MAKE_N(char *, 3);
members[0] = SC_strsave(float x[20]);
members[1] = SC_strsave(float y[20]);
members[2] = SC_strsave(integer number);
ptr =
PD_defstr_alt(file, sample, 3, members);
SFREE(members[0]);
SFREE(members[1]);
SFREE(members[3]);
SFREE(members);
.
.
.
PDBfile *PD_family(PDBfile *file, int flag) This function checks to see whether the specified file has exceeded it size limit. If it has a new file is opened and returns. If not the given file pointer is returned. The flag is set to TRUE if you want PD_family to close the file it is given. Otherwise the application is responsible for closing the file
The arguments to this function are: file, the pointer to the PDBfile structure returned by a previous call to PD_open; and flag an integer value (either TRUE or FALSE).
This function returns a pointer to a PDBfile.
#include pdb.h
PDBfile *old, *new;
.
.
.
new = PD_family(old, FALSE);
if (new != old)
{PD_close(old);
.
.
.
old = new;};
.
.
.
4.17 PD_FLUSH
int
PD_flush(PDBfile *file)
This function writes out the information which describes the contents of the PDB file specified. Normally, PD_close calls this routine, but applications that want to protect themselves from system failures or other problems may chose to periodically use this function. After a successful return and until or unless more data is written to the file or space reserved for future writes, the PDB file is valid in the sense that if the application terminates unexpectedly before calling PD_close, the file can be PD_opend successfully.
NOTE: this call does NOT obviate PD_close!
#include pdb.h
PDBfile *file;
.
.
.
if (
PD_flush(file) == FALSE)
printf(%s, PD_err);
.
.
.
4.18 PD_GET_ATTRIBUTE
void *
PD_get_attribute(PDBfile *file,
char *vr,
char *attr)
Return the value of the specified attribute for the named entity.
The model of an attribute in PDBLib is an entity that has a name and type. The two supported operations on attributes are to create them and to remove them. An entity in a PDB file can be assigned an attribute value simply by calling PD_set_attribute. The only association between an entry in a PDB file and any attribute is made by the name in the attribute table and the entry in the symbol table. In particular, this mechanism allows the application developer to define and use entities in a PDB file solely in terms of attributes.
Attribute values are always assigned by reference and PD_get_attribute returns them the same way. The application may have to make a cast on the returned pointer.
The arguments to this function are: file, a pointer to a PDBfile; vr, an ASCII string containing the name of an entity in the PDB file; and attr, an ASCII string containing the name of the attribute being sought.
void *
PD_get_attribute(PDBfile *file,
char *vr,
char *attr)
#include pdb.h
PDBfile *file;
char *dt;
.
.
.
dt = (char *)
PD_get_attribute(file, foo, date);
printf(%s, PD_err);
.
.
.
4.19 PD_LN
int
PD_ln(PDBfile *file,
char *var,
char *link)
Create a link to a variable in the specified PDB file.
PDBLib supports an optional hierarchical directory structure inside PDB files. A directory or a variable in a directory may be specified by either a relative path or an absolute path. Slashes separate nodes in a path name. Absolute paths begin with a slash. Nodes consisting of two periods, .., refer to the next higher level directory.
The arguments to PD_ln are: file, a pointer to a PDBfile; var, an ASCII string containing the path name of an existing variable; and link, an ASCII string containing the path name of the new link.
The return value is a TRUE if successful; otherwise, FALSE is returned and the ASCII string PD_err contains any error message that was generated.
char *var,
#include pdb.h
PDBfile *file;
.
.
.
if (
PD_ln(file, /animals/mammals/chimpanzee, /chimp) == FALSE)
printf(%s, PD_err);
.
.
.
4.20 PD_LS
char **PD_ls(PDBfile *file,
char *path,
char *type,
int *num)
Return a list of names of entries (variables and directories) in PDB file file that are of type type and that are in the directory and match the variable name pattern specified by path.
PDBLib supports an optional hierarchical directory structure inside PDB files. A directory or a variable in a directory may be specified by either a relative path or an absolute path. Slashes separate nodes in a path name. Absolute paths begin with a slash. Nodes consisting of two periods, .., refer to the next higher level directory.
The arguments to PD_ls are: file, a pointer to a PDBfile; path, an ASCII string containing the path name of the directory to search and/or the variable name pattern to match; type, an ASCII string containing the type of entries to return; and num, a pointer to an integer to contain the number of entries returned.
If path is NULL, the contents of the current directory are listed. If type is NULL, all types are returned.
The terminal node of path may contain meta characters * and ?. Each * matches any zero or more characters and each ? matches any single character.
char *path,
#include pdb.h
PDBfile *file;
char **list;
int num;
.
.
.
/* get a list of all directories in the current directory */
list =
PD_ls(file, NULL, Directory, &num);
if (list == NULL)
printf(%s, PD_err);
.
.
.
SFREE(list);
.
.
.
/* get a list of the variables of type char * in directory animals */
list =
PD_ls(file, animals, char *, &num);
if (list == NULL)
printf(%s, PD_err);
.
.
.
SFREE(list);
.
.
.
4.21 PD_MKDIR
int
PD_mkdir(PDBfile *file,
char *dirname)
Create a new directory in the specified PDB file.
PDBLib supports an optional hierarchical directory structure inside PDB files. A directory or a variable in a directory may be specified by either a relative path or an absolute path. Slashes separate nodes in a path name. Absolute paths begin with a slash. Nodes consisting of two periods, .., refer to the next higher level directory.
The arguments to PD_mkdir are: file, a pointer to a PDBfile and dirname, an ASCII string containing the path name of the new directory.
The root directory, /, does not have to be created.
The return value is a TRUE if successful; otherwise, FALSE is returned and the ASCII string PD_err contains any error message that was generated.
char *dirname)
#include pdb.h
PDBfile *file;
.
.
.
if (
PD_mkdir(file, /animals/mammals) == FALSE)
printf(%s, PD_err);
.
.
.
4.22 PD_OPEN
PDBfile *
PD_open(char *filename,
char *mode)
Open an existing PDB file or create a new PDB file. Depending on the value of the mode argument, PDBLib attempts to open the file filename in read-only binary mode, open the file in append binary mode, or create a new file in read-write binary mode. Any string which begins with r causes the file to be opened in read-only mode, any string beginning with a causes the file to be opened in append mode, and any string beginning with w causes a file to be created in read-write mode. Next the beginning of the file is searched for the header which identifies the file as having been generated by PDBLib. The addresses of the structure chart and symbol table are then sought.
The structure chart from the file is read in. The structure chart contains information about data types (e.g. floats), their sizes in bytes and their structures if any. By default there are six primitive data types that PDBLib knows about: short integers, integers, long integers, floating point numbers, double precision floating point numbers, characters, and pointers. The sizes of these types varies from machine to machine, but PDBLib hides this from the user.
The symbol table from the file is read in. The symbol table contains the list of variables in the file, their types as defined in the structure chart, and dimensioning information for arrays. Each read from the file first consults the symbol table to see if the requested variable is present in the PDB file.
The function returns a pointer to a PDBfile. This PDBfile identifies the particular file to PDBLib. As such, if it is overwritten the file is lost. The number of PDB files which can be open simultaneously is machine or operating system dependent, but each open file has a unique PDBfile associated with it.
char *mode)
#include pdb.h
PDBfile *file;
.
.
.
if ((file =
PD_open(filenam, r)) == NULL)
printf(%s, PD_err);
.
.
.
4.23 PD_PWD
char *PD_pwd(PDBfile *file)
Return the current directory for the specified PDB file.
PDBLib supports an optional hierarchical directory structure inside PDB files. A directory or a variable in a directory may be specified by either a relative path or an absolute path. Slashes separate nodes in a path name. Absolute paths begin with a slash. Nodes consisting of two periods, .., refer to the next higher level directory.
The argument to PD_pwd is file, a pointer to a PDBfile.
If no directory has been created, / is returned.
#include pdb.h
PDBfile *file;
char *dirname;
.
.
.
if ((dirname =
PD_pwd(file)) == NULL)
printf(%s, PD_err);
.
.
.
4.24 PD_READ
int
PD_read(PDBfile *file,
char *name,
void *var)
Read all or part of a data entry from an open PDB file. The symbol table of the given PDB file is searched for the given name and if it is found the information there is used to read the proper number of bytes from the file, do any conversions, and put the result in memory pointed to by var.
The arguments to PD_read are: file, a pointer to a PDBfile which designates the PDB file from which to attempt the read; name, an ASCII string containing the specification of data to be read; and var, a pointer to the location where the data is to be placed.
Note: In each PD_read operation, the type of var must be a pointer to the type of the variable name.
Note: PDBLib can only read part of an entry if the type of the terminal node is primitive or a structure which contains no indirections and whose descendant members contain no indirections.
The return value is TRUE, if successful; otherwise, FALSE is returned and the ASCII string PD_err contains any error messages.
char *name,
#include pdb.h
PDBfile *file;
float x[20];
.
.
.
if (
PD_read(file, x, x) == FALSE)
printf(%s, PD_err);
.
.
.
4.25 PD_READ_ALT
int
PD_read_alt(PDBfile *file,
char *name,
void *var,
long *ind)
Read all or part of a data entry from an open PDB file. The symbol table of the given PDB file is searched for the given name and if it is found the information there is used to read the proper number of bytes from the file, do any conversions, and put the result in memory pointed to by var.
The arguments to PD_read_alt are: file, a pointer to a PDBfile which designates the PDB file from which to attempt the read; name, an ASCII string containing the specification of the data to be read; var, a pointer to the location where the data is to be placed; and ind, an array of long integers consisting of three indexes (start, stop, and step) for each dimension of the entry.
Note: In each PD_read_alt operation, the type of var must be a pointer to the type of the variable name.
Note: PDBLib can only read part of an entry if the type of the terminal node is primitive or a structure which contains no indirections and whose descendant members contain no indirections.
The return value is TRUE, if successful; otherwise, FALSE is returned and the ASCII string PD_err contains any error messages.
char *name,
#include pdb.h
PDBfile *file;
long ind[3];
float x[20];
.
.
.
ind[0] = 3;
ind[1] = 18;
ind[2] = 2;
if (
PD_read_alt(file, x, x, ind) == FALSE)
printf(%s, PD_err);
.
.
.
4.26 PD_READ_AS
int
PD_read_as(PDBfile *file,
char *name,
char *type,
void *var)
Read data from an open PDB file. The symbol table of the given PDB file is searched for the given name and if it is found the information there is used with the type specified by type to read the proper number of bytes from the file, do any conversions, and put the result in memory pointed to by var. The type specified overrides the type in the symbol table entry as far as deciding on data conversions goes.
This function is generally used to read floats as doubles and so on. However with sufficient care and understanding of both the file data and C data structuring, it can be used to transmute structured data.
Note: In each PD_read_as operation, the type of var must be a pointer to the type specified by type.
Note: PDBLib can only read part of an entry if the type of the terminal node is primitive or a structure which contains no indirections and whose descendant members contain no indirections.
The return value is TRUE, if successful; otherwise, FALSE is returned and the ASCII string PD_err contains any error messages.
char *name,
#include pdb.h
PDBfile *file;
float x[20];
.
.
.
/* x is a double in the file */
if (
PD_read_as(file, x, float, x) == FALSE)
printf(%s, PD_err);
.
.
.
4.27 PD_READ_AS_ALT
int
PD_read_as_alt(PDBfile *file,
char *name,
char *type,
void *var,
long *ind)
Read all or part of a data entry from an open PDB file. The symbol table of the given PDB file is searched for the given name and if it is found the information there is used with the type specified by type to read the proper number of bytes from the file, do any conversions, and put the result in memory pointed to by var. The type specified overrides the type in the symbol table entry as far as deciding on data conversions goes.
This function is generally used to read floats as doubles and so on. However with sufficient care and understanding of both the file data and C data structuring, it can be used to transmute structured data.
Note: In each PD_read_as_alt operation, the type of var must be a pointer to the type specified by type.
Note: PDBLib can only read part of an entry if the type of the terminal node is primitive or a structure which contains no indirections and whose descendant members contain no indirections.
The return value is TRUE, if successful; otherwise, FALSE is returned and the ASCII string PD_err contains any error messages.
int
PD_read_as_alt(PDBfile *file,
char *name,
char *type,
void *var,
long *ind)
#include pdb.h
PDBfile *file;
long ind[3];
float x[20];
.
.
.
ind[0] = 2;
ind[1] = 10;
ind[2] = 2;
/* x is a double in the file */
if (
PD_read_as_alt(file, x, float, x, ind) == FALSE)
printf(%s, PD_err);
.
.
.
4.28 PD_RESET_PTR_LIST
int
PD_reset_ptr_list(PDBfile *file)
Free the list of pointers which the PDB file file knows about. This includes both pointers in memory acquired during write operations and pointers in the file acquired during read operations.
The argument to this function is file a pointer to a PDBfile.
int
PD_reset_ptr_list(PDBfile *file)
#include pdb.h
PDBfile *file;
.
.
.
if (
PD_reset_ptr_list(file) == FALSE)
printf(%s, PD_err);
.
.
4.29 PD_REM_ATTRIBUTE
int
PD_rem_attribute(PDBfile *file,
char *attr)
Remove the specified attribute. Any entities which have a value for this attribute will have it removed by PDBLib.
The model of an attribute in PDBLib is an entity that has a name and type. The two supported operations on attributes are to create them and to remove them. An entity in a PDB file can be assigned an attribute value simply by calling PD_set_attribute. The only association between an entry in a PDB file and any attribute is made by the name in the attribute table and the entry in the symbol table. In particular, this mechanism allows the application developer to define and use entities in a PDB file solely in terms of attributes.
The arguments to this function are: file, a pointer to a PDBfile; and attr, an ASCII string containing the name of the attribute being removed.
int
PD_rem_attribute(PDBfile *file,
char *attr)
#include pdb.h
PDBfile *file;
.
.
.
if (
PD_rem_attribute(file, date) == FALSE)
printf(%s, PD_err);
.
.
.
4.30 PD_SET_ATTRIBUTE
int
PD_set_attribute(PDBfile *file,
char *vr,
char *attr,
void *vl)
Set the value of the specified attribute for the named entity. Attribute values are always assigned by reference.
The model of an attribute in PDBLib is an entity that has a name and type. The two supported operations on attributes are to create them and to remove them. An entity in a PDB file can be assigned an attribute value simply by calling PD_set_attribute. The only association between an entry in a PDB file and any attribute is made by the name in the attribute table and the entry in the symbol table. In particular, this mechanism allows the application developer to define and use entities in a PDB file solely in terms of attributes.
The arguments to this function are: file, a pointer to a PDBfile; vr, an ASCII string containing the name of an entity in the PDB file; attr, an ASCII string containing the name of the attribute being set; and vl, a pointer to data whose type matches the attribute type.
int
PD_set_attribute(PDBfile *file,
char *vr,
char *attr,
void *vl)
#include pdb.h
PDBfile *file;
char *dt;
.
.
.
dt = SC_strsave(Mon March 23, 1921);
if (
PD_set_attribute(file, foo, date, dt) == FALSE)
printf(%s, PD_err);
.
.
.
4.31 PD_TARGET
int
PD_target(data_standard *std,
data_alignment *align)
Write the next PDB file according to the specified data standard and alignment. PDBLib has a general binary data conversion mechanism called parametrized data conversion (PDC). The an integer type is described by one set of parameters and a floating point type is described by another. A general purpose conversion routine takes the description of the input type and a description of the desired output type and does the conversion. In this way, PDBLib avoids an N2 increase in data conversion routines as it ports to new machines. In fact, the number of data standards and alignments grows more slowly than N because many machines share common formats.
An additional advantage to PDC is that by specifying a format involving the minimal number of bits to represent the data for a file, PDBLib can carry out a large class of data compressions.
For programmer convenience, PDBLib carries several data standards and alignments. Data standards: IEEEA_STD, IEEEB_STD, IEEEC_STD, INTELA_STD, INTELB_STD, VAX_STD, and CRAY_STD. Data alignments: DEF_ALIGNMENT, SPARC_ALIGNMENT, MIPS_ALIGNMENT, M68000_ALIGNMENT, INTEL_ALIGNMENT, and CRAY_ALIGNMENT.
Some common configurations are:
The return value is TRUE, if successful; otherwise, FALSE is returned and the ASCII string PD_err contains any error messages.
int PD_target(data_standard *std,
data_alignment *align)
#include pdb.h
void test_target(tgt, base, n, fname, datfile)
char *tgt, *base;
int n;
char *fname, *datfile;
{if (tgt != NULL)
/* for DOS machines */
{if (strcmp(tgt, dos) == 0)
PD_target(&INTEL_STD, &INTEL_ALIGNMENT);
/* for CRAY computers */
else if (strcmp(tgt, cray) == 0)
PD_target(&CRAY_STD, &UNICOS_ALIGNMENT);
/* for DEC VAX machines */
else if (strcmp(tgt, vax) == 0)
PD_target(&VAX_STD, &DEF_ALIGNMENT);
/* for MIPS based machines */
else if (strcmp(tgt, mips) == 0)
PD_target(&IEEEA_STD, &MIPS_ALIGNMENT);
/* for standard M68000 machines */
else if (strcmp(tgt, sun3) == 0)
PD_target(&IEEEA_STD, &M68000_ALIGNMENT);
/* for SPARC machines */
else if (strcmp(tgt, sun4) == 0)
PD_target(&IEEEA_STD, &SPARC_ALIGNMENT);
/* for Macintosh */
else if (strcmp(tgt, mac) == 0)
PD_target(&IEEEB_STD, &M68000_ALIGNMENT);
sprintf(fname, %s-%s.rs%d, base, tgt, n);
sprintf(datfile, %s-%s.db%d, base, tgt, n);}
else
{sprintf(fname, %s-nat.rs%d, base, n);
sprintf(datfile, %s-nat.db%d, base, n);};
return;}
defstr *PD_typedef(PDBfile *file,
char *oname,
char *tname)
Define a an alternate name for an existing type. The intended use of this function is to allow users to make their PDB data types match their C types as closely as possible. It does this by mimicking the C typedef mechanism in a limited way. More accurately it provides an aliasing capability. This can be used in conjunction with either PD_defix or PD_defloat to install a definition of a data type in the host chart (PD_defix and PD_defloat define their types to the file chart only).
Input to PD_defix is: file, a pointer to a PDBfile; oname, an ASCII string containing the name of the original data type; tname, an ASCII string containing the name of the alias.
A pointer to the original types defstr is returned if the call is successful; otherwise, NULL is returned and the ASCII string PD_err contains any error message that was generated.
char *oname,
#include pdb.h
PDBfile *file;
defstr *ptr;
.
.
.
/* define enum as an alias for integer */
ptr =
PD_typedef(file, integer, enum);
.
.
4.33 PD_WRITE
char *name,
The primitive data types which the PDBLib system knows about by default are: short, integer, long, float, double, and char for short integer, integer, long integer, floating point or real number, double precision floating point number, and character or single byte respectively. Additional types may be added using PD_defstr.
PDBLib supports arbitrary levels of indirections. This means that all types of pointers (except function pointers) can be traced down to the actual data to which they point and that data will be written out into the PDB file in such a way that the read operations can reconstruct the data as it exists prior to the write operation. There is one crucial restriction. That is that the memory associated with any pointer must have been allocated using a SCORE memory management function or macro. See the memory management section near the beginning of this document.
Rationale: When writing out scalar variables (i.e. non-dimensioned variables - structured variables are scalars unless specifically dimensioned) this function is the most convenient to use since it involves no variable argument list and hence no worries about terminating the list. Another situation, which is more common than expected, in which PD_write would be preferred is when it is desirable to make entries in a PDB file which do not correspond to any variables in the application program. Since string manipulations might be involved in preparing the name under which to write the data, coding in the dimensional information is not any less efficient.
Dimensions can be given in two ways. If the default offset value for the PDB file can be taken as the minimum value for the range which a dimension index can legally run, the maximum value may be specified alone. Alternatively, the minimum value, maximum value, and stride (separated by colons) may be specified. The stride is optional and defaults to 1.
Note: PDBLib can only write part of an entry if the type of the terminal node is primitive or a structure which contains no indirections and whose descendant members contain no indirections.
The return value is TRUE if successful; otherwise, FALSE is returned and the ASCII string PD_err contains any error messages.
char *name,
#include pdb.h
PDBfile *file;
float x[20];
.
.
.
if (!
PD_write(file, x(20), float, x))
printf(%s, PD_err);
.
.
.
4.34 PD_WRITE_ALT
int
PD_write_alt(PDBfile *file,
char *name,
char *type,
void *var,
int nd,
long *ind)
Write data to a PDB file. This is an alternate form to PD_write. If an entry already exists in the file, the data overwrites the specified file data; otherwise, before writing data to the PDB file an entry is prepared for the symbol table consisting of the name, the type, the dimension information, the disk address to which the data will be written, and the total number of bytes as computed with the help of the structure chart. After the entry is installed in the symbol table the data from memory is converted (only if the target machine type is different from the current machine type) and then written out to disk starting at the current disk address.
The primitive data types which the PDBLib system knows about by default are: short, integer, long, float, double, and char for short integer, integer, long integer, floating point or real number, double precision floating point number, and character or single byte respectively. Additional types may be added using PD_defstr.
PDBLib supports arbitrary levels of indirections. This means that, subject to the restrictions spelled out in the section on rules, pointers (except function pointers) can be traced down to the actual data to which they point and that data will be written out into the PDB file in such a way that the read operations can reconstruct the data as it exists prior to the write operation. There is one crucial restriction. That is that the memory associated with any pointer must have been allocated by a SCORE memory management function or macro. See the Memory Management section near the beginning of this document.
The rationale for this function is that in some situations, it is desirable to be able to specify the dimensions without building them into an ASCII string.
The return value is TRUE if successful; otherwise, FALSE is returned and the ASCII string PD_err contains any error messages.
char *name,
#include pdb.h
PDBfile *file;
long ind[6];
float x[20][5];
.
.
.
ind[0] = 0L;
ind[1] = 19L;
ind[2] = 1L;
ind[3] = -2L;
ind[4] = 2L;
ind[5] = 1L;
if (!
PD_write_alt(file, x, float, x, 2, ind))
printf(%s, PD_err);
.
.
.
4.35 PD_WRITE_AS
int
PD_write_as(PDBfile *file,
char *name,
char *intype,
char *outtype,
void *var)
Write the data pointed to by var under name and with intype in PDB file file as data of outtype.
The rationale for this function is that in some situations, it is desirable to not only convert the formats of data of a specified type, but to convert between types. An example that occurs in practice often enough is converting a 32 bit int to a 32 bit long on a machine which only has a 16 bit int.
Note: PDBLib can only write part of an entry if the type of the terminal node is primitive or a structure which contains no indirections and whose descendant members contain no indirections.
PD_write_as returns TRUE if successful; otherwise, FALSE is returned and the ASCII string PD_err contains any error messages.
See also PD_write_as_alt and PD_defent_alt.
char *name,
#include pdb.h
PDBfile *file;
float x[20];
.
.
.
if (!
PD_write_as(file, x(20), float, double, x))
printf(%s, PD_err);
.
.
.
4.36 PD_WRITE_AS_ALT
int
PD_write_as_alt(PDBfile *file,
char *name,
char *intype,
char *outtype,
void *var,
int nd,
long *ind)
Write the data pointed to by var under name and with intype in PDB file file as data of outtype. This is an alternate form of PD_write_as.
The rationale for this function is that in some situations, it is desirable to be able to specify the dimensions without building them into an ASCII string.
Note: PDBLib can only write part of an entry if the type of the terminal node is primitive or a structure which contains no indirections and whose descendant members contain no indirections.
PD_write_as_alt returns TRUE if successful; otherwise, FALSE is returned and the ASCII string PD_err contains any error messages.
char *name,
#include pdb.h
PDBfile *file;
long ind[6];
float x[20][5];
.
.
.
ind[0] = 0L;
ind[1] = 19L;
ind[2] = 1L;
ind[3] = -2L;
ind[4] = 2L;
ind[5] = 1L;
if (!
PD_write_as_alt(file, x, float, double, x, 2, ind))
printf(%s, PD_err);
.
.
.
5.0
Summary of the FORTRAN API
There is a hierarchy of routines in PDBLib from high to low level. The high level routines form the API while the lower level routines are modularized to perform the actual work. It should be noted that the lower level routines are sufficiently well modularized so as to make it possible to build entirely different APIs for PDBLib.
The high level PDBLib routines have a strict naming convention. All routines in the FORTRAN API begin with PF.
Note: many of these functions return integer values. The implicit typing convention in FORTRAN would indicate that they return real values. Application programs must explicitly type these functions as integers.
When an error condition is detected by PDBLib it saves a message in a global C character string. FORTRAN programs can access this error message by invoking function PFGERR. The message contains the name of the function in which the error occurred thus eliminating the need for a cross reference document on error codes. In this way applications programs can check for error conditions themselves and decide in what manner to use the PDBLib error messages instead of having error messages printed by the system routines. Error messages are not stacked and must be processed by the application before any other PDBLib calls are made in order to avoid potential overwrites. See the FORTRAN API section for more information about which routines return error messages
5.1 Some Guidance in Using the FORTRAN API to PDBLib
PDBLib offers a great deal of flexibility to its users. In some cases the flexibility results in a bewildering assortment of function calls from which the application developer must choose. This section is intended to offer some guidance and enable developers to home in on the functions they need to use.5.1.1 Opening, Creating and Closing PDB Files
These are the most fundamental operations involving PDBLib. The function PFOPEN is used to either open an existing file or create a new one. PFCLOS is used to close a PDB file so that it can be recognized by PDBLib for future operations.
PDBLib allows applications to specify the binary format in which a newly created file will be written. PFTRGT does this work. It is not necessary to invoke PFTRGT before creating a new PDB file.
5.1.2 Writing Data to PDB Files
The following paragraphs describe a sequence of increasingly more elaborate output operations for PDB files. They are all compatible with one another so users can select the ones which match their needs best. The most straightforward operations are first.
PDBLib allows applications to append data to existing entries. This is handy in situations where the total amount of data is not known in advance, but a logical ordering of the data is apparent which matches the order in which data will be written. The functions which do this are PFAPPA, PFAPPD, PFAPAS and PFAPAD.
Finally, PDBLib allows applications to reserve space on disk and then let subsequent writes fill in that space with values. This is handy in instances where an application knows a logical structure for a data set but needs to write it out in smaller pieces and not necessarily in the order implied by its logical structure. The functions which let applications reserve space are PFDEFA, and PFDEFD. Reserved spaces may be written to with PFWRTA, PFWRTD, PFWRAS or PFWRAD.
5.1.3 Reading Data from PDB Files
Since data in a file has a definite size and shape, the reading operations in PDBLib are somewhat simpler than the writing operations. The functions PFREAD, PFPTRD, PFRDAS, and PFRDAD, the counterparts of PFWRTA, PFWRTD, PFWRAS, and PFWRAD, do all of the work in reading data from files.
5.1.4 Defining New Data Types
To aid application developers in using structured data PDBLib lets applications define new data types in a PDBfile. New data types may either be derived from other existing data types or they may be primitive (integer types, floating point types, or byte sequences). To define derived types applications should use PFDEFS.
5.1.5 Defining Attributes
PDBLib supports a general mechanism for managing a class of data which is variously referred to as attributes or meta data. In a great many cases, the careful design of data structures obviates the need for this kind of data. Nevertheless, PDBLib supplies four functions to manage attributive data: PFDATT, PFRATT, PFSVAT, and PFGVAT.
5.1.6 Queries
The FORTRAN API supports several query operations to help applications interpret the contents of a PDB file. The current functions are: PFGBFS, PFGERR, PFGMOD, PFGOFF, PFITYP, and PFIVAR.
A few definitions must be given first to keep the following summary concise. Some of these will be elaborated upon in the next section.
ASCII: an array of characters
5.2
Function Summary
These routines form the interface between FORTRAN applications programs and the PDBLib system.
PFAPAD(fileid, nchr, name, ntype, type, space, nd, ind)
Append the data from spaceof type type to the entry name in a PDB file. In this alternate to PFAPAS the dimensions are specified via the array ind.
PFAPAS(fileid, nchr, name, ntype, type, space)
PFAPPA(fileid, nchr, name, space)
PFAPPD(fileid, nchr, name, space, nd, ind)
[
PFCD(fileid, nchr, dirname)
PFCLOS(fileid)
PFDATT(fileid, na, attr, nt, type)
PFDEFA(fileid, nchr, name, ntype, outtype)
PFDEFD(fileid, nchr, name, ntype, outtype, nd, ind)
PFDEFS(fileid, nchr, name, ncm1, mem1, ..., ncmn, memn, LAST)
PFDEFT(fileid, nchr, name, nm, nc, memb)
PFDLS()
PFDVAR()
PFFAMI(fileid, flag)
PFFLSH(fileid)
PFGBFS()
PFGERR(nchr, err)
PFGLS(n, nchr, name)
PFGMOD(fileid)
PFGMXS(fileid)
PFGNM(fileid, nchr, name)
PFGOFF(fileid)
PFGVAR(n, nchr, name)
PFGVAT(fileid, nv, var, na, attr, value)
PFIMBR(file, ntype, type, n, size, space)
PFITYP(fileid, ntype, type, size, align, ind)
PFIVAR(fileid, nchr, name, ntype, type, size, ndims, dims)
PFLN(fileid, nvar, var, nlink, link)
PFLST(fileid, npath, path, ntype, type, num)
PFMKDR(fileid, nchr, dirname)
PFOPEN(nchr, name, mode)
PFPTRD(fileid, nchr, name, space, ind)
PFPWD(fileid, nchr, dirname)
PFRATT(fileid, na, attr)
PFRDAD(fileid, nchr, name, ntype, type, space, ind)
PFRDAS(fileid, nchr, name, ntype, type, space)
PFREAD(fileid, nchr, name, space)
PFSBFS(v)
PFSMXS(fileid, v)
PFSOFF(fileid, v)
PFSVAT(fileid, nv, var, na, attr, value)
PFTRGT(is, ia)
PFVART(fileid, order, nvars)
PFWIMA(fileid, nchr, name, pkn, pkx, pln, plx, data, pxn, pxx, pyn, pyx, pim)
PFWMAP(fileid, dname, dp, dm, rname, rp, rm, pim)
PFWRAD(fileid, nchr, name, ntypin, intype, ntypout, outtype, space, nd, ind)
PFWRAN(fileid, dname, nchr, rname, rp, rm, pim)
PFWRAS(fileid, nchr, name, ntypin, intype, ntypout, outtype, space)
PFWRTA(fileid, nchr, name, ntype, type, space)
PFWRTD(fileid, nchr, name, ntype, type, space, nd, ind)
PFWSET(fileid, dname, dp, dm)
Write the given information out to file fileid as a PM_mapping. The number pim represents the mapping number and must be unique.
Write the data pointed to by space under name and with type in PDB file fileid. Array
ind contains nd triples indicating the minimum and maximum index and the stride for
each dimension.
Write the given information out to file fileid as a PM_mapping. The number pim represents the mapping number and must be unique.
Write the data pointed to by space of type intype in PDB file fileid under name and with
type outtype. An arbitrary number of dimensions may be included in the name string.
Write the data pointed to by space under name and with type in PDB file fileid. An arbitrary number of dimensions may be included in the name string.
Write the data pointed to by space under name and with type in PDB file fileid. Array
ind contains nd triples indicating the minimum and maximum index and the stride for
each dimension.
integerPFAPAD(integer fileid,
integer nchr,
character name,
integer ntype,
character intype,
void space,
integer nd,
integer ind)Append data of type intype to an entry in the specified file. The outtype is assumed to be the same as for the original entry. The dimensions of the appended data are specified in nd and ind. They must match the original entry except for the most slowly varying one. The specification of the most slowly varying dimension must be one of the following;
The arguments to PFAPAD are: fileid, an integer identifier which designates the PDB file to which to write; nchr, an integer number of characters in the name string; name, an ASCII string containing the name of the variable to install in the symbol table; ntype, an integer number of characters in the intype string; intype, an ASCII string specifying the type of data to which space points; space, the data to be written; nd, an integer number of dimensions; and ind, an array of nd integer triples containing the minimum and maximum index and the stride for each dimension.
See also PFAPAS, PFAPPA, PFAPPD, PFWRAD, PFWRAS, PFWRTA, and PFWRTD.
integer
PFAPAD(integer fileid,
integer nchr,
character name,
integer ntype,
character intype,
void space,
integer nd,
integer ind)
character*8 intype
integer pfapad, pfwrtd
integer fileid, ntype, nd, ind(3)
real x(20)
real*8 y(10)
.
.
.
c write array x
ind(1) = 1
ind(2) = 20
ind(3) = 1
if (
pfwrtd(fileid, 1, x, 5, float, x, 1, ind) .eq. 0)
$ call errproc
.
.
.
c append to x
ind(2) = 10
if (
pfapad(fileid, 1, x, 6, double, y, 1, ind) .eq. 0)
$ call errproc
.
.
.
Compare this with the example of
PFWRAD.
integerPFAPAS(integer fileid,
integer nchr,
character name,
integer ntype,
character intype,
void space)Append data to an entry in the specified file. The outtype is assumed to be the same as for the original entry. The dimensions of the appended data are specified in name. They must match the original entry except for the most slowly varying one. The specification of the most slowly varying dimension must be one of the following;
The shape or dimensional information of the entry is a part of the name string. In this respect PFAPAS behaves just like PFWRAS.
The arguments to PFAPAS are: fileid, an integer identifier which designates the PDB file to which to write; nchr, an integer number of characters in the name string; name, an ASCII string containing the name of the variable and any dimensional information, ntype, an integer number of characters in the intype string; intype, an ASCII string specifying the type of data to which space points and space, the data to be appended.
See also PFAPAD, PFAPPA, PFAPPD, PFWRAD, PFWRAS, PFWRTA, and PFWRTD.
integer
PFAPAS(integer fileid,
integer nchr,
character name,
integer ntype,
character intype,
void space)
character*8 intype
integer pfapas, pfwrta
integer fileid, nchr, ntype
real x(20)
real*8 y(10)
.
.
.
c write array x
if (
pfwrta(fileid, 5, x(20), 5, float, x) .eq. 0)
$ call errproc
.
.
.
c append to x
if (
pfapas(fileid, 7, x(1:10), 6, double, y) .eq. 0)
$ call errproc
.
.
.
Compare this with the example of PFWRAS.
integerPFAPPA(integer fileid,
integer nchr,
character name,
void space)Append data to an entry in the specified file. The type is assumed to be the same as for the original entry. The dimensions of the appended data are specified in name. They must match the original entry except for the most slowly varying one. The specification of the most slowly varying dimension must be one of the following;
The shape or dimensional information of the entry is a part of the name string. In this respect PFAPPA behaves just like PFWRTA.
The arguments to PFAPPA are: fileid, an integer identifier which designates the PDB file to which to write; nchr, an integer number of characters in the name string; name, an ASCII string containing the name of the variable to install in the symbol table; and space, the data to be written.
See also PFAPAD, PFAPAS, PFAPPD, PFWRAD, PFWRAS, PFWRTA, and PFWRTD.
integer
PFAPPA(integer fileid,
integer nchr,
character name,
void space)
integer pfappa, pfwrta
integer fileid
real x(20), y(10)
.
.
.
c write array x
if (
pfwrta(fileid, 5, x(20), 5, float, x) .eq. 0)
$ call errproc
c append to x
if (
pfappa(fileid, 7, x(1:10), y) .eq. 0)
$ call errproc
.
.
.
integerPFAPPD(integer fileid,
integer nchr,
character name,
void space,
integer nd,
integer ind)Append data to an entry in the specified file. The type is assumed to be the same as for the original entry. The dimensions of the appended data are specified in nd and ind. They must match the original entry except for the most slowly varying one. The specification of the most slowly varying dimension must be one of the following;
The shape or dimensional information of the entry is specified in nd and ind. In this respect PFAPPD behaves just like PFWRTD.
The arguments to PFAPPD are: fileid, an integer identifier which designates the PDB file to which to write; nchr, an integer number of characters in the name string; name, an ASCII string containing the name of the variable to install in the symbol table; space, the data to be written; nd, an integer number of dimensions; and ind, an array of nd integer triples containing the minimum and maximum index and the stride for each dimension.
See also PFAPAD, PFAPAS, PFAPPA, PFWRAD, PFWRAS, PFWRTA, and PFWRTD.
integer
PFAPPD(integer fileid,
integer nchr,
character name,
void space,
integer nd,
integer ind)
integer pfappd, pfwrtd
integer fileid, ind(3)
real x(20), y(10)
.
.
.
c write array x
ind(1) = 1
ind(2) = 20
ind(3) = 1
if (
pfwrtd(fileid, 1, x, 5, float, x, 1, ind) .eq. 0)
$ call errproc
c append to x
ind(2) = 10
if (
pfappd(fileid, 1, x, y, 1, ind) .eq. 0)
$ call errproc
.
.
.
integerPFCD(integer fileid,
integer nchr,
char *dirname)Change the current directory in a PDB file.
PDBLib supports an optional hierarchical directory structure inside PDB files. A directory or a variable in a directory may be specified by either a relative path or an absolute path. Slashes separate nodes in a path name. Absolute paths begin with a slash. Nodes consisting of two periods, .., refer to the next higher level directory.
The arguments to PFCD are: fileid, an integer file identifier; nchr, an integer number of characters in string dirname; and dirname, an ASCII string containing the path name of the directory to change to.
If dirname is an empty string or a slash, it refers to the top level or root directory.
The return value is 1, if successful; otherwise, 0 is returned and an error message may be retrieved by invoking function PFGERR.
integer
PFCD(integer fileid,
integer nchr,
char *dirname)
integer pfcd
integer fileid
.
.
.
if (
pfcd(fileid, 16, /animals/mammals) .eq. 0)
$ call errproc
.
.
.
if (
pfcd(fileid, 11, ../reptiles) .eq. 0)
$ call errproc
.
.
.
6.6 PFCLOS (PD_close)
integer
PFCLOS(integer fileid)
Close a PDB file. After all data is written to the PDB file, the structure chart and symbol table must be written out to the file and their disk addresses recorded in the file header. Without these operations the file cannot be read back in by PDBLib and all data is lost.
All open PDB files must be PFCLOSd before exiting the program. The integer identifier fileid associated with the PDB file must be passed to PFCLOS.
This function returns 1 if the PDB file is correctly written and closed; otherwise, 0 is returned and an error message may be retrieved by invoking function PFGERR.
integer
PFCLOS(integer fileid)
integer
pfclos
integer fileid
.
.
.
if (
pfclos(fileid) .eq. 0)
$ call errproc
.
.
.
6.7 PFDATT (PD_def_attribute)
integer
PFDATT(integer fileid,
integer na,
char *attr,
integer nt,
char *type)
Define an attribute to the given PDB file. The model of an attribute in PDBLib is an entity that has a name and type. The two supported operations on attributes are to create them and to remove them. An entity in a PDB file can be assigned an attribute value simply by making a call which specifies the entity name, the attribute name, and the attribute value (which is determined by the type). The only association between an entry in a PDB file and any attribute is made by the name in the attribute table and the entry in the symbol table. In particular, this mechanism allows the application developer to define and use entities in a PDB file solely in terms of attributes.
The arguments to PFDATT are: fileid, an integer identifier which designates the PDB file in which the attribute is being defined; na, an integer number of characters in the attr string; attr, an ASCII string containing the name of the attribute; nt, an integer number of characters in the type string; and type, an ASCII string containing the type of the attribute;
The return value is 1, if successful; otherwise, 0 is returned and an error message may be retrieved by invoking function PFGERR.
integer
PFDATT(integer fileid,
integer na,
char *attr,
integer nt,
char *type)
integer pfdatt
integer fileid
.
.
.
if (
pfdatt(fileid, 4, date, 6, char *) .eq. 0)
$ call errproc
.
.
.
6.8 PFDEFA (PD_defent)
integer
PFDEFA(integer fileid,
integer nc,
char *name,
integer nt,
char *type)
Define an entry in the symbol table of the PDB file specified by fileid. This function reserves space on disk but writes no data. The data can be written with later calls to PFWRTA or PFWRTD.
The rationale for this function is to block out space in a PDB file corresponding to some logical layout of a piece of data. The data may not exist at the time the space is reserved or for some reason it may be desirable to write out the data in pieces. In any case if the type and shape of a variable is known at some point, an entry may be made in the PDB file without writing any data. The space may filled with other PDBLib calls at some later time.
The arguments to this function are: fileid, an integer identifier which designates the PDB file in which to define an entry; nchr, an integer number of characters in the name string; name, an ASCII string containing the name of the variable to install in the symbol table; ntype, an integer number of characters in the type string; and type, an ASCII string specifying the variable type.
integer
PFDEFA(integer fileid,
integer nc,
char *name,
integer nt,
char *type)
integer
pfdefa
integer fileid
.
.
.
c define and reserve array x
c declaration for x would be: real x(20)
if (
pfdefa(fileid, 5, x(20), 5, float) .eq. 0)
$ call errproc
.
.
.
Compare this with the example of PFWRTA.
6.9 PFDEFD (PD_defent_alt)
integer
PFDEFD(integer fileid,
integer nc,
char *name,
integer nt,
char *type,
integer nd,
integer ind)
Define an entry in the symbol table of the PDB file specified by fileid. This function reserves space on disk but writes no data. The data can be written with later calls to PFWRTA or PFWRTD.
This is an alternate form of PFDEFA. The difference is that the dimension information is supplied via the nd and ind arguments instead of being a part of the name string. In this respect it behaves as PFWRTD.
The rationale for this function is to block out space in a PDB file corresponding to some logical layout of a piece of data. The data may not exist at the time the space is reserved or for some reason it may be desirable to write out the data in pieces. In any case if the type and shape of a variable is known at some point, an entry may be made in the PDB file without writing any data. The space may filled with other PDBLib calls at some later time.
The arguments to this function are: fileid, an integer identifier which designates the PDB file in which to define an entry; nchr, an integer number of characters in the name string; name, an ASCII string containing the name of the variable to install in the symbol table; ntype, an integer number of characters in the type string; type, an ASCII string specifying the variable type; nd, an integer number of dimensions; and ind, an array of nd integer pairs containing the minimum and maximum index for each dimension.
See also PFAPPA, PFAPPD, PFDEFA, PFWRTA, and PFWRTD.
integer
PFDEFD(integer fileid,
integer nc,
char *name,
integer nt,
char *type,
integer nd,
integer ind)
integer
pfdefd
integer fileid, nd, ind(4)
.
.
.
c define and reserve array c
c declaration for c would be: real c(2,2:4)
nd = 2
ind(1) = 1
ind(2) = 2
ind(3) = 2
ind(4) = 4
if (
pfdefd(fileid, 1, c, 5, float, nd, ind) .eq. 0)
$ call errproc
.
.
.
Compare with the example for PFWRTD.
6.10 PFDEFS (PD_defstr))
integer
PFDEFS(integer fileid,
integer nchr,
character name,
integer ncm1, character mem1,
...,
integer ncmn, character memn,
integer LAST)
Define a data structure for a PDB file. As a matter of programming efficiency and clarity it is useful to be able to refer to more complex structural units than the primitive types: short integers, integers, long integers, floating point numbers, double precision floating point numbers, and characters. Arrays do this in a very simple-minded way. Many modern languages support extended types or structures which allow the programmer to group diverse types of data together in a very sophisticated way.
PDBLib supports an extended data typing mechanism called a structure. A structure is a set of declarations of members. Each member is in turn a data type known to the system. Much of the style and usage of structures comes from the C struct. Note: because FORTRAN 77 lacks a pointer type, structures defined with this function should not contain pointered members.
PFDEFS defines data structures to the PDB system so that instances of such extended types can be read and written as a whole in a single statement. The members of the structure are processed and an entry in the structure chart is made. Subsequent references to the new structure type are processed using information from the structure chart. The syntax by which members of a structure are specified is like that for C structs. The formal definition is given below ([ ] enclose optional elements). Note: self-referential structures should not be used in FORTRAN applications.
The return value is 1, if successful; otherwise, 0 is returned and an error message may be retrieved by invoking function PFGERR.
integer
PFDEFS(integer fileid,
integer nchr,
character name,
integer ncm1, character mem1,
...,
integer ncmn, character memn,
integer LAST)
parameter(LAST = 0)
integer
pfdefs
integer fileid
common /abc/ a(2), b, c(2,2:4)
real a, b, c
common /jkl/ j, k, l
integer j, k, l
.
.
.
if (
pfdefs(fileid,
$ 3, abc,
$ 10, float a(2),
$ 7, float b,
$ 14, float c(2,2:4),
$ LAST) .eq. 0)
$ call errproc
if (
pfdefs(fileid,
$ 3, jkl,
$ 9, integer j,
$ 9, integer k,
$ 9, integer l,
$ LAST) .eq. 0)
$ call errproc
.
.
.
integerPFDEFT(integer fileid,
integer nchr,
character name,
integer nm,
integer nc(2*nm),
character *memb)
Define a data structure for a PDB file. This is an alternate form of PFDEFS (see the description above for a discussion of structured data types).
The arguments to PFDEFT are: fileid, an integer identifier which designates the PDB file to which to write; nchr, the integer number of characters in the name string; name, an ASCII string containing the name of the variable to install in the symbol table; nm, an integer specifying how many members the type has; nc, an array of integer pairs specifying the 0 based offset into the nm array and the number of characters for each member; and nm, an array of characters containing the member specifications.
The return value is 1, if successful; otherwise, 0 is returned and an error message may be retrieved by invoking function PFGERR.
integer
PFDEFT(integer fileid,
integer nchr,
character name,
integer nm,
integer nc(2*nm),
character *memb)
integer
pfdeft
integer fileid, nc(6)
character*8 nm(4)
common /abc/ a(2), b, c(2,2:4)
.
.
.
nc(1) = 0
nc(2) = 10
nc(3) = 10
nc(4) = 7
nc(5) = 17
nc(6) = 14
nm(1) = float a(
nm(2) = 2)float
nm(3) = bfloat c
nm(4) = (2,2:4)
if (pfdeft(fileid, 3, abc, 3, nc, nm) .eq. 0)
call errproc
.
.
.
Compare with the example for PFDEFS.
6.12 PFFAMI (PD_family)
integer
PFFAMI(integer fileid, integer flag)
This function checks to see whether the specified file has exceeded it size limit. If it has a new file is opened and returns. If not the given file pointer is returned. The flag is set to TRUE if you want PFFAMI to close the file it is given. Otherwise the application is responsible for closing the file
The arguments to this function are: fileid, an integer file identifier returned by a previous call to PFOPEN; and flag an integer value (either TRUE or FALSE).
This function returns an integer file identifier.
integer old, new
integer
pffami
.
.
.
new = pffami(old, 0)
if (new .ne. old) then
pfclos(old)
.
.
.
old = new
endif
.
.
.
6.13 PFFLSH (PD_flush)
integer
PFFLSH(integer fileid)
This function writes out the information which describes the contents of the PDB file specified. Normally, PFCLOS calls this routine, but applications that want to protect themselves from system failures or other problems may chose to periodically use this function. After a successful return and until or unless more data is written to the file or space reserved for future writes, the PDB file is valid in the sense that if the application terminates unexpectedly before calling PFCLOS, the file can be PFOPENd successfully.
NOTE: this call does NOT obviate PFCLOS!
The argument to this function is file, the pointer to the PDBfile structure returned by a previous call to PD_open.
integer
PFFLSH(integer fileid)
integer
pfflsh
integer fileid
.
.
.
if (
pfflsh(fileid) .eq. 0)
$ call errproc
.
.
.
6.14 PFGFNM
integer
PFGFNM(integer fileid,
integer nchr,
character name)
Return the name of the specified PDB file. The nchr argument contains the length of the buffer on input and the length of the file name on output. If the buffer is not long enough, the length of the file name is returned in nchr and a value of 0 is returned.
The return value is 1, if successful; otherwise, 0 is returned and an error message may be retrieved by invoking function PFGERR.
integer
PFGFNM(integer fileid,
integer nchr,
character name)
integer pfgfnm
integer fileid
character*8 name(4)
.
.
.
if (
pfgfnm(fileid, 32, name) .eq. 0)
$ call errproc
.
.
.
6.15 PFGLS
integer
PFGLS(integer n,
integer nchr,
char *name)
Get the name of the nth entry in the internal table generated by PFLST.
PDBLib supports an optional hierarchical directory structure inside PDB files. A directory or a variable in a directory may be specified by either a relative path or an absolute path. Slashes separate nodes in a path name. Absolute paths begin with a slash. Nodes consisting of two periods, .., refer to the next higher level directory.
The arguments to PFGLS are: n, an integer ordinal index into the internal table; nchr, an integer to contain the number of characters returned in string name; and name, an ASCII string to contain the returned entry name.
Calls to PFGLS must be preceded by a call to PFLST to set up an internal table of directory and/or variable names.
This function copies the name of a symbol table entry into the name, if successful. The application must ensure that name is large enough to contain the longest name in the symbol table (although PDBLib permits names of arbitrary length, 256 characters would probably be more than enough).
The return value is 1, if successful; otherwise, 0 is returned and an error message may be retrieved by invoking function PFGERR.
integer
PFGLS(integer n,
integer nchr,
char *name)
integer pfgls
integer i, nvar, nchr
character name(256)
.
.
.
do 100 i = 1, nvar
if (
pfgls(i, nchr, name) .eq. 0)
$ call errproc
.
.
.
100 continue
.
.
.
6.16 PFGVAR
integer
PFGVAR(n, nchr, name)
Get the name of the nth variable in the internal table generated by a previous call to PFVART. The table will have been sorted in a particular order and this function allows applications to access the variables in the sorted order, not the default hash ordering that would normally apply.
This function copies the name into the array name, if successful. The application must ensure that name is large enough to contain the longest name in the symbol table (although PDBLib permits names of arbitrary length, 256 characters would probably be more than enough).
The arguments to PFGVAR are: n, an integer ordinal index into the internal sorted name table; nchr, an integer in which the number of characters in the name string is returned; name, an ASCII string which will contain the variable name upon successful completion.
The return value is 1, if successful; otherwise, 0 is returned and an error message may be retrieved by invoking function PFGERR.
integer
PFGVAR(n, nchr, name)
integer
pfgvar
integer i, n, nvar, nchar
character vname(256)
.
.
.
c print out the table of variable names created by pfvart
write(6,700)
700 format(/,Alphabetic list of variables:)
do 701 n = 1, nvar
if (
pfgvar(n, nchar, vname) .eq. 0)
$ call errproc
write(6,702) (vname(i), i=1,nchar)
702 format( ,256a1)
701 continue
.
.
.
6.17 PFGVAT (PD_get_attribute)
integer
PFGVAT(integer fileid,
integer nv,
char *var,
integer na
char *attr,
void value)
Get the value of the specified attribute for the named entity. The application must ensure that there is sufficient space to receive the attribute value.
The model of an attribute in PDBLib is an entity that has a name and type. The two supported operations on attributes are to create them and to remove them. An entity in a PDB file can be assigned an attribute value simply by calling PFSVAT. The only association between an entry in a PDB file and any attribute is made by the name in the attribute table and the entry in the symbol table. In particular, this mechanism allows the application developer to define and use entities in a PDB file solely in terms of attributes.
The arguments to PFGVAT are: fileid, an integer identifier which designates the PDB file from which to get the attribute; nv, an integer number of characters in the var string; var, an ASCII string containing the name of an entity; na, an integer number of characters in the attr string; attr, an ASCII string containing the name of the attribute; and value into which the attribute value will be copied.
The return value is 1, if successful; otherwise, 0 is returned and an error message may be retrieved by invoking function PFGERR.
integer
PFGVAT(integer fileid,
integer nv,
char *var,
integer na
char *attr,
void value)
integer pfgvat
integer fileid
character*8 dt(10)
.
.
.
if (
pfgvat(fileid, 3, foo, 4, date, dt) .eq. 0)
$ call errproc
.
.
.
6.18 PFIMBR
integer
PFIMBR(integer fileid,
integer ntype,
char *type,
integer n
integer size
char *space)
Inquire about the nth member of the type type in PDB file fileid. Return the description of the member in the character buffer, space. On input size is the number of characters in the buffer space. If the member description requires more space, size is set to the number of bytes required and 0 is returned.
Input to this function is: fileid, an integer PDBfile identification number; ntype, the number of characters in type; type, an ASCII string containing the name of the type; n, an integer specifying the member; size, an integer character size of the space buffer; and space, an character buffer to hold the member description.
integer
PFIMBR(integer fileid,
integer ntype,
char *type,
integer n
integer size
char *space)
integer pfimbr
integer fileid
character*8 type(10), desc(10), bdesc(100)
.
.
.
size = 80
if (
pfimbr(fileid, 3, foo, 4, size, desc) .eq. 0) then
if (size .le. 800) then
if (
pfimbr(fileid, 3, foo, 4, size, bdesc) .eq. 0) then
$ call errproc
endif
endif
endif
.
.
.
6.19 PFLN (PD_ln)
integer
PFLN(integer fileid,
integer nvar,
char *var,
integer nlink,
char *link)
Create a link to a variable in a PDB file.
PDBLib supports an optional hierarchical directory structure inside PDB files. A directory or a variable in a directory may be specified by either a relative path or an absolute path. Slashes separate nodes in a path name. Absolute paths begin with a slash. Nodes consisting of two periods, .., refer to the next higher level directory.
The arguments to PFLN are: fileid, an integer file identifier; nvar, an integer number of characters in string var; var, an ASCII string containing the path name of an existing variable; nlink, an integer number of characters in string link; and link, an ASCII string containing the path name of the new link.
The return value is 1, if successful; otherwise, 0 is returned and an error message may be retrieved by invoking function PFGERR.
integer
PFLN(integer fileid,
integer nvar,
char *var,
integer nlink,
char *link)
integer pfln
integer fileid
.
.
.
if (
pfln(fileid, 27, /animals/mammals/chimpanzee,
$ 6, /chimp) .eq. 0)
$ call errproc
.
.
.
6.20 PFLST (PD_ls)
integer
PFLST(integer fileid,
integer npath,
char *path,
integer ntype,
char *type,
integer num)
Generate an internal table of names of entries (variables and/or directories) in a PDB file that are of a specified type and that are in the directory and match the variable name pattern specified.
PDBLib supports an optional hierarchical directory structure inside PDB files. A directory or a variable in a directory may be specified by either a relative path or an absolute path. Slashes separate nodes in a path name. Absolute paths begin with a slash. Nodes consisting of two periods, .., refer to the next higher level directory.
The arguments to PFLST are: fileid, an integer file identifier; npath, an integer number of characters in string path; path, an ASCII string containing the path name of the directory to search and/or the variable name pattern to match; ntype, an integer number of characters in string type; type, an ASCII string containing the type of entries to return; and num, an integer to contain the number of entries returned.
If npath is zero, the contents of the current directory are listed. If ntype is zero, all types are returned.
The terminal node of path may contain meta characters * and ?. Each * matches any zero or more characters and each ? matches any single character.
The return value is 1, if successful; otherwise, 0 is returned and an error message may be retrieved by invoking function PFGERR.
integer
PFLST(integer fileid,
integer npath,
char *path,
integer ntype,
char *type,
integer num)
integer pflst, pfdls
integer fileid, num
.
.
.
c generate a table of all directories in the current directory
if (
pflst(fileid, 0, , 9, Directory, num) .eq. 0)
$ call errproc
.
.
.
c generate a table of the variables of type char * in directory animals
if (
pflst(fileid, 7, animals, 6, char *, num) .eq. 0)
$ call errproc
.
.
.
6.21 PFMKDR (PD_mkdir)
integer
PFMKDR(integer fileid,
integer nchr,
char *dirname)
Create a new directory in a PDB file.
PDBLib supports an optional hierarchical directory structure inside PDB files. A directory or a variable in a directory may be specified by either a relative path or an absolute path. Slashes separate nodes in a path name. Absolute paths begin with a slash. Nodes consisting of two periods, .., refer to the next higher level directory.
The arguments to PFMKDR are: fileid, an integer file identifier; nchr, an integer number of characters in string dirname; and dirname, an ASCII string containing the path name of the new directory.
The return value is 1, if successful; otherwise, 0 is returned and an error message may be retrieved by invoking function PFGERR.
integer PFMKDR(integer fileid,
integer nchr,
char *dirname)
integer pfmkdr
integer fileid
.
.
.
if (
pfmkdr(fileid, 16, /animals/mammals) .eq. 0)
$ call errproc
.
.
.
6.22 PFOPEN (PD_open)
integer
PFOPEN(integer nchr,
character name,
character mode)
Open an existing PDB file or create a new PDB file. Depending on the value of mode, PDBLib attempts to open the file name in read-only binary mode, open the file in append binary mode, or create a new file in read-write binary mode.
Any string which begins with r causes the file to be opened in read-only mode, any string beginning with a causes the file to be opened in append mode, and any string beginning with w causes a file to be created in read-write mode.
Next, the beginning of the file is searched for the header which identifies the file as having been generated by PDBLib. The addresses of the structure chart and symbol table are then sought.
The symbol table from the file is read in. The symbol table contains the list of variables in the file, their types as defined in the structure chart, and dimensioning information for arrays. Each read from the file first consults the symbol table to see if the requested variable is present in the PDB file.
The function returns an integer identifier for the PDB file opened/created. This identifies the particular file to PDBLib. As such, if it is overwritten the file is lost. The number of PDB files which can be open simultaneously is machine or operating system dependent, but each open PDB file has a unique identifier associated with it.
integer
PFOPEN(integer nchr,
character name,
character mode)
integer
pfopen
integer fileid
.
.
.
fileid =
pfopen(8, file.pdb, r)
if (fileid .eq. 0)
$ call errproc
.
.
.
6.23 PFPTRD (PD_read_alt)
integer
PFPTRD(integer fileid,
integer nchr,
character name,
void space
integer ind)
Read all or part of a data entry from an open PDB file. The symbol table of the given PDB file is searched for the given name and if it is found the information there is used to read the proper number of bytes from the file, do any conversions, and put the result in memory pointed to by var.
The elements to be read from an array are designated by start, stop, step triples (one for each dimension) passed in the argument ind.
Note: In each PFPTRD operation, the type of space must be a pointer to the type of name.
Note: When reading part of a variable, especially a structured variable, the path to the desired part must contain one array reference for each level of indirection traversed.
The return value is 1, if successful; otherwise, 0 is returned and an error message may be retrieved by invoking function PFGERR.
integer
PFPTRD(integer fileid,
integer nchr,
character name,
void space
integer ind)
integer
pfptrd
integer fileid, ind(3)
real xodd(10)
.
.
.
c read the first 10 odd elements of x into array xodd
ind(1) = 1
ind(2) = 20
ind(3) = 2
if (
pfptrd(fileid, 1, x, xodd, ind) .eq. 0)
$ call errproc
.
.
.
6.24 PFPWD
integer
PFPWD(integer fileid,
integer nchr,
char *dirname)
Get the current directory for a PDB file.
PDBLib supports an optional hierarchical directory structure inside PDB files. A directory or a variable in a directory may be specified by either a relative path or an absolute path. Slashes separate nodes in a path name. Absolute paths begin with a slash. Nodes consisting of two periods, .., refer to the next higher level directory.
The arguments to PFPWD are: fileid, an integer file identifier; nchr, an integer to contain the number of characters returned in string dirname; and dirname, an ASCII string to contain the path name of the current directory.
This function copies the path name of a directory into the dirname, if successful. The application must ensure that dirname is large enough to contain the longest directory name (although PDBLib permits names of arbitrary length, 256 characters would probably be more than enough).
integer
PFPWD(integer fileid,
integer nchr,
char *dirname)
integer pfpwd
integer fileid, nchr
character dirname(256)
.
.
.
if (
pfpwd(fileid, nchr, dirname) .eq. 0)
$ call errproc
.
.
.
6.25 PFRATT (PD_rem_attribute)
integer
PFRATT(integer fileid,
integer na
char *attr)
Remove the specified attribute. PDBLib will remove the values of this attribute which may be associated with entities in the file.
The model of an attribute in PDBLib is an entity that has a name and type. The two supported operations on attributes are to create them and to remove them. An entity in a PDB file can be assigned an attribute value simply by calling PFSVAT. The only association between an entry in a PDB file and any attribute is made by the name in the attribute table and the entry in the symbol table. In particular, this mechanism allows the application developer to define and use entities in a PDB file solely in terms of attributes.
The arguments to PFRATT are: fileid, an integer identifier which designates the PDB file from which to remove the attribute; na, an integer number of characters in the attr string; and attr, an ASCII string containing the name of the attribute.
The return value is 1 if successful and 0 otherwise.
integer
PFRATT(integer fileid,
integer na
char *attr)
integer pfratt
integer fileid
.
.
.
if (
pfratt(fileid, 4, date) .eq. 0)
$ call errproc
.
.
.
6.26 PFRDAD (PD_read_as_alt)
integer
PFRDAD(integer fileid,
integer nchr,
character name,
integer ntype,
character intype,
void space
integer ind)
Read all or part of a data entry from an open PDB file as data type intype. The symbol table of the given PDB file is searched for the given name and if it is found the information there is used to read the proper number of bytes from the file, do any conversions, and put the result in memory pointed to by space.
The elements to be read from an array are designated by start, stop, step triples (one for each dimension) passed in the argument ind.
Note: In each PFRDAD operation, the type of space must be a pointer to the type of intype.
Note: When reading part of a variable, especially a structured variable, the path to the desired part must contain one array reference for each level of indirection traversed.
The return value is 1, if successful; otherwise, 0 is returned and an error message may be retrieved by invoking function PFGERR.
integer
PFRDAD(integer fileid,
integer nchr,
character name,
integer ntype,
character intype,
void space
integer ind)
integer
pfrdad
integer fileid, ind(3)
real*8 xdd(10)
.
.
.
c read the first 10 elements of float x into array xdd
c as type double.
ind(1) = 1
ind(2) = 10
ind(3) = 1
if (
pfrdad(fileid, 1, x, 6, double, xdd, ind) .eq. 0)
$ call errproc
.
.
.
6.27 PFRDAS (PD_read_as)
integer
PFRDAS(integer fileid,
integer nchr,
character name,
integer ntype,
character intype,
void space)
Read data from an open PDB file as data type intype. The symbol table of the given PDB file is searched for the given name and if it is found the information there is used to read the proper number of bytes from the file, do any conversions, and put the result in memory pointed to by space.
The arguments to PFRDAS are: fileid, an integer identifier which designates the PDB file from which to attempt the read; nchr, an integer number of characters in the name string; name, an ASCII string containing the name of the variable to lookup; ntype, an integer number of characters in the intype string; intype, an ASCII string specifying the type of data to which space points; and space, the location where the data is to be placed.
Note: In each PFRDAS operation, the type of space must be a pointer to the type of intype.
Note: When reading part of a variable, especially a structured variable, the path to the desired part must contain one array reference for each level of indirection traversed.
The return value is 1, if successful; otherwise, 0 is returned and an error message may be retrieved by invoking function PFGERR.
integer
PFRDAS(integer fileid,
integer nchr,
character name,
integer ntype,
character intype,
void space)
integer
pfrdas
integer fileid
real*8 xx(20)
.
.
.
c read array x into array xx as type double
if (
pfrdas(fileid, 1, x, 6, double, xx) .eq. 0)
$ call errproc
.
.
.
6.28 PFREAD (PD_read)
integer
PFREAD(integer fileid,
integer nchr,
character name,
void space)
Read data from an open PDB file. The symbol table of the given PDB file is searched for the given name and if it is found the information there is used to read the proper number of bytes from the file, do any conversions, and put the result in memory pointed to by space.
The arguments to PFREAD are: fileid, an integer identifier which designates the PDB file from which to attempt the read; nchr, an integer number of characters in the name string; name, an ASCII string containing the name of the variable to lookup; and space, the location where the data is to be placed.
Note: In each PFREAD operation, the type of space must be a pointer to the type of name.
Note: When reading part of a variable, especially a structured variable, the path to the desired part must contain one array reference for each level of indirection traversed.
The return value is 1, if successful; otherwise, 0 is returned and an error message may be retrieved by invoking function PFGERR.
integer
PFREAD(integer fileid,
integer nchr,
character name,
void space)
integer
pfread
integer fileid
real x(20)
common /abc/ a(2), b, c(2,2:4)
real a, b, c
common /jkl/ j, k, l
integer j, k, l
.
.
.
c read array x
if (
pfread(fileid, 1, x, x) .eq. 0)
$ call errproc
c read first element of member c of structure abc
if (
pfread(fileid, 10, abc.c(1,2), c) .eq. 0)
$ call errproc
c read entire structure jkl
if (
pfread(fileid, 3, jkl, j) .eq. 0)
$ call errproc
.
.
.
6.29 PFSVAT (PD_set_attribute)
integer
PFSVAT(integer fileid,
integer nv,
char *var,
integer na
char *attr,
void value)
Set the value of the specified attribute for the named entity.
The model of an attribute in PDBLib is an entity that has a name and type. The two supported operations on attributes are to create them and to remove them. An entity in a PDB file can be assigned an attribute value simply by calling PFSVAT. The only association between an entry in a PDB file and any attribute is made by the name in the attribute table and the entry in the symbol table. In particular, this mechanism allows the application developer to define and use entities in a PDB file solely in terms of attributes.
The arguments to PFSVAT are: fileid, an integer identifier which designates the PDB file in which the attribute is being set; nv, an integer number of characters in the var string; var, an ASCII string containing the name of an entity; na, an integer number of characters in the attr string; attr, an ASCII string containing the name of the attribute being set; and value containing the attribute value.
The return value is 1, if successful; otherwise, 0 is returned and an error message may be retrieved by invoking function PFGERR.
integer
PFSVAT(integer fileid,
integer nv,
char *var,
integer na
char *attr,
void value)
integer pfsvat
integer scftcs
integer fileid
character*80 dt
.
.
.
scftcs(dt, Mon March 27, 1921, 18)
if (pfsvat(fileid, 3, foo, 4, date, dt) .eq. 0)
$ call errproc
.
.
.
6.30 PFTRGT (PD_target)
integer
PFTRGT(integer is,
integer ia)
Write the next PDB file to be created according to the specified data standard and alignment. PDBLib has a general binary data conversion mechanism called parametrized data conversion (PDC). An integer type is described by one set of parameters and a floating point type is described by another. A general purpose conversion routine takes the description of the input type and a description of the desired output type and does the conversion. In this way, PDBLib avoids an N2 increase in data conversion routines as it ports to new machines. In fact, the number of data standards and alignments grows more slowly than N because many machines share common formats.
An additional advantage to PDC is that by specifying a format involving the minimal number of bits to represent the data for a file, PDBLib can carry out a large class of data compressions.
Data standards: IEEEA_STD, IEEEB_STD, IEEEC_STD, INTELA_STD, INTELB_STD, VAX_STD, and CRAY_STD.
Data alignments: DEF_ALIGNMENT, SPARC_ALIGNMENT, MIPS_ALIGNMENT, RS6000_ALIGNMENT, 68000_ALIGNMENT, INTEL_ALIGNMENT, CRAY_ALIGNMENT, and UNICOS_ALIGNMENT.
In the FORTRAN API, these structures are placed in two arrays and the indices into these arrays are passed into PFTRGT to specify the binary format to be targeted.
The list of standards is:
The list of alignments is:
The return value is 1, if successful; otherwise, 0 is returned and an error message may be retrieved by invoking function PFGERR.
integer
PFTRGT(integer is,
integer ia)
integer
pftrgt
integer is, ia
.
.
.
c set target architecture (MIPS, SGI)
c IEEEA_STD
is = 1
c MIPS_ALIGNMENT
ia = 3
if (
pftrgt(is, ia) .eq. 0)
$ call errproc
.
.
.
integerPFVART(integer fileid,
integer order,
integer nvars)Generate an internal table of variables in the specified PDB file. With subsequent calls to PFGVAR, each entry can be obtained one at a time by ordinal index. The table is sorted according to a specified scheme. The current choices are alphabetic and by disk address.
The arguments to this function are: fileid, an integer which identifies the PDBfile; order, an integer specifying the sort ordering; and nvars, an integer in which the number of variables in the file is returned. The choices for order are: 1, for an alphabetic sort; and 2, for a disk address order sort.
The return value is 1, if successful; otherwise, 0 is returned and an error message may be retrieved by invoking function PFGERR.
integer
PFVART(integer fileid,
integer order,
integer nvars)
integer
pfvart
integer fileid, nvar, order
.
.
.
c create table of variable names in alphabetic order
order = 1
if (
pfvart(fileid, order, nvar) .eq. 0)
$ call errproc
.
.
.
6.32 PFWIMA
integer
PFWIMA(integer fileid,
integer nchr,
character name,
integer pkn,
integer pkx,
integer pln,
integer plx,
real*8 data,
real*8 pxn,
real*8 pxx,
real*8 pyn,
real*8 pyx,
integer pim)
Build a PD_image structure out of the given input data and write it to a PDB file.
Rationale: The PD_image structure is a useful and general purpose representation of a raster image. The nature of the generalization is that the values in the raster are floating point numbers. So in addition to the standard data sets that can be rasterized, the PD_image can be used to display the computational matrix of some system of equations, for example. This function is a convenient way for FORTRAN programs to put out their data into PDB files as PD_images for later visualization and processing by other programs. It allows a rectangular subset of a two dimensional array to be specified for the PD_image.
The calling application must keep track of how many PM_images have been written to each file. PDBLib will write each PM_image under the name composed of the string, Image, and the integer pim. For example if pim is 9, the PM_image will be written under the name Image9. If the application passes the same value for pim more than once only the last one will survive in the symbol table even though the data for each PM_image will persist in the file!
The return value is 1, if successful; otherwise, 0 is returned and an error message may be retrieved by invoking function PFGERR.
integer
PFWIMA(integer fileid,
integer nchr,
character name,
integer pkn,
integer pkx,
integer pln,
integer plx,
real*8 data,
real*8 pxn,
real*8 pxx,
real*8 pyn,
real*8 pyx,
integer pim)
integer
pfwima
integer fileid, k, l
c these arguments to pfwima must have 8 byte element size
double precision xmin, xmax, ymin, ymax, data(0:10,0:10)
.
.
.
xmin = 0.
xmax = 10.
ymin = 0.
ymax = 10.
do 100 l = 0, 10
do 101 k = 0, 10
data(k, l) = (k - 5)**2 + (l - 5)**2
101 continue
100 continue
if (
pfwima(fileid, 10, Test image, 0, 10, 0, 10,
$ data, xmin, xmax, ymin, ymax, 1) .eq. 0)
$ call errproc
.
.
.
6.33 PFWMAP
integer
PFWMAP(integer fileid,
character dname,
integer dp,
real*8 dm,
character rname,
integer rp,
real*8 rm,
integer pim)
Build a PM_mapping structure out of the given input data and write it to a PDB file.
Rationale: The PM_mapping structure is a convenient medium of exchange between data production systems such as simulation codes, storage systems such as PDBLib, and visualization systems such as PDBView. This function is a convenient way for FORTRAN programs to put out their data into PDB files as PM_mappings for later visualization and processing by other programs.
The PM_mapping is a structure with two main parts: a domain and a range. These two parts are in turn represented by a structure called a PM_set. Because they are both represented as the same type of data object, they are specified similarly in PFWMAP. For each of the domain and range sets the following information is given: a name; an array of integer quantities specifying such information as the dimensionality of the set, the dimensionality of the elements, the number of elements, and so on; and a linear array containing the elements of the set.
The entries in the arrays dp and rp are as follows:
The arguments to PFWMAP are: fileid, an integer identifier which designates the PDB file to which to attempt to write; dname, an ASCII string containing the name of the domain set; dp, an integer array of parameters defining the domain set; dm, an array of real*8 values containing the set elements component by component; rname, an ASCII string containing the name of the range set; rp, an integer array of parameters defining the range set; rm, an array of real*8 values containing the range elements component by component; and pim a counter specifying the number of the mapping being written out.
The return value is 1, if successful; otherwise, 0 is returned and an error message may be retrieved by invoking function PFGERR.
integer
PFWMAP(integer fileid,
character dname,
integer dp,
real*8 dm,
character rname,
integer rp,
real*8 rm,
integer pim)
integer
pfwmap
integer fileid, dp(5), rp(5)
double precision dm(0:99), rm(0:99)
.
.
.
dp(1) = 6
dp(2) = 1
dp(3) = 1
dp(4) = 100
dp(5) = 100
rp(1) = 6
rp(2) = 1
rp(3) = 1
rp(4) = 100
rp(5) = 100
do 100 i = 0, 99
dm(i) = 6.28*float(i)/99.
rm(i) = sin(6.28*float(i)/99.)
100 continue
if (
pfwmap(fileid, Domain, dp, dm, Range, rp, rm, 0)
$ .eq. 0)
$ call errproc
.
.
.
integerPFWRAD(integer fileid,
integer nchr,
character name,
integer ntypin,
character intype,
integer ntypout,
character outtype,
void space,
integer nd,
integer ind)Write the data of type intype to the PDB file as data of type outtype.
The rationale for this function is:
The arguments to PFWRAD are: fileid, an integer identifier which designates the PDB file to which to write; nchr, an integer number of characters in the name string; name, an ASCII string containing the name of the variable to install in the symbol table; ntypin, an integer number of characters in the intype string; intype, an ASCII string specifying the variable type in space; ntypout, an integer number of characters in the outtype string; outtype, an ASCII string specifying the variable type in the PDB file; space, the data to be written; nd, an integer number of dimensions; and ind, an array of nd integer triples containing the minimum and maximum index and the stride for each dimension.
The return value is 1, if successful; otherwise, 0 is returned and an error message may be retrieved by invoking function PFGERR.
integer
PFWRAD(integer fileid,
integer nchr,
character name,
integer ntypin,
character intype,
integer ntypout,
character outtype,
void space,
integer nd,
integer ind)
integer
pfwrad
integer fileid, nd, ind(6)
real*8 c(2,2:4)
.
.
.
c write array c of type double as type float
nd = 2
ind(1) = 1
ind(2) = 2
ind(3) = 1
ind(4) = 2
ind(5) = 4
ind(6) = 1
if (
pfwrad(fileid, 1, c, 6, double,
$ 5, float, c, nd, ind) .eq. 0)
$ call errproc
.
.
.
6.35 PFWRAN
integer
PFWRAN(integer fileid,
character dname,
integer nchr,
character rname,
integer rp,
real*8 rm,
integer pim)
Build a PM_mapping structure out of the given input data and write it to a PDB file.
Rationale: The PM_mapping structure is a convenient medium of exchange between data production systems such as simulation codes, storage systems such as PDBLib, and visualization systems such as PDBView. This function is a convenient way for FORTRAN programs to put out their data into PDB files as PM_mappings for later visualization and processing by other programs.
The PM_mapping is a structure with two main parts: a domain and a range. These two parts are in turn represented by a structure called a PM_set. In many cases a number of PM_mappings share a common domain set. It is therefore more efficient to write the unique domain sets out separately and use PFWRAN to write out the PM_mappings without their domains. Post processor codes such as PDBView (by definition) know how to put the full PM_mapping back together. Note: the domain name given for PFWRAN must be the same as the domain name passed to the corresponding PFWSET call.
For each range set the following information is given: a name; an array of integer quantities specifying such information as the dimensionality of the set, the dimensionality of the elements, the number of elements, and so on; and a linear array containing the elements of the set.
The entries in the array rp are as follows:
The arguments to PFWRAN are: fileid, an integer identifier which designates the PDB file to which to attempt to write; dname, an ASCII string containing the name of the domain set; nchr, an integer number of characters in dname; rname, an ASCII string containing the name of the range set; rp, an integer array of parameters defining the range set; rm, an array of real*8 values containing the range elements component by component; and pim a counter specifying the number of the mapping being written out.
The return value is 1, if successful; otherwise, 0 is returned and an error message may be retrieved by invoking function PFGERR.
integerPFWRAN(integer fileid,
character dname,
integer nchr,
character rname,
integer rp,
real*8 rm,
integer pim)
integerpfwran
integer fileid, i, pim, rp(5)
double precision rm(0:99)
.
.
.
pim = 0
rp(1) = 6
rp(2) = 1
rp(3) = 1
rp(4) = 100
rp(5) = 100
do 100 i = 0, 99
rm(i) = sin(6.28*float(i)/99.)
100 continue
c Domain written previously by pfwset
if (pfwran(fileid, Domain, 6, Range, rp, rm, pim)
$ .eq. 0)
$ call errproc
.
.
.
integerPFWRAS(integer fileid,
integer nchr,
character name,
integer ntypin,
character intype,
integer ntypout,
character outtype,
void space)Write the data of type intype to the PDB file as data of type outtype.
The rationale for this function is that in some situations, it is desirable to not only convert the formats of data of a specified type, but to convert between types. An example that occurs in practice often enough is converting a 32 bit int to a 32 bit long on a machine which only has a 16 bit int.
The arguments to PFWRAS are: fileid, an integer identifier which designates the PDB file to which to write; nchr, an integer number of characters in the name string; name, an ASCII string containing the name of the variable to install in the symbol table; ntypin, an integer number of characters in the intype string; intype, an ASCII string specifying the variable type in space; ntypout, an integer number of characters in the outtype string; outtype, an ASCII string specifying the variable type in the PDB file; and space, the data to be written.
The return value is 1, if successful; otherwise, 0 is returned and an error message may be retrieved by invoking function PFGERR
See also PFAPAS, PFAPAD, PFAPPA, PFAPPD, PFWRAD, PFWRTA, and PFWRTD.
integerPFWRAS(integer fileid,
integer nchr,
character name,
integer ntypin,
character intype,
integer ntypout,
character outtype,
void space)
integerpfwras
integer fileid
real*8 x(20)
.
.
.
c write array x of type double as type float
if (pfwras(fileid, 5, x(20), 6, double,
$ 5, float, x) .eq. 0)
$ call errproc
.
.
.
integerPFWRTA(integer fileid,
integer nchr,
character name,
integer ntype,
character type,
void space)Write data to a PDB file. Before writing data to the PDB file an entry is prepared for the symbol table consisting of the name, the type, the dimension information, the disk address to which the data will be written, and the total number of bytes as computed with the help of the structure chart. After the entry is installed in the symbol table the data from memory is converted (only if the target machine type is different from the current machine type) and then written out to disk starting at the current disk address.
The primitive data types which the PDBLib system knows about by default are: short, integer, long, float, double, and char for short integer, integer, long integer, floating point or real*8 number, double precision floating point number, and character or single byte respectively.
Rationale: When writing out scalar variables (i.e. non-dimensioned variables - structured variables are scalars unless specifically dimensioned) or arrays with fixed dimensions this function is the most convenient to use. Dimension information can be encoded in the name of the entry. PDBLib will strip that information off the name before creating the symbol table entry.
integer
PFWRTA(integer fileid,
integer nchr,
character name,
integer ntype,
character type,
void space)
integer
pfwrta
integer fileid
real x(20)
common /abc/ a(2), b, c(2,2:4)
real a, b, c
.
.
.
c write array x
if (
pfwrta(fileid, 5, x(20), 5, float, x) .eq. 0)
$ call errproc
c write entire structure abc (previous defined with pfdefs)
if (
pfwrta(fileid, 3, abc, 3, abc, a) .eq. 0)
$ call errproc
.
.
.
6.38 PFWRTD (PD_write_alternate)
integer
PFWRTD(integer fileid,
integer nchr,
character name,
integer ntype,
character type,
void space,
integer nd,
integer ind)
Write data to a PDB file. Before writing data to the PDB file an entry is prepared for the symbol table consisting of the name, the type, the dimension information, the disk address to which the data will be written, and the total number of bytes as computed with the help of the structure chart. After the entry is installed in the symbol table the data from memory is converted (only if the target machine type is different from the current machine type) and then written out to disk starting at the current disk address.
The primitive data types which the PDBLib system knows about by default are: short, integer, long, float, double, and char for short integer, integer, long integer, floating point or real number, double precision floating point number, and character or single byte respectively.
The rationale for this function is that in some situations, it is desirable to be able to specify the dimensions without building them into an ASCII string.
The return value is 1, if successful; otherwise, 0 is returned and an error message may be retrieved by invoking function PFGERR.
integer
PFWRTD(integer fileid,
integer nchr,
character name,
integer ntype,
character type,
void space,
integer nd,
integer ind)
integer
pfwrtd
integer fileid, nd, ind(6)
real c(2,2:4)
.
.
.
c write array c
nd = 2
ind(1) = 1
ind(2) = 2
ind(3) = 1
ind(4) = 2
ind(5) = 4
ind(6) = 1
if (
pfwrtd(fileid, 1, c, 5, float, c, nd, ind) .eq. 0)
$ call errproc
.
.
.
6.39 PFWSET)
integer
PFWSET(integer fileid,
character dname,
integer dp,
real*8 dm)
Build a PM_set structure out of the given input data and write it to a PDB file.
Rationale: The PM_set structure is a fundamental component of the PM_mapping structure which is a convenient medium of exchange between data production systems such as simulation codes, storage systems such as PDBLib, and visualization systems such as PDBView. Although the function PFWMAP most conveniently writes a mapping out to a PDB file, it does not make the best use of limited storage space. In many cases a number of PM_mappings share a common domain set. It is therefore more efficient to write the unique domain sets out separately and use PFWRAN to write out the PM_mappings without their domains. Post processor codes such as PDBView (by definition) know how to put the full PM_mapping back together. Note: the domain name given for PFWSET must be the same as the domain name passed to the corresponding PFWRAN call!
For each PM_set the following information is given: a name; an array of integer quantities specifying such information as the dimensionality of the set, the dimensionality of the elements, the number of elements, etc.; and a linear array containing the elements of the set.
The return value is 1, if successful; otherwise, 0 is returned and an error message may be retrieved by invoking function PFGERR.
integer
PFWSET(integer fileid,
character dname,
integer dp,
real*8 dm)
integer
pfwset
integer fileid, i, dp(5)
double precision dm(0:99)
.
.
.
dp(1) = 6
dp(2) = 1
dp(3) = 1
dp(4) = 100
dp(5) = 100
do 100 i = 0, 99
dm(i) = 6.28*float(i)/99.
100 continue
if (
pfwset(fileid, Domain, dp, dm) .eq. 0)
$ call errproc
.
.
.
An abstraction barrier is simply a technique or device which allows a section of code to be written assuming other functions or routines are defined and that their internal workings are irrelevant to their use. In this way a routine or module can be changed without any other part of the code which uses it being affected (so long as the definition of its function does not change). Abstraction barriers are most effectively created by a careful choice of the basic functional units and by the interfaces between them.
These units are put together in such a way that they are used over and over again in the process of doing any of the high level functions. In this way the code size was kept relatively small. Again this is one of the rewards of modularity.
7.2
Data Conversion and Compression
PDBLib has a quasi-universal data translation capability. It is called Parametrized Data Conversion (PDC). A set of parameters which characterizes a large set of integer and floating point formats was developed. It describes the byte size and order of integer types. For floating point data it describes the bit location and width of the sign, exponent, and mantissa field as well as the byte size and order of the data. Using this information a single integer conversion routine and a single floating point conversion routine handle all of the data conversions in PDBLib. The advantage of this approach is that there is no increase in the size of the library for each port to a new environment. Furthermore, it will allow future releases to auto-configure themselves to the machines on which they run. Another benefit is that a data representation may be targeted without regard to its implementation. This provides a vehicle for developing data representations, evaluating them, or using them in a highly abstract manner. The sole drawback of this approach is that it makes assumptions about the representation of data in computers. While the assumptions are general and the result of incorporating data representations outside these assumptions is more work on the library itself, it is philosophically unsatisfying to make any assumptions about how things are to be done or data to be represented. The other drawback is that by being general purpose the conversion routines are slightly slower than specific ones. This is more than made up for in the saving in library size and ease of porting the library.
Alternative data conversion strategies are either hub and spoke (such as Suns XDR) or specific format to format. The latter suffers from an N2 growth in the number of conversion routines where N is the number of machine/architectures which the library supports. On the other hand, hub and spoke strategies necessitate a conversion on each read or write operation.
PDC prevents the conversion problem from being N2. At worst, the PDC method should grow like N in the number of parameter sets required. In practice, it is even better than that. Most computer systems today are based on a handful of CPUs which are the most constraining factor in binary data formats. For the convenience of the users of PDBLib, several data_standards and data_alignments are predefined by the library itself.
A significant advantage to PDC is that a class of data compression algorithms is implicit in the method. By simply describing a format which describes data in the correct range (up to a possible overall offset for each type), PDBLib can do all of the work to store and retrieve the data in a compressed form.
7.2.1 DATA_STANDARDS
See the section on the data_standard structure for a detailed discussion of its members. The following is a list of the data_standards which PDBLib provides by default. The purpose is twofold: to help users identify target formats; and to guide users who wish to create their own data_standards.
The members of the data_standard are indicated in the template:
DEF_STD
Note: There are several variants of floating type format on the VAX. Accordingly the user must decide which one to use and PDBLib has the descriptions:
otherwise
7.2.1.2
Byte Ordering
There is much discussion in the literature about little endian and big endian machines. Those two refer to two possible byte orderings for binary data. That is not the most general way to talk about byte ordering however. In fact the VAX format exemplifies the need for generality. PDBLib simply uses an array of integers which describe the order of the bytes in memory relative to CPUs such as the Motorola and SPARC families.
7.2.2
DATA_ALIGNMENTS
The term alignment refers to the fact that many CPUs require certain data types to begin at memory locations whose addresses are even multiples of some integer number of bytes. So for example, to say that the alignment of a double is 8 means that a double must begin at an address which is a multiple of 8.
Compilers hide this concept from almost all applications. PDBLib is one that must know data alignments precisely. It employs a structure called a data_alignment to record the alignments of the default primitive data types which PDBLib supports. See the discussion of the data_alignment structure in the section on data structures.
The following is the list of data_alignments which PDBLib provides automatically (applications can add their own as needed):
RS6000_ALIGNMENT = {1, 4, 2, 4, 4, 4, 4}
8.0
Data Structures in PDBLib
The data structures with which the PDBLib system works are passed back to the application program as the result of the high level calls. This gives the programmer access to a great deal of information about the PDB file, the symbol table and the structure chart. Hopefully, this also makes the package more powerful without pushing any special responsibility onto the programmer.
8.1
DATA_ALIGNMENT
The set of alignments for the primitive types is kept in a structure called data_alignment. Its actual definition is:
struct s_data_alignment
{int char_alignment;
int ptr_alignment;
int short_alignment;
int int_alignment;
int long_alignment;
int float_alignment;
int double_alignment;};
typedef struct s_data_alignment
data_alignment;
Each member is an integer which specifies the alignment for a primitive type. The alignment is a number of bytes such that a piece of data of this type must begin at an address which is an even multiple of that number. For example, if ptr_alignment is 4, a pointer must begin at an address divisible by 4.8.2
DATA_STANDARD
The set of information describing all of the primitive data types is organized into a structure called a data_standard. The data_standard characterizes the CPU architecture because all types are either primitive or derived from known types.
Its actual definition is:
struct s_data_standard
{int ptr_bytes;
int short_bytes;
int short_order;
int int_bytes;
int int_order;
int long_bytes;
int long_order;
int float_bytes;
long *float_format;
int *float_order;
int double_bytes;
long *double_format;
int *double_order;};
typedef struct s_data_standard
data_standard;
The integer types only require a number of bytes and their order. The floating point types require additional information describing the bit layout of the components of the number: the sign bit; the exponent; and the mantissa. These are given as an array of 8 integers as follows:8.3
DEFSTR
An entry in the structure chart is represented by a structure called a defstr. It contains information about the data type such as the type name, the byte size and alignment, and a list of members.
8.4
DIMDES
A dimdes or dimension descriptor contains the information necessary to characterize a list of dimension specifications. It contains such information as the minimum and maximum values the dimension index may have and the net size of the dimension index range.
8.5
MEMDES
A memdes or member descriptor is the structure used to contain the information about a member of a defstr. It contains information about the type of the member, the name of the member, any dimensions which the member may have, and any casts which have been defined via PD_cast.
8.6
PDBFILE
The PDBfile is the analog to the FILE structure in standard C I/O. In fact, the PDBfile contains a FILE pointer to access the file via the standard C library functions. In addition, the PDBfile contains information such as: the symbol table, the structure charts for the file and the host platform; data_standards and data_alignments for the file and the host platform; and a modification date.
8.7
SYMENT
Just as the defstr type describes entries in the structure chart the syment type describes entries in the symbol table. The syment includes information about the data type of the entry, the number of elements, the dimensions of the entry, and its disk address.
9.0
PDBLib by Example
The following code fragments illustrate the functionality of PDBLib. Some of the code is taken from the validation suite and some from the library itself.9.1 Working with PDB files
This routine is taken from the validation suite for PDBLib. In it, a target for the PDB file is chosen with the routine test_target (see the section on PD_target for the definition of this function), a PDB file created, some structures defined, data written, and the file closed. The file is then reopened in append mode, some more data written to the file, and the file is closed again. Finally, the file is opened in read mode, the data read, some comparisons done, and the file is closed. The read and write operations are hidden in this example. The significance of the example is that a PDB file is created, closed, and opened in both append and read-only mode.
test_1(base, tgt, n)
char *base, *tgt;
int n;
{PDBfile *strm;
char datfile[MAXLINE], fname[MAXLINE];
int err;
FILE *fp;
/* target the file as asked */
test_target(tgt, base, n, fname, datfile);
fp = fopen(fname, w);
/* create the named file */
if ((strm =
PD_open(datfile, w)) == NULL)
{fprintf(fp, Test couldnt create file %s\r\n, datfile);
exit(1);};
fprintf(fp, File %s created\n, datfile);
prep_test_1_data();
/* make a few defstructs */
PD_defstr(strm, l_frame,
float x_min, float x_max, float y_min,
float y_max, LAST);
PD_defstr(strm, plot,
float x_axis(10), float y_axis(10), integer npts,
char * label, l_frame view, LAST);
/* write the test data */
write_test_1_data(strm);
/* close the file */
if (!
PD_close(strm))
{fprintf(fp, Test couldnt close file %s\r\n, datfile);
exit(1);};
fprintf(fp, File %s closed\n, datfile);
/* reopen the file to append */
if ((strm =
PD_open(datfile, a)) == NULL)
{fprintf(fp, Test couldnt open file %s to append\r\n,
datfile);
exit(1);};
fprintf(fp, File %s opened to append\n, datfile);
append_test_1_data(strm);
/* close the file after append */
if (!
PD_close(strm))
{fprintf(fp, Test couldnt close file %s after append\r\n,
datfile);
exit(1);};
fprintf(fp, File %s closed after append\n, datfile);
/* reopen the file */
if ((strm =
PD_open(datfile, r)) == NULL)
{fprintf(fp, Test couldnt open file %s\r\n, datfile);
exit(1);};
fprintf(fp, File %s opened\n, datfile);
/* dump the symbol table */
dump_test_symbol_table(fp, strm->symtab, 1);
/* read the data from the file */
read_test_1_data(strm);
/* compare the original data with that read in */
err = compare_test_1_data(strm, fp);
/* close the file */
if (!
PD_close(strm))
{fprintf(fp, Test couldnt close file %s\r\n, datfile);
exit(1);};
fprintf(fp, File %s closed\n, datfile);
/* print it out to stdout */
print_test_1_data(fp);
fclose(fp);
return(err);}
9.2
Writing Data to PDB files
These two routines exemplify the various write routines of PDBLib. In particular, they were built to test the spectrum of write calls. Notice their demonstration of the rules for write operations: the variable must be a pointer to data of the type specified. static char
cs_w,
ca_w[N_CHAR],
*cap_w[N_DOUBLE];
static short
ss_w,
sa_w[N_INT];
static int
is_w,
ia_w[N_INT],
p_w[N_INT],
len;
static float
fs_w,
fa2_w[N_FLOAT][N_DOUBLE];
static double
ds_w,
da_w[N_FLOAT];
static plot
graph_w;
static l_frame
view_w;
static lev1
*tar_w;
/*-----------------------------------------------------------------*/
/*-----------------------------------------------------------------*/
void write_test_1_data(strm)
PDBfile *strm;
{
/* write scalars into the file */
PD_write(strm, cs, char, &cs_w);
PD_write(strm, ss, short, &ss_w);
PD_write(strm, is, integer, &is_w);
PD_write(strm, fs, float, &fs_w);
PD_write(strm, ds, double, &ds_w);
/* write primitive arrays into the file */
PD_write(strm, sa(5), short, sa_w);
PD_write(strm, ia(5), integer, ia_w);
/* write structures into the file */
PD_write(strm, view, l_frame, &view_w);
PD_write(strm, graph, plot, &graph_w);
return;}
/*-----------------------------------------------------------------*/
/*-----------------------------------------------------------------*/
void write_test_2_data(strm)
PDBfile *strm;
{
PD_write(strm, tar, lev1 *, &tar_w);
return;}
/*-----------------------------------------------------------------*/
/*-----------------------------------------------------------------*/
9.3
Reading Data from PDB files
These two routines exemplify the various read routines of PDBLib. In particular, they were built to test the spectrum of read operations. They read the data written out in the previous example. Notice their demonstration of the rules for read operations: the variable must be a pointer to data of the type specified. This is often a more difficult proposition for reads since the type information isnt supplied in the read call.
struct s_lev2
{char **s;
int type;};
typedef struct s_lev2 lev2;
struct s_lev1
{int *a;
double *b;
lev2 *c;};
typedef struct s_lev1 lev1;
static char
cs_r,
ca_r[N_CHAR],
*cap_r[N_DOUBLE];
static short
ss_r,
sa_r[N_INT];
static int
is_r,
ia_r[N_INT];
static float
fs_r,
fs_app_r,
fs_p1_r,
fs_p2_r,
fs_p3_r,
fa2_r[N_FLOAT][N_DOUBLE],
fa2_app_r[N_FLOAT][N_DOUBLE];
static double
ds_r,
da_r[N_FLOAT];
static plot
graph_r;
static l_frame
view_r;
static lev1
*tar_r;
/*-----------------------------------------------------------------*/
/*-----------------------------------------------------------------*/
void read_test_1_data(strm)
PDBfile *strm;
{
/* read the scalar data from the file */
PD_read(strm, cs, &cs_r);
PD_read(strm, ss, &ss_r);
PD_read(strm, is, &is_r);
PD_read(strm, fs, &fs_r);
PD_read(strm, ds, &ds_r);
/* read the primitive arrays from the file */
PD_read(strm, ca, ca_r);
PD_read(strm, sa, sa_r);
PD_read(strm, ia, ia_r);
PD_read(strm, fa2, fa2_r);
PD_read(strm, da, da_r);
PD_read(strm, cap, cap_r);
/* read the entire structures from the file */
PD_read(strm, view, &view_r);
PD_read(strm, graph, &graph_r);
/* read the appended data from the file */
PD_read(strm, fs_app, &fs_app_r);
PD_read(strm, fa2_app, fa2_app_r);
/* struct member test */
PD_read(strm, graph.view.x_max, &fs_p2_r);
PD_read(strm, view.y_max, &fs_p3_r);
return;}
/*-----------------------------------------------------------------*/
/*-----------------------------------------------------------------*/
/* READ_TEST_2_DATA - read the test data from the file */
void read_test_2_data(strm)
PDBfile *strm;
{do_r = strm->default_offset;
PD_read(strm, tar, &tar_r);
PD_read(strm, p, p_r);
PD_read(strm, tar(0).a, &ap1);
PD_read(strm, tar(1).a, &ap2);
PD_read(strm, tar(0).a(0), &aa[0]);
PD_read(strm, tar(0).a(1), &aa[1]);
PD_read(strm, tar(1).a(0), &aa[2]);
PD_read(strm, tar(1).a(1), &aa[3]);
PD_read(strm, tar(0).b, &bp1);
PD_read(strm, tar(1).b, &bp2);
PD_read(strm, tar(0).b(0), &ba[0]);
PD_read(strm, tar(0).b(1), &ba[1]);
PD_read(strm, tar(1).b(0), &ba[2]);
PD_read(strm, tar(1).b(1), &ba[3]);
PD_read(strm, tar(0).c, &cp1);
PD_read(strm, tar(1).c, &cp2);
PD_read(strm, tar(0).c(0), &ca[0]);
PD_read(strm, tar(0).c(1), &ca[1]);
PD_read(strm, tar(1).c(0), &ca[2]);
PD_read(strm, tar(1).c(1), &ca[3]);
PD_read(strm, tar(0).c(0).s, &sp1);
PD_read(strm, tar(0).c(1).s, &sp2);
PD_read(strm, tar(1).c(0).s, &sp3);
PD_read(strm, tar(1).c(1).s, &sp4);
PD_read(strm, tar(0).c(0).s(0), &tp1);
PD_read(strm, tar(0).c(0).s(1), &tp2);
PD_read(strm, tar(0).c(1).s(0), &tp3);
PD_read(strm, tar(0).c(1).s(1), &tp4);
PD_read(strm, tar(0).c(0).s(0)(2), &ta[0]);
PD_read(strm, tar(0).c(0).s(1)(1), &ta[1]);
PD_read(strm, tar(0).c(1).s(0)(3), &ta[2]);
PD_read(strm, tar(0).c(1).s(1)(2), &ta[3]);
PD_read(strm, tar(1).c(0).s(0), &tp5);
PD_read(strm, tar(1).c(0).s(1), &tp6);
PD_read(strm, tar(1).c(1).s(0), &tp7);
PD_read(strm, tar(1).c(1).s(1), &tp8);
return;}
9.4
Inquiries in PDBLib
The following fragments show how to obtain information about PDB files and their contents.
/*-----------------------------------------------------------------*/
/*-----------------------------------------------------------------*/
myread(file, name, var, offset, number)
PDBfile *file;
char *name;
void *var;
long offset, number;
{long addr, num;
char *token, *type, memb[MAXLINE];
dimdes *dims;
syment *ep;
strcpy(memb, name);
token = strtok(memb, .([);
/* look up the variable name */
ep =
PD_inquire_entry(file, token);
if (ep == NULL)
PD_error(VARIABLE NOT IN SYMBOL TABLE - MYREAD,
READ);
addr =
PD_entry_address(ep);
dims =
PD_entry_dimensions(ep);
num =
PD_entry_number(ep);
type =
PD_entry_type(ep);
/* with ep in hand, we know the variable type, number of elements,
* dimensions, and disk address
*/
.
.
.
/*-----------------------------------------------------------------*/
/*-----------------------------------------------------------------*/
_PD_wr_leaf(file, var, nitems, type)
PDBfile *file;
char *var;
long nitems;
char *type;
{char *svar;
int size;
FILE *fp;
defstr *dp;
memdes *desc, *mem_lst;
fp = file->stream;
.
.
.
/* dispatch all other writes */
if (file->conversions)
.
.
.
/* obtain a pointer to the defstr associated with type */
dp = PD_inquire_host_type(file, type);
if (dp == NULL)
PD_error(BAD TYPE - WR-LEAF, WRITE);
/* if the structure has any pointered members loop over the members */
if (dp->n_indirects && ((mem_lst = dp->members) != NULL))
{size = dp->size;
for (svar = var, offset = 0L, i = 0L; i < nitems; i++)
{for (desc = mem_lst; desc != NULL; desc = desc->next)
{ ... };
svar += size;};};
.
.
.
/*-----------------------------------------------------------------*/
/*-----------------------------------------------------------------*/
9.5
Writing PM_mappings with PFWMAP
The following fragment shows how to write a PM_mapping to a PDB file from a FORTRAN program. This example uses PFWMAP. PFWMAP writes out both domain and range as a complete mapping. The drawback to this approach is that many mappings might have the same domain which would be written out over and over again. This could lead to unacceptably large data files. See the next example for a more space saving approach.
c
c************************************************************
c************************************************************
c
subroutine sxdmp(namesx, namelen)
c traverse plot list to make dumps suitable for sx
integer
pfopen, pfclos, pfgerr, pfwmap, pfwset, pfwran
integer zscanleq
integer pderr(32), rp(6), dp(6)
integer fileid, pim, dmnsn
double precision rm(nsavept), dm(nsavept)
c ... set up
.
.
.
c ... open the file
fileid =
pfopen(namelen, namesx, w)
if (fileid .eq. -1) then
iplpderr =
pfgerr(nchr, pderr)
call errproc(pderr, nchr, 0, 0)
endif
pim = 0
c ... loop over plots
do ...
c ... setup domain
dname = <domain name>
dp(1) = <length of domain name>
select case (dmnsn)
case (d2r1)
dp(2) = 2
dp(3) = 2
dp(4) = nr
dp(5) = kmax
dp(6) = lmax
call zmovewrd(dm(1), x2d, nr)
call zmovewrd(dm(nr+1), y2d, nr)
case (d1r1)
dp(2) = 1
dp(3) = 1
dp(4) = nr
dp(5) = nr
call zmovewrd(dm(1), <domain data>, nr)
endselect
c ... set up range
rname = <range name>
rp(1) = <length of range name>
rp(2) = dp(2)
rp(3) = 1
rp(4) = nr
rp(5) = dp(5)
rp(6) = dp(6)
call zmovewrd(rm(1), <range data>, nr)
c ... write the mapping
ierr =
pfwmap(fileid, dname, dp, dm, rname, rp, rm, pim)
if (ierr.eq.0) then
pfgerr(nchr, pderr)
call errproc(pderr, nchr, 0, 0)
endif
pim = pim + 1
repeat
c ... close the file
icloseok =
pfclos(fileid)
if (icloseok.eq.0) then
pfgerr(nchr, pderr)
call errproc(pderr, nchr, 0, 0)
endif
return
end
9.6
Writing PM_mappings with PFWSET and PFWRAN
The following fragment shows how to write a PM_mapping to a PDB file from a FORTRAN program. This example uses PFWSET and PFWRAN. With PFWSET and PFWRAN an application can write mappings in the most space efficient way. Instead of writing the same domains over and over again as would be done with PFWMAP, the application can select the unique domains and write them out with PFWSET. Then all mappings can be written using PFWRAN which writes out a PM_mapping with a null domain. The post processing tools (such as PDBView) reconstruct the complete PM_mapping by looking for the domain as a variable with the same name as the domain component of the mapping name. This approach is clearly a little more involved than using PFWMAP and application developers should weigh the advantages and disadvantages before selecting one method over the other. See the previous example for an illustration of the use of PFWMAP.
c
c************************************************************
c************************************************************
c
subroutine sxdmp(namesx, namelen)
c traverse plot list to make dumps suitable for sx
integer
pfopen, pfclos, pfgerr, pfwmap, pfwset, pfwran
integer zscanleq
integer pderr(32), rp(6), dp(6)
integer fileid, pim, dmnsn
double precision rm(nsavept), dm(nsavept)
c ... set up
.
.
.
c ... open the file
fileid =
pfopen(namelen, namesx, w)
if (fileid .eq. -1) then
iplpderr =
pfgerr(nchr, pderr)
call errproc(pderr, nchr, 0, 0)
endif
pim = 0
c ... loop over plots
do ...
c ... setup domain
dname = <domain name>
dp(1) = <length of domain name>
select case (dmnsn)
case (d2r1)
dp(2) = 2
dp(3) = 2
dp(4) = nr
dp(5) = kmax
dp(6) = lmax
call zmovewrd(dm(1), x2d, nr)
call zmovewrd(dm(nr+1), y2d, nr)
case (d1r1)
dp(2) = 1
dp(3) = 1
dp(4) = nr
dp(5) = nr
call zmovewrd(dm(1), <domain data>, nr)
endselect
if <unique domain> then
ierr =
pfwset(fileid, dname, dp, dm)
if (ierr.eq.0) then
iplpderr =
pfgerr(nchr, pderr)
call errproc(pderr, nchr, 0, 0)
endif
endif
c ... set up range
rname = <range name>
rp(1) = <length of range name>
rp(2) = dp(2)
rp(3) = 1
rp(4) = nr
rp(5) = dp(5)
rp(6) = dp(6)
call zmovewrd(rm(1), <range data>, nr)
c ... write out range
ierr =
pfwran(fileid, dname, dp(1), rname, rp, rm, pim)
if (ierr.eq.0) then
pfgerr(nchr, pderr)
call errproc(pderr, nchr, 0, 0)
endif
pim = pim+1
repeat
c ... close the file
icloseok =
pfclos(fileid)
if (icloseok.eq.0) then
pfgerr(nchr, pderr)
call errproc(pderr, nchr, 0, 0)
endif
return
end
10.0 Related
Documentation
PDBLib is one part of a collection of libraries called PACT. PDBLib uses the SCORE library in PACT for memory management, hash table, and string handling support. Interested readers should consult the SCORE manual as well as the PDBView manual, the ULTRA II manual, and the PANACEA manual for more information on how PDBLib is used.
The list of PACT documents is:
PACT Users Guide, UCRL-MA-112087
SCORE Users Manual, UCRL-MA-108976 Rev.1
PPC Users Manual UCRL-MA-108964 Rev.1
PML Users Manual, UCRL-MA-108965 Rev.1
PDBLib Users Manual, M-270 Rev.2 (this document)
PGS Users Manual, UCRL-MA-108966 Rev.1
PANACEA Users Manual, M-276 Rev.2
ULTRA II Users Manual, UCRL-MA-108967 Rev.1
PDBDiff Users Manual, UCRL-MA-108975 Rev.1
PDBView Users Manual, UCRL-MA-108968 Rev.1
SX Users Manual, UCRL-MA-112315