diff --git a/c_tools/mock/generateFromCatalog.cpp b/c_tools/mock/generateFromCatalog.cpp index 54cbf87..0a578c0 100644 --- a/c_tools/mock/generateFromCatalog.cpp +++ b/c_tools/mock/generateFromCatalog.cpp @@ -334,9 +334,9 @@ void generateSurfaceMask(generateFromCatalog_info& args , // TEST - insert mock galaxies along spheres of survey redshift boundaries fp = fopen("mock_sphere.txt", "w"); - for (int p = 0; p < 0; p++) { + for (int q = 0; q < 0; q++) { //for (int p = 0; p < full_mask_list.size(); p++) { - vec3 v = mask.pix2vec(full_mask_list[p]); + vec3 v = mask.pix2vec(full_mask_list[q]); Position p; double r = args.zMin_arg * LIGHT_SPEED; diff --git a/c_tools/mock/generateMock.cpp b/c_tools/mock/generateMock.cpp index c222a7f..77eb04e 100644 --- a/c_tools/mock/generateMock.cpp +++ b/c_tools/mock/generateMock.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -244,11 +245,40 @@ void selectBox(SimuData *simu, std::vector& targets, generateMock_info& ar (simu->Pos[j][i] < ranges[j][1]); } - if (acceptance && (drand48() <= subsample)) + if (acceptance) targets.push_back(i); } } +class PreselectParticles: public SimulationPreprocessor +{ +private: + gsl_rng *rng; + double subsample; + int seed; +public: + PreselectParticles(double s, int seed_value) + : subsample(s), seed(seed_value), rng(gsl_rng_alloc(gsl_rng_default)) + { + gsl_rng_set(rng, seed); + } + + virtual ~PreselectParticles() + { + gsl_rng_free(rng); + } + + bool accept(const SingleParticle& p) + { + return gsl_rng_uniform(rng) < subsample; + } + + void reset() + { + gsl_rng_set(rng, seed); + } +}; + void createBox(SimuData *simu, vector& targets, vector& snapshot_split, SimuData *& boxed, generateMock_info& args_info) { double *ranges = new double[6]; @@ -511,13 +541,15 @@ int main(int argc, char **argv) generateMock_conf_print_version(); + SimulationPreprocessor *preselector = new PreselectParticles(args_info.subsample_arg, args_info.subsample_seed_arg); + if (args_info.ramsesBase_given || args_info.ramsesId_given) { if (args_info.ramsesBase_given && args_info.ramsesId_given) { loader = ramsesLoader(args_info.ramsesBase_arg, args_info.ramsesId_arg, false, - NEED_POSITION|NEED_VELOCITY|NEED_GADGET_ID); + NEED_POSITION|NEED_VELOCITY|NEED_GADGET_ID, preselector); } else { @@ -527,15 +559,15 @@ int main(int argc, char **argv) } else if (args_info.gadget_given) { - loader = gadgetLoader(args_info.gadget_arg, 1/args_info.gadgetUnit_arg, NEED_POSITION|NEED_VELOCITY|NEED_GADGET_ID); + loader = gadgetLoader(args_info.gadget_arg, 1/args_info.gadgetUnit_arg, NEED_POSITION|NEED_VELOCITY|NEED_GADGET_ID, preselector); } else if (args_info.flash_given) { - loader = flashLoader(args_info.flash_arg, NEED_POSITION|NEED_VELOCITY|NEED_GADGET_ID); + loader = flashLoader(args_info.flash_arg, NEED_POSITION|NEED_VELOCITY|NEED_GADGET_ID, preselector); } else if (args_info.multidark_given) { - loader = multidarkLoader(args_info.multidark_arg); + loader = multidarkLoader(args_info.multidark_arg, preselector); } else { @@ -570,6 +602,9 @@ int main(int argc, char **argv) else makeBoxFromSimulation(loader, simuOut, metricOperation, args_info); + // Reset the random number generator + preselector->reset(); + long loaded = 0; for (int nf = 0; nf < loader->num_files(); nf++) { @@ -598,8 +633,8 @@ int main(int argc, char **argv) saveBox(simuOut, args_info.outputParameter_arg); generateOutput(simuOut, args_info.axis_arg, args_info.output_arg); + delete preselector; - printf("Done!\n"); return 0; } diff --git a/c_tools/mock/generateMock.ggo b/c_tools/mock/generateMock.ggo index cd05c43..33aea77 100644 --- a/c_tools/mock/generateMock.ggo +++ b/c_tools/mock/generateMock.ggo @@ -33,3 +33,4 @@ option "subsample" - "Subsample the input simulation by the specified amount" do option "inputParameter" - "Input geometry (optional, warning!)" string optional option "gadgetUnit" - "Unit of length in gadget file in Mpc/h" double optional default="0.001" +option "subsample_seed" - "Seed for random number generation to select the subsample" int optional default="190524" \ No newline at end of file diff --git a/c_tools/mock/loaders/basic_loader.cpp b/c_tools/mock/loaders/basic_loader.cpp new file mode 100644 index 0000000..a58bb10 --- /dev/null +++ b/c_tools/mock/loaders/basic_loader.cpp @@ -0,0 +1,128 @@ +#include +#include +#include +#include +#include +#include +#include "simulation_loader.hpp" + +using namespace std; +using namespace CosmoTool; +using boost::format; +using boost::str; + +class BasicGroupLoader: public SimulationLoader +{ +private: + string storage; + SimuData *header; + int flags, numFiles; +public: + BasicGroupLoader(const string& storage_path, SimuData *header, int flags, int numfiles) + { + this->header = header; + this->storage = storage_path; + this->flags = flags; + this->numFiles = numfiles; + } + + SimuData *getHeader() { + return header; + } + + int num_files() { + return numFiles; + } + + SimuData *loadFile(int id) { + if (id < 0 || id >= numFiles) + return 0; + + SimuData *simu = new SimuData; + uint32_t *dimlist, dimrank; + string fname; + + simu->time = header->time; + simu->TotalNumPart = header->NumPart; + simu->Omega_M = header->Omega_M; + simu->Omega_Lambda = header->Omega_Lambda; + simu->NumPart = -1; + + if (flags & NEED_POSITION) + { + loadArray(str(format("%s/x_%d.nc") % storage % id), + simu->Pos[0], dimlist, dimrank); + assert(dimrank == 1); + simu->NumPart = dimlist[0]; + + loadArray(str(format("%s/y_%d.nc") % storage % id), + simu->Pos[1], dimlist, dimrank); + assert(dimrank == 1); + assert(simu->NumPart == dimlist[0]); + + loadArray(str(format("%s/z_%d.nc") % storage % id), + simu->Pos[2], dimlist, dimrank); + assert(dimrank == 1); + assert(simu->NumPart == dimlist[0]); + } + + if (flags & NEED_VELOCITY) + { + loadArray(str(format("%s/vx_%d.nc") % storage % id), + simu->Vel[0], dimlist, dimrank); + assert(dimrank == 1); + if (simu->NumPart < 0) + simu->NumPart = dimlist[0]; + + assert(simu->NumPart == dimlist[0]); + + loadArray(str(format("%s/vy_%d.nc") % storage % id), + simu->Vel[0], dimlist, dimrank); + assert(dimrank == 1); + assert(simu->NumPart == dimlist[0]); + + loadArray(str(format("%s/vz_%d.nc") % storage % id), + simu->Vel[2], dimlist, dimrank); + assert(dimrank == 1); + assert(simu->NumPart == dimlist[0]); + } + + if (flags & NEED_GADGET_ID) + { + loadArray(str(format("%s/id_%d.nc") % storage % id), + simu->Id, dimlist, dimrank); + assert(dimrank == 1); + if (simu->NumPart < 0) + simu->NumPart = dimlist[0]; + + assert(simu->NumPart == dimlist[0]); + } + + return simu; + } + + ~BasicGroupLoader() + { + delete header; + } +}; + +SimulationLoader *basicGroupLoader(const std::string& simupath, + int flags) +{ + SimuData *header; + ifstream f; + string header_path = simupath + "/header.txt"; + int numFiles; + + header = new SimuData; + f.open(header_path.c_str()); + + f >> header->time + >> header->Omega_M + >> header->Omega_Lambda + >> header->NumPart + >> numFiles; + + return new BasicGroupLoader(simupath, header, flags, numFiles); +} diff --git a/c_tools/mock/loaders/flash_loader.cpp b/c_tools/mock/loaders/flash_loader.cpp index 50e769f..70a7493 100644 --- a/c_tools/mock/loaders/flash_loader.cpp +++ b/c_tools/mock/loaders/flash_loader.cpp @@ -15,9 +15,10 @@ private: int _num_files; SimuData *gadget_header; string snapshot_name; + SimulationPreprocessor *preproc; public: - FlashLoader(const string& basename, SimuData *header, int flags, bool singleFile, int _num) - : snapshot_name(basename), load_flags(flags), onefile(singleFile), _num_files(_num), gadget_header(header) + FlashLoader(const string& basename, SimuData *header, int flags, bool singleFile, int _num, SimulationPreprocessor *p) + : snapshot_name(basename), load_flags(flags), onefile(singleFile), _num_files(_num), gadget_header(header), preproc(p) { } @@ -58,13 +59,14 @@ public: } applyTransformations(d); + basicPreprocessing(d, preproc); return d; } }; -SimulationLoader *flashLoader(const std::string& snapshot, int flags) +SimulationLoader *flashLoader(const std::string& snapshot, int flags, SimulationPreprocessor *p) { bool singleFile; int num_files; @@ -107,5 +109,5 @@ SimulationLoader *flashLoader(const std::string& snapshot, int flags) } } - return new FlashLoader(snapshot, header, flags, singleFile, num_files); + return new FlashLoader(snapshot, header, flags, singleFile, num_files, p); } diff --git a/c_tools/mock/loaders/gadget_loader.cpp b/c_tools/mock/loaders/gadget_loader.cpp index 906f6c1..ff7fd17 100644 --- a/c_tools/mock/loaders/gadget_loader.cpp +++ b/c_tools/mock/loaders/gadget_loader.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -16,9 +17,10 @@ private: double unitMpc; SimuData *gadget_header; string snapshot_name; + SimulationPreprocessor *preproc; public: - GadgetLoader(const string& basename, SimuData *header, int flags, bool singleFile, int _num, double unit) - : snapshot_name(basename), load_flags(flags), onefile(singleFile), _num_files(_num), unitMpc(1/unit), gadget_header(header) + GadgetLoader(const string& basename, SimuData *header, int flags, bool singleFile, int _num, double unit, SimulationPreprocessor *p) + : snapshot_name(basename), load_flags(flags), onefile(singleFile), _num_files(_num), unitMpc(1/unit), gadget_header(header), preproc(p) { } @@ -34,7 +36,7 @@ public: int num_files() { return _num_files; } - + SimuData *loadFile(int id) { SimuData *d; @@ -69,13 +71,14 @@ public: d->BoxSize *= unitMpc; applyTransformations(d); + basicPreprocessing(d, preproc); return d; } }; -SimulationLoader *gadgetLoader(const std::string& snapshot, double Mpc_unitLength, int flags) +SimulationLoader *gadgetLoader(const std::string& snapshot, double Mpc_unitLength, int flags, SimulationPreprocessor *p) { bool singleFile = false; int num_files; @@ -120,5 +123,5 @@ SimulationLoader *gadgetLoader(const std::string& snapshot, double Mpc_unitLengt } } - return new GadgetLoader(snapshot, header, flags, singleFile, num_files, Mpc_unitLength); + return new GadgetLoader(snapshot, header, flags, singleFile, num_files, Mpc_unitLength, p); } diff --git a/c_tools/mock/loaders/multidark_loader.cpp b/c_tools/mock/loaders/multidark_loader.cpp index 5047a5a..cffe086 100644 --- a/c_tools/mock/loaders/multidark_loader.cpp +++ b/c_tools/mock/loaders/multidark_loader.cpp @@ -14,9 +14,10 @@ class MultiDarkLoader: public SimulationLoader protected: SimuData *header; string darkname; + SimulationPreprocessor *preproc; public: - MultiDarkLoader(const std::string& name, SimuData *h) - : darkname(name), header(h) + MultiDarkLoader(const std::string& name, SimuData *h, SimulationPreprocessor *p) + : preproc(p), darkname(name), header(h) { } @@ -48,40 +49,59 @@ public: simu->TotalNumPart = simu->NumPart; simu->Omega_Lambda = 1.0 - simu->Omega_M; + long estimated = (preproc == 0) ? simu->NumPart : preproc->getEstimatedPostprocessed(simu->NumPart); + long allocated = estimated; + for (int k = 0; k < 3; k++) - simu->Pos[k] = new float[simu->NumPart]; - simu->Vel[2] = new float[simu->NumPart]; - simu->Id = new long[simu->NumPart]; - long *uniqueID = new long[simu->NumPart]; + simu->Pos[k] = new float[allocated]; + simu->Vel[2] = new float[allocated]; + simu->Id = new long[allocated]; + long *uniqueID = new long[allocated]; + long *index = new long[allocated]; + double tempData; simu->new_attribute("uniqueID", uniqueID, delete_adaptor); + simu->new_attribute("index", index, delete_adaptor); cout << "loading multidark particles" << endl; long actualNumPart = 0; + for (long i = 0; i < simu->NumPart; i++) { + SingleParticle p; - fp >> simu->Id[i] >> simu->Pos[0][i] >> simu->Pos[1][i] - >> simu->Pos[2][i] >> simu->Vel[2][i] >> tempData >> tempData; + fp >> p.ID >> p.Pos[0] >> p.Pos[1] + >> p.Pos[2] >> p.Vel[2] >> tempData >> tempData; - uniqueID[i] = simu->Id[i]; - - if (simu->Id[i] == -99 && - simu->Pos[0][i] == -99 && simu->Pos[1][i] == -99 && - simu->Pos[2][i] == -99 && simu->Vel[2][i] == -99) { + if (p.ID == -99 && + p.Pos[0] == -99 && p.Pos[1] == -99 && + p.Pos[2] == -99 && p.Vel[2] == -99) { break; - } else { - actualNumPart++; + + if (preproc != 0 && !preproc->accept(p)) + continue; + + copyParticleToSimu(p, simu, actualNumPart); + uniqueID[actualNumPart]= p.ID; + index[actualNumPart] = i; + actualNumPart++; + if (actualNumPart == allocated) + { + allocated += (estimated+9)/10; + reallocSimu(simu, allocated); + reallocArray(uniqueID, allocated, actualNumPart); + reallocArray(index, allocated, actualNumPart); + } } } - + applyTransformations(simu); simu->NumPart = actualNumPart; simu->TotalNumPart = actualNumPart; return simu; } }; -SimulationLoader *multidarkLoader(const string& multidarkname) +SimulationLoader *multidarkLoader(const string& multidarkname, SimulationPreprocessor *p) { SimuData *header; int actualNumPart; @@ -101,7 +121,7 @@ SimulationLoader *multidarkLoader(const string& multidarkname) header->TotalNumPart = header->NumPart; header->Omega_Lambda = 1.0 - header->Omega_M; - return new MultiDarkLoader(multidarkname, header); + return new MultiDarkLoader(multidarkname, header, p); } diff --git a/c_tools/mock/loaders/ramses_loader.cpp b/c_tools/mock/loaders/ramses_loader.cpp index 8f9fb37..f8f1fef 100644 --- a/c_tools/mock/loaders/ramses_loader.cpp +++ b/c_tools/mock/loaders/ramses_loader.cpp @@ -16,10 +16,11 @@ private: bool double_precision; SimuData *ramses_header; string snapshot_name; + SimulationPreprocessor *preproc; public: - RamsesLoader(const string& basename, int baseid, bool dp, SimuData *header, int flags, int _num) + RamsesLoader(const string& basename, int baseid, bool dp, SimuData *header, int flags, int _num, SimulationPreprocessor *p) : snapshot_name(basename), load_flags(flags), _num_files(_num), double_precision(dp), - ramses_header(header) + ramses_header(header), preproc(p) { } @@ -56,12 +57,13 @@ public: } applyTransformations(d); + basicPreprocessing(d, preproc); return d; } }; -SimulationLoader *ramsesLoader(const std::string& snapshot, int baseid, bool double_precision, int flags) +SimulationLoader *ramsesLoader(const std::string& snapshot, int baseid, bool double_precision, int flags, SimulationPreprocessor *p) { SimuData *d, *header; int num_files = 0; @@ -76,6 +78,6 @@ SimulationLoader *ramsesLoader(const std::string& snapshot, int baseid, bool dou delete d; } - return new RamsesLoader(snapshot, baseid, double_precision, header, flags, num_files); + return new RamsesLoader(snapshot, baseid, double_precision, header, flags, num_files, p); } diff --git a/c_tools/mock/loaders/sdf_loader.cpp b/c_tools/mock/loaders/sdf_loader.cpp new file mode 100644 index 0000000..4b0f8a5 --- /dev/null +++ b/c_tools/mock/loaders/sdf_loader.cpp @@ -0,0 +1,232 @@ +#include +#include +#include +#include +#include +#include "sdfloader_internal.hpp" +#include "simulation_loader.hpp" +#include +#include +#include +#include + +using boost::format; + +using namespace std; +using namespace CosmoTool; + +class SDFLoader: public SimulationLoader +{ +private: + int load_flags; + bool onefile; + int _num_files; + double unitMpc; + SimuData *sdf_header; + SDF *sdfp; + SimulationPreprocessor *preproc; + int num_splitting; +public: + SDFLoader(SDF *sdf_file, SimuData *header, int flags, int num_splitting, + SimulationPreprocessor *p) + : sdfp(sdf_file), load_flags(flags), + sdf_header(header), preproc(p) + { + this->num_splitting = num_splitting; + } + + ~SDFLoader() + { + delete sdf_header; + } + + SimuData *getHeader() { + return sdf_header; + } + + int num_files() { + return num_splitting; + } + + + int64_t getStart(int id) + { + return sdf_header->TotalNumPart * int64_t(id) / num_splitting; + } + + int64_t getNumberInSplit(int id) + { + return getStart(id+1)-getStart(id); + } + + void rescaleParticles(SimuData *d, + double rescale_position, + double rescale_velocity) + { + float shift = 0.5*d->BoxSize; + rescale_position /= d->time; + + if (d->Pos[0] != 0) + { + for (int k = 0; k < 3; k++) + { + for (int64_t i = 0; i < d->NumPart; i++) + { + d->Pos[k][i] = (d->Pos[k][i]*rescale_position + shift); + } + } + } + if (d->Vel[0] != 0) + { + for (int k = 0; k < 3; k++) + { + for (int64_t i = 0; i < d->NumPart; i++) + { + d->Vel[k][i] *= rescale_velocity; + } + } + } + } + + + SimuData *loadFile(int id) { + SimuData *d; + int64_t starts[7]; + int nobjs[7]; + int strides[7]; + void *addrs[7]; + const char *names[7]; + int ret; + + if (id >= num_splitting) + return 0; + + d = new SimuData; + *d = *sdf_header; + d->NumPart = getNumberInSplit(id); + + int64_t numPartToLoad = getNumberInSplit(id); + int64_t start = getStart(id); + int k = 0; +#define SETUP_READ(name, vec) \ + names[k] = name, starts[k] = start, nobjs[k] = numPartToLoad, strides[k] = sizeof(vec[0]), addrs[k] = vec, k++; + + if (load_flags & NEED_POSITION) + { + const char *name_template[3] = { "x", "y", "z" }; + for (int q = 0; q < 3; q++) + { + d->Pos[q] = new float[numPartToLoad]; + SETUP_READ(name_template[q], d->Pos[q]); + } + } + if (load_flags & NEED_VELOCITY) + { + const char *name_template[3] = { "x", "y", "z" }; + for (int q = 0; q < 3; q++) + { + d->Vel[q] = new float[numPartToLoad]; + SETUP_READ(name_template[q], d->Vel[q]); + } + } + if (load_flags & NEED_GADGET_ID) + { + d->Id = new long[numPartToLoad]; + SETUP_READ("ident", d->Id); + } +#undef SETUP_READ + + ret = SDFseekrdvecsarr(sdfp, k, (char**)names, starts, nobjs, addrs, strides); + if (ret != 0) + { + cerr << format("Splitting %d/%d, SDF read failure: %s") % id % num_splitting % SDFerrstring << endl; + abort(); + } + + if (load_flags & (NEED_POSITION | NEED_VELOCITY)) + rescaleParticles(d, 0.001*d->Hubble, one_kpc/one_Gyr); + + applyTransformations(d); + basicPreprocessing(d, preproc); + + return d; + } +}; + +SimulationLoader *sdfLoader(const std::string& snapshot, int flags, + int num_splitting, + SimulationPreprocessor *p) +{ + SDF *sdfp; + int fileversion; + SimuData *hdr; + int64_t gnobj; + + sdfp = SDFopen(0, snapshot.c_str()); + if (sdfp == 0) + { + return 0; + } + + SDFgetintOrDefault(sdfp, "version", &fileversion, 1); + if (fileversion == 1) + { + SDFgetfloatOrDie(sdfp, "Omega0", &hdr->Omega_M); + SDFgetfloatOrDie(sdfp, "Lambda_prime", &hdr->Omega_Lambda); + SDFgetfloatOrDie(sdfp, "H0", &hdr->Hubble); + } + else + { + float Or, Of; + SDFgetfloatOrDie(sdfp, "Omega0_m", &hdr->Omega_M); + SDFgetfloatOrDie(sdfp, "Omega0_lambda", &hdr->Omega_Lambda); + SDFgetfloatOrDie(sdfp, "Omega0_r", &Or); + SDFgetfloatOrDie(sdfp, "Omega0_fld", &Of); + + hdr->Omega_M += Or; + hdr->Omega_Lambda += Of; + SDFgetfloatOrDie(sdfp, "H0", &hdr->Hubble); + + } + double h0; + h0 = hdr->Hubble*10.0*(one_kpc/one_Gyr); + + if (SDFhasname("R0", sdfp)) + { + double R0; + + SDFgetdoubleOrDie(sdfp, "R0", &R0); + hdr->BoxSize = 2.0*0.001*R0*h0; + } + + if (SDFhasname("Rx", sdfp)) + { + double R0; + + SDFgetdoubleOrDie(sdfp, "Rx", &R0); + hdr->BoxSize = 2.0*0.001*R0*h0; + } + + if (SDFhasname("redshift", sdfp)) + { + double redshift; + + SDFgetdoubleOrDie(sdfp, "redshift", &redshift); + hdr->time = 1/(1+redshift); + } + + if (SDFgetint64(sdfp, "npart", &gnobj)) + { + gnobj = SDFnrecs("x", sdfp); + cerr << format("[Warning] No 'npart' found in SDF file '%s', guessing npart=%ld from SDFnrecs") % snapshot % gnobj << endl; + } + hdr->NumPart = hdr->TotalNumPart = gnobj; + + return new SDFLoader(sdfp, hdr, flags, num_splitting, p); +} + + +void sdfLoaderInit(int& argc, char **& argv) +{ + MPMY_Init(&argc, &argv); +} diff --git a/c_tools/mock/loaders/sdfloader_internal.hpp b/c_tools/mock/loaders/sdfloader_internal.hpp new file mode 100644 index 0000000..93635ac --- /dev/null +++ b/c_tools/mock/loaders/sdfloader_internal.hpp @@ -0,0 +1,6 @@ +#ifndef __VOID_SDF_LOADER_INTERNAL_HPP +#define __VOID_SDF_LOADER_INTERNAL_HPP + +void sdfLoaderInit(int& argc, char **&argv); + +#endif diff --git a/c_tools/mock/loaders/simulation_loader.cpp b/c_tools/mock/loaders/simulation_loader.cpp index 2f7515f..7751885 100644 --- a/c_tools/mock/loaders/simulation_loader.cpp +++ b/c_tools/mock/loaders/simulation_loader.cpp @@ -1,8 +1,37 @@ +#include #include #include "simulation_loader.hpp" +#ifdef SDF_SUPPORT +#include "sdfloader_internal.hpp" +#endif +using std::min; using namespace CosmoTool; +template void reallocArray(T *& a, long newSize, long toCopy) +{ + T *b = new T[newSize]; + if (a != 0) + { + memcpy(b, a, sizeof(T)*toCopy); + delete[] a; + } + a = b; +} + +void SimulationLoader::reallocSimu(SimuData *s, long newNumPart) +{ + long to_copy = min(newNumPart, s->NumPart); + + for (int j = 0; j < 3; j++) + { + reallocArray(s->Pos[j], newNumPart, to_copy); + reallocArray(s->Vel[j], newNumPart, to_copy); + } + reallocArray(s->Id, newNumPart, to_copy); + reallocArray(s->type, newNumPart, to_copy); +} + void SimulationLoader::applyTransformations(SimuData *s) { float redshift_gravity = do_redshift ? 1.0 : 0.0; @@ -13,3 +42,45 @@ void SimulationLoader::applyTransformations(SimuData *s) redshift_gravity*s->Vel[redshift_axis][i]/100.; } } + + +void SimulationLoader::basicPreprocessing(SimuData *d, + SimulationPreprocessor *preproc) +{ + if (preproc == 0) + return; + + long numAccepted = 0; + bool *accepted = new bool[d->NumPart]; + for (long i = 0; i < d->NumPart; i++) + { + SingleParticle p; + + for (int k = 0; k < 3; k++) + { + p.Pos[k] = (d->Pos[k]) ? 0 : d->Pos[k][i]; + p.Vel[k] = (d->Vel[k]) ? 0 : d->Vel[k][i]; + } + p.ID = (d->Id) ? 0 : d->Id[i]; + + accepted[i] = preproc->accept(p); + numAccepted += accepted[i]; + } + + for (int k = 0; k < 3; k++) + { + filteredCopy(d->Pos[k], accepted, d->NumPart); + filteredCopy(d->Vel[k], accepted, d->NumPart); + } + filteredCopy(d->Id, accepted, d->NumPart); + filteredCopy(d->type, accepted, d->NumPart); + d->NumPart = numAccepted; + delete[] accepted; +} + +void simulationLoadersInit(int& argc, char **& argv) +{ +#ifdef SDF_SUPPORT + sdfLoaderInit(argc, argv); +#endif +} diff --git a/c_tools/mock/loaders/simulation_loader.hpp b/c_tools/mock/loaders/simulation_loader.hpp index d96cb47..e0d79cb 100644 --- a/c_tools/mock/loaders/simulation_loader.hpp +++ b/c_tools/mock/loaders/simulation_loader.hpp @@ -2,8 +2,28 @@ #define _MOCK_SIMULATION_LOADER_HPP #include +#include #include +struct SingleParticle +{ + float Pos[3]; + float Vel[3]; + long Index; + long ID; +}; + +class SimulationPreprocessor +{ +public: + SimulationPreprocessor() {} + virtual ~SimulationPreprocessor() {} + + virtual long getEstimatedPostprocessed(long numParticles) { return numParticles; }; + virtual bool accept(const SingleParticle& p) { return true; } + virtual void reset() {} +}; + class SimulationLoader { protected: @@ -15,9 +35,39 @@ protected: do_redshift = false; redshift_axis = 2; } + + template void reallocArray(T *& a, long newSize, long toCopy) + { + T *b = new T[newSize]; + if (a != 0) + { + std::copy(a, a+toCopy, b); + delete[] a; + } + a = b; + } + + + + void reallocSimu(CosmoTool::SimuData *s, long newNumPart); + + void basicPreprocessing(CosmoTool::SimuData *d, SimulationPreprocessor *preproc); void applyTransformations(CosmoTool::SimuData *s); + void copyParticleToSimu(const SingleParticle& p, CosmoTool::SimuData *s, long index) + { + s->Pos[0][index] = p.Pos[0]; + s->Pos[1][index] = p.Pos[1]; + s->Pos[2][index] = p.Pos[2]; + if (s->Vel[0]) + s->Vel[0][index] = p.Vel[0]; + if (s->Vel[1]) + s->Vel[1][index] = p.Vel[1]; + if (s->Vel[2]) + s->Vel[2][index] = p.Vel[2]; + s->Id[index] = p.ID; + } public: virtual ~SimulationLoader() {} @@ -28,8 +78,31 @@ public: virtual int num_files() = 0; virtual CosmoTool::SimuData* loadFile(int id) = 0; + + template + void filteredCopy(T *a, bool *accepted, long N) + { + long i = 0, j = 0; + + if (a == 0) + return; + + while (i < N) + { + if (!accepted[i]) + { + i++; + continue; + } + + a[j] = a[i]; + j++; + i++; + } + } }; + template void delete_adaptor(void *ptr) { @@ -40,10 +113,13 @@ void delete_adaptor(void *ptr) // Unit length is the size of one Mpc in the simulation units -SimulationLoader *gadgetLoader(const std::string& snapshot, double Mpc_unitLength, int flags); -SimulationLoader *flashLoader(const std::string& snapshot, int flags); -SimulationLoader *multidarkLoader(const std::string& snapshot); -SimulationLoader *ramsesLoader(const std::string& snapshot, int baseid, bool double_precision, int flags); +SimulationLoader *gadgetLoader(const std::string& snapshot, double Mpc_unitLength, int flags, SimulationPreprocessor *p); +SimulationLoader *flashLoader(const std::string& snapshot, int flags, SimulationPreprocessor *p); +SimulationLoader *multidarkLoader(const std::string& snapshot, SimulationPreprocessor *p); +SimulationLoader *ramsesLoader(const std::string& snapshot, int baseid, bool double_precision, int flags, SimulationPreprocessor *p); +SimulationLoader *sdfLoader(const std::string& snapshot, int flags, int num_splitting, SimulationPreprocessor *p); +/* This is required for some parallel I/O handler (thus MPI beneath it) */ +void simulationLoadersInit(int& argc, char **& argv); #endif diff --git a/external/cosmotool/src/fourier/details/healpix_utility.hpp b/external/cosmotool/src/fourier/details/healpix_utility.hpp index d989dd8..cf501d6 100644 --- a/external/cosmotool/src/fourier/details/healpix_utility.hpp +++ b/external/cosmotool/src/fourier/details/healpix_utility.hpp @@ -52,7 +52,7 @@ namespace CosmoTool HealpixSpectrum *new_spectrum = new HealpixSpectrum(in_spec.Lmax()); T *out_d = new_spectrum->data(); - std::copy(data, data + min(size,new_spectrum->size()), out_d); + std::copy(data, data + std::min(size,new_spectrum->size()), out_d); return Spectrum_ptr(new_spectrum); } diff --git a/external/external_build.cmake b/external/external_build.cmake index 8cfb26d..029f429 100644 --- a/external/external_build.cmake +++ b/external/external_build.cmake @@ -1,6 +1,7 @@ include(FindOpenMP) OPTION(ENABLE_OPENMP "Set to Yes if Healpix and/or you need openMP" OFF) +OPTION(SDF_SUPPORT "Set to Yes to activate support for SDF" OFF) IF(ENABLE_OPENMP) @@ -76,7 +77,7 @@ if (INTERNAL_GENGETOPT) CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} BUILD_IN_SOURCE 1 - INSTALL_COMMAND make install + INSTALL_COMMAND ${CMAKE_MAKE_PROGRAM} install ) SET(GENGETOPT ${GENGETOPT_BIN_DIR}/bin/gengetopt CACHE FILEPATH "Path GenGetOpt binary") else(INTERNAL_GENGETOPT) @@ -100,7 +101,7 @@ if (INTERNAL_HDF5) CPPFLAGS=${CONFIGURE_CPP_FLAGS} CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} BUILD_IN_SOURCE 1 - INSTALL_COMMAND make install + INSTALL_COMMAND ${CMAKE_MAKE_PROGRAM} install ) SET(cosmotool_DEPS ${cosmotool_DEPS} hdf5) SET(hdf5_built hdf5) @@ -144,7 +145,7 @@ if (INTERNAL_NETCDF) --disable-examples ${EXTRA_NC_FLAGS} CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} BUILD_IN_SOURCE 1 - INSTALL_COMMAND make install + INSTALL_COMMAND ${CMAKE_MAKE_PROGRAM} install ) SET(CONFIGURE_CPP_LDFLAGS "${CONFIGURE_LDFLAGS}") SET(EXTRA_NC_FLAGS CPPFLAGS=${CONFIGURE_CPP_FLAGS} LDFLAGS=${CONFIGURE_CPP_LDFLAGS}) @@ -198,8 +199,8 @@ IF(INTERNAL_GSL) --with-pic --libdir=${CMAKE_BINARY_DIR}/ext_build/gsl/lib CPPFLAGS=${CONFIGURE_CPP_FLAGS} CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} BUILD_IN_SOURCE 1 - BUILD_COMMAND make - INSTALL_COMMAND make install + BUILD_COMMAND ${CMAKE_MAKE_PROGRAM} + INSTALL_COMMAND ${CMAKE_MAKE_PROGRAM} install ) SET(GSL_INTERNAL_LIBS ${CMAKE_BINARY_DIR}/ext_build/gsl/lib) SET(GSL_LIBRARY ${GSL_INTERNAL_LIBS}/libgsl.a CACHE STRING "GSL internal path" FORCE) @@ -249,9 +250,9 @@ ExternalProject_Add(cfitsio CPPFLAGS=${CONFIGURE_CPP_FLAGS} CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} - BUILD_COMMAND make + BUILD_COMMAND ${CMAKE_MAKE_PROGRAM} BUILD_IN_SOURCE 1 - INSTALL_COMMAND make install + INSTALL_COMMAND ${CMAKE_MAKE_PROGRAM} install ) SET(CFITSIO_PREFIX ${CMAKE_BINARY_DIR}/ext_build/cfitsio) SET(CFITSIO_LIBRARY ${CFITSIO_PREFIX}/lib/libcfitsio.a) @@ -266,7 +267,7 @@ ExternalProject_Add(healpix PREFIX ${BUILD_PREFIX}/healpix-prefix SOURCE_DIR ${CMAKE_SOURCE_DIR}/external/healpix CONFIGURE_COMMAND echo No configure - BUILD_COMMAND make + BUILD_COMMAND ${CMAKE_MAKE_PROGRAM} HEALPIX_TARGET=sampler HEALPIX_CC=${CMAKE_C_COMPILER} HEALPIX_CXX=${CMAKE_CXX_COMPILER} @@ -315,9 +316,28 @@ endif(INTERNAL_QHULL) SET(QHULL_LIBRARIES ${QHULL_CPP_LIBRARY} ${QHULL_LIBRARY} ) + +############### +# Build libSDF +############### +IF(SDF_SUPPORT) + SET(LIBSDF_ARCH x86_64) + SET(LIBSDF_PATH ${CMAKE_SOURCE_DIR}/external/libsdf) + + ExternalProject_Add(libSDF + PREFIX ${BUILD_PREFIX}/libSDF-prefix + SOURCE_DIR ${LIBSDF_PATH} + CONFIGURE_COMMAND echo No configure + BUILD_COMMAND ${CMAKE_MAKE_PROGRAM} ARCH=${LIBSDF_ARCH} + INSTALL_COMMAND echo No install + BUILD_IN_SOURCE 1 + ) + SET(LIBSDF_INCLUDE_PATH ${LIBSDF_PATH}/include) + SET(LIBSDF_LIBRARY ${LIBSDF_PATH}/Objfiles/${LIBSDF_ARCH}/libsw.a) +ENDIF(SDF_SUPPORT) + include_directories(${CMAKE_BINARY_DIR}/src ${NETCDF_INCLUDE_PATH} ${GSL_INCLUDE_PATH} ${HDF5_INCLUDE_PATH} ${COSMOTOOL_INCLUDE_PATH} ${Boost_INCLUDE_DIRS} - ${QHULL_INCLUDE_PATH}) - + ${QHULL_INCLUDE_PATH} ${LIBSDF_INCLUDE_PATH}) diff --git a/external/libsdf/GNUmakefile b/external/libsdf/GNUmakefile new file mode 100644 index 0000000..0997fee --- /dev/null +++ b/external/libsdf/GNUmakefile @@ -0,0 +1,34 @@ +tarname:=tree19 +ARCH=x86_64 + +# Make.$(ARCH) sets many of the variables that are then used in +# Make.generic. Leaving it out can cause problems, for example, +# Make.$(ARCH) wants to redefine 'TAR'. On the other hand, leaving +# it in can cause problems (apparently) with older versions of GNUmake +# because, e.g., assignements like LOADLIBES:=-foo $(LOADLIBES) get +# 'executed' multiple times. Once in this Makefile, and once in the +# daughter makefiles. + +###include Make-common/Make.$(ARCH) + +# we should also go into SDFcvt, SDF2fld, commtst, lsv, lsvtst, (anything +# else?) and build them. Possibly under a different target? + +all: All + +# Make.generic has targets for clean, all, etc., so we need to +# spell them a little differently in this file... +include Make-common/Make.generic + +subdirs:= libSDF libmpmy + +All: + for dir in $(subdirs); do (cd $$dir; $(MAKE) ARCH=$(ARCH) all); done + +Depends : + for dir in $(subdirs); do (cd $$dir; $(MAKE) ARCH=$(ARCH) depends); done + +Clean : + for dir in $(subdirs); do (cd $$dir; $(MAKE) ARCH=$(ARCH) clean); done + +# $(treedir) diff --git a/external/libsdf/Make-common/Make.default b/external/libsdf/Make-common/Make.default new file mode 100644 index 0000000..d2460ef --- /dev/null +++ b/external/libsdf/Make-common/Make.default @@ -0,0 +1,87 @@ +# You can override the specification of any of these variables with +# make command line arguments. Those that should not be completely +# replaced require the "override" modifier. + +# You can further modify these values in the Make.$(ARCH) files + +ifndef defaultPAROS +defaultPAROS:=seq +endif + +ifndef defaultCC +defaultCC:=cc +endif + +ifndef defaultFC +defaultFC:=g77 +endif + +ifndef OPTIMIZE +OPTIMIZE:=-O2 +CC_SPECIFIC:=$(CC_SPECIFIC) -g -Wall +endif + +ifndef FOPTIMIZE +OPTIMIZE=-O +endif + +PAROS:=$(defaultPAROS) +CC:=$(defaultCC) +FC:=$(defaultFC) + +ifneq ($(PAROS),$(defaultPAROS)) +PAROSsuf:=-$(PAROS) +endif + +# Put a non-default CC into ARCH +ifneq ($(defaultCC),$(CC)) +override ARCH:=$(ARCH)-$(CC) +endif + +ifeq ($(FC),g77) +OPTIMIZE:=-O2 +FC_SPECIFIC:=$(FC_SPECIFIC) -g -ffast-math +endif + +# Some compilers turn off optimization with -g, so we don't specify +# -g by default on those machines. +ifdef DEBUG +override ARCH:=$(ARCH)-g +OPTIMIZE:= +endif + +# i.e., specify PROFILE=-p or PROFILE=-pg +ifdef PROFILE +override ARCH:=$(ARCH)-p +endif + +ifeq ($(PAROS),pvm) +PAROSCFLAGS:=-I$(PVM_ROOT)/include +LOADLIBES:=$(LOADLIBES) $(PVM_ROOT)/lib/$(PVM_ARCH)/libpvm3.a +endif + +ifeq ($(EXTRALIB),efence) +PRELIBS:=$(treedir)/Objfiles/$(ARCH)/libefence.a +programname:=$(programname)-efence +endif + +ifndef ARFLAGS +ARFLAGS:=r +endif + +ifndef RANLIB +RANLIB:=@echo no ranlib +endif + +ifdef fsrc +LD:=$(FC) +else +LD:=$(CC) +endif +objsuf:=.o +libext:=.a + +CFLAGS:=$(DEBUG) $(OPTIMIZE) $(PROFILE) $(CC_SPECIFIC) $(ARCH_SPECIFIC) +FFLAGS:=$(DEBUG) $(FOPTIMIZE) $(PROFILE) $(FC_SPECIFIC) $(ARCH_SPECIFIC) +LDFLAGS:=$(DEBUG) $(PROFILE) $(LDFLAGS) + diff --git a/external/libsdf/Make-common/Make.generic b/external/libsdf/Make-common/Make.generic new file mode 100644 index 0000000..c23a12c --- /dev/null +++ b/external/libsdf/Make-common/Make.generic @@ -0,0 +1,217 @@ +## This is a 'generic' makefile with all the stuff that we seem to +## repeat over and over in all our application (and library!) Makefiles. + +incdir=$(treedir)/include/libsdf +objdir=Objfiles/$(ARCH) +libdir=$(treedir)/Objfiles/$(ARCH) +override CFLAGS:=-I$(incdir) $(CFLAGS) $(EXTRACFLAGS) +override LDFLAGS:=$(LDFLAGS) $(EXTRALDFLAGS) +ifndef tarname +tarname:=$(programname) +endif +tarpath:=$(TARPREFIX)$(tarname) +excludepath:=$(TARPREFIX)exclude + +# Allow the local directory to do arch-specific stuff... +localmake:=$(wildcard Make.$(ARCH)) +ifneq ($(localmake),) +include $(localmake) +endif + +ifeq ($(PAROS),$(defaultPAROS)) +# we don't need mpmy if we are using the default PAROS! +LIBDEPENDS=$(libdir)/libsw.a +else +LIBDEPENDS=$(libdir)/mpmy_$(PAROS)$(objsuf) \ + $(libdir)/libsw.a +endif + +# If we're going to the trouble to list out the full directory names +# in LIBDEPENDS, there's not much point in making the linker figure them +# out (possibly erroneously) again with -L... -l... +LOADLIBES_:=$(PRELIBS) $(LIBDEPENDS) -L$(libdir) -lm $(POSTLIBS) $(LOADLIBES) + +ifdef programname +bin:=$(programname).$(ARCH)$(PAROSsuf) +# Substitue for the string PAROS in the 'src' variable +# It would be really nice if we could then check to make sure the +# file exists, and if not, substitue with, e.g., "generic". But +# I can't figure out how to do that. +_src:=$(subst PAROS,$(PAROS),$(src)) +obj=$(patsubst %.c,$(objdir)/%$(objsuf),$(src)) \ + $(patsubst %.cu,$(objdir)/%$(objsuf),$(cusrc)) \ + $(patsubst %.f,$(objdir)/%$(objsuf),$(fsrc)) +ifndef special_rule_for_all +all: $(bin) +endif + +$(bin) : $(objdir) $(obj) $(LIBDEPENDS) + $(LD) $(LDFLAGS) -o $@ $(obj) $(LOADLIBES_) + $(finishlink) + +release : $(bin) + rsync -abq $(bin) ../release +else +bin:= +endif + +ifdef libname +lib:=$(libdir)/$(libname)$(libext) +libobj=$(patsubst %.c,$(lib)($(objdir)/%$(objsuf)),$(src)) +ifeq ($(libname),libsw) +libobj:=$(libobj) $(patsubst %.c,$(lib)($(objdir)/%$(objsuf)),$(swsrc)) \ + $(patsubst %.s,$(lib)($(objdir)/%$(objsuf)),$(asmsrc)) \ + $(patsubst %.S,$(lib)($(objdir)/%$(objsuf)),$(cppasmsrc)) +endif +ifndef special_rule_for_all +all: $(lib) +endif + + +$(lib) : $(objdir) $(libdir) $(libobj) + $(RANLIB) $@ + +endif + +$(objdir)/%$(objsuf) : %.c + $(CC) $(CFLAGS) -c $< + -@mv $*$(objsuf) $@ + +$(objdir)/%$(objsuf) : %.cu + $(CUDACC) $(CUDACFLAGS) -c $< + -@mv $*$(objsuf) $@ + +$(objdir)/%$(objsuf) : %.f + $(FC) $(FFLAGS) -c $< + -@mv $*$(objsuf) $@ + +$(objdir)/%$(objsuf) : $(asmdir)/%.s + (cd $(asmdir); $(AS) $(ASFLAGS) -o $*$(objsuf) $*.s) + -@mv $(asmdir)/$*$(objsuf) $@ + +$(objdir)/%$(objsuf) : $(asmdir)/%.S + (cd $(asmdir); $(CC) $(ASFLAGS) -c -o $*$(objsuf) $*.S) + -@mv $(asmdir)/$*$(objsuf) $@ + +# Gnu tar doesn't seem to do -X exclude properly?? It's probably +# because it uses names without a leading './'. I could add a sed to +# double each line in exclude??? +ifndef TAR +TAR=/bin/tar +endif + +ifndef FIND +FIND=/usr/bin/find +endif + +MAKEDEPEND=makedepend + +ifndef RANLIB +RANLIB=/usr/bin/ranlib +endif + +$(objdir) : + if [ ! -d Objfiles ]; then mkdir Objfiles; fi + if [ ! -d $(objdir) ]; then mkdir $(objdir); fi + +$(libdir) : + if [ ! -d $(treedir)/Objfiles ]; then mkdir $(treedir)/Objfiles; fi + if [ ! -d $(libdir) ]; then mkdir $(libdir); fi + +# Use appexcludes to exclude any particular application-specific directories. +# e.g., +# appexcludes="-name data -prune -o -name secret_dir -prune" +ifdef appexcludes +extraexcludes=\( $(appexcludes) \) -o +endif + +ifndef treedir_sed +treedir_sed:=$(treedir) +endif + +# Exclude emacs backups (*~), and auto-saves (#*#) +# Exclude anything in one of the object dirs, or misc.*, +# anything named 'core' or *.tar.* or anything that's executable and +# bigger than 10k or anything at all that's bigger than 100k. +# In addition, just in case they don't exist yet, we have to explicitly +# exclude the $(tarname).tar.Z and .gz targets. +# Finally exclude the "proprietary" ibm assembly language +$(excludepath) : FORCE + ($(FIND) . $(extraexcludes) -name Objfiles -prune -o -name '*.o' -o -name '#*#' -o -name '*~' -o -name '*-' -o -name '*.bak' -o -name '*.bak2' -o -name Obsolete -o -name NOT_PORTED -o -name '*.orig' -o -name core -o -name 'lsv.core.*' -o -name 'misc.*' -o -name '*.tar.*' -o -name '*gz' -o \( -perm +0111 -and -size +10k \) -o -size +100k -o -name '*readrtc.s*' ; \ + echo ./$(tarname).tar.Z ; \ + echo ./$(tarname).tgz ; \ + echo ./$(tarname)-dist.tgz ; \ + ) | sed "s/^\.\//`basename $$PWD`\//" > $@ + +tar : $(tarpath).tgz + +dist : $(tarpath)-dist.tgz + +$(tarpath).tar.Z: $(excludepath) + (dir=`basename $$PWD`; cd `dirname $$PWD`; $(TAR) cvfX - $$dir/$(excludepath) $$dir)| compress > $(tarpath).tar.Z + +$(tarpath).tgz: $(excludepath) + (dir=`basename $$PWD`; cd `dirname $$PWD`; $(TAR) cvfX - $$dir/$(excludepath) $$dir)| gzip > $(tarpath).tgz + +$(tarpath)-dist.tgz: $(excludepath) + (dir=`basename $$PWD`; cd `dirname $$PWD`; $(TAR) cvfX - $$dir/$(excludepath) $$dir/COPY* $$dir/Make-common $$dir/INSTRUCTIONS $$dir/GNUmakefile $$dir/include $$dir/relerr $$dir/Change* $$dir/lib* $$dir/bin $$dir/lsv $$dir/shmz $$dir/snsph $$dir/nln)| gzip > $(tarpath)-dist.tgz + +# Make a floppy by writing a meta-tar file containing $(tarname).tgz +floppy: $(tarname).tgz + $(TAR) cvf /dev/fd0 $(tarname).tgz + +# clean...how much should we attempt to clean up?? Should there be +# additional clean-ables set in the application-makefile? + +# clean-clutter will remove the ~ files, the #*#, etc. +clean-clutter: FORCE + rm -f *~ #*# *.bak *.bakk + +# clean will remove the binary and object files associated with the +# current ARCH-PAROS pair +clean: FORCE clean-clutter + rm $(bin) $(objdir)/* + +# clean-all will attempt to remove all object files in Objfiles/ and +# all executables in . associated with them. USE WITH CARE!! +clean-all: FORCE clean-clutter + for dir in `ls Objfiles`; do \ + set arch=`basename $$dir`; \ + rm -rf Objfiles/$$dir; \ + rm -f $(programname).$$dir* ; \ + done + +# Run makedepend, and then massage the Makfile to the symbolic names +# for the files in $(treedir). WARNING! If $(treedir) contains +# sed meta-characters you lose in a big way! We fix this by letting you +# override it with $(treedir_sed), e.g., if treedir=.., you should +# probably set treedir_sed=\.\. . This should be automatic :-(. +# This command kills the entire line with the /usr/ dependency. +# -e '/ \/usr/d' Makefile.bak2 > foo +# The sed below leaves lines with no dependency. Is that a problem? +MAKEFILENAME=GNUmakefile +#depends: +# $(MAKEDEPEND) -f$(MAKEFILENAME) '-o$$(objsuf)' '-p$$(objdir)/' -- $(CFLAGS) -- $(src) +# cp $(MAKEFILENAME) $(MAKEFILENAME).bak2 +# sed \ +# -e '/DO NOT DELETE/,$$s!$(treedir_sed)!$$(treedir)!g'\ +# -e '/DO NOT DELETE/,$$s@ /usr/[^ ]*@@g'\ +# $(MAKEFILENAME).bak2 > $(MAKEFILENAME) + +# The last rule replaces -p$$(objdir)/ which doesn't work in openwin +# and presumably in X11R4 or earlier +depends: + $(MAKEDEPEND) -f$(MAKEFILENAME) '-o$$(objsuf)' -- $(CFLAGS) -- $(src) + cp $(MAKEFILENAME) $(MAKEFILENAME).bak2 + sed \ + -e '/DO NOT DELETE/,$$s!$(treedir_sed)!$$(treedir)!g'\ + -e '/DO NOT DELETE/,$$s@ /usr/[^ ]*@@g'\ + -e '/DO NOT DELETE/,$$s@ float.h@@g'\ + -e '/DO NOT DELETE/,$$s@ stdarg.h@@g'\ + -e '/DO NOT DELETE/,$$s@^\([A-Za-z]\)@$$(objdir)/\1@g'\ + $(MAKEFILENAME).bak2 > $(MAKEFILENAME) + +depends-nosed: + $(MAKEDEPEND) -f$(MAKEFILENAME) '-o$$(objsuf)' '-p$$(objdir)/' -- $(CFLAGS) -- $(src) + +FORCE: diff --git a/external/libsdf/Make-common/Make.x86_64 b/external/libsdf/Make-common/Make.x86_64 new file mode 100644 index 0000000..be62088 --- /dev/null +++ b/external/libsdf/Make-common/Make.x86_64 @@ -0,0 +1,25 @@ +defaultCC:=gcc + +CC_SPECIFIC:=-g -Wall +ARCH_SPECIFIC:=-D__iX86__=x86_64 -DLONG_NK1_KEY -DSTK_FORCE_ALIGNMENT=4 -D_FILE_OFFSET_BITS=64 -DUSE_SYSTEM_MALLOC -DUSE_MPIIO -DUSE_HWCLOCK -DPROCS_PER_NODE=8 +OPTIMIZE=-O2 +AGGRESSIVE_OPT=-Ofast +LDFLAGS=-g +LEX:=flex +YACC:=bison -y + +include $(treedir)/Make-common/Make.default + +swsrc:=lsv.c swampi.c +asmdir:=asm-sse +asmsrc= +cppasmsrc= + +LOADLIBES=-lrt + +MPI_ROOT=/softs/openmpi/1.6.4-ifort-13.0-torque-CentOS5 +ifeq ($(PAROS),mpi) +LOADLIBES:=-L$(MPI_ROOT)/lib -L$(MPI_ROOT)/lib64 -lmpi +PAROSCFLAGS:=-I$(MPI_ROOT)/include +endif + diff --git a/external/libsdf/_NOTES_ b/external/libsdf/_NOTES_ new file mode 100644 index 0000000..f7fd449 --- /dev/null +++ b/external/libsdf/_NOTES_ @@ -0,0 +1 @@ +This is Tree19, a snapshot of some of Michael S. Warren's code to handle SDF data format and parallel IO. diff --git a/external/libsdf/include/libsdf/Assert.h b/external/libsdf/include/libsdf/Assert.h new file mode 100644 index 0000000..8714b57 --- /dev/null +++ b/external/libsdf/include/libsdf/Assert.h @@ -0,0 +1,23 @@ +/* A drop-in replacement for assert.h, but it calls "error" which */ +/* deposits a message in the msgbuf, the terminal, your home answering */ +/* machine, and in skywriting at Malibu beach. */ +#undef assert +# ifndef NDEBUG +/* Error may be #defined */ +#include "error.h" + +#ifndef NO_STRINGIFICATION +# define assert(ex) ((void)((ex)?0 :\ + ((SWError)("Assertion (%s) failed: file \"%s\", line %d\n",\ + #ex, __FILE__, __LINE__),0))) +#else +/* Not only do we not have Stringification, but we assume that we have */ +/* the brain-damaged macro substitution into "..." */ +/* Note that this breaks if the substituted string has " " in it!, e.g. + assert(SDFhasname("x", sdfp)); +*/ +# define assert(ex) ((void)((ex)?0 : ((SWError)("Assertion (%s) failed: file \"%s\", line %d\n", "ex", __FILE__, __LINE__), 0))) +#endif /* NO_STRINGIFICATION */ +# else +# define assert(ex) ((void)0) +# endif diff --git a/external/libsdf/include/libsdf/Malloc.h b/external/libsdf/include/libsdf/Malloc.h new file mode 100644 index 0000000..4347806 --- /dev/null +++ b/external/libsdf/include/libsdf/Malloc.h @@ -0,0 +1,37 @@ +#ifndef _MAlloCDOTh +#define _MAlloCDOTh + +#include +#include "error.h" + +#ifdef __cplusplus +extern "C"{ +#endif +/* Set the default behavior of the Malloc family when encountering */ +/* errors, e.g., NULL returns, etc. */ +Error_t MallocHandler(Error_t); + +void xFree (void *ptr, const char *file, int lineno); +void *xMalloc (size_t, const char *file, int lineno); +void *xRealloc (void *ptr, size_t, const char *file, int lineno); +void *xCalloc (size_t, size_t, const char *file, int lineno); +/* No extra parens needed ?? */ +void Free_f (void *ptr); +void *Malloc_f (size_t); +void *Realloc_f (void *ptr, size_t); +void *Calloc_f (size_t, size_t); +#ifdef __cplusplus +} +#endif +/* Some pre-processors are so stupid that they will convert + foo(Realloc); +into + foo(xRealloc(,,__FILE__, __LINE__)); +Thus, we can't use Realloc as function name. +*/ +#define Free(p) xFree(p, __FILE__, __LINE__) +#define Malloc(n) xMalloc(n, __FILE__, __LINE__) +#define Calloc(n,s) xCalloc(n, s, __FILE__, __LINE__) +#define Realloc(p, n) xRealloc(p, n, __FILE__, __LINE__) + +#endif /* _MAllocDOTh */ diff --git a/external/libsdf/include/libsdf/Msgs.h b/external/libsdf/include/libsdf/Msgs.h new file mode 100644 index 0000000..493e8ce --- /dev/null +++ b/external/libsdf/include/libsdf/Msgs.h @@ -0,0 +1,88 @@ +/* Declarations for the functions defined in Msgs.c */ +#ifndef MsgsDOTh +#define MsgsDOTh +#include + +#include "gccextensions.h" + +/* These two typedefs simplify the task of casting function ptrs */ +/* to the appropriate type when calling Msg_addfile */ +typedef int (*Msgvfprintf_t)(void *, const char *, va_list); +typedef int (*Msgfflush_t)(void *); + +#ifdef __cplusplus +extern "C" { +#endif +/* The fflush_like function pointer MUST BE ASYNCHRONOUSLY CALLABLE */ +/* If you don't have one, don't worry. Pass NULL instead. */ +int Msg_addfile(void *fp, /* add fp to the list of msg files */ + int (*vfprintf_like)(void *, const char *, va_list), + int (*fflush_like)(void *)); +int Msg_delfile(void *fp); /* fp should no longer receive msgs */ +int Msg_on(const char *); /* turn on a specific type of msgs */ +int Msg_off(const char *); /* turn off a specific type of msgs */ +/* Normally, you should use the Msg_test macro instead. */ +int _Msg_test(const char *); /* is a specific type on or off? */ +int Msg_set_enable(int); /* enable (1) or disable (0) all message */ + /* return the previous state. */ +void Msg_turnon(const char *msg_turn_on); /* an interface to Msg_on */ + /* that calls Msg_on for every file */ + /* in a comma-whitespace delimited list */ + /* of names. If a name is specified as */ + /* NAME:lo-hi or NAME:procnum, then */ + /* messages are on only in the corresponding */ + /* processors. If the string is "nomsgs", */ + /* then msgs are totally disabled. */ +void MsgdirInit(const char *path); /* tries to do a mkdir and open */ + /* msg files for each process */ +int Msg_do(const char *fmt, ...) /* Unconditionally say something. */ + __attribute__ ((format (printf, 1, 2))) ; /* it's printf-like! */ +int Msg_doalist(const char *fmt, va_list) +/* this is broken in gcc2.4.0 through 2.4.4 */ +#ifndef BROKEN_GCC_FORMAT_ATTRIBUTE + __attribute__ ((format (printf, 1, 0))) +#endif + ; + +int Msg_flush(void); /* flush all the buffers now. */ +int Msg_flushalways(int newval);/* flush buffers after every Msg_do. + return the previous value.*/ +#ifdef __cplusplus +} +#endif + +/* Don't use these! _Msg_enabled */ +extern int _Msg_enabled; + +/* Msg is called with an extra set of parentheses, to hide */ +/* the variadic arguments, e.g. + Msg("foo", ("Hello world this is a \"foo\" message\n")); +or + Msg(__FILE__, ("Hello from file: %s, line: %d\n", __FILE__, __LINE__)); + +The macro 'Msgf' is a shorthand for the Msg(__FILE__, ...) construction. +The macro 'Msglno' is a shorthand for: + Msg(name, "%s(%d):" , __FILE__, __LINE__, ); +The macro 'Msgfunc' is a shorthand for Msg(__FUNCTION__, ...). + Thus, you can turn on messaging at the function level. +*/ + +#define Msglno(name, args) Msg(name, ("%s(%d): ", __FILE__, __LINE__)),Msg(name, args) +#define Msgf(args) Msg(__FILE__, args) +#define Msglnof(args) Msglno(__FILE__, args) +#ifdef __FUNCTION__ +#define Msgfunc(args) Msg(__FUNCTION__, args) +#else +#define Msgfunc(args) +#endif + +#ifndef NO_MSGS +#define Msg_test(name) (_Msg_enabled && _Msg_test(name)) +#define Msg(name, args) ((void)((Msg_test(name))? Msg_do args : 0 )) +#else +#define Msg_test(name) (0) +#define Msg(name, args) ((void)0) +#endif + + +#endif /* MsgsDOTh */ diff --git a/external/libsdf/include/libsdf/SDF.h b/external/libsdf/include/libsdf/SDF.h new file mode 100644 index 0000000..01b1eed --- /dev/null +++ b/external/libsdf/include/libsdf/SDF.h @@ -0,0 +1,165 @@ +/* + SDF Library for reading Self-Describing Files + Copyright (C) 1991,1992 John K. Salmon + + Terms and conditions are specified in the file "copyright.h", + and more precisely in the file COPYING.LIB which you should have + received with this library. +*/ +#ifndef sdfDOTh +#define sdfDOTh +#include +#include +#define SDF_SEEK_SET 0 +#define SDF_SEEK_CUR 1 +#define SDF_SEEK_END 2 + +#define SDF_SYNC 0 +#define SDF_ASYNC 1 + +#define SDF_SINGL 0 +#define SDF_MULTI 1 + +#ifndef INT64_MAX +#if __WORDSIZE==64 +#define INT64_MAX LONG_MAX +#else +/* #define INT64_MAX LLONG_MAX Why doesn't this work? */ +#define INT64_MAX 9223372036854775807LL +#endif +#endif + +#ifndef sdfprivateDOTh +/* It isn't really this, but I don't want to tell you what it is. */ +/* If you believe it's this, then your compiler can check prototypes */ +/* for you. */ +typedef char *SDF[32]; + +/* Identical to declaration in SDF-private.h */ +enum SDF_type_enum{SDF_NOTYPE, + SDF_CHAR, + SDF_SHORT, + SDF_INT, + SDF_LONG, + SDF_INT64, + SDF_FLOAT, + SDF_DOUBLE, + SDF_STRING}; +#endif + +/* Provided for backwards compatibility. Not recommended! */ +#ifdef SDF_OLD_ENUM_NAMES +#define CHAR SDF_CHAR +#define SHORT SDF_SHORT +#define INT SDF_INT +#define FLOAT SDF_FLOAT +#define DOUBLE SDF_DOUBLE +#define STRING SDF_STRING +#endif + +#ifdef __cplusplus +extern "C" { +#endif +/* Two arrays indexed by a type_enum */ +extern char *SDFtype_names[]; +extern int SDFtype_sizes[]; + +extern char SDFerrstring[]; + +int SDFissdf(const char *filename); /* Not guaranteed correct! */ +SDF *SDFopen(const char *hdrfname, const char *datafname); +int SDFseekable(SDF *hdr); /* are non-sequential reads allowed? */ +int SDFclose(SDF *hdr); +int SDFnvecs(SDF *hdr); +int SDFhasname(const char *name, SDF *hdr); +char **SDFvecnames(SDF *hdr); +int64_t SDFnrecs(const char *name, SDF *hdr); +int SDFarrcnt(const char *name, SDF *hdr); +enum SDF_type_enum SDFtype(const char *name, SDF *hdr); +int SDFseek(const char *name, int64_t offset, int whence, SDF *hdr); +int SDFtell(const char *name, SDF *hdr); +unsigned int SDFcpubyteorder(void); +unsigned int SDFbyteorder(SDF *hdr); +int SDFswap(SDF *hdr); +int SDFnoswap(SDF *hdr); +int SDFisswapping(SDF *hdr); +int SDFsetmaxbufsz(int new_size); +int SDFrdvecs(SDF *hdr, ... + /* char *name, int n, void *address, int stride, + ... , + NULL */ ); +int SDFrdvecsv(SDF *hdr, va_list ap); +/* Where is the const supposed to go? */ +int SDFrdvecsarr(SDF *hdr, int nreq, + char **names, int *ns, void **addresses, int *strides); + +int SDFseekrdvecs(SDF *hdr, ... + /* char *name, int start, int n, void *addr, int stride, + ... , + NULL */ ); +int SDFseekrdvecsv(SDF *hdr, va_list ap); +int SDFseekrdvecsarr(SDF *hdr, int nreq, + char **names, int64_t *starts, int *ns, void **addresses, int *strides); +void SDFsetiomode(int mode); + +/* These two subvert the SDF "abstraction" and tell you about */ +/* the actual layout of the file. Are you absolutely sure you need */ +/* to call these? */ +int64_t SDFfileoffset(const char *name, SDF *hdr); +int64_t SDFfilestride(const char *name, SDF *hdr); + +/* These four are harder to write than one might guess. */ +/* They're in the library to avoid duplicating code. */ +int SDFgetint(SDF *sdfp, char *name, int *value); +int SDFgetint64(SDF *sdfp, char *name, int64_t *value); +int SDFgetfloat(SDF *sdfp, char *name, float *value); +int SDFgetdouble(SDF *sdfp, char *name, double *value); +int SDFgetstring(SDF *sdfp, const char *name, char *string, int size); +#ifdef __cplusplus +} +#endif + +/* four macros that call SDFget and bail out if the value isn't there */ +#define SDFgetintOrDie(sdfp, name, value) \ + do{ if( SDFgetint(sdfp, name, value) ) \ + Error("SDFgetint(\"%s\") failed\n", name); } while(0) + +#define SDFgetint64OrDie(sdfp, name, value) \ + do{ if( SDFgetint64(sdfp, name, value) ) \ + Error("SDFgetint64(\"%s\") failed\n", name); } while(0) + +#define SDFgetfloatOrDie(sdfp, name, value) \ + do{ if( SDFgetfloat(sdfp, name, value) ) \ + Error("SDFgetfloat(\"%s\") failed\n", name); } while(0) + +#define SDFgetdoubleOrDie(sdfp, name, value) \ + do{ if( SDFgetdouble(sdfp, name, value) ) \ + Error("SDFgetdouble(\"%s\") failed\n", name); } while(0) + +#define SDFgetstringOrDie(sdfp, name, string, size) \ + do{ if( SDFgetstring(sdfp, name, string, size) ) \ + Error("SDFgetstring(\"%s\") failed", name); } while(0) + +/* And four more that use a default if the value isn't there */ +#define SDFgetintOrDefault(sdfp, name, value, def) \ + do{ if( SDFgetint(sdfp, name, value) ){ \ + *value = def;}} while(0) + +#define SDFgetint64OrDefault(sdfp, name, value, def) \ + do{ if( SDFgetint64(sdfp, name, value) ){ \ + *value = def;}} while(0) + +#define SDFgetfloatOrDefault(sdfp, name, value, def) \ + do{ if( SDFgetfloat(sdfp, name, value) ){ \ + *value = def;} } while(0) + + +#define SDFgetdoubleOrDefault(sdfp, name, value, def) \ + do{ if( SDFgetdouble(sdfp, name, value) ){ \ + *value = def;} } while(0) + +#define SDFgetstringOrDefault(sdfp, name, value, size, def) \ + do{ if( SDFgetstring(sdfp, name, value, size) ){ \ + strncpy(value, def, size);} } while(0) + +#endif /* sdfDOTh */ diff --git a/external/libsdf/include/libsdf/SDFread.h b/external/libsdf/include/libsdf/SDFread.h new file mode 100644 index 0000000..ac76884 --- /dev/null +++ b/external/libsdf/include/libsdf/SDFread.h @@ -0,0 +1,39 @@ +#ifndef _RdDataDOTh +#define _RdDataDOTh + +#include "timers.h" +#include "SDF.h" +/* Can read distributed datafiles if csdfp contains something like: +struct {char datafiles[64];}[4] = {"foo1", "foo2", "foo3", "foo4"}; +*/ +#ifdef __cplusplus +extern "C" { +#endif +extern Timer_t SDFreadTm; + +/* By default, SDFread will look for a "char datafile[]" in csdfp and + read data from there. The name of the variable to look for is + stored in this variable. I.e., it defaults to "datafile". Set it + to NULL to turn this feature off altogether. */ +extern char *SDFread_datafile; + +/* Do the same thing with "hdrfile" */ +extern char *SDFread_hdrfile; + +/* Also by default, SDFread will look for a variable "int npart" in csdfp + and attempt to read that many "particles" from datafile. This variable + storest the name of that variable. Default: "npart"; */ +extern char *SDFread_npart; + +SDF *SDFread(SDF *csdfp, void **btabp, int *gnobjp, int *nobjp, int stride, + /* char *name, offset_t offset, int *confirm */...); +SDF *SDFread64(SDF *csdfp, void **btabp, int64_t *gnobjp, int *nobjp, int stride, + /* char *name, offset_t offset, int *confirm */...); +SDF *SDFreadf(char *hdr, char *name, void **btabp, int *gnobjp, int *nobjp, + int stride, /* char *name, offset_t offset, int *confirm */...); +SDF *SDFreadf64(char *hdr, char *name, void **btabp, int64_t *gnobjp, int *nobjp, + int stride, /* char *name, offset_t offset, int *confirm */...); +#ifdef __cplusplus +} +#endif +#endif diff --git a/external/libsdf/include/libsdf/SDFwrite.h b/external/libsdf/include/libsdf/SDFwrite.h new file mode 100644 index 0000000..4963ffa --- /dev/null +++ b/external/libsdf/include/libsdf/SDFwrite.h @@ -0,0 +1,28 @@ +#ifndef _SDFWriteDOTh +#define _SDFWRiteDOTh + +#ifdef __cplusplus +extern "C" { +#endif +void SDFwrite(const char *filename, int gnobj, int nobj, const void *btab, + int bsize, const char *bodydesc, + /* const char *name, SDF_type_enum type, val */ ...); +void SDFwrite64(const char *filename, int64_t gnobj, int64_t nobj, const void *btab, + int bsize, const char *bodydesc, + /* const char *name, SDF_type_enum type, val */ ...); +void SDFappend64(const char *filename, int64_t gnobj, int64_t nobj, const void *btab, + int bsize, const char *bodydesc, + /* const char *name, SDF_type_enum type, val */ ...); + +/* A trivial special case, just don't write any body data */ +void SDFwritehdr(const char *filename, const char *bodydesc, + /* const char *name, SDF_type_enum type, val */ ...); + +void SDFunsetwroteheader(void); +void SDFsetwroteheader(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/external/libsdf/include/libsdf/byteswap.h b/external/libsdf/include/libsdf/byteswap.h new file mode 100644 index 0000000..3723d8f --- /dev/null +++ b/external/libsdf/include/libsdf/byteswap.h @@ -0,0 +1,21 @@ +#ifndef _ByteSwapDOTh +#define _ByteSwapDOTh + +/* A general, in-place, byte-swapper. */ +/* It swaps a total of unit_len*n_units bytes, unit_len bytes at a time. */ +/* Thus, you can use it for arrays of doubles with unit_len=8, or */ +/* arrays of chars with unit_len=1 (which is equivalent to memcpy). */ +/* It checks for stupid arguments. It works fine when */ +/* from and to are identical. It breaks if from and to are */ +/* almost the same. */ +#ifdef __cplusplus +extern "C" { +#endif +int Byteswap(int unit_len, int n_units, void *from, void *to); +#ifdef __cplusplus +} +#endif + +/* It would probalby be worthwhile to inline these! */ + +#endif diff --git a/external/libsdf/include/libsdf/chn.h b/external/libsdf/include/libsdf/chn.h new file mode 100644 index 0000000..2760f5c --- /dev/null +++ b/external/libsdf/include/libsdf/chn.h @@ -0,0 +1,141 @@ +#ifndef chnDOTh +#define chnDOTh +#include + +/* + CHN.C: Routines for allocating and freeing memory + in fixed length blocks. CHN is mnemonic for either 'chain' or 'chunk'. + The idea is that malloc is called infrequently to get large chunks + which are broken down into smaller pieces which are chained together + to make a freelist. ChnAlloc and ChnFree are very fast O(1), and + use memory efficiently even for small objects. In contrast, + malloc and free are often slow and typically waste several bytes per + allocated object. The down side is that fragmentation problems can be + magnified. Once a large chunk is allocated it never gets freed, even + if all the objects in it have been freed. + Entry points: + void ChnInit(Chn *id, int sz, int nalloc, + void *(realloc_like)(void *, size_t)); + void *ChnAlloc(Chn *id); + void ChnFree(Chn *id, Void *p); + void ChnFreeAll(Chn *id); + void ChnTerminate(Chn *id); + int ChnCheck(Chn *id); + int ChnFreeCnt(Chn *id); + int ChnAllocCnt(Chn *id); + It wouldn't be hard to write "ChnCrunch" which would look for chunks + that have been completely freed, and return them to the system. This + has limited utility, but it might be handy when running near the edge + of memory. + + For diagnostic purposes, use ChnFreeCnt to get the length of the current + freelist. Note that more space will be dynamically allocated, so this + is NOT an upper limit. ChnAllocCnt is the count of how many chunks + are currently allocated. + */ + +typedef struct { + int sz; + int nalloc; + void *free_list; + void *first_chunk; + int free_cnt; + int nmalloced; /* diagnostic purposes only */ + int tbl_sz; + void *(*realloc_like)(void *, size_t); +} Chn; + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ +extern int ChnMoreMem(Chn *id); +extern void ChnInit(Chn *new, int sz, int nalloc, + void *(*realloc_like)(void *, size_t)); +extern void ChnTerminate(Chn *id); +extern void ChnFreeAll(Chn *id); +extern int ChnCheck(Chn *id); +#if !(__STDC_VERSION__ >= 199901L) +extern void *ChnAlloc(Chn *id); +extern void ChnFree(Chn *id, void *p); +extern int ChnFreeCnt(Chn *id); +extern int ChnAllocCnt(Chn *id); +extern size_t ChnUnitSz(Chn *id); +#endif +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#if (defined(__GNUC__) || defined(__ICC__)) || defined(CHNdotC) + +#undef INLINE +#if (__STDC_VERSION__ >= 199901L) && !defined (CHNdotC) +#define INLINE inline +#else +#if (defined (__GNUC__) || defined(__ICC__)) && !defined (CHNdotC) +#define INLINE extern __inline__ +#else +#define INLINE +#endif +#endif + +#if defined(ChnNext) || defined(ChnMagic) || defined(ChnMAGIC) + # error define conflict in __FILE__ +#endif +#define ChnNext(x) (*(void**)(x)) +#define ChnMagic(x) (*(int *)((void**)x+1)) +#define ChnMAGIC 0x82345078 + +#ifndef assert +#include "Assert.h" +#endif + +INLINE void *ChnAlloc(Chn *id) +{ + void *c; + + if (id->free_cnt <= 0) { + if(ChnMoreMem(id)) + return 0; + } + c = id->free_list; + + assert(c); + assert(ChnMagic(c) == ChnMAGIC); + + id->free_cnt--; + id->free_list = ChnNext(c); + return (c); +} + +INLINE void ChnFree(Chn *id, void *p) +{ + /* This assertion can give a false-error reading if the "user" */ + /* has stored the exact value ChnMAGIC in the right location. */ + /* assert(ChnMagic(p) != ChnMAGIC); */ + ChnNext(p) = id->free_list; + ChnMagic(p) = ChnMAGIC; + id->free_list = p; + id->free_cnt++; +} + +INLINE int ChnFreeCnt(Chn *id){ + return id->free_cnt; +} + +INLINE int ChnAllocCnt(Chn *id){ + return id->nmalloced - id->free_cnt; +} + +INLINE size_t ChnUnitSz(Chn *id){ + return id->sz; +} + +#ifndef CHNdotC +#undef ChnNext +#undef ChnMagic +#undef ChnMAGIC +#endif +#undef INLINE + +#endif /* __GNUC__ || CHNdotC */ +#endif diff --git a/external/libsdf/include/libsdf/cosmo.h b/external/libsdf/include/libsdf/cosmo.h new file mode 100644 index 0000000..df107e4 --- /dev/null +++ b/external/libsdf/include/libsdf/cosmo.h @@ -0,0 +1,113 @@ +/* Hide the cosmological parameters in here. + Keep them self-consistent... */ + +struct cosmo_s { + double t; + double a; + double H0; + double Omega0; + double Omega_m; + double Omega_r; + double Omega_de; + double w0; + double wa; + double Lambda; + double Gnewt; + double Zel_f;/* the 'f' factor for linearly growing modes */ +}; + +/* new struct for CLASS interface */ +/* some names have changed definition (Omega_m/Omega_r not constants now) */ +typedef struct cosmology { + double z; + double t; + double tau; + double a; + double H; + double Omega_m; + double Omega_r; + double conf_distance; + double kick; /* union with tau? */ + double drift; + double growthfac; + double velfac; + double velfac2; + /* constants */ + double h_100; + double H0; + double Omega0; /* m+r+lambda+fld */ + double Omega0_m; /* cdm+b+ur+some ncdm */ + double Omega0_r; /* g+ur+rest of ncdm */ + double Omega0_lambda; + double Omega0_cdm; + double Omega0_ncdm_tot; + double Omega0_b; + double Omega0_g; + double Omega0_ur; + double Omega0_fld; + double w0_fld; + double wa_fld; + double Gnewt; + double age; + void *reserved; + void (*background_at_z)(struct cosmology *c, double z); + void (*background_at_t)(struct cosmology *c, double t); + void (*background_at_tau)(struct cosmology *c, double tau); + double (*t_at_z)(struct cosmology *c, double z); + double (*z_at_t)(struct cosmology *c, double t); + double (*a_at_t)(struct cosmology *c, double t); + double (*t_at_a)(struct cosmology *c, double a); + double (*H_at_z)(struct cosmology *c, double z); + double (*H_at_t)(struct cosmology *c, double t); + double (*conformal_distance_at_z)(struct cosmology *c, double z); + double (*conformal_distance_at_t)(struct cosmology *c, double t); + double (*angular_diameter_distance_at_z)(struct cosmology *c, double z); + double (*angular_diameter_distance_at_t)(struct cosmology *c, double t); + double (*luminosity_distance_at_z)(struct cosmology *c, double z); + double (*luminosity_distance_at_t)(struct cosmology *c, double t); + double (*growthfac_at_z)(struct cosmology *c, double z); + double (*growthfac_at_t)(struct cosmology *c, double t); + double (*velfac_at_z)(struct cosmology *c, double z); + double (*velfac_at_t)(struct cosmology *c, double t); + double (*kick_t0_t1)(struct cosmology *c, double t0, double t1); + double (*drift_t0_t1)(struct cosmology *c, double t0, double t1); + void (*free)(struct cosmology *c); +} cosmology; + +void class_init(cosmology *c, char *class_ini, char *class_pre, double zmax); +void class_params(cosmology *c, char *class_ini); +void tbl_init(cosmology *c, char *tbl); + +double Anow(struct cosmo_s *c, double time); +double Znow(struct cosmo_s *c, double time); +double Hnow(struct cosmo_s *c, double time); +double growthfac_from_Z(struct cosmo_s *c, double z); +double velfac_from_Z(struct cosmo_s *c, double z); +double velfac_approx_from_Z(struct cosmo_s *c, double z); +double t_from_Z(struct cosmo_s *c, double z); +double comoving_distance_from_Z(struct cosmo_s *c, double z); +double dp_from_Z(struct cosmo_s *c, double z); +double hubble_from_Z(struct cosmo_s *c, double z); +double kick_delta(struct cosmo_s *c, double t0, double t1); +double drift_delta(struct cosmo_s *c, double t0, double t1); +void CosmoPush(struct cosmo_s *c, double time); + +#define one_kpc 3.08567802e16 /* km */ +#define one_Gyr 3.1558149984e16 /* sec */ +#define cm_kpc 3.08567802e21 +#define sec_Gyr 3.1558149984e16 +#define g_Msol 1.98892e33 +#define g_Msol10 1.98892e43 /* 10^10 Msol */ +/* http://physics.nist.gov/cgi-bin/cuu/Value?bg|search_for=G */ +/* #define G_cgs (6.67384e-8) cm3 g-1 s-2 */ +#define G_cgs (6.67259e-8) +#define speed_of_light (299792.458) /* km/sec */ +/* Gaussian Gravitational Constant */ +#define k_cgs 0.01720209895 +#define GM_cgs 1.32712442099e26 +/* GM_cgs*sec_Gyr*sec_Gyr/cm_kpc*cm_kpc*cm_kpc */ +#define GNEWT 44986.564 + + + + diff --git a/external/libsdf/include/libsdf/error.h b/external/libsdf/include/libsdf/error.h new file mode 100644 index 0000000..749e4a3 --- /dev/null +++ b/external/libsdf/include/libsdf/error.h @@ -0,0 +1,69 @@ +#ifndef _ErrorDOTh +#define _ErrorDOTh + +#include +#include "gccextensions.h" + +/* Define an Error_t to describe error-like functions. */ +typedef void (*Error_t)(const char *, ...); + +#ifdef __cplusplus +extern "C"{ +#endif /* __cplusplus */ +void SWError(const char *, ...) +/* noreturn only works in 2.5 or higher */ +#if (__GNUC_MINOR__>=5 && __GNUC__==2)||__GNUC__>2 + __attribute__ ((format (printf, 1, 2),noreturn)); +#else + __attribute__ ((format (printf, 1, 2))); +#endif + +void vError(const char *, va_list) +/* noreturn only works in 2.5 or higher */ +#if (__GNUC_MINOR__>=5 && __GNUC__==2)||__GNUC__>2 + __attribute__ ((format (printf, 1, 0),noreturn)); +#else + ; +#endif + +void SinglError(const char *, ...) +/* noreturn only works in 2.5 or higher */ +#if (__GNUC_MINOR__>=5 && __GNUC__==2)||__GNUC__>2 + __attribute__ ((format (printf, 1, 2),noreturn)); +#else + __attribute__ ((format (printf, 1, 2))); +#endif +void Warning(const char *, ...) + __attribute__ ((format (printf, 1, 2))); +void SinglWarning(const char *, ...) + __attribute__ ((format (printf, 1, 2))); +void SeriousWarning(const char *, ...) + __attribute__ ((format (printf, 1, 2))); +void Shout(const char *mesg, ...) + __attribute__ ((format (printf, 1, 2))); +void SinglShout(const char *mesg, ...) + __attribute__ ((format (printf, 1, 2))); +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#if __GNUC__>1 /* Actually, only 2.4 or higher? */ +/* We have varargs macros! */ +#define Error(format, args...) \ + (SWError)("%s (%d) in %s :\n" format, __FILE__, __LINE__, __FUNCTION__, ##args) +#define SinglError(format, args...) \ + (SinglError)("%s (%d) in %s :\n" format, __FILE__, __LINE__, __FUNCTION__, ##args) +#define Warning(format, args...) \ + (Warning)("%s (%d) in %s :\n" format, __FILE__, __LINE__, __FUNCTION__, ##args) +#define SinglWarning(format, args...) \ + (SinglWarning)("%s (%d) in %s :\n" format, __FILE__, __LINE__, __FUNCTION__, ##args) +#define SeriousWarning(format, args...) \ + (SeriousWarning)("%s (%d) in %s :\n" format, __FILE__, __LINE__, __FUNCTION__, ##args) + +#else /* No wacky GNUC varargs stuff...*/ +/* This prevents namespace collisions when linking SDF into perl5! (really!) */ +#define Error SWError + +#endif + +#endif /* _ErrorDOTh */ diff --git a/external/libsdf/include/libsdf/gccextensions.h b/external/libsdf/include/libsdf/gccextensions.h new file mode 100644 index 0000000..b43a8ea --- /dev/null +++ b/external/libsdf/include/libsdf/gccextensions.h @@ -0,0 +1,34 @@ +#ifndef _GccExtensionsDOTh +#define _GccExtensionsDOTh + +/* this is broken in gcc2.4.0 through 2.4.4 */ +#if __GNUC__<2 || (__GNUC__== 2 && __GNUC_MINOR__<=4) +#define BROKEN_GCC_FORMAT_ATTRIBUTE +#endif + +/* This isn't an entirely perfect way to deal with functions that + don't return because sometimes we want more than one __attribute__. + See, for example, the code in error.h and mpmy_abnormal.h */ +#if (__GNUC_MINOR__>=5 && __GNUC__==2)||__GNUC__>2 +#define __NORETURN__ __attribute__ ((noreturn)) +#else +#define __NORETURN__ +#endif + +#undef __attribute__ +#if !defined(__GNUC__) || defined(printf) || defined(scanf) +#define __attribute__(x) +#endif /* __GNUC__ */ + +/* NoInline can be used to prevent inlining of function calls at the */ +/* calling location. I.e., NoInline(func)(arg) instead of func(arg) */ +/* We leave everything alone if we're not optimizing because there */ +/* are no inlines in that case anyway. */ +#if defined(__GNUC__) && defined(__OPTIMIZE__) +#define NoInline(f) ({typeof(f) *fp = &f; *fp;}) +#else +#define NoInline(f) f +#endif + +#endif + diff --git a/external/libsdf/include/libsdf/memfile.h b/external/libsdf/include/libsdf/memfile.h new file mode 100644 index 0000000..8259ec9 --- /dev/null +++ b/external/libsdf/include/libsdf/memfile.h @@ -0,0 +1,15 @@ +#ifndef _MemfilEdotH +#define _MemfilEdotH + +#ifdef __cplusplus +extern "C"{ +#endif +void memfile_init(int sz) ; +void memfile_delete(void) ; +void memfile_vfprintf(void *junk, const char *fmt, va_list args) ; +void PrintMemfile(void); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/external/libsdf/include/libsdf/mpmy.h b/external/libsdf/include/libsdf/mpmy.h new file mode 100644 index 0000000..32d016f --- /dev/null +++ b/external/libsdf/include/libsdf/mpmy.h @@ -0,0 +1,164 @@ +#ifndef _MpMYdotH +#define _MpMYdotH + +#include "timers.h" + +typedef void *MPMY_Comm_request; +typedef struct { + int tag; + int src; + int count; +}MPMY_Status; + +#define MPMY_SUCCESS (0) +#define MPMY_FAILED (1) +/* This corresponds to the ANY-source in udp.c. */ +/* What about other PAROS??? */ +#define MPMY_SOURCE_ANY -2 +#define MPMY_TAG_ANY -1 + +/* Data types and operations supported in MPMY_Combine */ + +typedef enum { + MPMY_SUM, MPMY_PROD, MPMY_MAX, MPMY_MIN, MPMY_BAND, MPMY_BOR, MPMY_BXOR +} MPMY_Op; + +typedef void (*MPMY_user_comb_func)(const void *from1, const void *from2, + void *to); + +typedef enum { + MPMY_FLOAT, MPMY_DOUBLE, MPMY_INT, MPMY_CHAR, MPMY_SHORT, MPMY_LONG, + MPMY_UNSIGNED_INT, MPMY_UNSIGNED_CHAR, MPMY_UNSIGNED_SHORT, + MPMY_UNSIGNED_LONG, MPMY_OFFT, MPMY_INT64, MPMY_USER_DATA +} MPMY_Datatype; + +extern unsigned int MPMY_Datasize[]; + +#ifdef __cplusplus +extern "C"{ +#endif /* __cplusplus */ +/* Reduction prototypes */ +int MPMY_Combine(const void *sendbuf, void *recvbuf, const int count, + const MPMY_Datatype datatype, const MPMY_Op op); +int MPMY_ICombine_Init(MPMY_Comm_request *reqp); +int MPMY_ICombine_Wait(MPMY_Comm_request req); +int MPMY_ICombine(const void *sendbuf, void *recvbuf, int count, + MPMY_Datatype datatype, MPMY_Op op, + MPMY_Comm_request req); +/* A separate entry point for the user-specified-function version */ +int MPMY_ICombine_func(const void *sendbuf, void *recvbuf, int size, + MPMY_user_comb_func func, + MPMY_Comm_request req); +int MPMY_AllGather(const void *sndbuf, int count, MPMY_Datatype type, + void *rcvbuf); +int MPMY_Gather(const void *sendbuf, int count, MPMY_Datatype type, + void *recvbuf, int recvproc); +int MPMY_NGather(const void *sendbuf, int count, MPMY_Datatype type, + void **recvhndl, int recvproc); +int MPMY_Bcast(void *buf, int count, MPMY_Datatype type, int sendproc); +int MPMY_BcastTag(void *buf, int count, MPMY_Datatype type, int sendproc, int Tag0); +int MPMY_Alltoall(void *sendbuf, int sendcount, MPMY_Datatype sendtype, + void *recvbuf, int recvcount, MPMY_Datatype recvtype); +int MPMY_Alltoallv(void *sendbuf, int *sendcounts, int *sendoffsets, MPMY_Datatype sendtype, + void *recvbuf, int *recvcounts, int *recvoffsets, MPMY_Datatype recvtype); +int Native_MPMY_Allgather(void *sendbuf, int sendcount, MPMY_Datatype type, void *recvbuf); +int Native_MPMY_Allgatherv(void *sendbuf, int sendcount, MPMY_Datatype type, void *recvbuf, + int *rcounts, int *roffsets); +int Native_MPMY_Alltoall(void *sendbuf, int sendcount, MPMY_Datatype sendtype, + void *recvbuf, int recvcount, MPMY_Datatype recvtype); +int Native_MPMY_Alltoallv(void *sendbuf, int *sendcounts, int *sendoffsets, MPMY_Datatype sendtype, + void *recvbuf, int *recvcounts, int *recvoffsets, MPMY_Datatype recvtype); + +/* + A NULL stat argument is allowed, indicating that you aren't interested in + the status. +*/ +int MPMY_Init(int *argcp, char ***argvp); +int MPMY_Isend(const void *buf, int cnt, int dest, int tag, MPMY_Comm_request *req); +int MPMY_Irsend(const void *buf, int cnt, int dest, int tag, MPMY_Comm_request *req); +int MPMY_Irecv(void *buf, int cnt, int src, int tag, MPMY_Comm_request *req); +int MPMY_Test(MPMY_Comm_request request, int *flag, MPMY_Status *stat); +int MPMY_Wait(MPMY_Comm_request request, MPMY_Status *stat); +/* I don't know how to write the general WaitN, but we seem to use Wait2 + often enough that it's worth providing in the library. Note that this + waits for BOTH. Not EITHER. */ +int MPMY_Wait2(MPMY_Comm_request req1, MPMY_Status *stat1, + MPMY_Comm_request req2, MPMY_Status *stat2); +/* send with wait */ +void MPMY_send(const void *buf, int cnt, int dest, int tag); +/* Blocking recv of exactly cnt bytes */ +void MPMY_recvn(void *buf, int cnt, int src, int tag); +int MPMY_Finalize(void); + +/* These are occasionally useful and seem to be highly system-dependent */ +int MPMY_Sync(void); +int MPMY_Flick(void); + +/* Desperate times require desperate measures... (c.f. malloc_print) + Consider using Msg_do or Shout as the argument. Note that, despite + the name, they aren't strictly printf-identical because they don't + return an int. C'est la vie. */ +void MPMY_Diagnostic(int (*printflike)(const char *, ...)); + +/* And a version suitable for passing to OnAbnormal */ +void PrintMPMYDiags(void); + +/* These don't really have analogues in mpi. MPI does have Sendrecv + and Sendrecv_replace, but those are both more general (allowing + different sources and destinations, allowing tags, allowing *_ANY) + and less general ('replace' instead of 'overlap'). + +*/ +int MPMY_Shift(int proc, void *recvbuf, int recvcnt, + const void *sendbuf, int sendcnt, MPMY_Status *stat); + +int MPMY_Shift_overlap(int proc, void *recvbuf, int recvcnt, + const void *sendbuf, int sendcnt, MPMY_Status *stat); + + +/* In MPI, they actually give you the name of the field element. For backward + compatibility, I'll also give them as macros */ +#define MPMY_SOURCE src +#define MPMY_TAG tag +#define MPMY_Source(stat) ((stat)->src) +#define MPMY_Tag(stat) ((stat)->tag) +/* In MPI, this is still a function because it has to deal with typing. + We don't worry about typing... */ +#define MPMY_COUNT count +#define MPMY_Count(stat) ((stat)->count) + +int MPMY_Nproc(void); +int MPMY_Procnum(void); +/* Returns a pointer to a static char string describing the phys node. */ +const char *MPMY_Physnode(void); +/* We call these an awful lot. Let's just set them up in init and + save a function-call */ +extern int _MPMY_nproc_; +extern int _MPMY_procnum_; +extern int _MPMY_procs_per_node_; +#define MPMY_Nproc() (_MPMY_nproc_) +#define MPMY_Procnum() (_MPMY_procnum_) +#define MPMY_ProcsPerNode() (_MPMY_procs_per_node_) + +/* How can a "subsystem" like SDF know if MPMY has been initialized? */ +extern int MPMY_Initialized(void); +extern int _MPMY_initialized_; /* internal use only! */ + +/* Counters for the number of Isends, Irecvs and (successful Tests + Waits) */ +extern Counter_t MPMYSendCnt; +extern Counter_t MPMYRecvCnt; +extern Counter_t MPMYDoneCnt; + +void MPMY_CheckpointSetup(int job_seconds, int interval_seconds, int step_seconds); +int MPMY_CheckpointDue(int next_output_seconds); +void MPMY_CheckpointFinished(void); +int MPMY_JobDone(void); +int MPMY_JobRemaining(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +/* INTERNAL USE ONLY!! */ + +#endif diff --git a/external/libsdf/include/libsdf/mpmy_abnormal.h b/external/libsdf/include/libsdf/mpmy_abnormal.h new file mode 100644 index 0000000..5b2c819 --- /dev/null +++ b/external/libsdf/include/libsdf/mpmy_abnormal.h @@ -0,0 +1,71 @@ +#ifndef _MPMYAbnormalDOTh_ +#define _MPMYAbnormalDOTh_ +#include "gccextensions.h" + +/* Abhndlrs are void functions of void. Use them as arguments to + MPMY_OnAbnormal. */ +typedef void (*Abhndlr)(void); + +#ifdef __cplusplus +extern "C"{ +#endif + +/* MPMY_Abort will execute MPMY_RaiseAbnormal(SIGABRT) and then call + MPMY_SystemAbort. Don't be surprised if the OnAbnormal functions + themselves call MPMY_SystemAbort first, though. */ +void MPMY_Abort(void) __NORETURN__; + +extern int MPMY_Abnormal_signum; +extern int MPMY_stop_abnormal_processing; +void MPMY_RaiseAbnormal(int sig); /* fake a signal of type 'sig' */ + +/* Push a handler to the stack that will be executed on abnormal termination. + Some useful arguments to consider are: + malloc_print(); + PrintMemfile(); + Msg_flush(); + MPMY_abchdir(); (with MPMY_abchdir_arg set beforehand) + MPMY_SystemAbort(); + MPMY_SystemExit(); (with MPMY_exit_arg set beforehand) + + They are called in the reverse chronological order from the order that + they were requested by MPMY_OnAbnormal, so later functions + might 'override' earlier ones. This isn't perfect, but it's better than + the monolithic handler we had before. The handler can + find out which signal is being handled by looking at + int MPMY_current_signal ; + + As a final twist, it is possible to bail out of the stack and just + return from the handler immediately by setting: + int MPMY_stop_abnormal_processing; + to non-zero. +*/ +void MPMY_OnAbnormal(Abhndlr hndlr); + +/* Really, truly, abort(). Now! */ +void MPMY_SystemAbort(void) __NORETURN__; + +/* Really, truly, exit(MPMY_exit_arg). Now! */ +extern int MPMY_exit_arg; +void MPMY_SystemExit(void) __NORETURN__; /* An Abhndlr */ + +/* Do a mkdir/chdir to the directory named by MPMY_abchdir_arg. + This can be extremely useful before dumping core... */ +extern char MPMY_Abchdir_arg[]; +void MPMY_Abchdir(void); /* An Abhndlr */ + +/* Announce (Shout) that we are handling a signal. Try not to repeat + yourself if it's been said already... */ +void MPMY_Abannounce(void); + +/* Arrange to crash and burn if n seconds elapse before Reset is called */ +void MPMY_TimeoutSet(int n); +void MPMY_TimeoutReset(int n); +void MPMY_TimeoutCancel(void); + +/* Not for public use. */ +void _MPMY_setup_absigs(void); +#ifdef __cplusplus +} +#endif +#endif /* _MPMYAbnormalDOTh_ */ diff --git a/external/libsdf/include/libsdf/mpmy_io.h b/external/libsdf/include/libsdf/mpmy_io.h new file mode 100644 index 0000000..2839b98 --- /dev/null +++ b/external/libsdf/include/libsdf/mpmy_io.h @@ -0,0 +1,62 @@ +#ifndef MPMY_IOdotH +#define MPMY_IOdotH + +#include +#include + +typedef void MPMYFile; + +/* mode flags for open */ +/* The first three correspond to the analogous modes O_??? that seem + to be fairly common on different unices (linux, sunos, solaris). I + guess that's a good thing. But who decided that OR'ing zero + (O_RDONLY) with other values should be used as a flag???? The latter + ones show no commonality between other flavors of unix anyway, so + there's nothing to remain analogous to... */ +#define MPMY_RDONLY 00000000 +#define MPMY_WRONLY 00000001 +#define MPMY_RDWR 00000002 +#define MPMY_APPEND 00000004 +#define MPMY_CREAT 00000010 +#define MPMY_TRUNC 00000020 +/* io modes */ +#define MPMY_SINGL 00010000 /* like cubix single mode */ +#define MPMY_MULTI 00020000 /* like cubix multi mode */ +/* These four are used by the 'mpmy_pario' implementation, but that is + no longer linked with any of our default systems... */ +#define MPMY_UNIX 00040000 /* one file, UNIX multi-process semantics */ +#define MPMY_IOZERO 00100000 /* if(procnum==0){...} */ +#define MPMY_INDEPENDENT 00200000 /* many files. Complete independence */ +#define MPMY_NFILE 00400000 /* many files. Really. */ + +/* modes for seek */ +#define MPMY_SEEK_SET 0 +#define MPMY_SEEK_CUR 1 +#define MPMY_SEEK_END 2 + + +#ifdef __cplusplus +extern "C"{ +#endif /* __cplusplus */ +MPMYFile *MPMY_Fopen(const char *path, int flags); +int MPMY_SetIOMode(MPMYFile *fp, int iomode); +int MPMY_Fclose(MPMYFile *fp); +int MPMY_Mkdir(const char *path, int mode); +size_t MPMY_Fread(void *ptr, size_t size, size_t nitems, MPMYFile *fp); +size_t MPMY_Fwrite(const void *ptr, size_t size, size_t nitems, MPMYFile *fp); +off_t MPMY_Fseek(MPMYFile *fp, off_t offset, int whence); +off_t MPMY_Ftell(MPMYFile *fp); +off_t MPMY_Flen(MPMYFile *fp); +int MPMY_Getc(MPMYFile *fp); +int MPMY_Ungetc(char c, MPMYFile *fp); +size_t MPMY_Fseekrd(MPMYFile *fp, off_t offset, int whence, void *buf, size_t reclen, + size_t nrecs); +int MPMY_Fprintf(MPMYFile *fp, const char *fmt, ...); +int MPMY_Vfprintf(MPMYFile *fp, const char *fmt, va_list args); +int MPMY_Fflush(MPMYFile *fp); +int MPMY_Nfileio(int val); +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* MPMY_IOdotH */ diff --git a/external/libsdf/include/libsdf/mpmy_time.h b/external/libsdf/include/libsdf/mpmy_time.h new file mode 100644 index 0000000..f333063 --- /dev/null +++ b/external/libsdf/include/libsdf/mpmy_time.h @@ -0,0 +1,23 @@ +#ifndef MPMY_timeDOTh +#define MPMY_timeDOTh + +/* some simple system-dependent routines to facilitate timing */ + +#define MPMY_CPU_TIME 1 +#define MPMY_WC_TIME 2 + +#ifdef __cplusplus +extern "C"{ +#endif /* __cplusplus */ +void *MPMY_CreateTimer(int type); +int MPMY_StartTimer(void *); + int MPMY_CopyTimer(void *, void *); +int MPMY_StopTimer(void *); +int MPMY_ClearTimer(void *); +double MPMY_ReadTimer(void *); +int MPMY_DestroyTimer(void *); +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/external/libsdf/include/libsdf/protos.h b/external/libsdf/include/libsdf/protos.h new file mode 100644 index 0000000..9e08a57 --- /dev/null +++ b/external/libsdf/include/libsdf/protos.h @@ -0,0 +1,128 @@ +/* This is where we keep the code to shut up warnings about implicit */ +/* declarations. */ + +/* + * Copyright 1991 Michael S. Warren and John K. Salmon. All Rights Reserved. + */ +#ifndef _ProtosDOTh +#define _ProtosDOTh + +/* gcc's fixprotos changed in 2.5 so that it is no longer necessary + to have protos for all these. If __GNUC__ and __GNUC_MINOR are undefined, + ANSI says the pre-processor should treat them as 0, so the test should + pass and we should see the prototypes - fingers crossed. +*/ +/* AIEEEE!!! The above comment only applied to the short-lived + aberation 2.5.4. It is broken again in 2.5.5. Unfortunately, + there is no __GNUC__SUBMINOR__ so I can't switch on it. The + following conditional worked for 2.5.4... +#if defined(sun) && !defined(__SUN5__) && __GNUC__<=2 && __GNUC_MINOR__<=4 +*/ + +/*------------------------------------------------------*/ +/* ----------------BEGIN--SUNOS------------------------ */ +/*------------------------------------------------------*/ +#if defined(sun) +#include +/* Sunos4.1.3 sometimes seems to come with prototypes...And they're wrong! */ +/* Setting ARCH=sun4proto will activate this */ +#ifndef _SUNOS4_PROTOTYPES_ +extern int bcopy(const void *from, void *to, size_t); +#if !defined(__SUN5__) && !defined (_SUNACC) +/* Sun's stdio doesn't have protos for fflush, printf, what else?? */ +/* I can't predict whether FILE is meaningful, so I use void* */ +/* Furthermore, I can't give a prototype for sprintf because gcc complains */ +/* about a conflict between old-style decl and one with an ellipsis */ +#include "gccextensions.h" +#include + +/* Sigh... In 2.5.6 and 2.5.7 (at least). fixincludes gives full + prototypes for all the non-integer-return functions in std*.h. */ +#if 0 +extern char *sprintf(); +#endif + +extern int printf( const char *, ... ) + __attribute__ ((format (printf, 1, 2))); +extern int fprintf(void *, const char *, ...) + __attribute__((format (printf, 2, 3))); +extern int vfprintf(void *, const char *, va_list) + __attribute__((format (printf, 2, 0))); +extern int vsprintf(char *, const char *, va_list) + __attribute__((format (printf, 2, 0))); +extern int scanf(const char *, ...) + __attribute__((format (scanf, 1, 2))); +extern int sscanf(const char *, const char *, ...) + __attribute__((format (scanf, 2, 3))); +extern int fflush(void *); +extern int fwrite(const void *, size_t, size_t, void/*FILE*/ *); +extern int fseek(void/*FILE*/ *, long, int); +extern int fread(void *, size_t, size_t, void/*FILE*/ *); +extern int fclose(void *); +extern int raise(int); +extern int _filbuf(void *); +extern int _flsbuf(int, void *); +#ifndef ungetc +extern int ungetc(int, void*); +#endif +extern int setvbuf(void *, void *, int, size_t); +/* We carefully include stdlib.h when we use these, */ +/* but Sun has elected to leave them out of stdlib.h...go figure */ +extern void *memmove(void *, const void *, size_t); +extern void *memccpy (void *, const void *, int, size_t ); +extern void *memchr (const void *, int, size_t ); +extern void *memcpy (void *, const void *, size_t ); +extern void *memset (void *, int, size_t ); +#endif /* __SUN5__ */ +#endif /* _SUNOS4_PROTOTYPES_ */ +#endif /* sun */ +/*------------------------------------------------------*/ +/* ------------------END--SUNOS------------------------ */ +/*------------------------------------------------------*/ + +/*------------------------------------------------------*/ +/* ------------------BEGIN--INTEL---------------------- */ +/*------------------------------------------------------*/ +#if defined(__INTEL_SSD__) +#include +extern int bcopy(const void *from, void *to, size_t); + +/* This should be in nx.h or cube.h or mesh.h */ +extern void flick(void); + +#if defined(__DELTA__) || defined(__GAMMA__) +/* This should be in fcntl.h */ +int open(const char *, int flags, ...); +int creat(const char *, int/* mode_t */); + +/* These should be in unistd.h */ +int close(int); +int unlink(const char *); +int read(int, void *buf, unsigned int); +int write(int, const void *, unsigned int); +/*off_t*/long lseek(int, long/*off_t*/, int); + +/* Should be in sys/stat.h */ +int mkdir(const char *, int); +#ifdef S_IRGRP +/* this means we already included */ +int fstat(int, struct stat *); +#endif +#endif /* __DELTA__ || __GAMMA__ */ + +#endif /* !__INTEL_SSD__ */ +/*------------------------------------------------------*/ +/* ------------------END--INTEL------------------------ */ +/*------------------------------------------------------*/ + +/*------------------------------------------------------*/ +/* ------------------BEGIN--SOLARIS/STARDENT----------- */ +/*------------------------------------------------------*/ +#if defined(__STARDENT__) || defined(__SUN5__) +int finite(double); +#endif +/*------------------------------------------------------*/ +/* --------------------END--SOLARIS/STARDENT----------- */ +/*------------------------------------------------------*/ + +#endif /* _PrototDOTh */ diff --git a/external/libsdf/include/libsdf/singlio.h b/external/libsdf/include/libsdf/singlio.h new file mode 100644 index 0000000..b63ff0c --- /dev/null +++ b/external/libsdf/include/libsdf/singlio.h @@ -0,0 +1,14 @@ +#ifndef _SinglIODOTh +#define _SinglIODOTh + +#ifdef __cplusplus +extern "C"{ +#endif /* __cplusplus */ +int singlPrintf(const char *, ...); +void singlFflush(void); +int singlAutoflush(int); +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/external/libsdf/include/libsdf/timers.h b/external/libsdf/include/libsdf/timers.h new file mode 100644 index 0000000..a983e29 --- /dev/null +++ b/external/libsdf/include/libsdf/timers.h @@ -0,0 +1,78 @@ +/* + * Copyright 1991, 1992, 1993 Michael S. Warren and John K. Salmon. + * All Rights Reserved. + */ + +#ifndef _TimersDOTh +#define _TimersDOTh +#include + +/* This used to look more like a Counter_t, but it was just too much */ +/* trouble to deal with the archtecture specific differences, so we */ +/* hide all the ugliness behind another layer of indirection. In */ +/* fact, it would make more sense if, e.g., EnableTimer returned a void* */ +/* but that would require too much changing of "application" code. */ +typedef struct { + int enabled; + void *mpmy_tm; + char *name; + double min, max, mean; +} Timer_t; + +typedef struct { + int enabled; + int64_t counter; + int64_t max, min; + double mean, sum; + char *name; +} Counter_t; + +#ifdef __cplusplus +extern "C"{ +#endif /* __cplusplus */ +void StartTimer(Timer_t *t); +void StopTimer(Timer_t *t); +void SumTimers(void); +void CopyTimer(Timer_t *src, Timer_t *dest); +void EnableWCTimer(Timer_t *t, char *name); +void EnableCPUTimer(Timer_t *t, char *name); +void DisableTimer(Timer_t *t); +void ClearTimer(Timer_t *t); +void ClearEnabledTimers(void); +void OutputTimers(int (*Printf_Like)(const char *, ...)); +void OutputTimer(Timer_t *t, int (*Printf_Like)(const char *, ...)); +void OutputIndividualTimers(int (*Printf_Like)(const char *, ...)); +double ReadTimer(Timer_t *t); + +void SumCounters(void); +void EnableCounter(Counter_t *t, char *name); +void DisableCounter(Counter_t *t); +void ClearCounter(Counter_t *c); +void ClearEnabledCounters(void); +void OutputCounters(int (*Printf_Like)(const char *, ...)); +void OutputIndividualCounters(int (*Printf_Like)(const char *, ...)); +void OutputOneCounter(Counter_t *c, int (*Printf_Like)(const char *, ...)); +int64_t ReadCounter(Counter_t *c); +int64_t ReadCounter64(Counter_t *c); +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#define EnableTimer(t, name) EnableWCTimer(t, name) + +#ifdef NOTIMERS +#define StartTimer(x) /**/ +#define StopTimer(x) /**/ +#define StartWCTimer(x) /**/ +#define StopWCTimer(x) /**/ +#endif + +#ifndef NOCOUNTERS +#define IncrCounter(c) ((c)->counter++) +#define AddCounter(c, add) ((c)->counter += (add)) +#else +#define IncrCounter(c) +#define AddCounter(c, add) +#endif + +#endif /* _TimersDOTh */ diff --git a/external/libsdf/libSDF/ChangeLog.14 b/external/libsdf/libSDF/ChangeLog.14 new file mode 100644 index 0000000..bee9043 --- /dev/null +++ b/external/libsdf/libSDF/ChangeLog.14 @@ -0,0 +1,313 @@ +Fri Jan 7 13:50:53 1994 John Salmon (johns@haggis) + + * Terminate this ChangeLog. Future changes to be logged + in the parent directory. + +Wed Dec 29 08:57:39 1993 John Salmon (johns@sampson) + + * fseekrd.c (fseekrd): #include protos.h and error.h + +Mon Dec 27 18:05:36 1993 John Salmon (johns@lux) + + * fseekrd.c: Bail out with Error in the event of an error. + +Sun Oct 10 21:02:27 1993 John Salmon (johns@sockeye) + + * SDFget.c: Added protos.h. Silenced a warning. + +Tue Jul 13 11:19:20 1993 John Salmon (johns@lux) + + * libSDF/: changed some formats to silence complaints about + incorrect argument passing to printf. These SHOULD all be + changed to singlWarning. + +Thu Jun 10 15:34:01 1993 John Salmon (johns@haggis) + + * SDF.h, SDFget.c: Added the functions SDFgetint, SDFgetdouble + SDFgetfloat and SDFgetstring to the library. In addition, added + the macros SDFget*OrDie and SDFget*OrDefault to SDF.h. The macros + use Error and singlWarning, which can be found in the swutils + library, or which the user may redefine to taste. + +Thu Jun 3 16:32:18 1993 John Salmon (johns at haggis) + + * Revert back to the i860_utils style of managing the PGI, + IPSC_XDEV, etc. environment variables. "The management apologizes + for the inconvenience." The reason is that i860_target doesn't + interact well with Make running inside emacs. + +Tue Jun 1 20:51:16 1993 John Salmon (johns@sockeye) + + * (../SDF): Changed Make.common so it creates libraries in, e.g., + sun4/libSDF.a. Make the old-style SDF_sun4.a a symbolic link to + the new file. Use of /libSDF.a is encouraged. + +Tue Jun 1 20:47:04 1993 John Salmon (johns at haggis) + + * Added (this) ChangeLog to the list of docs copied into .tar files! + +Wed May 26 20:02:14 1993 John Salmon (johns at sampson) + + * Removed the -delta flags from Make.delta. Use the i860_target + technology instead. + + * Fixed two bugs related to ascii data. On line 399 of + SDF-parse.y and line 646 of SDFfuncs.c. Recompiled sun4 and delta + versions. It should now correctly handle ascii data. + +Tue Mar 2 20:26:09 1993 John Salmon (johns at sampson) + + * Conditionalized the #define YYDEBUG 1 so it won't get linked on + the delta. It surely can't do us any good! + + * Added a comment (but no code) to SDF-parse.y that worries about + what to do when a string constant is too long to fit in a char array. + + * Changed SDFtst.c so it prints the first element of every vector + in the file it reads. Just another diagnostic that might show up + an error... + +Wed Feb 10 20:12:15 1993 John Salmon (johns at sampson) + + * Don't close stdin in SDFissdf! + +Wed Dec 9 11:36:53 1992 John Salmon (johns at haggis) + + * Changed the #ifdef SEEK_SET conditionals in SDF.h. Now + the 'preferred' usage is SDF_SEEK_SET, etc., but they are + almost guaranteed to be the same as SEEK_SET from stdio.h. + If they aren't, complete and untraceable confusion will surely + result. Changed SEEK_SET, etc. in SDFfuncs.c to SDF_SEEK_SET, + etc. + +Wed Dec 2 17:55:08 1992 John Salmon (johns at pollux) + + * Added ncube2 support. This means setting up a Make.ncube2, + and getting alloca.c (unmodified) from the emacs distribution, + and saying 'extrasrc:=alloca.c' in Make.ncube2. Also added + a call to alloca(0) to SDFopen just after yyparse, which should + clean up any mess left behind by the C alloca. + +Fri Nov 13 18:42:33 1992 John Salmon (johns at sampson) + + * Reset yylineno in SDFyyprepare(). Otherwise error message + line numbers accumulate! + +Tue Nov 10 20:21:11 1992 John Salmon (johns at haggis) + + * Changed the typedef for SDF in SDF.h. It still doesn't tell + you what's really going on in an SDF hdr, but at least prototypes + get checked for correctness, and printing an SDF* under gdb might + even tell you most of what you care to know. + +Tue Oct 27 12:24:50 1992 John Salmon (johns at haggis) + + * Fixed a bug in SDF-lex.l that didn't recognize signed + integer constants. How did this last for so long?! The + {Sign} specifier was simply missing from the regex. + +Fri Oct 16 11:10:13 1992 John Salmon (johns at haggis) + + * Added halocenterx, halocentery and halocenterz to the + generic tree.sdfh and tree_ap.sdfh files. These are used + by the isothermal halo integrator (i.e., Carl). + +Thu Oct 15 21:34:20 1992 John Salmon (johns at haggis) + + * Try to be even more defensive in SDFclose, in order to not + get SEGV when bailing out of a parse error. This is not + a finished project! Careful cleanup should be attempted in + yyerror(). + +Fri Oct 9 08:34:50 1992 John Salmon (johns at delilah) + + * SDF now only uses SEEK_CUR to reposition itself in the file. + fseekrd() will work with SEEK_CUR and any positive offset by + freading into a junk buffer, regardless of whether the file is + seekable. Thus, operations on unseekable files need not be + sequential. They must still be "monotonic increasing". + +Thu Oct 8 10:06:49 1992 John Salmon (johns at delilah) + + * Added support for reading from unseekable files. This means + keeping track of the "seek pointer" ourselves, and checking + whether seeking is really necessary to accomodate requests. If + the caller doesn't require us to seek, then we don't. If he does, + then we fail. + + * Added SDFsetbufsz/SDFgetbufsz, which induce SDF to malloc a + buffer and call setvbuf in all subsequent SDFopen's. Use for + tuning access to tape devices and pipes. + +Wed Sep 16 11:12:40 1992 John Salmon (johns at haggis) + + * Added the keyword "long" to the set of possible types. + It behaves EXACTLY the same as "int". There is no corresponding + SDF_LONG. Is this really a good idea (the same was done for unsigned). + + * Fixed a bug in SDF-parse.y which caused miscounting the + lengths of implicit arrays, e.g., char greeting[] = "hello"; + + * Added Const to many of the arguments in SDF.h. + +Tue Sep 15 17:10:48 1992 John Salmon (johns at haggis) + + * Eliminated the huge redundancy in SDFrdvecsarr, and made it + call SDFseekrdvecsarr. This not only shortens the code, but it + probably means more reasonable behavior on return from errors. + Ever wonder what would happen if you do an SDFrdvecsarr and the + last "name" you give it doesn't exist? Well it's much better now. + +Wed Sep 2 15:12:06 1992 John Salmon (johns at haggis) + + * Changed the strategy for grabbing temporary space in SDFrdvecsarr + and SDFseekrdvecsarr. Now if malloc fails, we try successively + smaller requests until we get something. We only give up with + an error if we can't get enough for a single "record" (i.e., + struct). The memory is freed at the end of the execution of + SDF*rdvecsarr. + + * In the interests of reducing namespace pollution, changed the enum + names in SDF_type_enum to be SDF_INT, SDF_FLOAT, etc. This will + break some old codes. Old codes can be made to compile by + adding a #define OLD_ENUM_NAMES before #include "SDF.h". + + * Changed the external name of swapn to SDFswapn. This should + not effect anything. + +Tue Sep 1 10:13:05 1992 John Salmon (johns at haggis) + + * Added an if( hdr==NULL ) test to each of the exported SDF + functions. This should cut down on memory faults from users + who don't check the return from SDFopen. It might even be + worthwhile to put a magic number in the SDF hdr. + +Mon Aug 31 17:43:25 1992 John Salmon (johns at haggis) + + * Fixed a typo in SDF-lex.l and recompiled delta and sun4. + + * Checked the return of realloc against NULL in the middle of + SDFrdvecsarr and SDFseekrdvecsarr. The program now fails with + a message rather than getting a Segv. It is probably not recoverable. + We really should reduce the size of some of these buffers by + staging them. + +Tue Jun 30 02:39:30 1992 John Salmon (johns at haggis) + + * Removed some spurious newlines from the ends of the .sdfh files. + These make trouble if you try to do "cat tree.sdfh foo.tree > foo.sdf" + + * INCOMPATIBLE CHANGE: changed the calling convention for + SDFopen. Now we pass in two char strings, both filenames, one + for the header and one for the data. This has a number of + beneficial effects: + 1) It means we don't have to 'agree' on what kind of FILE is + in use with the 'user'. (e.g., CUBIX, NX, SRV, etc.) All the nasty + business gets handled inside SDF in the Makefile and such. + 2) It's easier for a 'user' to specify a header that comes from a + file. The user doesn't have to stat the file, malloc space, read + it in and then call SDFopen with the contents as an arg. + 3) SDF is reasonably careful about checking out whether fopen + returns NULL. This means less obscure failure when a bad name + is provided. + + If the hdrname is NULL, or if it is empty or if it strcmp's + equal to the datafname, then the data file is treated as an + SDF file with a header attached. + + * Made a similar change to SDFissdf, so that one calls it with + a name rather than a FILE *. "-" is stdin. + +Tue Jun 9 17:30:13 1992 John Salmon (johns at delilah) + + * Created SDF_sun4.a SDF_risc6000.a and SDF_delta.a. + + * Added some new functions to SDF.h and SDFfuncs.c: + SDFissdf, SDFbyteorder, SDFswap, SDFnoswap, SDFisswapping. + + These make it simpler to use generic header files for things + like pjq, tree, etc. files. The nbio_ routines are no longer + the preferred way to read old-style files. It might be worth + writing a function that reads an alternative header directly + from disk, rather than from a string. It really is a shame + that there is no portable way to treat a string as a FILE *. + +Sat Apr 4 09:34:16 1992 John Salmon (johns at haggis) + + * Created SDF_risc6000.a. + + * Changed the declaration of do_value_param so it DOES NOT say + Static int do_value_param(...., const_t const); + This caused the AIX compiler to fail in a very obscure way! + +Thu Mar 26 05:20:04 1992 John Salmon (johns at kastor) + + * Some minor surgery on SDF-parse.y to deal with zero-length + blocks at the end of the data file. We now try to fstat the + file to figure out how many records will fit in the file. This + should make writing generic tree-file readers easier, because + "npart" is implicit. + +Tue Mar 24 09:32:01 1992 John Salmon (johns at haggis) + + * "Released" v1.2.0. + + * Changed the Makefile, SDFfuncs.c and SDF-parse.y so the + bison-generated externals now start with SDFyy, i.e., + SDFyyparse, SDFyyerror, etc. This makes it easier to merge + SDF with programs like sm. + +Thu Mar 19 05:05:12 1992 John Salmon (johns at haggis) + + * Removed #pragma once from the rest of the .h files + + * Changed malloc to calloc in SDFopen. + +Fri Mar 13 08:24:32 1992 John Salmon (johns at haggis) + + * Rebuilt SDF_delta.a and SDF_sun4.a + + * Removed #pragma once from all the .h files. + + * Added dependency for SDF-lex.c and SDF-parse.o to Makefile + so changes to SDF-lex.l are understood by make. + + * Added the 'unsigned' keyword to SDF-lex.l. It's a total + no-op. It may make it somewhat easier (and dangerous?) to + convert C structs into SDF headers. + + * Changed the definition of the end-of-header symbol. + Now it's any comment line containing the string SDF-EOH. + The newline is the last character in the header. It is + highly recommended that users add their own form-feeds + to this line, but it is now at the user's discretion. + +Thu Mar 12 22:23:37 1992 Mike Warren (msw at sampson) + + * (nbio_open) Added a break to the case NBIO_SDF_TYPE: + +Sun Feb 9 13:26:20 1992 John Salmon (johns at haggis) + + * Added some more error reporting to nbio. On most errors, + something is now written into nbio_errstring. If the error + is detected by SDF, then we (usually) copy SDFerrstring too. + + * Added the SDFhasname() and nbio_hasname() functions to test + for the existence of a name in a file. + +Fri Feb 7 18:32:04 1992 John Salmon (johns at haggis) + + * Added missing ';' in the "parameter byteorder=blaa; " + strings in nbio.c + + * Added the char nbio_errstring[] array for messages. + + * Added the char *nbio_type_names[] array. + + * Added the "seekrd" functions to SDF and nbio, which use the + fseekrd(...) "primitive". Hopefully, this will be supported + by servix on all future parallel machines. + + * Fiddled around with the header files. There's now only + one copy of the prototypes in the "public" files, nbio.h and + SDF.h. diff --git a/external/libsdf/libSDF/GNUmakefile b/external/libsdf/libSDF/GNUmakefile new file mode 100644 index 0000000..062b13a --- /dev/null +++ b/external/libsdf/libSDF/GNUmakefile @@ -0,0 +1,64 @@ +# Make.$(ARCH) sets many of the variables used below including: +# CC, CFLAGS, AS, RANLIB, objdir, objsuf, asmdir + +treedir=.. +treedir_sed=\.\. +appexcludes= +# Put everything into the libsw library!!! +libname=libsw + +# The "SDF" library +src:= \ +SDF-parse.c SDFfuncs.c SDFget.c SDFhdrio.c + +include $(treedir)/Make-common/Make.$(ARCH) + +include $(treedir)/Make-common/Make.generic + +# These rules are slight modifications of the builtin ones +$(objdir)/%.c : %.y + $(YACC.y) $< + mv -f y.tab.c $@ + +$(objdir)/%.c : %.l +# commands to execute (built-in): + @$(RM) $@ + $(LEX.l) $< > $@ + +# Makedepends can't pick these up... +$(objdir)/SDF-parse$(objsuf): SDF-private.h $(objdir)/SDF-lex.c $(objdir)/SDF-parse.c + (cd $(objdir); $(CC) $(CFLAGS) -I../../../include -I../.. -c SDF-parse.c) + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +$(objdir)/SDF-parse$(objsuf): +$(objdir)/SDF-parse$(objsuf): +$(objdir)/SDF-parse$(objsuf): $(treedir)/include/libsdf/protos.h +$(objdir)/SDF-parse$(objsuf): $(treedir)/include/libsdf/Msgs.h +$(objdir)/SDF-parse$(objsuf): $(treedir)/include/libsdf/gccextensions.h SDF-private.h stdio.h +$(objdir)/SDF-parse$(objsuf): $(treedir)/include/libsdf/mpmy_io.h +$(objdir)/SDF-parse$(objsuf): $(treedir)/include/libsdf/SDF.h $(treedir)/include/libsdf/Malloc.h +$(objdir)/SDF-parse$(objsuf): $(treedir)/include/libsdf/error.h SDF-lex.c +$(objdir)/SDF-parse$(objsuf): +$(objdir)/SDF-parse$(objsuf): +$(objdir)/SDFfuncs$(objsuf): +$(objdir)/SDFfuncs$(objsuf): +$(objdir)/SDFfuncs$(objsuf): +$(objdir)/SDFfuncs$(objsuf): +$(objdir)/SDFfuncs$(objsuf): $(treedir)/include/libsdf/Msgs.h $(treedir)/include/libsdf/gccextensions.h +$(objdir)/SDFfuncs$(objsuf): stdio.h $(treedir)/include/libsdf/mpmy_io.h SDF-private.h +$(objdir)/SDFfuncs$(objsuf): $(treedir)/include/libsdf/SDF.h +$(objdir)/SDFfuncs$(objsuf): $(treedir)/include/libsdf/byteswap.h $(treedir)/include/libsdf/Malloc.h +$(objdir)/SDFfuncs$(objsuf): $(treedir)/include/libsdf/error.h $(treedir)/include/libsdf/protos.h +$(objdir)/SDFfuncs$(objsuf): $(treedir)/include/libsdf/mpmy.h $(treedir)/include/libsdf/timers.h +$(objdir)/SDFfuncs$(objsuf): +$(objdir)/SDFget$(objsuf): stdio.h $(treedir)/include/libsdf/mpmy_io.h +$(objdir)/SDFget$(objsuf): $(treedir)/include/libsdf/error.h $(treedir)/include/libsdf/gccextensions.h +$(objdir)/SDFget$(objsuf): $(treedir)/include/libsdf/SDF.h +$(objdir)/SDFhdrio$(objsuf): +$(objdir)/SDFhdrio$(objsuf): $(treedir)/include/libsdf/Msgs.h $(treedir)/include/libsdf/gccextensions.h +$(objdir)/SDFhdrio$(objsuf): $(treedir)/include/libsdf/error.h SDF-private.h +$(objdir)/SDFhdrio$(objsuf): stdio.h +$(objdir)/SDFhdrio$(objsuf): $(treedir)/include/libsdf/mpmy_io.h +$(objdir)/SDFhdrio$(objsuf): +$(objdir)/SDFhdrio$(objsuf): $(treedir)/include/libsdf/SDF.h diff --git a/external/libsdf/libSDF/README b/external/libsdf/libSDF/README new file mode 100644 index 0000000..787d10a --- /dev/null +++ b/external/libsdf/libSDF/README @@ -0,0 +1,199 @@ +--------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, + 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_.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 + +# SDF-EOH \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 \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. diff --git a/external/libsdf/libSDF/SDF-lex.c b/external/libsdf/libSDF/SDF-lex.c new file mode 100644 index 0000000..4dd8101 --- /dev/null +++ b/external/libsdf/libSDF/SDF-lex.c @@ -0,0 +1,2055 @@ + +#line 3 "" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 35 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; +#endif /* ! C99 */ + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! FLEXINT_H */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +/* C99 requires __STDC__ to be defined as 1. */ +#if defined (__STDC__) + +#define YY_USE_CONST + +#endif /* defined (__STDC__) */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN (yy_start) = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START (((yy_start) - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart(yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#define YY_BUF_SIZE 16384 +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +extern int yyleng; + +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + #define YY_LESS_LINENO(n) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = (yy_hold_char); \ + YY_RESTORE_YY_MORE_OFFSET \ + (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, (yytext_ptr) ) + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* Stack of input buffers. */ +static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ +static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ +static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ + ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ + : NULL) + +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; +static int yy_n_chars; /* number of characters read into yy_ch_buf */ +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 0; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart (FILE *input_file ); +void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ); +YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ); +void yy_delete_buffer (YY_BUFFER_STATE b ); +void yy_flush_buffer (YY_BUFFER_STATE b ); +void yypush_buffer_state (YY_BUFFER_STATE new_buffer ); +void yypop_buffer_state (void ); + +static void yyensure_buffer_stack (void ); +static void yy_load_buffer_state (void ); +static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ); + +#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ) + +YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ); +YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ); +YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len ); + +void *yyalloc (yy_size_t ); +void *yyrealloc (void *,yy_size_t ); +void yyfree (void * ); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + yyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer(yyin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + yyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer(yyin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +typedef unsigned char YY_CHAR; + +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; + +typedef int yy_state_type; + +extern int yylineno; + +int yylineno = 1; + +extern char *yytext; +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state (void ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); +static int yy_get_next_buffer (void ); +static void yy_fatal_error (yyconst char msg[] ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + (yytext_ptr) = yy_bp; \ + yyleng = (size_t) (yy_cp - yy_bp); \ + (yy_hold_char) = *yy_cp; \ + *yy_cp = '\0'; \ + (yy_c_buf_p) = yy_cp; + +#define YY_NUM_RULES 26 +#define YY_END_OF_BUFFER 27 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static yyconst flex_int16_t yy_accept[119] = + { 0, + 0, 0, 27, 25, 3, 3, 25, 2, 25, 24, + 25, 25, 23, 23, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 0, 17, 2, 2, 0, 23, + 19, 4, 18, 22, 0, 0, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 2, 0, 18, + 0, 0, 20, 21, 16, 16, 16, 16, 7, 16, + 16, 16, 16, 16, 2, 0, 19, 0, 0, 18, + 16, 5, 16, 16, 16, 8, 16, 16, 16, 16, + 2, 0, 18, 16, 16, 10, 16, 16, 6, 16, + 16, 2, 16, 11, 16, 16, 12, 16, 2, 16, + + 9, 16, 16, 1, 16, 16, 13, 1, 1, 15, + 14, 1, 1, 1, 1, 1, 1, 0 + } ; + +static yyconst flex_int32_t yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 4, 5, 1, 1, 1, 1, 1, + 1, 6, 7, 8, 9, 10, 11, 12, 13, 13, + 13, 14, 13, 15, 13, 16, 16, 1, 17, 1, + 18, 1, 1, 1, 19, 19, 19, 20, 21, 22, + 23, 24, 23, 23, 23, 23, 23, 23, 25, 23, + 23, 23, 26, 23, 23, 23, 23, 23, 23, 23, + 27, 1, 28, 1, 29, 1, 30, 31, 32, 33, + + 34, 35, 36, 37, 38, 23, 23, 39, 40, 41, + 42, 43, 23, 44, 45, 46, 47, 23, 23, 48, + 49, 23, 50, 1, 51, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst flex_int32_t yy_meta[52] = + { 0, + 1, 1, 2, 1, 1, 1, 1, 1, 1, 3, + 1, 4, 4, 4, 4, 4, 1, 1, 5, 5, + 4, 5, 6, 6, 6, 6, 1, 1, 6, 5, + 5, 5, 5, 4, 5, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 1, + 1 + } ; + +static yyconst flex_int16_t yy_base[125] = + { 0, + 0, 0, 281, 282, 282, 282, 276, 253, 42, 282, + 47, 272, 54, 55, 0, 228, 239, 233, 235, 232, + 230, 241, 34, 229, 265, 282, 242, 52, 69, 69, + 79, 282, 93, 219, 103, 0, 0, 220, 235, 217, + 221, 216, 220, 216, 217, 214, 212, 51, 116, 121, + 131, 136, 144, 0, 222, 211, 223, 223, 237, 215, + 220, 205, 201, 209, 78, 149, 154, 164, 169, 174, + 204, 0, 206, 198, 229, 0, 202, 195, 208, 203, + 75, 179, 184, 194, 203, 0, 207, 201, 0, 188, + 192, 72, 195, 0, 169, 159, 0, 170, 96, 169, + + 0, 141, 106, 85, 55, 42, 0, 48, 181, 0, + 0, 180, 115, 100, 128, 148, 27, 282, 207, 213, + 217, 218, 221, 226 + } ; + +static yyconst flex_int16_t yy_def[125] = + { 0, + 118, 1, 118, 118, 118, 118, 119, 120, 118, 118, + 118, 118, 118, 121, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 119, 118, 120, 120, 118, 121, + 118, 118, 118, 13, 118, 123, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 120, 118, 118, + 118, 118, 118, 123, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 120, 118, 118, 118, 118, 118, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 120, 118, 118, 122, 122, 122, 122, 122, 122, 122, + 122, 120, 122, 122, 122, 122, 122, 122, 120, 122, + + 122, 122, 122, 124, 122, 122, 122, 124, 124, 122, + 122, 124, 124, 124, 124, 124, 124, 0, 118, 118, + 118, 118, 118, 118 + } ; + +static yyconst flex_int16_t yy_nxt[334] = + { 0, + 4, 5, 6, 7, 8, 4, 9, 10, 9, 11, + 12, 13, 14, 14, 14, 14, 10, 10, 15, 15, + 15, 15, 15, 15, 15, 15, 10, 10, 15, 15, + 16, 17, 18, 15, 19, 15, 15, 20, 21, 15, + 15, 15, 22, 15, 23, 15, 24, 15, 15, 10, + 10, 29, 109, 30, 30, 30, 30, 30, 31, 31, + 31, 31, 31, 33, 33, 34, 34, 34, 34, 30, + 45, 48, 65, 109, 35, 35, 28, 28, 33, 46, + 31, 31, 31, 31, 31, 111, 81, 35, 35, 35, + 31, 31, 31, 31, 31, 92, 99, 28, 110, 49, + + 28, 36, 35, 28, 50, 50, 50, 50, 50, 52, + 109, 52, 49, 51, 53, 53, 53, 53, 53, 104, + 115, 28, 66, 114, 66, 109, 51, 67, 67, 67, + 67, 67, 50, 50, 50, 50, 50, 69, 107, 69, + 109, 68, 70, 70, 70, 70, 70, 53, 53, 53, + 53, 53, 116, 109, 68, 53, 53, 53, 53, 53, + 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, + 82, 117, 82, 109, 106, 83, 83, 83, 83, 83, + 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + + 112, 113, 105, 103, 102, 109, 109, 25, 25, 25, + 25, 25, 25, 27, 101, 27, 27, 27, 27, 30, + 30, 37, 37, 37, 54, 54, 108, 100, 108, 108, + 108, 108, 98, 97, 96, 95, 94, 93, 91, 90, + 89, 88, 87, 86, 85, 84, 80, 79, 78, 77, + 76, 75, 74, 73, 72, 71, 64, 63, 62, 61, + 60, 59, 58, 57, 56, 55, 118, 28, 26, 47, + 44, 43, 42, 41, 40, 39, 38, 32, 28, 26, + 118, 3, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 118 + } ; + +static yyconst flex_int16_t yy_chk[334] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 9, 117, 9, 9, 9, 9, 9, 11, 11, + 11, 11, 11, 13, 14, 13, 13, 13, 13, 13, + 23, 28, 48, 108, 13, 14, 48, 28, 30, 23, + 29, 29, 29, 29, 29, 106, 65, 13, 14, 30, + 31, 31, 31, 31, 31, 81, 92, 92, 105, 31, + + 81, 13, 30, 65, 33, 33, 33, 33, 33, 35, + 104, 35, 31, 33, 35, 35, 35, 35, 35, 99, + 114, 99, 49, 113, 49, 114, 33, 49, 49, 49, + 49, 49, 50, 50, 50, 50, 50, 51, 103, 51, + 113, 50, 51, 51, 51, 51, 51, 52, 52, 52, + 52, 52, 115, 115, 50, 53, 53, 53, 53, 53, + 66, 66, 66, 66, 66, 67, 67, 67, 67, 67, + 68, 116, 68, 116, 102, 68, 68, 68, 68, 68, + 69, 69, 69, 69, 69, 70, 70, 70, 70, 70, + 82, 82, 82, 82, 82, 83, 83, 83, 83, 83, + + 109, 112, 100, 98, 96, 112, 109, 119, 119, 119, + 119, 119, 119, 120, 95, 120, 120, 120, 120, 121, + 121, 122, 122, 122, 123, 123, 124, 93, 124, 124, + 124, 124, 91, 90, 88, 87, 85, 84, 80, 79, + 78, 77, 75, 74, 73, 71, 64, 63, 62, 61, + 60, 59, 58, 57, 56, 55, 47, 46, 45, 44, + 43, 42, 41, 40, 39, 38, 34, 27, 25, 24, + 22, 21, 20, 19, 18, 17, 16, 12, 8, 7, + 3, 118, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, + 118, 118, 118 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +extern int yy_flex_debug; +int yy_flex_debug = 0; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *yytext; +#line 1 "SDF-lex.l" +#line 2 "SDF-lex.l" +/* + SDF Library for reading Self-Describing Files + Copyright (C) 1991,1992 John K. Salmon + + Terms and conditions are specified in the file "copyright.h", + and more precisely in the file COPYING.LIB which you should have + received with this library. +*/ +#include +/* This define means we don't have to link with the lex library! */ +#define YY_SKIP_YYWRAP +#define yywrap() 1 + +/* This one is ugly. + Lex's output contains fprintf(yyout, of various error messages. + We try here to redirect them to a Msg_doalist. */ +#include +#include "Msgs.h" +#undef fprintf +#define fprintf MYFprintf +void MYFprintf(int *junk, const char *fmt, ...){ + va_list alist; + va_start(alist, fmt); + Msg_doalist(fmt, alist); + va_end(alist); +} + +#ifdef FLEX_SCANNER +/* Flex DOES have a much better way to handle non-standard input strategies. + This doesn't have to be this twisted to work with Flex, but if we are + going to continue to support lex, it's easiest to just follow along */ +#define YY_INPUT(buf, result, maxsize) \ + { \ + int c = SDF_Hdrgetc(); \ + /* Msgf(("YY_INPUT: c=%c\n", c)); */\ + result = (c==EOF) ? YY_NULL : (buf[0] = c, 1); \ + } +/* Flex also has some new-and-different behavior AFTER YY_INPUT has returned + NULL. In particular, all subsequent calls to yylex will immediately + return NULL unless yyrestart is called. If we were always using Flex, + I could attach this to the BEGIN rule, but I can't do that with lex, + so I have to call it from outside, e.g., in SDFyyprepare. */ +void SDFlexprepare(void){ + yyrestart(NULL); +} +#else /* Not FLEX_SCANNER */ +void SDFlexprepare(void){} +#endif +#line 611 "" + +#define INITIAL 0 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +static int yy_init_globals (void ); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int yylex_destroy (void ); + +int yyget_debug (void ); + +void yyset_debug (int debug_flag ); + +YY_EXTRA_TYPE yyget_extra (void ); + +void yyset_extra (YY_EXTRA_TYPE user_defined ); + +FILE *yyget_in (void ); + +void yyset_in (FILE * in_str ); + +FILE *yyget_out (void ); + +void yyset_out (FILE * out_str ); + +int yyget_leng (void ); + +char *yyget_text (void ); + +int yyget_lineno (void ); + +void yyset_lineno (int line_number ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap (void ); +#else +extern int yywrap (void ); +#endif +#endif + + static void yyunput (int c,char *buf_ptr ); + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ); +#endif + +#ifndef YY_NO_INPUT + +#ifdef __cplusplus +static int yyinput (void ); +#else +static int input (void ); +#endif + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO fwrite( yytext, yyleng, 1, yyout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + { \ + int c = '*'; \ + int n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else \ + { \ + errno=0; \ + while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(yyin); \ + } \ + }\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int yylex (void); + +#define YY_DECL int yylex (void) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +#line 60 "SDF-lex.l" + +#line 795 "" + + if ( !(yy_init) ) + { + (yy_init) = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! (yy_start) ) + (yy_start) = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! YY_CURRENT_BUFFER ) { + yyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer(yyin,YY_BUF_SIZE ); + } + + yy_load_buffer_state( ); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = (yy_c_buf_p); + + /* Support of yytext. */ + *yy_cp = (yy_hold_char); + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = (yy_start); +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 119 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 282 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + +do_action: /* This label is used only to access EOF actions. */ + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = (yy_hold_char); + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 61 "SDF-lex.l" +{SDFlineno++; return EOHDR;} /* Terminate the header on a comment line */ + YY_BREAK +case 2: +YY_RULE_SETUP +#line 62 "SDF-lex.l" +{SDFlineno++;} /* Otherwise, skip comments from '#' to eol. */ + YY_BREAK +case 3: +/* rule 3 can match eol */ +YY_RULE_SETUP +#line 63 "SDF-lex.l" +{if(yytext[0] == '\n') SDFlineno++;} /* skip white space. count lines*/ + YY_BREAK +case 4: +YY_RULE_SETUP +#line 64 "SDF-lex.l" +{ int c; + loop: + while((c=input()) != '*') {if(c=='\n') SDFlineno++;} + switch(input()){ + case '/': break; + case '*': unput('*'); + default: goto loop; + } + } /* Skip normal C comments. (no nesting) */ + YY_BREAK +case 5: +YY_RULE_SETUP +#line 73 "SDF-lex.l" +{yylval.type = SDF_CHAR; return TYPE;} + YY_BREAK +case 6: +YY_RULE_SETUP +#line 74 "SDF-lex.l" +{yylval.type = SDF_SHORT; return TYPE;} + YY_BREAK +case 7: +YY_RULE_SETUP +#line 75 "SDF-lex.l" +{yylval.type = SDF_INT; return TYPE;} + YY_BREAK +case 8: +YY_RULE_SETUP +#line 76 "SDF-lex.l" +{yylval.type = SDF_LONG; return TYPE;} + YY_BREAK +case 9: +YY_RULE_SETUP +#line 77 "SDF-lex.l" +{yylval.type = SDF_INT64; return TYPE;} + YY_BREAK +case 10: +YY_RULE_SETUP +#line 78 "SDF-lex.l" +{yylval.type = SDF_FLOAT; return TYPE;} + YY_BREAK +case 11: +YY_RULE_SETUP +#line 79 "SDF-lex.l" +{yylval.type = SDF_DOUBLE; return TYPE;} + YY_BREAK +case 12: +YY_RULE_SETUP +#line 80 "SDF-lex.l" +{return STRUCT;} + YY_BREAK +case 13: +YY_RULE_SETUP +#line 81 "SDF-lex.l" +; /* WARNING. The keyword 'unsigned' is skipped entirely. */ + YY_BREAK +case 14: +YY_RULE_SETUP +#line 82 "SDF-lex.l" +{return PARAMETER;} + YY_BREAK +case 15: +YY_RULE_SETUP +#line 83 "SDF-lex.l" +{yylval.valueparam = BYTEORDER; return VALUEPARAM;} + YY_BREAK +case 16: +YY_RULE_SETUP +#line 84 "SDF-lex.l" +{yylval.string = Malloc(yyleng+1); + strcpy(yylval.string, (char *)yytext); +#if YYDEBUG + if(yydebug) + printf("lex-malloc(%d) at 0x%lx\n", + yyleng+1, (unsigned long)yylval.string); +#endif + return NAME;} + YY_BREAK +case 17: +/* rule 17 can match eol */ +YY_RULE_SETUP +#line 92 "SDF-lex.l" +{ + /* strings extend to the next double-quote. */ + /* there are no escapes, and no exceptions. */ + /* We fiddle with the yyleng so we only get the contents in yylval. */ + /* Newlines embedded in strings will be missed by SDFlineno! */ + yylval.constant.u.stringval = Malloc(yyleng-1); + strncpy(yylval.constant.u.stringval, (char *)yytext+1, yyleng-2); + yylval.constant.u.stringval[yyleng-2] = '\0'; + yylval.constant.type = SDF_STRING; +#if YYDEBUG + if(yydebug) + printf("lex-malloc(%d) = 0x%lx\n", yyleng-1, + (unsigned long)yylval.constant.u.stringval); +#endif + return CONST;} + YY_BREAK +case 18: +#line 108 "SDF-lex.l" +case 19: +#line 109 "SDF-lex.l" +case 20: +YY_RULE_SETUP +#line 109 "SDF-lex.l" +{ + yylval.constant.type = SDF_DOUBLE; + sscanf((char *)yytext, "%lf", &yylval.constant.u.doubleval); + return CONST;} + YY_BREAK +case 21: +YY_RULE_SETUP +#line 113 "SDF-lex.l" +{ + yylval.constant.type = SDF_INT64; +#if __WORDSIZE==64 + sscanf((char *)yytext+2, "%lx", &yylval.constant.u.int64val); +#else + sscanf((char *)yytext+2, "%llx", &yylval.constant.u.int64val); +#endif + return CONST;} + YY_BREAK +case 22: +YY_RULE_SETUP +#line 121 "SDF-lex.l" +{ + yylval.constant.type = SDF_INT64; +#if __WORDSIZE==64 + sscanf((char *)yytext+1, "%lo", &yylval.constant.u.int64val); +#else + sscanf((char *)yytext+1, "%llo", &yylval.constant.u.int64val); +#endif + return CONST;} + YY_BREAK +case 23: +YY_RULE_SETUP +#line 129 "SDF-lex.l" +{ + yylval.constant.type = SDF_INT64; +#if __WORDSIZE==64 + sscanf((char *)yytext, "%ld", &yylval.constant.u.int64val); +#else + sscanf((char *)yytext, "%lld", &yylval.constant.u.int64val); +#endif + return CONST;} + YY_BREAK +case 24: +YY_RULE_SETUP +#line 137 "SDF-lex.l" +{return yytext[0];} + YY_BREAK +case 25: +YY_RULE_SETUP +#line 138 "SDF-lex.l" +{yyerror("lexer confusion on char: <%c>, line: %d\n", (yytext[0])?yytext[0]:'?', + SDFlineno); return LEXERROR;} + YY_BREAK +case 26: +YY_RULE_SETUP +#line 140 "SDF-lex.l" +ECHO; + YY_BREAK +#line 1058 "" +case YY_STATE_EOF(INITIAL): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = (yy_hold_char); + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++(yy_c_buf_p); + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = (yy_c_buf_p); + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_END_OF_FILE: + { + (yy_did_buffer_switch_on_eof) = 0; + + if ( yywrap( ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = + (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + (yy_c_buf_p) = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ +} /* end of yylex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (void) +{ + register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + register char *source = (yytext_ptr); + register int number_to_move, i; + int ret_val; + + if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; + + else + { + int num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER; + + int yy_c_buf_p_offset = + (int) ((yy_c_buf_p) - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + (yy_n_chars), (size_t) num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + if ( (yy_n_chars) == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart(yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + } + + (yy_n_chars) += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; + + (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + + static yy_state_type yy_get_previous_state (void) +{ + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = (yy_start); + + for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 119 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) +{ + register int yy_is_jam; + register char *yy_cp = (yy_c_buf_p); + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 119 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 118); + + return yy_is_jam ? 0 : yy_current_state; +} + + static void yyunput (int c, register char * yy_bp ) +{ + register char *yy_cp; + + yy_cp = (yy_c_buf_p); + + /* undo effects of setting up yytext */ + *yy_cp = (yy_hold_char); + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = (yy_n_chars) + 2; + register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ + YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; + register char *source = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; + + while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + (yytext_ptr) = yy_bp; + (yy_hold_char) = *yy_cp; + (yy_c_buf_p) = yy_cp; +} + +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (void) +#else + static int input (void) +#endif + +{ + int c; + + *(yy_c_buf_p) = (yy_hold_char); + + if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + /* This was really a NUL. */ + *(yy_c_buf_p) = '\0'; + + else + { /* need more input */ + int offset = (yy_c_buf_p) - (yytext_ptr); + ++(yy_c_buf_p); + + switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart(yyin ); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap( ) ) + return EOF; + + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = (yytext_ptr) + offset; + break; + } + } + } + + c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ + *(yy_c_buf_p) = '\0'; /* preserve yytext */ + (yy_hold_char) = *++(yy_c_buf_p); + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * + * @note This function does not reset the start condition to @c INITIAL . + */ + void yyrestart (FILE * input_file ) +{ + + if ( ! YY_CURRENT_BUFFER ){ + yyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer(yyin,YY_BUF_SIZE ); + } + + yy_init_buffer(YY_CURRENT_BUFFER,input_file ); + yy_load_buffer_state( ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * + */ + void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) +{ + + /* TODO. We should be able to replace this entire function body + * with + * yypop_buffer_state(); + * yypush_buffer_state(new_buffer); + */ + yyensure_buffer_stack (); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + yy_load_buffer_state( ); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + (yy_did_buffer_switch_on_eof) = 1; +} + +static void yy_load_buffer_state (void) +{ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + (yy_hold_char) = *(yy_c_buf_p); +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * + * @return the allocated buffer state. + */ + YY_BUFFER_STATE yy_create_buffer (FILE * file, int size ) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer(b,file ); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with yy_create_buffer() + * + */ + void yy_delete_buffer (YY_BUFFER_STATE b ) +{ + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yyfree((void *) b->yy_ch_buf ); + + yyfree((void *) b ); +} + +#ifndef __cplusplus +extern int isatty (int ); +#endif /* __cplusplus */ + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a yyrestart() or at EOF. + */ + static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file ) + +{ + int oerrno = errno; + + yy_flush_buffer(b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then yy_init_buffer was _probably_ + * called from yyrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * + */ + void yy_flush_buffer (YY_BUFFER_STATE b ) +{ + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + yy_load_buffer_state( ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * + */ +void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) +{ + if (new_buffer == NULL) + return; + + yyensure_buffer_stack(); + + /* This block is copied from yy_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + (yy_buffer_stack_top)++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from yy_switch_to_buffer. */ + yy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * + */ +void yypop_buffer_state (void) +{ + if (!YY_CURRENT_BUFFER) + return; + + yy_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + if ((yy_buffer_stack_top) > 0) + --(yy_buffer_stack_top); + + if (YY_CURRENT_BUFFER) { + yy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void yyensure_buffer_stack (void) +{ + int num_to_alloc; + + if (!(yy_buffer_stack)) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; + (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + (yy_buffer_stack_max) = num_to_alloc; + (yy_buffer_stack_top) = 0; + return; + } + + if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + int grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = (yy_buffer_stack_max) + grow_size; + (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc + ((yy_buffer_stack), + num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + /* zero only the new slots.*/ + memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); + (yy_buffer_stack_max) = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer(b ); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to yylex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * yy_scan_bytes() instead. + */ +YY_BUFFER_STATE yy_scan_string (yyconst char * yystr ) +{ + + return yy_scan_bytes(yystr,strlen(yystr) ); +} + +/** Setup the input buffer state to scan the given bytes. The next call to yylex() will + * scan from a @e copy of @a bytes. + * @param bytes the byte buffer to scan + * @param len the number of bytes in the buffer pointed to by @a bytes. + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len ) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = _yybytes_len + 2; + buf = (char *) yyalloc(n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer(buf,n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yy_fatal_error (yyconst char* msg ) +{ + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + yytext[yyleng] = (yy_hold_char); \ + (yy_c_buf_p) = yytext + yyless_macro_arg; \ + (yy_hold_char) = *(yy_c_buf_p); \ + *(yy_c_buf_p) = '\0'; \ + yyleng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the current line number. + * + */ +int yyget_lineno (void) +{ + + return yylineno; +} + +/** Get the input stream. + * + */ +FILE *yyget_in (void) +{ + return yyin; +} + +/** Get the output stream. + * + */ +FILE *yyget_out (void) +{ + return yyout; +} + +/** Get the length of the current token. + * + */ +int yyget_leng (void) +{ + return yyleng; +} + +/** Get the current token. + * + */ + +char *yyget_text (void) +{ + return yytext; +} + +/** Set the current line number. + * @param line_number + * + */ +void yyset_lineno (int line_number ) +{ + + yylineno = line_number; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param in_str A readable stream. + * + * @see yy_switch_to_buffer + */ +void yyset_in (FILE * in_str ) +{ + yyin = in_str ; +} + +void yyset_out (FILE * out_str ) +{ + yyout = out_str ; +} + +int yyget_debug (void) +{ + return yy_flex_debug; +} + +void yyset_debug (int bdebug ) +{ + yy_flex_debug = bdebug ; +} + +static int yy_init_globals (void) +{ + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from yylex_destroy(), so don't allocate here. + */ + + (yy_buffer_stack) = 0; + (yy_buffer_stack_top) = 0; + (yy_buffer_stack_max) = 0; + (yy_c_buf_p) = (char *) 0; + (yy_init) = 0; + (yy_start) = 0; + +/* Defined in main.c */ +#ifdef YY_STDINIT + yyin = stdin; + yyout = stdout; +#else + yyin = (FILE *) 0; + yyout = (FILE *) 0; +#endif + + /* For future reference: Set errno on error, since we are called by + * yylex_init() + */ + return 0; +} + +/* yylex_destroy is for both reentrant and non-reentrant scanners. */ +int yylex_destroy (void) +{ + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + yy_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + yypop_buffer_state(); + } + + /* Destroy the stack itself. */ + yyfree((yy_buffer_stack) ); + (yy_buffer_stack) = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * yylex() is called, initialization will occur. */ + yy_init_globals( ); + + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) +{ + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * s ) +{ + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *yyalloc (yy_size_t size ) +{ + return (void *) malloc( size ); +} + +void *yyrealloc (void * ptr, yy_size_t size ) +{ + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); +} + +void yyfree (void * ptr ) +{ + free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" + +#line 140 "SDF-lex.l" diff --git a/external/libsdf/libSDF/SDF-lex.l b/external/libsdf/libSDF/SDF-lex.l new file mode 100644 index 0000000..b2905ed --- /dev/null +++ b/external/libsdf/libSDF/SDF-lex.l @@ -0,0 +1,139 @@ +%{ +/* + SDF Library for reading Self-Describing Files + Copyright (C) 1991,1992 John K. Salmon + + Terms and conditions are specified in the file "copyright.h", + and more precisely in the file COPYING.LIB which you should have + received with this library. +*/ +#include +/* This define means we don't have to link with the lex library! */ +#define YY_SKIP_YYWRAP +#define yywrap() 1 + +/* This one is ugly. + Lex's output contains fprintf(yyout, of various error messages. + We try here to redirect them to a Msg_doalist. */ +#include +#include "Msgs.h" +#undef fprintf +#define fprintf MYFprintf +void MYFprintf(int *junk, const char *fmt, ...){ + va_list alist; + va_start(alist, fmt); + Msg_doalist(fmt, alist); + va_end(alist); +} + +#ifdef FLEX_SCANNER +/* Flex DOES have a much better way to handle non-standard input strategies. + This doesn't have to be this twisted to work with Flex, but if we are + going to continue to support lex, it's easiest to just follow along */ +#define YY_INPUT(buf, result, maxsize) \ + { \ + int c = SDF_Hdrgetc(); \ + /* Msgf(("YY_INPUT: c=%c\n", c)); */\ + result = (c==EOF) ? YY_NULL : (buf[0] = c, 1); \ + } +/* Flex also has some new-and-different behavior AFTER YY_INPUT has returned + NULL. In particular, all subsequent calls to yylex will immediately + return NULL unless yyrestart is called. If we were always using Flex, + I could attach this to the BEGIN rule, but I can't do that with lex, + so I have to call it from outside, e.g., in SDFyyprepare. */ +void SDFlexprepare(void){ + yyrestart(NULL); +} +#else /* Not FLEX_SCANNER */ +void SDFlexprepare(void){} +#endif +%} +White [ \f\t\n] +Dig [0-9] +Alpha [A-Za-z_] +Hex [A-Fa-f0-9] +Octal [0-7] +Alphanum [A-Za-z0-9_] +Expon [Ee]{Sign}{Dig}+ +Punct "="|"["|"]"|"{"|"}"|";"|"," +Sign [-+]? +%% +#.*SDF-EOH.* {SDFlineno++; return EOHDR;} /* Terminate the header on a comment line */ +#.* {SDFlineno++;} /* Otherwise, skip comments from '#' to eol. */ +{White} {if(yytext[0] == '\n') SDFlineno++;} /* skip white space. count lines*/ +"/*" { int c; + loop: + while((c=input()) != '*') {if(c=='\n') SDFlineno++;} + switch(input()){ + case '/': break; + case '*': unput('*'); + default: goto loop; + } + } /* Skip normal C comments. (no nesting) */ +char {yylval.type = SDF_CHAR; return TYPE;} +short {yylval.type = SDF_SHORT; return TYPE;} +int {yylval.type = SDF_INT; return TYPE;} +long {yylval.type = SDF_LONG; return TYPE;} +int64_t {yylval.type = SDF_INT64; return TYPE;} +float {yylval.type = SDF_FLOAT; return TYPE;} +double {yylval.type = SDF_DOUBLE; return TYPE;} +struct {return STRUCT;} +unsigned ; /* WARNING. The keyword 'unsigned' is skipped entirely. */ +parameter {return PARAMETER;} +byteorder {yylval.valueparam = BYTEORDER; return VALUEPARAM;} +{Alpha}{Alphanum}* {yylval.string = Malloc(yyleng+1); + strcpy(yylval.string, (char *)yytext); +#if YYDEBUG + if(yydebug) + printf("lex-malloc(%d) at 0x%lx\n", + yyleng+1, (unsigned long)yylval.string); +#endif + return NAME;} +\"[^"]*\" { + /* strings extend to the next double-quote. */ + /* there are no escapes, and no exceptions. */ + /* We fiddle with the yyleng so we only get the contents in yylval. */ + /* Newlines embedded in strings will be missed by SDFlineno! */ + yylval.constant.u.stringval = Malloc(yyleng-1); + strncpy(yylval.constant.u.stringval, (char *)yytext+1, yyleng-2); + yylval.constant.u.stringval[yyleng-2] = '\0'; + yylval.constant.type = SDF_STRING; +#if YYDEBUG + if(yydebug) + printf("lex-malloc(%d) = 0x%lx\n", yyleng-1, + (unsigned long)yylval.constant.u.stringval); +#endif + return CONST;} +{Sign}{Dig}+"."{Dig}*({Expon})? | +{Sign}{Dig}*"."{Dig}+({Expon})? | +{Sign}{Dig}+{Expon} { + yylval.constant.type = SDF_DOUBLE; + sscanf((char *)yytext, "%lf", &yylval.constant.u.doubleval); + return CONST;} +0x{Hex}+ { + yylval.constant.type = SDF_INT64; +#if __WORDSIZE==64 + sscanf((char *)yytext+2, "%lx", &yylval.constant.u.int64val); +#else + sscanf((char *)yytext+2, "%llx", &yylval.constant.u.int64val); +#endif + return CONST;} +0{Octal}+ { + yylval.constant.type = SDF_INT64; +#if __WORDSIZE==64 + sscanf((char *)yytext+1, "%lo", &yylval.constant.u.int64val); +#else + sscanf((char *)yytext+1, "%llo", &yylval.constant.u.int64val); +#endif + return CONST;} +{Sign}{Dig}+ { + yylval.constant.type = SDF_INT64; +#if __WORDSIZE==64 + sscanf((char *)yytext, "%ld", &yylval.constant.u.int64val); +#else + sscanf((char *)yytext, "%lld", &yylval.constant.u.int64val); +#endif + return CONST;} +{Punct} {return yytext[0];} +. {yyerror("lexer confusion on char: <%c>, line: %d\n", (yytext[0])?yytext[0]:'?', + SDFlineno); return LEXERROR;} diff --git a/external/libsdf/libSDF/SDF-parse.c b/external/libsdf/libSDF/SDF-parse.c new file mode 100644 index 0000000..0e8c1e3 --- /dev/null +++ b/external/libsdf/libSDF/SDF-parse.c @@ -0,0 +1,2366 @@ +/* A Bison parser, made by GNU Bison 2.3. */ + +/* Skeleton implementation for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Bison version. */ +#define YYBISON_VERSION "2.3" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 0 + +/* Using locations. */ +#define YYLSP_NEEDED 0 + + + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + STRUCT = 258, + NAME = 259, + TYPE = 260, + CONST = 261, + VALUEPARAM = 262, + PARAMETER = 263, + EOHDR = 264, + LEXERROR = 265 + }; +#endif +/* Tokens. */ +#define STRUCT 258 +#define NAME 259 +#define TYPE 260 +#define CONST 261 +#define VALUEPARAM 262 +#define PARAMETER 263 +#define EOHDR 264 +#define LEXERROR 265 + + + + +/* Copy the first part of user declarations. */ +#line 1 "SDF-parse.y" + +/* + SDF Library for reading Self-Describing Files + Copyright (C) 1991,1992 John K. Salmon + + Terms and conditions are specified in the file "copyright.h", + and more precisely in the file COPYING.LIB which you should have + received with this library. +*/ + +/* We don't rely on bison's -p argument any more. + Instead, just #define the name changes ourselves. These are taken + from the beginning of bison -p output. These are far from a complete + set of external 'yy' names, as a quick run throug 'nm' will show. Maybe + all the others come from lex. I dunno. In any event, the namespace is only + partially cleaned up. Perhaps we should apply for Superfund money + to finish the cleanup? bison -p does no better. +*/ +#define yyparse SDFyyparse +#define yylex SDFyylex +#define yyerror SDFyyerror +#define yylval SDFyylval +#define yychar SDFyychar +#define yydebug SDFyydebug +#define yynerrs SDFyynerrs + +#include +#include +#include +#include +#include "protos.h" +#include "Msgs.h" +#include "SDF-private.h" +#include "obstack.h" +#include "Malloc.h" + +#ifndef __DELTA__ +#define YYDEBUG 1 +#endif + +#if YYDEBUG +/* yacc sends its debug output throught printf. We change that... */ +#define printf Msg_do /* MUST be after protos.h!!! */ +#endif + +#ifdef cray +/* This wants to be a long on the cray?? */ +extern long int yydebug; +#else +extern int yydebug; +#endif +extern void yyerror(char *fmt, ...); + + +static enum SDF_type_enum curtype; +static blk_descrip_t cur_blk; +static int cur_file_offset; +static int cur_data_offset; +static SDF *cur_hdr; +static int no_more_data_blks; +static int zero_len_blknum; + +char *SDFtype_names[] = {"notype", "char", "short", "int", "long", "int64_t", + "float", "double", "string"}; + + int SDFtype_sizes[] = {0, sizeof(char), sizeof(short), sizeof(int), sizeof(long), + sizeof(int64_t), sizeof(float), sizeof(double), sizeof(char *)}; + +static int do_value_param(enum value_param_enum type, const_t value); +static int data_dcl(declaration_t dcl); +static int const_dcl(declaration_t dcl, const_list_t consts); +static void finish_curblk(void); +static const_t convert_const(const_t *cp, enum SDF_type_enum type); +static int finish_parse(void); + + + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +/* Enabling the token table. */ +#ifndef YYTOKEN_TABLE +# define YYTOKEN_TABLE 0 +#endif + +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef union YYSTYPE +#line 90 "SDF-parse.y" +{ + enum SDF_type_enum type; + enum value_param_enum valueparam; + char *string; + const_t constant; + declaration_t declaration; + dcl_list_t dcl_list; + one_dcl_t one_dcl; + const_list_t const_list; +} +/* Line 193 of yacc.c. */ +#line 204 "y.tab.c" + YYSTYPE; +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif + + + +/* Copy the second part of user declarations. */ + + +/* Line 216 of yacc.c. */ +#line 217 "y.tab.c" + +#ifdef short +# undef short +#endif + +#ifdef YYTYPE_UINT8 +typedef YYTYPE_UINT8 yytype_uint8; +#else +typedef unsigned char yytype_uint8; +#endif + +#ifdef YYTYPE_INT8 +typedef YYTYPE_INT8 yytype_int8; +#elif (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +typedef signed char yytype_int8; +#else +typedef short int yytype_int8; +#endif + +#ifdef YYTYPE_UINT16 +typedef YYTYPE_UINT16 yytype_uint16; +#else +typedef unsigned short int yytype_uint16; +#endif + +#ifdef YYTYPE_INT16 +typedef YYTYPE_INT16 yytype_int16; +#else +typedef short int yytype_int16; +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned int +# endif +#endif + +#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) + +#ifndef YY_ +# if YYENABLE_NLS +# if ENABLE_NLS +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_(msgid) dgettext ("bison-runtime", msgid) +# endif +# endif +# ifndef YY_ +# define YY_(msgid) msgid +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(e) ((void) (e)) +#else +# define YYUSE(e) /* empty */ +#endif + +/* Identity function, used to suppress warnings about constant conditions. */ +#ifndef lint +# define YYID(n) (n) +#else +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static int +YYID (int i) +#else +static int +YYID (i) + int i; +#endif +{ + return i; +} +#endif + +#if ! defined yyoverflow || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined _STDLIB_H \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ + + +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yytype_int16 yyss; + YYSTYPE yyvs; + }; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (YYID (0)) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack, Stack, yysize); \ + Stack = &yyptr->Stack; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (YYID (0)) + +#endif + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 13 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 44 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 18 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 12 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 26 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 48 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 265 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const yytype_uint8 yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 17, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 11, + 2, 12, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 13, 2, 14, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 15, 2, 16, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10 +}; + +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const yytype_uint8 yyprhs[] = +{ + 0, 0, 3, 5, 8, 10, 12, 15, 18, 23, + 29, 31, 37, 46, 54, 56, 60, 61, 65, 67, + 71, 73, 78, 82, 84, 88, 90 +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const yytype_int8 yyrhs[] = +{ + 19, 0, -1, 20, -1, 20, 9, -1, 10, -1, + 21, -1, 20, 21, -1, 22, 11, -1, 22, 12, + 28, 11, -1, 8, 7, 12, 6, 11, -1, 24, + -1, 3, 15, 23, 11, 16, -1, 3, 15, 23, + 11, 16, 13, 6, 14, -1, 3, 15, 23, 11, + 16, 13, 14, -1, 24, -1, 23, 11, 24, -1, + -1, 5, 25, 26, -1, 27, -1, 26, 17, 27, + -1, 4, -1, 4, 13, 6, 14, -1, 4, 13, + 14, -1, 6, -1, 15, 29, 16, -1, 6, -1, + 29, 17, 6, -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const yytype_uint8 yyrline[] = +{ + 0, 101, 101, 102, 103, 106, 107, 110, 111, 112, + 115, 116, 117, 126, 130, 131, 143, 143, 146, 152, + 160, 161, 170, 173, 179, 182, 188 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "STRUCT", "NAME", "TYPE", "CONST", + "VALUEPARAM", "PARAMETER", "EOHDR", "LEXERROR", "';'", "'='", "'['", + "']'", "'{'", "'}'", "','", "$accept", "hdr", "hdr1", "stmt", + "declaration", "many_typed_dcl_list", "typed_dcl_list", "@1", + "comma_sep_dcls", "dcl1", "const_lst", "comma_sep_consts", 0 +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const yytype_uint16 yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 59, 61, 91, 93, 123, 125, 44 +}; +# endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint8 yyr1[] = +{ + 0, 18, 19, 19, 19, 20, 20, 21, 21, 21, + 22, 22, 22, 22, 23, 23, 25, 24, 26, 26, + 27, 27, 27, 28, 28, 29, 29 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const yytype_uint8 yyr2[] = +{ + 0, 2, 1, 2, 1, 1, 2, 2, 4, 5, + 1, 5, 8, 7, 1, 3, 0, 3, 1, 3, + 1, 4, 3, 1, 3, 1, 3 +}; + +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const yytype_uint8 yydefact[] = +{ + 0, 0, 16, 0, 4, 0, 2, 5, 0, 10, + 0, 0, 0, 1, 3, 6, 7, 0, 0, 14, + 20, 17, 18, 0, 23, 0, 0, 0, 0, 0, + 0, 25, 0, 8, 11, 15, 0, 22, 19, 9, + 24, 0, 0, 21, 26, 0, 13, 12 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int8 yydefgoto[] = +{ + -1, 5, 6, 7, 8, 18, 9, 11, 21, 22, + 26, 32 +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -14 +static const yytype_int8 yypact[] = +{ + 13, -13, -14, 2, -14, 5, 17, -14, 16, -14, + 10, 6, 7, -14, -14, -14, -14, -2, 18, -14, + 11, 14, -14, 24, -14, 26, 22, -4, -3, 6, + 23, -14, -9, -14, 25, -14, 21, -14, -14, -14, + -14, 30, 0, -14, -14, 27, -14, -14 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const yytype_int8 yypgoto[] = +{ + -14, -14, -14, 31, -14, -14, -10, -14, -14, 15, + -14, -14 +}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -1 +static const yytype_uint8 yytable[] = +{ + 19, 2, 10, 36, 24, 13, 45, 40, 41, 12, + 20, 37, 34, 25, 46, 2, 1, 35, 2, 23, + 1, 3, 2, 4, 28, 3, 14, 16, 17, 27, + 30, 29, 31, 33, 39, 43, 44, 15, 42, 0, + 0, 47, 0, 0, 38 +}; + +static const yytype_int8 yycheck[] = +{ + 10, 5, 15, 6, 6, 0, 6, 16, 17, 7, + 4, 14, 16, 15, 14, 5, 3, 27, 5, 12, + 3, 8, 5, 10, 13, 8, 9, 11, 12, 11, + 6, 17, 6, 11, 11, 14, 6, 6, 13, -1, + -1, 14, -1, -1, 29 +}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const yytype_uint8 yystos[] = +{ + 0, 3, 5, 8, 10, 19, 20, 21, 22, 24, + 15, 25, 7, 0, 9, 21, 11, 12, 23, 24, + 4, 26, 27, 12, 6, 15, 28, 11, 13, 17, + 6, 6, 29, 11, 16, 24, 6, 14, 27, 11, + 16, 17, 13, 14, 6, 6, 14, 14 +}; + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ + +#define YYFAIL goto yyerrlab + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yytoken = YYTRANSLATE (yychar); \ + YYPOPSTACK (1); \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ +while (YYID (0)) + + +#define YYTERROR 1 +#define YYERRCODE 256 + + +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (YYID (N)) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + } \ + while (YYID (0)) +#endif + + +/* YY_LOCATION_PRINT -- Print the location on the stream. + This macro was not mandated originally: define only if we know + we won't break user code: when these are the locations we know. */ + +#ifndef YY_LOCATION_PRINT +# if YYLTYPE_IS_TRIVIAL +# define YY_LOCATION_PRINT(File, Loc) \ + fprintf (File, "%d.%d-%d.%d", \ + (Loc).first_line, (Loc).first_column, \ + (Loc).last_line, (Loc).last_column) +# else +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# endif +#endif + + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#ifdef YYLEX_PARAM +# define YYLEX yylex (YYLEX_PARAM) +#else +# define YYLEX yylex () +#endif + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (YYID (0)) + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (YYID (0)) + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +#else +static void +yy_symbol_value_print (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; +#endif +{ + if (!yyvaluep) + return; +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# else + YYUSE (yyoutput); +# endif + switch (yytype) + { + default: + break; + } +} + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +#else +static void +yy_symbol_print (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; +#endif +{ + if (yytype < YYNTOKENS) + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); + else + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + + yy_symbol_value_print (yyoutput, yytype, yyvaluep); + YYFPRINTF (yyoutput, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_stack_print (yytype_int16 *bottom, yytype_int16 *top) +#else +static void +yy_stack_print (bottom, top) + yytype_int16 *bottom; + yytype_int16 *top; +#endif +{ + YYFPRINTF (stderr, "Stack now"); + for (; bottom <= top; ++bottom) + YYFPRINTF (stderr, " %d", *bottom); + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (YYID (0)) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_reduce_print (YYSTYPE *yyvsp, int yyrule) +#else +static void +yy_reduce_print (yyvsp, yyrule) + YYSTYPE *yyvsp; + int yyrule; +#endif +{ + int yynrhs = yyr2[yyrule]; + int yyi; + unsigned long int yylno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + fprintf (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], + &(yyvsp[(yyi + 1) - (yynrhs)]) + ); + fprintf (stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyvsp, Rule); \ +} while (YYID (0)) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined __GLIBC__ && defined _STRING_H +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static YYSIZE_T +yystrlen (const char *yystr) +#else +static YYSIZE_T +yystrlen (yystr) + const char *yystr; +#endif +{ + YYSIZE_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) + continue; + return yylen; +} +# endif +# endif + +# ifndef yystpcpy +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static char * +yystpcpy (char *yydest, const char *yysrc) +#else +static char * +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +#endif +{ + char *yyd = yydest; + const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + YYSIZE_T yyn = 0; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes: ; + } + + if (! yyres) + return yystrlen (yystr); + + return yystpcpy (yyres, yystr) - yyres; +} +# endif + +/* Copy into YYRESULT an error message about the unexpected token + YYCHAR while in state YYSTATE. Return the number of bytes copied, + including the terminating null byte. If YYRESULT is null, do not + copy anything; just return the number of bytes that would be + copied. As a special case, return 0 if an ordinary "syntax error" + message will do. Return YYSIZE_MAXIMUM if overflow occurs during + size calculation. */ +static YYSIZE_T +yysyntax_error (char *yyresult, int yystate, int yychar) +{ + int yyn = yypact[yystate]; + + if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) + return 0; + else + { + int yytype = YYTRANSLATE (yychar); + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + int yysize_overflow = 0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + int yyx; + +# if 0 + /* This is so xgettext sees the translatable formats that are + constructed on the fly. */ + YY_("syntax error, unexpected %s"); + YY_("syntax error, unexpected %s, expecting %s"); + YY_("syntax error, unexpected %s, expecting %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); +# endif + char *yyfmt; + char const *yyf; + static char const yyunexpected[] = "syntax error, unexpected %s"; + static char const yyexpecting[] = ", expecting %s"; + static char const yyor[] = " or %s"; + char yyformat[sizeof yyunexpected + + sizeof yyexpecting - 1 + + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) + * (sizeof yyor - 1))]; + char const *yyprefix = yyexpecting; + + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 1; + + yyarg[0] = yytname[yytype]; + yyfmt = yystpcpy (yyformat, yyunexpected); + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + yyformat[sizeof yyunexpected - 1] = '\0'; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + yyfmt = yystpcpy (yyfmt, yyprefix); + yyprefix = yyor; + } + + yyf = YY_(yyformat); + yysize1 = yysize + yystrlen (yyf); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + + if (yysize_overflow) + return YYSIZE_MAXIMUM; + + if (yyresult) + { + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + char *yyp = yyresult; + int yyi = 0; + while ((*yyp = *yyf) != '\0') + { + if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyf += 2; + } + else + { + yyp++; + yyf++; + } + } + } + return yysize; + } +} +#endif /* YYERROR_VERBOSE */ + + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) +#else +static void +yydestruct (yymsg, yytype, yyvaluep) + const char *yymsg; + int yytype; + YYSTYPE *yyvaluep; +#endif +{ + YYUSE (yyvaluep); + + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + + switch (yytype) + { + + default: + break; + } +} + + +/* Prevent warnings from -Wmissing-prototypes. */ + +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int yyparse (void *YYPARSE_PARAM); +#else +int yyparse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int yyparse (void); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ + + + +/* The look-ahead symbol. */ +int yychar; + +/* The semantic value of the look-ahead symbol. */ +YYSTYPE yylval; + +/* Number of syntax errors so far. */ +int yynerrs; + + + +/*----------. +| yyparse. | +`----------*/ + +#ifdef YYPARSE_PARAM +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void *YYPARSE_PARAM) +#else +int +yyparse (YYPARSE_PARAM) + void *YYPARSE_PARAM; +#endif +#else /* ! YYPARSE_PARAM */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void) +#else +int +yyparse () + +#endif +#endif +{ + + int yystate; + int yyn; + int yyresult; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + /* Look-ahead token as an internal (translated) token number. */ + int yytoken = 0; +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif + + /* Three stacks and their tools: + `yyss': related to states, + `yyvs': related to semantic values, + `yyls': related to locations. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss = yyssa; + yytype_int16 *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + YYSTYPE *yyvsp; + + + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + + YYSIZE_T yystacksize = YYINITDEPTH; + + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss; + yyvsp = yyvs; + + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + yytype_int16 *yyss1 = yyss; + + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyexhaustedlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yytype_int16 *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss); + YYSTACK_RELOCATE (yyvs); + +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + + /* Do appropriate processing given the current state. Read a + look-ahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to look-ahead token. */ + yyn = yypact[yystate]; + if (yyn == YYPACT_NINF) + goto yydefault; + + /* Not known => get a look-ahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yyn == 0 || yyn == YYTABLE_NINF) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + if (yyn == YYFINAL) + YYACCEPT; + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the look-ahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the shifted token unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + yystate = yyn; + *++yyvsp = yylval; + + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 2: +#line 101 "SDF-parse.y" + {if(finish_parse()) YYERROR;} + break; + + case 3: +#line 102 "SDF-parse.y" + {if(finish_parse()) YYERROR; else YYACCEPT;} + break; + + case 4: +#line 103 "SDF-parse.y" + {YYERROR;} + break; + + case 7: +#line 110 "SDF-parse.y" + {if(data_dcl((yyvsp[(1) - (2)].declaration))) YYERROR;} + break; + + case 8: +#line 111 "SDF-parse.y" + {if(const_dcl((yyvsp[(1) - (4)].declaration), (yyvsp[(3) - (4)].const_list))) YYERROR;} + break; + + case 9: +#line 112 "SDF-parse.y" + {if(do_value_param((yyvsp[(2) - (5)].valueparam), (yyvsp[(4) - (5)].constant))) YYERROR;} + break; + + case 10: +#line 115 "SDF-parse.y" + {(yyval.declaration).dcl_list = (yyvsp[(1) - (1)].dcl_list); (yyval.declaration).Nrec = 1;} + break; + + case 11: +#line 116 "SDF-parse.y" + {(yyval.declaration).dcl_list=(yyvsp[(3) - (5)].dcl_list); (yyval.declaration).Nrec=1;} + break; + + case 12: +#line 118 "SDF-parse.y" + { + if( (yyvsp[(7) - (8)].constant).type != SDF_INT64 ){ + yyerror("Expected integer constant"); + YYERROR; + }else{ + (yyval.declaration).dcl_list = (yyvsp[(3) - (8)].dcl_list); (yyval.declaration).Nrec = (yyvsp[(7) - (8)].constant).u.int64val; + } + } + break; + + case 13: +#line 127 "SDF-parse.y" + { (yyval.declaration).dcl_list = (yyvsp[(3) - (7)].dcl_list); (yyval.declaration).Nrec = 0;} + break; + + case 14: +#line 130 "SDF-parse.y" + {(yyval.dcl_list) = (yyvsp[(1) - (1)].dcl_list);} + break; + + case 15: +#line 132 "SDF-parse.y" + { + int sz; + + (yyval.dcl_list).ndcl = (yyvsp[(1) - (3)].dcl_list).ndcl + (yyvsp[(3) - (3)].dcl_list).ndcl; + (yyval.dcl_list).obs = (yyvsp[(1) - (3)].dcl_list).obs; + sz = obstack_object_size(&(yyvsp[(3) - (3)].dcl_list).obs); + (void)obstack_grow(&(yyval.dcl_list).obs, obstack_finish(&(yyvsp[(3) - (3)].dcl_list).obs), sz); + (void)obstack_free(&(yyvsp[(3) - (3)].dcl_list).obs, NULL); + } + break; + + case 16: +#line 143 "SDF-parse.y" + {curtype = (yyvsp[(1) - (1)].type);} + break; + + case 17: +#line 143 "SDF-parse.y" + {(yyval.dcl_list) = (yyvsp[(3) - (3)].dcl_list);} + break; + + case 18: +#line 147 "SDF-parse.y" + { + obstack_begin(&(yyval.dcl_list).obs, 16*sizeof((yyvsp[(1) - (1)].one_dcl))); + (yyval.dcl_list).ndcl = 1; + (void)obstack_grow(&(yyval.dcl_list).obs, &(yyvsp[(1) - (1)].one_dcl), sizeof((yyvsp[(1) - (1)].one_dcl))); + } + break; + + case 19: +#line 153 "SDF-parse.y" + { + (yyval.dcl_list) = (yyvsp[(1) - (3)].dcl_list); + (yyval.dcl_list).ndcl += 1; + (void)obstack_grow(&(yyval.dcl_list).obs, &(yyvsp[(3) - (3)].one_dcl), sizeof((yyvsp[(3) - (3)].one_dcl))); + } + break; + + case 20: +#line 160 "SDF-parse.y" + {(yyval.one_dcl).name = (yyvsp[(1) - (1)].string); (yyval.one_dcl).type = curtype; (yyval.one_dcl).arrcnt = 1;} + break; + + case 21: +#line 162 "SDF-parse.y" + { + if( (yyvsp[(3) - (4)].constant).type != SDF_INT64 ){ + yyerror("Expected integer constant"); + YYERROR; + }else{ + (yyval.one_dcl).name = (yyvsp[(1) - (4)].string); (yyval.one_dcl).type = curtype; (yyval.one_dcl).arrcnt = (yyvsp[(3) - (4)].constant).u.int64val; + } + } + break; + + case 22: +#line 170 "SDF-parse.y" + {(yyval.one_dcl).name=(yyvsp[(1) - (3)].string); (yyval.one_dcl).type=curtype; (yyval.one_dcl).arrcnt = 0;} + break; + + case 23: +#line 174 "SDF-parse.y" + { + (yyval.const_list).nconst = 1; + obstack_begin(&(yyval.const_list).obs, 16*sizeof((yyvsp[(1) - (1)].constant))); + (void)obstack_grow(&(yyval.const_list).obs, &(yyvsp[(1) - (1)].constant), sizeof((yyvsp[(1) - (1)].constant))); + } + break; + + case 24: +#line 179 "SDF-parse.y" + {(yyval.const_list) = (yyvsp[(2) - (3)].const_list);} + break; + + case 25: +#line 183 "SDF-parse.y" + { + (yyval.const_list).nconst = 1; + obstack_begin(&(yyval.const_list).obs, 16*sizeof((yyvsp[(1) - (1)].constant))); + (void)obstack_grow(&(yyval.const_list).obs, &(yyvsp[(1) - (1)].constant), sizeof((yyvsp[(1) - (1)].constant))); + } + break; + + case 26: +#line 189 "SDF-parse.y" + { + (yyval.const_list) = (yyvsp[(1) - (3)].const_list); + (yyval.const_list).nconst += 1; + (void)obstack_grow(&(yyval.const_list).obs, &(yyvsp[(3) - (3)].constant), sizeof((yyvsp[(3) - (3)].constant))); + } + break; + + +/* Line 1267 of yacc.c. */ +#line 1597 "y.tab.c" + default: break; + } + YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if ! YYERROR_VERBOSE + yyerror (YY_("syntax error")); +#else + { + YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); + if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) + { + YYSIZE_T yyalloc = 2 * yysize; + if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) + yyalloc = YYSTACK_ALLOC_MAXIMUM; + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yyalloc); + if (yymsg) + yymsg_alloc = yyalloc; + else + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + } + } + + if (0 < yysize && yysize <= yymsg_alloc) + { + (void) yysyntax_error (yymsg, yystate, yychar); + yyerror (yymsg); + } + else + { + yyerror (YY_("syntax error")); + if (yysize != 0) + goto yyexhaustedlab; + } + } +#endif + } + + + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse look-ahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", + yytoken, &yylval); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse look-ahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ + if (/*CONSTCOND*/ 0) + goto yyerrorlab; + + /* Do not reclaim the symbols of the rule which action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (yyn != YYPACT_NINF) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + + yydestruct ("Error: popping", + yystos[yystate], yyvsp); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + if (yyn == YYFINAL) + YYACCEPT; + + *++yyvsp = yylval; + + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#ifndef yyoverflow +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (YY_("memory exhausted")); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: + if (yychar != YYEOF && yychar != YYEMPTY) + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval); + /* Do not reclaim the symbols of the rule which action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + yystos[*yyssp], yyvsp); + YYPOPSTACK (1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif +#if YYERROR_VERBOSE + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); +#endif + /* Make sure YYID is used. */ + return YYID (yyresult); +} + + +#line 196 "SDF-parse.y" + +static int SDFlineno; + +static const char *Dataname, *Hdrname; + +#ifdef STANDALONE +char SDFerrstring[512]; +unsigned int SDFcpubyteorder(void){return 0;} + +main(int argc, char **argv) +{ + SDF hdr; + + if(argc > 1){ + yydebug = 1; + }else{ + yydebug = 0; + } + SDFyyprepare(&hdr, "-", "-"); + if(yyparse()){ + printf("Terminated on error. \n"); + exit(1); + } + exit(0); +} +#endif + +static int SDF_iomode = SDF_SYNC; + +void SDF_Setiomode(int mode) +{ + SDF_iomode = mode; +} + + + +void SDFyyerror(char *fmt, ...) +{ + char *p; + va_list ap; + + va_start(ap, fmt); + vsprintf(SDFerrstring, fmt, ap); + p = SDFerrstring + strlen(SDFerrstring); + sprintf(p, " lineno = %d\n", SDFlineno); + va_end(ap); +} + +int SDFyyprepare(SDF *hdr, const char *hdrname, const char *dataname) +{ + no_more_data_blks = 0; + + cur_file_offset = 0; + cur_data_offset = 0; + + cur_blk.Nrec = 1; + cur_blk.inmem = 1; + cur_blk.begin_offset = 0; + cur_blk.reclen = 0; + + cur_hdr = hdr; + cur_hdr->nblks = 0; + cur_hdr->nvecs = 0; + /* Assume that MPMY_Fopen does the 'right' thing with "-" */ + if( SDF_Hdropen(hdrname) < 0 ){ + sprintf(SDFerrstring, "SDFopen: could not open %s\n", hdrname); + return -1; + } + Dataname = dataname; + Hdrname = hdrname; + SDFlineno = 0; /* or 1? It's always +-1 anyway */ + SDFlexprepare(); + + obstack_begin(&cur_hdr->blks_obs, 16*sizeof(blk_descrip_t)); + obstack_begin(&cur_hdr->vecs_obs, 32*sizeof(vec_descrip_t)); + obstack_begin(&cur_hdr->data_obs, 2048); + return 0; +} + +static int finish_parse(void) +{ + int i; + + finish_curblk(); + cur_hdr->blks = (blk_descrip_t *)obstack_finish(&cur_hdr->blks_obs); + cur_hdr->vecs = (vec_descrip_t *)obstack_finish(&cur_hdr->vecs_obs); + cur_hdr->data = obstack_finish(&cur_hdr->data_obs); + cur_hdr->vec_names = Malloc(cur_hdr->nvecs * sizeof(char *)); + for(i=0; invecs; i++){ + cur_hdr->vec_names[i] = cur_hdr->vecs[i].name; + } + + if( (Dataname == NULL) || (Dataname[0] == '\0') + || (strcmp(Hdrname, Dataname)==0)){ + cur_hdr->begin_file_offset = SDF_Hdroffset(); + if( cur_hdr->begin_file_offset < 0 ){ + yyerror("Can't get offset of end of header\n"); + return -1; + } + }else{ + cur_hdr->begin_file_offset = 0; + } + SDF_Hdrclose(); + + /* cur_hdr->datafp = MPMY_Fopen(Dataname, MPMY_RDONLY); */ + /* If we come up with a better model for IO, call it here.. */ + cur_hdr->datafp = MPMY_Fopen(Dataname, MPMY_RDONLY | MPMY_MULTI); + + Msgf(("cur_hdr->datafp = %p\n", cur_hdr->datafp)); + + if( cur_hdr->datafp == NULL ){ + sprintf(SDFerrstring, "SDFopen: could not open data file: %s\n", + Dataname); + return -1; + } + + if(no_more_data_blks){ + blk_descrip_t *zerolenblk; + off_t bytesleft, recsleft; + off_t datalen; + + zerolenblk = &cur_hdr->blks[zero_len_blknum]; + if(zerolenblk->Nrec != 0){ + yyerror("Zero length block has non-zero length!?\n"); + return -1; + } + if( cur_hdr->begin_file_offset < 0 ){ + yyerror("Can't have zero-len blk in an unseekable file\n"); + return -1; + } + Msgf(("About to call MPMY_Flen\n")); + if( (datalen = MPMY_Flen(cur_hdr->datafp)) < 0 ){ + yyerror("Could not get length of data file.\n"); + return -1; + } + bytesleft = datalen + - (zerolenblk->begin_offset + cur_hdr->begin_file_offset); + Msgf(("datalen = %ld, butesleft = %ld\n", + (long)datalen, (long)bytesleft)); + if( bytesleft < 0 ){ + yyerror("File too short.\n"); + return -1; + } + recsleft = bytesleft/zerolenblk->reclen; + if( recsleft*zerolenblk->reclen != bytesleft ){ + printf("datalen is %ld, bytesleft is %ld\n", (long)datalen, (long)bytesleft); + yyerror("File ends between record boundaries\n"); + return -1; + } + zerolenblk->Nrec = recsleft; + } + return 0; +} + +static int do_value_param(enum value_param_enum param, const_t value) +{ + switch(param){ + case BYTEORDER: + if( value.type != SDF_INT64 ) + return -1; + cur_hdr->byteorder = value.u.int64val; + cur_hdr->swapping = (cur_hdr->byteorder != SDFcpubyteorder()); + break; + } + return 0; +} + + +static int data_dcl(declaration_t dcl) +{ + dcl_list_t *dcl_list; + one_dcl_t *base, *dclp; + int i, offset; + vec_descrip_t vec_descrip; + +#if YYDEBUG + if(yydebug) + printf("Declaration of %ld records:\n", dcl.Nrec); +#endif + if(no_more_data_blks){ + yyerror("You can't have data following an implicit-length dcl.\n"); + return -1; + } + + /* Test to see if we can append this dcl to the current */ + /* block. */ + if(cur_blk.inmem || cur_blk.Nrec != 1 || dcl.Nrec != 1){ + finish_curblk(); + cur_blk.Nrec = dcl.Nrec; + cur_blk.reclen = 0; + cur_blk.inmem = 0; + cur_blk.begin_offset = cur_file_offset; +#if YYDEBUG + if(yydebug) + printf("New block (%d) at offset %d in file\n", + cur_hdr->nblks, cur_file_offset); +#endif + } + + if(dcl.Nrec == 0){ + no_more_data_blks = 1; + zero_len_blknum = cur_hdr->nblks; + } + + offset = cur_blk.reclen; + + dcl_list = &dcl.dcl_list; + base = (one_dcl_t *)obstack_base(&dcl_list->obs); + for(i=0; indcl; i++){ + dclp = &base[i]; + vec_descrip.name = dclp->name; + vec_descrip.arrcnt = dclp->arrcnt; + vec_descrip.type = dclp->type; + vec_descrip.blk_off = offset; + vec_descrip.blk_num = cur_hdr->nblks; + vec_descrip.nread = 0; + offset += SDFtype_sizes[dclp->type] * dclp->arrcnt; + cur_hdr->nvecs++; + (void)obstack_grow(&cur_hdr->vecs_obs, + &vec_descrip, sizeof(vec_descrip)); +#if YYDEBUG + if(yydebug){ + printf("\t %s %s[%d]", SDFtype_names[dclp->type], dclp->name, + dclp->arrcnt); + printf(" in block %ld at offset %ld\n", + vec_descrip.blk_num, vec_descrip.blk_off); + } +#endif + } + (void)obstack_free(&dcl_list->obs, NULL); + cur_blk.reclen = offset; + return 0; +} + +static void finish_curblk(void) +{ + cur_hdr->nblks++; + (void)obstack_grow(&cur_hdr->blks_obs, &cur_blk, sizeof(cur_blk)); + if(cur_blk.inmem){ + cur_data_offset += cur_blk.reclen * cur_blk.Nrec; + }else{ + cur_file_offset += cur_blk.reclen * cur_blk.Nrec; + } +} + +static int const_dcl(declaration_t dcl, const_list_t consts) +{ + dcl_list_t *dcl_list; + one_dcl_t *dclbase, *dclp; + const_t *cp, *cbase, converted; + vec_descrip_t vec_descrip; + int i, j, k; + int offset; + void *to; + + dcl_list = &dcl.dcl_list; + if(dcl.Nrec == 0){ + dcl.Nrec = consts.nconst; +#if 0 /* Was it really this easy?? */ + yyerror("Cannot deal with implicit length constant dcls."); + return -1; +#endif + } + + /* Test to see if we can append this dcl to the current */ + /* block. */ + if(!cur_blk.inmem || cur_blk.Nrec != 1 || dcl.Nrec != 1){ + finish_curblk(); + cur_blk.Nrec = dcl.Nrec; + cur_blk.reclen = 0; + cur_blk.inmem = 1; + cur_blk.begin_offset = cur_data_offset; +#if YYDEBUG + if(yydebug) + printf("New block (%d) at offset %d in data\n", + cur_hdr->nblks, cur_data_offset); +#endif + } + + offset = cur_blk.reclen; + cbase = (const_t *)obstack_base(&consts.obs); + dclbase = (one_dcl_t *)obstack_base(&dcl_list->obs); + + for(i=0; indcl; i++){ + dclp = &dclbase[i]; + if(dclp->arrcnt == 0){ + if(dclp->type == SDF_CHAR + && cbase[i].type == SDF_STRING + && dcl.Nrec == 1){ + dclp->arrcnt = strlen(cbase[i].u.stringval)+1; + /* Round up for padding purposes. */ + dclp->arrcnt = (dclp->arrcnt + 7)& (~0x7); + }else if(i == dcl_list->ndcl-1 && dcl.Nrec == 1){ + dclp->arrcnt = consts.nconst - i; + }else{ + yyerror("Can't figure out implicit dcl from context."); + return -1; + } + } + + vec_descrip.name = dclp->name; + vec_descrip.arrcnt = dclp->arrcnt; + vec_descrip.type = dclp->type; + vec_descrip.blk_off = offset; + vec_descrip.blk_num = cur_hdr->nblks; + vec_descrip.nread = 0; + offset += SDFtype_sizes[dclp->type] * dclp->arrcnt; + cur_hdr->nvecs++; + (void)obstack_grow(&cur_hdr->vecs_obs, + &vec_descrip, sizeof(vec_descrip)); +#if YYDEBUG + if(yydebug){ + printf("\t %s %s[%d]", SDFtype_names[dclp->type], dclp->name, + dclp->arrcnt); + printf(" in block %ld at offset %ld\n", + vec_descrip.blk_num, vec_descrip.blk_off); + } +#endif + } + cur_blk.reclen = offset; + + cp = cbase; + for(i=0; indcl; j++){ + dclp = &dclbase[j]; +#if YYDEBUG + if(yydebug) + printf("\t %s %s[%d] (%d) = ", + SDFtype_names[dclp->type], dclp->name, + dclp->arrcnt, i); +#endif + if( dclp->type == SDF_CHAR && cp->type == SDF_STRING){ +#if YYDEBUG + if(yydebug) + printf("\"%s\"\n", cp->u.stringval); +#endif + to = obstack_next_free(&cur_hdr->data_obs); + (void)obstack_blank(&cur_hdr->data_obs, dclp->arrcnt); + /* Should we warn + if strlen(cp->u.stringval) > dclp->arrcnt ???? + It implies that the 'string' won't be null-terminated? */ + (void)strncpy(to, cp->u.stringval, dclp->arrcnt); +#ifdef YYDEBUG + if(yydebug) + printf("Freeing const string 0x%lx\n", + (unsigned long)cp->u.stringval); +#endif + Free(cp->u.stringval); + cp++; + continue; + } + + for(k=0; karrcnt; k++){ + converted = convert_const(cp, dclp->type); + if(converted.type == SDF_NOTYPE){ + yyerror("Failed constant conversion."); + return -1; + } + (void)obstack_grow(&cur_hdr->data_obs, &converted.u, + SDFtype_sizes[converted.type]); + +#ifdef YYDEBUG + if(yydebug){ + printf("(%s)", SDFtype_names[cp->type]); + switch(converted.type){ + case SDF_CHAR: + printf("%c", converted.u.charval); + break; + case SDF_SHORT: + printf("%d", converted.u.shortval); + break; + case SDF_INT: + printf("%d", converted.u.intval); + break; + case SDF_LONG: + printf("%ld", converted.u.longval); + break; + case SDF_INT64: +#if __WORDSIZE==64 + printf("%ld", converted.u.int64val); +#else + printf("%lld", converted.u.int64val); +#endif + break; + case SDF_FLOAT: + printf("%.7g", converted.u.floatval); + break; + case SDF_DOUBLE: + printf("%.17g", converted.u.doubleval); + break; + default: + printf("Unrecognized type: %d\n", converted.type); + break; + } + if(k == dclp->arrcnt-1){ + printf("\n"); + }else{ + printf(", "); + } + } +#endif + cp++; + } + } + } + (void)obstack_free(&dcl_list->obs, NULL); + (void)obstack_free(&consts.obs, NULL); + return 0; +} + +static const_t convert_const(const_t *cp, enum SDF_type_enum newtype) +/* Return a constant of type NEWTYPE, with the same value as */ +/* *CP. If the conversion does not preserve value, then */ +/* return a constant of NOTYPE, with garbage value. */ +{ + const_t value; + double dval = 0.; + int64_t ival = 0; + + if(cp->type == newtype){ + /* IRIX -32 bug fix */ + memcpy(&value, cp, sizeof(value)); + /* value = *cp; */ + return value; + } + + if(cp->type == SDF_STRING || newtype == SDF_STRING){ + value.type = SDF_NOTYPE; + yyerror("Cannot do const conversions with strings.\n"); + return value; + } + + /* Now rely on the fact that a double can faithfully hold */ + /* any other arithmetic type (except long ints on 64-bit archs). */ + switch(cp->type){ + case SDF_CHAR: + dval = (double)cp->u.charval; + break; + case SDF_SHORT: + dval = (double)cp->u.shortval; + break; + case SDF_INT: + dval = (double)cp->u.intval; + ival = cp->u.intval; + break; + case SDF_LONG: + dval = (double)cp->u.longval; + ival = cp->u.longval; + break; + case SDF_INT64: + dval = (double)cp->u.int64val; + ival = cp->u.int64val; + break; + case SDF_FLOAT: + dval = cp->u.floatval; + break; + case SDF_DOUBLE: + dval = cp->u.doubleval; + break; + default: + dval = 0.0; + yyerror("Cannot do const conversions with strings.\n"); + } + + value.type = newtype; + switch(newtype){ + case SDF_CHAR: + value.u.charval = (char)dval; + if( value.u.charval != dval ){ + yyerror("Can't fit value into char."); + value.type = SDF_NOTYPE; + } + break; + case SDF_SHORT: + value.u.shortval = (short)dval; + if( value.u.shortval != dval ){ + yyerror("Can't fit value into short."); + value.type = SDF_NOTYPE; + } + break; + case SDF_INT: + value.u.intval = (int)dval; + if( value.u.intval != dval ){ + value.u.intval = ival; + if( value.u.intval != ival ){ + yyerror("Can't fit value into int."); + value.type = SDF_NOTYPE; + } + break; + } + break; + case SDF_LONG: + value.u.longval = (long)dval; + if( value.u.longval != dval ){ + value.u.longval = ival; + if( value.u.longval != ival ){ + yyerror("Can't fit value into long."); + value.type = SDF_NOTYPE; + } + break; + } + break; + case SDF_INT64: + value.u.int64val = (int64_t)dval; + if( value.u.int64val != dval ){ + value.u.int64val = ival; + if( value.u.int64val != ival ){ + yyerror("Can't fit value into int64_t."); + value.type = SDF_NOTYPE; + } + break; + } + break; + case SDF_FLOAT: + if(dval > FLT_MAX || dval < -FLT_MAX){ + yyerror("Can't fit value into float."); + value.type = SDF_NOTYPE; + } + value.u.floatval = dval; + break; + case SDF_DOUBLE: + value.u.doubleval = dval; + break; + default: + yyerror("Impossible case.\n"); + break; + } + return value; +} + +void *SDFobstack_chunk_alloc(size_t n) +{ + void *p = Malloc(n); +#if YYDEBUG + if(yydebug) + printf("malloc(%ld) = 0x%lx\n", (long)n, (unsigned long)p); +#endif + return p; +} + +void SDFobstack_chunk_free(void *p) +{ +#if YYDEBUG + if(yydebug) + printf("free(0x%lx)\n", (unsigned long)p); +#endif + Free(p); +} + +/* This symbol tells a Flex-based scanner not to bother trying to + call isatty to figure out whether to do char-at-a-time input. The + actual behavior is under our explicit control anyway (see SDF-lex.l), + but linking against fileno() and isatty() can be annoying. */ +#define YY_ALWAYS_INTERACTIVE 1 +#include "SDF-lex.c" + diff --git a/external/libsdf/libSDF/SDF-parse.y b/external/libsdf/libSDF/SDF-parse.y new file mode 100644 index 0000000..eab6ea2 --- /dev/null +++ b/external/libsdf/libSDF/SDF-parse.y @@ -0,0 +1,754 @@ +%{ +/* + SDF Library for reading Self-Describing Files + Copyright (C) 1991,1992 John K. Salmon + + Terms and conditions are specified in the file "copyright.h", + and more precisely in the file COPYING.LIB which you should have + received with this library. +*/ + +/* We don't rely on bison's -p argument any more. + Instead, just #define the name changes ourselves. These are taken + from the beginning of bison -p output. These are far from a complete + set of external 'yy' names, as a quick run throug 'nm' will show. Maybe + all the others come from lex. I dunno. In any event, the namespace is only + partially cleaned up. Perhaps we should apply for Superfund money + to finish the cleanup? bison -p does no better. +*/ +#define yyparse SDFyyparse +#define yylex SDFyylex +#define yyerror SDFyyerror +#define yylval SDFyylval +#define yychar SDFyychar +#define yydebug SDFyydebug +#define yynerrs SDFyynerrs + +#include +#include +#include +#include +#include "protos.h" +#include "Msgs.h" +#include "SDF-private.h" +#include "obstack.h" +#include "Malloc.h" + +#ifndef __DELTA__ +#define YYDEBUG 1 +#endif + +#if YYDEBUG +/* yacc sends its debug output throught printf. We change that... */ +#define printf Msg_do /* MUST be after protos.h!!! */ +#endif + +#ifdef cray +/* This wants to be a long on the cray?? */ +extern long int yydebug; +#else +extern int yydebug; +#endif +extern void yyerror(char *fmt, ...); + + +static enum SDF_type_enum curtype; +static blk_descrip_t cur_blk; +static int cur_file_offset; +static int cur_data_offset; +static SDF *cur_hdr; +static int no_more_data_blks; +static int zero_len_blknum; + +char *SDFtype_names[] = {"notype", "char", "short", "int", "long", "int64_t", + "float", "double", "string"}; + + int SDFtype_sizes[] = {0, sizeof(char), sizeof(short), sizeof(int), sizeof(long), + sizeof(int64_t), sizeof(float), sizeof(double), sizeof(char *)}; + +static int do_value_param(enum value_param_enum type, const_t value); +static int data_dcl(declaration_t dcl); +static int const_dcl(declaration_t dcl, const_list_t consts); +static void finish_curblk(void); +static const_t convert_const(const_t *cp, enum SDF_type_enum type); +static int finish_parse(void); + +%} + +%token STRUCT +%token NAME +%token TYPE +%token CONST +%token VALUEPARAM +%token PARAMETER +%token EOHDR LEXERROR +%token ';' '=' '[' ']' '{' '}' ',' +%type declaration +%type dcl1 +%type const_lst comma_sep_consts +%type comma_sep_dcls typed_dcl_list many_typed_dcl_list +%union{ + enum SDF_type_enum type; + enum value_param_enum valueparam; + char *string; + const_t constant; + declaration_t declaration; + dcl_list_t dcl_list; + one_dcl_t one_dcl; + const_list_t const_list; +} +%% +hdr : hdr1 {if(finish_parse()) YYERROR;} + | hdr1 EOHDR {if(finish_parse()) YYERROR; else YYACCEPT;} + | LEXERROR {YYERROR;} + ; + +hdr1 : stmt + | hdr1 stmt + ; + +stmt : declaration ';' {if(data_dcl($1)) YYERROR;} + | declaration '=' const_lst ';' {if(const_dcl($1, $3)) YYERROR;} + | PARAMETER VALUEPARAM '=' CONST ';' {if(do_value_param($2, $4)) YYERROR;} + ; + +declaration : typed_dcl_list {$$.dcl_list = $1; $$.Nrec = 1;} + | STRUCT '{' many_typed_dcl_list ';' '}' {$$.dcl_list=$3; $$.Nrec=1;} + | STRUCT '{' many_typed_dcl_list ';' '}' '[' CONST ']' + { + if( $7.type != SDF_INT64 ){ + yyerror("Expected integer constant"); + YYERROR; + }else{ + $$.dcl_list = $3; $$.Nrec = $7.u.int64val; + } + } + | STRUCT '{' many_typed_dcl_list ';' '}' '[' ']' + { $$.dcl_list = $3; $$.Nrec = 0;} + ; + +many_typed_dcl_list : typed_dcl_list {$$ = $1;} + | many_typed_dcl_list ';' typed_dcl_list + { + int sz; + + $$.ndcl = $1.ndcl + $3.ndcl; + $$.obs = $1.obs; + sz = obstack_object_size(&$3.obs); + (void)obstack_grow(&$$.obs, obstack_finish(&$3.obs), sz); + (void)obstack_free(&$3.obs, NULL); + } + ; + +typed_dcl_list: TYPE {curtype = $1;} comma_sep_dcls {$$ = $3;} + ; + +comma_sep_dcls: dcl1 + { + obstack_begin(&$$.obs, 16*sizeof($1)); + $$.ndcl = 1; + (void)obstack_grow(&$$.obs, &$1, sizeof($1)); + } + | comma_sep_dcls ',' dcl1 + { + $$ = $1; + $$.ndcl += 1; + (void)obstack_grow(&$$.obs, &$3, sizeof($3)); + } + ; + +dcl1 : NAME {$$.name = $1; $$.type = curtype; $$.arrcnt = 1;} + | NAME '[' CONST ']' + { + if( $3.type != SDF_INT64 ){ + yyerror("Expected integer constant"); + YYERROR; + }else{ + $$.name = $1; $$.type = curtype; $$.arrcnt = $3.u.int64val; + } + } + | NAME '[' ']' {$$.name=$1; $$.type=curtype; $$.arrcnt = 0;} + ; + +const_lst : CONST + { + $$.nconst = 1; + obstack_begin(&$$.obs, 16*sizeof($1)); + (void)obstack_grow(&$$.obs, &$1, sizeof($1)); + } + | '{' comma_sep_consts '}' {$$ = $2;} + ; + +comma_sep_consts : CONST + { + $$.nconst = 1; + obstack_begin(&$$.obs, 16*sizeof($1)); + (void)obstack_grow(&$$.obs, &$1, sizeof($1)); + } + | comma_sep_consts ',' CONST + { + $$ = $1; + $$.nconst += 1; + (void)obstack_grow(&$$.obs, &$3, sizeof($3)); + } + ; + +%% +static int SDFlineno; + +static const char *Dataname, *Hdrname; + +#ifdef STANDALONE +char SDFerrstring[512]; +unsigned int SDFcpubyteorder(void){return 0;} + +main(int argc, char **argv) +{ + SDF hdr; + + if(argc > 1){ + yydebug = 1; + }else{ + yydebug = 0; + } + SDFyyprepare(&hdr, "-", "-"); + if(yyparse()){ + printf("Terminated on error. \n"); + exit(1); + } + exit(0); +} +#endif + +static int SDF_iomode = MPMY_RDONLY | MPMY_MULTI; + +void SDFsetiomode(int mode) +{ + if (mode == SDF_SINGL) { + SDF_iomode = MPMY_RDONLY | MPMY_SINGL; + } else { + SDF_iomode = MPMY_RDONLY | MPMY_MULTI; + } +} + + + +void SDFyyerror(char *fmt, ...) +{ + char *p; + va_list ap; + + va_start(ap, fmt); + vsprintf(SDFerrstring, fmt, ap); + p = SDFerrstring + strlen(SDFerrstring); + sprintf(p, " lineno = %d\n", SDFlineno); + va_end(ap); +} + +int SDFyyprepare(SDF *hdr, const char *hdrname, const char *dataname) +{ + no_more_data_blks = 0; + + cur_file_offset = 0; + cur_data_offset = 0; + + cur_blk.Nrec = 1; + cur_blk.inmem = 1; + cur_blk.begin_offset = 0; + cur_blk.reclen = 0; + + cur_hdr = hdr; + cur_hdr->nblks = 0; + cur_hdr->nvecs = 0; + /* Assume that MPMY_Fopen does the 'right' thing with "-" */ + if( SDF_Hdropen(hdrname) < 0 ){ + sprintf(SDFerrstring, "SDFopen: could not open %s\n", hdrname); + return -1; + } + Dataname = dataname; + Hdrname = hdrname; + SDFlineno = 0; /* or 1? It's always +-1 anyway */ + SDFlexprepare(); + + obstack_begin(&cur_hdr->blks_obs, 16*sizeof(blk_descrip_t)); + obstack_begin(&cur_hdr->vecs_obs, 32*sizeof(vec_descrip_t)); + obstack_begin(&cur_hdr->data_obs, 2048); + return 0; +} + +static int finish_parse(void) +{ + int i; + + finish_curblk(); + cur_hdr->blks = (blk_descrip_t *)obstack_finish(&cur_hdr->blks_obs); + cur_hdr->vecs = (vec_descrip_t *)obstack_finish(&cur_hdr->vecs_obs); + cur_hdr->data = obstack_finish(&cur_hdr->data_obs); + cur_hdr->vec_names = Malloc(cur_hdr->nvecs * sizeof(char *)); + for(i=0; invecs; i++){ + cur_hdr->vec_names[i] = cur_hdr->vecs[i].name; + } + + if( (Dataname == NULL) || (Dataname[0] == '\0') + || (strcmp(Hdrname, Dataname)==0)){ + cur_hdr->begin_file_offset = SDF_Hdroffset(); + if( cur_hdr->begin_file_offset < 0 ){ + yyerror("Can't get offset of end of header\n"); + return -1; + } + }else{ + cur_hdr->begin_file_offset = 0; + } + SDF_Hdrclose(); + + /* cur_hdr->datafp = MPMY_Fopen(Dataname, MPMY_RDONLY); */ + /* If we come up with a better model for IO, call it here.. */ + cur_hdr->datafp = MPMY_Fopen(Dataname, SDF_iomode); + + Msgf(("cur_hdr->datafp = %p\n", cur_hdr->datafp)); + + if( cur_hdr->datafp == NULL ){ + sprintf(SDFerrstring, "SDFopen: could not open data file: %s\n", + Dataname); + return -1; + } + + if(no_more_data_blks){ + blk_descrip_t *zerolenblk; + off_t bytesleft, recsleft; + off_t datalen; + + zerolenblk = &cur_hdr->blks[zero_len_blknum]; + if(zerolenblk->Nrec != 0){ + yyerror("Zero length block has non-zero length!?\n"); + return -1; + } + if( cur_hdr->begin_file_offset < 0 ){ + yyerror("Can't have zero-len blk in an unseekable file\n"); + return -1; + } + Msgf(("About to call MPMY_Flen\n")); + if( (datalen = MPMY_Flen(cur_hdr->datafp)) < 0 ){ + yyerror("Could not get length of data file.\n"); + return -1; + } + bytesleft = datalen + - (zerolenblk->begin_offset + cur_hdr->begin_file_offset); + Msgf(("datalen = %ld, butesleft = %ld\n", + (long)datalen, (long)bytesleft)); + if( bytesleft < 0 ){ + yyerror("File too short.\n"); + return -1; + } + recsleft = bytesleft/zerolenblk->reclen; + if( recsleft*zerolenblk->reclen != bytesleft ){ + printf("datalen is %ld, bytesleft is %ld\n", (long)datalen, (long)bytesleft); + yyerror("File ends between record boundaries\n"); + return -1; + } + zerolenblk->Nrec = recsleft; + } + return 0; +} + +static int do_value_param(enum value_param_enum param, const_t value) +{ + switch(param){ + case BYTEORDER: + if( value.type != SDF_INT64 ) + return -1; + cur_hdr->byteorder = value.u.int64val; + cur_hdr->swapping = (cur_hdr->byteorder != SDFcpubyteorder()); + break; + } + return 0; +} + + +static int data_dcl(declaration_t dcl) +{ + dcl_list_t *dcl_list; + one_dcl_t *base, *dclp; + int i, offset; + vec_descrip_t vec_descrip; + +#if YYDEBUG + if(yydebug) + printf("Declaration of %ld records:\n", dcl.Nrec); +#endif + if(no_more_data_blks){ + yyerror("You can't have data following an implicit-length dcl.\n"); + return -1; + } + + /* Test to see if we can append this dcl to the current */ + /* block. */ + if(cur_blk.inmem || cur_blk.Nrec != 1 || dcl.Nrec != 1){ + finish_curblk(); + cur_blk.Nrec = dcl.Nrec; + cur_blk.reclen = 0; + cur_blk.inmem = 0; + cur_blk.begin_offset = cur_file_offset; +#if YYDEBUG + if(yydebug) + printf("New block (%d) at offset %d in file\n", + cur_hdr->nblks, cur_file_offset); +#endif + } + + if(dcl.Nrec == 0){ + no_more_data_blks = 1; + zero_len_blknum = cur_hdr->nblks; + } + + offset = cur_blk.reclen; + + dcl_list = &dcl.dcl_list; + base = (one_dcl_t *)obstack_base(&dcl_list->obs); + for(i=0; indcl; i++){ + dclp = &base[i]; + vec_descrip.name = dclp->name; + vec_descrip.arrcnt = dclp->arrcnt; + vec_descrip.type = dclp->type; + vec_descrip.blk_off = offset; + vec_descrip.blk_num = cur_hdr->nblks; + vec_descrip.nread = 0; + offset += SDFtype_sizes[dclp->type] * dclp->arrcnt; + cur_hdr->nvecs++; + (void)obstack_grow(&cur_hdr->vecs_obs, + &vec_descrip, sizeof(vec_descrip)); +#if YYDEBUG + if(yydebug){ + printf("\t %s %s[%d]", SDFtype_names[dclp->type], dclp->name, + dclp->arrcnt); + printf(" in block %ld at offset %ld\n", + vec_descrip.blk_num, vec_descrip.blk_off); + } +#endif + } + (void)obstack_free(&dcl_list->obs, NULL); + cur_blk.reclen = offset; + return 0; +} + +static void finish_curblk(void) +{ + cur_hdr->nblks++; + (void)obstack_grow(&cur_hdr->blks_obs, &cur_blk, sizeof(cur_blk)); + if(cur_blk.inmem){ + cur_data_offset += cur_blk.reclen * cur_blk.Nrec; + }else{ + cur_file_offset += cur_blk.reclen * cur_blk.Nrec; + } +} + +static int const_dcl(declaration_t dcl, const_list_t consts) +{ + dcl_list_t *dcl_list; + one_dcl_t *dclbase, *dclp; + const_t *cp, *cbase, converted; + vec_descrip_t vec_descrip; + int i, j, k; + int offset; + void *to; + + dcl_list = &dcl.dcl_list; + if(dcl.Nrec == 0){ + dcl.Nrec = consts.nconst; +#if 0 /* Was it really this easy?? */ + yyerror("Cannot deal with implicit length constant dcls."); + return -1; +#endif + } + + /* Test to see if we can append this dcl to the current */ + /* block. */ + if(!cur_blk.inmem || cur_blk.Nrec != 1 || dcl.Nrec != 1){ + finish_curblk(); + cur_blk.Nrec = dcl.Nrec; + cur_blk.reclen = 0; + cur_blk.inmem = 1; + cur_blk.begin_offset = cur_data_offset; +#if YYDEBUG + if(yydebug) + printf("New block (%d) at offset %d in data\n", + cur_hdr->nblks, cur_data_offset); +#endif + } + + offset = cur_blk.reclen; + cbase = (const_t *)obstack_base(&consts.obs); + dclbase = (one_dcl_t *)obstack_base(&dcl_list->obs); + + for(i=0; indcl; i++){ + dclp = &dclbase[i]; + if(dclp->arrcnt == 0){ + if(dclp->type == SDF_CHAR + && cbase[i].type == SDF_STRING + && dcl.Nrec == 1){ + dclp->arrcnt = strlen(cbase[i].u.stringval)+1; + /* Round up for padding purposes. */ + dclp->arrcnt = (dclp->arrcnt + 7)& (~0x7); + }else if(i == dcl_list->ndcl-1 && dcl.Nrec == 1){ + dclp->arrcnt = consts.nconst - i; + }else{ + yyerror("Can't figure out implicit dcl from context."); + return -1; + } + } + + vec_descrip.name = dclp->name; + vec_descrip.arrcnt = dclp->arrcnt; + vec_descrip.type = dclp->type; + vec_descrip.blk_off = offset; + vec_descrip.blk_num = cur_hdr->nblks; + vec_descrip.nread = 0; + offset += SDFtype_sizes[dclp->type] * dclp->arrcnt; + cur_hdr->nvecs++; + (void)obstack_grow(&cur_hdr->vecs_obs, + &vec_descrip, sizeof(vec_descrip)); +#if YYDEBUG + if(yydebug){ + printf("\t %s %s[%d]", SDFtype_names[dclp->type], dclp->name, + dclp->arrcnt); + printf(" in block %ld at offset %ld\n", + vec_descrip.blk_num, vec_descrip.blk_off); + } +#endif + } + cur_blk.reclen = offset; + + cp = cbase; + for(i=0; indcl; j++){ + dclp = &dclbase[j]; +#if YYDEBUG + if(yydebug) + printf("\t %s %s[%d] (%d) = ", + SDFtype_names[dclp->type], dclp->name, + dclp->arrcnt, i); +#endif + if( dclp->type == SDF_CHAR && cp->type == SDF_STRING){ +#if YYDEBUG + if(yydebug) + printf("\"%s\"\n", cp->u.stringval); +#endif + to = obstack_next_free(&cur_hdr->data_obs); + (void)obstack_blank(&cur_hdr->data_obs, dclp->arrcnt); + /* Should we warn + if strlen(cp->u.stringval) > dclp->arrcnt ???? + It implies that the 'string' won't be null-terminated? */ + (void)strncpy(to, cp->u.stringval, dclp->arrcnt); +#ifdef YYDEBUG + if(yydebug) + printf("Freeing const string 0x%lx\n", + (unsigned long)cp->u.stringval); +#endif + Free(cp->u.stringval); + cp++; + continue; + } + + for(k=0; karrcnt; k++){ + converted = convert_const(cp, dclp->type); + if(converted.type == SDF_NOTYPE){ + yyerror("Failed constant conversion."); + return -1; + } + (void)obstack_grow(&cur_hdr->data_obs, &converted.u, + SDFtype_sizes[converted.type]); + +#ifdef YYDEBUG + if(yydebug){ + printf("(%s)", SDFtype_names[cp->type]); + switch(converted.type){ + case SDF_CHAR: + printf("%c", converted.u.charval); + break; + case SDF_SHORT: + printf("%d", converted.u.shortval); + break; + case SDF_INT: + printf("%d", converted.u.intval); + break; + case SDF_LONG: + printf("%ld", converted.u.longval); + break; + case SDF_INT64: +#if __WORDSIZE==64 + printf("%ld", converted.u.int64val); +#else + printf("%lld", converted.u.int64val); +#endif + break; + case SDF_FLOAT: + printf("%.7g", converted.u.floatval); + break; + case SDF_DOUBLE: + printf("%.17g", converted.u.doubleval); + break; + default: + printf("Unrecognized type: %d\n", converted.type); + break; + } + if(k == dclp->arrcnt-1){ + printf("\n"); + }else{ + printf(", "); + } + } +#endif + cp++; + } + } + } + (void)obstack_free(&dcl_list->obs, NULL); + (void)obstack_free(&consts.obs, NULL); + return 0; +} + +static const_t convert_const(const_t *cp, enum SDF_type_enum newtype) +/* Return a constant of type NEWTYPE, with the same value as */ +/* *CP. If the conversion does not preserve value, then */ +/* return a constant of NOTYPE, with garbage value. */ +{ + const_t value; + double dval = 0.; + int64_t ival = 0; + + if(cp->type == newtype){ + /* IRIX -32 bug fix */ + memcpy(&value, cp, sizeof(value)); + /* value = *cp; */ + return value; + } + + if(cp->type == SDF_STRING || newtype == SDF_STRING){ + value.type = SDF_NOTYPE; + yyerror("Cannot do const conversions with strings.\n"); + return value; + } + + /* Now rely on the fact that a double can faithfully hold */ + /* any other arithmetic type (except long ints on 64-bit archs). */ + switch(cp->type){ + case SDF_CHAR: + dval = (double)cp->u.charval; + break; + case SDF_SHORT: + dval = (double)cp->u.shortval; + break; + case SDF_INT: + dval = (double)cp->u.intval; + ival = cp->u.intval; + break; + case SDF_LONG: + dval = (double)cp->u.longval; + ival = cp->u.longval; + break; + case SDF_INT64: + dval = (double)cp->u.int64val; + ival = cp->u.int64val; + break; + case SDF_FLOAT: + dval = cp->u.floatval; + break; + case SDF_DOUBLE: + dval = cp->u.doubleval; + break; + default: + dval = 0.0; + yyerror("Cannot do const conversions with strings.\n"); + } + + value.type = newtype; + switch(newtype){ + case SDF_CHAR: + value.u.charval = (char)dval; + if( value.u.charval != dval ){ + yyerror("Can't fit value into char."); + value.type = SDF_NOTYPE; + } + break; + case SDF_SHORT: + value.u.shortval = (short)dval; + if( value.u.shortval != dval ){ + yyerror("Can't fit value into short."); + value.type = SDF_NOTYPE; + } + break; + case SDF_INT: + value.u.intval = (int)dval; + if( value.u.intval != dval ){ + value.u.intval = ival; + if( value.u.intval != ival ){ + yyerror("Can't fit value into int."); + value.type = SDF_NOTYPE; + } + break; + } + break; + case SDF_LONG: + value.u.longval = (long)dval; + if( value.u.longval != dval ){ + value.u.longval = ival; + if( value.u.longval != ival ){ + yyerror("Can't fit value into long."); + value.type = SDF_NOTYPE; + } + break; + } + break; + case SDF_INT64: + value.u.int64val = (int64_t)dval; + if( value.u.int64val != dval ){ + value.u.int64val = ival; + if( value.u.int64val != ival ){ + yyerror("Can't fit value into int64_t."); + value.type = SDF_NOTYPE; + } + break; + } + break; + case SDF_FLOAT: + if(dval > FLT_MAX || dval < -FLT_MAX){ + yyerror("Can't fit value into float."); + value.type = SDF_NOTYPE; + } + value.u.floatval = dval; + break; + case SDF_DOUBLE: + value.u.doubleval = dval; + break; + default: + yyerror("Impossible case.\n"); + break; + } + return value; +} + +void *SDFobstack_chunk_alloc(size_t n) +{ + void *p = Malloc(n); +#if YYDEBUG + if(yydebug) + printf("malloc(%ld) = 0x%lx\n", (long)n, (unsigned long)p); +#endif + return p; +} + +void SDFobstack_chunk_free(void *p) +{ +#if YYDEBUG + if(yydebug) + printf("free(0x%lx)\n", (unsigned long)p); +#endif + Free(p); +} + +/* This symbol tells a Flex-based scanner not to bother trying to + call isatty to figure out whether to do char-at-a-time input. The + actual behavior is under our explicit control anyway (see SDF-lex.l), + but linking against fileno() and isatty() can be annoying. */ +#define YY_ALWAYS_INTERACTIVE 1 +#include "SDF-lex.c" diff --git a/external/libsdf/libSDF/SDF-private.h b/external/libsdf/libSDF/SDF-private.h new file mode 100644 index 0000000..a154976 --- /dev/null +++ b/external/libsdf/libSDF/SDF-private.h @@ -0,0 +1,119 @@ +/* + SDF Library for reading Self-Describing Files + Copyright (C) 1991,1992 John K. Salmon + + Terms and conditions are specified in the file "copyright.h", + and more precisely in the file COPYING.LIB which you should have + received with this library. +*/ +#ifndef sdfprivateDOTh +#define sdfprivateDOTh +#include +#include +#include "stdio.h" /* from this directory!! */ +#include "obstack.h" + +/* Exact copy of declaration in SDF.h */ +enum SDF_type_enum{SDF_NOTYPE, + SDF_CHAR, + SDF_SHORT, + SDF_INT, + SDF_LONG, + SDF_INT64, + SDF_FLOAT, + SDF_DOUBLE, + SDF_STRING}; + +extern char SDFerrstring[]; + +enum toggle_param_enum{NOTHING}; + +enum value_param_enum{BYTEORDER}; + +/* How the lexical analyzer returns constants. */ +typedef struct{ + enum SDF_type_enum type; + union{ + char charval; + short shortval; + int intval; + long longval; + int64_t int64val; + float floatval; + double doubleval; + char *stringval; + } u; +} const_t; + +typedef struct{ + int nconst; + struct obstack obs; +} const_list_t; + +typedef struct{ + char *name; + enum SDF_type_enum type; + int arrcnt; +} one_dcl_t; + +typedef struct{ + int ndcl; + struct obstack obs; +} dcl_list_t; + +typedef struct{ + dcl_list_t dcl_list; + int64_t Nrec; +} declaration_t; + +typedef struct{ + char *name; + enum SDF_type_enum type; + int arrcnt; + int64_t blk_off; + int64_t blk_num; + int64_t nread; +} vec_descrip_t; + +typedef struct{ + int reclen; + int inmem; + int64_t Nrec; + int64_t begin_offset; +} blk_descrip_t; + +typedef struct{ + int nblks; + struct obstack blks_obs; + blk_descrip_t *blks; + int nvecs; + struct obstack vecs_obs; + vec_descrip_t *vecs; + char **vec_names; + struct obstack data_obs; + void *data; + MPMYFile *datafp; + int64_t begin_file_offset; + int byteorder; + int swapping; + int hashsz; + vec_descrip_t **hashtbl; +} SDF; + +void SDFlexprepare(void); +int SDFyyprepare(SDF *hdr, const char *hdrname, const char *dataname); +void SDFobstack_chunk_free(void *p); +void *SDFobstack_chunk_alloc(size_t n); + +int SDF_Hdropen(const char *name); +void SDF_Hdrclose(void); +int SDF_Hdroffset(void); +int SDF_Hdrgetc(); + +#define obstack_chunk_alloc SDFobstack_chunk_alloc +#define obstack_chunk_free SDFobstack_chunk_free + +#include "SDF.h" + + +#endif /* sdfprivateDOTh */ diff --git a/external/libsdf/libSDF/SDFfuncs.c b/external/libsdf/libSDF/SDFfuncs.c new file mode 100644 index 0000000..fb10319 --- /dev/null +++ b/external/libsdf/libSDF/SDFfuncs.c @@ -0,0 +1,941 @@ +/* + SDF Library for reading Self-Describing Files + Copyright (C) 1991,1992 John K. Salmon + + Terms and conditions are specified in the file "copyright.h", + and more precisely in the file COPYING.LIB which you should have + received with this library. +*/ +/* Implement the user-visible functions that make up the */ +/* SDF package. */ + +/* Using alloca reduces memory fragmentation, and allows the halo */ +/* finder to work on larger datasets */ +#define USE_ALLOCA + +#include +#include +#include +#include +#include +#ifdef USE_ALLOCA +#include +#endif +#include "Msgs.h" +#include "stdio.h" /* for sprintf, etc. No 'real' stdio */ +#include "SDF-private.h" +#include "obstack.h" +#include "byteswap.h" +#include "Malloc.h" +#include "protos.h" +#include "mpmy.h" +#include "mpmy_io.h" + +/* max_bufsz is the maximum read-buffer that we will attempt to + malloc. The code in rdvecs is capable of requesting arbitrarily + large blocks and scaling back (in powers of 2) until malloc returns + non-NULL. That doesn't seem like a good idea on virtual systems, + though, so the maximum first attempt is dynamically settable with + SDFsetmaxbufsz. Setting it to zero will remove the limit. This is + the initial value. */ +#define DEFAULT_MAX_BUFSZ (256LL*1024*1024) + +static void buildhash(SDF *hdr); +static vec_descrip_t *lookup(const char *name, SDF *hdr); +static int compar_func(const void *p1, const void *p2); +static vec_descrip_t **compar_vds; +static unsigned char junk[4] = {0x12, 0x34, 0x56, 0x78}; +static unsigned int *cpubyteorder = (unsigned int *)&junk[0]; +static int max_bufsz = DEFAULT_MAX_BUFSZ; + +char SDFerrstring[256]; +extern int SDFyyparse(void); + +/* This is a non-guaranteed way to test if a file is SDF or not. */ +/* It really only tests the initial comment! This is not fail-safe! */ +int SDFissdf(const char *name){ + MPMYFile *fp; + int result = 1; + int c; + char buf[64]; + int bufcnt = 0; + + if( MPMY_Initialized() == 0 ){ + MPMY_Init(0, NULL); + } + /* Assume we do the 'right' thing with "-" */ + /* but what IS the right thing?? (see below) */ + fp = MPMY_Fopen(name, MPMY_RDONLY | MPMY_SINGL | MPMY_IOZERO); + if( fp == NULL ) + return 0; + + buf[bufcnt] = 0; /* In case read returns nothing */ + MPMY_Fread(buf, 1, 64, fp); + if( (c=buf[bufcnt++]) != '#' ){ result=0; goto done;} + while( isspace(c = buf[bufcnt++]) && c != '\n' ); + if( c == '\n' ) { result=0; goto done; } + if( c != 'S' ) { result=0; goto done; } + if( buf[bufcnt++] != 'D' ) { result=0; goto done; } + if( buf[bufcnt++] != 'F' ) { result=0; goto done; } + done: + MPMY_Fclose(fp); + + return result; +} + +SDF *SDFopen(const char *hdrfname, const char *datafname) +{ + SDF *hdr; + int parseerr; + + /* Is this a good idea? Does it promote sloppy programming? Or does + it allow a program that has no interest in MPMY to behave as + expected? Or does it belong in MPMY_Fopen instead? */ + if( MPMY_Initialized() == 0 ){ + MPMY_Init(0, NULL); + } + + if( datafname == NULL ){ + sprintf(SDFerrstring, "SDFopen: NULL data file %s\n", datafname); + return NULL; + } + + hdr = Calloc(1, sizeof(SDF)); + if( hdr == NULL ){ + sprintf(SDFerrstring, "SDFopen: could not calloc space for hdr\n"); + return NULL; + } + /* Handle the case of only one name in the arg list. */ + /* Don't worry about which one it is. Is this right? */ + if( hdrfname == NULL || hdrfname[0] == '\0' ) + hdrfname = datafname; + if( datafname == NULL || datafname[0] == '\0' ) + datafname = hdrfname; + + Msgf(("SDFopen: Calling SDFyyprepare(ptr, hdr=%s, data=%s)\n", hdrfname, datafname)); + if( SDFyyprepare(hdr, hdrfname, datafname) < 0 ){ + /* Hopefully, errstring was already set... */ + Free(hdr); + return NULL; + } + + parseerr= SDFyyparse(); + + if(parseerr){ + /* Try to free up whatever's been allocated inside the hdr */ + SDFclose(hdr); + return NULL; + }else{ + Msgf(("SDFopen: SDFyyparse completed ok\n")); + /* buildhash belongs in SDF_finishparse, but then I'd need to add + a bunch more externals... Yuck. */ + buildhash(hdr); + return hdr; + } +} + +int SDFclose(SDF *hdr) +{ + int i; + + if( hdr == NULL ){ + sprintf(SDFerrstring, "SDFclose: not an SDF hdr\n"); + return -1; + } + /* The check here is necessary in case we are trying to bail */ + /* out from inside SDFopen on a parse error. Cleaning up the */ + /* mess after a parse error still needs work! */ + if( hdr->vecs ){ + for(i=0; invecs; i++){ + Free(hdr->vecs[i].name); + } + } + obstack_free(&hdr->blks_obs, NULL); + obstack_free(&hdr->vecs_obs, NULL); + obstack_free(&hdr->data_obs, NULL); + if( hdr->vec_names ) + Free(hdr->vec_names); + if( hdr->datafp ) + MPMY_Fclose(hdr->datafp); + if( hdr->hashtbl ) + Free(hdr->hashtbl); + Free(hdr); + return 0; +} + +int SDFnvecs(SDF *hdr) +{ + if( hdr == NULL ){ + sprintf(SDFerrstring, "SDFnvecs: not an SDF hdr\n"); + return -1; + } + return hdr->nvecs; +} + +int SDFseekable(SDF *hdr) +{ + if( hdr == NULL ){ + sprintf(SDFerrstring, "SDFseekable: not an SDF hdr\n"); + return -1; + } + return (MPMY_Fseek(hdr->datafp, 0, MPMY_SEEK_CUR) >= 0); +} + +int SDFhasname(const char *name, SDF *hdr) +{ + if( hdr == NULL ){ + sprintf(SDFerrstring, "SDFhasname: not an SDF hdr\n"); + return -1; + } + return (lookup(name, hdr)) ? 1 : 0; +} + +char **SDFvecnames(SDF *hdr) +{ + if( hdr == NULL ){ + sprintf(SDFerrstring, "SDFvecnames: not an SDF hdr\n"); + return NULL; + } + return hdr->vec_names; +} + +int64_t SDFnrecs(const char *name, SDF *hdr) +{ + vec_descrip_t *desc; + + if( hdr == NULL ){ + sprintf(SDFerrstring, "SDFnrecs: not an SDF hdr\n"); + return -1; + } + desc = lookup(name, hdr); + if(desc) + return hdr->blks[desc->blk_num].Nrec; + else + return 0; +} + +int SDFarrcnt(const char *name, SDF *hdr) +{ + vec_descrip_t *desc; + + if( hdr == NULL ){ + sprintf(SDFerrstring, "SDFarrcnt: not an SDF hdr\n"); + return -1; + } + desc = lookup(name, hdr); + if(desc) + return desc->arrcnt; + else + return 0; +} + +enum SDF_type_enum SDFtype(const char *name, SDF *hdr) +{ + vec_descrip_t *desc; + + if( hdr == NULL ){ + sprintf(SDFerrstring, "SDFtype: not an SDF hdr\n"); + return SDF_NOTYPE; + } + desc = lookup(name, hdr); + if(desc) + return desc->type; + else + return SDF_NOTYPE; +} + +int SDFtell(const char *name, SDF *hdr) +{ + vec_descrip_t *desc; + + if( hdr == NULL ){ + sprintf(SDFerrstring, "SDFtell: not an SDF hdr\n"); + return -1; + } + desc = lookup(name, hdr); + if(desc) + return desc->nread; + else + return -1; +} + +int SDFseek(const char *name, int64_t offset, int whence, SDF *hdr) +{ + vec_descrip_t *desc; + int64_t nrec; + + if( hdr == NULL ){ + sprintf(SDFerrstring, "SDFseek: not an SDF hdr\n"); + return -1; + } + desc = lookup(name, hdr); + if(desc == NULL) + return -1; + + switch(whence){ + case SDF_SEEK_SET: + desc->nread = offset; + break; + case SDF_SEEK_CUR: + desc->nread += offset; + break; + case SDF_SEEK_END: + nrec = hdr->blks[desc->blk_num].Nrec ; + if(nrec == 0) + return -1; + desc->nread = nrec + offset; + } + return 0; +} + +/* SDFfileoffset and SDFfilestride are for those who think they */ +/* can outsmart SDF*rdvecs*. They tell you the offset of the FIRST */ +/* element of NAME in the file, and the stride between successive */ +/* elements. They do not pay any attention to the current seek pointer. */ +/* We do not provide SDFfilefp because we don't want you to mess with */ +/* our file pointer. Open the file yourself if you're so smart... */ +int64_t SDFfileoffset(const char *name, SDF *hdr){ + vec_descrip_t *desc; + blk_descrip_t *blk; + + if( hdr == NULL ){ + sprintf(SDFerrstring, "SDFfileoffset: not an SDF hdr\n"); + return -1; + } + if( hdr->begin_file_offset < 0 ){ + sprintf(SDFerrstring, "SDFfileoffset: unseekable file\n"); + return -1; + } + + desc = lookup(name, hdr); + if(desc == NULL) + return -1; + blk = &hdr->blks[desc->blk_num]; + if( blk->inmem ){ + sprintf(SDFerrstring, "SDFfileoffset: %s not in data segment\n", name); + return -1; + } + return blk->begin_offset + desc->blk_off + hdr->begin_file_offset; +} + +int64_t SDFfilestride(const char *name, SDF *hdr){ + vec_descrip_t *desc; + blk_descrip_t *blk; + + if( hdr == NULL ){ + sprintf(SDFerrstring, "SDFfilestride: not an SDF hdr\n"); + return -1; + } + desc = lookup(name, hdr); + if(desc == NULL) + return -1; + blk = &hdr->blks[desc->blk_num]; + if( blk->inmem ){ + sprintf(SDFerrstring, "SDFfilestride: %s not in data segment\n", name); + return -1; + } + return blk->reclen; +} + +unsigned int SDFcpubyteorder(void){ + return *cpubyteorder; +} + +unsigned int SDFbyteorder(SDF *hdr){ + if( hdr == NULL ){ + sprintf(SDFerrstring, "SDFbyteorder: not an SDF hdr\n"); + return -1; + } + /* This is either 0 or the value set by a 'parameter byteorder=' stmt */ + return hdr->byteorder; +} + +int SDFswap(SDF *hdr){ + if( hdr == NULL ){ + sprintf(SDFerrstring, "SDFswap: not an SDF hdr\n"); + return -1; + } + hdr->swapping = 1; + return 0; +} + +int SDFnoswap(SDF *hdr){ + if( hdr == NULL ){ + sprintf(SDFerrstring, "SDFnoswap: not an SDF hdr\n"); + return -1; + } + hdr->swapping = 0; + return 0; +} + +int SDFisswapping(SDF *hdr){ + if( hdr == NULL ){ + sprintf(SDFerrstring, "SDFisswapping: not an SDF hdr\n"); + return -1; + } + return hdr->swapping; +} + +int SDFsetmaxbufsz(int new){ + int ret = max_bufsz; + max_bufsz = new; + return ret; +} + +int SDFrdvecs(SDF *hdr, ... + /* char *name, int n, void *address, int stride, ... */ ) +{ + va_list ap; + int ret; + + if( hdr == NULL ){ + sprintf(SDFerrstring, "SDFrdvecs: not an SDF hdr\n"); + return -1; + } + va_start(ap, hdr); + ret = SDFrdvecsv(hdr, ap); + va_end(ap); + return ret; +} + +int SDFrdvecsv(SDF *hdr, va_list ap) +{ + int *narray; + char **namearray; + void **addressarray; + int *stridearray; + struct obstack nobs; + struct obstack nameobs; + struct obstack addressobs; + struct obstack strideobs; + int nrequests; + char *name; + int stride, n; + void *address; + int ret; + + if( hdr == NULL ){ + sprintf(SDFerrstring, "SDFrdvecsv: not an SDF hdr\n"); + return -1; + } + obstack_begin(&nameobs, 32*sizeof(char *)); + obstack_begin(&strideobs, 32*sizeof(int)); + obstack_begin(&nobs, 32*sizeof(int)); + obstack_begin(&addressobs, 32*sizeof(void *)); + + nrequests = 0; + while( (name = va_arg(ap, char *)) ){ + nrequests++; + obstack_ptr_grow(&nameobs, name); + n = va_arg(ap, int); + obstack_int_grow(&nobs, n); + address = va_arg(ap, void *); + obstack_ptr_grow(&addressobs, address); + stride = va_arg(ap, int); + obstack_int_grow(&strideobs, stride); + } + obstack_int_grow(&nobs, 0); + obstack_int_grow(&strideobs, 0); + obstack_ptr_grow(&nameobs, NULL); + obstack_ptr_grow(&addressobs, NULL); + + narray = (int *)obstack_finish(&nobs); + namearray = (char **)obstack_finish(&nameobs); + addressarray = (void **)obstack_finish(&addressobs); + stridearray = (int *)obstack_finish(&strideobs); + ret = SDFrdvecsarr(hdr, nrequests, + namearray, narray, addressarray, stridearray); + obstack_free(&nobs, NULL); + obstack_free(&nameobs, NULL); + obstack_free(&addressobs, NULL); + obstack_free(&strideobs, NULL); + return ret; +} + +int SDFrdvecsarr(SDF *hdr, int nreq, + char **names, int *ns, void **addresses, int *strides) +{ + int64_t *starts; + int i; + int ret; + vec_descrip_t *descrip; + + starts = Malloc(nreq*sizeof(int64_t)); + if( starts == NULL && nreq>0 ){ + sprintf(SDFerrstring, "Could not malloc tmp space in SDFrdvecsarr\n"); + return -1; + } + + for(i=0; inread; + } + if( (ret = SDFseekrdvecsarr(hdr, nreq, names, + starts, ns, addresses, strides)) ){ + goto outahere; + } + /* At this point, we have successfully looked up all */ + /* the names twice (at least). */ + for(i=0; inread += ns[i]; + } + outahere: + Free(starts); + return ret; +} + +int SDFseekrdvecs(SDF *hdr, ... + /* char *name, int start, int n, void *addr, int stride, ... */ ) +{ + va_list ap; + int ret; + + if( hdr == NULL ){ + sprintf(SDFerrstring, "SDFseekrdvecs: not an SDF hdr\n"); + return -1; + } + va_start(ap, hdr); + ret = SDFseekrdvecsv(hdr, ap); + va_end(ap); + return ret; +} + +int SDFseekrdvecsv(SDF *hdr, va_list ap) +{ + int *narray; + int64_t *startarray; + char **namearray; + void **addressarray; + int *stridearray; + struct obstack nobs; + struct obstack nameobs; + struct obstack startobs; + struct obstack addressobs; + struct obstack strideobs; + int nrequests; + char *name; + int64_t start; + int64_t zero64 = 0; + int stride, n; + void *address; + int ret; + + if( hdr == NULL ){ + sprintf(SDFerrstring, "SDFseekrdvecsv: not an SDF hdr\n"); + return -1; + } + obstack_begin(&nameobs, 32*sizeof(char *)); + obstack_begin(&startobs, 32*sizeof(int64_t)); + obstack_begin(&strideobs, 32*sizeof(int)); + obstack_begin(&nobs, 32*sizeof(int)); + obstack_begin(&addressobs, 32*sizeof(void *)); + + nrequests = 0; + while( (name = va_arg(ap, char *)) ){ + nrequests++; + obstack_ptr_grow(&nameobs, name); + start = va_arg(ap, int64_t); + obstack_grow(&startobs, &start, sizeof(int64_t)); + n = va_arg(ap, int); + obstack_int_grow(&nobs, n); + address = va_arg(ap, void *); + obstack_ptr_grow(&addressobs, address); + stride = va_arg(ap, int); + obstack_int_grow(&strideobs, stride); + } + obstack_int_grow(&nobs, 0); + obstack_grow(&startobs, &zero64, sizeof(int64_t)); + obstack_int_grow(&strideobs, 0); + obstack_ptr_grow(&nameobs, NULL); + obstack_ptr_grow(&addressobs, NULL); + + narray = (int *)obstack_finish(&nobs); + namearray = (char **)obstack_finish(&nameobs); + startarray = (int64_t *)obstack_finish(&startobs); + addressarray = (void **)obstack_finish(&addressobs); + stridearray = (int *)obstack_finish(&strideobs); + ret = SDFseekrdvecsarr(hdr, nrequests, + namearray, startarray, narray, addressarray, stridearray); + obstack_free(&nobs, NULL); + obstack_free(&nameobs, NULL); + obstack_free(&startobs, NULL); + obstack_free(&addressobs, NULL); + obstack_free(&strideobs, NULL); + return ret; +} + +static +void no_problem(const char *fmt, ...){ + /* Pass this to the MallocHandler function to tell Malloc that we + know what we're doing, and we really can recover from malloc + returning null! */ + return; +} + +int SDFseekrdvecsarr(SDF *hdr, int nreq, + char **names, int64_t *starts, int *ns, void **addresses, int *strides) +{ + int nn; + off_t fileoffset; + int i; + int64_t nrec; + int vecnum, first; + int next_blknum; + int last_blknum; + int64_t sz_needed; + int *sort_index; + vec_descrip_t *descrip, **vd_array; + char *fromptr, *toptr; + char *recptr, *buf; + int64_t buf_sz; + int64_t last_rec, first_rec, new_last_rec; + blk_descrip_t *blk; + int stride, sz; + int ret; + int64_t nread, rec_cnt, rec_left, ncopy, ntry; + int64_t *nleft, *seekto; + char **toptr_arr; + int64_t whole_sz; + Error_t oldmallochandler; + + if( hdr == NULL ){ + sprintf(SDFerrstring, "SDFseekrdvecsarr: not an SDF hdr\n"); + return -1; + } + buf = NULL; + buf_sz = 0; +#ifdef USE_ALLOCA + sort_index = alloca(nreq*sizeof(int)); + vd_array = alloca(nreq*sizeof(vec_descrip_t *)); + nleft = alloca(nreq*sizeof(int64_t)); + toptr_arr = alloca(nreq*sizeof(char *)); + seekto = alloca(nreq*sizeof(int64_t)); +#else + sort_index = Malloc(nreq*sizeof(int)); + vd_array = Malloc(nreq*sizeof(vec_descrip_t *)); + nleft = Malloc(nreq*sizeof(int64_t)); + toptr_arr = Malloc(nreq*sizeof(char *)); + seekto = Malloc(nreq*sizeof(int64_t)); +#endif + + if( nreq>0 && (sort_index == NULL + || vd_array == NULL || nleft == NULL || toptr_arr == NULL + || seekto == NULL) ){ + sprintf(SDFerrstring, + "SDFseekrdvecsarr: Malloc failed\n" + "sort_index(%lu) = 0x%lx, vd_array(%lu) = 0x%lx\n", + (unsigned long)nreq*sizeof(int), (unsigned long)sort_index, + (unsigned long)nreq*sizeof(vec_descrip_t), + (unsigned long)vd_array); + ret = -1; + goto outahere; + } + + for(i=0; iblks[vd_array[i]->blk_num].Nrec; + if(nrec > 0 && starts[i] + ns[i] > nrec){ + ret = -1; + Msg_do("nrec %ld i %d starts[i] %ld ns[i] %d\n", + nrec, i, starts[i], ns[i]); + sprintf(SDFerrstring, + "SDFseekrdvecsarr: attempt to read past end of vector \"%s\"", + names[i]); + goto outahere; + } + } + + compar_vds = vd_array; + qsort(sort_index, nreq, sizeof(sort_index[0]), compar_func); + /* Now the descrip_list is sorted so that we can do all the */ + /* vectors in the same block at once. */ + + vecnum = 0; + while( vecnum < nreq ){ + descrip = vd_array[sort_index[vecnum]]; + first = vecnum; + next_blknum = descrip->blk_num; + blk = &hdr->blks[next_blknum]; + first_rec = starts[sort_index[vecnum]]; + last_rec = first_rec; + do{ + new_last_rec = ns[sort_index[vecnum]] + starts[sort_index[vecnum]]; + if(new_last_rec > last_rec) + last_rec = new_last_rec; + last_blknum = next_blknum; + if(++vecnum == nreq) + break; + descrip = vd_array[sort_index[vecnum]]; + next_blknum = descrip->blk_num; + }while( last_blknum==next_blknum ); + + /* We are going to do all the vectors between first and vecnum */ + /* all at once. They all point at the same block. */ + rec_left = rec_cnt = last_rec - first_rec; + for(i=first; iinmem){ + recptr = ((char *)hdr->data) + blk->begin_offset + blk->reclen*first_rec; + fileoffset = 0; /* not necessary, but it quiets a warning */ + }else{ + whole_sz = blk->reclen * rec_left; + if( max_bufsz > 0 && whole_sz > max_bufsz ){ + sz_needed = (max_bufsz/blk->reclen)*blk->reclen; + if( sz_needed < blk->reclen ) + sz_needed = blk->reclen; + }else{ + sz_needed = whole_sz; + } + if( sz_needed > buf_sz ){ + oldmallochandler = MallocHandler(no_problem); + if( buf ) + Free(buf); + buf_sz = sz_needed; + buf = Malloc(buf_sz); + while( buf == NULL && buf_sz >= blk->reclen ){ + buf_sz >>= 1; + buf = Malloc(buf_sz); + } + MallocHandler(oldmallochandler); + if( buf == NULL ){ + sprintf(SDFerrstring, "SDFrdvecsarr: no space!\n"); + ret = -1; + goto outahere; + } + } + recptr = buf; + /* Repaired by msw Mon Jul 11 14:35:19 PDT 1994 */ + /* Repaired again by johns Tue Jun 27 14:55:42 EST 1995 */ + fileoffset = blk->begin_offset + (off_t)blk->reclen * first_rec + + hdr->begin_file_offset; + Msgf(("blk->reclen %d, first_rec %ld\n", blk->reclen, first_rec)); + Msgf(("fileoffset is %ld\n", fileoffset)); + Msgf(("buf_sz is %ld\n", buf_sz)); + } + + while( rec_left > 0 ){ + if(blk->inmem){ + nread = rec_left; + rec_left = 0; + }else{ + if( blk->reclen > buf_sz ){ + sprintf(SDFerrstring, "SDFrdvecsarr: not enough for one record!\n"); + ret = -1; + goto outahere; + } + whole_sz = blk->reclen * rec_left; + if( whole_sz > buf_sz ){ + ntry = (buf_sz-blk->reclen)/blk->reclen + 1; + }else{ + ntry = rec_left; + } + + /* SDFlib2 model has one file pointer, thus use SEEK_SET */ + if((nread = MPMY_Fseekrd(hdr->datafp, fileoffset, + MPMY_SEEK_SET, buf, blk->reclen, ntry)) + != ntry ){ + ret = -1; + sprintf(SDFerrstring, + "SDFrdvecsarr: fseekrd(offset=%ld, SEEK_CUR, reclen=%d, ntry=%ld) only got %ld, errno=%d\n", + fileoffset, blk->reclen, ntry, nread, errno); + goto outahere; + } + rec_left -= nread; + fileoffset += blk->reclen * (off_t)nread; + } + + for(i=first; i (first_rec + nread) || nleft[i] == 0 ) + continue; + fromptr = recptr + (seekto[i] - first_rec)*blk->reclen + + descrip->blk_off; + ncopy = nread - (seekto[i] - first_rec); + if( ncopy > nleft[i] ){ + ncopy = nleft[i]; + } + toptr = toptr_arr[i]; + stride = strides[sort_index[i]]; + sz = SDFtype_sizes[descrip->type]; + if( stride == 0 ) + stride = sz*descrip->arrcnt; + if( sz*descrip->arrcnt > stride ){ + /* This could have been checked earlier!!! */ + sprintf(SDFerrstring, "stride for %s not long enough to step over successive elements. arrcnt=%d, unit_sz=%d, stride=%d\n", + descrip->name, descrip->arrcnt, sz, stride); + ret = -1; + goto outahere; + } + for(nn=0; nn< ncopy; nn++){ + if(!blk->inmem && hdr->swapping){ + if(Byteswap( sz, descrip->arrcnt, fromptr, toptr)){ + sprintf(SDFerrstring, "SDFswapn(%d, %d, 0x%lx, 0x%lx) Failed", + sz, descrip->arrcnt, + (unsigned long)fromptr, + (unsigned long)toptr); + /* There's probably more cleaning up to do! */ + ret = -1; + goto outahere; + } + }else{ + (void)memcpy( toptr, fromptr, sz * descrip->arrcnt); + } + fromptr += blk->reclen; + toptr += stride; + } + seekto[i] += ncopy; + nleft[i] -= ncopy; + toptr_arr[i] = toptr; + } + first_rec += nread; + } + } + ret = 0; + outahere: + /* alloca would be simpler! */ + /* The tests are not necessary according to ANSI... */ +#ifndef USE_ALLOCA + if( seekto ) Free(seekto); + if( toptr_arr ) Free(toptr_arr); + if( nleft ) Free(nleft); + if( vd_array ) Free(vd_array); + if( sort_index ) Free(sort_index); +#endif + if( buf ) Free(buf); + return ret; +} + +static int compar_func(const void *p1, const void *p2){ + int i1 = *(int *)p1; + int i2 = *(int *)p2; + vec_descrip_t *d1 = compar_vds[i1]; + vec_descrip_t *d2 = compar_vds[i2]; + + if(d1->blk_num < d2->blk_num) + return -1; + else if(d1->blk_num > d2->blk_num) + return 1; + else if(d1->nread < d2->nread) + return -1; + else if(d1->nread > d2->nread) + return 1; + else if(d1->blk_off < d2->blk_off) + return -1; + else if(d1->blk_off > d2->blk_off) + return 1; + else + return 0; +} + +/* a few prime numbers chosen entirely at random... */ +#define NCOEF (sizeof(hashcoef)/sizeof(*hashcoef)) +static int hashcoef[] = { 17, 37, 3, 97, 57, 23, 151, 7, 41 }; + +/* + This completely bogus hash function computes a linear combination of + characters in the word. +*/ +static int SDFhash(const char *word, SDF *hdr){ + int i; + const char *p; + int sum = 0; + + p = word; + i = 0; + while(*p){ + sum += hashcoef[i] * *p; + p++; + if( ++i == NCOEF ) + i = 0; + } + Msgf(("hash(%s) = %d%%%d = %d\n", word, sum, hdr->hashsz, sum%hdr->hashsz)); + return sum % hdr->hashsz; +} + +static int isprime(int n){ + int d; + /* this only needs to work for small O(few hundred) values of n */ + /* first make sure it's not even */ + if( (n&1) == 0 ) + return 0; + /* Extremely naive. Now check all odd potential divisors up to sqrt(n) */ + for(d = 3; d*d<=n ; d+=2){ + if( n%d == 0 ) + return 0; + } + return 1; +} + +static int nextprime(int n){ + Msgf(("nextprime(%d) = ", n)); + if( (n&1) == 0 ) + n++; + while(!isprime(n)) n+=2; + Msgf(("%d\n", n)); + return n; +} + +static void buildhash(SDF *hdr){ + int sz; + int i, h; + + sz = nextprime(5*hdr->nvecs); + Msgf(("hash table of size %d\n", sz)); + hdr->hashsz = sz; + hdr->hashtbl = Calloc(sz, sizeof(*hdr->hashtbl)); + + for(i=0; invecs; i++){ + h = SDFhash(hdr->vecs[i].name, hdr); + while( hdr->hashtbl[h] != NULL ){ + Msgf(("build: hcollision between %s and %s in name-space\n", + hdr->hashtbl[h]->name, hdr->vecs[i].name)); + h++; + if(h==sz) /* wrap */ + h = 0; + } + hdr->hashtbl[h] = &hdr->vecs[i]; + } +} + +static vec_descrip_t *lookup(const char *name, SDF *hdr) +{ + int i, istart; + vec_descrip_t *possible; + + i = istart = SDFhash(name, hdr); + do{ + possible = hdr->hashtbl[i]; + if( possible == NULL ){ + break; + } + if( strcmp(possible->name, name) == 0 ) + return possible; + + Msgf(("lookup: hcollision i=%d, name=%s, tblname=%s\n", + i, name, possible->name)); + i++; + if( i==hdr->hashsz ) /* wrap */ + i = 0; + /* It ought to be imposible to fall off the bottom of this loop */ + }while(i!= istart); + + sprintf(SDFerrstring, "No such name, \"%s\" in file.", name); + return NULL; +} diff --git a/external/libsdf/libSDF/SDFget.c b/external/libsdf/libSDF/SDFget.c new file mode 100644 index 0000000..2dfe7b1 --- /dev/null +++ b/external/libsdf/libSDF/SDFget.c @@ -0,0 +1,278 @@ +#include +/* stdio only needed for sprintf proto */ +#include +#include "error.h" +#include "SDF.h" +/* + +These routines return 0 on success and 1 on failure. They set +SDFerrstring if they think something strange is happening. They +don't change the value under the VALUE argument until they are sure +that everything is OK, so it's possible (but what would Henry Spencer +say?) to use them by setting a default value, then calling the routine, +and not worrying about the error condition. + +*/ + +/* An abbreviation used many times... */ + +#define SDFget(sdfp, name, addr) \ + if(SDFseekrdvecs(sdfp, name, 0, 1, addr, 0, NULL)) return -1 + +/* I'll resist the temptation to make one macro to cover all these cases */ +/* Should we check for loss of precision in float too? */ +int +SDFgetfloat(SDF *sdfp, char *name, float *value) +{ + double double_value; + int int_value; + long long_value; + int64_t int64_value; + float float_value; + + if( sdfp == NULL || !SDFhasname(name, sdfp) ){ + return -1; + } + switch(SDFtype(name, sdfp)){ + case SDF_FLOAT: + SDFget(sdfp, name, &float_value); + *value = float_value; + return 0; + case SDF_DOUBLE: + SDFget(sdfp, name, &double_value); + *value = (float) double_value; + return 0; + case SDF_INT: + SDFget(sdfp, name, &int_value); + *value = (float) int_value; + return 0; + case SDF_LONG: + SDFget(sdfp, name, &long_value); + *value = (float) long_value; + return 0; + case SDF_INT64: + SDFget(sdfp, name, &int64_value); + *value = (float) int64_value; + return 0; + default: + sprintf(SDFerrstring, + "SDFgetfloat: \"%s\" must be either float or int.\n", name); + return -1; + } +} + +int +SDFgetdouble(SDF *sdfp, char *name, double *value) +{ + double double_value; + float float_value; + int int_value; + long long_value; + int64_t int64_value; + + if( sdfp == NULL || !SDFhasname(name, sdfp) ){ + return -1; + } + switch(SDFtype(name, sdfp)){ + case SDF_DOUBLE: + SDFget(sdfp, name, &double_value); + *value = double_value; + return 0; + case SDF_FLOAT: + SDFget(sdfp, name, &float_value); + *value = (double) float_value; + return 0; + case SDF_INT: + SDFget(sdfp, name, &int_value); + *value = (double) int_value; + return 0; + case SDF_LONG: + SDFget(sdfp, name, &long_value); + *value = (double) long_value; + return 0; + case SDF_INT64: + SDFget(sdfp, name, &int64_value); + *value = (double) int64_value; + return 0; + default: + sprintf(SDFerrstring, + "SDFgetdouble: \"%s\" must be either float or int.\n", name); + return -1; + } +} + +int +SDFgetint(SDF *sdfp, char *name, int *value) +{ + int int_value; + float float_value; + double double_value; + + if( sdfp == NULL || !SDFhasname(name, sdfp) ){ + return -1; + } + switch(SDFtype(name, sdfp)){ + case SDF_INT: + SDFget(sdfp, name, &int_value); + *value = int_value; + return 0; + case SDF_DOUBLE: + SDFget(sdfp, name, &double_value); + int_value = (int) double_value; + if ((double)int_value != double_value){ + sprintf(SDFerrstring, + "SDFgetint: \"%s\" has lost precision\n", name); + return -1; + } + *value = int_value; + return 0; + case SDF_FLOAT: + SDFget(sdfp, name, &float_value); + int_value = (int) float_value; + if ((float)int_value != float_value){ + Warning("SDFgetint: \"%s\" has lost precision\n", name); + return -1; + } + *value = int_value; + return 0; + default: + sprintf(SDFerrstring, "SDFgetint: \"%s\" must be either float or int.\n", name); + return -1; + } +} + +int +SDFgetlong(SDF *sdfp, char *name, long *value) +{ + int int_value; + float float_value; + double double_value; + long long_value; + int64_t int64_value; + + if( sdfp == NULL || !SDFhasname(name, sdfp) ){ + return -1; + } + switch(SDFtype(name, sdfp)){ + case SDF_INT: + SDFget(sdfp, name, &int_value); + *value = int_value; + return 0; + case SDF_LONG: + SDFget(sdfp, name, &long_value); + *value = long_value; + return 0; + case SDF_INT64: + SDFget(sdfp, name, &int64_value); + long_value = (long) int64_value; + if ((int64_t)long_value != int64_value){ + sprintf(SDFerrstring, + "SDFgetint: \"%s\" has lost precision\n", name); + return -1; + } + *value = int64_value; + return 0; + case SDF_DOUBLE: + SDFget(sdfp, name, &double_value); + long_value = (long) double_value; + if ((double)int_value != double_value){ + sprintf(SDFerrstring, + "SDFgetlong: \"%s\" has lost precision\n", name); + return -1; + } + *value = int_value; + return 0; + case SDF_FLOAT: + SDFget(sdfp, name, &float_value); + long_value = (long) float_value; + if ((float)long_value != float_value){ + Warning("SDFgetlong: \"%s\" has lost precision\n", name); + return -1; + } + *value = long_value; + return 0; + default: + sprintf(SDFerrstring, "SDFgetint: \"%s\" must be either float or int.\n", name); + return -1; + } +} + +int +SDFgetint64(SDF *sdfp, char *name, int64_t *value) +{ + int int_value; + float float_value; + double double_value; + long long_value; + int64_t int64_value; + + if( sdfp == NULL || !SDFhasname(name, sdfp) ){ + return -1; + } + switch(SDFtype(name, sdfp)){ + case SDF_INT: + SDFget(sdfp, name, &int_value); + *value = int_value; + return 0; + case SDF_LONG: + SDFget(sdfp, name, &long_value); + *value = long_value; + return 0; + case SDF_INT64: + SDFget(sdfp, name, &int64_value); + *value = int64_value; + return 0; + case SDF_DOUBLE: + SDFget(sdfp, name, &double_value); + int64_value = (int64_t) double_value; + if ((double)int64_value != double_value){ + sprintf(SDFerrstring, + "SDFgetint64: \"%s\" has lost precision\n", name); + return -1; + } + *value = int64_value; + return 0; + case SDF_FLOAT: + SDFget(sdfp, name, &float_value); + int64_value = (int64_t) float_value; + if ((float)int64_value != float_value){ + Warning("SDFgetint64: \"%s\" has lost precision\n", name); + return -1; + } + *value = int64_value; + return 0; + default: + sprintf(SDFerrstring, "SDFgetint: \"%s\" must be either float or int.\n", name); + return -1; + } +} + +int +SDFgetstring(SDF *sdfp, const char *name, char *string, int size){ + int len; + int ret; + + if( sdfp == NULL ){ + sprintf(SDFerrstring, "SDFgetint: NULL sdfp\n"); + return -1; + } + if( !SDFhasname(name, sdfp) ){ + return -1; + } + if( SDFtype(name, sdfp) != SDF_CHAR ){ + return -1; + } + if( (len=SDFarrcnt(name, sdfp)) >= size ){ + return -1; + } + + ret = SDFseekrdvecs(sdfp, name, 0, 1, string, 0, NULL); + if( string[len-1] != '\0' ){ + sprintf(SDFerrstring, + "Read non-terminated string in SDFgetstring(\"%s\")\n", name); + string[len] = '\0'; + } + return ret; +} + + diff --git a/external/libsdf/libSDF/SDFhdrio.c b/external/libsdf/libSDF/SDFhdrio.c new file mode 100644 index 0000000..dccb38a --- /dev/null +++ b/external/libsdf/libSDF/SDFhdrio.c @@ -0,0 +1,86 @@ +/* An implementation of getc, using MPMY functions. */ + +#include +#include +#include "Msgs.h" +#include "error.h" +#include "SDF-private.h" +#include "stdio.h" +#include "mpmy_io.h" + +#define MYBUFSZ 4096 + +/* Assumption: we can only have one header at a time being read. + The header is opened, read anc closed, all during the course of SDFopen + so we don't have to screw around with multiple open files, etc. */ + +static MPMYFile *fp; +static char buf[MYBUFSZ]; +static char *ptr; +static char *endbuf; +static int buf_offset; + + +int SDF_Hdropen(const char *name){ + fp = MPMY_Fopen(name, MPMY_RDONLY|MPMY_SINGL); + if( fp == NULL ) + return -1; + endbuf = ptr = buf; + buf_offset = 0; + Msg("SDF", ("SDFhdropen: return fp=%p\n", fp)); + return 0; +} + +void SDF_Hdrclose(void){ + Msg("SDF", ("SDFhdrclose called\n")); + MPMY_Fclose(fp); + endbuf = ptr = NULL; + fp = NULL; + buf_offset = -1; +} + +int SDF_Hdroffset(void){ + if( ptr == NULL ) + return -1; + return buf_offset + (ptr - buf); +} + +int SDF_Hdrgetc(){ + int nread; + + if( ptr == NULL ){ + Msgf(("SDFhdrgetc: Returning EOF, ptr==NULL\n")); + return EOF; + } + + if( ptr < endbuf ){ + if( *ptr == '\0' ){ + SinglWarning("Returning NULL at char %d in SDFhdrio\n", (int)(ptr-buf)); + } + Msgf(("SDF_hdrgetc: %c\n", *ptr)); + return *ptr++; + } + + nread = MPMY_Fread(buf, 1, MYBUFSZ, fp); + {int i; + int sum = 0; + for(i=0; iptr */ + return SDF_Hdrgetc(); +} + diff --git a/external/libsdf/libSDF/dictionary b/external/libsdf/libSDF/dictionary new file mode 100644 index 0000000..301e818 --- /dev/null +++ b/external/libsdf/libSDF/dictionary @@ -0,0 +1,54 @@ +This is a dictionary of "known" names in nbody files. +It will be extended as the need arises. + +The first few come from the headers: + +float npart +float iter +float time +float ke +float pe +float masstot +float l_ang +float Gnewt +float epsilon +float zinitial +float omega +float hubble +float box_size +float znow +float initial_rsize +float initial_rmin_x +float initial_rmin_y +float initial_rmin_z +float veltime +float sizeof_ext +float alpha +float beta +float curvature +float lambda +float cosm_integral +float radius +int int_npart +int int_sizeof_ext +char tree_header_text[384]; + +The following arrays are of length (int)nbody. Unfortunately, +in order to maintain historical compatibilty, the length of the +array is stored as a binary float in the files, so consider using +nbio_rd_double(..., "nbody") to figure out how long these vectors are. + +float x[], y[], z[] +float vx[], vy[], vz[] +float mass[] + +From the msw .ap files, we also have +float acc[] +float phi[] + +Presumably, we should also reserve: +float ax[], ay[], az[] + +The char id[][4] is specified by tree and tree_ap files. + +There will undoubtedly be others. \ No newline at end of file diff --git a/external/libsdf/libSDF/stdio.h b/external/libsdf/libSDF/stdio.h new file mode 100644 index 0000000..b4bf00b --- /dev/null +++ b/external/libsdf/libSDF/stdio.h @@ -0,0 +1,35 @@ +/* This file is a replacement for the few parts of stdio.h */ +/* that are assumed by the output of lex and yacc. */ +/* It is here because lex's output contains #include "stdio.h" */ +/* and we don't want to be contaminated by the system stdio.h */ + +#ifndef MYSTDIOdotH +#define MYSTDIOdotH +#include "mpmy_io.h" + +/* These are replacements for stdio */ +#undef getc +#define getc(fp) SDF_Hdrgetc() +/* Putc is used by 'output'. This is the easiest way to deal with it */ +#undef putc +#define putc(c, fp) (Msg_do("%c", c)) +#undef FILE +#define FILE MPMYFile +#undef stdin +#define stdin NULL +#undef stdout +#define stdout NULL +#undef stderr +#define stderr NULL +#undef EOF +#define EOF (-1) +#undef BUFSIZ +#define BUFSIZ 512 + +/* A couple of prototypes that are in stdio are also needed */ +#include +int sscanf(const char *, const char *, ...); +int vsprintf(char *, const char *, va_list); +int sprintf(char *, const char *, ...); + +#endif diff --git a/external/libsdf/libmpmy/GNUmakefile b/external/libsdf/libmpmy/GNUmakefile new file mode 100644 index 0000000..1d4bd32 --- /dev/null +++ b/external/libsdf/libmpmy/GNUmakefile @@ -0,0 +1,106 @@ +# Make.$(ARCH) sets many of the variables used below including: +# CC, CFLAGS, AS, RANLIB, objdir, objsuf, asmdir + +# This Makefile is 'non-standard' because we are trying to create a .o +# file in the '$(libdir)' directory. Furthermore, the name of the +# file we are creating can't be determined until after we have 'include'd +# the $(ARCH)-specific makefile (so we can use the default PAROS). +# +# The dependencies are even more unreliable than usual. +# +# It's amazing that it works at all... + +treedir=.. +treedir_sed=\.\. +appexcludes= +libname=NO_NAME +# This is here only to allow 'make depends' to work. +src=mpmy_seq.c mpmy_lsv.c mpmy_nx.c mpmy_vertex.c mpmy_sunmos.c mpmy_mpi.c mpmy_eui.c mpmy_pvm.c mpmy_craypvm.c + +special_rule_for_all=YES +all: special + +include $(treedir)/Make-common/Make.$(ARCH) + +include $(treedir)/Make-common/Make.generic + +override CFLAGS:=$(PAROSCFLAGS) $(CFLAGS) + +# I think these should be handled with PAROSCFLAGS +# So sue me! +#ifeq ($(PAROS),eui) +#CFLAGS:=-I/usr/lpp/euih/eui $(CFLAGS) +#endif + +#ifeq ($(PAROS),mpi) +#CFLAGS:=-I/usr/lpp/mpif $(CFLAGS) +#endif + +#ifeq ($(PAROS),srv) +#CFLAGS:=-I$(SRVHOME)/include/cros3 $(CFLAGS) +#endif + +#ifeq ($(PAROS),pvm) +#CFLAGS:=-I$(PVM_ROOT)/include $(CFLAGS) +#endif + +# order is important here. We need to make $(libdir) +special: $(libdir)/mpmy_$(PAROS)$(objsuf) + +$(libdir)/mpmy_$(PAROS)$(objsuf) : $(objdir)/mpmy_$(PAROS)$(objsuf) $(libdir) + cp $< $@ + +$(objdir)/mpmy_$(PAROS)$(objsuf) : $(objdir) + +# If there's a default PAROS for this architecture, then we put +# mpmy_$(PAROS).o into libsw.a. To override it, it is +# necessary to list mpmy_$(alternative).o AHEAD of libsw.a in the +# link command. But if you just want the defaults (typically _seq), then +# the only thing to link against is libsw.a. +ifeq ($(PAROS),$(defaultPAROS)) +special: $(libdir)/libsw$(libext)($(objdir)/mpmy_$(PAROS)$(objsuf)) + $(RANLIB) $(libdir)/libsw$(libext) + +$(libdir)/libsw$(libext)($(objdir)/mpmy_$(PAROS)$(objsuf)) : $(libdir) + +endif + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +$(objdir)/mpmy_seq$(objsuf): +$(objdir)/mpmy_seq$(objsuf): $(treedir)/include/libsdf/Msgs.h +$(objdir)/mpmy_seq$(objsuf): $(treedir)/include/libsdf/gccextensions.h $(treedir)/include/libsdf/mpmy.h +$(objdir)/mpmy_seq$(objsuf): $(treedir)/include/libsdf/timers.h +$(objdir)/mpmy_seq$(objsuf): $(treedir)/include/libsdf/Assert.h $(treedir)/include/libsdf/error.h +$(objdir)/mpmy_seq$(objsuf): $(treedir)/include/libsdf/mpmy_io.h $(treedir)/include/libsdf/mpmy_time.h +$(objdir)/mpmy_seq$(objsuf): $(treedir)/include/libsdf/mpmy_abnormal.h timers_hwclock.c +$(objdir)/mpmy_seq$(objsuf): $(treedir)/include/libsdf/Malloc.h +$(objdir)/mpmy_seq$(objsuf): $(treedir)/include/libsdf/chn.h mpmy_io.c +$(objdir)/mpmy_seq$(objsuf): +$(objdir)/mpmy_seq$(objsuf): +$(objdir)/mpmy_seq$(objsuf): +$(objdir)/mpmy_seq$(objsuf): +$(objdir)/mpmy_seq$(objsuf): $(treedir)/include/libsdf/protos.h iozero.h +$(objdir)/mpmy_seq$(objsuf): iozero.c io_generic.c mpmy_abnormal.c +$(objdir)/mpmy_seq$(objsuf): +$(objdir)/mpmy_seq$(objsuf): $(treedir)/include/libsdf/singlio.h +$(objdir)/mpmy_seq$(objsuf): mpmy_generic.c +$(objdir)/mpmy_mpi$(objsuf): $(treedir)/include/libsdf/mpmy_abnormal.h +$(objdir)/mpmy_mpi$(objsuf): $(treedir)/include/libsdf/gccextensions.h +$(objdir)/mpmy_mpi$(objsuf): $(treedir)/include/libsdf/Malloc.h $(treedir)/include/libsdf/error.h +$(objdir)/mpmy_mpi$(objsuf): $(treedir)/include/libsdf/chn.h $(treedir)/include/libsdf/Assert.h +$(objdir)/mpmy_mpi$(objsuf): $(treedir)/include/libsdf/mpmy.h $(treedir)/include/libsdf/timers.h +$(objdir)/mpmy_mpi$(objsuf): +$(objdir)/mpmy_mpi$(objsuf): $(treedir)/include/libsdf/Msgs.h $(treedir)/include/libsdf/memfile.h +$(objdir)/mpmy_mpi$(objsuf): timers_hwclock.c +$(objdir)/mpmy_mpi$(objsuf): $(treedir)/include/libsdf/mpmy_time.h +$(objdir)/mpmy_mpi$(objsuf): mpmy_mpiio.c +$(objdir)/mpmy_mpi$(objsuf): +$(objdir)/mpmy_mpi$(objsuf): +$(objdir)/mpmy_mpi$(objsuf): +$(objdir)/mpmy_mpi$(objsuf): +$(objdir)/mpmy_mpi$(objsuf): +$(objdir)/mpmy_mpi$(objsuf): $(treedir)/include/libsdf/protos.h +$(objdir)/mpmy_mpi$(objsuf): $(treedir)/include/libsdf/mpmy_io.h io_generic.c mpmy_abnormal.c +$(objdir)/mpmy_mpi$(objsuf): $(treedir)/include/libsdf/singlio.h +$(objdir)/mpmy_mpi$(objsuf): mpmy_generic.c diff --git a/external/libsdf/libmpmy/io_generic.c b/external/libsdf/libmpmy/io_generic.c new file mode 100644 index 0000000..244116c --- /dev/null +++ b/external/libsdf/libmpmy/io_generic.c @@ -0,0 +1,59 @@ +/* Some i/o routines that are likely to be common... */ + +#ifndef HAVE_MPMY_FPRINTF + +int MPMY_Fprintf(MPMYFile *fp, const char *fmt, ...){ + int ret; + va_list ap; + va_start(ap, fmt); + ret = MPMY_Vfprintf(fp, fmt, ap); + va_end(ap); + return ret; +} +#endif + +#ifndef HAVE_MPMY_VFPRINTF +#include +#include + +static char buf[1024]; + +int MPMY_Vfprintf(MPMYFile *fp, const char *fmt, va_list args){ + /* What a pain. Sometimes sprintf returns a char* and sometimes + it returns an int. There's no good way to tell, but this + should do.*/ + long ret = (long)vsprintf(buf, fmt, args); + + /* Broken versions of sprintf return their first arg... */ + if( ret == (long)buf ) + ret = strlen(buf); + + if( ret < 0 ){ + return ret; + } + if( ret >= sizeof(buf) ){ + /* This is serious. We've probably scribbled over memory. + Maybe we should just bail out now? + */ + static int recursion; + if( recursion++ == 0 ) + Error("MPMY_Vfprintf overflow. Data corruption likely!\n"); + recursion--; + } + + if( MPMY_Fwrite(buf, 1, ret, fp) != ret ){ + return -1; + } + return ret; +} +#endif + +#ifndef HAVE_MPMY_FLUSH + +/* This is here just for completeness... The higher levels all do + their I/O using unbuffered primitives (read/write/open/close), so + we don't have to do anything special to flush output */ +int MPMY_Fflush(MPMYFile *fp){ + return 0; +} +#endif diff --git a/external/libsdf/libmpmy/iozero.c b/external/libsdf/libmpmy/iozero.c new file mode 100644 index 0000000..279c3aa --- /dev/null +++ b/external/libsdf/libmpmy/iozero.c @@ -0,0 +1,360 @@ +/* More include madness. This is such good stuff, that I can't resist */ +/* just "#include"ing it into all the mpmy_??io.c files...*/ + +/* Try to use different tags for the different kinds of broadcasts... */ +#define BCAST_CLOSE 0x3579 +#define BCAST_OPEN 0x3779 +#define BCAST_READ1 0x3979 +#define BCAST_READ2 0x3b79 +#define BCAST_WRITE 0x3d79 +#define BCAST_LSEEK 0x3f79 +#define BCAST_TELL 0x4179 +#define BCAST_FLEN 0x4379 +#define BCAST_MKDIR 0x4579 + +static int +open0(const char *path, int flags, int mode) +{ + int ret; + + /* paragon left the const out of the prototype */ + Msgf(("open0(path=%s, flags=%#x, mode=%#x\n", path, flags, mode)); + if (MPMY_Procnum() == 0){ + ret = open((char *)path, flags, mode); + Msgf(("open returns %d on node 0\n", ret)); + } + MPMY_BcastTag(&ret, 1, MPMY_INT, 0, BCAST_OPEN); + Msgf(("open0 returning %d\n", ret)); + return ret; +} + +static int +close0(int fd) +{ + int ret; + + if (MPMY_Procnum() == 0) ret = close(fd); + MPMY_BcastTag(&ret, 1, MPMY_INT, 0, BCAST_CLOSE); + return ret; +} + +static long +read0(int fd, void *buf, unsigned long nbytes) +{ + long ret; + + if (MPMY_Procnum() == 0){ + ret = read(fd, buf, nbytes); + Msgf(("read0: read(fd=%d, nbytes=%ld) returns %ld\n", + fd, nbytes, ret)); + } + MPMY_BcastTag(&ret, 1, MPMY_LONG, 0, BCAST_READ1); + Msgf(("read0: after Bcast ret = %ld\n", ret)); + if( ret > 0 ) + MPMY_BcastTag(buf, ret, MPMY_CHAR, 0, BCAST_READ2); + if( Msg_test(__FILE__)){ + int i; + int sum = 0; + char *cbuf = buf; + for(i=0; i 0) { + off_t nwrite = (nbytes > MAX_IOBUF) ? MAX_IOBUF : nbytes; + off_t wrote; + wrote = write(fd, buf+ret, nwrite); + if (wrote != nwrite) Shout("write failed, errno=%d\n", errno); + ret += wrote; + nbytes -= wrote; + } + Msgf(("write0 %ld\n", ret)); + if (nproc > 1) { + tmpbuf = Malloc(nbytes); + for (i = procnum+1; i < nproc; i++) { + /* This could be double-buffered */ + tmpbuf = Realloc(tmpbuf, sizes[i]); + /* Avoid deluge of messages by sync */ + MPMY_send(&sync, sizeof(int), i, MPMY_IOTAG); + MPMY_recvn(tmpbuf, sizes[i], i, MPMY_IOTAG); + n = write(fd, tmpbuf, sizes[i]); + if (n != sizes[i]) Shout("write failed, errno=%d\n", errno); + Msgf(("write%d %d\n", i, n)); + /* should we send errno as well? */ + MPMY_send(&n, sizeof(int), i, MPMY_IOTAG); + } + Free(tmpbuf); + } + Free(sizes); + } else { + MPMY_Gather(&nbytes, 1, MPMY_OFFT, NULL, 0); + MPMY_recvn(&sync, sizeof(int), 0, MPMY_IOTAG); + Msgf(("sending %ld bytes\n", nbytes)); + MPMY_send(buf, nbytes, 0, MPMY_IOTAG); + MPMY_recvn(&ret, sizeof(int), 0, MPMY_IOTAG); + } + return ret; +} + +static long +read0_multi(int fd, void *buf, off_t nbytes) +{ + int ret; + off_t *sizes; + int i, n; + char *tmpbuf; + int nproc = MPMY_Nproc(); + int procnum = MPMY_Procnum(); + + if (sizeof(off_t) != sizeof(long long)) { + Error("Type problem in write0_multi\n"); + } + if (procnum == 0) { + sizes = Malloc(sizeof(off_t)*nproc); + MPMY_Gather(&nbytes, 1, MPMY_OFFT, sizes, 0); + ret = read(fd, buf, nbytes); + if (ret != nbytes) Shout("read failed, errno=%d\n", errno); + Msgf(("read0 %d\n", ret)); + if (nproc > 1) { + tmpbuf = Malloc(nbytes); + for (i = procnum+1; i < nproc; i++) { + /* This could be double-buffered */ + tmpbuf = Realloc(tmpbuf, sizes[i]); + n = read(fd, tmpbuf, sizes[i]); + MPMY_send(tmpbuf, n, i, MPMY_IOTAG); + if (n != sizes[i]) Shout("read failed, errno=%d\n", errno); + Msgf(("read%d %d\n", i, n)); + } + Free(tmpbuf); + } + Free(sizes); + } else { + MPMY_Status stat; + MPMY_Comm_request req; + + MPMY_Gather(&nbytes, 1, MPMY_OFFT, NULL, 0); + MPMY_Irecv(buf, nbytes, 0, MPMY_IOTAG, &req); + MPMY_Wait(req, &stat); + ret = MPMY_Count(&stat); + } + return ret; +} + + diff --git a/external/libsdf/libmpmy/iozero.h b/external/libsdf/libmpmy/iozero.h new file mode 100644 index 0000000..4ea2f48 --- /dev/null +++ b/external/libsdf/libmpmy/iozero.h @@ -0,0 +1,20 @@ +#ifndef IOzeroDOTh +#define IOzeroDOTh + +#define MPMY_IOTAG (0x183) +#define IoZero(fp) (fp->flags & MPMY_IOZERO) + +static int open0(const char *path, int flags, int mode); +static int close0(int fd); +static int mkdir0(const char *path, int mode); +static long read0(int fd, void *buf, unsigned long nbytes); +static long write0(int fd, const void *buf, unsigned long nbytes); +static off_t lseek0(int fd, off_t offset, int whence); +static off_t tell0(int fd); +static off_t flen(int fd); +static off_t flen0(int fd); +static long fseekrd0(int fd, off_t offset, int whence, void *buf, + int reclen, int nrecs); +static long write0_multi(int fd, const void *buf, off_t nbytes); +static long read0_multi(int fd, void *buf, off_t nbytes); +#endif diff --git a/external/libsdf/libmpmy/mpmy-private.h b/external/libsdf/libmpmy/mpmy-private.h new file mode 100644 index 0000000..139597f --- /dev/null +++ b/external/libsdf/libmpmy/mpmy-private.h @@ -0,0 +1,2 @@ + + diff --git a/external/libsdf/libmpmy/mpmy_abnormal.c b/external/libsdf/libmpmy/mpmy_abnormal.c new file mode 100644 index 0000000..44f53c1 --- /dev/null +++ b/external/libsdf/libmpmy/mpmy_abnormal.c @@ -0,0 +1,259 @@ +/* Yet another attempt to rationalize the abnormal termination of + parallel programs. + + Issues to consider: + - Do core files exist, and are they useful. + - Do we need to chdir before dumping a core file. + - Exactly how do we go about dumping a core file. + - Do we want to do anything else before quitting. + - Sometimes we get the most information when we just return + from a signal handler (delta). + - Parts will need to be over-ridden by mpmy_.c, but + duplication of code should be minimized. + - include files, values of signals, etc. are all wildly system + specific. +*/ + +#include +#include +#include "singlio.h" +#include "Msgs.h" +#include "mpmy_abnormal.h" + +#ifndef MPMY_ABORT +void MPMY_Abort(void){ + MPMY_RaiseAbnormal(SIGABRT); + MPMY_SystemAbort(); +} +#endif + +#ifdef _AIX + /* dje says AIX dumps core fine, but the debuggers are confused by + the signal handlers. Another way of achieving this might be + to set absiglist and MPMY_HAVE_ABSIGLIST in the mpmy_paros.c file. */ +#define NO_SIGNALS +#endif + +#if !defined( HAVE_ABSIG_LIST ) && !defined(NO_SIGNALS) +static int absiglist[]={ +#if 0 && defined(SIGABRT) /* ANSI */ +/* DO NOT TRAP SIGABRT! Just leave it completely alone. We studiously + avoid calling abort in our code, so we should just let SIGABRT do its + normal, unmodified thing. */ +SIGABRT, +#endif +#ifdef SIGFPE /* ANSI */ +SIGFPE, +#endif +#ifdef SIGIILL /* ANSI */ +SIGILL, +#endif +#ifdef SIGIOT /* ANSI */ +SIGIOT, +#endif +#ifdef SIGSEGV /* ANSI */ +SIGSEGV, +#endif +#ifdef SIGQUIT +SIGQUIT, +#endif +#ifdef SIGTRAP +SIGTRAP, +#endif +#ifdef SIGEMT +SIGEMT, +#endif +#ifdef SIGKILL +SIGKILL, /* for form's sake */ +#endif +#ifdef SIGBUS +SIGBUS, +#endif +#ifdef SIGSYS +SIGSYS, +#endif +#ifdef SIGPIPE +SIGPIPE, +#endif +/* Do we need to worry about a trailing comma?? */ +}; +#endif /* HAVE_ABSIGLIST */ + +#ifndef HAVE_SETUP_ABSIGS +void _MPMY_setup_absigs(void){ + int i; +#if !defined(NO_SIGNALS) + for(i=0; i< sizeof(absiglist)/sizeof(*absiglist); i++){ + signal(absiglist[i], MPMY_RaiseAbnormal); + } +#endif +} +#endif + +#ifndef HAVE_ABNORMAL +#define MAXUSERFUNCS 64 + +static int nuserfuncs = 0; +static Abhndlr userfuncs[MAXUSERFUNCS]; +/* Lots of functions are suitable for use as userfuncs to be called in + the event of abnormal termination. These might include: + malloc_print(); + PrintMemfile(); + PrintMPMYDiags(); + Msg_flush(); + MPMY_abchdir(); (with MPMY_abchdir_arg set beforehand) + MPMY_SystemAbort(); + MPMY_SystemExit(); (with MPMY_exit_arg set beforehand) + MPMY_Abannounce(); + + They are called in the reverse chronological order, so later functions + might 'override' earlier ones. This isn't perfect, but it's better than + the monolithic handler we had before. +*/ + +void MPMY_OnAbnormal(Abhndlr hndlr){ + if(nuserfuncs < MAXUSERFUNCS) + userfuncs[nuserfuncs++] = hndlr; +} + +int MPMY_Abnormal_signum; +int MPMY_stop_abnormal_processing; +void MPMY_RaiseAbnormal(int sig){ + int i; + + MPMY_Abnormal_signum = sig; + MPMY_stop_abnormal_processing = 0; + /* Just cycle through the 'user' functions. */ + for(i=nuserfuncs-1; i>=0 && !MPMY_stop_abnormal_processing; i--){ + (*userfuncs[i])(); + } + MPMY_Abnormal_signum = 0; +} +#endif + +#ifndef HAVE_SYSTEM_ABORT +void MPMY_SystemAbort(void){ + /* This should be unnecessary, since we didn't trap SIGABRT above. */ + signal(SIGABRT, SIG_DFL); + abort(); +} +#endif + +#ifndef HAVE_SYSTEM_EXIT +int MPMY_exit_arg = 0; +void MPMY_SystemExit(void){ + exit(MPMY_exit_arg); +} +#endif + +#ifndef HAVE_MPMY_CHDIR +/* This is pretty generic, but if the system can't even link against + mkdir and chdir, then it will be necessary to override this with + a noop in the PAROS-specific file. */ +#include +#ifndef __INTEL_SSD__ /* Intel's headers aren't safe for multiple inclusion! */ +#include +#endif +#include +char MPMY_Abchdir_arg[128]; + +/* Suitable for use as a userfunc */ +void MPMY_Abchdir(void){ + if( strlen(MPMY_Abchdir_arg) ){ + errno=0; + if( mkdir(MPMY_Abchdir_arg, 0777) && errno != EEXIST ){ + Msg_do("Can't mkdir(\"%s\"): %d\n", MPMY_Abchdir_arg, errno); + } + errno = 0; + if( chdir(MPMY_Abchdir_arg) ){ + Msg_do("Can't chdir(\"%s\"): %d\n", MPMY_Abchdir_arg, errno); + }else{ + Msg_do("New directory: \"%s\"\n", MPMY_Abchdir_arg); + } + } +} +#endif + +#ifndef HAVE_ABANNOUNCE +void MPMY_Abannounce(void){ + static int announced; + /* Don't repeat yourself! */ + if (!announced){ + Msg_do("MPMY_ABNORMAL_SIGNUM: %d\n", MPMY_Abnormal_signum); + MPMY_Diagnostic(Msg_do); + } + Msg_flush(); + announced = 1; +} +#endif + +#ifndef HAVE_PRINTMPMY_DIAGS +void PrintMPMYDiags(void){ + MPMY_Diagnostic(Msg_do); +} +#endif + +#ifndef HAVE_MPMY_TIMEOUT +/* Aieeee!!! Some systems can link alarm, but when the execute it, + they die (cm5). Other systems can't even link it (sunmos, ap1000). + Others will crash mysteriously if they use alarm (lsv). This isn't + really a PAROS thing, and it's not really ARCH either. Aargh. */ +#ifdef CANT_USE_ALARM +#define HAVE_MPMY_TIMEOUT +void +MPMY_TimeoutSet(int n){ + SinglWarning("Can't use alarm(). Timeout not set!\n"); +} + +void +MPMY_TimeoutReset(int n){ + return; +} + +void +MPMY_TimeoutCancel(void){ + return; +} + +#else /* CANT_USE_ALARM */ + +static int nt; +static void +alrm_hndlr(int sig) +{ + /* Should this be Shout followed by MPMY_RaiseAbnormal()?? */ + Error("Exceeded timeout (%d sec)\n", nt); +} + +void +MPMY_TimeoutSet(int n) +{ + void (*prev_sig)(int); + prev_sig = signal(SIGALRM, alrm_hndlr); + if( prev_sig == SIG_DFL || prev_sig == NULL || prev_sig == SIG_IGN ){ + singlPrintf("Setting timeout to %d seconds.\n", n); + alarm(n); + nt = n; + }else{ + singlPrintf("There is already a handler for SIGALRM at %p\n", + prev_sig); + singlPrintf("NOT setting timeout!\n"); + signal(SIGALRM, prev_sig); + } +} + +void +MPMY_TimeoutReset(int n) +{ + alarm(n); + nt = n; +} + +void +MPMY_TimeoutCancel(void) +{ + alarm(0); + signal(SIGALRM, SIG_DFL); +} +#endif /* CANT_USE_ALARM */ +#endif /* HAVE_MPMY_TIMEOUT */ diff --git a/external/libsdf/libmpmy/mpmy_generic.c b/external/libsdf/libmpmy/mpmy_generic.c new file mode 100644 index 0000000..c3dd30e --- /dev/null +++ b/external/libsdf/libmpmy/mpmy_generic.c @@ -0,0 +1,286 @@ +/* This file is included in most (all?) of the mpmy_PAROS files. + It defines several of the required mpmy functions in terms of a + more primitive set. In some cases, however, there will be a PAROS + specific way to achieve these results defined in the mpmy_PAROS file + When that happens, the mpmy_PAROS file will also + #define HAVE_MPMY_FUNCNAME +so we know that we shouldn't define it here. */ + +/* These are set to the "right" thing on a uniprocessor, where it is + most likely that we will neglect to call MPMY_Init, but where + we really can proceed without any problems. I tried + setting them to -1, but that just led to hard-to-understand + crashes. We really should test occasionally that MPMY_Init has + been called. But I'll leave that for another day... */ +int _MPMY_procnum_ = 0; +int _MPMY_nproc_ = 1; +int _MPMY_procs_per_node_ = 1; +int _MPMY_initialized_ = 0; + +Counter_t MPMYSendCnt; +Counter_t MPMYRecvCnt; +Counter_t MPMYDoneCnt; + +#ifndef HAVE_MPMY_FLICK +int MPMY_Flick(void){return MPMY_SUCCESS;} +#endif /* HAVE_MPMY_FLICK */ + +#ifndef HAVE_MPMY_IRSEND +int MPMY_Irsend(const void *buf, int cnt, int dest, int tag, MPMY_Comm_request *req){ + return MPMY_Isend(buf, cnt, dest, tag, req); +} +#endif /* HAVE_MPMY_IRSEND */ + +#ifndef HAVE_MPMY_SHIFT +/* An implementation of shift that just uses mpmy_isend/irecv */ +/* Some systems will have a better option, but this should always work. */ + +#define SHIFT_TAG 0x1492 +/* Because NX can't distinguish different sources when reading */ +/* messages, we help it out by adding processor info to the tag. */ +/* Is this really necessary for the "generic" implementation? */ +int MPMY_Shift(int proc, void *recvbuf, int recvcnt, + const void *sendbuf, int sendcnt, MPMY_Status *stat){ + MPMY_Comm_request inreq, outreq; + Msgf(("Starting MPMY_Shift(proc=%d, recvcnt=%d, sendcnt=%d:\n", + proc, recvcnt, sendcnt)); + if (proc > _MPMY_procnum_) { + MPMY_Irecv(recvbuf, recvcnt, proc, SHIFT_TAG+proc, &inreq); + Msgf(("Irecv posted\n")); + MPMY_Wait(inreq, stat); + Msgf(("Irecv done\n")); + MPMY_Isend(sendbuf, sendcnt, proc, SHIFT_TAG+MPMY_Procnum(), &outreq); + Msgf(("Isend posted\n")); + MPMY_Wait(outreq, NULL); + Msgf(("Isend done\n")); + } else { + MPMY_Isend(sendbuf, sendcnt, proc, SHIFT_TAG+MPMY_Procnum(), &outreq); + Msgf(("Isend posted\n")); + MPMY_Wait(outreq, NULL); + Msgf(("Isend done\n")); + MPMY_Irecv(recvbuf, recvcnt, proc, SHIFT_TAG+proc, &inreq); + Msgf(("Irecv posted\n")); + MPMY_Wait(inreq, stat); + Msgf(("Irecv done\n")); + } + + Msgf(("Finished MPMY_Shift\n")); + return MPMY_SUCCESS; +} +#endif /* HAVE_MPMY_SHIFT */ + +/* + This could be smarter. In particular, it could recover gracefully + from malloc failing to deliver. + */ +#ifndef HAVE_MPMY_SHIFT_OVERLAP +#include "Malloc.h" +#include + +int MPMY_Shift_overlap(int proc, void *recvbuf, int recvcnt, + const void *sendbuf, int sendcnt, MPMY_Status *stat){ + void *tmp = Malloc(sendcnt); + int ret; + + if( tmp == NULL && sendcnt>0 ) + return MPMY_FAILED; + memcpy(tmp, sendbuf, sendcnt); + ret = MPMY_Shift(proc, recvbuf, recvcnt, tmp, sendcnt, stat); + Free(tmp); + return ret; +} +#endif /* HAVE_MPMY_SHIFT_OVERLAP */ + +#ifndef HAVE_MPMY_SYNC +/* Implementation of MPMY_Sync in terms of the 'combine' functions. */ +/* Some systems might provide a more useful interface. */ + +int MPMY_Sync(void){ + int junk=0; + + /* I'm sure this is overkill! */ + return MPMY_Combine(&junk, &junk, 1, MPMY_INT, MPMY_BOR); +} +#endif + +#ifndef HAVE_MPMY_FINALIZE +/* Any system specific stuff gets handled by a system-specific finalizer */ +int MPMY_Finalize(void){ + return MPMY_SUCCESS; +} +#endif + +#ifndef HAVE_MPMY_WAIT +/* An implementation of mpmy_wait that just busy-waits on MPMY_Test. */ +/* Some systems will have a better option, but this should always work. */ + +int MPMY_Wait(MPMY_Comm_request req, MPMY_Status *stat){ + /* Should we do a 'MPMY_Flick'' ? */ + int flag = 0; + int ret; + + do{ + MPMY_Flick(); + ret = MPMY_Test(req, &flag, stat); + }while( ret == MPMY_SUCCESS && flag==0 ); + return ret; +} +#endif /* HAVE_MPMY_WAIT */ + +#ifndef HAVE_MPMY_WAIT2 +int MPMY_Wait2(MPMY_Comm_request req1, MPMY_Status *stat1, + MPMY_Comm_request req2, MPMY_Status *stat2){ + /* Should we do a 'MPMY_Flick'' ? */ + int done1, done2; + int ret; + + done1 = done2 = 0; + do{ /* loop until at least one is finished */ + MPMY_Flick(); + ret = MPMY_Test(req1, &done1, stat1); + if( ret != MPMY_SUCCESS ) + return ret; + ret = MPMY_Test(req2, &done2, stat2); + if( ret != MPMY_SUCCESS ) + return ret; + }while( done1 == 0 && done2 == 0 ); + + /* Now there's only one left, so we can call MPMY_Wait */ + if( !done1 ){ + ret = MPMY_Wait(req1, stat1); + if( ret != MPMY_SUCCESS ) + return ret; + } + if( !done2 ){ + ret = MPMY_Wait(req2, stat2); + if( ret != MPMY_SUCCESS ) + return ret; + } + return MPMY_SUCCESS; +} +#endif + + +#ifndef HAVE_MPMY_DIAGNOSTIC +void MPMY_Diagnostic(int (*printflike)(const char *, ...)){ + (*printflike)("No Diagnostic info for this MPMY\n"); +} +#endif + +#ifndef HAVE_MPMY_INITIALIZED +int MPMY_Initialized(void){ + return _MPMY_initialized_; +} +#endif + +#ifndef HAVE_MPMY_PHYSNODE +const char *MPMY_Physnode(void){ + return "?"; +} +#endif + +#ifndef HAVE_MPMY_TIMERS +/* This is a nightmare! Timers should really be ARCH dependent */ +/* but because of the CM5's special closeness to ARCH=sun4, they */ +/* are PAROS dependent, instead. That means that we would otherwise */ +/* repeat this code block in lots of mpmy_PAROS.c files */ +#ifdef _AIX +/* No longer working?? Nov 3 1994 + # include "timers_readrtc.c" */ +#if !defined(USE_HWCLOCK) && !defined(USE_GETTIME) +#include "timers_posix.c" +#endif +/* it's not inconceivable to compile sequentially for the intels */ +/* However, we won't necessarily be linking against, e.g, hwclock +#elif defined(__INTEL_SSD__) +# include "timers_nx.c" +*/ +#else +#if !defined(USE_HWCLOCK) && !defined(USE_GETTIME) +# include "timers_posix.c" +#endif +#endif /* _AIX */ +#endif /* HAVE_MPMY_TIMERS */ + +static time_t job_start; +static time_t job_end; +static time_t checkpoint_last; +static time_t checkpoint_next; +static time_t checkpoint_interval; +static int checkpoint_setup; + +void +MPMY_CheckpointSetup(int job_seconds, int interval_seconds, int step_seconds) +{ + if (MPMY_Procnum() == 0) { + job_start = time(NULL); + if (job_seconds == -1) job_end = -1; + else job_end = job_start + job_seconds - step_seconds; + checkpoint_interval = interval_seconds - step_seconds; + checkpoint_last = job_start; + checkpoint_next = job_start + checkpoint_interval; + Msg_do("Checkpoint Setup interval %ld start %ld next %ld end %ld\n", + checkpoint_interval, job_start, checkpoint_next, job_end); + } + checkpoint_setup = 1; +} + +int +MPMY_CheckpointDue(int next_output_seconds) +{ + time_t t; + int retval = 0; + + if (MPMY_Procnum() == 0) { + t = time(NULL); + if (t >= checkpoint_next) retval = 1; + if (next_output_seconds < checkpoint_interval/4) { + Msg_do("Postponing checkpoint since output expected in %d seconds\n", + next_output_seconds); + retval = 0; + } + if (job_end > 0 && t >= job_end) retval = 1; + } + if (retval) Msg_do("Checkpoint Due\n"); + MPMY_Bcast(&retval, 1, MPMY_INT, 0); + return retval; +} + +void +MPMY_CheckpointFinished(void) +{ + time_t t; + + if (MPMY_Procnum() == 0) { + t = time(NULL); + checkpoint_last = t; + checkpoint_next = t + checkpoint_interval; + if (job_end > 0 && checkpoint_next > job_end) checkpoint_next = job_end; + Msg_do("next checkpoint %ld (%ld from now)\n", checkpoint_next, checkpoint_next-t); + } +} + +int +MPMY_JobDone(void) +{ + time_t t; + int retval = 0; + + if (MPMY_Procnum() == 0) { + t = time(NULL); + if (job_end > 0 && t >= job_end) { + retval = 1; + Msg_do("Job Done\n"); + } + } + MPMY_Bcast(&retval, 1, MPMY_INT, 0); + return retval; +} + +#ifndef HAVE_MPMY_JOBREMAINING +int +MPMY_JobRemaining(void) +{ + return -1; +} +#endif diff --git a/external/libsdf/libmpmy/mpmy_io.c b/external/libsdf/libmpmy/mpmy_io.c new file mode 100644 index 0000000..f7dd2ef --- /dev/null +++ b/external/libsdf/libmpmy/mpmy_io.c @@ -0,0 +1,525 @@ + +/* The default I/O model here is that only proc 0 can read/write etc. */ +/* There are two I/O modes for read and write, MULTI and SINGL */ +/* All other functions do not have an I/O mode associated with them */ +/* All calls must be loosely synchronous. There is a single file pointer */ +/* This model works on all machines, but it may not be the most efficient */ + +/* MPMY_NFILE extends the mpmy_io model to include multiple file segments */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "Assert.h" +#include "protos.h" +#include "mpmy.h" +#include "mpmy_io.h" +#include "Msgs.h" +#include "Malloc.h" +#include "iozero.h" + +#ifndef EINVAL +/* just in case... */ +#define EINVAL 0 +#endif + +#define NFILES 4096 +static struct _File{ + int fd; + int iomode; + int iotype; +} _files[NFILES]; + +#define DEFAULT_PERMS 0644 +static int do_nfileio; + +int +MPMY_Nfileio(int val){ + int oldval = do_nfileio; + do_nfileio = val; + return oldval; +} + +int +MPMY_SetIOMode(MPMYFile *Fp, int iomode) +{ + struct _File *fp = (struct _File *)Fp; + + fp->iomode = iomode; + return 0; +} + +MPMYFile * +MPMY_Fopen(const char *path, int mpmy_flags) +{ + int fd; + int flags = 0; + int iomode = MPMY_SINGL; + int iotype = 0; + + Msgf(("Fopen %s\n", path)); + if (mpmy_flags & MPMY_RDONLY) flags |= O_RDONLY; + if (mpmy_flags & MPMY_WRONLY) flags |= O_WRONLY; + if (mpmy_flags & MPMY_RDWR) flags |= O_RDWR; + if (mpmy_flags & MPMY_APPEND) flags |= O_APPEND; + if (mpmy_flags & MPMY_TRUNC) flags |= O_TRUNC; + if (mpmy_flags & MPMY_CREAT) flags |= O_CREAT; + + if (mpmy_flags & MPMY_MULTI) iomode = MPMY_MULTI; + if (mpmy_flags & MPMY_SINGL) iomode = MPMY_SINGL; + + /* This is a sub-mode which can work with either of the above */ + if (mpmy_flags & MPMY_NFILE) iotype = MPMY_NFILE; + + if (mpmy_flags & MPMY_INDEPENDENT) { + iotype = MPMY_INDEPENDENT; + iomode = MPMY_MULTI; + } + + /* We need an external control for nfile mode */ + if (do_nfileio) iotype = MPMY_NFILE; + + if (iotype == MPMY_NFILE) { + char real_path[256]; + sprintf(real_path, "%s.p%03d", path, MPMY_Procnum()); + fd = open(real_path, flags, DEFAULT_PERMS); + } else if (iotype == MPMY_INDEPENDENT) { + fd = open(path, flags, DEFAULT_PERMS); + } else { + if( strcmp(path, "-") != 0 ){ + fd = open0(path, flags, DEFAULT_PERMS); + }else{ + /* Be very afraid. */ + /* We made MPMY_RDONLY zero because O_RDONLY==0. But why + did 'they' do that?! */ + if ( (mpmy_flags & MPMY_RDWR) ) + Error("Can't open '-' RDWR\n"); +#if MPMY_RDONLY != 0 + # error Aargh. +#endif + if(mpmy_flags & MPMY_WRONLY ) + fd = 1; /* stdout */ + else /* we can't test for MPMY_RDONLY! */ + fd = 0; /* stdout */ + } + } + + if (fd >= NFILES) Error("fd too large (%d)\n", fd); + if(fd >= 0){ + _files[fd].iomode = iomode; + _files[fd].iotype = iotype; + _files[fd].fd = fd; + Msgf(("Fopen returns %d, iomode=%d, flags=0x%x\n", fd, iomode, flags)); + return &(_files[fd]); + }else{ + Msgf(("Fopen fails, errno=%d\n", errno)); + return NULL; + } +} + +int +MPMY_Fclose(MPMYFile *Fp) +{ + struct _File *fp = (struct _File *)Fp; + int ret; + + if( fp == NULL ){ + errno = EINVAL; + return -1; + } + if (fp->iotype & MPMY_NFILE || fp->iotype & MPMY_INDEPENDENT) { + ret = close(fp->fd); + } else { + ret = close0(fp->fd); + } + fp->fd = -1; + Msgf(("Close returns %d\n", ret)); + return ret; +} + +int +MPMY_Mkdir(const char *path, int mode){ + return mkdir0(path, mode); +} + +size_t +MPMY_Fread(void *ptr, size_t size, size_t nitems, MPMYFile *Fp) +{ + struct _File *fp = (struct _File *)Fp; + ssize_t ret = -1; + + Msgf(("Fread(ptr=%p, size=%ld, nitems=%ld, FILE=%p)\n", + ptr, size, nitems, Fp)); + Msg_flush(); + if( fp == NULL ){ + errno = EINVAL; + return -1; + } + + switch (fp->iomode) { + case MPMY_SINGL: + ret = read0(fp->fd, ptr, (long)size*nitems); + break; + case MPMY_MULTI: + if (fp->iotype & MPMY_NFILE || fp->iotype & MPMY_INDEPENDENT) + ret = read(fp->fd, ptr, (long)size*nitems); + else + ret = read0_multi(fp->fd, ptr, (long)size*nitems); + break; + default: + ret = -1; + break; + } + + Msgf(("Fread returns %ld.\n", ret)); + if( ret < 0 ){ + Warning("MPMY_Fread: read returns %ld, errno=%d\n", ret, errno); + return -1; + } + if (ret % size) + Shout("MPMY_Fread has a problem, ret=%ld, size=%ld\n", ret, size); + return ret/size; +} + +size_t +MPMY_Fwrite(const void *ptr, size_t size, size_t nitems, MPMYFile *Fp) +{ + struct _File *fp = (struct _File *)Fp; + ssize_t ret = -1; + + if( fp == NULL ){ + errno = EINVAL; + return -1; + } + + switch (fp->iomode) { + case MPMY_SINGL: + ret = write0(fp->fd, ptr, size*nitems); + break; + case MPMY_MULTI: + if (fp->iotype & MPMY_NFILE || fp->iotype & MPMY_INDEPENDENT) + ret = write(fp->fd, ptr, size*nitems); + else + ret = write0_multi(fp->fd, ptr, size*nitems); + break; + default: + ret = -1; + Shout("Bad iomode in Fwrite\n"); + } + + Msgf(("Fwrite returns %ld.\n", ret)); + if( ret < 0 ){ + Warning("MPMY_Fwrite: write returns %ld, errno=%d\n", ret, errno); + return -1; + } + if (ret % size) + Shout("MPMY_Fwrite has a problem: ret=%ld, size=%ld\n", ret, size); + return ret/size; +} + +off_t +MPMY_Fseek(MPMYFile *Fp, off_t offset, int whence) +{ + struct _File *fp = (struct _File *)Fp; + off_t ret; + int real_whence = 0; + + if( fp == NULL ){ + errno = EINVAL; + return -1; + } + + if (whence == MPMY_SEEK_SET) real_whence = SEEK_SET; + if (whence == MPMY_SEEK_CUR) real_whence = SEEK_CUR; + if (whence == MPMY_SEEK_END) real_whence = SEEK_END; + + if (fp->iotype == MPMY_INDEPENDENT) { + ret = lseek(fp->fd, offset, real_whence); + } else { + ret = lseek0(fp->fd, offset, real_whence); + } + if (ret != -1) ret = 0; + Msgf(("Fseek returns %ld\n", (long)ret)); + return ret; +} + +off_t +MPMY_Ftell(MPMYFile *Fp) +{ + struct _File *fp = (struct _File *)Fp; + off_t ret; + + if( fp == NULL ){ + errno = EINVAL; + return -1; + } + if (fp->iotype == MPMY_INDEPENDENT) { + ret = lseek(fp->fd, 0L, SEEK_CUR); + } else { + ret = tell0(fp->fd); + } + Msgf(("Ftell returns %ld\n", (long)ret)); + return ret; +} + +off_t +MPMY_Flen(MPMYFile *Fp) +{ + struct _File *fp = (struct _File *)Fp; + off_t ret; + + if( fp == NULL ){ + errno = EINVAL; + return -1; + } + if (fp->iotype & MPMY_NFILE) { + ret = flen(fp->fd); + Msgf(("flen segment %ld\n", (long)ret)); + if (sizeof(ret) != sizeof(long)) { + Error("Bad types in MPMY_Flen\n"); + } + MPMY_Combine(&ret, &ret, 1, MPMY_LONG, MPMY_SUM); + } else if (fp->iotype == MPMY_INDEPENDENT) { + ret = flen(fp->fd); + } else { + ret = flen0(fp->fd); + } + Msgf(("Flen returns %ld\n", (long)ret)); + return ret; +} + +#define MAXREQ 4 + +static int +fseekrd_nfile(int fd, off_t offset, int whence, void *buf, int reclen, + int nrecs) +{ + off_t offend; + void *tmpbuf = 0; /* realloc null first time */ + int i; + off_t nread; + long size; + struct { + off_t offset; + off_t flen; + off_t start; + long reclen; + long nrecs; + } parbuf, *allbuf; + MPMY_Status stat; + MPMY_Comm_request req[MAXREQ]; /* should be dynamic? */ + int nreq = 0; + int procnum = MPMY_Procnum(); + off_t my_start, my_size, my_end; + int nproc = MPMY_Nproc(); + + if (whence != MPMY_SEEK_SET) + Error("Fseekrd Nfiles must use SEEK_SET\n"); + + parbuf.offset = offset; + parbuf.reclen = reclen; + parbuf.nrecs = nrecs; + parbuf.flen = flen(fd); + + allbuf = Malloc(sizeof(parbuf)*nproc); + + MPMY_AllGather(&parbuf, sizeof(parbuf)/sizeof(long), MPMY_LONG, allbuf); + + my_start = 0; + for (i = 0; i < nproc; i++) { + allbuf[i].start = my_start; + my_start += allbuf[i].flen; + } + offend = offset+nrecs*reclen; + my_start = allbuf[procnum].start; + my_size = allbuf[procnum].flen; + my_end = my_start+my_size; + + Msgf(("reclen %d\n", reclen)); + Msgf(("offset %ld\n", offset)); + Msgf(("nrecs*reclen %d\n", nrecs*reclen)); + Msgf(("my_start %ld\n", my_start)); + Msgf(("my_size %ld\n", my_size)); + Msgf(("my_end %ld\n", my_end)); + + /* post Irecvs for my data */ + for (i = 0; i < nproc; i++) { + if (allbuf[i].start<=offset && offset reclen*nrecs) size = reclen*nrecs; + Msgf(("irecv %ld from %d\n", size, i)); + if (nreq >= MAXREQ) Error("Too many Irecvs in fseekrd\n"); + MPMY_Irecv(buf, size, i, MPMY_IOTAG, &req[nreq]); + ++nreq; + } else if (offset <= allbuf[i].start && offend > allbuf[i].start+allbuf[i].flen) { + size = allbuf[i].flen; + Msgf(("irecv %ld from %d\n", size, i)); + if (nreq >= MAXREQ) Error("Too many Irecvs in fseekrd\n"); + MPMY_Irecv((char *)buf+allbuf[i-1].start+allbuf[i-1].flen-offset, + size, i, MPMY_IOTAG+2, &req[nreq]); + ++nreq; + } else if (allbuf[i].start= MAXREQ) Error("Too many Irecvs in fseekrd\n"); + MPMY_Irecv((char *)buf+reclen*nrecs-size, size, i, + MPMY_IOTAG+1, &req[nreq]); + ++nreq; + } + } + + for (i = 0; i < nproc; i++) { + offset = allbuf[i].offset; + reclen = allbuf[i].reclen; + nrecs = allbuf[i].nrecs; + offend = offset+reclen*nrecs; + + if (my_start <= offset && offset < my_end) { + size = my_end-offset; + if (size > reclen*nrecs) size = reclen*nrecs; + lseek(fd, offset-my_start, SEEK_SET); + tmpbuf = Realloc(tmpbuf, size); + nread = read(fd, tmpbuf, size); + Msgf(("send %ld to %d\n", size, i)); + MPMY_send(tmpbuf, size, i, MPMY_IOTAG); + } else if (offset <= my_start && offend > my_end) { + size = my_end-my_start; + lseek(fd, 0, SEEK_SET); + tmpbuf = Realloc(tmpbuf, size); + nread = read(fd, tmpbuf, size); + Msgf(("send %ld to %d\n", size, i)); + MPMY_send(tmpbuf, size, i, MPMY_IOTAG+2); + } else if (my_start < offend && offend <= my_end) { + size = offend-my_start; + lseek(fd, 0, SEEK_SET); + tmpbuf = Realloc(tmpbuf, size); + nread = read(fd, tmpbuf, size); + Msgf(("send %ld to %d\n", size, i)); + MPMY_send(tmpbuf, size, i, MPMY_IOTAG+1); + } + } + Free(tmpbuf); + Free(allbuf); + nread = 0; + Msg_flush(); +#if 0 + for (i = 0; i < nreq; i++) { + MPMY_Wait(req[i], &stat); + Msgf(("Got %d from %d\n", stat.count, stat.src)); + nread += stat.count; + } +#else + i = 0; + while( nreq ){ + int done; + /* Msgf(("Testing req[%d] = %p\n", i, req[i])); */ + MPMY_Test(req[i], &done, &stat); + if( done ){ + Msgf(("Got %d from %d\n", stat.count, stat.src)); + nread += stat.count; + Msgf(("Moving req[%d] = req[%d] = ", i, nreq-1)); + req[i] = req[--nreq]; + Msgf(("%p\n", req[i])); + }else{ + /* Msgf(("Req[%d] not done yet\n", i)); */ + i++; + } + assert(i <= nreq ); + if( i == nreq ) + i = 0; + } +#endif + Msgf(("fseekrd_nfile returning = %ld\n", nread/reclen)); + return nread/reclen; +} + +/* This should be called from fseekrd0 instead of replicating code */ + +static int +fseekrd(int fd, off_t offset, int whence, void *buf, int reclen, + int nrecs) +{ + int doseek; + int real_whence; + off_t nread = 0; + off_t len; + + if( whence == SEEK_CUR ){ + doseek = (offset != 0); + }else if( whence == SEEK_SET ){ + /* don't worry about errors. If ftell returns -1, */ + /* doseek will be turned on, and the fseek below will */ + /* (probably) fail */ + doseek = (lseek(fd, 0L, SEEK_CUR) != offset); + }else{ + doseek = 1; + } + + if( doseek ){ + switch(whence){ + case MPMY_SEEK_SET: + real_whence = SEEK_SET; + break; + case MPMY_SEEK_CUR: + real_whence = SEEK_CUR; + break; + case MPMY_SEEK_END: + real_whence = SEEK_END; + break; + default: + Shout("Illegal value of whence (%d) in fseekrd\n", whence); + return -1; + } + if (lseek(fd, offset, real_whence) == -1) { + Error("fseekrd: lseek(%d, %ld, %d) failed, errno=%d\n", + fd, (long)offset, whence, errno); + return -1; + } + } + len = 0; + while (len < reclen*nrecs) { + nread = read(fd, (char *)buf+len, reclen*nrecs-len); + if (nread == -1) { + Error("fseekrd: read(%d, %ld) failed, errno=%d\n", + fd, (long)reclen*nrecs-len, errno); + return -1; + } else if (nread == 0) { + Error("fseekrd: read(%d, %ld) got EOF\n", + fd, (long)reclen*nrecs-len); + return -1; + } else { + printf("%d fseekrd(%d): got %ld\n", fd, MPMY_Procnum(), (long)nread); + len += nread; + } + } + if (len != reclen*nrecs) Error("fseekrd: Wrong amount of data\n"); + return nread/reclen; +} + +size_t +MPMY_Fseekrd(MPMYFile *Fp, off_t offset, int whence, void *buf, size_t reclen, + size_t nrecs) +{ + struct _File *fp = (struct _File *)Fp; + + if( fp == NULL ){ + errno = EINVAL; + return -1; + } + if (fp->iotype & MPMY_NFILE) { + nrecs = fseekrd_nfile(fp->fd, offset, whence, buf, reclen, nrecs); + } else if (fp->iotype == MPMY_INDEPENDENT) { + nrecs = fseekrd(fp->fd, offset, whence, buf, reclen, nrecs); + } else { + nrecs = fseekrd0(fp->fd, offset, whence, buf, reclen, nrecs); + } + return nrecs; +} + +#include "iozero.c" +#include "io_generic.c" diff --git a/external/libsdf/libmpmy/mpmy_mpi.c b/external/libsdf/libmpmy/mpmy_mpi.c new file mode 100644 index 0000000..6218dd8 --- /dev/null +++ b/external/libsdf/libmpmy/mpmy_mpi.c @@ -0,0 +1,399 @@ +#ifdef _SWAMPI +#include +#else +#include +#endif +#include "mpmy_abnormal.h" + +#include "Malloc.h" + +#include "chn.h" +#include "mpmy.h" +#include "Assert.h" +#include "timers.h" +#include "Msgs.h" +#include "error.h" +#include "memfile.h" + +struct comm_s { + MPI_Request hndl; + int inout; +}; + +static Chn commchn; +#define NCOMM 2048 +#define IN 1 +#define OUT 2 + +int MPMY_Isend(const void *buf, int cnt, int dest, int tag, + MPMY_Comm_request *reqp) { + struct comm_s *comm = ChnAlloc(&commchn); + + Msgf(("Isend: buf=%p, cnt=%d, dest=%d, tag=%d\n", + buf, cnt, dest, tag)); + if (MPI_Isend((void *)buf, cnt, MPI_BYTE, dest, tag, MPI_COMM_WORLD, + &comm->hndl) != MPI_SUCCESS) + Error("MPMY_Isend MPI_Isend failed\n"); + comm->inout = OUT; + Msgf(("Isend: hndl=%ld\n", (long) comm->hndl)); + *reqp = comm; + return MPMY_SUCCESS; +} + +#if 0 +#define HAVE_MPMY_IRSEND +int MPMY_Irsend(const void *buf, int cnt, int dest, int tag, + MPMY_Comm_request *reqp) { + struct comm_s *comm = ChnAlloc(&commchn); + + Msgf(("Irsend: buf=%p, dest=%d, tag=%d\n", + buf, dest, tag)); + if (MPI_Irsend(buf, cnt, MPI_BYTE, dest, tag, MPI_COMM_WORLD, + &comm->hndl) != MPI_SUCCESS) + Error("MPMY_Isend MPI_Irsend failed\n"); + comm->inout = OUT; + Msgf(("Irsend: hndl=%d\n", (int) comm->hndl)); + *reqp = comm; + return MPMY_SUCCESS; +} +#endif /* 0 */ + +int MPMY_Irecv(void *buf, int cnt, int src, int tag, MPMY_Comm_request *reqp) { + struct comm_s *comm = ChnAlloc(&commchn); + + if (tag == MPMY_TAG_ANY) tag = MPI_ANY_TAG; + if (src == MPMY_SOURCE_ANY) { + src = MPI_ANY_SOURCE; + } else if (src < 0 || src >= MPMY_Nproc()) { + Error("Bad src (%d) in Irecv\n", src); + } + Msgf(("Irecv: buf=%p, src=%d, tag=%d\n", + buf, src, tag)); + if (MPI_Irecv(buf, cnt, MPI_BYTE, src, tag, MPI_COMM_WORLD, + &comm->hndl) != MPI_SUCCESS) + Error("MPMY_Irecv MPI_Irecv failed\n"); + comm->inout = IN; + Msgf(("Irecv: hndl=%ld\n", (long) comm->hndl)); + *reqp = comm; + return MPMY_SUCCESS; +} + +int MPMY_Test(MPMY_Comm_request req, int *flag, MPMY_Status *stat) { + struct comm_s *comm = req; + MPI_Status status; + int cnt; + int ret = 0; + + Msgf(("MPMY_Test hndl=%ld at %p\n", (long) comm->hndl, &comm->hndl)); + if ((ret = MPI_Test(&comm->hndl, flag, &status)) != MPI_SUCCESS) { + Error("MPMY_Test MPI_Test failed (%d), MPI_ERROR %d, hndl=%ld at %p, flag=%p, status=%p\n", + ret, status.MPI_ERROR, (long)comm->hndl, &comm->hndl, flag, &status); + } + Msgf(("Tested (%s), %d\n", + (comm->inout==IN)?"in":"out", *flag)); + if (*flag) { + if(comm->inout == IN) { + MPI_Get_count(&status, MPI_BYTE, &cnt); + Msgf(("Recvd(T) from %d, tag %d, count: %d\n", + status.MPI_SOURCE, status.MPI_TAG, cnt)); + if (stat) { + stat->src = status.MPI_SOURCE; + stat->tag = status.MPI_TAG; + stat->count = cnt; + } + } + ChnFree(&commchn, comm); + } + return MPMY_SUCCESS; +} + +#define HAVE_MPMY_WAIT +int MPMY_Wait(MPMY_Comm_request req, MPMY_Status *stat) { + struct comm_s *comm = req; + MPI_Status status; + int cnt; + + Msgf(("Wait for %ld\n", (long) comm->hndl)); + if (MPI_Wait(&comm->hndl, &status) != MPI_SUCCESS) + Error("MPMY_Wait MPI_Wait failed\n"); + Msgf(("Waited for (%s), deallocated\n", + (comm->inout==IN)?"in":"out")); + if(comm->inout == IN) { + MPI_Get_count(&status, MPI_BYTE, &cnt); + Msgf(("Recvd(W) from %d, tag %d, count: %d\n", + status.MPI_SOURCE, status.MPI_TAG, cnt)); + if (stat) { + stat->src = status.MPI_SOURCE; + stat->tag = status.MPI_TAG; + stat->count = cnt; + } + } + ChnFree(&commchn, comm); + return MPMY_SUCCESS; +} + +#define HAVE_MPMY_SHIFT +#define SHIFT_TAG 0x1492 +int MPMY_Shift(int proc, void *recvbuf, int recvcnt, + const void *sendbuf, int sendcnt, MPMY_Status *stat) { + MPI_Status status; + int count; + + Msgf(("Starting MPMY_Shift(proc=%d, recvcnt=%d, sendcnt=%d, recvbuf=%p, sendbuf=%p\n", + proc, recvcnt, sendcnt, recvbuf, sendbuf)); + + if (MPI_Sendrecv((void *)sendbuf, sendcnt, MPI_BYTE, proc, SHIFT_TAG, + recvbuf, recvcnt, MPI_BYTE, proc, SHIFT_TAG, + MPI_COMM_WORLD, &status) != MPI_SUCCESS) + Error("MPMY_Shift MPI_Sendrecv failed\n"); + MPI_Get_count(&status, MPI_BYTE, &count); + Msgf(("MPMY_Shift done, received=%d\n", count)); + if (stat) { + stat->count = count; + stat->src = status.MPI_SOURCE; + stat->tag = status.MPI_TAG; + } + return MPMY_SUCCESS; +} + +int +Native_MPMY_Alltoall(void *sendbuf, int sendcount, MPMY_Datatype sendtype, + void *recvbuf, int recvcount, MPMY_Datatype recvtype) +{ + MPI_Datatype st, rt; + + switch (sendtype){ + case MPMY_FLOAT: + st = MPI_FLOAT; + break; + case MPMY_DOUBLE: + st = MPI_DOUBLE; + break; + case MPMY_INT: + st = MPI_INT; + break; + case MPMY_CHAR: + st = MPI_CHAR; + break; + default: + Error("No type match in alltoall\n"); + } + switch (recvtype){ + case MPMY_FLOAT: + rt = MPI_FLOAT; + break; + case MPMY_DOUBLE: + rt = MPI_DOUBLE; + break; + case MPMY_INT: + rt = MPI_INT; + break; + case MPMY_CHAR: + rt = MPI_CHAR; + break; + default: + Error("No type match in alltoall\n"); + } + MPI_Alltoall(sendbuf, sendcount, st, + recvbuf, recvcount, rt, MPI_COMM_WORLD); + return MPMY_SUCCESS; +} + +int +Native_MPMY_Alltoallv(void *sendbuf, int *sendcounts, int *sendoffsets, MPMY_Datatype sendtype, + void *recvbuf, int *recvcounts, int *recvoffsets, MPMY_Datatype recvtype) +{ + MPI_Datatype st, rt; + + switch (sendtype){ + case MPMY_FLOAT: + st = MPI_FLOAT; + break; + case MPMY_DOUBLE: + st = MPI_DOUBLE; + break; + case MPMY_INT: + st = MPI_INT; + break; + case MPMY_CHAR: + st = MPI_CHAR; + break; + case MPMY_SHORT: + st = MPI_SHORT; + break; + case MPMY_LONG: + st = MPI_LONG; + break; + default: + Error("No type match in alltoallv\n"); + } + switch (recvtype){ + case MPMY_FLOAT: + rt = MPI_FLOAT; + break; + case MPMY_DOUBLE: + rt = MPI_DOUBLE; + break; + case MPMY_INT: + rt = MPI_INT; + break; + case MPMY_CHAR: + rt = MPI_CHAR; + break; + case MPMY_SHORT: + rt = MPI_SHORT; + break; + case MPMY_LONG: + rt = MPI_LONG; + break; + default: + Error("No type match in alltoallv\n"); + } + MPI_Alltoallv(sendbuf, sendcounts, sendoffsets, st, + recvbuf, recvcounts, recvoffsets, rt, MPI_COMM_WORLD); + return MPMY_SUCCESS; +} + +int +Native_MPMY_Allgather(void *sendbuf, int sendcount, MPMY_Datatype type, void *recvbuf) +{ + MPI_Datatype st, rt; + int recvcount = sendcount; + + switch (type){ + case MPMY_FLOAT: + st = MPI_FLOAT; + break; + case MPMY_DOUBLE: + st = MPI_DOUBLE; + break; + case MPMY_INT: + st = MPI_INT; + break; + case MPMY_CHAR: + st = MPI_CHAR; + break; + case MPMY_SHORT: + st = MPI_SHORT; + break; + case MPMY_LONG: + st = MPI_LONG; + break; + default: + Error("No type match in allgather\n"); + } + rt = st; + MPI_Allgather(sendbuf, sendcount, st, + recvbuf, recvcount, rt, MPI_COMM_WORLD); + return MPMY_SUCCESS; +} + +int +Native_MPMY_Allgatherv(void *sendbuf, int sendcount, MPMY_Datatype type, void *recvbuf, + int *rcounts, int *roffsets) +{ + MPI_Datatype st, rt; + + switch (type){ + case MPMY_FLOAT: + st = MPI_FLOAT; + break; + case MPMY_DOUBLE: + st = MPI_DOUBLE; + break; + case MPMY_INT: + st = MPI_INT; + break; + case MPMY_CHAR: + st = MPI_CHAR; + break; + case MPMY_SHORT: + st = MPI_SHORT; + break; + case MPMY_LONG: + st = MPI_LONG; + break; + default: + Error("No type match in allgather\n"); + } + rt = st; + MPI_Allgatherv(sendbuf, sendcount, st, + recvbuf, rcounts, roffsets, rt, MPI_COMM_WORLD); + return MPMY_SUCCESS; +} + + +#define HAVE_MPMY_SYNC +int MPMY_Sync(void) { + MPI_Barrier(MPI_COMM_WORLD); + return MPMY_SUCCESS; +} + +int MPMY_Init(int *argcp, char ***argvp) { + ChnInit(&commchn, sizeof(struct comm_s), NCOMM, Realloc_f); + ChnMoreMem(&commchn); /* alloc now to prevent heap fragmentation later */ + if (MPI_Init(argcp, argvp) != MPI_SUCCESS) + Error("MPMY_Init MPI_Init failed\n"); + if (MPI_Comm_size(MPI_COMM_WORLD, &_MPMY_nproc_) != MPI_SUCCESS) + Error("MPMY_Init MPI_Comm_size failed\n"); + if (MPI_Comm_rank(MPI_COMM_WORLD, &_MPMY_procnum_) != MPI_SUCCESS) + Error("MPMY_Init MPI_Comm_rank failed\n"); +#ifdef PROCS_PER_NODE + _MPMY_procs_per_node_ = PROCS_PER_NODE; +#else + _MPMY_procs_per_node_ = 1; +#endif + _MPMY_setup_absigs(); + MPMY_OnAbnormal(MPMY_SystemAbort); + MPMY_OnAbnormal(MPMY_Abannounce); + MPMY_OnAbnormal(PrintMemfile); + _MPMY_initialized_ = 1; + return MPMY_SUCCESS; +} + +#define HAVE_MPMY_FINALIZE +int MPMY_Finalize(void){ + return (MPI_Finalize() == MPI_SUCCESS) ? MPMY_SUCCESS : MPMY_FAILED ; +} + +#define HAVE_MPMY_FLICK +int MPMY_Flick(void){ + return MPMY_SUCCESS; +} + +#define HAVE_MPMY_JOBREMAINING +int +MPMY_JobRemaining(void) +{ + /* returns -1 for failure, or if not a slurm job */ + return -1; +} + + +#ifdef USE_HWCLOCK +#include "timers_hwclock.c" +#endif + +#ifdef USE_GETTIME +#include "timers_gettime.c" +#endif + +#if !defined(USE_HWCLOCK) && !defined(USE_GETTIME) +#define HAVE_MPMY_TIMERS +#include "timers_mpi.c" +#endif + +#if defined(__CM5__) || defined(_AIX) || defined(__AP1000__) +#define CANT_USE_ALARM +#endif +#if defined(__CM5__) || defined(__INTEL_SSD__) +#include "mpmy_pario.c" +#else +#if defined(USE_MPIIO) +#include "mpmy_mpiio.c" +#else +#include "mpmy_io.c" +#endif +#endif +#include "mpmy_abnormal.c" +#include "mpmy_generic.c" diff --git a/external/libsdf/libmpmy/mpmy_mpiio.1.c b/external/libsdf/libmpmy/mpmy_mpiio.1.c new file mode 100644 index 0000000..84b59c6 --- /dev/null +++ b/external/libsdf/libmpmy/mpmy_mpiio.1.c @@ -0,0 +1,292 @@ +/* This file contains the parallel I/O suitable for CMMD and NX. + It wouldn't be hard to add cubix-syntax as well. Are there any + other options? Would they fit in this structure? The only + difference between CMMD and NX is in Fopen, where one + system calls gopen() and the other calls CMMD_set_io_mode(). + We use a pre-processor symbol (__INTEL_SSD__) or (__CM5__) to decide + which one to use. __INTEL_SSD__ is set by the ARCH-specific Makefiles, + while __CM5__ is set by mpmy_cm5.c, which #includes this file. +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef OPEN_MPI +#include +#endif +#include "protos.h" +#include "mpmy.h" +#include "mpmy_io.h" +#include "Msgs.h" + +#ifndef EINVAL +/* just in case... */ +#define EINVAL 0 +#endif + +#define NFILES 4096 + +static struct _File{ + MPI_File fd; + int iomode; +} _files[NFILES]; + +static int files; /* need dynamic storage */ + +static int do_nfileio; + +MPMYFile * +MPMY_Fopen(const char *path, int flags) +{ + MPI_File fd; + MPI_Info info; + int iomode = MPMY_SINGL; /* default */ + int real_flags = MPI_MODE_RDONLY; /* if no flags specified */ + int ret; + + Msgf(("Fopen %s, flags = 0x%x\n", path, flags)); + if (flags & MPMY_RDONLY) real_flags = MPI_MODE_RDONLY; + if (flags & MPMY_WRONLY) real_flags = MPI_MODE_WRONLY; + if (flags & MPMY_RDWR) real_flags = MPI_MODE_RDWR; + if (flags & MPMY_APPEND) real_flags |= MPI_MODE_APPEND; + if (flags & MPMY_TRUNC && ((flags & MPMY_WRONLY) || (flags & MPMY_RDWR))) { + int fd; + if (MPMY_Procnum() == 0) { + fd = open(path, O_RDWR|O_TRUNC, 0644); + if (fd < 0) Msgf(("Fopen fails, errno=%d\n", errno)); + else close(fd); + MPMY_Sync(); + } else { + MPMY_Sync(); + } + } + if (flags & MPMY_CREAT) real_flags |= MPI_MODE_CREATE; + + /* Panasas optimizations */ + real_flags |= MPI_MODE_UNIQUE_OPEN; /* dangerous? */ + MPI_Info_create(&info); + MPI_Info_set(info, "panfs_concurrent_write", "1"); + + /* Should we make sure that only one of them is on?? */ + if (flags & MPMY_MULTI) iomode = MPMY_MULTI; + if (flags & MPMY_SINGL) iomode = MPMY_SINGL; + + if (flags & MPMY_NFILE) Error("MPMY_NFILE not supported\n"); + if (flags & MPMY_IOZERO) Error("MPMY_IOZERO not supported\n"); + if (flags & MPMY_INDEPENDENT) Error("MPMY_INDEPENDENT not supported\n"); + + if (flags & MPMY_SINGL) { + Msgf(("Fopen %s in SINGL mode\n", path)); + } else { + Msgf(("Fopen %s in MULTI mode\n", path)); + } + Msgf(("MPI_File_open %s with flags = 0x%x\n", path, real_flags)); + ret = MPI_File_open(MPI_COMM_WORLD, (char *)path, real_flags, info, &fd); + + if (files >= NFILES) Error("files too large\n"); + if (ret == 0) { + _files[files].iomode = iomode; + _files[files].fd = fd; + Msgf(("Fopen returns fd %p, iomode=%d, flags=0x%x\n", + fd, iomode, flags)); + return &(_files[files++]); + } else { + Msgf(("Fopen fails, errno=%d\n", errno)); + return NULL; + } +} + +int +MPMY_Nfileio(int val){ + int oldval = do_nfileio; + do_nfileio = val; + return oldval; +} + +int +MPMY_Fclose(MPMYFile *Fp) +{ + struct _File *fp = (struct _File *)Fp; + int ret; + + if( fp == NULL ){ + errno = EINVAL; + return -1; + } + Msgf(("Fclose %p\n", fp->fd)); + ret = MPI_File_close(&fp->fd); + return ret; +} + +int +MPMY_Mkdir(const char *path, int mode) +{ + int ret; + + if( MPMY_Procnum() == 0 ){ + ret = mkdir(path, mode); + if( ret && errno == EEXIST ){ + /* Let's just pretend we really made it... */ + ret = 0; + } + } + MPMY_BcastTag(&ret, 1, MPMY_INT, 0, 0x4579 ); + return ret; +} + +size_t +MPMY_Fread(void *ptr, size_t size, size_t nitems, MPMYFile *Fp) +{ + struct _File *fp = (struct _File *)Fp; + MPI_Status status; + int cnt; + size_t nread = size*nitems; + const char *p = ptr; + + if( fp == NULL ){ + errno = EINVAL; + return -1; + } + if (fp->iomode == MPMY_SINGL) { + MPI_File_read_all(fp->fd, (void *)p, nread, MPI_CHAR, &status); + } else { + MPI_File_read_ordered(fp->fd, (void *)p, nread, MPI_CHAR, &status); + } + MPI_Get_count(&status, MPI_BYTE, &cnt); + if (cnt != nread) Error("MPMY_Fread has a problem\n"); + Msgf(("MPI_File_read from %p returns %d\n", fp->fd, cnt)); + return nitems; +} + +size_t +MPMY_Fwrite(const void *ptr, size_t size, size_t nitems, MPMYFile *Fp) +{ + struct _File *fp = (struct _File *)Fp; + MPI_Status status; + int cnt; + size_t nwrite = size*nitems; + const char *p = ptr; + + Msgf(("MPMY_Fwrite %ld %ld\n", size, nitems)); + if( fp == NULL ){ + errno = EINVAL; + return -1; + } + if (fp->iomode == MPMY_SINGL) { + MPI_File_write_all(fp->fd, (void *)p, nwrite, MPI_CHAR, &status); + } else { + MPI_File_write_ordered(fp->fd, (void *)p, nwrite, MPI_CHAR, &status); + } + MPI_Get_count(&status, MPI_BYTE, &cnt); + if (cnt != nwrite) Error("MPMY_Fread has a problem\n"); + Msgf(("MPI_File_write from %p returns %d\n", fp->fd, cnt)); + return nitems; +} + +int +MPMY_Fseek(MPMYFile *Fp, off_t offset, int whence) +{ + struct _File *fp = (struct _File *)Fp; + int ret; + MPI_Offset mpi_offset; + int real_whence = 0; + + if( fp == NULL ){ + errno = EINVAL; + return -1; + } + + if (whence == MPMY_SEEK_SET) real_whence = MPI_SEEK_SET; + if (whence == MPMY_SEEK_CUR) real_whence = MPI_SEEK_CUR; + if (whence == MPMY_SEEK_END) real_whence = MPI_SEEK_END; + + mpi_offset = offset; /* potential conversion problem */ + if (fp->iomode == MPMY_SINGL) { + ret = MPI_File_seek_shared(fp->fd, mpi_offset, real_whence); + } else { + ret = MPI_File_seek(fp->fd, mpi_offset, real_whence); + } + if (ret != -1) ret = 0; + Msgf(("Fseek to %ld returns %d\n", (long)mpi_offset, ret)); + return ret; +} + +off_t +MPMY_Ftell(MPMYFile *Fp) +{ + struct _File *fp = (struct _File *)Fp; + MPI_Offset mpi_offset; + + if( fp == NULL ){ + errno = EINVAL; + return -1; + } + if (fp->iomode == MPMY_SINGL) { + MPI_File_get_position_shared(fp->fd, &mpi_offset); + } else { + MPI_File_get_position(fp->fd, &mpi_offset); + } + Msgf(("Ftell returns %ld\n", (long)mpi_offset)); + return mpi_offset; +} + +off_t +MPMY_Flen(MPMYFile *Fp) +{ + struct _File *fp = (struct _File *)Fp; + MPI_Offset mpi_offset_current, mpi_offset_end; + + if( fp == NULL ){ + errno = EINVAL; + return -1; + } + if (fp->iomode == MPMY_SINGL) { + MPI_File_get_position_shared(fp->fd, &mpi_offset_current); + MPI_File_seek_shared(fp->fd, mpi_offset_current, MPI_SEEK_END); + MPI_File_get_position_shared(fp->fd, &mpi_offset_end); + MPI_File_seek_shared(fp->fd, mpi_offset_current, MPI_SEEK_SET); + } else { + MPI_File_get_position(fp->fd, &mpi_offset_current); + MPI_File_seek(fp->fd, mpi_offset_current, MPI_SEEK_END); + MPI_File_get_position(fp->fd, &mpi_offset_end); + MPI_File_seek(fp->fd, mpi_offset_current, MPI_SEEK_SET); + } + Msgf(("Flen returns %ld\n", (long)mpi_offset_end)); + return mpi_offset_end; +} + +size_t +MPMY_Fseekrd(MPMYFile *Fp, off_t offset, int whence, void *buf, size_t reclen, + size_t nrecs) +{ + struct _File *fp = (struct _File *)Fp; + MPI_Offset mpi_offset; + MPI_Status status; + int cnt; + size_t nread = reclen*nrecs; + const char *p = buf; + + Msgf(("Fseekrd %ld at %ld\n", (size_t)reclen*nrecs, offset)); + mpi_offset = offset; + if( fp == NULL ){ + errno = EINVAL; + return -1; + } + if (fp->iomode == MPMY_SINGL) { + MPI_File_read_at_all(fp->fd, mpi_offset, (void *)p, nread, MPI_BYTE, &status); + } else { + MPI_File_read_at(fp->fd, mpi_offset, (void *)p, nread, MPI_BYTE, &status); + } + MPI_Get_count(&status, MPI_BYTE, &cnt); + if (cnt != nread) Error("MPMY_Fseekrd has a problem, got %d expected %ld\n", + cnt, nread); + return nrecs; +} + +#include "io_generic.c" diff --git a/external/libsdf/libmpmy/mpmy_mpiio.c b/external/libsdf/libmpmy/mpmy_mpiio.c new file mode 100644 index 0000000..f1c1c93 --- /dev/null +++ b/external/libsdf/libmpmy/mpmy_mpiio.c @@ -0,0 +1,346 @@ +/* This file contains the parallel I/O suitable for CMMD and NX. + It wouldn't be hard to add cubix-syntax as well. Are there any + other options? Would they fit in this structure? The only + difference between CMMD and NX is in Fopen, where one + system calls gopen() and the other calls CMMD_set_io_mode(). + We use a pre-processor symbol (__INTEL_SSD__) or (__CM5__) to decide + which one to use. __INTEL_SSD__ is set by the ARCH-specific Makefiles, + while __CM5__ is set by mpmy_cm5.c, which #includes this file. +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef OPEN_MPI +#include +#endif +#include "protos.h" +#include "mpmy.h" +#include "mpmy_io.h" +#include "Msgs.h" + +#ifndef EINVAL +/* just in case... */ +#define EINVAL 0 +#endif + +#define NFILES 4096 + +/* MPI only allows 2GB buffer sizes, and MPI_Get_Count uses an int */ +#define MAXIOSIZE (256*1024*1024) + +static struct _File{ + MPI_File fd; + int iomode; +} _files[NFILES]; + +static int files; /* need dynamic storage */ + +static int do_nfileio; + +MPMYFile * +MPMY_Fopen(const char *path, int flags) +{ + MPI_File fd; + MPI_Info info; + int iomode = MPMY_SINGL; /* default */ + int real_flags = MPI_MODE_RDONLY; /* if no flags specified */ + int ret; + + Msgf(("Fopen %s, flags = 0x%x\n", path, flags)); + if (flags & MPMY_RDONLY) real_flags = MPI_MODE_RDONLY; + if (flags & MPMY_WRONLY) real_flags = MPI_MODE_WRONLY; + if (flags & MPMY_RDWR) real_flags = MPI_MODE_RDWR; + if (flags & MPMY_APPEND) real_flags |= MPI_MODE_APPEND; + if (flags & MPMY_TRUNC && ((flags & MPMY_WRONLY) || (flags & MPMY_RDWR))) { + int fd; + if (MPMY_Procnum() == 0) { + fd = open(path, O_RDWR|O_TRUNC, 0644); + if (fd < 0) Msgf(("Fopen fails, errno=%d\n", errno)); + else close(fd); + MPMY_Sync(); + } else { + MPMY_Sync(); + } + } + if (flags & MPMY_CREAT) real_flags |= MPI_MODE_CREATE; + + /* Panasas optimizations */ + if (!(flags & MPMY_RDONLY)) + real_flags |= MPI_MODE_UNIQUE_OPEN; /* dangerous? */ + MPI_Info_create(&info); + MPI_Info_set(info, "panfs_concurrent_write", "1"); + + /* Should we make sure that only one of them is on?? */ + if (flags & MPMY_MULTI) iomode = MPMY_MULTI; + if (flags & MPMY_SINGL) iomode = MPMY_SINGL; + + if (flags & MPMY_NFILE) Error("MPMY_NFILE not supported\n"); + if (flags & MPMY_IOZERO) Error("MPMY_IOZERO not supported\n"); + if (flags & MPMY_INDEPENDENT) Error("MPMY_INDEPENDENT not supported\n"); + + if (flags & MPMY_SINGL) { + Msgf(("Fopen %s in SINGL mode\n", path)); + } else { + Msgf(("Fopen %s in MULTI mode\n", path)); + } + Msgf(("MPI_File_open %s with flags = 0x%x\n", path, real_flags)); + ret = MPI_File_open(MPI_COMM_WORLD, (char *)path, real_flags, info, &fd); + + if (files >= NFILES) Error("files too large\n"); + if (ret == 0) { + _files[files].iomode = iomode; + _files[files].fd = fd; + Msgf(("Fopen returns fd %p, iomode=%d, flags=0x%x\n", + fd, iomode, flags)); + return &(_files[files++]); + } else { + Msgf(("Fopen fails, errno=%d\n", errno)); + return NULL; + } +} + +int +MPMY_Nfileio(int val){ + int oldval = do_nfileio; + do_nfileio = val; + return oldval; +} + +int +MPMY_Fclose(MPMYFile *Fp) +{ + struct _File *fp = (struct _File *)Fp; + int ret; + + if( fp == NULL ){ + errno = EINVAL; + return -1; + } + Msgf(("Fclose %p\n", fp->fd)); + ret = MPI_File_close(&fp->fd); + return ret; +} + +int +MPMY_Mkdir(const char *path, int mode) +{ + int ret; + + if( MPMY_Procnum() == 0 ){ + ret = mkdir(path, mode); + if( ret && errno == EEXIST ){ + /* Let's just pretend we really made it... */ + ret = 0; + } + } + MPMY_BcastTag(&ret, 1, MPMY_INT, 0, 0x4579 ); + return ret; +} + +size_t +MPMY_Fread(void *ptr, size_t size, size_t nitems, MPMYFile *Fp) +{ + struct _File *fp = (struct _File *)Fp; + MPI_Status status; + int cnt; + size_t nread = size*nitems; + const char *p = ptr; + + Msgf(("MPMY_Fread %ld %ld\n", size, nitems)); + if( fp == NULL ){ + errno = EINVAL; + return -1; + } + if (fp->iomode == MPMY_SINGL) { + if (nread >= (1 << 31)) Error("MPMY_SINGL does not yet support large reads\n"); + MPI_File_read_all(fp->fd, (void *)p, nread, MPI_CHAR, &status); + MPI_Get_count(&status, MPI_CHAR, &cnt); + } else { + MPI_Offset mpi_offset; + size_t left, *sizes; + int i; + assert(sizeof(size_t) == MPMY_Datasize[MPMY_LONG]); + sizes = Malloc(sizeof(size_t)*MPMY_Nproc()); + /* Use scan instead? */ + Native_MPMY_Allgather(&nread, 1, MPMY_LONG, sizes); + MPI_File_get_position(fp->fd, &mpi_offset); + Msgf(("Starting offset in MPMY_Fread is %lld\n", mpi_offset)); + for (i = 0; i < MPMY_Procnum(); i++) { + mpi_offset += sizes[i]; + } + Msgf(("My offset in MPMY_Fread is %lld\n", mpi_offset)); + Free(sizes); + left = nread; + while (left > 0) { + nread = (left < MAXIOSIZE) ? left : MAXIOSIZE; + Msgf(("read %ld at %lld\n", nread, mpi_offset)); + Msg_flush(); + MPI_File_read_at(fp->fd, mpi_offset, (void *)p, nread, MPI_CHAR, &status); + left -= nread; + p += nread; + mpi_offset += nread; + MPI_Get_count(&status, MPI_CHAR, &cnt); + } + } + return cnt/size; +} + +size_t +MPMY_Fwrite(const void *ptr, size_t size, size_t nitems, MPMYFile *Fp) +{ + struct _File *fp = (struct _File *)Fp; + MPI_Status status; + int cnt; + size_t nwrite = size*nitems; + const char *p = ptr; + + Msgf(("MPMY_Fwrite %ld %ld\n", size, nitems)); + if( fp == NULL ){ + errno = EINVAL; + return -1; + } + if (fp->iomode == MPMY_SINGL) { + if (nwrite >= (1 << 31)) Error("MPMY_SINGL does not yet support large writes\n"); + MPI_File_write_all(fp->fd, (void *)p, nwrite, MPI_CHAR, &status); + MPI_Get_count(&status, MPI_CHAR, &cnt); + if (cnt != nwrite) Error("MPMY_Fwrite has a problem, wrote %d of %ld\n", + cnt, nwrite); + } else { + MPI_Offset mpi_offset; + size_t left, *sizes; + int i; + assert(sizeof(size_t) == MPMY_Datasize[MPMY_LONG]); + sizes = Malloc(sizeof(size_t)*MPMY_Nproc()); + Native_MPMY_Allgather(&nwrite, 1, MPMY_LONG, sizes); + MPI_File_get_position(fp->fd, &mpi_offset); + Msgf(("Starting offset in MPMY_Fwrite is %lld\n", mpi_offset)); + for (i = 0; i < MPMY_Procnum(); i++) { + mpi_offset += sizes[i]; + } + Msgf(("My offset in MPMY_Fwrite is %lld\n", mpi_offset)); + Free(sizes); + left = nwrite; + while (left > 0) { + nwrite = (left < MAXIOSIZE) ? left : MAXIOSIZE; + Msgf(("write %ld at %lld\n", nwrite, mpi_offset)); + Msg_flush(); + MPI_File_write_at(fp->fd, mpi_offset, (void *)p, nwrite, MPI_CHAR, &status); + left -= nwrite; + p += nwrite; + mpi_offset += nwrite; + MPI_Get_count(&status, MPI_CHAR, &cnt); + if (cnt != nwrite) Error("MPMY_Fwrite has a problem, wrote %d of %ld\n", + cnt, nwrite); + } + } + return nitems; +} + +off_t +MPMY_Fseek(MPMYFile *Fp, off_t offset, int whence) +{ + struct _File *fp = (struct _File *)Fp; + int ret; + MPI_Offset mpi_offset; + int real_whence = 0; + + if( fp == NULL ){ + errno = EINVAL; + return -1; + } + + if (whence == MPMY_SEEK_SET) real_whence = MPI_SEEK_SET; + if (whence == MPMY_SEEK_CUR) real_whence = MPI_SEEK_CUR; + if (whence == MPMY_SEEK_END) real_whence = MPI_SEEK_END; + + mpi_offset = offset; /* potential conversion problem */ + if (fp->iomode == MPMY_SINGL) { + ret = MPI_File_seek_shared(fp->fd, mpi_offset, real_whence); + } else { + ret = MPI_File_seek(fp->fd, mpi_offset, real_whence); + } + if (ret != -1) ret = 0; + Msgf(("Fseek to %ld returns %d\n", (long)mpi_offset, ret)); + return ret; +} + +off_t +MPMY_Ftell(MPMYFile *Fp) +{ + struct _File *fp = (struct _File *)Fp; + MPI_Offset mpi_offset; + + if( fp == NULL ){ + errno = EINVAL; + return -1; + } + if (fp->iomode == MPMY_SINGL) { + MPI_File_get_position_shared(fp->fd, &mpi_offset); + } else { + MPI_File_get_position(fp->fd, &mpi_offset); + } + Msgf(("Ftell returns %ld\n", (long)mpi_offset)); + return mpi_offset; +} + +off_t +MPMY_Flen(MPMYFile *Fp) +{ + struct _File *fp = (struct _File *)Fp; + MPI_Offset mpi_offset_current, mpi_offset_end; + + if( fp == NULL ){ + errno = EINVAL; + return -1; + } + if (fp->iomode == MPMY_SINGL) { + MPI_File_get_position_shared(fp->fd, &mpi_offset_current); + MPI_File_seek_shared(fp->fd, mpi_offset_current, MPI_SEEK_END); + MPI_File_get_position_shared(fp->fd, &mpi_offset_end); + MPI_File_seek_shared(fp->fd, mpi_offset_current, MPI_SEEK_SET); + } else { + MPI_File_get_position(fp->fd, &mpi_offset_current); + MPI_File_seek(fp->fd, mpi_offset_current, MPI_SEEK_END); + MPI_File_get_position(fp->fd, &mpi_offset_end); + MPI_File_seek(fp->fd, mpi_offset_current, MPI_SEEK_SET); + } + Msgf(("Flen returns %ld\n", (long)mpi_offset_end)); + return mpi_offset_end; +} + +size_t +MPMY_Fseekrd(MPMYFile *Fp, off_t offset, int whence, void *buf, size_t reclen, + size_t nrecs) +{ + struct _File *fp = (struct _File *)Fp; + MPI_Offset mpi_offset; + MPI_Status status; + int cnt; + size_t nread = reclen*nrecs; + const char *p = buf; + + Msgf(("Fseekrd %ld at %ld\n", (size_t)reclen*nrecs, offset)); + mpi_offset = offset; + if( fp == NULL ){ + errno = EINVAL; + return -1; + } + if (fp->iomode == MPMY_SINGL) { + MPI_File_read_at_all(fp->fd, mpi_offset, (void *)p, nread, MPI_BYTE, &status); + } else { + MPI_File_read_at(fp->fd, mpi_offset, (void *)p, nread, MPI_BYTE, &status); + } + MPI_Get_count(&status, MPI_BYTE, &cnt); + if (cnt != nread) Error("MPMY_Fseekrd has a problem, got %d expected %ld\n", + cnt, nread); + return nrecs; +} + +#include "io_generic.c" diff --git a/external/libsdf/libmpmy/mpmy_mvapich2.c b/external/libsdf/libmpmy/mpmy_mvapich2.c new file mode 120000 index 0000000..74dd607 --- /dev/null +++ b/external/libsdf/libmpmy/mpmy_mvapich2.c @@ -0,0 +1 @@ +mpmy_mpi.c \ No newline at end of file diff --git a/external/libsdf/libmpmy/mpmy_panio.c b/external/libsdf/libmpmy/mpmy_panio.c new file mode 100644 index 0000000..730a4dd --- /dev/null +++ b/external/libsdf/libmpmy/mpmy_panio.c @@ -0,0 +1,281 @@ +/* This file contains the parallel I/O suitable for CMMD and NX. + It wouldn't be hard to add cubix-syntax as well. Are there any + other options? Would they fit in this structure? The only + difference between CMMD and NX is in Fopen, where one + system calls gopen() and the other calls CMMD_set_io_mode(). + We use a pre-processor symbol (__INTEL_SSD__) or (__CM5__) to decide + which one to use. __INTEL_SSD__ is set by the ARCH-specific Makefiles, + while __CM5__ is set by mpmy_cm5.c, which #includes this file. +*/ +#include +#include +#include +#include +#include +#include +#include +#include "protos.h" +#include "mpmy.h" +#include "mpmy_io.h" +#include "Msgs.h" +#include "iozero.h" + +#ifndef EINVAL +/* just in case... */ +#define EINVAL 0 +#endif + +#define NFILES 4096 +static struct _File{ + int fd; + int iomode; + int iotype; + int flags; +} _files[NFILES]; + +static int do_nfileio; + +MPMYFile * +MPMY_Fopen(const char *path, int flags) +{ + int fd; + int mode = 0644; + int iomode = MPMY_SINGL; /* default */ + int iotype = 0; + int real_flags = 0; + + Msgf(("Fopen %s\n", path)); + if (flags & MPMY_RDONLY) real_flags |= O_RDONLY; + if (flags & MPMY_WRONLY) real_flags |= O_WRONLY; + if (flags & MPMY_RDWR) real_flags |= O_RDWR; + if (flags & MPMY_APPEND) real_flags |= O_APPEND; + if (flags & MPMY_TRUNC) real_flags |= O_TRUNC; + if (flags & MPMY_CREAT) real_flags |= O_CREAT; + + /* Should we make sure that only one of them is on?? */ + if (flags & MPMY_MULTI) iomode = MPMY_MULTI; + if (flags & MPMY_SINGL) iomode = MPMY_SINGL; + + if (flags & MPMY_NFILE) iotype = MPMY_NFILE; + if (flags & MPMY_IOZERO) Error("MPMY_IOZERO not supported\n"); + if (flags & MPMY_INDEPENDENT) Error("MPMY_INDEPENDENT not supported\n"); + + if (iotype == MPMY_NFILE) { + char real_path[256]; + sprintf(real_path, "%s.p%03d", path, MPMY_Procnum()); + Msgf(("Fopen %s in NFILE mode\n", path)); + fd = open(real_path, real_flags, mode); + } else if (flags & MPMY_SINGL) { + Msgf(("Fopen %s in SINGL mode\n", path)); + fd = open(path, real_flags, mode); + } else { + Msgf(("Fopen %s in MULTI mode\n", path)); + fd = open(path, real_flags, mode); + } + + if (fd >= NFILES) Error("fd too large (%d)\n", fd); + if( fd >= 0 ){ + _files[fd].iomode = iomode; + _files[fd].iotype = iotype; + Msgf(("Fopen returns %d, iomode=%d, flags=0x%x\n", fd, iomode, flags)); + return &(_files[fd]); + }else{ + Msgf(("Fopen fails, errno=%d\n", errno)); + return NULL; + } +} + +int +MPMY_Nfileio(int val){ + int oldval = do_nfileio; + do_nfileio = val; + return oldval; +} + +int +MPMY_Fclose(MPMYFile *Fp) +{ + struct _File *fp = (struct _File *)Fp; + int ret; + + if( fp == NULL ){ + errno = EINVAL; + return -1; + } + if (fp->iomode == MPMY_SINGL) ret = close0(fp->fd); + else ret = close(fp->fd); + Msgf(("Fclose of %d returns %d\n", fp->fd, ret)); + return ret; +} + +int +MPMY_Mkdir(const char *path, int mode){ + return mkdir0(path, mode); +} + +int +MPMY_Fread(void *ptr, int size, int nitems, MPMYFile *Fp) +{ + struct _File *fp = (struct _File *)Fp; + int ret; + + if( fp == NULL ){ + errno = EINVAL; + return -1; + } + if (fp->iomode == MPMY_SINGL) ret = read0(fp->fd, ptr, size*nitems); + else ret = read(fp->fd, ptr, size*nitems); + + Msgf(("Fread from %d returns %d\n", fp->fd, ret)); + if (ret % size) Error("MPMY_Fread has a problem\n"); + return ret/size; +} + +int +MPMY_Fwrite(const void *ptr, int size, int nitems, MPMYFile *Fp) +{ + struct _File *fp = (struct _File *)Fp; + int ret; + + if( fp == NULL ){ + errno = EINVAL; + return -1; + } + if (fp->iomode == MPMY_SINGL) ret= write0(fp->fd, ptr, size*nitems); + else ret = write(fp->fd, ptr, size*nitems); + /* Msgf(("Fwrite to %d returns %d.\n", fp->fd, ret)); */ + if (ret % size) Error("MPMY_Fwrite has a problem\n"); + return ret/size; +} + +int +MPMY_Fseek(MPMYFile *Fp, off_t offset, int whence) +{ + struct _File *fp = (struct _File *)Fp; + off_t ret; + int real_whence = 0; + + if( fp == NULL ){ + errno = EINVAL; + return -1; + } + + if (whence == MPMY_SEEK_SET) real_whence = SEEK_SET; + if (whence == MPMY_SEEK_CUR) real_whence = SEEK_CUR; + if (whence == MPMY_SEEK_END) real_whence = SEEK_END; + + if (fp->iotype == MPMY_SINGL) { + ret = lseek0(fp->fd, offset, real_whence); + } else { + ret = lseek(fp->fd, offset, real_whence); + } + if (ret != -1) ret = 0; + Msgf(("Fseek returns %ld\n", (long)ret)); + return ret; +} + +int +MPMY_Ftell(MPMYFile *Fp) +{ + struct _File *fp = (struct _File *)Fp; + off_t ret; + + if( fp == NULL ){ + errno = EINVAL; + return -1; + } + if (fp->iotype == MPMY_SINGL) { + ret = tell0(fp->fd); + } else { + ret = lseek(fp->fd, 0L, SEEK_CUR); + } + Msgf(("Ftell returns %ld\n", (long)ret)); + return ret; +} + +off_t +MPMY_Flen(MPMYFile *Fp) +{ + struct _File *fp = (struct _File *)Fp; + off_t ret; + + if( fp == NULL ){ + errno = EINVAL; + return -1; + } + if (fp->iotype & MPMY_NFILE) { + ret = flen(fp->fd); + Msgf(("flen segment %ld\n", (long)ret)); + if (sizeof(ret) != sizeof(long)) { + Error("Bad types in MPMY_Flen\n"); + } + MPMY_Combine(&ret, &ret, 1, MPMY_LONG, MPMY_SUM); + } else if (fp->iotype == MPMY_SINGL) { + ret = flen0(fp->fd); + } else { + ret = flen(fp->fd); + } + Msgf(("Flen returns %ld\n", (long)ret)); + return ret; +} + +int +MPMY_Fseekrd(MPMYFile *Fp, off_t offset, int whence, void *buf, int reclen, + int nrecs) +{ + struct _File *fp = (struct _File *)Fp; + int doseek; + + if( fp == NULL ){ + errno = EINVAL; + return -1; + } + if (fp->iomode == MPMY_SINGL) { + nrecs = fseekrd0(fp->fd, offset, whence, buf, reclen, nrecs); + return nrecs; + } + + if( whence == MPMY_SEEK_CUR ){ + doseek = (offset != 0); + }else if( whence == MPMY_SEEK_SET ){ + /* don't worry about errors. If ftell returns -1, */ + /* doseek will be turned on, and the fseek below will */ + /* (probably) fail */ + doseek = (MPMY_Ftell(Fp) != offset); + }else{ + doseek = 1; + } + + if( doseek ){ + if( MPMY_Fseek(Fp, offset, whence) ){ + if( whence == MPMY_SEEK_CUR && offset > 0 ){ + /* Make a final heroic effort to seek by reading forward! */ + char junk[BUFSIZ]; + int nleft = offset; + while( nleft ){ + int ntry = ( nleft > sizeof(junk) ) ? sizeof(junk) : nleft; + if( MPMY_Fread(junk, ntry, 1, Fp) != 1 ){ + Error("fseekrd: incremental fread(%#lx, %d, 1, %#lx) failed, errno=%d\n", + (unsigned long)junk, ntry, + (unsigned long)fp, errno); + return -1; + } + nleft -= ntry; + } + }else{ + Error("fseekrd: fseek(%#lx, %lld, %d) failed, errno=%d\n", + (unsigned long)fp, offset, whence, errno); + return -1; + } + } + } + if( MPMY_Fread(buf, reclen, nrecs, Fp) != nrecs ){ + Error("fseekrd: fread(%#lx, %d, %d, %#lx) failed, errno=%d\n", + (unsigned long)buf, reclen, nrecs, (unsigned long)fp, errno); + return -1; + } + return nrecs; +} + +#include "iozero.c" +#include "io_generic.c" diff --git a/external/libsdf/libmpmy/mpmy_seq.c b/external/libsdf/libmpmy/mpmy_seq.c new file mode 100644 index 0000000..c1bd98d --- /dev/null +++ b/external/libsdf/libmpmy/mpmy_seq.c @@ -0,0 +1,262 @@ +/* + Not-so-trivial implementation of the mpmy interface for a single process(or) + that handles messages sent to itself. + + This is not designed for speed. In fact, it's not designed at all. It's + just meant to limp along. I think it's a bad idea to be sending a lot + of messages to yourself. +*/ +#include +#include "Msgs.h" +#include "mpmy.h" +#include "Assert.h" +#include "mpmy_io.h" +#include "mpmy_time.h" +#include "mpmy_abnormal.h" + +#define IN 1 +#define OUT 2 + +#ifdef __SUN4__ +/* ARCH=sun4 code may have been compiled and linked with __CM5VU__, which + means that if we're not careful we'll hit some illegal instructions when + we try to call do_grav. This variable sidesteps those Vector-Unit + calls at run-time. It's twisted, but it's the price we pay for using + ARCH=sun4 for the CM5. */ +int have_vu = 0; +void *VUHeap; +int VUaux_allocated; + +#if 0 +void *aux_alloc_heap(int n){ + Error("aux_alloc_heap: You shouldn't reach this on a non-cm5 processor!\n"); +} +#endif + +#endif + +struct comm_s{ + int cnt; + int tag; + void *buf; + int inout; + int finished; +}; + +/* These do a little more than mpmy_alloc_generic. It lets us search */ +/* the list of allocated requests too. Unfortunately, it takes O(Nreq) */ +/* time to do a Dealloc or a Match. I'm sure there's something simpler than */ +/* hashing that would do better, but I'm being dense. */ + +#define MAXCOMM 200 +static struct comm_s _comms[MAXCOMM]; +static int freecomm[MAXCOMM]; +static int usedcomm[MAXCOMM]; +static int mpmy_nfree = 0; +static int mpmy_nused = 0; + +static void CommInit(void){ + int i; + for(i=0; i= 0 ){ + ret = freecomm[--mpmy_nfree]; + usedcomm[mpmy_nused++] = ret; + return ret; + }else + return -1; +} + +static void CommDealloc(int req){ + int i; + assert(mpmy_nfree < MAXCOMM); + for(i=0; ifinished + && (comm->tag == tag || tag == MPMY_TAG_ANY || comm->tag == MPMY_TAG_ANY) + && comm->inout == inout ) + return ui; + } + return -1; +} + +int MPMY_Isend(const void *buf, int cnt, int dest, int tag, MPMY_Comm_request *reqp){ + struct comm_s *comm; + int req; + + if( dest != 0 ) + return MPMY_FAILED; + req = CommAlloc(); + if( req < 0 ) + return MPMY_FAILED; + + comm = &_comms[req]; + comm->inout = OUT; + comm->cnt = cnt; + comm->tag = tag; + comm->buf = (void *)buf; /* drop const. modifier */ + comm->finished = 0; + *reqp = comm; + IncrCounter(&MPMYSendCnt); + return MPMY_SUCCESS; +} + +int MPMY_Irecv(void *buf, int cnt, int src, int tag, MPMY_Comm_request *reqp){ + struct comm_s *comm; + int req; + + if( src != 0 && src != MPMY_SOURCE_ANY ) + return MPMY_FAILED; + req = CommAlloc(); + if( req < 0 ) + return MPMY_FAILED; + + comm = &_comms[req]; + comm->inout = IN; + comm->cnt = cnt; + comm->tag = tag; + comm->buf = buf; + comm->finished = 0; + *reqp = comm; + IncrCounter(&MPMYRecvCnt); + return MPMY_SUCCESS; +} + +int MPMY_Test(MPMY_Comm_request req, int *flag, MPMY_Status *stat){ + struct comm_s *comm = req; + struct comm_s *mcomm; + int match; + int ireq = comm - _comms; + + if( comm->finished ){ + *flag = 1; + if( comm->inout == IN && stat ){ + stat->count = comm->cnt; + stat->tag = comm->tag; + stat->src = 0; + } + CommDealloc(ireq); + IncrCounter(&MPMYDoneCnt); + return MPMY_SUCCESS; + } + if( comm->inout == IN ){ + match = find_match(OUT, comm->tag); + if( match >= 0 ){ + mcomm = &_comms[match]; + if( mcomm->cnt > comm->cnt ){ + SeriousWarning("MPMY_Test message too long\n"); + CommDealloc(ireq); + return MPMY_FAILED; + } + memcpy(comm->buf, mcomm->buf, mcomm->cnt); + if( stat ){ + stat->count = mcomm->cnt; + stat->tag = mcomm->tag; + stat->src = 0; + } + mcomm->finished = 1; + *flag = 1; + IncrCounter(&MPMYDoneCnt); + CommDealloc(ireq); + return MPMY_SUCCESS; + }else{ + *flag = 0; + return MPMY_SUCCESS; + } + }else{ + match = find_match(IN, comm->tag); + if( match >= 0 ){ + mcomm = &_comms[match]; + if( comm->cnt > mcomm->cnt ){ + SeriousWarning("MPMY_Test message too long\n"); + CommDealloc(ireq); + return MPMY_FAILED; + } + memcpy(mcomm->buf, comm->buf, comm->cnt); + mcomm->cnt = comm->cnt; + mcomm->tag = comm->tag; + mcomm->finished = 1; + *flag = 1; + IncrCounter(&MPMYDoneCnt); + CommDealloc(ireq); + return MPMY_SUCCESS; + }else{ + *flag = 0; + return MPMY_SUCCESS; + } + } +} + +int +Native_MPMY_Alltoall(void *sendbuf, int sendcount, MPMY_Datatype sendtype, + void *recvbuf, int recvcount, MPMY_Datatype recvtype) +{ + memcpy(recvbuf, sendbuf, sendcount*MPMY_Datasize[sendtype]); + return MPMY_SUCCESS; +} + +int +Native_MPMY_Allgather(void *sendbuf, int sendcount, MPMY_Datatype type, void *recvbuf) +{ + memcpy(recvbuf, sendbuf, sendcount*MPMY_Datasize[type]); + return MPMY_SUCCESS; +} + +int +Native_MPMY_Allgatherv(void *sendbuf, int sendcount, MPMY_Datatype type, void *recvbuf, + int *rcounts, int *roffsets) +{ + memcpy(recvbuf, sendbuf, sendcount*MPMY_Datasize[type]); + return MPMY_SUCCESS; +} + + + +int MPMY_Init(int *argcp, char ***argvp){ + CommInit(); + _MPMY_nproc_ = 1; + _MPMY_procnum_ = 0; + _MPMY_initialized_ = 1; + /* There should really be a better way to opt out of MPMY abnormal + signal handling. For now, this will work for programs that might + use SDF, but which have their own carefully crafted signal handlers, + e.g., SM */ + if( argcp ) + _MPMY_setup_absigs(); + MPMY_OnAbnormal(MPMY_SystemAbort); + MPMY_OnAbnormal(MPMY_Abannounce); + return MPMY_SUCCESS; +} + +#ifdef USE_GETTIME +#include "timers_gettime.c" +#endif + +#ifdef USE_HWCLOCK +#include "timers_hwclock.c" +#endif + +#include "mpmy_io.c" +#include "mpmy_abnormal.c" +#include "mpmy_generic.c" diff --git a/external/libsdf/libmpmy/timers_gettime.c b/external/libsdf/libmpmy/timers_gettime.c new file mode 100644 index 0000000..d36709a --- /dev/null +++ b/external/libsdf/libmpmy/timers_gettime.c @@ -0,0 +1,85 @@ +#include +#include "mpmy_time.h" +#include "Malloc.h" +#include "chn.h" + +static Chn timer_chn; +static int initialized; + +typedef struct { + int type; + struct timespec cpu_start; + double cpu_accum; + struct timespec wc_start; + double wc_accum; +} MPMY_Timer; + +void *MPMY_CreateTimer(int type){ + MPMY_Timer *ret; + + if( initialized == 0 ){ + ChnInit(&timer_chn, sizeof(MPMY_Timer), 40, Realloc_f); + initialized = 1; + } + + ret = ChnAlloc(&timer_chn); + ret->type = type; + MPMY_ClearTimer(ret); + return (void *)ret; +} + +int MPMY_DestroyTimer(void *p){ + ChnFree(&timer_chn, p); + return MPMY_SUCCESS; +} + +int MPMY_StartTimer(void *p){ + MPMY_Timer *t = p; + + switch(t->type){ + case MPMY_CPU_TIME: + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t->cpu_start); + break; + case MPMY_WC_TIME: + clock_gettime(CLOCK_REALTIME, &t->wc_start); + break; + } + return MPMY_SUCCESS; +} + +int MPMY_StopTimer(void *p){ + MPMY_Timer *t = p; + struct timespec tnow; + + switch(t->type){ + case MPMY_CPU_TIME: + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tnow); + t->cpu_accum += (tnow.tv_sec - t->cpu_start.tv_sec) + (tnow.tv_nsec - t->cpu_start.tv_nsec) * 1e-9; + break; + case MPMY_WC_TIME: + clock_gettime(CLOCK_REALTIME, &tnow); + t->wc_accum += (tnow.tv_sec - t->wc_start.tv_sec) + (tnow.tv_nsec - t->wc_start.tv_nsec) * 1e-9; + break; + } + return MPMY_SUCCESS; +} + +int MPMY_ClearTimer(void *p){ + MPMY_Timer *t = p; + + t->cpu_accum = 0.0; + t->wc_accum = 0.0; + return MPMY_SUCCESS; +} + +double MPMY_ReadTimer(void *p){ + MPMY_Timer *t = p; + + switch(t->type){ + case MPMY_CPU_TIME: + return t->cpu_accum; + case MPMY_WC_TIME: + return t->wc_accum; + } + return -1.0; +} diff --git a/external/libsdf/libmpmy/timers_hwclock.c b/external/libsdf/libmpmy/timers_hwclock.c new file mode 100644 index 0000000..b9d5d90 --- /dev/null +++ b/external/libsdf/libmpmy/timers_hwclock.c @@ -0,0 +1,106 @@ +#include +#include "mpmy_time.h" +#include "Malloc.h" +#include "chn.h" + +static Chn timer_chn; +static int initialized; + +typedef struct { + unsigned long long start; + unsigned long long accum; + struct timespec wc_start; + double wc_accum; + int type; +} MPMY_Timer; + +#ifdef AMD6100 +#define DEFAULT_MHZ 2300.0e6 +#else +#define DEFAULT_MHZ 2668.0e6 +#endif + +static __inline__ unsigned long long rdtsc(void) +{ + unsigned hi, lo; + __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi)); + return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 ); +} + +void *MPMY_CreateTimer(int type){ + MPMY_Timer *ret; + + if( initialized == 0 ){ + ChnInit(&timer_chn, sizeof(MPMY_Timer), 40, Realloc_f); + initialized = 1; + } + + ret = ChnAlloc(&timer_chn); + ret->type = type; + MPMY_ClearTimer(ret); + return (void *)ret; +} + +int MPMY_DestroyTimer(void *p){ + ChnFree(&timer_chn, p); + return MPMY_SUCCESS; +} + +int MPMY_CopyTimer(void *p, void *q) +{ + MPMY_Timer *t = p; + MPMY_Timer *u = q; + + *u = *t; + return MPMY_SUCCESS; +} + +int MPMY_StartTimer(void *p){ + MPMY_Timer *t = p; + + switch(t->type){ + case MPMY_CPU_TIME: + t->start = rdtsc(); + break; + case MPMY_WC_TIME: + clock_gettime(CLOCK_REALTIME, &t->wc_start); + break; + } + return MPMY_SUCCESS; +} + +int MPMY_StopTimer(void *p){ + MPMY_Timer *t = p; + struct timespec tnow; + + switch(t->type){ + case MPMY_CPU_TIME: + t->accum += rdtsc()-t->start; + break; + case MPMY_WC_TIME: + clock_gettime(CLOCK_REALTIME, &tnow); + t->wc_accum += (tnow.tv_sec - t->wc_start.tv_sec) + (tnow.tv_nsec - t->wc_start.tv_nsec) * 1e-9; + break; + } + return MPMY_SUCCESS; +} + +int MPMY_ClearTimer(void *p){ + MPMY_Timer *t = p; + + t->accum = 0; + t->wc_accum = 0.0; + return MPMY_SUCCESS; +} + +double MPMY_ReadTimer(void *p){ + MPMY_Timer *t = p; + + switch(t->type){ + case MPMY_CPU_TIME: + return t->accum/DEFAULT_MHZ; + case MPMY_WC_TIME: + return t->wc_accum; + } + return -1.0; +} diff --git a/external/libsdf/libmpmy/timers_mpi.c b/external/libsdf/libmpmy/timers_mpi.c new file mode 100644 index 0000000..9bb6c5e --- /dev/null +++ b/external/libsdf/libmpmy/timers_mpi.c @@ -0,0 +1,59 @@ +/* This file tries to use only MPI-approved timer constructs. */ + +/* time.h should define CLOCKS_PER_SECOND and prototype clock() and time() + and it should have typedefs for time_t and clock_t. */ +#include "mpmy_time.h" +#include "chn.h" + +static Chn timer_chn; +static int initialized; + +typedef struct { + int type; + double wc_start, wc_accum; +} MPMY_Timer; + +void *MPMY_CreateTimer(int type){ + MPMY_Timer *ret; + + if( initialized == 0 ){ + ChnInit(&timer_chn, sizeof(MPMY_Timer), 40, Realloc_f); + initialized = 1; + } + + ret = ChnAlloc(&timer_chn); + ret->type = type; + return (void *)ret; +} + +int MPMY_DestroyTimer(void *p){ + ChnFree(&timer_chn, p); + return MPMY_SUCCESS; +} + +int MPMY_StartTimer(void *p){ + MPMY_Timer *t = p; + + t->wc_start = MPI_Wtime(); + return MPMY_SUCCESS; +} + +int MPMY_StopTimer(void *p){ + MPMY_Timer *t = p; + + t->wc_accum += MPI_Wtime() - t->wc_start; + return MPMY_SUCCESS; +} + +int MPMY_ClearTimer(void *p){ + MPMY_Timer *t = p; + + t->wc_accum = 0.; + return MPMY_SUCCESS; +} + +double MPMY_ReadTimer(void *p){ + MPMY_Timer *t = p; + + return (double)t->wc_accum; +} diff --git a/external/libsdf/libmpmy/timers_posix.c b/external/libsdf/libmpmy/timers_posix.c new file mode 100644 index 0000000..edc3403 --- /dev/null +++ b/external/libsdf/libmpmy/timers_posix.c @@ -0,0 +1,139 @@ +/* This file tries to use only ANSI/POSIX-approved timer constructs. */ +/* It should compile correctly everywhere (Ha!) */ + +/* time.h should define CLOCKS_PER_SECOND and prototype clock() and time() + and it should have typedefs for time_t and clock_t. */ +#include +#include "mpmy_time.h" +#include "chn.h" +#include "Malloc.h" + +#ifndef CLOCKS_PER_SECOND +/* We've got a non-standard time.h. At least we have a time.h...*/ +#ifdef CLOCKS_PER_SEC /* This works for linux */ +#define CLOCKS_PER_SECOND CLOCKS_PER_SEC +#else +#define CLOCKS_PER_SECOND 1000000 /* this is just a wild guess!! */ +#endif +#endif + +/* POSIX only guarantees 'time', which returns a time_t. The option + is available for the 'implementor' to make time_t a double. Does + the friendly implementor at Sun do this? Nooooo. If we want more + precision we have to use gettimeofday, which is a non-POSIX BSD-ism. + + Better still, gettimeofday has mutually incompatible definitions in + SVr4 (one argument) and XSH4.2 (two arguments). Sigh... +*/ +#if defined(sun) || defined(__INTEL_SSD__) || defined(_AIX) || defined(__x86_64__) +# define USE_GETTIMEOFDAY +# include +#else /* don't use gettimeofday. use time() instead */ +extern time_t time(time_t *); +#endif + +/* This ought to be in one of the system headers... */ +extern clock_t clock(void); + +static Chn timer_chn; +static int initialized; + +typedef struct { + int type; + clock_t cpu_start, cpu_accum; +#ifdef USE_GETTIMEOFDAY + struct timeval wc_start; + struct timeval wc_accum; +#else + time_t wc_start, wc_accum; +#endif +} MPMY_Timer; + +void *MPMY_CreateTimer(int type){ + MPMY_Timer *ret; + + if( initialized == 0 ){ + ChnInit(&timer_chn, sizeof(MPMY_Timer), 40, Realloc_f); + initialized = 1; + } + + ret = ChnAlloc(&timer_chn); + ret->type = type; + MPMY_ClearTimer(ret); + return (void *)ret; +} + +int MPMY_DestroyTimer(void *p){ + ChnFree(&timer_chn, p); + return MPMY_SUCCESS; +} + +int MPMY_StartTimer(void *p){ + MPMY_Timer *t = p; + + switch(t->type){ + case MPMY_WC_TIME: +#ifdef USE_GETTIMEOFDAY + gettimeofday(&t->wc_start, 0); +#else + t->wc_start = time(0); +#endif + break; + case MPMY_CPU_TIME: + t->cpu_start = clock(); + break; + } + return MPMY_SUCCESS; +} + +int MPMY_StopTimer(void *p){ + MPMY_Timer *t = p; + + switch(t->type){ + case MPMY_WC_TIME: +#ifdef USE_GETTIMEOFDAY + { + struct timeval tnow; + gettimeofday(&tnow, 0); + t->wc_accum.tv_sec += tnow.tv_sec - t->wc_start.tv_sec; + t->wc_accum.tv_usec += tnow.tv_usec - t->wc_start.tv_usec; + } +#else + t->wc_accum += time(0) - t->wc_start; +#endif + break; + case MPMY_CPU_TIME: + t->cpu_accum += clock() - t->cpu_start; + break; + } + return MPMY_SUCCESS; +} + +int MPMY_ClearTimer(void *p){ + MPMY_Timer *t = p; + +#ifdef USE_GETTIMEOFDAY + t->wc_accum.tv_sec = 0; + t->wc_accum.tv_usec = 0; +#else + t->wc_accum = 0; +#endif + t->cpu_accum = 0; + return MPMY_SUCCESS; +} + +double MPMY_ReadTimer(void *p){ + MPMY_Timer *t = p; + + switch(t->type){ + case MPMY_WC_TIME: +#ifdef USE_GETTIMEOFDAY + return (double)t->wc_accum.tv_sec + (double)t->wc_accum.tv_usec*1.0e-6; +#else + return (double)t->wc_accum; +#endif + case MPMY_CPU_TIME: + return (double)t->cpu_accum * (1.0/CLOCKS_PER_SECOND); + } + return -1.0; +} diff --git a/python_tools/void_python_tools/backend/launchers.py b/python_tools/void_python_tools/backend/launchers.py index 0f78788..17acc76 100755 --- a/python_tools/void_python_tools/backend/launchers.py +++ b/python_tools/void_python_tools/backend/launchers.py @@ -1515,3 +1515,39 @@ def launchEstimateErrorBars(workDir=None, nullDir=None, numNulls=None, +# ----------------------------------------------------------------------------- +def launchVelocityStack(sample, stack, binPath, + velField_file, + thisDataPortion=None, logDir=None, + voidDir=None, runSuffix=None, + zobovDir=None, + summaryFile=None, + continueRun=None, dataType=None, prefixRun=""): + + sampleName = sample.fullName + + runSuffix = getStackSuffix(stack.zMin, stack.zMax, stack.rMin, + stack.rMax, thisDataPortion) + + logFile = logDir+("/%svelocity_stack_"%prefixRun)+sampleName+"_"+runSuffix+".out" + + voidCenters=voidDir+"/centers.txt" +# Rmax = + + centralRadius = stack.rMin * 0.25 + Rextracut = stack.rMin*3 + 1 + Rcircular = stack.rMin*3 + 2 + + parameters="--velocityField=%s --voidCenters=%s --Rmax=%e --L0=%e --numBins=%d" % (velField_file, voidCenters, Rmax, Boxsize, numBins) + + if not (continueRun and jobSuccessful(logFile, "Done!\n")): + cmd = "%s %s &> %s" % (binPath,parameters,logFile) + os.system(cmd) + if jobSuccessful(logFile, "Done!\n"): + print "done" + else: + print "FAILED!" + exit(-1) + + else: + print "already done!"