mirror of
https://bitbucket.org/cosmicvoids/vide_public.git
synced 2025-07-05 15:51:12 +00:00
.. | ||
ChangeLog.14 | ||
dictionary | ||
GNUmakefile | ||
README | ||
SDF-lex.c | ||
SDF-lex.l | ||
SDF-parse.c | ||
SDF-parse.y | ||
SDF-private.h | ||
SDFfuncs.c | ||
SDFget.c | ||
SDFhdrio.c | ||
stdio.h |
--------README from 1.3 ------------- This is version 1.3 of SDF. This version has been de-stdio-ized. It uses MY* functions in lieu of all stdio functions. Unless I've missed something, the only stdio function that remains is sprintf. Because lex is brain-damaged and insists on writing #include "stdio.h" into its output, I created a "./stdio.h" to override the system one. This is not strictly ANSI, but then, what is? --------README from 1.2------- This is version 1.2 of SDF ("Self Describing Files" or "Super-Duper Files, depending on how impressed you are). It is the first version of the last i/o package you'll ever need. SDF files are binary data files with an optional header which contains 1) a description of the layout of the data, and 2) optional ascii constants. There is no output capability because the sdf files are so easy to write :-). This document is completely unstructured, and probably incomprehensible to anyone but the author. It's a stream-of-consciousness first-draft. Be generous. The user-callable SDF programs are declared with prototypes in SDF.h. I refuse to consider systems that can't deal with prototypes, <stdarg.h> and the ellipsis for variadic functions and enum types. If you don't have gcc on your Sun, then call up Sun and give them a piece of your mind, and then go get gcc. The ANSI standard has been out for long enough now. Accept no substitutes. The object modules are in the library SDF_<machine>.a. I have tried to keep the "name-space pollution" to a minimum. Unfortunately, there are a few additional external names used by the SDF package that do not appear explicitly in SDF.h. These include anything starting with "obstack_" (SDF uses the gnu obstack package) and all names starting with "SDF". There are no provisions for writing SDF files. The reason is that it would be more complicated to go through a programmatic interface than to just create the files with fprintf() and fwrite(). The basic idea behind SDF files is that they are self-describing. That is, they have an ASCII header (human-readable, machine-parseable), which describes the contents of the file. The ascii header may contain explicit values, like: float npart = 200000.; int int_npart = 200000; char text[] = "Perhaps a few words about the file's pedigree could go here"; Notice the similarity to C declarations. In addition, the header contains declarations for the binary data that appears immediately after it. The allowed data types are char, short, int, float and double, arrays of same, and structs containing the basic types and arrays. (Multi-dimensional arrays are not supported. Nor are nested structures. But some kinds of two dimensional arrays can be captured by an array of structs, c.f., the 'id' vector in .tree files. These limitations may be relaxed in the future.) The header is terminated by a comment of the form # <anything> SDF-EOH <anything> \n That is, any comment containing the string SDF-EOH. The final new-line is the last character of the header. The binary data follows immediately after the new-line character. It is strongly recommended that the terminal comment contain one or more form-feeds (ctrl-L, \f in ANSI, \014 (octal), 0xc (hex), 12 (decimal)). That way, 'more' or similar programs can be used on the file without getting confused by the binary data. Similarly, it is strongly recommended that the first line of an SDF file contain the comment: # SDF <anything> \n This makes it easy for a modified version of 'file', as well as other utilities to figure out that they are dealing with an SDF file. Thus, the header for the output of an nbody simulation might look like: # SDF float npart; float iter; float time; ... char tree_header_text[384]; struct {float mass; float x, y, z; char id[4]; float vx, vy, vz; } []; # SDF-EOH ^L^L This header means that the floats npart, iter, time, etc. are stored as binary data following the header. Then comes a 384 byte character array, followed by an array (of unspecified length) containing the vectors mass, x, y, z, id, vx, vy, vz. Only the last array in the header may be of unspecifiec length. It means that when the file is read, the array is assumed to extend to the end of the file. SDF routines figure out the length of the file by asking the OS, and hence can determine the number of elements in arrays of unspecified length. Specifications with unknown length are useful for creating generic SDF headers, i.e., headers that describe binary files that you may already be using. If one were writing out a new SDF file, it is possible to write a header exactly as above, followed by the identical binary data. However, it would be much more convenient to write the "scalar" data as ascii values into the header. A new SDF file might look like: # SDF /* Comments may be between C-like comment delimiters */ # Or they follow the shell-like comment delimiter to end-of-line # This file was created by dave@h9k.hal.com on January 12, 1992... float npart = 200000.; int int_npart = 200000; float Gnewt = 1.0; float iter = 17.; float masstot = 1.1; float epsilon = 0.02; ... struct {float mass; float x, y, z; char id[4]; float vx, vy, vz;} [200000]; # SDF-EOH ^L^L This has the great advantage that most of the file's parameters are now both human-readable and machine-readable. A disadvantage to putting "history" information into comments is that it becomes inaccessable to programs (since SDF doesn't record comments). Another option is to put it in a character string: char history[] = "This file created by ... on ... 200000 body torqued Jaffe model constructed using: cubix ... "; Don't bother with C-syntax for newlines, etc in character strings. SDF just scans till it hits another " character. It doesn't do any escape-interpretation, so don't bother with '\n' and especially don't try to put the double-quote character inside strings. Byte order is another headache. The function SDFcpubyteorder() returns an unsigned int which "describes" the host-cpu's byte order, in a format which may be placed into an SDF header with the. "parameter byteorder" keyword. parameter byteorder = 0x12345678; You can make this line in a C program with: fprintf(fp, "parameter byteorder = 0x%x;\n", SDFcpubyteorder()); If such a parameter is in the header, then SDFread functions will assume that the binary data is written in the file in the byte order specified by the parameter. If the machine doing the reading has a different byte order, then bytes are swapped automatically. If there is no such parameter, you can tell the read functions to swap with SDFswapon(). Similarly, you can turn off swapping (for whatever reason) with SDFswapoff(), and you can inquire about swapping with SDFisswapping(); Non-ieee floats are completely out of the question. Don't even mention them in my presence. Dictionaries ------------ Nbody files contain a number of scalars, and a number of vectors. The names of these objects must be agreed upon between the entity creating the file and the entity reading the file. Since the creators of pjq, tree and tree_ap files could barely agree that the sun rises in the east and sets in the west, I have created a set of names for the items in common amongst these file types. The list is in the file "./dictionary". SDF files name their own contents. It's important that the names continue to agree with the names in ./dictionary. Thus, with the current dictionary it is agreed that the name "npart" refers to a float value equal to the number of bodies in the file. Similarly, the name "masstot" refers to the total mass of the file. These are the strings that you have to pass as names to SDFread routines in order to extract the appropriate values from a file. What you call these quantities inside your program is completely irrelevant, but if you create another SDF file, it's important to use the same names. The SDFopen function now takes two char* arguments, one for the filename of the header and one for the data. If they strcmp the same, or if the header is NULL or if the header is "", the descriptor is found at the beginning of the data file. If the name is "-", then stdin is used. If you really must open a file called "-", then you can do it by opening "./-". SDF will not gratuitously do random seeks around the file. In fact, it will struggle mightily to read the file sequentially. In many cases, SDFread will succeed on files that are not seekable. However, there are some requests that simply require rewinding the file. If your program does such a thing, then it MUST be possible to do arbitrary seeks on the data file, so taking stdin from a tty or a pipe would be a bad idea. You're supposed to get an error message in SDFerrstring for this (and all other) errors. Segmentation violations are increasingly rare. I'm certain that bugs still remain which will blow SDF right away, but they're getting harder to find every day.