From a3e7567cbc3c8ee0891cda8391b3b91b3b3ff618 Mon Sep 17 00:00:00 2001 From: gsjaardema Date: Mon, 11 Oct 2021 17:26:42 -0600 Subject: [PATCH] Automatic snapshot commit from seacas at 1c9b366266 Origin repo remote tracking branch: 'origin/master' Origin repo remote repo URL: 'origin = https://github.com/gsjaardema/seacas' At commit: commit 1c9b366266d76108e6a1dd6adf100179e2af36c5 Author: Greg Sjaardema Date: Mon Oct 11 10:45:23 2021 -0600 Summary: SCRIPTS: Update name of script inside script [ci skip] * Primarily windows build fixes -- mingw32 and ming64 * Replace aprepro internal unordered map with a better one * run include-what-you-use * clean out some unused functionality in the getline functions --- packages/seacas/CMakeLists.txt | 44 +- .../seacas/applications/aprepro/aprepro.C | 16 +- .../aprepro/test-array.stderr.gold | 20 +- .../applications/aprepro/test-dump.gold | 4 +- .../applications/cpup/CP_SystemInterface.C | 8 +- .../applications/cpup/CP_SystemInterface.h | 1 - packages/seacas/applications/cpup/cpup.C | 1 - .../seacas/applications/epu/EP_Internals.C | 8 +- .../applications/epu/EP_ParallelDisks.C | 5 +- packages/seacas/applications/epu/epu.C | 4 - .../seacas/applications/exodiff/ED_Version.h | 4 +- .../seacas/applications/exodiff/exoII_read.h | 2 - .../seacas/applications/exodiff/exodiff.C | 47 +- .../seacas/applications/nem_slice/elb_inp.C | 35 +- .../seacas/applications/nem_slice/elb_main.C | 2 +- .../applications/nem_spread/nem_spread.C | 3 +- packages/seacas/cmake/Dependencies.cmake | 2 +- .../libraries/aprepro_lib/CMakeLists.txt | 1 - .../libraries/aprepro_lib/apr_aprepro.cc | 345 ++-- .../seacas/libraries/aprepro_lib/apr_array.cc | 4 +- .../libraries/aprepro_lib/apr_builtin.cc | 15 +- .../libraries/aprepro_lib/apr_exodus.cc | 1 + .../libraries/aprepro_lib/apr_getline_int.c | 1245 +------------ .../libraries/aprepro_lib/apr_getline_int.h | 43 +- .../seacas/libraries/aprepro_lib/apr_init.cc | 1 + .../libraries/aprepro_lib/apr_parser.cc | 3 +- .../seacas/libraries/aprepro_lib/apr_stats.cc | 37 - .../seacas/libraries/aprepro_lib/apr_stats.h | 30 - .../seacas/libraries/aprepro_lib/apr_symrec.h | 93 + .../seacas/libraries/aprepro_lib/apr_test.cc | 3 +- .../seacas/libraries/aprepro_lib/apr_util.cc | 46 +- .../seacas/libraries/aprepro_lib/apr_util.h | 3 +- .../seacas/libraries/aprepro_lib/aprepro.h | 90 +- .../seacas/libraries/aprepro_lib/aprepro.yy | 3 +- .../aprepro_lib/robin_growth_policy.h | 403 +++++ .../seacas/libraries/aprepro_lib/robin_hash.h | 1587 +++++++++++++++++ .../seacas/libraries/aprepro_lib/robin_map.h | 813 +++++++++ .../seacas/libraries/aprepro_lib/robin_set.h | 668 +++++++ .../aprepro_lib/test-array.stderr.gold | 24 +- .../seacas/libraries/exodus/include/doxygen.h | 3 +- .../exodus/include/exodusII_cfg.h.in | 11 +- .../seacas/libraries/exodus/src/ex_utils.c | 6 + .../libraries/ioss/src/Ioss_CodeTypes.h | 9 +- .../libraries/ioss/src/Ioss_CopyDatabase.C | 2 +- .../libraries/ioss/src/Ioss_Decomposition.h | 4 +- .../seacas/libraries/ioss/src/Ioss_FileInfo.C | 12 +- .../seacas/libraries/ioss/src/Ioss_Getline.c | 1237 +------------ .../seacas/libraries/ioss/src/Ioss_Getline.h | 43 +- .../seacas/libraries/ioss/src/Ioss_Glob.h | 14 +- .../libraries/ioss/src/Ioss_IOFactory.C | 2 +- .../seacas/libraries/ioss/src/Ioss_Utils.C | 10 +- .../ioss/src/cgns/Iocgns_DatabaseIO.C | 2 +- .../ioss/src/cgns/Iocgns_ParallelDatabaseIO.C | 2 +- .../libraries/ioss/src/cgns/Iocgns_Utils.C | 3 +- .../ioss/src/exodus/Ioex_ParallelDatabaseIO.C | 8 +- .../ioss/src/faodel/Iofaodel_Utils.C | 2 +- .../ioss/src/faodel/Iofaodel_Utils.h | 5 +- .../libraries/ioss/src/main/cgns_decomp.C | 31 +- .../libraries/ioss/src/utest/Utst_map.C | 11 +- .../libraries/ioss/src/utest/Utst_utils.C | 3 + .../ioss/src/visualization/CMakeLists.txt | 8 +- .../ioss/src/visualization/utils/Iovs_Utils.C | 23 +- .../seacas/libraries/supes/ext_lib/excpus.c | 3 - .../seacas/libraries/supes/ext_lib/exparm.c | 1 - .../libraries/supes/ext_lib/getline_int.c | 1245 +------------ .../libraries/supes/ext_lib/getline_int.h | 43 +- packages/seacas/libraries/suplib/addlog.c | 112 +- .../seacas/libraries/suplib_c/add_to_log.c | 15 +- .../libraries/suplib_c/open_file_limit.c | 12 +- .../seacas/libraries/suplib_c/term_width.c | 5 +- .../seacas/libraries/suplib_cpp/FileInfo.C | 19 +- packages/seacas/libraries/suplib_cpp/hwm.C | 9 +- packages/seacas/scripts/pconjoin.in | 14 +- 73 files changed, 4180 insertions(+), 4413 deletions(-) delete mode 100644 packages/seacas/libraries/aprepro_lib/apr_stats.cc delete mode 100644 packages/seacas/libraries/aprepro_lib/apr_stats.h create mode 100644 packages/seacas/libraries/aprepro_lib/apr_symrec.h create mode 100644 packages/seacas/libraries/aprepro_lib/robin_growth_policy.h create mode 100644 packages/seacas/libraries/aprepro_lib/robin_hash.h create mode 100644 packages/seacas/libraries/aprepro_lib/robin_map.h create mode 100644 packages/seacas/libraries/aprepro_lib/robin_set.h diff --git a/packages/seacas/CMakeLists.txt b/packages/seacas/CMakeLists.txt index cabdc6875a2a..0d5886c5aa8c 100644 --- a/packages/seacas/CMakeLists.txt +++ b/packages/seacas/CMakeLists.txt @@ -29,30 +29,32 @@ IF (NOT CMAKE_CXX_STANDARD MATCHES "^${${PROJECT_NAME}_CMAKE_CXX_STANDARDS_ALLOW ENDIF () set(SEACASExodus_ENABLE_STATIC_DEFAULT "OFF") -if (${CMAKE_PROJECT_NAME} STREQUAL "SEACASProj") - if (BUILD_SHARED_LIBS) - set(SEACASExodus_ENABLE_STATIC_DEFAULT "ON") - endif() -endif() -TRIBITS_ADD_OPTION_AND_DEFINE( - SEACASExodus_ENABLE_STATIC - EXODUS_STATIC - "Build static version of Exodus in addition to shared version." - ${SEACASExodus_ENABLE_STATIC_DEFAULT} - ) - set(SEACASExodus_ENABLE_SHARED_DEFAULT "OFF") -if (${CMAKE_PROJECT_NAME} STREQUAL "SEACASProj") - if (NOT BUILD_SHARED_LIBS) - set(SEACASExodus_ENABLE_SHARED_DEFAULT "ON") + +# On windows (and probably other systems), we only want a single +# exodus library and not both static and shared. +if (NOT CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + if (${CMAKE_PROJECT_NAME} STREQUAL "SEACASProj") + if (BUILD_SHARED_LIBS) + set(SEACASExodus_ENABLE_STATIC_DEFAULT "ON") + else() + set(SEACASExodus_ENABLE_SHARED_DEFAULT "ON") + endif() endif() + + TRIBITS_ADD_OPTION_AND_DEFINE( + SEACASExodus_ENABLE_STATIC + EXODUS_STATIC + "Build static version of Exodus in addition to shared version." + ${SEACASExodus_ENABLE_STATIC_DEFAULT} + ) + TRIBITS_ADD_OPTION_AND_DEFINE( + SEACASExodus_ENABLE_SHARED + EXODUS_SHARED + "Build shared version of Exodus in addition to static version." + ${SEACASExodus_ENABLE_SHARED_DEFAULT} + ) endif() -TRIBITS_ADD_OPTION_AND_DEFINE( - SEACASExodus_ENABLE_SHARED - EXODUS_SHARED - "Build shared version of Exodus in addition to static version." - ${SEACASExodus_ENABLE_SHARED_DEFAULT} - ) TRIBITS_ADD_OPTION_AND_DEFINE( SEACASIoss_ENABLE_THREADSAFE diff --git a/packages/seacas/applications/aprepro/aprepro.C b/packages/seacas/applications/aprepro/aprepro.C index 64dd2ab16467..58b3e1cd654a 100644 --- a/packages/seacas/applications/aprepro/aprepro.C +++ b/packages/seacas/applications/aprepro/aprepro.C @@ -4,9 +4,13 @@ // // See packages/seacas/LICENSE for details +#include #include +#include #include #include +#include +#include #include "aprepro.h" @@ -61,9 +65,7 @@ int main(int argc, char *argv[]) if (input_files.empty()) { if (!quiet) { - auto comment = aprepro.getsym("_C_")->value.svar; - std::cout << comment << " Algebraic Preprocessor -- Aprepro, version " << aprepro.version() - << "\n"; + std::cout << aprepro.long_version() << "\n"; } aprepro.ap_options.interactive = true; try { @@ -110,17 +112,13 @@ int main(int argc, char *argv[]) if (input_files.size() > 1) { std::ofstream ofile(input_files[1]); if (!quiet) { - auto comment = aprepro.getsym("_C_")->value.svar; - ofile << comment << " Algebraic Preprocessor (Aprepro) version " << aprepro.version() - << "\n"; + ofile << aprepro.long_version() << "\n"; } ofile << aprepro.parsing_results().str(); } else { if (!quiet) { - auto comment = aprepro.getsym("_C_")->value.svar; - std::cout << comment << " Algebraic Preprocessor (Aprepro) version " - << aprepro.version() << "\n"; + std::cout << aprepro.long_version() << "\n"; } std::cout << aprepro.parsing_results().str(); } diff --git a/packages/seacas/applications/aprepro/test-array.stderr.gold b/packages/seacas/applications/aprepro/test-array.stderr.gold index 33d408d70b21..f642d6978125 100644 --- a/packages/seacas/applications/aprepro/test-array.stderr.gold +++ b/packages/seacas/applications/aprepro/test-array.stderr.gold @@ -1,15 +1,15 @@ $ Variable = Value -$ {a (array) rows = 27, cols = 21} -$ {b (array) rows = 3, cols = 2} -$ {c (array) rows = 2, cols = 3} -$ {d (array) rows = 3, cols = 3} -$ {e (array) rows = 2, cols = 2} -$ {_col = 3} -$ {asub_rows = 17} +$ {c (array) rows = 2, cols = 3} $ {_c = 3} -$ {_r = 2} +$ {a (array) rows = 27, cols = 21} $ {a_rows = 27} -$ {asub (array) rows = 17, cols = 21} +$ {asub_rows = 17} +$ {b (array) rows = 3, cols = 2} $ {_therow = 2} -$ {et (array) rows = 2, cols = 2} +$ {_r = 2} +$ {asub (array) rows = 17, cols = 21} +$ {_col = 3} +$ {e (array) rows = 2, cols = 2} +$ {d (array) rows = 3, cols = 3} +$ {et (array) rows = 2, cols = 2} diff --git a/packages/seacas/applications/aprepro/test-dump.gold b/packages/seacas/applications/aprepro/test-dump.gold index d4a5a6394516..32f86d52da1c 100644 --- a/packages/seacas/applications/aprepro/test-dump.gold +++ b/packages/seacas/applications/aprepro/test-dump.gold @@ -1,4 +1,4 @@ -$ Variable = Value -$ {svar = "String"} (immutable) +$ Variable = Value $ {var = 42} (immutable) +$ {svar = "String"} (immutable) diff --git a/packages/seacas/applications/cpup/CP_SystemInterface.C b/packages/seacas/applications/cpup/CP_SystemInterface.C index ae07508ff37b..35faf7b2cd02 100644 --- a/packages/seacas/applications/cpup/CP_SystemInterface.C +++ b/packages/seacas/applications/cpup/CP_SystemInterface.C @@ -6,13 +6,13 @@ * See packages/seacas/LICENSE for details */ #include "CP_SystemInterface.h" -#include "CP_Version.h" // for qainfo -#include "GetLongOpt.h" // for GetLongOption, etc +#include "CP_Version.h" // for qainfo +#include "GetLongOpt.h" // for GetLongOption, etc +#include "Ioss_CodeTypes.h" #include "SL_tokenize.h" // for tokenize #include // for sort, transform #include // for tolower #include -#include // for size_t #include // for strtol, abs, exit, strtoul, etc #include // for strchr, strlen #include @@ -26,7 +26,7 @@ namespace { bool is_path_absolute(const std::string &path) { -#ifdef _WIN32 +#ifdef __IOSS_WINDOWS__ return path[0] == '\\' || path[1] == ':'; #else return path[0] == '/'; diff --git a/packages/seacas/applications/cpup/CP_SystemInterface.h b/packages/seacas/applications/cpup/CP_SystemInterface.h index 51759ed500e5..e90ff6e107b2 100644 --- a/packages/seacas/applications/cpup/CP_SystemInterface.h +++ b/packages/seacas/applications/cpup/CP_SystemInterface.h @@ -12,7 +12,6 @@ #include // for INT_MAX #include // for ostream #include // for string -#include // for pair #include // for vector namespace Cpup { diff --git a/packages/seacas/applications/cpup/cpup.C b/packages/seacas/applications/cpup/cpup.C index fad9f8c62027..4a7bc48aba3f 100644 --- a/packages/seacas/applications/cpup/cpup.C +++ b/packages/seacas/applications/cpup/cpup.C @@ -4,7 +4,6 @@ // // See packages/seacas/LICENSE for details #include -#include #include #include #include diff --git a/packages/seacas/applications/epu/EP_Internals.C b/packages/seacas/applications/epu/EP_Internals.C index c01a4c9164b6..1886768f7977 100644 --- a/packages/seacas/applications/epu/EP_Internals.C +++ b/packages/seacas/applications/epu/EP_Internals.C @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2020 National Technology & Engineering Solutions + * Copyright(C) 1999-, 20212021 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * @@ -21,7 +21,8 @@ #include // for string, basic_string #include // for vector -#ifdef _WIN32 +#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || \ + defined(__MINGW32__) || defined(_WIN64) || defined(__MINGW64__) #include #endif @@ -83,7 +84,8 @@ namespace { bool Excn::is_path_absolute(const std::string &path) { -#ifdef _WIN32 +#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || \ + defined(__MINGW32__) || defined(_WIN64) || defined(__MINGW64__) return path[0] == '\\' || path[1] == ':'; #else return path[0] == '/'; diff --git a/packages/seacas/applications/epu/EP_ParallelDisks.C b/packages/seacas/applications/epu/EP_ParallelDisks.C index f280992e4b50..f5496b983e66 100644 --- a/packages/seacas/applications/epu/EP_ParallelDisks.C +++ b/packages/seacas/applications/epu/EP_ParallelDisks.C @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2020 National Technology & Engineering Solutions + * Copyright(C) 1999-2021 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * @@ -13,7 +13,8 @@ #include #include -#ifdef _WIN32 +#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || \ + defined(__MINGW32__) || defined(_WIN64) || defined(__MINGW64__) #include #endif diff --git a/packages/seacas/applications/epu/epu.C b/packages/seacas/applications/epu/epu.C index 2026a946d67c..450d5810d237 100644 --- a/packages/seacas/applications/epu/epu.C +++ b/packages/seacas/applications/epu/epu.C @@ -60,9 +60,7 @@ using StringVector = std::vector; #error "Requires exodusII version 4.68 or later" #endif -#ifndef _WIN32 #include "add_to_log.h" -#endif // The main program templated to permit float/double transfer. template @@ -609,12 +607,10 @@ int main(int argc, char *argv[]) } } -#ifndef _WIN32 time_t end_time = std::time(nullptr); if (rank == 0) { add_to_log(argv[0], static_cast(end_time - begin_time)); } -#endif return (error); } catch (std::exception &e) { diff --git a/packages/seacas/applications/exodiff/ED_Version.h b/packages/seacas/applications/exodiff/ED_Version.h index 3eebded4e792..ee1403ca83c5 100644 --- a/packages/seacas/applications/exodiff/ED_Version.h +++ b/packages/seacas/applications/exodiff/ED_Version.h @@ -6,7 +6,7 @@ #ifndef ED_Version_h #define ED_Version_h -static std::string version("3.20"); -static std::string verdate("2021-09-23"); +static std::string version("3.21"); +static std::string verdate("2021-10-06"); #endif // ED_Version_h diff --git a/packages/seacas/applications/exodiff/exoII_read.h b/packages/seacas/applications/exodiff/exoII_read.h index c184c0d97419..b2f3778fbbe8 100644 --- a/packages/seacas/applications/exodiff/exoII_read.h +++ b/packages/seacas/applications/exodiff/exoII_read.h @@ -8,8 +8,6 @@ #define EXOII_READ_H #include "exo_entity.h" -#include "exodusII.h" -#include "netcdf.h" #include #include diff --git a/packages/seacas/applications/exodiff/exodiff.C b/packages/seacas/applications/exodiff/exodiff.C index 9451f8fcd53f..f3d17fe8ac99 100644 --- a/packages/seacas/applications/exodiff/exodiff.C +++ b/packages/seacas/applications/exodiff/exodiff.C @@ -185,6 +185,12 @@ void output_summary(ExoII_Read &file1, MinMaxData &mm_time, std::vector &mm_eb, std::vector &mm_fb, const INT *node_id_map, const INT *elem_id_map); +#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || \ + defined(__MINGW32__) || defined(_WIN64) || defined(__MINGW64__) +#define __ED_WINDOWS__ 1 +#endif + +#if !defined(__ED_WINDOWS__) #include // bit of a hack to get GNU's functions to enable floating point error trapping #ifdef LINUX @@ -197,9 +203,10 @@ void output_summary(ExoII_Read &file1, MinMaxData &mm_time, std::vector &file, int step, const std::vector & size_t global_elmt_index = 0; for (size_t b = 0; b < file.Num_Element_Blocks(); ++b) { Exo_Block *eblock = file.Get_Element_Block_by_Index(b); - const double * vals = get_validated_variable(eblock, step, vidx, name, &diff_flag); + const double *vals = get_validated_variable(eblock, step, vidx, name, &diff_flag); if (vals == nullptr) { global_elmt_index += eblock->Size(); continue; @@ -1888,7 +1895,7 @@ bool diff_nodeset(ExoII_Read &file1, ExoII_Read &file2, int step1, con for (size_t b = 0; b < file1.Num_Node_Sets(); ++b) { Node_Set *nset1 = file1.Get_Node_Set_by_Index(b); - const double * vals1 = get_validated_variable(nset1, step1, vidx1, name, &diff_flag); + const double *vals1 = get_validated_variable(nset1, step1, vidx1, name, &diff_flag); if (vals1 == nullptr) { continue; } @@ -1958,9 +1965,9 @@ bool diff_nodeset(ExoII_Read &file1, ExoII_Read &file2, int step1, con if (!interFace.quiet_flag) { Node_Set *nset = file1.Get_Node_Set_by_Id(max_diff.blk); std::string buf = fmt::format( - " {:<{}} {} diff: {:14.7e} ~ {:14.7e} ={:12.5e} (set {}, node {})", name, - name_length(), interFace.ns_var[e_idx].abrstr(), max_diff.val1, max_diff.val2, - max_diff.diff, max_diff.blk, id_map[nset->Node_Id(max_diff.id) - 1]); + " {:<{}} {} diff: {:14.7e} ~ {:14.7e} ={:12.5e} (set {}, node {})", name, + name_length(), interFace.ns_var[e_idx].abrstr(), max_diff.val1, max_diff.val2, + max_diff.diff, max_diff.blk, id_map[nset->Node_Id(max_diff.id) - 1]); DIFF_OUT(buf); } else { @@ -2068,10 +2075,10 @@ bool diff_sideset(ExoII_Read &file1, ExoII_Read &file2, int step1, con if (!interFace.quiet_flag) { Side_Set *sset = file1.Get_Side_Set_by_Id(max_diff.blk); std::string buf = fmt::format( - " {:<{}} {} diff: {:14.7e} ~ {:14.7e} ={:12.5e} (set {}, side {}.{})", name, - name_length(), interFace.ss_var[e_idx].abrstr(), max_diff.val1, max_diff.val2, - max_diff.diff, max_diff.blk, id_map[sset->Side_Id(max_diff.id).first - 1], - (int)sset->Side_Id(max_diff.id).second); + " {:<{}} {} diff: {:14.7e} ~ {:14.7e} ={:12.5e} (set {}, side {}.{})", name, + name_length(), interFace.ss_var[e_idx].abrstr(), max_diff.val1, max_diff.val2, + max_diff.diff, max_diff.blk, id_map[sset->Side_Id(max_diff.id).first - 1], + (int)sset->Side_Id(max_diff.id).second); DIFF_OUT(buf); } else { @@ -2254,7 +2261,7 @@ bool diff_edgeblock(ExoII_Read &file1, ExoII_Read &file2, int step1, c for (size_t b = 0; b < file1.Num_Edge_Blocks(); ++b) { Edge_Block *eblock1 = file1.Get_Edge_Block_by_Index(b); - const double * vals1 = get_validated_variable(eblock1, step1, vidx1, name, &diff_flag); + const double *vals1 = get_validated_variable(eblock1, step1, vidx1, name, &diff_flag); if (vals1 == nullptr) { continue; } @@ -2322,9 +2329,9 @@ bool diff_edgeblock(ExoII_Read &file1, ExoII_Read &file2, int step1, c if (!interFace.quiet_flag) { Edge_Block *eblock = file1.Get_Edge_Block_by_Id(max_diff.blk); std::string buf = fmt::format( - " {:<{}} {} diff: {:14.7e} ~ {:14.7e} ={:12.5e} (edge block {}, edge {})", name, - name_length(), interFace.eb_var[e_idx].abrstr(), max_diff.val1, max_diff.val2, - max_diff.diff, max_diff.blk, eblock->Edge_Index(max_diff.id) + 1); + " {:<{}} {} diff: {:14.7e} ~ {:14.7e} ={:12.5e} (edge block {}, edge {})", name, + name_length(), interFace.eb_var[e_idx].abrstr(), max_diff.val1, max_diff.val2, + max_diff.diff, max_diff.blk, eblock->Edge_Index(max_diff.id) + 1); DIFF_OUT(buf); } else { @@ -2363,7 +2370,7 @@ bool diff_faceblock(ExoII_Read &file1, ExoII_Read &file2, int step1, c for (size_t b = 0; b < file1.Num_Face_Blocks(); ++b) { Face_Block *fblock1 = file1.Get_Face_Block_by_Index(b); - const double * vals1 = get_validated_variable(fblock1, step1, vidx1, name, &diff_flag); + const double *vals1 = get_validated_variable(fblock1, step1, vidx1, name, &diff_flag); if (vals1 == nullptr) { continue; } @@ -2445,7 +2452,7 @@ bool diff_faceblock(ExoII_Read &file1, ExoII_Read &file2, int step1, c } template -bool diff_element_attributes(ExoII_Read &file1, ExoII_Read & file2, +bool diff_element_attributes(ExoII_Read &file1, ExoII_Read &file2, const std::vector & /*elmt_map*/, const INT *id_map, Exo_Block ** /*blocks2*/) { @@ -2686,8 +2693,8 @@ void output_summary(ExoII_Read &file1, MinMaxData &mm_time, std::vector 0) { fmt::print("\nSIDESET VARIABLES relative 1.e-6 floor 0.0\n"); for (i = 0; i < n; ++i) { - Side_Set * ssmin = file1.Get_Side_Set_by_Id(mm_ss[i].min_blk); - Side_Set * ssmax = file1.Get_Side_Set_by_Id(mm_ss[i].max_blk); + Side_Set *ssmin = file1.Get_Side_Set_by_Id(mm_ss[i].min_blk); + Side_Set *ssmax = file1.Get_Side_Set_by_Id(mm_ss[i].max_blk); std::pair min_side = ssmin->Side_Id(mm_ss[i].min_id); std::pair max_side = ssmax->Side_Id(mm_ss[i].max_id); fmt::print("\t{:<{}} # min: {:15.8g} @ t{},s{},f{}.{}\tmax: {:15.8g} @ t{},s{}" diff --git a/packages/seacas/applications/nem_slice/elb_inp.C b/packages/seacas/applications/nem_slice/elb_inp.C index ff443359d490..be9147e6da9b 100644 --- a/packages/seacas/applications/nem_slice/elb_inp.C +++ b/packages/seacas/applications/nem_slice/elb_inp.C @@ -19,7 +19,8 @@ #include "elb_inp.h" #include "elb_util.h" // for strip_string, token_compare, etc #include "fmt/ostream.h" -#if defined(_WIN64) || defined(WIN32) || defined(_WINDOWS) || defined(_MSC_VER) +#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || \ + defined(__MINGW32__) || defined(_WIN64) || defined(__MINGW64__) #include "XGetopt.h" #include #else @@ -67,13 +68,13 @@ template int cmd_line_arg_parse(int argc, char *argv[], std::string &exoII_inp_f template int cmd_line_arg_parse(int argc, char *argv[], /* Args as passed by main() */ - std::string & exoII_inp_file, /* The input ExodusII file name */ - std::string & ascii_inp_file, /* The ASCII input file name */ - std::string & nemI_out_file, /* Output NemesisI file name */ - Machine_Description * machine, /* Structure for machine description */ - LB_Description * lb, /* Structure for load balance description */ - Problem_Description * prob, /* Structure for various problem params */ - Solver_Description * solver, /* Structure for eigen solver params */ + std::string &exoII_inp_file, /* The input ExodusII file name */ + std::string &ascii_inp_file, /* The ASCII input file name */ + std::string &nemI_out_file, /* Output NemesisI file name */ + Machine_Description *machine, /* Structure for machine description */ + LB_Description *lb, /* Structure for load balance description */ + Problem_Description *prob, /* Structure for various problem params */ + Solver_Description *solver, /* Structure for eigen solver params */ Weight_Description *weight /* Structure for weighting graph */ ) { @@ -83,7 +84,7 @@ int cmd_line_arg_parse(int argc, char *argv[], /* Args as passe int wgt; int max_dim = 0; int i; - char * sub_opt = nullptr, *value = nullptr, *cptr = nullptr, *cptr2 = nullptr; + char *sub_opt = nullptr, *value = nullptr, *cptr = nullptr, *cptr2 = nullptr; std::string ctemp; /* see NOTE in elb.h about the order of the following array */ @@ -174,7 +175,8 @@ int cmd_line_arg_parse(int argc, char *argv[], /* Args as passe case 'w': /* Weighting options */ sub_opt = optarg; -#if defined(_WIN64) || defined(WIN32) || defined(_WINDOWS) || defined(_MSC_VER) +#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || \ + defined(__MINGW32__) || defined(_WIN64) || defined(__MINGW64__) fprintf(stderr, "Windows build does not use getsubopt yet...\n"); exit(1); #else @@ -369,7 +371,8 @@ int cmd_line_arg_parse(int argc, char *argv[], /* Args as passe if (sub_opt != nullptr) { string_to_lower(sub_opt, '\0'); } -#if defined(_WIN64) || defined(WIN32) || defined(_WINDOWS) || defined(_MSC_VER) +#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || \ + defined(__MINGW32__) || defined(_WIN64) || defined(__MINGW64__) fprintf(stderr, "Windows build does not use getsubopt yet...\n"); exit(1); #else @@ -474,7 +477,8 @@ int cmd_line_arg_parse(int argc, char *argv[], /* Args as passe if (sub_opt != nullptr) { string_to_lower(sub_opt, '\0'); } -#if defined(_WIN64) || defined(WIN32) || defined(_WINDOWS) || defined(_MSC_VER) +#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || \ + defined(__MINGW32__) || defined(_WIN64) || defined(__MINGW64__) fprintf(stderr, "Windows build does not use getsubopt yet...\n"); exit(1); #else @@ -570,7 +574,8 @@ int cmd_line_arg_parse(int argc, char *argv[], /* Args as passe if (sub_opt != nullptr) { string_to_lower(sub_opt, '\0'); } -#if defined(_WIN64) || defined(WIN32) || defined(_WINDOWS) || defined(_MSC_VER) +#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || \ + defined(__MINGW32__) || defined(_WIN64) || defined(__MINGW64__) fprintf(stderr, "Windows build does not use getsubopt yet...\n"); exit(1); #else @@ -683,11 +688,11 @@ int read_cmd_file(std::string &ascii_inp_file, std::string &exoII_inp_file, Problem_Description *problem, Solver_Description *solver, Weight_Description *weight) { - FILE * inp_fd; + FILE *inp_fd; std::string ctemp; char inp_line[MAX_INP_LINE]; char inp_copy[MAX_INP_LINE]; - char * cptr, *cptr2; + char *cptr, *cptr2; int iret; int el_blk; diff --git a/packages/seacas/applications/nem_slice/elb_main.C b/packages/seacas/applications/nem_slice/elb_main.C index 3f69ab49e01a..c27da49cc4cd 100644 --- a/packages/seacas/applications/nem_slice/elb_main.C +++ b/packages/seacas/applications/nem_slice/elb_main.C @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2021y National Technology & Engineering Solutions + * Copyright(C) 1999-2021 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * diff --git a/packages/seacas/applications/nem_spread/nem_spread.C b/packages/seacas/applications/nem_spread/nem_spread.C index 9c80beb81b0d..a0c451fd5fb3 100644 --- a/packages/seacas/applications/nem_spread/nem_spread.C +++ b/packages/seacas/applications/nem_spread/nem_spread.C @@ -25,7 +25,8 @@ #include #include // for getopt, optarg, optind -#if defined(_WIN64) || defined(WIN32) || defined(_WINDOWS) || defined(_MSC_VER) +#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || \ + defined(__MINGW32__) || defined(_WIN64) || defined(__MINGW64__) #include "XGetopt.h" #else #include "getopt.h" // for getopt diff --git a/packages/seacas/cmake/Dependencies.cmake b/packages/seacas/cmake/Dependencies.cmake index b2fbfd3805d7..be59628054e9 100644 --- a/packages/seacas/cmake/Dependencies.cmake +++ b/packages/seacas/cmake/Dependencies.cmake @@ -42,7 +42,7 @@ TRIBITS_PACKAGE_DEFINE_DEPENDENCIES( Nemslice applications/nem_slice PT OPTIONAL Nemspread applications/nem_spread PT OPTIONAL Numbers applications/numbers PT OPTIONAL - Slice applications/slice EX OPTIONAL + Slice applications/slice ST OPTIONAL Txtexo applications/txtexo PT OPTIONAL Ex2ex1v2 applications/ex2ex1v2 PT OPTIONAL ) diff --git a/packages/seacas/libraries/aprepro_lib/CMakeLists.txt b/packages/seacas/libraries/aprepro_lib/CMakeLists.txt index 1da7d53bdec0..795e979d77cd 100644 --- a/packages/seacas/libraries/aprepro_lib/CMakeLists.txt +++ b/packages/seacas/libraries/aprepro_lib/CMakeLists.txt @@ -35,7 +35,6 @@ SET(HEADERS SET(SOURCES apr_aprepro.cc apr_util.cc - apr_stats.cc apr_init.cc apr_builtin.cc apr_units.cc diff --git a/packages/seacas/libraries/aprepro_lib/apr_aprepro.cc b/packages/seacas/libraries/aprepro_lib/apr_aprepro.cc index 59f8e5b0fe33..240ab17bf9bb 100644 --- a/packages/seacas/libraries/aprepro_lib/apr_aprepro.cc +++ b/packages/seacas/libraries/aprepro_lib/apr_aprepro.cc @@ -4,13 +4,12 @@ // // See packages/seacas/LICENSE for details -#include "apr_scanner.h" // for Scanner -#include "apr_stats.h" // for Stats +#include "apr_scanner.h" // for Scanner +#include "apr_symrec.h" +#include "apr_util.h" #include "aprepro.h" // for Aprepro, symrec, file_rec, etc #include "aprepro_parser.h" // for Parser, Parser::token, etc #include "terminal_color.h" -#include // for INT_MAX -#include // for size_t #include // for exit, EXIT_SUCCESS, etc #include // for strcmp #include // for operator<<, basic_ostream, etc @@ -18,13 +17,22 @@ #include // for left, cerr, cout, streampos #include // for stack #include +#include #include // for string, operator==, etc #include #include // for allocator, vector +#define HASHSIZE 5939 + +#define USE_ROBIN_MAP +#if defined USE_ROBIN_MAP +#include +#else +#include +#endif + namespace { - const unsigned int HASHSIZE = 5939; - const char * version_string = "5.30 (2021/09/13)"; + const char *version_string = "6.02 (2021/09/30)"; void output_copyright(); @@ -41,24 +49,45 @@ namespace { } return value; } +} // namespace - unsigned hash_symbol(const char *symbol) +namespace SEAMS { + struct Symtable { - unsigned hashval; - for (hashval = 0; *symbol != '\0'; symbol++) { - hashval = *symbol + 65599 * hashval; + Symtable() = default; + ~Symtable() + { + for (auto &sym : sym_table) { + auto &ptr = sym.second; + delete ptr; + } } - return (hashval % HASHSIZE); - } -} // namespace -namespace SEAMS { + void add(const std::string &name, SEAMS::symrec *ptr) { sym_table[name] = ptr; } + void erase(const std::string &name) { sym_table.erase(name); } + SEAMS::symrec *getsym(const char *sym_name) + { + auto ptr = sym_table.find(sym_name); + if (ptr != sym_table.end()) { + return ptr->second; + } + return nullptr; + } + +#if defined USE_ROBIN_MAP + tsl::robin_pg_map sym_table{HASHSIZE}; + const tsl::robin_pg_map &get() { return sym_table; } +#else + std::unordered_map sym_table{HASHSIZE}; + const std::unordered_map &get() { return sym_table; } +#endif + }; + Aprepro *aprepro = nullptr; // A global for use in the library. Clean this up... bool echo = true; - Aprepro::Aprepro() + Aprepro::Aprepro() : sym_table(new Symtable()) { - sym_table.resize(HASHSIZE); ap_file_list.push(file_rec()); init_table("$"); aprepro = this; @@ -80,13 +109,6 @@ namespace SEAMS { delete lexer; - for (unsigned hashval = 0; hashval < HASHSIZE; hashval++) { - for (symrec *ptr = sym_table[hashval]; ptr != nullptr;) { - symrec *save = ptr; - ptr = ptr->next; - delete save; - } - } aprepro = nullptr; for (auto &arr_mem : array_allocations) { @@ -99,6 +121,12 @@ namespace SEAMS { std::string Aprepro::version() { return version_string; } + std::string Aprepro::long_version() const + { + auto comment = getsym("_C_")->value.svar; + return comment + " Algebraic Preprocessor (Aprepro) version " + version(); + } + void Aprepro::clear_results() { parsingResults.str(""); @@ -396,10 +424,7 @@ namespace SEAMS { } auto ptr = new symrec(sym_name, parser_type, is_internal); - - unsigned hashval = hash_symbol(ptr->name.c_str()); - ptr->next = sym_table[hashval]; - sym_table[hashval] = ptr; + sym_table->add(sym_name, ptr); return ptr; } @@ -622,29 +647,27 @@ namespace SEAMS { { std::vector names; - for (unsigned int hashval = 0; hashval < HASHSIZE; hashval++) { - for (symrec *ptr = sym_table[hashval]; ptr != nullptr; ptr = ptr->next) { - if (ptr->isInternal != doInternal) { - continue; - } + for (const auto &sym : sym_table->get()) { + const auto &ptr = sym.second; + if (ptr->isInternal != doInternal) { + continue; + } - switch (ptr->type) { - case Parser::token::VAR: - case Parser::token::IMMVAR: - case Parser::token::SVAR: - case Parser::token::IMMSVAR: - case Parser::token::AVAR: - // Add to our vector - names.push_back(ptr->name); - break; - - default: - // Do nothing - break; - } + switch (ptr->type) { + case Parser::token::VAR: + case Parser::token::IMMVAR: + case Parser::token::SVAR: + case Parser::token::IMMSVAR: + case Parser::token::AVAR: + // Add to our vector + names.push_back(ptr->name); + break; + + default: + // Do nothing + break; } } - return names; } @@ -658,51 +681,15 @@ namespace SEAMS { (ptr->type == Parser::token::IMMSVAR) || (ptr->type == Parser::token::UNDVAR)); if (is_valid_variable) { - int hashval = hash_symbol(sym_name.c_str()); - symrec *hash_ptr = sym_table[hashval]; - - // Handle the case if the variable we want to delete is first in the - // linked list. - if (ptr == hash_ptr) { - // NOTE: If ptr is the only thing in the linked list, ptr->next will be - // nullptr, which is what we want in sym_table when we delete ptr. - sym_table[hashval] = ptr->next; - delete ptr; - } - - // Handle the case where the variable we want to delete is somewhere - // in the middle or at the end of the linked list. - else { - // Find the preceding ptr (singly linked list). - // NOTE: We don't have a check for nullptr here because the fact that - // ptr != hash_ptr tells us that we must have more than one item in our - // linked list, in which case hash_ptr->next will not be nullptr until we - // reach the end of the list. hash_ptr->next should be equal to ptr - // before that happens. - while (hash_ptr->next != ptr) { - hash_ptr = hash_ptr->next; - } - - // NOTE: If ptr is at the end of the list ptr->next will be nullptr, in - // which case this will change hash_ptr to be the end of the list. - hash_ptr->next = ptr->next; - delete ptr; - } + sym_table->erase(sym_name); + delete ptr; } else { warning("Variable '" + sym_name + "' not defined.\n", false); } } - symrec *Aprepro::getsym(const char *sym_name) const - { - for (symrec *ptr = sym_table[hash_symbol(sym_name)]; ptr != nullptr; ptr = ptr->next) { - if (strcmp(ptr->name.c_str(), sym_name) == 0) { - return ptr; - } - } - return nullptr; - } + symrec *Aprepro::getsym(const char *sym_name) const { return sym_table->getsym(sym_name); } symrec *Aprepro::getsym(const std::string &sym_name) const { return getsym(sym_name.c_str()); } @@ -723,21 +710,21 @@ namespace SEAMS { (*infoStream) << "\n{\n"; bool first = true; - for (unsigned hashval = 0; hashval < HASHSIZE; hashval++) { - for (symrec *ptr = sym_table[hashval]; ptr != nullptr; ptr = ptr->next) { - if (!ptr->isInternal) { - if (first) { - first = false; - } - else { - (*infoStream) << ",\n"; - } - if (ptr->type == Parser::token::VAR || ptr->type == Parser::token::IMMVAR) { - (*infoStream) << "\"" << ptr->name << "\": " << std::setprecision(10) << ptr->value.var; - } - else if (ptr->type == Parser::token::SVAR || ptr->type == Parser::token::IMMSVAR) { - (*infoStream) << "\"" << ptr->name << "\": \"" << ptr->value.svar << "\""; - } + for (const auto &sym : sym_table->get()) { + const auto &ptr = sym.second; + + if (!ptr->isInternal) { + if (first) { + first = false; + } + else { + (*infoStream) << ",\n"; + } + if (ptr->type == Parser::token::VAR || ptr->type == Parser::token::IMMVAR) { + (*infoStream) << "\"" << ptr->name << "\": " << std::setprecision(10) << ptr->value.var; + } + else if (ptr->type == Parser::token::SVAR || ptr->type == Parser::token::IMMSVAR) { + (*infoStream) << "\"" << ptr->name << "\": \"" << ptr->value.svar << "\""; } } } @@ -757,48 +744,47 @@ namespace SEAMS { (*infoStream) << "\n" << comment << " Variable = Value" << '\n'; int width = 10; // controls spacing/padding for the variable names - for (unsigned hashval = 0; hashval < HASHSIZE; hashval++) { - for (symrec *ptr = sym_table[hashval]; ptr != nullptr; ptr = ptr->next) { - if (pre == nullptr || ptr->name.find(spre) != std::string::npos) { - if (doInternal == ptr->isInternal) { - if (ptr->type == Parser::token::VAR) { + for (const auto &sym : sym_table->get()) { + const auto &ptr = sym.second; + if (pre == nullptr || ptr->name.find(spre) != std::string::npos) { + if (doInternal == ptr->isInternal) { + if (ptr->type == Parser::token::VAR) { + (*infoStream) << comment << " {" << std::left << std::setw(width) << ptr->name + << "\t= " << std::setprecision(10) << ptr->value.var << "}" << '\n'; + } + else if (ptr->type == Parser::token::IMMVAR) { + (*infoStream) << comment << " {" << std::left << std::setw(width) << ptr->name + << "\t= " << std::setprecision(10) << ptr->value.var << "} (immutable)" + << '\n'; + } + else if (ptr->type == Parser::token::SVAR) { + if (strchr(ptr->value.svar.c_str(), '\n') != nullptr || + strchr(ptr->value.svar.c_str(), '"') != nullptr) { (*infoStream) << comment << " {" << std::left << std::setw(width) << ptr->name - << "\t= " << std::setprecision(10) << ptr->value.var << "}" << '\n'; + << "\t= '" << ptr->value.svar << "'}" << '\n'; } - else if (ptr->type == Parser::token::IMMVAR) { + else { (*infoStream) << comment << " {" << std::left << std::setw(width) << ptr->name - << "\t= " << std::setprecision(10) << ptr->value.var - << "}\t(immutable)" << '\n'; - } - else if (ptr->type == Parser::token::SVAR) { - if (strchr(ptr->value.svar.c_str(), '\n') != nullptr || - strchr(ptr->value.svar.c_str(), '"') != nullptr) { - (*infoStream) << comment << " {" << std::left << std::setw(width) << ptr->name - << "\t= '" << ptr->value.svar << "'}" << '\n'; - } - else { - (*infoStream) << comment << " {" << std::left << std::setw(width) << ptr->name - << "\t= \"" << ptr->value.svar << "\"}" << '\n'; - } + << "\t= \"" << ptr->value.svar << "\"}" << '\n'; } - else if (ptr->type == Parser::token::IMMSVAR) { - if (strchr(ptr->value.svar.c_str(), '\n') != nullptr || - strchr(ptr->value.svar.c_str(), '"') != nullptr) { - (*infoStream) << comment << " {" << std::left << std::setw(width) << ptr->name - << "\t= '" << ptr->value.svar << "'}\t(immutable)" << '\n'; - } - else { - (*infoStream) << comment << " {" << std::left << std::setw(width) << ptr->name - << "\t= \"" << ptr->value.svar << "\"}\t(immutable)" << '\n'; - } + } + else if (ptr->type == Parser::token::IMMSVAR) { + if (strchr(ptr->value.svar.c_str(), '\n') != nullptr || + strchr(ptr->value.svar.c_str(), '"') != nullptr) { + (*infoStream) << comment << " {" << std::left << std::setw(width) << ptr->name + << "\t= '" << ptr->value.svar << "'} (immutable)" << '\n'; } - else if (ptr->type == Parser::token::AVAR) { - array *arr = ptr->value.avar; + else { (*infoStream) << comment << " {" << std::left << std::setw(width) << ptr->name - << "\t (array) rows = " << arr->rows << ", cols = " << arr->cols - << "} " << '\n'; + << "\t= \"" << ptr->value.svar << "\"} (immutable)" << '\n'; } } + else if (ptr->type == Parser::token::AVAR) { + array *arr = ptr->value.avar; + (*infoStream) << comment << " {" << std::left << std::setw(width) << ptr->name + << "\t (array) rows = " << arr->rows << ", cols = " << arr->cols << "} " + << '\n'; + } } } } @@ -807,38 +793,35 @@ namespace SEAMS { type == Parser::token::AFNCT) { int fwidth = 20; // controls spacing/padding for the function names (*infoStream) << trmclr::blue << "\nFunctions returning double:" << trmclr::normal << '\n'; - for (unsigned hashval = 0; hashval < HASHSIZE; hashval++) { - for (symrec *ptr = sym_table[hashval]; ptr != nullptr; ptr = ptr->next) { - if (pre == nullptr || ptr->name.find(spre) != std::string::npos) { - if (ptr->type == Parser::token::FNCT) { - (*infoStream) << std::left << trmclr::green << std::setw(fwidth) << ptr->syntax - << trmclr::normal << ": " << ptr->info << '\n'; - } + for (const auto &sym : sym_table->get()) { + const auto &ptr = sym.second; + if (pre == nullptr || ptr->name.find(spre) != std::string::npos) { + if (ptr->type == Parser::token::FNCT) { + (*infoStream) << std::left << trmclr::green << std::setw(fwidth) << ptr->syntax + << trmclr::normal << ": " << ptr->info << '\n'; } } } (*infoStream) << trmclr::blue << trmclr::blue << "\nFunctions returning string:" << trmclr::normal << '\n'; - for (unsigned hashval = 0; hashval < HASHSIZE; hashval++) { - for (symrec *ptr = sym_table[hashval]; ptr != nullptr; ptr = ptr->next) { - if (pre == nullptr || ptr->name.find(spre) != std::string::npos) { - if (ptr->type == Parser::token::SFNCT) { - (*infoStream) << std::left << trmclr::green << std::setw(fwidth) << ptr->syntax - << trmclr::normal << ": " << ptr->info << '\n'; - } + for (const auto &sym : sym_table->get()) { + const auto &ptr = sym.second; + if (pre == nullptr || ptr->name.find(spre) != std::string::npos) { + if (ptr->type == Parser::token::SFNCT) { + (*infoStream) << std::left << trmclr::green << std::setw(fwidth) << ptr->syntax + << trmclr::normal << ": " << ptr->info << '\n'; } } } (*infoStream) << trmclr::blue << "\nFunctions returning array:" << trmclr::normal << '\n'; - for (unsigned hashval = 0; hashval < HASHSIZE; hashval++) { - for (symrec *ptr = sym_table[hashval]; ptr != nullptr; ptr = ptr->next) { - if (pre == nullptr || ptr->name.find(spre) != std::string::npos) { - if (ptr->type == Parser::token::AFNCT) { - (*infoStream) << std::left << trmclr::green << std::setw(fwidth) << ptr->syntax - << trmclr::normal << ": " << ptr->info << '\n'; - } + for (const auto &sym : sym_table->get()) { + const auto &ptr = sym.second; + if (pre == nullptr || ptr->name.find(spre) != std::string::npos) { + if (ptr->type == Parser::token::AFNCT) { + (*infoStream) << std::left << trmclr::green << std::setw(fwidth) << ptr->syntax + << trmclr::normal << ": " << ptr->info << '\n'; } } } @@ -848,57 +831,9 @@ namespace SEAMS { #define min(x, y) ((x) < (y) ? (x) : (y)) #define max(x, y) ((x) > (y) ? (x) : (y)) -#define MAXLEN 16 void Aprepro::statistics(std::ostream *out) const { - std::ostream *output = out; - if (output == nullptr) { - output = &std::cout; - } - - unsigned entries = 0; - int maxlen = 0; - int minlen = INT_MAX; - int longer = 0; - Stats stats; - - std::vector lengths(MAXLEN); - - for (unsigned hashval = 0; hashval < HASHSIZE; hashval++) { - int chain_len = 0; - for (symrec *ptr = sym_table[hashval]; ptr != nullptr; ptr = ptr->next) { - chain_len++; - } - - entries += chain_len; - if (chain_len >= MAXLEN) { - ++longer; - } - else { - ++lengths[chain_len]; - } - - minlen = min(minlen, chain_len); - maxlen = max(maxlen, chain_len); - - if (chain_len > 0) { - stats.newsample(chain_len); - } - } - - (*output) << entries << " entries in " << HASHSIZE << " element hash table, " << lengths[0] - << " (" << (static_cast(lengths[0]) / HASHSIZE) * 100.0 << "%) empty.\n" - << "Mean (nonempty) chain length = " << stats.mean() << ", max = " << maxlen - << ", min = " << minlen << ", deviation = " << stats.deviation() << "\n"; - - for (int i = 0; i < MAXLEN; i++) { - if (lengths[i] != 0) { - (*output) << lengths[i] << " chain(s) of length " << i << "\n"; - } - if (longer != 0) { - (*output) << longer << " chain(s) of length " << MAXLEN << " or longer\n"; - } - } + (*out) << "Statistics function no longer supported.\n"; } void Aprepro::add_history(const std::string &original, const std::string &substitution) diff --git a/packages/seacas/libraries/aprepro_lib/apr_array.cc b/packages/seacas/libraries/aprepro_lib/apr_array.cc index e9820284f5fb..4a61465bede8 100644 --- a/packages/seacas/libraries/aprepro_lib/apr_array.cc +++ b/packages/seacas/libraries/aprepro_lib/apr_array.cc @@ -4,8 +4,10 @@ // // See packages/seacas/LICENSE for details +#include "apr_symrec.h" #include "aprepro.h" // for array, Aprepro, etc -#include // for vector + +#include // for vector namespace SEAMS { extern SEAMS::Aprepro *aprepro; diff --git a/packages/seacas/libraries/aprepro_lib/apr_builtin.cc b/packages/seacas/libraries/aprepro_lib/apr_builtin.cc index 0815ebcc9715..16e54ccff726 100644 --- a/packages/seacas/libraries/aprepro_lib/apr_builtin.cc +++ b/packages/seacas/libraries/aprepro_lib/apr_builtin.cc @@ -5,6 +5,7 @@ // See packages/seacas/LICENSE for details #include "apr_builtin.h" +#include "apr_symrec.h" #include #include @@ -14,17 +15,16 @@ #include #include #include -#include -#include +#include #include +#include #include #include +#include -#include -#ifdef _WIN32 +#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || \ + defined(__MINGW32__) || defined(_WIN64) || defined(__MINGW64__) #include -#else -#include #endif #include "apr_scanner.h" #include "apr_tokenize.h" @@ -60,7 +60,8 @@ namespace { void reset_error() { -#ifndef _WIN32 +#if !defined(WIN32) && !defined(__WIN32__) && !defined(_WIN32) && !defined(_MSC_VER) && \ + !defined(__MINGW32__) && !defined(_WIN64) && !defined(__MINGW64__) #ifndef math_errhandling #define math_errhandling MATH_ERRNO #endif diff --git a/packages/seacas/libraries/aprepro_lib/apr_exodus.cc b/packages/seacas/libraries/aprepro_lib/apr_exodus.cc index 9fcbef7d29da..e81b841feb82 100644 --- a/packages/seacas/libraries/aprepro_lib/apr_exodus.cc +++ b/packages/seacas/libraries/aprepro_lib/apr_exodus.cc @@ -8,6 +8,7 @@ #include "aprepro.h" #include "exodusII.h" +#include "apr_symrec.h" #include "apr_util.h" #include "aprepro_parser.h" diff --git a/packages/seacas/libraries/aprepro_lib/apr_getline_int.c b/packages/seacas/libraries/aprepro_lib/apr_getline_int.c index f50a6b1a1419..3f8ceb0e5783 100644 --- a/packages/seacas/libraries/aprepro_lib/apr_getline_int.c +++ b/packages/seacas/libraries/aprepro_lib/apr_getline_int.c @@ -1,4 +1,3 @@ - /* * Copyright (C) 1991, 1992, 1993, 2020, 2021 by Chris Thewalt (thewalt@ce.berkeley.edu) * @@ -19,117 +18,53 @@ * Note: This version has been updated by Mike Gleason */ -#if defined(_WIN64) || defined(WIN32) || defined(_WINDOWS) || defined(_MSC_VER) +#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || \ + defined(__MINGW32__) || defined(_WIN64) || defined(__MINGW64__) #define __windows__ 1 #include -#include -#include #include -#include -#include #define NOMINMAX #include -#define strcasecmp stricmp -#define strncasecmp strnicmp #define sleep(a) Sleep(a * 1000) -#ifndef S_ISREG -#define S_ISREG(m) (((m)&_S_IFMT) == _S_IFREG) -#define S_ISDIR(m) (((m)&_S_IFMT) == _S_IFDIR) -#endif -#ifndef open -#define open _open +#ifndef write #define write _write #define read _read -#define close _close -#define lseek _lseek -#define stat _stat -#define lstat _stat -#define fstat _fstat -#define dup _dup -#define utime _utime -#define utimbuf _utimbuf -#endif -#ifndef unlink -#define unlink remove #endif -#define NO_SIGNALS 1 -#define LOCAL_PATH_DELIM '\\' -#define LOCAL_PATH_DELIM_STR "\\" -#define LOCAL_PATH_ALTDELIM '/' -#define IsLocalPathDelim(c) ((c == LOCAL_PATH_DELIM) || (c == LOCAL_PATH_ALTDELIM)) -#define UNC_PATH_PREFIX "\\\\" -#define IsUNCPrefixed(s) (IsLocalPathDelim(s[0]) && IsLocalPathDelim(s[1])) -#define pid_t int #else +#ifndef __unix__ #define __unix__ 1 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#define HAVE_TERMIOS_H 1 -#ifdef HAVE_TERMIOS_H /* use HAVE_TERMIOS_H interface */ +#endif + #include struct termios new_termios, old_termios; -#else /* not HAVE_TERMIOS_H */ -#include -#ifdef TIOCSETN /* use BSD interface */ -#include -struct sgttyb new_tty, old_tty; -struct tchars tch; -struct ltchars ltch; -#else /* use SYSV interface */ -#include -struct termio new_termio, old_termio; -#endif /* TIOCSETN */ -#endif /* HAVE_TERMIOS_H */ -#define LOCAL_PATH_DELIM '/' -#define LOCAL_PATH_DELIM_STR "/" -#define _StrFindLocalPathDelim(a) strchr(a, LOCAL_PATH_DELIM) -#define _StrRFindLocalPathDelim(a) strrchr(a, LOCAL_PATH_DELIM) -#define IsLocalPathDelim(c) (c == LOCAL_PATH_DELIM) #endif /********************* C library headers ********************************/ #include -#include +#include #include #include #include -#include -#include -#include #include -extern int kill(pid_t pid, int sig); - -#define _ap_getline_c_ 1 #include "apr_getline_int.h" -static int ap_gl_tab(char *buf, int offset, int *loc, size_t bufsize); +#define AP_GL_BUF_SIZE 1024 /******************** external interface *********************************/ -ap_gl_in_hook_proc ap_gl_in_hook = NULL; -ap_gl_out_hook_proc ap_gl_out_hook = NULL; -ap_gl_tab_hook_proc ap_gl_tab_hook = ap_gl_tab; -ap_gl_strlen_proc ap_gl_strlen = (ap_gl_strlen_proc)strlen; -ap_gl_tab_completion_proc ap_gl_completion_proc = NULL; -int ap_gl_filename_quoting_desired = -1; /* default to unspecified */ -const char * ap_gl_filename_quote_characters = " \t*?<>|;&()[]$`"; -int ap_gl_ellipses_during_completion = 1; -int ap_gl_completion_exact_match_extra_char; -char ap_gl_buf[AP_GL_BUF_SIZE]; /* input buffer */ +int ap_gl_filename_quoting_desired = -1; /* default to unspecified */ +const char *ap_gl_filename_quote_characters = " \t*?<>|;&()[]$`"; +int ap_gl_ellipses_during_completion = 1; +char ap_gl_buf[AP_GL_BUF_SIZE]; /* input buffer */ /******************** internal interface *********************************/ +#define AP_GL_BUF_SIZE 1024 + static int ap_gl_init_done = -1; /* terminal mode flag */ static int ap_gl_termw = 80; /* actual terminal width */ static int ap_gl_scroll = 27; /* width of EOL scrolling region */ @@ -139,15 +74,7 @@ static int ap_gl_overwrite = 0; /* overwrite mode */ static int ap_gl_pos, ap_gl_cnt = 0; /* position and size of input */ static char ap_gl_killbuf[AP_GL_BUF_SIZE] = ""; /* killed text */ static const char *ap_gl_prompt; /* to save the prompt string */ -static char ap_gl_intrc = 0; /* keyboard SIGINT char */ -static char ap_gl_quitc = 0; /* keyboard SIGQUIT char */ -static char ap_gl_suspc = 0; /* keyboard SIGTSTP char */ -static char ap_gl_dsuspc = 0; /* delayed SIGTSTP char */ -static int ap_gl_search_mode = 0; /* search mode flag */ -static char ** ap_gl_matchlist = NULL; -static char * ap_gl_home_dir = NULL; -static int ap_gl_vi_preferred = -1; -static int ap_gl_vi_mode = 0; +static int ap_gl_search_mode = 0; /* search mode flag */ static void ap_gl_init(void); /* prepare to edit a line */ static void ap_gl_cleanup(void); /* to undo ap_gl_init */ @@ -159,18 +86,15 @@ static void ap_gl_addchar(int c); /* install specified char */ static void ap_gl_del(int loc, int); /* del, either left (-1) or cur (0) */ static void ap_gl_error(const char *const buf); /* write error msg and die */ static void ap_gl_fixup(const char *prompt, int change, - int cursor); /* fixup state variables and screen */ -static int ap_gl_getc(void); /* read one char from terminal */ -static int ap_gl_getcx(int); /* read one char from terminal, if available before timeout */ -static void ap_gl_kill(int pos); /* delete to EOL */ -static void ap_gl_newline(void); /* handle \n or \r */ -static void ap_gl_putc(int c); /* write one char to terminal */ + int cursor); /* fixup state variables and screen */ +static int ap_gl_getc(void); /* read one char from terminal */ +static void ap_gl_kill(int pos); /* delete to EOL */ +static void ap_gl_newline(void); /* handle \n or \r */ +static void ap_gl_putc(int c); /* write one char to terminal */ static void ap_gl_puts(const char *const buf); /* write a line to terminal */ static void ap_gl_redraw(void); /* issue \n and redraw all */ static void ap_gl_transpose(void); /* transpose two chars */ static void ap_gl_yank(void); /* yank killed text */ -static void ap_gl_word(int direction); /* move a word */ -static void ap_gl_killword(int direction); static void hist_init(void); /* initializes hist pointers */ static char *hist_next(void); /* return ptr to next item */ @@ -183,8 +107,6 @@ static void search_back(int new_search); /* look back for current string */ static void search_forw(int new_search); /* look forw for current string */ static void ap_gl_beep(void); /* try to play a system beep sound */ -static int ap_gl_do_tab_completion(char *buf, int *loc, size_t bufsize, int tabtab); - static char *copy_string(char *dest, char const *source, long int elements) { char *d; @@ -204,16 +126,7 @@ static char *copy_string(char *dest, char const *source, long int elements) static void ap_gl_char_init(void) /* turn off input echo */ { #ifdef __unix__ -#ifdef HAVE_TERMIOS_H /* Use POSIX */ tcgetattr(0, &old_termios); - ap_gl_intrc = old_termios.c_cc[VINTR]; - ap_gl_quitc = old_termios.c_cc[VQUIT]; -#ifdef VSUSP - ap_gl_suspc = old_termios.c_cc[VSUSP]; -#endif -#ifdef VDSUSP - ap_gl_dsuspc = old_termios.c_cc[VDSUSP]; -#endif new_termios = old_termios; new_termios.c_iflag &= ~(BRKINT | ISTRIP | IXON | IXOFF); new_termios.c_iflag |= (IGNBRK | IGNPAR); @@ -221,43 +134,13 @@ static void ap_gl_char_init(void) /* turn off input echo */ new_termios.c_cc[VMIN] = 1; new_termios.c_cc[VTIME] = 0; tcsetattr(0, TCSANOW, &new_termios); -#elif defined(TIOCSETN) /* BSD */ - ioctl(0, TIOCGETC, &tch); - ioctl(0, TIOCGLTC, <ch); - ap_gl_intrc = tch.t_intrc; - ap_gl_quitc = tch.t_quitc; - ap_gl_suspc = ltch.t_suspc; - ap_gl_dsuspc = ltch.t_dsuspc; - ioctl(0, TIOCGETP, &old_tty); - new_tty = old_tty; - new_tty.sg_flags |= RAW; - new_tty.sg_flags &= ~ECHO; - ioctl(0, TIOCSETN, &new_tty); -#else /* SYSV */ - ioctl(0, TCGETA, &old_termio); - ap_gl_intrc = old_termio.c_cc[VINTR]; - ap_gl_quitc = old_termio.c_cc[VQUIT]; - new_termio = old_termio; - new_termio.c_iflag &= ~(BRKINT | ISTRIP | IXON | IXOFF); - new_termio.c_iflag |= (IGNBRK | IGNPAR); - new_termio.c_lflag &= ~(ICANON | ISIG | ECHO); - new_termio.c_cc[VMIN] = 1; - new_termio.c_cc[VTIME] = 0; - ioctl(0, TCSETA, &new_termio); -#endif #endif /* __unix__ */ } static void ap_gl_char_cleanup(void) /* undo effects of ap_gl_char_init */ { #ifdef __unix__ -#ifdef HAVE_TERMIOS_H tcsetattr(0, TCSANOW, &old_termios); -#elif defined(TIOCSETN) /* BSD */ - ioctl(0, TIOCSETN, &old_tty); -#else /* SYSV */ - ioctl(0, TCSETA, &old_termio); -#endif #endif /* __unix__ */ } @@ -348,78 +231,6 @@ static int ap_gl_getc(void) return c; } -#ifdef __unix__ - -static int ap_gl_getcx(int tlen) -/* Get a character without echoing it to screen, timing out - * after tlen tenths of a second. - */ -{ - for (errno = 0;;) { - fd_set ss; - FD_ZERO(&ss); - FD_SET(0, &ss); /* set STDIN_FILENO */ - - struct timeval tv; - tv.tv_sec = tlen / 10; - tv.tv_usec = (tlen % 10) * 100000L; - - int result = select(1, &ss, NULL, NULL, &tv); - if (result == 1) { - /* ready */ - break; - } - if (result == 0) { - errno = ETIMEDOUT; - return (-2); - } - else if (errno != EINTR) { - return (-1); - } - } - - for (errno = 0;;) { - char ch; - int c = read(0, &ch, 1); - if (c == 1) { - return ((int)ch); - } - if (errno != EINTR) { - break; - } - } - - return (-1); -} /* ap_gl_getcx */ - -#endif /* __unix__ */ - -#ifdef __windows__ - -static int ap_gl_getcx(int tlen) -{ - int i, c; - - c = (-2); - tlen -= 2; /* Adjust for 200ms overhead */ - if (tlen < 1) - tlen = 1; - for (i = 0; i < tlen; i++) { - if (_kbhit()) { - c = (int)_getch(); - if ((c == 0) || (c == 0xE0)) { - /* Read key code */ - c = (int)_getch(); - c = pc_keymap(c); - } - } - (void)SleepEx((DWORD)(tlen * 100), FALSE); - } - return (c); -} /* ap_gl_getcx */ - -#endif /* __windows__ */ - static void ap_gl_putc(int c) { char ch = (char)(unsigned char)c; @@ -460,7 +271,6 @@ static void ap_gl_init(void) ap_gl_setwidth(w); } hist_init(); - ap_gl_completion_proc = ap_gl_local_filename_completion_proc; } if (isatty(0) == 0 || isatty(1) == 0) ap_gl_error("\n*** Error: getline(): not interactive, use stdio.\n"); @@ -495,178 +305,20 @@ void ap_gl_setwidth(int w) char *ap_getline_int(char *prompt) { - int c, loc, tmp, lastch; - int vi_count, count; - int vi_delete; - char vi_countbuf[32]; - char *cp; - -#ifdef __unix__ - int sig; -#endif - - /* Even if it appears that "vi" is preferred, we - * don't start in ap_gl_vi_mode. They need to hit - * ESC to go into vi command mode. - */ - ap_gl_vi_mode = 0; - vi_count = 0; - vi_delete = 0; - if (ap_gl_vi_preferred < 0) { - ap_gl_vi_preferred = 0; - cp = (char *)getenv("EDITOR"); - if (cp != NULL) - ap_gl_vi_preferred = (strstr(cp, "vi") != NULL); - } - ap_gl_init(); ap_gl_prompt = (prompt) ? prompt : ""; ap_gl_buf[0] = '\0'; - if (ap_gl_in_hook) - ap_gl_in_hook(ap_gl_buf); ap_gl_fixup(ap_gl_prompt, -2, AP_GL_BUF_SIZE); - lastch = 0; #ifdef __windows__ FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE)); #endif + int c; while ((c = ap_gl_getc()) >= 0) { ap_gl_extent = 0; /* reset to full extent */ if (isprint(c)) { - if (ap_gl_vi_mode > 0) { - /* "vi" emulation -- far from perfect, - * but reasonably functional. - */ - vi: - for (count = 0;;) { - if (isdigit(c)) { - if (vi_countbuf[sizeof(vi_countbuf) - 2] == '\0') - vi_countbuf[strlen(vi_countbuf)] = (char)c; - } - else if (vi_countbuf[0] != '\0') { - vi_count = atoi(vi_countbuf); - memset(vi_countbuf, 0, sizeof(vi_countbuf)); - } - switch (c) { - case 'b': ap_gl_word(-1); break; - case 'w': - if (vi_delete) { - ap_gl_killword(1); - } - else { - ap_gl_word(1); - } - break; - case 'h': /* left */ - if (vi_delete) { - if (ap_gl_pos > 0) { - ap_gl_fixup(ap_gl_prompt, -1, ap_gl_pos - 1); - ap_gl_del(0, 1); - } - } - else { - ap_gl_fixup(ap_gl_prompt, -1, ap_gl_pos - 1); - } - break; - case ' ': - case 'l': /* right */ - if (vi_delete) { - ap_gl_del(0, 1); - } - else { - ap_gl_fixup(ap_gl_prompt, -1, ap_gl_pos + 1); - } - break; - case 'k': /* up */ - copy_string(ap_gl_buf, hist_prev(), AP_GL_BUF_SIZE); - if (ap_gl_in_hook) - ap_gl_in_hook(ap_gl_buf); - ap_gl_fixup(ap_gl_prompt, 0, AP_GL_BUF_SIZE); - break; - case 'j': /* down */ - copy_string(ap_gl_buf, hist_next(), AP_GL_BUF_SIZE); - if (ap_gl_in_hook) - ap_gl_in_hook(ap_gl_buf); - ap_gl_fixup(ap_gl_prompt, 0, AP_GL_BUF_SIZE); - break; - case 'd': - if (vi_delete == 1) { - ap_gl_kill(0); - vi_count = 1; - vi_delete = 0; - ap_gl_vi_mode = 0; - goto vi_break; - } - else { - vi_delete = 1; - goto vi_break; - } - break; - case '^': /* start of line */ - if (vi_delete) { - vi_count = ap_gl_pos; - ap_gl_fixup(ap_gl_prompt, -1, 0); - for (c = 0; c < vi_count; c++) { - if (ap_gl_cnt > 0) - ap_gl_del(0, 0); - } - vi_count = 1; - vi_delete = 0; - } - else { - ap_gl_fixup(ap_gl_prompt, -1, 0); - } - break; - case '$': /* end of line */ - if (vi_delete) { - ap_gl_kill(ap_gl_pos); - } - else { - loc = (int)strlen(ap_gl_buf); - if (loc > 1) - loc--; - ap_gl_fixup(ap_gl_prompt, -1, loc); - } - break; - case 'p': /* paste after */ - ap_gl_fixup(ap_gl_prompt, -1, ap_gl_pos + 1); - ap_gl_yank(); - break; - case 'P': /* paste before */ ap_gl_yank(); break; - case 'r': /* replace character */ - ap_gl_buf[ap_gl_pos] = (char)ap_gl_getc(); - ap_gl_fixup(ap_gl_prompt, ap_gl_pos, ap_gl_pos); - vi_count = 1; - break; - case 'R': - ap_gl_overwrite = 1; - ap_gl_vi_mode = 0; - break; - case 'i': - case 'I': - ap_gl_overwrite = 0; - ap_gl_vi_mode = 0; - break; - case 'o': - case 'O': - case 'a': - case 'A': - ap_gl_overwrite = 0; - ap_gl_fixup(ap_gl_prompt, -1, ap_gl_pos + 1); - ap_gl_vi_mode = 0; - break; - } - count++; - if (count >= vi_count) - break; - } - vi_count = 1; - vi_delete = 0; - vi_break: - continue; - } - else if (ap_gl_search_mode) { + if (ap_gl_search_mode) { search_addchar(c); } else { @@ -722,28 +374,7 @@ char *ap_getline_int(char *prompt) case '\177': ap_gl_del(-1, 0); /* ^H and DEL */ break; - case '\t': /* TAB */ - if (ap_gl_completion_proc) { - tmp = ap_gl_pos; - ap_gl_buf[sizeof(ap_gl_buf) - 1] = '\0'; - loc = ap_gl_do_tab_completion(ap_gl_buf, &tmp, sizeof(ap_gl_buf), (lastch == '\t')); - ap_gl_buf[sizeof(ap_gl_buf) - 1] = '\0'; - if (loc >= 0 || tmp != ap_gl_pos) - ap_gl_fixup(ap_gl_prompt, /* loc */ -2, tmp); - if (lastch == '\t') { - c = 0; - lastch = 0; - } - } - else if (ap_gl_tab_hook) { - tmp = ap_gl_pos; - ap_gl_buf[sizeof(ap_gl_buf) - 1] = '\0'; - loc = ap_gl_tab_hook(ap_gl_buf, (int)ap_gl_strlen(ap_gl_prompt), &tmp, sizeof(ap_gl_buf)); - ap_gl_buf[sizeof(ap_gl_buf) - 1] = '\0'; - if (loc >= 0 || tmp != ap_gl_pos) - ap_gl_fixup(ap_gl_prompt, loc, tmp); - } - break; + case '\t': /* TAB */ break; case '\013': ap_gl_kill(ap_gl_pos); /* ^K */ break; @@ -752,8 +383,6 @@ char *ap_getline_int(char *prompt) break; case '\016': /* ^N */ copy_string(ap_gl_buf, hist_next(), AP_GL_BUF_SIZE); - if (ap_gl_in_hook) - ap_gl_in_hook(ap_gl_buf); ap_gl_fixup(ap_gl_prompt, 0, AP_GL_BUF_SIZE); break; case '\017': @@ -761,8 +390,6 @@ char *ap_getline_int(char *prompt) break; case '\020': /* ^P */ copy_string(ap_gl_buf, hist_prev(), AP_GL_BUF_SIZE); - if (ap_gl_in_hook) - ap_gl_in_hook(ap_gl_buf); ap_gl_fixup(ap_gl_prompt, 0, AP_GL_BUF_SIZE); break; case '\022': @@ -780,90 +407,12 @@ char *ap_getline_int(char *prompt) case '\031': ap_gl_yank(); /* ^Y */ break; - case '\033': /* ansi arrow keys */ - c = ap_gl_getcx(3); - if (c == '[') { - switch (c = ap_gl_getc()) { - case 'A': /* up */ - copy_string(ap_gl_buf, hist_prev(), AP_GL_BUF_SIZE); - if (ap_gl_in_hook) - ap_gl_in_hook(ap_gl_buf); - ap_gl_fixup(ap_gl_prompt, 0, AP_GL_BUF_SIZE); - break; - case 'B': /* down */ - copy_string(ap_gl_buf, hist_next(), AP_GL_BUF_SIZE); - if (ap_gl_in_hook) - ap_gl_in_hook(ap_gl_buf); - ap_gl_fixup(ap_gl_prompt, 0, AP_GL_BUF_SIZE); - break; - case 'C': - ap_gl_fixup(ap_gl_prompt, -1, ap_gl_pos + 1); /* right */ - break; - case 'D': - ap_gl_fixup(ap_gl_prompt, -1, ap_gl_pos - 1); /* left */ - break; - default: - ap_gl_beep(); /* who knows */ - break; - } - } - else if ((ap_gl_vi_preferred == 0) && ((c == 'f') || (c == 'F'))) { - ap_gl_word(1); - } - else if ((ap_gl_vi_preferred == 0) && ((c == 'b') || (c == 'B'))) { - ap_gl_word(-1); - } - else { - /* enter vi command mode */ - if (ap_gl_vi_mode == 0) { - ap_gl_vi_mode = 1; - vi_count = 1; - vi_delete = 0; - memset(vi_countbuf, 0, sizeof(vi_countbuf)); - if (ap_gl_pos > 0) - ap_gl_fixup(ap_gl_prompt, -2, ap_gl_pos - 1); /* left 1 char */ - /* Don't bother if the line is empty. */ - if (ap_gl_cnt > 0) { - /* We still have to use the char read! */ - goto vi; - } - ap_gl_vi_mode = 0; - } - ap_gl_beep(); - } - break; - default: /* check for a terminal signal */ -#ifdef __unix__ - if (c > 0) { /* ignore 0 (reset above) */ - sig = 0; -#ifdef SIGINT - if (c == ap_gl_intrc) - sig = SIGINT; -#endif -#ifdef SIGQUIT - if (c == ap_gl_quitc) - sig = SIGQUIT; -#endif -#ifdef SIGTSTP - if (c == ap_gl_suspc || c == ap_gl_dsuspc) - sig = SIGTSTP; -#endif - if (sig != 0) { - ap_gl_cleanup(); - kill(0, sig); - ap_gl_init(); - ap_gl_redraw(); - c = 0; - } - } -#endif /* __unix__ */ + default: if (c > 0) ap_gl_beep(); break; } } - if (c > 0) - lastch = c; } ap_gl_cleanup(); ap_gl_buf[0] = '\0'; @@ -946,10 +495,6 @@ static void ap_gl_newline(void) if (ap_gl_cnt >= AP_GL_BUF_SIZE - 1) ap_gl_error("\n*** Error: getline(): input buffer overflow\n"); - if (ap_gl_out_hook) { - change = ap_gl_out_hook(ap_gl_buf); - len = strlen(ap_gl_buf); - } if (loc > len) loc = len; ap_gl_fixup(ap_gl_prompt, change, loc); /* must do this before appending \n */ @@ -968,7 +513,7 @@ static void ap_gl_del(int loc, int killsave) { if ((loc == -1 && ap_gl_pos > 0) || (loc == 0 && ap_gl_pos < ap_gl_cnt)) { for (int j = 0, i = ap_gl_pos + loc; i < ap_gl_cnt; i++) { - if ((j == 0) && (killsave != 0) && (ap_gl_vi_mode != 0)) { + if ((j == 0) && (killsave != 0)) { ap_gl_killbuf[0] = ap_gl_buf[i]; ap_gl_killbuf[1] = '\0'; j = 1; @@ -994,66 +539,6 @@ static void ap_gl_kill(int pos) ap_gl_beep(); } -static void ap_gl_killword(int direction) -{ - int pos = ap_gl_pos; - if (direction > 0) { /* forward */ - while (pos < ap_gl_cnt && !isspace(ap_gl_buf[pos])) - pos++; - while (pos < ap_gl_cnt && isspace(ap_gl_buf[pos])) - pos++; - } - else { /* backward */ - if (pos > 0) - pos--; - while (pos > 0 && isspace(ap_gl_buf[pos])) - pos--; - while (pos > 0 && !isspace(ap_gl_buf[pos])) - pos--; - if (pos < ap_gl_cnt && isspace(ap_gl_buf[pos])) /* move onto word */ - pos++; - } - - int startpos = ap_gl_pos; - if (pos < startpos) { - int tmp = pos; - pos = startpos; - startpos = tmp; - } - memcpy(ap_gl_killbuf, ap_gl_buf + startpos, (size_t)(pos - startpos)); - ap_gl_killbuf[pos - startpos] = '\0'; - if (isspace(ap_gl_killbuf[pos - startpos - 1])) - ap_gl_killbuf[pos - startpos - 1] = '\0'; - ap_gl_fixup(ap_gl_prompt, -1, startpos); - for (int i = 0, tmp = pos - startpos; i < tmp; i++) - ap_gl_del(0, 0); -} /* ap_gl_killword */ - -static void ap_gl_word(int direction) - -/* move forward or backward one word */ -{ - int pos = ap_gl_pos; - - if (direction > 0) { /* forward */ - while (pos < ap_gl_cnt && !isspace(ap_gl_buf[pos])) - pos++; - while (pos < ap_gl_cnt && isspace(ap_gl_buf[pos])) - pos++; - } - else { /* backward */ - if (pos > 0) - pos--; - while (pos > 0 && isspace(ap_gl_buf[pos])) - pos--; - while (pos > 0 && !isspace(ap_gl_buf[pos])) - pos--; - if (pos < ap_gl_cnt && isspace(ap_gl_buf[pos])) /* move onto word */ - pos++; - } - ap_gl_fixup(ap_gl_prompt, -1, pos); -} - static void ap_gl_redraw(void) /* emit a newline, reset and redraw prompt and current input line */ { @@ -1096,11 +581,11 @@ static void ap_gl_fixup(const char *prompt, int change, int cursor) ap_gl_puts(prompt); copy_string(last_prompt, prompt, 80); change = 0; - ap_gl_width = ap_gl_termw - ap_gl_strlen(prompt); + ap_gl_width = ap_gl_termw - strlen(prompt); } else if (strcmp(prompt, last_prompt) != 0) { - l1 = ap_gl_strlen(last_prompt); - l2 = ap_gl_strlen(prompt); + l1 = strlen(last_prompt); + l2 = strlen(prompt); ap_gl_cnt = ap_gl_cnt + l1 - l2; copy_string(last_prompt, prompt, 80); ap_gl_putc('\r'); @@ -1192,23 +677,6 @@ static void ap_gl_fixup(const char *prompt, int change, int cursor) ap_gl_pos = cursor; } -static int ap_gl_tab(char *buf, int offset, int *loc, size_t bufsize) -/* default tab handler, acts like tabstops every 8 cols */ -{ - int len = strlen(buf); - int count = 8 - (offset + *loc) % 8; - int i; - for (i = len; i >= *loc; i--) - if (i + count < (int)bufsize) - buf[i + count] = buf[i]; - for (i = 0; i < count; i++) - if (*loc + i < (int)bufsize) - buf[*loc + i] = ' '; - i = *loc; - *loc = i + count; - return i; -} - /******************* History stuff **************************************/ #ifndef HIST_SIZE @@ -1312,46 +780,6 @@ static char *hist_save(char *p) return s; } -void ap_gl_histsavefile(const char *const path) -{ - FILE *fp = fopen(path, -#if defined(__windows__) || defined(MSDOS) - "wt" -#else - "w" -#endif - ); - if (fp != NULL) { - for (int i = 2; i < HIST_SIZE; i++) { - int j = (hist_pos + i) % HIST_SIZE; - const char *p = hist_buf[j]; - if ((p == NULL) || (*p == '\0')) - continue; - fprintf(fp, "%s\n", p); - } - fclose(fp); - } -} /* ap_gl_histsavefile */ - -void ap_gl_histloadfile(const char *const path) -{ - FILE *fp = fopen(path, -#if defined(__windows__) || defined(MSDOS) - "rt" -#else - "r" -#endif - ); - if (fp != NULL) { - char line[256]; - memset(line, 0, sizeof(line)); - while (fgets(line, sizeof(line) - 2, fp) != NULL) { - ap_gl_histadd(line); - } - fclose(fp); - } -} /* ap_gl_histloadfile */ - /******************* Search stuff **************************************/ static char search_prompt[101]; /* prompt includes search string */ @@ -1428,8 +856,6 @@ static void search_term(void) ap_gl_search_mode = 0; if (ap_gl_buf[0] == '\0') /* not found, reset hist list */ hist_pos = hist_last; - if (ap_gl_in_hook) - ap_gl_in_hook(ap_gl_buf); ap_gl_fixup(ap_gl_prompt, 0, ap_gl_pos); } @@ -1511,618 +937,3 @@ static void ap_gl_beep(void) ap_gl_putc('\007'); #endif } /* ap_gl_beep */ - -static int ap_gl_do_tab_completion(char *buf, int *loc, size_t bufsize, int tabtab) -{ - /* Zero out the rest of the buffer, so we can move stuff around - * and know we'll still be NUL-terminated. - */ - size_t llen = strlen(buf); - memset(buf + llen, 0, bufsize - llen); - bufsize -= 4; /* leave room for a NUL, space, and two quotes. */ - char * curposp = buf + *loc; - int wasateol = (*curposp == '\0'); - size_t lenaftercursor = llen - (curposp - buf); - if (ap_gl_ellipses_during_completion != 0) { - char ellipsessave[4]; - memcpy(ellipsessave, curposp, (size_t)4); - memcpy(curposp, "... ", (size_t)4); - ap_gl_fixup(ap_gl_prompt, ap_gl_pos, ap_gl_pos + 3); - memcpy(curposp, ellipsessave, (size_t)4); - } - - int qmode = 0; - char *qstart = NULL; - char *lastspacestart = NULL; - char *matchpfx = NULL; - - char *cp = buf; - while (cp < curposp) { - int c = (int)*cp++; - if (c == '\0') - break; - if ((c == '"') || (c == '\'')) { - if (qmode == c) { - /* closing quote; end it. */ - qstart = NULL; - qmode = 0; - } - else if (qmode != 0) { - /* just treat it as a regular char. */ - } - else { - /* start new quote group. */ - qmode = c; - qstart = cp - 1; - } - } - else if ((isspace(c)) && (qmode == 0)) { - /* found a non-quoted space. */ - lastspacestart = cp - 1; - } - else { - /* regular char */ - } - } - - char *startp; - if (qstart != NULL) - startp = qstart + 1; - else if (lastspacestart != NULL) - startp = lastspacestart + 1; - else - startp = buf; - - cp = startp; - size_t mlen = (curposp - cp); - - matchpfx = (char *)malloc(mlen + 1); - memcpy(matchpfx, cp, mlen); - matchpfx[mlen] = '\0'; - -#define AP_GL_COMPLETE_VECTOR_BLOCK_SIZE 64 - - int nused = 0; - int ntoalloc = AP_GL_COMPLETE_VECTOR_BLOCK_SIZE; - char **newap_gl_matchlist = (char **)malloc((size_t)(sizeof(char *) * (ntoalloc + 1))); - if (newap_gl_matchlist == NULL) { - free(matchpfx); - ap_gl_beep(); - return 0; - } - ap_gl_matchlist = newap_gl_matchlist; - int nalloced = ntoalloc; - for (int i = nused; i <= nalloced; i++) - ap_gl_matchlist[i] = NULL; - - ap_gl_completion_exact_match_extra_char = ' '; - for (;; nused++) { - if (nused == nalloced) { - ntoalloc += AP_GL_COMPLETE_VECTOR_BLOCK_SIZE; - newap_gl_matchlist = - (char **)realloc((char *)ap_gl_matchlist, (size_t)(sizeof(char *) * (ntoalloc + 1))); - if (newap_gl_matchlist == NULL) { - /* not enough memory to expand list -- abort */ - for (int i = 0; i < nused; i++) - free(ap_gl_matchlist[i]); - free(ap_gl_matchlist); - ap_gl_matchlist = NULL; - ap_gl_beep(); - free(matchpfx); - return 0; - } - ap_gl_matchlist = newap_gl_matchlist; - nalloced = ntoalloc; - for (int i = nused; i <= nalloced; i++) - ap_gl_matchlist[i] = NULL; - } - cp = ap_gl_completion_proc(matchpfx, nused); - ap_gl_matchlist[nused] = cp; - if (cp == NULL) - break; - } - - if (ap_gl_ellipses_during_completion != 0) { - ap_gl_fixup(ap_gl_prompt, ap_gl_pos, ap_gl_pos); - ap_gl_puts(" "); - } - - /* We now have an array strings, whose last element is NULL. */ - char *strtoadd = NULL; - char *strtoadd1 = NULL; - - int addquotes = (ap_gl_filename_quoting_desired > 0) || - ((ap_gl_filename_quoting_desired < 0) && - (ap_gl_completion_proc == ap_gl_local_filename_completion_proc)); - - if (nused == 1) { - /* Exactly one match. */ - strtoadd = ap_gl_matchlist[0]; - } - else if ((nused > 1) && (mlen > 0)) { - /* Find the greatest amount that matches. */ - size_t glen = 1; - for (;; glen++) { - int allmatch = 1; - for (int i = 1; i < nused; i++) { - if (ap_gl_matchlist[0][glen] != ap_gl_matchlist[i][glen]) { - allmatch = 0; - break; - } - } - if (allmatch == 0) - break; - } - strtoadd1 = (char *)malloc(glen + 1); - if (strtoadd1 != NULL) { - memcpy(strtoadd1, ap_gl_matchlist[0], glen); - strtoadd1[glen] = '\0'; - strtoadd = strtoadd1; - } - } - - if (strtoadd != NULL) { - if ((qmode == 0) && (addquotes != 0)) { - if (strpbrk(strtoadd, ap_gl_filename_quote_characters) != NULL) { - qmode = (strchr(strtoadd, '"') == NULL) ? '"' : '\''; - memmove(curposp + 1, curposp, lenaftercursor + 1 /* NUL */); - curposp++; - *startp++ = (char)qmode; - } - } - size_t startoff = (size_t)(startp - buf); - size_t amt = strlen(strtoadd); - if ((amt + startoff + lenaftercursor) >= bufsize) - amt = bufsize - (amt + startoff + lenaftercursor); - memmove(curposp + amt - mlen, curposp, lenaftercursor + 1 /* NUL */); - curposp += amt - mlen; - memcpy(startp, strtoadd, amt); - if (nused == 1) { - /* Exact match. */ - if (qmode != 0) { - /* Finish the quoting. */ - memmove(curposp + 1, curposp, lenaftercursor + 1 /* NUL */); - curposp++; - buf[amt + startoff] = (char)qmode; - amt++; - } - memmove(curposp + 1, curposp, lenaftercursor + 1 /* NUL */); - curposp++; - buf[amt + startoff] = (char)ap_gl_completion_exact_match_extra_char; - amt++; - } - else if ((!wasateol) && (!isspace(*curposp))) { - /* Not a full match, but insert a - * space for better readability. - */ - memmove(curposp + 1, curposp, lenaftercursor + 1 /* NUL */); - curposp++; - buf[amt + startoff] = ' '; - } - *loc = (int)(startoff + amt); - - if (strtoadd1 != NULL) - free(strtoadd1); - } - - /* Don't need this any more. */ - for (int i = 0; i < nused; i++) - free(ap_gl_matchlist[i]); - free(ap_gl_matchlist); - ap_gl_matchlist = NULL; - free(matchpfx); - - return 0; -} /* ap_gl_do_tab_completion */ - -void ap_gl_tab_completion(ap_gl_tab_completion_proc proc) -{ - if (proc == NULL) - proc = ap_gl_local_filename_completion_proc; /* default proc */ - ap_gl_completion_proc = proc; -} /* ap_gl_tab_completion */ - -#ifndef _StrFindLocalPathDelim -static char *_StrRFindLocalPathDelim(const char *src) /* TODO: optimize */ -{ - const char *last = NULL; - for (;;) { - int c = *src++; - if (c == '\0') - break; - if (IsLocalPathDelim(c)) - last = src - 1; - } - - return ((char *)last); -} /* StrRFindLocalPathDelim */ -#endif /* Windows */ - -void ap_gl_set_home_dir(const char *homedir) -{ - if (ap_gl_home_dir != NULL) { - free(ap_gl_home_dir); - ap_gl_home_dir = NULL; - } - - if (homedir == NULL) { -#ifdef __windows__ - const char *homedrive = getenv("HOMEDRIVE"); - const char *homepath = getenv("HOMEPATH"); - if ((homedrive != NULL) && (homepath != NULL)) { - size_t len = strlen(homedrive) + strlen(homepath) + 1; - ap_gl_home_dir = (char *)malloc(len); - if (ap_gl_home_dir != NULL) { - copy_string(ap_gl_home_dir, homedrive, len); - strcat(ap_gl_home_dir, homepath); - return; - } - } - - char wdir[64]; - wdir[0] = '\0'; - if (GetWindowsDirectory(wdir, sizeof(wdir) - 1) < 1) - (void)copy_string(wdir, ".", sizeof(wdir)); - else if (wdir[1] == ':') { - wdir[2] = '\\'; - wdir[3] = '\0'; - } - homedir = wdir; -#else - char *cp = (char *)getlogin(); - if (cp == NULL) { - cp = (char *)getenv("LOGNAME"); - if (cp == NULL) - cp = (char *)getenv("USER"); - } - struct passwd *pw = NULL; - if (cp != NULL) - pw = getpwnam(cp); - if (pw == NULL) - pw = getpwuid(getuid()); - if (pw == NULL) - return; /* hell with it */ - homedir = pw->pw_dir; -#endif - } - - size_t len = strlen(homedir) + /* NUL */ 1; - ap_gl_home_dir = (char *)malloc(len); - if (ap_gl_home_dir != NULL) { - memcpy(ap_gl_home_dir, homedir, len); - } -} /* ap_gl_set_home_dir */ - -#ifdef __unix__ - -char *ap_gl_local_filename_completion_proc(const char *start, int idx) -{ - static DIR * dir = NULL; - static int filepfxoffset; - static size_t filepfxlen; - - const char *filepfx; - - if (idx == 0) { - if (dir != NULL) { - /* shouldn't get here! */ - closedir(dir); - dir = NULL; - } - } - - if (dir == NULL) { - char * dirtoopen1 = NULL; - char * cp = _StrRFindLocalPathDelim(start); - const char *dirtoopen; - if (cp == start) { - dirtoopen = LOCAL_PATH_DELIM_STR; /* root dir */ - filepfxoffset = 1; - } - else if (cp == NULL) { - dirtoopen = "."; - filepfxoffset = 0; - } - else { - size_t len = strlen(start) + 1; - dirtoopen1 = (char *)malloc(len); - if (dirtoopen1 == NULL) - return NULL; - memcpy(dirtoopen1, start, len); - len = (cp - start); - dirtoopen1[len] = '\0'; - dirtoopen = dirtoopen1; - filepfxoffset = (int)((cp + 1) - start); - } - - if (strcmp(dirtoopen, "~") == 0) { - if (ap_gl_home_dir == NULL) - ap_gl_set_home_dir(NULL); - if (ap_gl_home_dir == NULL) { - if (dirtoopen1 != NULL) - free(dirtoopen1); - return (NULL); - } - dirtoopen = ap_gl_home_dir; - } - - dir = opendir(dirtoopen); - if (dirtoopen1 != NULL) - free(dirtoopen1); - - filepfx = start + filepfxoffset; - filepfxlen = strlen(filepfx); - } - - if (dir != NULL) { - /* assumes "start" is same for each iteration. */ - filepfx = start + filepfxoffset; - - for (;;) { - struct dirent *dent = readdir(dir); - if (dent == NULL) { - /* no more items */ - closedir(dir); - dir = NULL; - - if (idx == 1) { - /* There was exactly one match. - * In this special case, we - * want to append a / instead - * of a space. - */ - char *cp = ap_gl_matchlist[0]; - if ((cp[0] == '~') && ((cp[1] == '\0') || (IsLocalPathDelim(cp[1])))) { - size_t len = strlen(cp + 1) + /* NUL */ 1; - size_t len2 = strlen(ap_gl_home_dir); - if (IsLocalPathDelim(ap_gl_home_dir[len2 - 1])) - len2--; - cp = (char *)realloc(ap_gl_matchlist[0], len + len2); - if (cp == NULL) { - cp = ap_gl_matchlist[0]; - } - else { - memmove(cp + len2, cp + 1, len); - memcpy(cp, ap_gl_home_dir, len2); - ap_gl_matchlist[0] = cp; - } - } - struct stat st; - if ((stat(cp, &st) == 0) && (S_ISDIR(st.st_mode))) - ap_gl_completion_exact_match_extra_char = LOCAL_PATH_DELIM; - } - return NULL; - } - - const char *name = dent->d_name; - if ((name[0] == '.') && ((name[1] == '\0') || ((name[1] == '.') && (name[2] == '\0')))) - continue; /* Skip . and .. */ - - if ((filepfxlen == 0) || (strncmp(name, filepfx, filepfxlen) == 0)) { - /* match */ - size_t len = strlen(name); - char * cp = (char *)malloc(filepfxoffset + len + 1 /* spare */ + 1 /* NUL */); - *cp = '\0'; - if (filepfxoffset > 0) - memcpy(cp, start, (size_t)filepfxoffset); - memcpy(cp + filepfxoffset, name, len + 1); - return (cp); - } - } - } - - return NULL; -} /* ap_gl_local_filename_completion_proc */ - -#endif /* __unix__ */ - -#ifdef __windows__ - -char *ap_gl_local_filename_completion_proc(const char *start, int idx) -{ - static HANDLE searchHandle = NULL; - static int filepfxoffset; - static size_t filepfxlen; - - WIN32_FIND_DATA ffd; - DWORD dwErr; - char * cp, *c2, ch; - const char * filepfx; - const char * dirtoopen, *name; - char * dirtoopen1, *dirtoopen2; - size_t len, len2; - - if (idx == 0) { - if (searchHandle != NULL) { - /* shouldn't get here! */ - FindClose(searchHandle); - searchHandle = NULL; - } - } - - if (searchHandle == NULL) { - dirtoopen1 = NULL; - dirtoopen2 = NULL; - cp = _StrRFindLocalPathDelim(start); - if (cp == start) { - dirtoopen = LOCAL_PATH_DELIM_STR; /* root dir */ - filepfxoffset = 1; - } - else if (cp == NULL) { - dirtoopen = "."; - filepfxoffset = 0; - } - else { - len = strlen(start) + 1; - dirtoopen1 = (char *)malloc(len); - if (dirtoopen1 == NULL) - return NULL; - memcpy(dirtoopen1, start, len); - len = (cp - start); - dirtoopen1[len] = '\0'; - dirtoopen = dirtoopen1; - filepfxoffset = (int)((cp + 1) - start); - } - - if (strcmp(dirtoopen, "~") == 0) { - if (ap_gl_home_dir == NULL) - ap_gl_set_home_dir(NULL); - if (ap_gl_home_dir == NULL) - return (NULL); - dirtoopen = ap_gl_home_dir; - } - - len = strlen(dirtoopen); - dirtoopen2 = (char *)malloc(len + 8); - if (dirtoopen2 == NULL) { - if (dirtoopen1 != NULL) - free(dirtoopen1); - return NULL; - } - - memcpy(dirtoopen2, dirtoopen, len + 1); - if (dirtoopen2[len - 1] == LOCAL_PATH_DELIM) - memcpy(dirtoopen2 + len, "*.*", (size_t)4); - else - memcpy(dirtoopen2 + len, "\\*.*", (size_t)5); - - /* "Open" the directory. */ - memset(&ffd, 0, sizeof(ffd)); - searchHandle = FindFirstFile(dirtoopen2, &ffd); - - free(dirtoopen2); - if (dirtoopen1 != NULL) - free(dirtoopen1); - - if (searchHandle == INVALID_HANDLE_VALUE) { - return NULL; - } - - filepfx = start + filepfxoffset; - filepfxlen = strlen(filepfx); - } - else { - /* assumes "start" is same for each iteration. */ - filepfx = start + filepfxoffset; - goto next; - } - - for (;;) { - - name = ffd.cFileName; - if ((name[0] == '.') && ((name[1] == '\0') || ((name[1] == '.') && (name[2] == '\0')))) - goto next; /* Skip . and .. */ - - if ((filepfxlen == 0) || (strnicmp(name, filepfx, filepfxlen) == 0)) { - /* match */ - len = strlen(name); - cp = (char *)malloc(filepfxoffset + len + 4 /* spare */ + 1 /* NUL */); - *cp = '\0'; - if (filepfxoffset > 0) - memcpy(cp, start, filepfxoffset); - memcpy(cp + filepfxoffset, name, len + 1); - if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - /* Embed file type with name. */ - c2 = cp + filepfxoffset + len + 1; - *c2++ = '\0'; - *c2++ = 'd'; - *c2 = '\0'; - } - else { - c2 = cp + filepfxoffset + len + 1; - *c2++ = '\0'; - *c2++ = '-'; - *c2 = '\0'; - } - return (cp); - } - - next: - if (!FindNextFile(searchHandle, &ffd)) { - dwErr = GetLastError(); - if (dwErr != ERROR_NO_MORE_FILES) { - FindClose(searchHandle); - searchHandle = NULL; - return NULL; - } - - /* no more items */ - FindClose(searchHandle); - searchHandle = NULL; - - if (idx == 1) { - /* There was exactly one match. - * In this special case, we - * want to append a \ instead - * of a space. - */ - cp = ap_gl_matchlist[0]; - ch = (char)cp[strlen(cp) + 2]; - if (ch == (char)'d') - ap_gl_completion_exact_match_extra_char = LOCAL_PATH_DELIM; - - if ((cp[0] == '~') && ((cp[1] == '\0') || (IsLocalPathDelim(cp[1])))) { - len = strlen(cp + 1) + /* NUL */ 1; - len2 = strlen(ap_gl_home_dir); - if (IsLocalPathDelim(ap_gl_home_dir[len2 - 1])) - len2--; - cp = (char *)realloc(ap_gl_matchlist[0], len + len2 + 4); - if (cp == NULL) { - cp = ap_gl_matchlist[0]; - } - else { - memmove(cp + len2, cp + 1, len); - memcpy(cp, ap_gl_home_dir, len2); - c2 = cp + len + len2; - *c2++ = '\0'; - *c2++ = ch; - *c2 = '\0'; - ap_gl_matchlist[0] = cp; - } - } - } - break; - } - } - return (NULL); -} /* ap_gl_local_filename_completion_proc */ - -char *ap_gl_win_getpass(const char *const prompt, char *const pass, int dsize) -{ - char *cp; - - FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE)); - ZeroMemory(pass, (DWORD)sizeof(dsize)); - dsize--; - - if ((prompt != NULL) && (prompt[0] != '\0')) - _cputs(prompt); - - for (cp = pass;;) { - int c = (int)_getch(); - if ((c == '\r') || (c == '\n')) - break; - if ((c == '\010') || (c == '\177')) { - /* ^H and DEL */ - if (cp > pass) { - *--cp = '\0'; - _putch('\010'); - _putch(' '); - _putch('\010'); - } - } - else if (cp < (pass + dsize)) { - _putch('*'); - *cp++ = c; - } - } - _putch('\r'); - _putch('\n'); - Sleep(40); - FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE)); - - *cp = '\0'; - return (pass); -} /* ap_gl_getpass */ - -#endif /* __windows__ */ diff --git a/packages/seacas/libraries/aprepro_lib/apr_getline_int.h b/packages/seacas/libraries/aprepro_lib/apr_getline_int.h index fed833ea4df9..a14a817cc7a5 100644 --- a/packages/seacas/libraries/aprepro_lib/apr_getline_int.h +++ b/packages/seacas/libraries/aprepro_lib/apr_getline_int.h @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2020 National Technology & Engineering Solutions +// Copyright(C) 1999-2021 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -7,48 +7,13 @@ #ifndef APREPRO_GETLINE_H #define APREPRO_GETLINE_H -/* unix systems can #define POSIX to use termios, otherwise - * the bsd or sysv interface will be used - */ - -#define AP_GL_BUF_SIZE 1024 - #ifdef __cplusplus extern "C" { #endif -typedef size_t (*ap_gl_strwidth_proc)(char *); -typedef int (*ap_gl_in_hook_proc)(char *); -typedef int (*ap_gl_out_hook_proc)(char *); -typedef int (*ap_gl_tab_hook_proc)(char *, int, int *, size_t); -typedef size_t (*ap_gl_strlen_proc)(const char *); -typedef char *(*ap_gl_tab_completion_proc)(const char *, int); - -char *ap_getline_int(char *); /* read a line of input */ -void ap_gl_setwidth(int); /* specify width of screen */ -void ap_gl_histadd(char *); /* adds entries to hist */ -void ap_gl_strwidth(ap_gl_strwidth_proc); /* to bind ap_gl_strlen */ -void ap_gl_tab_completion(ap_gl_tab_completion_proc); -char *ap_gl_local_filename_completion_proc(const char *, int); -void ap_gl_set_home_dir(const char *homedir); -void ap_gl_histsavefile(const char *const path); -void ap_gl_histloadfile(const char *const path); -char *ap_gl_win_getpass(const char *const prompt, char *const pass, int dsize); - -#ifndef _ap_getline_c_ - -extern ap_gl_in_hook_proc ap_gl_in_hook; -extern ap_gl_out_hook_proc ap_gl_out_hook; -extern ap_gl_tab_hook_proc ap_gl_tab_hook; -extern ap_gl_strlen_proc ap_gl_strlen; -extern ap_gl_tab_completion_proc ap_gl_completion_proc; -extern int ap_gl_filename_quoting_desired; -extern const char * ap_gl_filename_quote_characters; -extern int ap_gl_ellipses_during_completion; -extern int ap_gl_completion_exact_match_extra_char; -extern char ap_gl_buf[AP_GL_BUF_SIZE]; - -#endif /* ! _ap_getline_c_ */ +char *ap_getline_int(char *); /* read a line of input */ +void ap_gl_setwidth(int); /* specify width of screen */ +void ap_gl_histadd(char *); /* adds entries to hist */ #ifdef __cplusplus } /* close brackets on extern "C" declaration */ diff --git a/packages/seacas/libraries/aprepro_lib/apr_init.cc b/packages/seacas/libraries/aprepro_lib/apr_init.cc index ead458e6299c..5a58107fb7ab 100644 --- a/packages/seacas/libraries/aprepro_lib/apr_init.cc +++ b/packages/seacas/libraries/aprepro_lib/apr_init.cc @@ -11,6 +11,7 @@ Initialize variables and functions Aprepro ***/ #include "apr_builtin.h" +#include "apr_symrec.h" #include "apr_tokenize.h" #include "aprepro.h" // for symrec, Aprepro, etc #include "init_structs.h" // for array_a_init, array_c_init, etc diff --git a/packages/seacas/libraries/aprepro_lib/apr_parser.cc b/packages/seacas/libraries/aprepro_lib/apr_parser.cc index 0f00c13b9045..0ec1b65fa3c5 100644 --- a/packages/seacas/libraries/aprepro_lib/apr_parser.cc +++ b/packages/seacas/libraries/aprepro_lib/apr_parser.cc @@ -54,7 +54,8 @@ namespace { void reset_error() { -#ifndef _WIN32 +#if !defined(WIN32) && !defined(__WIN32__) && !defined(_WIN32) && !defined(_MSC_VER) && \ + !defined(__MINGW32__) && !defined(_WIN64) && !defined(__MINGW64__) #ifndef math_errhandling #define math_errhandling MATH_ERRNO #endif diff --git a/packages/seacas/libraries/aprepro_lib/apr_stats.cc b/packages/seacas/libraries/aprepro_lib/apr_stats.cc deleted file mode 100644 index 605098943161..000000000000 --- a/packages/seacas/libraries/aprepro_lib/apr_stats.cc +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright(C) 1999-2021 National Technology & Engineering Solutions -// of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with -// NTESS, the U.S. Government retains certain rights in this software. -// -// See packages/seacas/LICENSE for details - -/******************************************************************* - * STATS.C: Statistics routines: - * - * newsample(n): Add a new sample to the mean/average totals. - * mean(): Returns the mean of the samples. - * deviation(): Returns the standard deviation of the sample. - * - ********************************************************************/ - -#include "apr_stats.h" -#include - -namespace SEAMS { - void Stats::newsample(int n) - { - // See Knuth, TAOCP vol 2, 3rd edition, page 232 - double TMean = Mean; - Numnums++; - Mean = TMean + (n - TMean) / Numnums; - - if (Numnums > 1) { - StdDev += (n - TMean) * (n - Mean); - } - } - - double Stats::mean() const { return Mean; } - - double Stats::variance() const { return (Numnums > 1) ? StdDev / (Numnums - 1) : 0.0; } - - double Stats::deviation() const { return std::sqrt(variance()); } -} // namespace SEAMS diff --git a/packages/seacas/libraries/aprepro_lib/apr_stats.h b/packages/seacas/libraries/aprepro_lib/apr_stats.h deleted file mode 100644 index 85af60e4e084..000000000000 --- a/packages/seacas/libraries/aprepro_lib/apr_stats.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright(C) 1999-2020 National Technology & Engineering Solutions - * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with - * NTESS, the U.S. Government retains certain rights in this software. - * - * See packages/seacas/LICENSE for details - */ -#ifndef APR_STATS_H -#define APR_STATS_H - -#include "apr_util.h" // for check_valid_var, new_string, etc - -namespace SEAMS { - class Stats - { - public: - Stats() = default; - - void newsample(int n); - double mean() const; - double deviation() const; - double variance() const; - - private: - size_t Numnums{0}; - double Mean{0.0}; - double StdDev{0.0}; - }; -} // namespace SEAMS -#endif diff --git a/packages/seacas/libraries/aprepro_lib/apr_symrec.h b/packages/seacas/libraries/aprepro_lib/apr_symrec.h new file mode 100644 index 000000000000..b3e569b362b6 --- /dev/null +++ b/packages/seacas/libraries/aprepro_lib/apr_symrec.h @@ -0,0 +1,93 @@ +// Copyright(C) 1999-, 20212021 National Technology & Engineering Solutions +// of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with +// NTESS, the U.S. Government retains certain rights in this software. +// +// See packages/seacas/LICENSE for details + +// Might be good to add a callback function which would be called +// when there was output -- In LexerOutput for example. Default +// could be to just write to std::cout or to resultsOutput stringstream... + +#ifndef APREPRO_SYMREC_H +#define APREPRO_SYMREC_H + +#include +#include + +namespace SEAMS { + struct array + { + std::vector data{}; + int rows{0}; + int cols{0}; + + array(int r, int c) : rows(r), cols(c) { data.resize(r * c); } + + array(const array &) = default; + array() = default; + ~array() = default; + }; + + struct symrec + { + std::string name{}; + std::string syntax{}; + std::string info{}; + int type; + bool isInternal; + struct value + { + double var{0}; + double (*fnctptr)(){nullptr}; + double (*fnctptr_d)(double){nullptr}; + double (*fnctptr_c)(char *){nullptr}; + double (*fnctptr_dc)(double, char *){nullptr}; + double (*fnctptr_cd)(char *, double){nullptr}; + double (*fnctptr_cc)(char *, char *){nullptr}; + double (*fnctptr_dd)(double, double){nullptr}; + double (*fnctptr_ddd)(double, double, double){nullptr}; + double (*fnctptr_ccc)(char *, char *, char *){nullptr}; + double (*fnctptr_ccd)(char *, char *, double){nullptr}; + double (*fnctptr_dddd)(double, double, double, double){nullptr}; + double (*fnctptr_ddddc)(double, double, double, double, char *){nullptr}; + double (*fnctptr_dddddd)(double, double, double, double, double, double){nullptr}; + double (*fnctptr_a)(const array *){nullptr}; + std::string svar{}; + const char *(*strfnct)(){nullptr}; + const char *(*strfnct_c)(char *){nullptr}; + const char *(*strfnct_d)(double){nullptr}; + const char *(*strfnct_a)(const array *){nullptr}; + const char *(*strfnct_dd)(double, double){nullptr}; + const char *(*strfnct_cc)(char *, char *){nullptr}; + const char *(*strfnct_ccc)(char *, char *, char *){nullptr}; + const char *(*strfnct_dcc)(double, char *, char *){nullptr}; + const char *(*strfnct_dcccc)(double, char *, char *, char *, char *){nullptr}; + array *avar{nullptr}; /* Array Variable */ + array *(*arrfnct_c)(const char *){nullptr}; + array *(*arrfnct_cc)(const char *, const char *){nullptr}; + array *(*arrfnct_cd)(const char *, double){nullptr}; + array *(*arrfnct_ddd)(double, double, double){nullptr}; + array *(*arrfnct_dd)(double, double){nullptr}; + array *(*arrfnct_d)(double){nullptr}; + array *(*arrfnct_a)(const array *){nullptr}; + + value() = default; + } value; + symrec *next; + + symrec(const char *my_name, int my_type, bool is_internal = false) + : name(my_name), syntax(my_name), info("UNDEFINED"), type(my_type), isInternal(is_internal), + next(nullptr) + { + value.var = 0; + } + + symrec(const std::string &my_name, int my_type, bool is_internal = false) + : name(my_name), syntax(my_name), info("UNDEFINED"), type(my_type), isInternal(is_internal), + next(nullptr) + { + value.var = 0; + } + }; +} // namespace SEAMS +#endif diff --git a/packages/seacas/libraries/aprepro_lib/apr_test.cc b/packages/seacas/libraries/aprepro_lib/apr_test.cc index f1ec7cbf9dbc..cdb3c4fbe111 100644 --- a/packages/seacas/libraries/aprepro_lib/apr_test.cc +++ b/packages/seacas/libraries/aprepro_lib/apr_test.cc @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2020 National Technology & Engineering Solutions +// Copyright(C) 1999-2021 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -7,6 +7,7 @@ #include #include +#include "apr_symrec.h" #include "aprepro.h" // This function is used below in the example showing how an diff --git a/packages/seacas/libraries/aprepro_lib/apr_util.cc b/packages/seacas/libraries/aprepro_lib/apr_util.cc index 7547fdbbe8eb..5e38b5f02d1c 100644 --- a/packages/seacas/libraries/aprepro_lib/apr_util.cc +++ b/packages/seacas/libraries/aprepro_lib/apr_util.cc @@ -4,34 +4,38 @@ // // See packages/seacas/LICENSE for details +#include "apr_symrec.h" #include "aprepro.h" // for symrec, Aprepro, etc #include "aprepro_parser.h" // for Parser, Parser::token, etc -#include // for isalnum, isalpha, isupper, etc -#include // for errno, EDOM, ERANGE -#include // for fetestexcept, FE_DIVBYZERO, etc -#include // for math_errhandling, etc -#include // for perror -#include // for mkstemp -#include // for strlen, etc -#include // for operator<<, cerr, ostream -#include // for allocator, operator+, etc -#include // for stat, S_ISDIR -#include // for close -#include // for vector - -#ifdef _WIN32 + +#include // for isalnum, isalpha, isupper, etc +#include // for errno, EDOM, ERANGE +#include // for fetestexcept, FE_DIVBYZERO, etc +#include // for math_errhandling, etc +#include // for perror +#include // for mkstemp +#include // for strlen, etc +#include // for operator<<, cerr, ostream +#include // for allocator, operator+, etc +#include // for stat, S_ISDIR +#include // for close +#include // for vector + +#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || \ + defined(__MINGW32__) || defined(_WIN64) || defined(__MINGW64__) #include #include #ifndef NOMINMAX #define NOMINMAX #endif #include -#else -#include // for close -#endif -#if !defined(S_ISDIR) && defined(_WIN32) +#if !defined(S_ISDIR) #define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR) + +#endif +#else +#include // for close #endif namespace { @@ -120,7 +124,8 @@ namespace SEAMS { int fd = mkstemps(tmp_name, 0); if (fd >= 0) close(fd); -#elif defined(_WIN32) +#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || \ + defined(__MINGW32__) || defined(_WIN64) || defined(__MINGW64__) copy_string(tmp_name, _mktemp(tmp_name), strlen(tmp_name) + 1); #else int fd = mkstemp(tmp_name); @@ -173,7 +178,8 @@ namespace SEAMS { void math_error(const SEAMS::Aprepro &apr, const char *function) { -#ifndef _WIN32 +#if !defined(WIN32) && !defined(__WIN32__) && !defined(_WIN32) && !defined(_MSC_VER) && \ + !defined(__MINGW32__) && !defined(_WIN64) && !defined(__MINGW64__) #ifndef math_errhandling #define math_errhandling MATH_ERRNO #endif diff --git a/packages/seacas/libraries/aprepro_lib/apr_util.h b/packages/seacas/libraries/aprepro_lib/apr_util.h index 5547558dbe41..738775537dc4 100644 --- a/packages/seacas/libraries/aprepro_lib/apr_util.h +++ b/packages/seacas/libraries/aprepro_lib/apr_util.h @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2020 National Technology & Engineering Solutions + * Copyright(C) 1999-2021 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * @@ -8,6 +8,7 @@ #ifndef SEAMS_UTIL_H #define SEAMS_UTIL_H +#include "apr_symrec.h" #include "aprepro.h" #include diff --git a/packages/seacas/libraries/aprepro_lib/aprepro.h b/packages/seacas/libraries/aprepro_lib/aprepro.h index d56b2af2a622..2fefa6e2d891 100644 --- a/packages/seacas/libraries/aprepro_lib/aprepro.h +++ b/packages/seacas/libraries/aprepro_lib/aprepro.h @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -28,80 +29,9 @@ * SEAMS::Parser, SEAMS::Scanner and SEAMS::Aprepro */ namespace SEAMS { - struct array - { - std::vector data{}; - int rows{0}; - int cols{0}; - - array(int r, int c) : rows(r), cols(c) { data.resize(r * c); } - - array(const array &) = default; - array() = default; - ~array() = default; - }; - - struct symrec - { - std::string name{}; - std::string syntax{}; - std::string info{}; - int type; - bool isInternal; - struct value - { - double var{0}; - double (*fnctptr)(){nullptr}; - double (*fnctptr_d)(double){nullptr}; - double (*fnctptr_c)(char *){nullptr}; - double (*fnctptr_dc)(double, char *){nullptr}; - double (*fnctptr_cd)(char *, double){nullptr}; - double (*fnctptr_cc)(char *, char *){nullptr}; - double (*fnctptr_dd)(double, double){nullptr}; - double (*fnctptr_ddd)(double, double, double){nullptr}; - double (*fnctptr_ccc)(char *, char *, char *){nullptr}; - double (*fnctptr_ccd)(char *, char *, double){nullptr}; - double (*fnctptr_dddd)(double, double, double, double){nullptr}; - double (*fnctptr_ddddc)(double, double, double, double, char *){nullptr}; - double (*fnctptr_dddddd)(double, double, double, double, double, double){nullptr}; - double (*fnctptr_a)(const array *){nullptr}; - std::string svar{}; - const char *(*strfnct)(){nullptr}; - const char *(*strfnct_c)(char *){nullptr}; - const char *(*strfnct_d)(double){nullptr}; - const char *(*strfnct_a)(const array *){nullptr}; - const char *(*strfnct_dd)(double, double){nullptr}; - const char *(*strfnct_cc)(char *, char *){nullptr}; - const char *(*strfnct_ccc)(char *, char *, char *){nullptr}; - const char *(*strfnct_dcc)(double, char *, char *){nullptr}; - const char *(*strfnct_dcccc)(double, char *, char *, char *, char *){nullptr}; - array *avar{nullptr}; /* Array Variable */ - array *(*arrfnct_c)(const char *){nullptr}; - array *(*arrfnct_cc)(const char *, const char *){nullptr}; - array *(*arrfnct_cd)(const char *, double){nullptr}; - array *(*arrfnct_ddd)(double, double, double){nullptr}; - array *(*arrfnct_dd)(double, double){nullptr}; - array *(*arrfnct_d)(double){nullptr}; - array *(*arrfnct_a)(const array *){nullptr}; - - value() = default; - } value; - symrec *next; - - symrec(const char *my_name, int my_type, bool is_internal = false) - : name(my_name), syntax(my_name), info("UNDEFINED"), type(my_type), isInternal(is_internal), - next(nullptr) - { - value.var = 0; - } - - symrec(const std::string &my_name, int my_type, bool is_internal = false) - : name(my_name), syntax(my_name), info("UNDEFINED"), type(my_type), isInternal(is_internal), - next(nullptr) - { - value.var = 0; - } - }; + struct Symtable; + struct symrec; + struct array; /* Global options */ struct aprepro_options @@ -184,6 +114,9 @@ namespace SEAMS { /** Return string representation of current version of aprepro. */ static std::string version(); + /** Return long version: `# Algebraic Preprocessor (Aprepro) version X.X.X` */ + std::string long_version() const; + /** Invoke the scanner and parser for a stream. * @param in input stream * @param in_name stream name for error messages @@ -281,10 +214,11 @@ namespace SEAMS { array *make_array(const array &from); private: - void init_table(const char *comment); - std::vector sym_table{}; - std::vector array_allocations{}; - std::ostringstream parsingResults{}; + std::unique_ptr sym_table; + + void init_table(const char *comment); + std::vector array_allocations{}; + std::ostringstream parsingResults{}; // Input stream used with parse_string_interactive std::istringstream stringInput{}; diff --git a/packages/seacas/libraries/aprepro_lib/aprepro.yy b/packages/seacas/libraries/aprepro_lib/aprepro.yy index a88b9b833cde..fc214b19c463 100644 --- a/packages/seacas/libraries/aprepro_lib/aprepro.yy +++ b/packages/seacas/libraries/aprepro_lib/aprepro.yy @@ -19,7 +19,8 @@ namespace { void reset_error() { -#ifndef _WIN32 +#if !defined(WIN32) && !defined(__WIN32__) && !defined(_WIN32) && !defined(_MSC_VER) && \ + !defined(__MINGW32__) && !defined(_WIN64) && !defined(__MINGW64__) #ifndef math_errhandling #define math_errhandling MATH_ERRNO #endif diff --git a/packages/seacas/libraries/aprepro_lib/robin_growth_policy.h b/packages/seacas/libraries/aprepro_lib/robin_growth_policy.h new file mode 100644 index 000000000000..4baadcce1263 --- /dev/null +++ b/packages/seacas/libraries/aprepro_lib/robin_growth_policy.h @@ -0,0 +1,403 @@ +/** + * MIT License + * + * Copyright (c) 2017 Thibaut Goetghebuer-Planchon + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef TSL_ROBIN_GROWTH_POLICY_H +#define TSL_ROBIN_GROWTH_POLICY_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef TSL_DEBUG +#define tsl_rh_assert(expr) assert(expr) +#else +#define tsl_rh_assert(expr) (static_cast(0)) +#endif + +/** + * If exceptions are enabled, throw the exception passed in parameter, otherwise + * call std::terminate. + */ +#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || \ + (defined(_MSC_VER) && defined(_CPPUNWIND))) && \ + !defined(TSL_NO_EXCEPTIONS) +#define TSL_RH_THROW_OR_TERMINATE(ex, msg) throw ex(msg) +#else +#define TSL_RH_NO_EXCEPTIONS +#ifdef NDEBUG +#define TSL_RH_THROW_OR_TERMINATE(ex, msg) std::terminate() +#else +#include +#define TSL_RH_THROW_OR_TERMINATE(ex, msg) \ + do { \ + std::cerr << msg << std::endl; \ + std::terminate(); \ + } while (0) +#endif +#endif + +#if defined(__GNUC__) || defined(__clang__) +#define TSL_RH_LIKELY(exp) (__builtin_expect(!!(exp), true)) +#else +#define TSL_RH_LIKELY(exp) (exp) +#endif + +#define TSL_RH_UNUSED(x) static_cast(x) + +namespace tsl { + namespace rh { + + /** + * Grow the hash table by a factor of GrowthFactor keeping the bucket count to a + * power of two. It allows the table to use a mask operation instead of a modulo + * operation to map a hash to a bucket. + * + * GrowthFactor must be a power of two >= 2. + */ + template class power_of_two_growth_policy + { + public: + /** + * Called on the hash table creation and on rehash. The number of buckets for + * the table is passed in parameter. This number is a minimum, the policy may + * update this value with a higher value if needed (but not lower). + * + * If 0 is given, min_bucket_count_in_out must still be 0 after the policy + * creation and bucket_for_hash must always return 0 in this case. + */ + explicit power_of_two_growth_policy(std::size_t &min_bucket_count_in_out) + { + if (min_bucket_count_in_out > max_bucket_count()) { + TSL_RH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); + } + + if (min_bucket_count_in_out > 0) { + min_bucket_count_in_out = round_up_to_power_of_two(min_bucket_count_in_out); + m_mask = min_bucket_count_in_out - 1; + } + else { + m_mask = 0; + } + } + + /** + * Return the bucket [0, bucket_count()) to which the hash belongs. + * If bucket_count() is 0, it must always return 0. + */ + std::size_t bucket_for_hash(std::size_t hash) const noexcept { return hash & m_mask; } + + /** + * Return the number of buckets that should be used on next growth. + */ + std::size_t next_bucket_count() const + { + if ((m_mask + 1) > max_bucket_count() / GrowthFactor) { + TSL_RH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); + } + + return (m_mask + 1) * GrowthFactor; + } + + /** + * Return the maximum number of buckets supported by the policy. + */ + std::size_t max_bucket_count() const + { + // Largest power of two. + return (std::numeric_limits::max() / 2) + 1; + } + + /** + * Reset the growth policy as if it was created with a bucket count of 0. + * After a clear, the policy must always return 0 when bucket_for_hash is + * called. + */ + void clear() noexcept { m_mask = 0; } + + private: + static std::size_t round_up_to_power_of_two(std::size_t value) + { + if (is_power_of_two(value)) { + return value; + } + + if (value == 0) { + return 1; + } + + --value; + for (std::size_t i = 1; i < sizeof(std::size_t) * CHAR_BIT; i *= 2) { + value |= value >> i; + } + + return value + 1; + } + + static constexpr bool is_power_of_two(std::size_t value) + { + return value != 0 && (value & (value - 1)) == 0; + } + + protected: + static_assert(is_power_of_two(GrowthFactor) && GrowthFactor >= 2, + "GrowthFactor must be a power of two >= 2."); + + std::size_t m_mask; + }; + + /** + * Grow the hash table by GrowthFactor::num / GrowthFactor::den and use a modulo + * to map a hash to a bucket. Slower but it can be useful if you want a slower + * growth. + */ + template > class mod_growth_policy + { + public: + explicit mod_growth_policy(std::size_t &min_bucket_count_in_out) + { + if (min_bucket_count_in_out > max_bucket_count()) { + TSL_RH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); + } + + if (min_bucket_count_in_out > 0) { + m_mod = min_bucket_count_in_out; + } + else { + m_mod = 1; + } + } + + std::size_t bucket_for_hash(std::size_t hash) const noexcept { return hash % m_mod; } + + std::size_t next_bucket_count() const + { + if (m_mod == max_bucket_count()) { + TSL_RH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); + } + + const double next_bucket_count = + std::ceil(double(m_mod) * REHASH_SIZE_MULTIPLICATION_FACTOR); + if (!std::isnormal(next_bucket_count)) { + TSL_RH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); + } + + if (next_bucket_count > double(max_bucket_count())) { + return max_bucket_count(); + } + else { + return std::size_t(next_bucket_count); + } + } + + std::size_t max_bucket_count() const { return MAX_BUCKET_COUNT; } + + void clear() noexcept { m_mod = 1; } + + private: + static constexpr double REHASH_SIZE_MULTIPLICATION_FACTOR = + 1.0 * GrowthFactor::num / GrowthFactor::den; + static const std::size_t MAX_BUCKET_COUNT = std::size_t( + double(std::numeric_limits::max() / REHASH_SIZE_MULTIPLICATION_FACTOR)); + + static_assert(REHASH_SIZE_MULTIPLICATION_FACTOR >= 1.1, "Growth factor should be >= 1.1."); + + std::size_t m_mod; + }; + + namespace detail { + +#if SIZE_MAX >= ULLONG_MAX +#define TSL_RH_NB_PRIMES 51 +#elif SIZE_MAX >= ULONG_MAX +#define TSL_RH_NB_PRIMES 40 +#else +#define TSL_RH_NB_PRIMES 23 +#endif + + static constexpr const std::array PRIMES = {{ + 1u, + 5u, + 17u, + 29u, + 37u, + 53u, + 67u, + 79u, + 97u, + 131u, + 193u, + 257u, + 389u, + 521u, + 769u, + 1031u, + 1543u, + 2053u, + 3079u, + 6151u, + 12289u, + 24593u, + 49157u, +#if SIZE_MAX >= ULONG_MAX + 98317ul, + 196613ul, + 393241ul, + 786433ul, + 1572869ul, + 3145739ul, + 6291469ul, + 12582917ul, + 25165843ul, + 50331653ul, + 100663319ul, + 201326611ul, + 402653189ul, + 805306457ul, + 1610612741ul, + 3221225473ul, + 4294967291ul, +#endif +#if SIZE_MAX >= ULLONG_MAX + 6442450939ull, + 12884901893ull, + 25769803751ull, + 51539607551ull, + 103079215111ull, + 206158430209ull, + 412316860441ull, + 824633720831ull, + 1649267441651ull, + 3298534883309ull, + 6597069766657ull, +#endif + }}; + + template static constexpr std::size_t mod(std::size_t hash) + { + return hash % PRIMES[IPrime]; + } + + // MOD_PRIME[iprime](hash) returns hash % PRIMES[iprime]. This table allows for + // faster modulo as the compiler can optimize the modulo code better with a + // constant known at the compilation. + static constexpr const std::array MOD_PRIME = + {{ + &mod<0>, &mod<1>, &mod<2>, &mod<3>, &mod<4>, &mod<5>, &mod<6>, &mod<7>, + &mod<8>, &mod<9>, &mod<10>, &mod<11>, &mod<12>, &mod<13>, &mod<14>, &mod<15>, + &mod<16>, &mod<17>, &mod<18>, &mod<19>, &mod<20>, &mod<21>, &mod<22>, +#if SIZE_MAX >= ULONG_MAX + &mod<23>, &mod<24>, &mod<25>, &mod<26>, &mod<27>, &mod<28>, &mod<29>, &mod<30>, + &mod<31>, &mod<32>, &mod<33>, &mod<34>, &mod<35>, &mod<36>, &mod<37>, &mod<38>, + &mod<39>, +#endif +#if SIZE_MAX >= ULLONG_MAX + &mod<40>, &mod<41>, &mod<42>, &mod<43>, &mod<44>, &mod<45>, &mod<46>, &mod<47>, + &mod<48>, &mod<49>, &mod<50>, +#endif + }}; + + } // namespace detail + + /** + * Grow the hash table by using prime numbers as bucket count. Slower than + * tsl::rh::power_of_two_growth_policy in general but will probably distribute + * the values around better in the buckets with a poor hash function. + * + * To allow the compiler to optimize the modulo operation, a lookup table is + * used with constant primes numbers. + * + * With a switch the code would look like: + * \code + * switch(iprime) { // iprime is the current prime of the hash table + * case 0: hash % 5ul; + * break; + * case 1: hash % 17ul; + * break; + * case 2: hash % 29ul; + * break; + * ... + * } + * \endcode + * + * Due to the constant variable in the modulo the compiler is able to optimize + * the operation by a series of multiplications, substractions and shifts. + * + * The 'hash % 5' could become something like 'hash - (hash * 0xCCCCCCCD) >> 34) + * * 5' in a 64 bits environment. + */ + class prime_growth_policy + { + public: + explicit prime_growth_policy(std::size_t &min_bucket_count_in_out) + { + auto it_prime = + std::lower_bound(detail::PRIMES.begin(), detail::PRIMES.end(), min_bucket_count_in_out); + if (it_prime == detail::PRIMES.end()) { + TSL_RH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); + } + + m_iprime = static_cast(std::distance(detail::PRIMES.begin(), it_prime)); + if (min_bucket_count_in_out > 0) { + min_bucket_count_in_out = *it_prime; + } + else { + min_bucket_count_in_out = 0; + } + } + + std::size_t bucket_for_hash(std::size_t hash) const noexcept + { + return detail::MOD_PRIME[m_iprime](hash); + } + + std::size_t next_bucket_count() const + { + if (m_iprime + 1 >= detail::PRIMES.size()) { + TSL_RH_THROW_OR_TERMINATE(std::length_error, "The hash table exceeds its maximum size."); + } + + return detail::PRIMES[m_iprime + 1]; + } + + std::size_t max_bucket_count() const { return detail::PRIMES.back(); } + + void clear() noexcept { m_iprime = 0; } + + private: + unsigned int m_iprime; + + static_assert(std::numeric_limits::max() >= detail::PRIMES.size(), + "The type of m_iprime is not big enough."); + }; + + } // namespace rh +} // namespace tsl + +#endif diff --git a/packages/seacas/libraries/aprepro_lib/robin_hash.h b/packages/seacas/libraries/aprepro_lib/robin_hash.h new file mode 100644 index 000000000000..03bf58bc5a1c --- /dev/null +++ b/packages/seacas/libraries/aprepro_lib/robin_hash.h @@ -0,0 +1,1587 @@ +/** + * MIT License + * + * Copyright (c) 2017 Thibaut Goetghebuer-Planchon + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef TSL_ROBIN_HASH_H +#define TSL_ROBIN_HASH_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "robin_growth_policy.h" + +namespace tsl { + + namespace detail_robin_hash { + + template struct make_void + { + using type = void; + }; + + template struct has_is_transparent : std::false_type + { + }; + + template + struct has_is_transparent::type> + : std::true_type + { + }; + + template struct is_power_of_two_policy : std::false_type + { + }; + + template + struct is_power_of_two_policy> + : std::true_type + { + }; + + // Only available in C++17, we need to be compatible with C++11 + template const T &clamp(const T &v, const T &lo, const T &hi) + { + return std::min(hi, std::max(lo, v)); + } + + template + static T numeric_cast(U value, const char *error_message = "numeric_cast() failed.") + { + T ret = static_cast(value); + if (static_cast(ret) != value) { + TSL_RH_THROW_OR_TERMINATE(std::runtime_error, error_message); + } + + const bool is_same_signedness = (std::is_unsigned::value && std::is_unsigned::value) || + (std::is_signed::value && std::is_signed::value); + if (!is_same_signedness && (ret < T{}) != (value < U{})) { + TSL_RH_THROW_OR_TERMINATE(std::runtime_error, error_message); + } + + return ret; + } + + template static T deserialize_value(Deserializer &deserializer) + { + // MSVC < 2017 is not conformant, circumvent the problem by removing the + // template keyword +#if defined(_MSC_VER) && _MSC_VER < 1910 + return deserializer.Deserializer::operator()(); +#else + return deserializer.Deserializer::template operator()(); +#endif + } + + /** + * Fixed size type used to represent size_type values on serialization. Need to + * be big enough to represent a std::size_t on 32 and 64 bits platforms, and + * must be the same size on both platforms. + */ + using slz_size_type = std::uint64_t; + static_assert(std::numeric_limits::max() >= + std::numeric_limits::max(), + "slz_size_type must be >= std::size_t"); + + using truncated_hash_type = std::uint32_t; + + /** + * Helper class that stores a truncated hash if StoreHash is true and nothing + * otherwise. + */ + template class bucket_entry_hash + { + public: + bool bucket_hash_equal(std::size_t /*hash*/) const noexcept { return true; } + + truncated_hash_type truncated_hash() const noexcept { return 0; } + + protected: + void set_hash(truncated_hash_type /*hash*/) noexcept {} + }; + + template <> class bucket_entry_hash + { + public: + bool bucket_hash_equal(std::size_t my_hash) const noexcept + { + return m_hash == truncated_hash_type(my_hash); + } + + truncated_hash_type truncated_hash() const noexcept { return m_hash; } + + protected: + void set_hash(truncated_hash_type my_hash) noexcept { m_hash = truncated_hash_type(my_hash); } + + private: + truncated_hash_type m_hash; + }; + + /** + * Each bucket entry has: + * - A value of type `ValueType`. + * - An integer to store how far the value of the bucket, if any, is from its + * ideal bucket (ex: if the current bucket 5 has the value 'foo' and + * `hash('foo') % nb_buckets` == 3, `dist_from_ideal_bucket()` will return 2 as + * the current value of the bucket is two buckets away from its ideal bucket) If + * there is no value in the bucket (i.e. `empty()` is true) + * `dist_from_ideal_bucket()` will be < 0. + * - A marker which tells us if the bucket is the last bucket of the bucket + * array (useful for the iterator of the hash table). + * - If `StoreHash` is true, 32 bits of the hash of the value, if any, are also + * stored in the bucket. If the size of the hash is more than 32 bits, it is + * truncated. We don't store the full hash as storing the hash is a potential + * opportunity to use the unused space due to the alignment of the bucket_entry + * structure. We can thus potentially store the hash without any extra space + * (which would not be possible with 64 bits of the hash). + */ + template + class bucket_entry : public bucket_entry_hash + { + using bucket_hash = bucket_entry_hash; + + public: + using value_type = ValueType; + using distance_type = std::int16_t; + + bucket_entry() noexcept + : bucket_hash(), m_dist_from_ideal_bucket(EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET) + { + tsl_rh_assert(empty()); + } + + bucket_entry(bool last_bucket) noexcept + : bucket_hash(), m_dist_from_ideal_bucket(EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET), + m_last_bucket(last_bucket) + { + tsl_rh_assert(empty()); + } + + bucket_entry(const bucket_entry &other) noexcept( + std::is_nothrow_copy_constructible::value) + : bucket_hash(other), m_dist_from_ideal_bucket(EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET), + m_last_bucket(other.m_last_bucket) + { + if (!other.empty()) { + ::new (static_cast(std::addressof(m_value))) value_type(other.value()); + m_dist_from_ideal_bucket = other.m_dist_from_ideal_bucket; + } + } + + /** + * Never really used, but still necessary as we must call resize on an empty + * `std::vector`. and we need to support move-only types. See + * robin_hash constructor for details. + */ + bucket_entry(bucket_entry &&other) noexcept( + std::is_nothrow_move_constructible::value) + : bucket_hash(std::move(other)), + m_dist_from_ideal_bucket(EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET), + m_last_bucket(other.m_last_bucket) + { + if (!other.empty()) { + ::new (static_cast(std::addressof(m_value))) value_type(std::move(other.value())); + m_dist_from_ideal_bucket = other.m_dist_from_ideal_bucket; + } + } + + bucket_entry &operator=(const bucket_entry &other) noexcept( + std::is_nothrow_copy_constructible::value) + { + if (this != &other) { + clear(); + + bucket_hash::operator=(other); + if (!other.empty()) { + ::new (static_cast(std::addressof(m_value))) value_type(other.value()); + } + + m_dist_from_ideal_bucket = other.m_dist_from_ideal_bucket; + m_last_bucket = other.m_last_bucket; + } + + return *this; + } + + bucket_entry &operator=(bucket_entry &&) = delete; + + ~bucket_entry() noexcept { clear(); } + + void clear() noexcept + { + if (!empty()) { + destroy_value(); + m_dist_from_ideal_bucket = EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET; + } + } + + bool empty() const noexcept + { + return m_dist_from_ideal_bucket == EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET; + } + + value_type &value() noexcept + { + tsl_rh_assert(!empty()); + return *reinterpret_cast(std::addressof(m_value)); + } + + const value_type &value() const noexcept + { + tsl_rh_assert(!empty()); + return *reinterpret_cast(std::addressof(m_value)); + } + + distance_type dist_from_ideal_bucket() const noexcept { return m_dist_from_ideal_bucket; } + + bool last_bucket() const noexcept { return m_last_bucket; } + + void set_as_last_bucket() noexcept { m_last_bucket = true; } + + template + void set_value_of_empty_bucket(distance_type dist_from_ideal_bucket, + truncated_hash_type my_hash, Args &&...value_type_args) + { + tsl_rh_assert(dist_from_ideal_bucket >= 0); + tsl_rh_assert(empty()); + + ::new (static_cast(std::addressof(m_value))) + value_type(std::forward(value_type_args)...); + this->set_hash(my_hash); + m_dist_from_ideal_bucket = dist_from_ideal_bucket; + + tsl_rh_assert(!empty()); + } + + void swap_with_value_in_bucket(distance_type & dist_from_ideal_bucket, + truncated_hash_type &my_hash, value_type &value) + { + tsl_rh_assert(!empty()); + + using std::swap; + swap(value, this->value()); + swap(dist_from_ideal_bucket, m_dist_from_ideal_bucket); + + if (StoreHash) { + const truncated_hash_type tmp_hash = this->truncated_hash(); + this->set_hash(my_hash); + my_hash = tmp_hash; + } + else { + // Avoid warning of unused variable if StoreHash is false + TSL_RH_UNUSED(my_hash); + } + } + + static truncated_hash_type truncate_hash(std::size_t my_hash) noexcept + { + return truncated_hash_type(my_hash); + } + + private: + void destroy_value() noexcept + { + tsl_rh_assert(!empty()); + value().~value_type(); + } + + public: + static const distance_type EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET = -1; + static const distance_type DIST_FROM_IDEAL_BUCKET_LIMIT = 4096; + static_assert(DIST_FROM_IDEAL_BUCKET_LIMIT <= std::numeric_limits::max() - 1, + "DIST_FROM_IDEAL_BUCKET_LIMIT must be <= " + "std::numeric_limits::max() - 1."); + + private: + using storage = typename std::aligned_storage::type; + + distance_type m_dist_from_ideal_bucket; + bool m_last_bucket{false}; + storage m_value; + }; + + /** + * Internal common class used by `robin_map` and `robin_set`. + * + * ValueType is what will be stored by `robin_hash` (usually `std::pair` + * for map and `Key` for set). + * + * `KeySelect` should be a `FunctionObject` which takes a `ValueType` in + * parameter and returns a reference to the key. + * + * `ValueSelect` should be a `FunctionObject` which takes a `ValueType` in + * parameter and returns a reference to the value. `ValueSelect` should be void + * if there is no value (in a set for example). + * + * The strong exception guarantee only holds if the expression + * `std::is_nothrow_swappable\:\:value && + * std::is_nothrow_move_constructible\:\:value` is true. + * + * Behaviour is undefined if the destructor of `ValueType` throws. + */ + template + class robin_hash : private Hash, private KeyEqual, private GrowthPolicy + { + private: + template + using has_mapped_type = typename std::integral_constant::value>; + + static_assert(noexcept(std::declval().bucket_for_hash(std::size_t(0))), + "GrowthPolicy::bucket_for_hash must be noexcept."); + static_assert(noexcept(std::declval().clear()), + "GrowthPolicy::clear must be noexcept."); + + public: + template class robin_iterator; + + using key_type = typename KeySelect::key_type; + using value_type = ValueType; + using size_type = std::size_t; + using difference_type = std::ptrdiff_t; + using hasher = Hash; + using key_equal = KeyEqual; + using allocator_type = Allocator; + using reference = value_type &; + using const_reference = const value_type &; + using pointer = value_type *; + using const_pointer = const value_type *; + using iterator = robin_iterator; + using const_iterator = robin_iterator; + + private: + /** + * Either store the hash because we are asked by the `StoreHash` template + * parameter or store the hash because it doesn't cost us anything in size and + * can be used to speed up rehash. + */ + static constexpr bool STORE_HASH = + StoreHash || ((sizeof(tsl::detail_robin_hash::bucket_entry) == + sizeof(tsl::detail_robin_hash::bucket_entry)) && + (sizeof(std::size_t) == sizeof(truncated_hash_type) || + is_power_of_two_policy::value) && + // Don't store the hash for primitive types with default hash. + (!std::is_arithmetic::value || + !std::is_same>::value)); + + /** + * Only use the stored hash on lookup if we are explicitly asked. We are not + * sure how slow the KeyEqual operation is. An extra comparison may slow + * things down with a fast KeyEqual. + */ + static constexpr bool USE_STORED_HASH_ON_LOOKUP = StoreHash; + + /** + * We can only use the hash on rehash if the size of the hash type is the same + * as the stored one or if we use a power of two modulo. In the case of the + * power of two modulo, we just mask the least significant bytes, we just have + * to check that the truncated_hash_type didn't truncated more bytes. + */ + static bool USE_STORED_HASH_ON_REHASH(size_type bucket_count) + { + if (STORE_HASH && sizeof(std::size_t) == sizeof(truncated_hash_type)) { + TSL_RH_UNUSED(bucket_count); + return true; + } + else if (STORE_HASH && is_power_of_two_policy::value) { + tsl_rh_assert(bucket_count > 0); + return (bucket_count - 1) <= std::numeric_limits::max(); + } + else { + TSL_RH_UNUSED(bucket_count); + return false; + } + } + + using bucket_entry = tsl::detail_robin_hash::bucket_entry; + using distance_type = typename bucket_entry::distance_type; + + using buckets_allocator = + typename std::allocator_traits::template rebind_alloc; + using buckets_container_type = std::vector; + + public: + /** + * The 'operator*()' and 'operator->()' methods return a const reference and + * const pointer respectively to the stored value type. + * + * In case of a map, to get a mutable reference to the value associated to a + * key (the '.second' in the stored pair), you have to call 'value()'. + * + * The main reason for this is that if we returned a `std::pair&` + * instead of a `const std::pair&`, the user may modify the key which + * will put the map in a undefined state. + */ + template class robin_iterator + { + friend class robin_hash; + + private: + using bucket_entry_ptr = + typename std::conditional::type; + + robin_iterator(bucket_entry_ptr bucket) noexcept : m_bucket(bucket) {} + + public: + using iterator_category = std::forward_iterator_tag; + using value_type = const typename robin_hash::value_type; + using difference_type = std::ptrdiff_t; + using reference = value_type &; + using pointer = value_type *; + + robin_iterator() noexcept {} + + // Copy constructor from iterator to const_iterator. + template ::type * = nullptr> + robin_iterator(const robin_iterator &other) noexcept : m_bucket(other.m_bucket) + { + } + + robin_iterator(const robin_iterator &other) = default; + robin_iterator(robin_iterator &&other) = default; + robin_iterator &operator=(const robin_iterator &other) = default; + robin_iterator &operator=(robin_iterator &&other) = default; + + const typename robin_hash::key_type &key() const { return KeySelect()(m_bucket->value()); } + + template ::value && IsConst>::type * = nullptr> + const typename U::value_type &value() const + { + return U()(m_bucket->value()); + } + + template ::value && !IsConst>::type * = nullptr> + typename U::value_type &value() const + { + return U()(m_bucket->value()); + } + + reference operator*() const { return m_bucket->value(); } + + pointer operator->() const { return std::addressof(m_bucket->value()); } + + robin_iterator &operator++() + { + while (true) { + if (m_bucket->last_bucket()) { + ++m_bucket; + return *this; + } + + ++m_bucket; + if (!m_bucket->empty()) { + return *this; + } + } + } + + robin_iterator operator++(int) + { + robin_iterator tmp(*this); + ++*this; + + return tmp; + } + + friend bool operator==(const robin_iterator &lhs, const robin_iterator &rhs) + { + return lhs.m_bucket == rhs.m_bucket; + } + + friend bool operator!=(const robin_iterator &lhs, const robin_iterator &rhs) + { + return !(lhs == rhs); + } + + private: + bucket_entry_ptr m_bucket; + }; + + public: +#if defined(__cplusplus) && __cplusplus >= 201402L + robin_hash(size_type bucket_count, const Hash &my_hash, const KeyEqual &equal, + const Allocator &alloc, float min_load_factor = DEFAULT_MIN_LOAD_FACTOR, + float max_load_factor = DEFAULT_MAX_LOAD_FACTOR) + : Hash(my_hash), KeyEqual(equal), GrowthPolicy(bucket_count), + m_buckets_data( + [&]() { + if (bucket_count > max_bucket_count()) { + TSL_RH_THROW_OR_TERMINATE(std::length_error, + "The map exceeds its maximum bucket count."); + } + + return bucket_count; + }(), + alloc), + m_buckets(m_buckets_data.empty() ? static_empty_bucket_ptr() : m_buckets_data.data()), + m_bucket_count(bucket_count), m_nb_elements(0), m_grow_on_next_insert(false), + m_try_shrink_on_next_insert(false) + { + if (m_bucket_count > 0) { + tsl_rh_assert(!m_buckets_data.empty()); + m_buckets_data.back().set_as_last_bucket(); + } + + this->min_load_factor(min_load_factor); + this->max_load_factor(max_load_factor); + } +#else + /** + * C++11 doesn't support the creation of a std::vector with a custom allocator + * and 'count' default-inserted elements. The needed contructor `explicit + * vector(size_type count, const Allocator& alloc = Allocator());` is only + * available in C++14 and later. We thus must resize after using the + * `vector(const Allocator& alloc)` constructor. + * + * We can't use `vector(size_type count, const T& value, const Allocator& + * alloc)` as it requires the value T to be copyable. + */ + robin_hash(size_type bucket_count, const Hash &my_hash, const KeyEqual &equal, + const Allocator &alloc, float min_load_factor = DEFAULT_MIN_LOAD_FACTOR, + float max_load_factor = DEFAULT_MAX_LOAD_FACTOR) + : Hash(my_hash), KeyEqual(equal), GrowthPolicy(bucket_count), m_buckets_data(alloc), + m_buckets(static_empty_bucket_ptr()), m_bucket_count(bucket_count), m_nb_elements(0), + m_grow_on_next_insert(false), m_try_shrink_on_next_insert(false) + { + if (bucket_count > max_bucket_count()) { + TSL_RH_THROW_OR_TERMINATE(std::length_error, "The map exceeds its maximum bucket count."); + } + + if (m_bucket_count > 0) { + m_buckets_data.resize(m_bucket_count); + m_buckets = m_buckets_data.data(); + + tsl_rh_assert(!m_buckets_data.empty()); + m_buckets_data.back().set_as_last_bucket(); + } + + this->min_load_factor(min_load_factor); + this->max_load_factor(max_load_factor); + } +#endif + + robin_hash(const robin_hash &other) + : Hash(other), KeyEqual(other), GrowthPolicy(other), m_buckets_data(other.m_buckets_data), + m_buckets(m_buckets_data.empty() ? static_empty_bucket_ptr() : m_buckets_data.data()), + m_bucket_count(other.m_bucket_count), m_nb_elements(other.m_nb_elements), + m_load_threshold(other.m_load_threshold), m_min_load_factor(other.m_min_load_factor), + m_max_load_factor(other.m_max_load_factor), + m_grow_on_next_insert(other.m_grow_on_next_insert), + m_try_shrink_on_next_insert(other.m_try_shrink_on_next_insert) + { + } + + robin_hash(robin_hash &&other) noexcept( + std::is_nothrow_move_constructible::value &&std::is_nothrow_move_constructible< + KeyEqual>::value &&std::is_nothrow_move_constructible::value + && std::is_nothrow_move_constructible::value) + : Hash(std::move(static_cast(other))), + KeyEqual(std::move(static_cast(other))), + GrowthPolicy(std::move(static_cast(other))), + m_buckets_data(std::move(other.m_buckets_data)), + m_buckets(m_buckets_data.empty() ? static_empty_bucket_ptr() : m_buckets_data.data()), + m_bucket_count(other.m_bucket_count), m_nb_elements(other.m_nb_elements), + m_load_threshold(other.m_load_threshold), m_min_load_factor(other.m_min_load_factor), + m_max_load_factor(other.m_max_load_factor), + m_grow_on_next_insert(other.m_grow_on_next_insert), + m_try_shrink_on_next_insert(other.m_try_shrink_on_next_insert) + { + other.clear_and_shrink(); + } + + robin_hash &operator=(const robin_hash &other) + { + if (&other != this) { + Hash:: operator=(other); + KeyEqual:: operator=(other); + GrowthPolicy::operator=(other); + + m_buckets_data = other.m_buckets_data; + m_buckets = m_buckets_data.empty() ? static_empty_bucket_ptr() : m_buckets_data.data(); + m_bucket_count = other.m_bucket_count; + m_nb_elements = other.m_nb_elements; + + m_load_threshold = other.m_load_threshold; + m_min_load_factor = other.m_min_load_factor; + m_max_load_factor = other.m_max_load_factor; + + m_grow_on_next_insert = other.m_grow_on_next_insert; + m_try_shrink_on_next_insert = other.m_try_shrink_on_next_insert; + } + + return *this; + } + + robin_hash &operator=(robin_hash &&other) + { + other.swap(*this); + other.clear(); + + return *this; + } + + allocator_type get_allocator() const { return m_buckets_data.get_allocator(); } + + /* + * Iterators + */ + iterator begin() noexcept + { + std::size_t i = 0; + while (i < m_bucket_count && m_buckets[i].empty()) { + i++; + } + + return iterator(m_buckets + i); + } + + const_iterator begin() const noexcept { return cbegin(); } + + const_iterator cbegin() const noexcept + { + std::size_t i = 0; + while (i < m_bucket_count && m_buckets[i].empty()) { + i++; + } + + return const_iterator(m_buckets + i); + } + + iterator end() noexcept { return iterator(m_buckets + m_bucket_count); } + + const_iterator end() const noexcept { return cend(); } + + const_iterator cend() const noexcept { return const_iterator(m_buckets + m_bucket_count); } + + /* + * Capacity + */ + bool empty() const noexcept { return m_nb_elements == 0; } + + size_type size() const noexcept { return m_nb_elements; } + + size_type max_size() const noexcept { return m_buckets_data.max_size(); } + + /* + * Modifiers + */ + void clear() noexcept + { + if (m_min_load_factor > 0.0f) { + clear_and_shrink(); + } + else { + for (auto &bucket : m_buckets_data) { + bucket.clear(); + } + + m_nb_elements = 0; + m_grow_on_next_insert = false; + } + } + + template std::pair insert(P &&value) + { + return insert_impl(KeySelect()(value), std::forward

(value)); + } + + template iterator insert_hint(const_iterator hint, P &&value) + { + if (hint != cend() && compare_keys(KeySelect()(*hint), KeySelect()(value))) { + return mutable_iterator(hint); + } + + return insert(std::forward

(value)).first; + } + + template void insert(InputIt first, InputIt last) + { + if (std::is_base_of::iterator_category>::value) { + const auto nb_elements_insert = std::distance(first, last); + const size_type nb_free_buckets = m_load_threshold - size(); + tsl_rh_assert(m_load_threshold >= size()); + + if (nb_elements_insert > 0 && nb_free_buckets < size_type(nb_elements_insert)) { + reserve(size() + size_type(nb_elements_insert)); + } + } + + for (; first != last; ++first) { + insert(*first); + } + } + + template std::pair insert_or_assign(K &&key, M &&obj) + { + auto it = try_emplace(std::forward(key), std::forward(obj)); + if (!it.second) { + it.first.value() = std::forward(obj); + } + + return it; + } + + template iterator insert_or_assign(const_iterator hint, K &&key, M &&obj) + { + if (hint != cend() && compare_keys(KeySelect()(*hint), key)) { + auto it = mutable_iterator(hint); + it.value() = std::forward(obj); + + return it; + } + + return insert_or_assign(std::forward(key), std::forward(obj)).first; + } + + template std::pair emplace(Args &&...args) + { + return insert(value_type(std::forward(args)...)); + } + + template iterator emplace_hint(const_iterator hint, Args &&...args) + { + return insert_hint(hint, value_type(std::forward(args)...)); + } + + template + std::pair try_emplace(K &&key, Args &&...args) + { + return insert_impl(key, std::piecewise_construct, + std::forward_as_tuple(std::forward(key)), + std::forward_as_tuple(std::forward(args)...)); + } + + template + iterator try_emplace_hint(const_iterator hint, K &&key, Args &&...args) + { + if (hint != cend() && compare_keys(KeySelect()(*hint), key)) { + return mutable_iterator(hint); + } + + return try_emplace(std::forward(key), std::forward(args)...).first; + } + + /** + * Here to avoid `template size_type erase(const K& key)` being used + * when we use an `iterator` instead of a `const_iterator`. + */ + iterator erase(iterator pos) + { + erase_from_bucket(pos); + + /** + * Erase bucket used a backward shift after clearing the bucket. + * Check if there is a new value in the bucket, if not get the next + * non-empty. + */ + if (pos.m_bucket->empty()) { + ++pos; + } + + m_try_shrink_on_next_insert = true; + + return pos; + } + + iterator erase(const_iterator pos) { return erase(mutable_iterator(pos)); } + + iterator erase(const_iterator first, const_iterator last) + { + if (first == last) { + return mutable_iterator(first); + } + + auto first_mutable = mutable_iterator(first); + auto last_mutable = mutable_iterator(last); + for (auto it = first_mutable.m_bucket; it != last_mutable.m_bucket; ++it) { + if (!it->empty()) { + it->clear(); + m_nb_elements--; + } + } + + if (last_mutable == end()) { + m_try_shrink_on_next_insert = true; + return end(); + } + + /* + * Backward shift on the values which come after the deleted values. + * We try to move the values closer to their ideal bucket. + */ + std::size_t icloser_bucket = static_cast(first_mutable.m_bucket - m_buckets); + std::size_t ito_move_closer_value = + static_cast(last_mutable.m_bucket - m_buckets); + tsl_rh_assert(ito_move_closer_value > icloser_bucket); + + const std::size_t ireturn_bucket = + ito_move_closer_value - + std::min(ito_move_closer_value - icloser_bucket, + std::size_t(m_buckets[ito_move_closer_value].dist_from_ideal_bucket())); + + while (ito_move_closer_value < m_bucket_count && + m_buckets[ito_move_closer_value].dist_from_ideal_bucket() > 0) { + icloser_bucket = + ito_move_closer_value - + std::min(ito_move_closer_value - icloser_bucket, + std::size_t(m_buckets[ito_move_closer_value].dist_from_ideal_bucket())); + + tsl_rh_assert(m_buckets[icloser_bucket].empty()); + const distance_type new_distance = + distance_type(m_buckets[ito_move_closer_value].dist_from_ideal_bucket() - + (ito_move_closer_value - icloser_bucket)); + m_buckets[icloser_bucket].set_value_of_empty_bucket( + new_distance, m_buckets[ito_move_closer_value].truncated_hash(), + std::move(m_buckets[ito_move_closer_value].value())); + m_buckets[ito_move_closer_value].clear(); + + ++icloser_bucket; + ++ito_move_closer_value; + } + + m_try_shrink_on_next_insert = true; + + return iterator(m_buckets + ireturn_bucket); + } + + template size_type erase(const K &key) { return erase(key, hash_key(key)); } + + template size_type erase(const K &key, std::size_t my_hash) + { + auto it = find(key, my_hash); + if (it != end()) { + erase_from_bucket(it); + m_try_shrink_on_next_insert = true; + + return 1; + } + else { + return 0; + } + } + + void swap(robin_hash &other) + { + using std::swap; + + swap(static_cast(*this), static_cast(other)); + swap(static_cast(*this), static_cast(other)); + swap(static_cast(*this), static_cast(other)); + swap(m_buckets_data, other.m_buckets_data); + swap(m_buckets, other.m_buckets); + swap(m_bucket_count, other.m_bucket_count); + swap(m_nb_elements, other.m_nb_elements); + swap(m_load_threshold, other.m_load_threshold); + swap(m_min_load_factor, other.m_min_load_factor); + swap(m_max_load_factor, other.m_max_load_factor); + swap(m_grow_on_next_insert, other.m_grow_on_next_insert); + swap(m_try_shrink_on_next_insert, other.m_try_shrink_on_next_insert); + } + + /* + * Lookup + */ + template ::value>::type * = nullptr> + typename U::value_type &at(const K &key) + { + return at(key, hash_key(key)); + } + + template ::value>::type * = nullptr> + typename U::value_type &at(const K &key, std::size_t my_hash) + { + return const_cast( + static_cast(this)->at(key, my_hash)); + } + + template ::value>::type * = nullptr> + const typename U::value_type &at(const K &key) const + { + return at(key, hash_key(key)); + } + + template ::value>::type * = nullptr> + const typename U::value_type &at(const K &key, std::size_t my_hash) const + { + auto it = find(key, my_hash); + if (it != cend()) { + return it.value(); + } + else { + TSL_RH_THROW_OR_TERMINATE(std::out_of_range, "Couldn't find key."); + } + } + + template ::value>::type * = nullptr> + typename U::value_type &operator[](K &&key) + { + return try_emplace(std::forward(key)).first.value(); + } + + template size_type count(const K &key) const { return count(key, hash_key(key)); } + + template size_type count(const K &key, std::size_t my_hash) const + { + if (find(key, my_hash) != cend()) { + return 1; + } + else { + return 0; + } + } + + template iterator find(const K &key) { return find_impl(key, hash_key(key)); } + + template iterator find(const K &key, std::size_t my_hash) + { + return find_impl(key, my_hash); + } + + template const_iterator find(const K &key) const + { + return find_impl(key, hash_key(key)); + } + + template const_iterator find(const K &key, std::size_t my_hash) const + { + return find_impl(key, my_hash); + } + + template bool contains(const K &key) const { return contains(key, hash_key(key)); } + + template bool contains(const K &key, std::size_t my_hash) const + { + return count(key, my_hash) != 0; + } + + template std::pair equal_range(const K &key) + { + return equal_range(key, hash_key(key)); + } + + template + std::pair equal_range(const K &key, std::size_t my_hash) + { + iterator it = find(key, my_hash); + return std::make_pair(it, (it == end()) ? it : std::next(it)); + } + + template std::pair equal_range(const K &key) const + { + return equal_range(key, hash_key(key)); + } + + template + std::pair equal_range(const K &key, std::size_t my_hash) const + { + const_iterator it = find(key, my_hash); + return std::make_pair(it, (it == cend()) ? it : std::next(it)); + } + + /* + * Bucket interface + */ + size_type bucket_count() const { return m_bucket_count; } + + size_type max_bucket_count() const + { + return std::min(GrowthPolicy::max_bucket_count(), m_buckets_data.max_size()); + } + + /* + * Hash policy + */ + float load_factor() const + { + if (bucket_count() == 0) { + return 0; + } + + return float(m_nb_elements) / float(bucket_count()); + } + + float min_load_factor() const { return m_min_load_factor; } + + float max_load_factor() const { return m_max_load_factor; } + + void min_load_factor(float ml) + { + m_min_load_factor = + clamp(ml, float(MINIMUM_MIN_LOAD_FACTOR), float(MAXIMUM_MIN_LOAD_FACTOR)); + } + + void max_load_factor(float ml) + { + m_max_load_factor = + clamp(ml, float(MINIMUM_MAX_LOAD_FACTOR), float(MAXIMUM_MAX_LOAD_FACTOR)); + m_load_threshold = size_type(float(bucket_count()) * m_max_load_factor); + } + + void rehash(size_type my_count) + { + my_count = std::max(my_count, size_type(std::ceil(float(size()) / max_load_factor()))); + rehash_impl(my_count); + } + + void reserve(size_type my_count) + { + rehash(size_type(std::ceil(float(my_count) / max_load_factor()))); + } + + /* + * Observers + */ + hasher hash_function() const { return static_cast(*this); } + + key_equal key_eq() const { return static_cast(*this); } + + /* + * Other + */ + iterator mutable_iterator(const_iterator pos) + { + return iterator(const_cast(pos.m_bucket)); + } + + template void serialize(Serializer &serializer) const + { + serialize_impl(serializer); + } + + template + void deserialize(Deserializer &deserializer, bool hash_compatible) + { + deserialize_impl(deserializer, hash_compatible); + } + + private: + template std::size_t hash_key(const K &key) const { return Hash::operator()(key); } + + template bool compare_keys(const K1 &key1, const K2 &key2) const + { + return KeyEqual::operator()(key1, key2); + } + + std::size_t bucket_for_hash(std::size_t my_hash) const + { + const std::size_t bucket = GrowthPolicy::bucket_for_hash(my_hash); + tsl_rh_assert(bucket < m_bucket_count || (bucket == 0 && m_bucket_count == 0)); + + return bucket; + } + + template ::value>::type * = nullptr> + std::size_t next_bucket(std::size_t index) const noexcept + { + tsl_rh_assert(index < bucket_count()); + + return (index + 1) & this->m_mask; + } + + template ::value>::type * = nullptr> + std::size_t next_bucket(std::size_t index) const noexcept + { + tsl_rh_assert(index < bucket_count()); + + index++; + return (index != bucket_count()) ? index : 0; + } + + template iterator find_impl(const K &key, std::size_t my_hash) + { + return mutable_iterator(static_cast(this)->find(key, my_hash)); + } + + template const_iterator find_impl(const K &key, std::size_t my_hash) const + { + std::size_t ibucket = bucket_for_hash(my_hash); + distance_type dist_from_ideal_bucket = 0; + + while (dist_from_ideal_bucket <= m_buckets[ibucket].dist_from_ideal_bucket()) { + if (TSL_RH_LIKELY( + (!USE_STORED_HASH_ON_LOOKUP || m_buckets[ibucket].bucket_hash_equal(my_hash)) && + compare_keys(KeySelect()(m_buckets[ibucket].value()), key))) { + return const_iterator(m_buckets + ibucket); + } + + ibucket = next_bucket(ibucket); + dist_from_ideal_bucket++; + } + + return cend(); + } + + void erase_from_bucket(iterator pos) + { + pos.m_bucket->clear(); + m_nb_elements--; + + /** + * Backward shift, swap the empty bucket, previous_ibucket, with the values + * on its right, ibucket, until we cross another empty bucket or if the + * other bucket has a distance_from_ideal_bucket == 0. + * + * We try to move the values closer to their ideal bucket. + */ + std::size_t previous_ibucket = static_cast(pos.m_bucket - m_buckets); + std::size_t ibucket = next_bucket(previous_ibucket); + + while (m_buckets[ibucket].dist_from_ideal_bucket() > 0) { + tsl_rh_assert(m_buckets[previous_ibucket].empty()); + + const distance_type new_distance = + distance_type(m_buckets[ibucket].dist_from_ideal_bucket() - 1); + m_buckets[previous_ibucket].set_value_of_empty_bucket( + new_distance, m_buckets[ibucket].truncated_hash(), + std::move(m_buckets[ibucket].value())); + m_buckets[ibucket].clear(); + + previous_ibucket = ibucket; + ibucket = next_bucket(ibucket); + } + } + + template + std::pair insert_impl(const K &key, Args &&...value_type_args) + { + const std::size_t my_hash = hash_key(key); + + std::size_t ibucket = bucket_for_hash(my_hash); + distance_type dist_from_ideal_bucket = 0; + + while (dist_from_ideal_bucket <= m_buckets[ibucket].dist_from_ideal_bucket()) { + if ((!USE_STORED_HASH_ON_LOOKUP || m_buckets[ibucket].bucket_hash_equal(my_hash)) && + compare_keys(KeySelect()(m_buckets[ibucket].value()), key)) { + return std::make_pair(iterator(m_buckets + ibucket), false); + } + + ibucket = next_bucket(ibucket); + dist_from_ideal_bucket++; + } + + if (rehash_on_extreme_load()) { + ibucket = bucket_for_hash(my_hash); + dist_from_ideal_bucket = 0; + + while (dist_from_ideal_bucket <= m_buckets[ibucket].dist_from_ideal_bucket()) { + ibucket = next_bucket(ibucket); + dist_from_ideal_bucket++; + } + } + + if (m_buckets[ibucket].empty()) { + m_buckets[ibucket].set_value_of_empty_bucket(dist_from_ideal_bucket, + bucket_entry::truncate_hash(my_hash), + std::forward(value_type_args)...); + } + else { + insert_value(ibucket, dist_from_ideal_bucket, bucket_entry::truncate_hash(my_hash), + std::forward(value_type_args)...); + } + + m_nb_elements++; + /* + * The value will be inserted in ibucket in any case, either because it was + * empty or by stealing the bucket (robin hood). + */ + return std::make_pair(iterator(m_buckets + ibucket), true); + } + + template + void insert_value(std::size_t ibucket, distance_type dist_from_ideal_bucket, + truncated_hash_type my_hash, Args &&...value_type_args) + { + value_type value(std::forward(value_type_args)...); + insert_value_impl(ibucket, dist_from_ideal_bucket, my_hash, value); + } + + void insert_value(std::size_t ibucket, distance_type dist_from_ideal_bucket, + truncated_hash_type my_hash, value_type &&value) + { + insert_value_impl(ibucket, dist_from_ideal_bucket, my_hash, value); + } + + /* + * We don't use `value_type&& value` as last argument due to a bug in MSVC + * when `value_type` is a pointer, The compiler is not able to see the + * difference between `std::string*` and `std::string*&&` resulting in a + * compilation error. + * + * The `value` will be in a moved state at the end of the function. + */ + void insert_value_impl(std::size_t ibucket, distance_type dist_from_ideal_bucket, + truncated_hash_type my_hash, value_type &value) + { + m_buckets[ibucket].swap_with_value_in_bucket(dist_from_ideal_bucket, my_hash, value); + ibucket = next_bucket(ibucket); + dist_from_ideal_bucket++; + + while (!m_buckets[ibucket].empty()) { + if (dist_from_ideal_bucket > m_buckets[ibucket].dist_from_ideal_bucket()) { + if (dist_from_ideal_bucket >= bucket_entry::DIST_FROM_IDEAL_BUCKET_LIMIT) { + /** + * The number of probes is really high, rehash the map on the next + * insert. Difficult to do now as rehash may throw an exception. + */ + m_grow_on_next_insert = true; + } + + m_buckets[ibucket].swap_with_value_in_bucket(dist_from_ideal_bucket, my_hash, value); + } + + ibucket = next_bucket(ibucket); + dist_from_ideal_bucket++; + } + + m_buckets[ibucket].set_value_of_empty_bucket(dist_from_ideal_bucket, my_hash, + std::move(value)); + } + + void rehash_impl(size_type my_count) + { + robin_hash new_table(my_count, static_cast(*this), static_cast(*this), + get_allocator(), m_min_load_factor, m_max_load_factor); + + const bool use_stored_hash = USE_STORED_HASH_ON_REHASH(new_table.bucket_count()); + for (auto &bucket : m_buckets_data) { + if (bucket.empty()) { + continue; + } + + const std::size_t my_hash = use_stored_hash + ? bucket.truncated_hash() + : new_table.hash_key(KeySelect()(bucket.value())); + + new_table.insert_value_on_rehash(new_table.bucket_for_hash(my_hash), 0, + bucket_entry::truncate_hash(my_hash), + std::move(bucket.value())); + } + + new_table.m_nb_elements = m_nb_elements; + new_table.swap(*this); + } + + void clear_and_shrink() noexcept + { + GrowthPolicy::clear(); + m_buckets_data.clear(); + m_buckets = static_empty_bucket_ptr(); + m_bucket_count = 0; + m_nb_elements = 0; + m_load_threshold = 0; + m_grow_on_next_insert = false; + m_try_shrink_on_next_insert = false; + } + + void insert_value_on_rehash(std::size_t ibucket, distance_type dist_from_ideal_bucket, + truncated_hash_type my_hash, value_type &&value) + { + while (true) { + if (dist_from_ideal_bucket > m_buckets[ibucket].dist_from_ideal_bucket()) { + if (m_buckets[ibucket].empty()) { + m_buckets[ibucket].set_value_of_empty_bucket(dist_from_ideal_bucket, my_hash, + std::move(value)); + return; + } + else { + m_buckets[ibucket].swap_with_value_in_bucket(dist_from_ideal_bucket, my_hash, value); + } + } + + dist_from_ideal_bucket++; + ibucket = next_bucket(ibucket); + } + } + + /** + * Grow the table if m_grow_on_next_insert is true or we reached the + * max_load_factor. Shrink the table if m_try_shrink_on_next_insert is true + * (an erase occurred) and we're below the min_load_factor. + * + * Return true if the table has been rehashed. + */ + bool rehash_on_extreme_load() + { + if (m_grow_on_next_insert || size() >= m_load_threshold) { + rehash_impl(GrowthPolicy::next_bucket_count()); + m_grow_on_next_insert = false; + + return true; + } + + if (m_try_shrink_on_next_insert) { + m_try_shrink_on_next_insert = false; + if (m_min_load_factor != 0.0f && load_factor() < m_min_load_factor) { + reserve(size() + 1); + + return true; + } + } + + return false; + } + + template void serialize_impl(Serializer &serializer) const + { + const slz_size_type version = SERIALIZATION_PROTOCOL_VERSION; + serializer(version); + + // Indicate if the truncated hash of each bucket is stored. Use a + // std::int16_t instead of a bool to avoid the need for the serializer to + // support an extra 'bool' type. + const std::int16_t hash_stored_for_bucket = static_cast(STORE_HASH); + serializer(hash_stored_for_bucket); + + const slz_size_type nb_elements = m_nb_elements; + serializer(nb_elements); + + const slz_size_type bucket_count = m_buckets_data.size(); + serializer(bucket_count); + + const float min_load_factor = m_min_load_factor; + serializer(min_load_factor); + + const float max_load_factor = m_max_load_factor; + serializer(max_load_factor); + + for (const bucket_entry &bucket : m_buckets_data) { + if (bucket.empty()) { + const std::int16_t empty_bucket = bucket_entry::EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET; + serializer(empty_bucket); + } + else { + const std::int16_t dist_from_ideal_bucket = bucket.dist_from_ideal_bucket(); + serializer(dist_from_ideal_bucket); + if (STORE_HASH) { + const std::uint32_t truncated_hash = bucket.truncated_hash(); + serializer(truncated_hash); + } + serializer(bucket.value()); + } + } + } + + template + void deserialize_impl(Deserializer &deserializer, bool hash_compatible) + { + tsl_rh_assert(m_buckets_data.empty()); // Current hash table must be empty + + const slz_size_type version = deserialize_value(deserializer); + // For now we only have one version of the serialization protocol. + // If it doesn't match there is a problem with the file. + if (version != SERIALIZATION_PROTOCOL_VERSION) { + TSL_RH_THROW_OR_TERMINATE(std::runtime_error, "Can't deserialize the ordered_map/set. " + "The protocol version header is invalid."); + } + + const bool hash_stored_for_bucket = + deserialize_value(deserializer) ? true : false; + if (hash_compatible && STORE_HASH != hash_stored_for_bucket) { + TSL_RH_THROW_OR_TERMINATE(std::runtime_error, + "Can't deserialize a map with a different StoreHash " + "than the one used during the serialization when " + "hash compatibility is used"); + } + + const slz_size_type nb_elements = deserialize_value(deserializer); + const slz_size_type bucket_count_ds = deserialize_value(deserializer); + const float min_load_factor = deserialize_value(deserializer); + const float max_load_factor = deserialize_value(deserializer); + + if (min_load_factor < MINIMUM_MIN_LOAD_FACTOR || + min_load_factor > MAXIMUM_MIN_LOAD_FACTOR) { + TSL_RH_THROW_OR_TERMINATE(std::runtime_error, + "Invalid min_load_factor. Check that the serializer " + "and deserializer support floats correctly as they " + "can be converted implicitly to ints."); + } + + if (max_load_factor < MINIMUM_MAX_LOAD_FACTOR || + max_load_factor > MAXIMUM_MAX_LOAD_FACTOR) { + TSL_RH_THROW_OR_TERMINATE(std::runtime_error, + "Invalid max_load_factor. Check that the serializer " + "and deserializer support floats correctly as they " + "can be converted implicitly to ints."); + } + + this->min_load_factor(min_load_factor); + this->max_load_factor(max_load_factor); + + if (bucket_count_ds == 0) { + tsl_rh_assert(nb_elements == 0); + return; + } + + if (!hash_compatible) { + reserve(numeric_cast(nb_elements, "Deserialized nb_elements is too big.")); + for (slz_size_type ibucket = 0; ibucket < bucket_count_ds; ibucket++) { + const distance_type dist_from_ideal_bucket = + deserialize_value(deserializer); + if (dist_from_ideal_bucket != bucket_entry::EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET) { + if (hash_stored_for_bucket) { + TSL_RH_UNUSED(deserialize_value(deserializer)); + } + + insert(deserialize_value(deserializer)); + } + } + + tsl_rh_assert(nb_elements == size()); + } + else { + m_bucket_count = + numeric_cast(bucket_count_ds, "Deserialized bucket_count is too big."); + + GrowthPolicy::operator=(GrowthPolicy(m_bucket_count)); + // GrowthPolicy should not modify the bucket count we got from + // deserialization + if (m_bucket_count != bucket_count_ds) { + TSL_RH_THROW_OR_TERMINATE(std::runtime_error, "The GrowthPolicy is not the same even " + "though hash_compatible is true."); + } + + m_nb_elements = + numeric_cast(nb_elements, "Deserialized nb_elements is too big."); + m_buckets_data.resize(m_bucket_count); + m_buckets = m_buckets_data.data(); + + for (bucket_entry &bucket : m_buckets_data) { + const distance_type dist_from_ideal_bucket = + deserialize_value(deserializer); + if (dist_from_ideal_bucket != bucket_entry::EMPTY_MARKER_DIST_FROM_IDEAL_BUCKET) { + truncated_hash_type truncated_hash = 0; + if (hash_stored_for_bucket) { + tsl_rh_assert(hash_stored_for_bucket); + truncated_hash = deserialize_value(deserializer); + } + + bucket.set_value_of_empty_bucket(dist_from_ideal_bucket, truncated_hash, + deserialize_value(deserializer)); + } + } + + if (!m_buckets_data.empty()) { + m_buckets_data.back().set_as_last_bucket(); + } + } + } + + public: + static const size_type DEFAULT_INIT_BUCKETS_SIZE = 0; + + static constexpr float DEFAULT_MAX_LOAD_FACTOR = 0.5f; + static constexpr float MINIMUM_MAX_LOAD_FACTOR = 0.2f; + static constexpr float MAXIMUM_MAX_LOAD_FACTOR = 0.95f; + + static constexpr float DEFAULT_MIN_LOAD_FACTOR = 0.0f; + static constexpr float MINIMUM_MIN_LOAD_FACTOR = 0.0f; + static constexpr float MAXIMUM_MIN_LOAD_FACTOR = 0.15f; + + static_assert(MINIMUM_MAX_LOAD_FACTOR < MAXIMUM_MAX_LOAD_FACTOR, + "MINIMUM_MAX_LOAD_FACTOR should be < MAXIMUM_MAX_LOAD_FACTOR"); + static_assert(MINIMUM_MIN_LOAD_FACTOR < MAXIMUM_MIN_LOAD_FACTOR, + "MINIMUM_MIN_LOAD_FACTOR should be < MAXIMUM_MIN_LOAD_FACTOR"); + static_assert(MAXIMUM_MIN_LOAD_FACTOR < MINIMUM_MAX_LOAD_FACTOR, + "MAXIMUM_MIN_LOAD_FACTOR should be < MINIMUM_MAX_LOAD_FACTOR"); + + private: + /** + * Protocol version currenlty used for serialization. + */ + static const slz_size_type SERIALIZATION_PROTOCOL_VERSION = 1; + + /** + * Return an always valid pointer to an static empty bucket_entry with + * last_bucket() == true. + */ + bucket_entry *static_empty_bucket_ptr() noexcept + { + static bucket_entry empty_bucket(true); + return &empty_bucket; + } + + private: + buckets_container_type m_buckets_data; + + /** + * Points to m_buckets_data.data() if !m_buckets_data.empty() otherwise points + * to static_empty_bucket_ptr. This variable is useful to avoid the cost of + * checking if m_buckets_data is empty when trying to find an element. + * + * TODO Remove m_buckets_data and only use a pointer instead of a + * pointer+vector to save some space in the robin_hash object. Manage the + * Allocator manually. + */ + bucket_entry *m_buckets; + + /** + * Used a lot in find, avoid the call to m_buckets_data.size() which is a bit + * slower. + */ + size_type m_bucket_count; + + size_type m_nb_elements; + + size_type m_load_threshold; + + float m_min_load_factor; + float m_max_load_factor; + + bool m_grow_on_next_insert; + + /** + * We can't shrink down the map on erase operations as the erase methods need + * to return the next iterator. Shrinking the map would invalidate all the + * iterators and we could not return the next iterator in a meaningful way, On + * erase, we thus just indicate on erase that we should try to shrink the hash + * table on the next insert if we go below the min_load_factor. + */ + bool m_try_shrink_on_next_insert; + }; + + } // namespace detail_robin_hash + +} // namespace tsl + +#endif diff --git a/packages/seacas/libraries/aprepro_lib/robin_map.h b/packages/seacas/libraries/aprepro_lib/robin_map.h new file mode 100644 index 000000000000..3b2c0f0989cb --- /dev/null +++ b/packages/seacas/libraries/aprepro_lib/robin_map.h @@ -0,0 +1,813 @@ +/** + * MIT License + * + * Copyright (c) 2017 Thibaut Goetghebuer-Planchon + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef TSL_ROBIN_MAP_H +#define TSL_ROBIN_MAP_H + +#include +#include +#include +#include +#include +#include + +#include "robin_hash.h" + +namespace tsl { + + /** + * Implementation of a hash map using open-addressing and the robin hood hashing + * algorithm with backward shift deletion. + * + * For operations modifying the hash map (insert, erase, rehash, ...), the + * strong exception guarantee is only guaranteed when the expression + * `std::is_nothrow_swappable>\:\:value && + * std::is_nothrow_move_constructible>\:\:value` is true, + * otherwise if an exception is thrown during the swap or the move, the hash map + * may end up in a undefined state. Per the standard a `Key` or `T` with a + * noexcept copy constructor and no move constructor also satisfies the + * `std::is_nothrow_move_constructible>\:\:value` criterion (and + * will thus guarantee the strong exception for the map). + * + * When `StoreHash` is true, 32 bits of the hash are stored alongside the + * values. It can improve the performance during lookups if the `KeyEqual` + * function takes time (if it engenders a cache-miss for example) as we then + * compare the stored hashes before comparing the keys. When + * `tsl::rh::power_of_two_growth_policy` is used as `GrowthPolicy`, it may also + * speed-up the rehash process as we can avoid to recalculate the hash. When it + * is detected that storing the hash will not incur any memory penalty due to + * alignment (i.e. `sizeof(tsl::detail_robin_hash::bucket_entry) == sizeof(tsl::detail_robin_hash::bucket_entry)`) + * and `tsl::rh::power_of_two_growth_policy` is used, the hash will be stored + * even if `StoreHash` is false so that we can speed-up the rehash (but it will + * not be used on lookups unless `StoreHash` is true). + * + * `GrowthPolicy` defines how the map grows and consequently how a hash value is + * mapped to a bucket. By default the map uses + * `tsl::rh::power_of_two_growth_policy`. This policy keeps the number of + * buckets to a power of two and uses a mask to map the hash to a bucket instead + * of the slow modulo. Other growth policies are available and you may define + * your own growth policy, check `tsl::rh::power_of_two_growth_policy` for the + * interface. + * + * `std::pair` must be swappable. + * + * `Key` and `T` must be copy and/or move constructible. + * + * If the destructor of `Key` or `T` throws an exception, the behaviour of the + * class is undefined. + * + * Iterators invalidation: + * - clear, operator=, reserve, rehash: always invalidate the iterators. + * - insert, emplace, emplace_hint, operator[]: if there is an effective + * insert, invalidate the iterators. + * - erase: always invalidate the iterators. + */ + template , class KeyEqual = std::equal_to, + class Allocator = std::allocator>, bool StoreHash = false, + class GrowthPolicy = tsl::rh::power_of_two_growth_policy<2>> + class robin_map + { + private: + template using has_is_transparent = tsl::detail_robin_hash::has_is_transparent; + + class KeySelect + { + public: + using key_type = Key; + + const key_type &operator()(const std::pair &key_value) const noexcept + { + return key_value.first; + } + + key_type &operator()(std::pair &key_value) noexcept { return key_value.first; } + }; + + class ValueSelect + { + public: + using value_type = T; + + const value_type &operator()(const std::pair &key_value) const noexcept + { + return key_value.second; + } + + value_type &operator()(std::pair &key_value) noexcept { return key_value.second; } + }; + + using ht = detail_robin_hash::robin_hash, KeySelect, ValueSelect, Hash, + KeyEqual, Allocator, StoreHash, GrowthPolicy>; + + public: + using key_type = typename ht::key_type; + using mapped_type = T; + using value_type = typename ht::value_type; + using size_type = typename ht::size_type; + using difference_type = typename ht::difference_type; + using hasher = typename ht::hasher; + using key_equal = typename ht::key_equal; + using allocator_type = typename ht::allocator_type; + using reference = typename ht::reference; + using const_reference = typename ht::const_reference; + using pointer = typename ht::pointer; + using const_pointer = typename ht::const_pointer; + using iterator = typename ht::iterator; + using const_iterator = typename ht::const_iterator; + + public: + /* + * Constructors + */ + robin_map() : robin_map(ht::DEFAULT_INIT_BUCKETS_SIZE) {} + + explicit robin_map(size_type bucket_count, const Hash &hash = Hash(), + const KeyEqual &equal = KeyEqual(), const Allocator &alloc = Allocator()) + : m_ht(bucket_count, hash, equal, alloc) + { + } + + robin_map(size_type bucket_count, const Allocator &alloc) + : robin_map(bucket_count, Hash(), KeyEqual(), alloc) + { + } + + robin_map(size_type bucket_count, const Hash &hash, const Allocator &alloc) + : robin_map(bucket_count, hash, KeyEqual(), alloc) + { + } + + explicit robin_map(const Allocator &alloc) : robin_map(ht::DEFAULT_INIT_BUCKETS_SIZE, alloc) {} + + template + robin_map(InputIt first, InputIt last, size_type bucket_count = ht::DEFAULT_INIT_BUCKETS_SIZE, + const Hash &hash = Hash(), const KeyEqual &equal = KeyEqual(), + const Allocator &alloc = Allocator()) + : robin_map(bucket_count, hash, equal, alloc) + { + insert(first, last); + } + + template + robin_map(InputIt first, InputIt last, size_type bucket_count, const Allocator &alloc) + : robin_map(first, last, bucket_count, Hash(), KeyEqual(), alloc) + { + } + + template + robin_map(InputIt first, InputIt last, size_type bucket_count, const Hash &hash, + const Allocator &alloc) + : robin_map(first, last, bucket_count, hash, KeyEqual(), alloc) + { + } + + robin_map(std::initializer_list init, + size_type bucket_count = ht::DEFAULT_INIT_BUCKETS_SIZE, const Hash &hash = Hash(), + const KeyEqual &equal = KeyEqual(), const Allocator &alloc = Allocator()) + : robin_map(init.begin(), init.end(), bucket_count, hash, equal, alloc) + { + } + + robin_map(std::initializer_list init, size_type bucket_count, + const Allocator &alloc) + : robin_map(init.begin(), init.end(), bucket_count, Hash(), KeyEqual(), alloc) + { + } + + robin_map(std::initializer_list init, size_type bucket_count, const Hash &hash, + const Allocator &alloc) + : robin_map(init.begin(), init.end(), bucket_count, hash, KeyEqual(), alloc) + { + } + + robin_map &operator=(std::initializer_list ilist) + { + m_ht.clear(); + + m_ht.reserve(ilist.size()); + m_ht.insert(ilist.begin(), ilist.end()); + + return *this; + } + + allocator_type get_allocator() const { return m_ht.get_allocator(); } + + /* + * Iterators + */ + iterator begin() noexcept { return m_ht.begin(); } + const_iterator begin() const noexcept { return m_ht.begin(); } + const_iterator cbegin() const noexcept { return m_ht.cbegin(); } + + iterator end() noexcept { return m_ht.end(); } + const_iterator end() const noexcept { return m_ht.end(); } + const_iterator cend() const noexcept { return m_ht.cend(); } + + /* + * Capacity + */ + bool empty() const noexcept { return m_ht.empty(); } + size_type size() const noexcept { return m_ht.size(); } + size_type max_size() const noexcept { return m_ht.max_size(); } + + /* + * Modifiers + */ + void clear() noexcept { m_ht.clear(); } + + std::pair insert(const value_type &value) { return m_ht.insert(value); } + + template ::value>::type + * = nullptr> + std::pair insert(P &&value) + { + return m_ht.emplace(std::forward

(value)); + } + + std::pair insert(value_type &&value) { return m_ht.insert(std::move(value)); } + + iterator insert(const_iterator hint, const value_type &value) + { + return m_ht.insert_hint(hint, value); + } + + template ::value>::type + * = nullptr> + iterator insert(const_iterator hint, P &&value) + { + return m_ht.emplace_hint(hint, std::forward

(value)); + } + + iterator insert(const_iterator hint, value_type &&value) + { + return m_ht.insert_hint(hint, std::move(value)); + } + + template void insert(InputIt first, InputIt last) { m_ht.insert(first, last); } + + void insert(std::initializer_list ilist) + { + m_ht.insert(ilist.begin(), ilist.end()); + } + + template std::pair insert_or_assign(const key_type &k, M &&obj) + { + return m_ht.insert_or_assign(k, std::forward(obj)); + } + + template std::pair insert_or_assign(key_type &&k, M &&obj) + { + return m_ht.insert_or_assign(std::move(k), std::forward(obj)); + } + + template iterator insert_or_assign(const_iterator hint, const key_type &k, M &&obj) + { + return m_ht.insert_or_assign(hint, k, std::forward(obj)); + } + + template iterator insert_or_assign(const_iterator hint, key_type &&k, M &&obj) + { + return m_ht.insert_or_assign(hint, std::move(k), std::forward(obj)); + } + + /** + * Due to the way elements are stored, emplace will need to move or copy the + * key-value once. The method is equivalent to + * insert(value_type(std::forward(args)...)); + * + * Mainly here for compatibility with the std::unordered_map interface. + */ + template std::pair emplace(Args &&...args) + { + return m_ht.emplace(std::forward(args)...); + } + + /** + * Due to the way elements are stored, emplace_hint will need to move or copy + * the key-value once. The method is equivalent to insert(hint, + * value_type(std::forward(args)...)); + * + * Mainly here for compatibility with the std::unordered_map interface. + */ + template iterator emplace_hint(const_iterator hint, Args &&...args) + { + return m_ht.emplace_hint(hint, std::forward(args)...); + } + + template + std::pair try_emplace(const key_type &k, Args &&...args) + { + return m_ht.try_emplace(k, std::forward(args)...); + } + + template std::pair try_emplace(key_type &&k, Args &&...args) + { + return m_ht.try_emplace(std::move(k), std::forward(args)...); + } + + template + iterator try_emplace(const_iterator hint, const key_type &k, Args &&...args) + { + return m_ht.try_emplace_hint(hint, k, std::forward(args)...); + } + + template iterator try_emplace(const_iterator hint, key_type &&k, Args &&...args) + { + return m_ht.try_emplace_hint(hint, std::move(k), std::forward(args)...); + } + + iterator erase(iterator pos) { return m_ht.erase(pos); } + iterator erase(const_iterator pos) { return m_ht.erase(pos); } + iterator erase(const_iterator first, const_iterator last) { return m_ht.erase(first, last); } + size_type erase(const key_type &key) { return m_ht.erase(key); } + + /** + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Useful to speed-up + * the lookup to the value if you already have the hash. + */ + size_type erase(const key_type &key, std::size_t precalculated_hash) + { + return m_ht.erase(key, precalculated_hash); + } + + /** + * This overload only participates in the overload resolution if the typedef + * KeyEqual::is_transparent exists. If so, K must be hashable and comparable + * to Key. + */ + template ::value>::type * = nullptr> + size_type erase(const K &key) + { + return m_ht.erase(key); + } + + /** + * @copydoc erase(const K& key) + * + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Useful to speed-up + * the lookup to the value if you already have the hash. + */ + template ::value>::type * = nullptr> + size_type erase(const K &key, std::size_t precalculated_hash) + { + return m_ht.erase(key, precalculated_hash); + } + + void swap(robin_map &other) { other.m_ht.swap(m_ht); } + + /* + * Lookup + */ + T &at(const Key &key) { return m_ht.at(key); } + + /** + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Useful to speed-up + * the lookup if you already have the hash. + */ + T &at(const Key &key, std::size_t precalculated_hash) + { + return m_ht.at(key, precalculated_hash); + } + + const T &at(const Key &key) const { return m_ht.at(key); } + + /** + * @copydoc at(const Key& key, std::size_t precalculated_hash) + */ + const T &at(const Key &key, std::size_t precalculated_hash) const + { + return m_ht.at(key, precalculated_hash); + } + + /** + * This overload only participates in the overload resolution if the typedef + * KeyEqual::is_transparent exists. If so, K must be hashable and comparable + * to Key. + */ + template ::value>::type * = nullptr> + T &at(const K &key) + { + return m_ht.at(key); + } + + /** + * @copydoc at(const K& key) + * + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Useful to speed-up + * the lookup if you already have the hash. + */ + template ::value>::type * = nullptr> + T &at(const K &key, std::size_t precalculated_hash) + { + return m_ht.at(key, precalculated_hash); + } + + /** + * @copydoc at(const K& key) + */ + template ::value>::type * = nullptr> + const T &at(const K &key) const + { + return m_ht.at(key); + } + + /** + * @copydoc at(const K& key, std::size_t precalculated_hash) + */ + template ::value>::type * = nullptr> + const T &at(const K &key, std::size_t precalculated_hash) const + { + return m_ht.at(key, precalculated_hash); + } + + T &operator[](const Key &key) { return m_ht[key]; } + T &operator[](Key &&key) { return m_ht[std::move(key)]; } + + size_type count(const Key &key) const { return m_ht.count(key); } + + /** + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Useful to speed-up + * the lookup if you already have the hash. + */ + size_type count(const Key &key, std::size_t precalculated_hash) const + { + return m_ht.count(key, precalculated_hash); + } + + /** + * This overload only participates in the overload resolution if the typedef + * KeyEqual::is_transparent exists. If so, K must be hashable and comparable + * to Key. + */ + template ::value>::type * = nullptr> + size_type count(const K &key) const + { + return m_ht.count(key); + } + + /** + * @copydoc count(const K& key) const + * + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Useful to speed-up + * the lookup if you already have the hash. + */ + template ::value>::type * = nullptr> + size_type count(const K &key, std::size_t precalculated_hash) const + { + return m_ht.count(key, precalculated_hash); + } + + iterator find(const Key &key) { return m_ht.find(key); } + + /** + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Useful to speed-up + * the lookup if you already have the hash. + */ + iterator find(const Key &key, std::size_t precalculated_hash) + { + return m_ht.find(key, precalculated_hash); + } + + const_iterator find(const Key &key) const { return m_ht.find(key); } + + /** + * @copydoc find(const Key& key, std::size_t precalculated_hash) + */ + const_iterator find(const Key &key, std::size_t precalculated_hash) const + { + return m_ht.find(key, precalculated_hash); + } + + /** + * This overload only participates in the overload resolution if the typedef + * KeyEqual::is_transparent exists. If so, K must be hashable and comparable + * to Key. + */ + template ::value>::type * = nullptr> + iterator find(const K &key) + { + return m_ht.find(key); + } + + /** + * @copydoc find(const K& key) + * + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Useful to speed-up + * the lookup if you already have the hash. + */ + template ::value>::type * = nullptr> + iterator find(const K &key, std::size_t precalculated_hash) + { + return m_ht.find(key, precalculated_hash); + } + + /** + * @copydoc find(const K& key) + */ + template ::value>::type * = nullptr> + const_iterator find(const K &key) const + { + return m_ht.find(key); + } + + /** + * @copydoc find(const K& key) + * + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Useful to speed-up + * the lookup if you already have the hash. + */ + template ::value>::type * = nullptr> + const_iterator find(const K &key, std::size_t precalculated_hash) const + { + return m_ht.find(key, precalculated_hash); + } + + bool contains(const Key &key) const { return m_ht.contains(key); } + + /** + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Useful to speed-up + * the lookup if you already have the hash. + */ + bool contains(const Key &key, std::size_t precalculated_hash) const + { + return m_ht.contains(key, precalculated_hash); + } + + /** + * This overload only participates in the overload resolution if the typedef + * KeyEqual::is_transparent exists. If so, K must be hashable and comparable + * to Key. + */ + template ::value>::type * = nullptr> + bool contains(const K &key) const + { + return m_ht.contains(key); + } + + /** + * @copydoc contains(const K& key) const + * + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Useful to speed-up + * the lookup if you already have the hash. + */ + template ::value>::type * = nullptr> + bool contains(const K &key, std::size_t precalculated_hash) const + { + return m_ht.contains(key, precalculated_hash); + } + + std::pair equal_range(const Key &key) { return m_ht.equal_range(key); } + + /** + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Useful to speed-up + * the lookup if you already have the hash. + */ + std::pair equal_range(const Key &key, std::size_t precalculated_hash) + { + return m_ht.equal_range(key, precalculated_hash); + } + + std::pair equal_range(const Key &key) const + { + return m_ht.equal_range(key); + } + + /** + * @copydoc equal_range(const Key& key, std::size_t precalculated_hash) + */ + std::pair equal_range(const Key & key, + std::size_t precalculated_hash) const + { + return m_ht.equal_range(key, precalculated_hash); + } + + /** + * This overload only participates in the overload resolution if the typedef + * KeyEqual::is_transparent exists. If so, K must be hashable and comparable + * to Key. + */ + template ::value>::type * = nullptr> + std::pair equal_range(const K &key) + { + return m_ht.equal_range(key); + } + + /** + * @copydoc equal_range(const K& key) + * + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Useful to speed-up + * the lookup if you already have the hash. + */ + template ::value>::type * = nullptr> + std::pair equal_range(const K &key, std::size_t precalculated_hash) + { + return m_ht.equal_range(key, precalculated_hash); + } + + /** + * @copydoc equal_range(const K& key) + */ + template ::value>::type * = nullptr> + std::pair equal_range(const K &key) const + { + return m_ht.equal_range(key); + } + + /** + * @copydoc equal_range(const K& key, std::size_t precalculated_hash) + */ + template ::value>::type * = nullptr> + std::pair equal_range(const K & key, + std::size_t precalculated_hash) const + { + return m_ht.equal_range(key, precalculated_hash); + } + + /* + * Bucket interface + */ + size_type bucket_count() const { return m_ht.bucket_count(); } + size_type max_bucket_count() const { return m_ht.max_bucket_count(); } + + /* + * Hash policy + */ + float load_factor() const { return m_ht.load_factor(); } + + float min_load_factor() const { return m_ht.min_load_factor(); } + float max_load_factor() const { return m_ht.max_load_factor(); } + + /** + * Set the `min_load_factor` to `ml`. When the `load_factor` of the map goes + * below `min_load_factor` after some erase operations, the map will be + * shrunk when an insertion occurs. The erase method itself never shrinks + * the map. + * + * The default value of `min_load_factor` is 0.0f, the map never shrinks by + * default. + */ + void min_load_factor(float ml) { m_ht.min_load_factor(ml); } + void max_load_factor(float ml) { m_ht.max_load_factor(ml); } + + void rehash(size_type my_count) { m_ht.rehash(my_count); } + void reserve(size_type my_count) { m_ht.reserve(my_count); } + + /* + * Observers + */ + hasher hash_function() const { return m_ht.hash_function(); } + key_equal key_eq() const { return m_ht.key_eq(); } + + /* + * Other + */ + + /** + * Convert a const_iterator to an iterator. + */ + iterator mutable_iterator(const_iterator pos) { return m_ht.mutable_iterator(pos); } + + /** + * Serialize the map through the `serializer` parameter. + * + * The `serializer` parameter must be a function object that supports the + * following call: + * - `template void operator()(const U& value);` where the types + * `std::int16_t`, `std::uint32_t`, `std::uint64_t`, `float` and + * `std::pair` must be supported for U. + * + * The implementation leaves binary compatibility (endianness, IEEE 754 for + * floats, ...) of the types it serializes in the hands of the `Serializer` + * function object if compatibility is required. + */ + template void serialize(Serializer &serializer) const + { + m_ht.serialize(serializer); + } + + /** + * Deserialize a previously serialized map through the `deserializer` + * parameter. + * + * The `deserializer` parameter must be a function object that supports the + * following call: + * - `template U operator()();` where the types `std::int16_t`, + * `std::uint32_t`, `std::uint64_t`, `float` and `std::pair` must be + * supported for U. + * + * If the deserialized hash map type is hash compatible with the serialized + * map, the deserialization process can be sped up by setting + * `hash_compatible` to true. To be hash compatible, the Hash, KeyEqual and + * GrowthPolicy must behave the same way than the ones used on the serialized + * map and the StoreHash must have the same value. The `std::size_t` must also + * be of the same size as the one on the platform used to serialize the map. + * If these criteria are not met, the behaviour is undefined with + * `hash_compatible` sets to true. + * + * The behaviour is undefined if the type `Key` and `T` of the `robin_map` are + * not the same as the types used during serialization. + * + * The implementation leaves binary compatibility (endianness, IEEE 754 for + * floats, size of int, ...) of the types it deserializes in the hands of the + * `Deserializer` function object if compatibility is required. + */ + template + static robin_map deserialize(Deserializer &deserializer, bool hash_compatible = false) + { + robin_map map(0); + map.m_ht.deserialize(deserializer, hash_compatible); + + return map; + } + + friend bool operator==(const robin_map &lhs, const robin_map &rhs) + { + if (lhs.size() != rhs.size()) { + return false; + } + + for (const auto &element_lhs : lhs) { + const auto it_element_rhs = rhs.find(element_lhs.first); + if (it_element_rhs == rhs.cend() || element_lhs.second != it_element_rhs->second) { + return false; + } + } + + return true; + } + + friend bool operator!=(const robin_map &lhs, const robin_map &rhs) + { + return !operator==(lhs, rhs); + } + + friend void swap(robin_map &lhs, robin_map &rhs) { lhs.swap(rhs); } + + private: + ht m_ht; + }; + + /** + * Same as `tsl::robin_map`. + */ + template , class KeyEqual = std::equal_to, + class Allocator = std::allocator>, bool StoreHash = false> + using robin_pg_map = + robin_map; + +} // end namespace tsl + +#endif diff --git a/packages/seacas/libraries/aprepro_lib/robin_set.h b/packages/seacas/libraries/aprepro_lib/robin_set.h new file mode 100644 index 000000000000..067c679492f7 --- /dev/null +++ b/packages/seacas/libraries/aprepro_lib/robin_set.h @@ -0,0 +1,668 @@ +/** + * MIT License + * + * Copyright (c) 2017 Thibaut Goetghebuer-Planchon + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef TSL_ROBIN_SET_H +#define TSL_ROBIN_SET_H + +#include +#include +#include +#include +#include +#include + +#include "robin_hash.h" + +namespace tsl { + + /** + * Implementation of a hash set using open-addressing and the robin hood hashing + * algorithm with backward shift deletion. + * + * For operations modifying the hash set (insert, erase, rehash, ...), the + * strong exception guarantee is only guaranteed when the expression + * `std::is_nothrow_swappable\:\:value && + * std::is_nothrow_move_constructible\:\:value` is true, otherwise if an + * exception is thrown during the swap or the move, the hash set may end up in a + * undefined state. Per the standard a `Key` with a noexcept copy constructor + * and no move constructor also satisfies the + * `std::is_nothrow_move_constructible\:\:value` criterion (and will thus + * guarantee the strong exception for the set). + * + * When `StoreHash` is true, 32 bits of the hash are stored alongside the + * values. It can improve the performance during lookups if the `KeyEqual` + * function takes time (or engenders a cache-miss for example) as we then + * compare the stored hashes before comparing the keys. When + * `tsl::rh::power_of_two_growth_policy` is used as `GrowthPolicy`, it may also + * speed-up the rehash process as we can avoid to recalculate the hash. When it + * is detected that storing the hash will not incur any memory penalty due to + * alignment (i.e. `sizeof(tsl::detail_robin_hash::bucket_entry) == sizeof(tsl::detail_robin_hash::bucket_entry)`) + * and `tsl::rh::power_of_two_growth_policy` is used, the hash will be stored + * even if `StoreHash` is false so that we can speed-up the rehash (but it will + * not be used on lookups unless `StoreHash` is true). + * + * `GrowthPolicy` defines how the set grows and consequently how a hash value is + * mapped to a bucket. By default the set uses + * `tsl::rh::power_of_two_growth_policy`. This policy keeps the number of + * buckets to a power of two and uses a mask to set the hash to a bucket instead + * of the slow modulo. Other growth policies are available and you may define + * your own growth policy, check `tsl::rh::power_of_two_growth_policy` for the + * interface. + * + * `Key` must be swappable. + * + * `Key` must be copy and/or move constructible. + * + * If the destructor of `Key` throws an exception, the behaviour of the class is + * undefined. + * + * Iterators invalidation: + * - clear, operator=, reserve, rehash: always invalidate the iterators. + * - insert, emplace, emplace_hint, operator[]: if there is an effective + * insert, invalidate the iterators. + * - erase: always invalidate the iterators. + */ + template , class KeyEqual = std::equal_to, + class Allocator = std::allocator, bool StoreHash = false, + class GrowthPolicy = tsl::rh::power_of_two_growth_policy<2>> + class robin_set + { + private: + template using has_is_transparent = tsl::detail_robin_hash::has_is_transparent; + + class KeySelect + { + public: + using key_type = Key; + + const key_type &operator()(const Key &key) const noexcept { return key; } + + key_type &operator()(Key &key) noexcept { return key; } + }; + + using ht = detail_robin_hash::robin_hash; + + public: + using key_type = typename ht::key_type; + using value_type = typename ht::value_type; + using size_type = typename ht::size_type; + using difference_type = typename ht::difference_type; + using hasher = typename ht::hasher; + using key_equal = typename ht::key_equal; + using allocator_type = typename ht::allocator_type; + using reference = typename ht::reference; + using const_reference = typename ht::const_reference; + using pointer = typename ht::pointer; + using const_pointer = typename ht::const_pointer; + using iterator = typename ht::iterator; + using const_iterator = typename ht::const_iterator; + + /* + * Constructors + */ + robin_set() : robin_set(ht::DEFAULT_INIT_BUCKETS_SIZE) {} + + explicit robin_set(size_type bucket_count, const Hash &hash = Hash(), + const KeyEqual &equal = KeyEqual(), const Allocator &alloc = Allocator()) + : m_ht(bucket_count, hash, equal, alloc) + { + } + + robin_set(size_type bucket_count, const Allocator &alloc) + : robin_set(bucket_count, Hash(), KeyEqual(), alloc) + { + } + + robin_set(size_type bucket_count, const Hash &hash, const Allocator &alloc) + : robin_set(bucket_count, hash, KeyEqual(), alloc) + { + } + + explicit robin_set(const Allocator &alloc) : robin_set(ht::DEFAULT_INIT_BUCKETS_SIZE, alloc) {} + + template + robin_set(InputIt first, InputIt last, size_type bucket_count = ht::DEFAULT_INIT_BUCKETS_SIZE, + const Hash &hash = Hash(), const KeyEqual &equal = KeyEqual(), + const Allocator &alloc = Allocator()) + : robin_set(bucket_count, hash, equal, alloc) + { + insert(first, last); + } + + template + robin_set(InputIt first, InputIt last, size_type bucket_count, const Allocator &alloc) + : robin_set(first, last, bucket_count, Hash(), KeyEqual(), alloc) + { + } + + template + robin_set(InputIt first, InputIt last, size_type bucket_count, const Hash &hash, + const Allocator &alloc) + : robin_set(first, last, bucket_count, hash, KeyEqual(), alloc) + { + } + + robin_set(std::initializer_list init, + size_type bucket_count = ht::DEFAULT_INIT_BUCKETS_SIZE, const Hash &hash = Hash(), + const KeyEqual &equal = KeyEqual(), const Allocator &alloc = Allocator()) + : robin_set(init.begin(), init.end(), bucket_count, hash, equal, alloc) + { + } + + robin_set(std::initializer_list init, size_type bucket_count, + const Allocator &alloc) + : robin_set(init.begin(), init.end(), bucket_count, Hash(), KeyEqual(), alloc) + { + } + + robin_set(std::initializer_list init, size_type bucket_count, const Hash &hash, + const Allocator &alloc) + : robin_set(init.begin(), init.end(), bucket_count, hash, KeyEqual(), alloc) + { + } + + robin_set &operator=(std::initializer_list ilist) + { + m_ht.clear(); + + m_ht.reserve(ilist.size()); + m_ht.insert(ilist.begin(), ilist.end()); + + return *this; + } + + allocator_type get_allocator() const { return m_ht.get_allocator(); } + + /* + * Iterators + */ + iterator begin() noexcept { return m_ht.begin(); } + const_iterator begin() const noexcept { return m_ht.begin(); } + const_iterator cbegin() const noexcept { return m_ht.cbegin(); } + + iterator end() noexcept { return m_ht.end(); } + const_iterator end() const noexcept { return m_ht.end(); } + const_iterator cend() const noexcept { return m_ht.cend(); } + + /* + * Capacity + */ + bool empty() const noexcept { return m_ht.empty(); } + size_type size() const noexcept { return m_ht.size(); } + size_type max_size() const noexcept { return m_ht.max_size(); } + + /* + * Modifiers + */ + void clear() noexcept { m_ht.clear(); } + + std::pair insert(const value_type &value) { return m_ht.insert(value); } + + std::pair insert(value_type &&value) { return m_ht.insert(std::move(value)); } + + iterator insert(const_iterator hint, const value_type &value) + { + return m_ht.insert_hint(hint, value); + } + + iterator insert(const_iterator hint, value_type &&value) + { + return m_ht.insert_hint(hint, std::move(value)); + } + + template void insert(InputIt first, InputIt last) { m_ht.insert(first, last); } + + void insert(std::initializer_list ilist) + { + m_ht.insert(ilist.begin(), ilist.end()); + } + + /** + * Due to the way elements are stored, emplace will need to move or copy the + * key-value once. The method is equivalent to + * insert(value_type(std::forward(args)...)); + * + * Mainly here for compatibility with the std::unordered_map interface. + */ + template std::pair emplace(Args &&...args) + { + return m_ht.emplace(std::forward(args)...); + } + + /** + * Due to the way elements are stored, emplace_hint will need to move or copy + * the key-value once. The method is equivalent to insert(hint, + * value_type(std::forward(args)...)); + * + * Mainly here for compatibility with the std::unordered_map interface. + */ + template iterator emplace_hint(const_iterator hint, Args &&...args) + { + return m_ht.emplace_hint(hint, std::forward(args)...); + } + + iterator erase(iterator pos) { return m_ht.erase(pos); } + iterator erase(const_iterator pos) { return m_ht.erase(pos); } + iterator erase(const_iterator first, const_iterator last) { return m_ht.erase(first, last); } + size_type erase(const key_type &key) { return m_ht.erase(key); } + + /** + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Useful to speed-up + * the lookup to the value if you already have the hash. + */ + size_type erase(const key_type &key, std::size_t precalculated_hash) + { + return m_ht.erase(key, precalculated_hash); + } + + /** + * This overload only participates in the overload resolution if the typedef + * KeyEqual::is_transparent exists. If so, K must be hashable and comparable + * to Key. + */ + template ::value>::type * = nullptr> + size_type erase(const K &key) + { + return m_ht.erase(key); + } + + /** + * @copydoc erase(const K& key) + * + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Useful to speed-up + * the lookup to the value if you already have the hash. + */ + template ::value>::type * = nullptr> + size_type erase(const K &key, std::size_t precalculated_hash) + { + return m_ht.erase(key, precalculated_hash); + } + + void swap(robin_set &other) { other.m_ht.swap(m_ht); } + + /* + * Lookup + */ + size_type count(const Key &key) const { return m_ht.count(key); } + + /** + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Useful to speed-up + * the lookup if you already have the hash. + */ + size_type count(const Key &key, std::size_t precalculated_hash) const + { + return m_ht.count(key, precalculated_hash); + } + + /** + * This overload only participates in the overload resolution if the typedef + * KeyEqual::is_transparent exists. If so, K must be hashable and comparable + * to Key. + */ + template ::value>::type * = nullptr> + size_type count(const K &key) const + { + return m_ht.count(key); + } + + /** + * @copydoc count(const K& key) const + * + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Useful to speed-up + * the lookup if you already have the hash. + */ + template ::value>::type * = nullptr> + size_type count(const K &key, std::size_t precalculated_hash) const + { + return m_ht.count(key, precalculated_hash); + } + + iterator find(const Key &key) { return m_ht.find(key); } + + /** + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Useful to speed-up + * the lookup if you already have the hash. + */ + iterator find(const Key &key, std::size_t precalculated_hash) + { + return m_ht.find(key, precalculated_hash); + } + + const_iterator find(const Key &key) const { return m_ht.find(key); } + + /** + * @copydoc find(const Key& key, std::size_t precalculated_hash) + */ + const_iterator find(const Key &key, std::size_t precalculated_hash) const + { + return m_ht.find(key, precalculated_hash); + } + + /** + * This overload only participates in the overload resolution if the typedef + * KeyEqual::is_transparent exists. If so, K must be hashable and comparable + * to Key. + */ + template ::value>::type * = nullptr> + iterator find(const K &key) + { + return m_ht.find(key); + } + + /** + * @copydoc find(const K& key) + * + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Useful to speed-up + * the lookup if you already have the hash. + */ + template ::value>::type * = nullptr> + iterator find(const K &key, std::size_t precalculated_hash) + { + return m_ht.find(key, precalculated_hash); + } + + /** + * @copydoc find(const K& key) + */ + template ::value>::type * = nullptr> + const_iterator find(const K &key) const + { + return m_ht.find(key); + } + + /** + * @copydoc find(const K& key) + * + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Useful to speed-up + * the lookup if you already have the hash. + */ + template ::value>::type * = nullptr> + const_iterator find(const K &key, std::size_t precalculated_hash) const + { + return m_ht.find(key, precalculated_hash); + } + + bool contains(const Key &key) const { return m_ht.contains(key); } + + /** + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Useful to speed-up + * the lookup if you already have the hash. + */ + bool contains(const Key &key, std::size_t precalculated_hash) const + { + return m_ht.contains(key, precalculated_hash); + } + + /** + * This overload only participates in the overload resolution if the typedef + * KeyEqual::is_transparent exists. If so, K must be hashable and comparable + * to Key. + */ + template ::value>::type * = nullptr> + bool contains(const K &key) const + { + return m_ht.contains(key); + } + + /** + * @copydoc contains(const K& key) const + * + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Useful to speed-up + * the lookup if you already have the hash. + */ + template ::value>::type * = nullptr> + bool contains(const K &key, std::size_t precalculated_hash) const + { + return m_ht.contains(key, precalculated_hash); + } + + std::pair equal_range(const Key &key) { return m_ht.equal_range(key); } + + /** + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Useful to speed-up + * the lookup if you already have the hash. + */ + std::pair equal_range(const Key &key, std::size_t precalculated_hash) + { + return m_ht.equal_range(key, precalculated_hash); + } + + std::pair equal_range(const Key &key) const + { + return m_ht.equal_range(key); + } + + /** + * @copydoc equal_range(const Key& key, std::size_t precalculated_hash) + */ + std::pair equal_range(const Key & key, + std::size_t precalculated_hash) const + { + return m_ht.equal_range(key, precalculated_hash); + } + + /** + * This overload only participates in the overload resolution if the typedef + * KeyEqual::is_transparent exists. If so, K must be hashable and comparable + * to Key. + */ + template ::value>::type * = nullptr> + std::pair equal_range(const K &key) + { + return m_ht.equal_range(key); + } + + /** + * @copydoc equal_range(const K& key) + * + * Use the hash value 'precalculated_hash' instead of hashing the key. The + * hash value should be the same as hash_function()(key). Useful to speed-up + * the lookup if you already have the hash. + */ + template ::value>::type * = nullptr> + std::pair equal_range(const K &key, std::size_t precalculated_hash) + { + return m_ht.equal_range(key, precalculated_hash); + } + + /** + * @copydoc equal_range(const K& key) + */ + template ::value>::type * = nullptr> + std::pair equal_range(const K &key) const + { + return m_ht.equal_range(key); + } + + /** + * @copydoc equal_range(const K& key, std::size_t precalculated_hash) + */ + template ::value>::type * = nullptr> + std::pair equal_range(const K & key, + std::size_t precalculated_hash) const + { + return m_ht.equal_range(key, precalculated_hash); + } + + /* + * Bucket interface + */ + size_type bucket_count() const { return m_ht.bucket_count(); } + size_type max_bucket_count() const { return m_ht.max_bucket_count(); } + + /* + * Hash policy + */ + float load_factor() const { return m_ht.load_factor(); } + + float min_load_factor() const { return m_ht.min_load_factor(); } + float max_load_factor() const { return m_ht.max_load_factor(); } + + /** + * Set the `min_load_factor` to `ml`. When the `load_factor` of the set goes + * below `min_load_factor` after some erase operations, the set will be + * shrunk when an insertion occurs. The erase method itself never shrinks + * the set. + * + * The default value of `min_load_factor` is 0.0f, the set never shrinks by + * default. + */ + void min_load_factor(float ml) { m_ht.min_load_factor(ml); } + void max_load_factor(float ml) { m_ht.max_load_factor(ml); } + + void rehash(size_type my_count) { m_ht.rehash(my_count); } + void reserve(size_type my_count) { m_ht.reserve(my_count); } + + /* + * Observers + */ + hasher hash_function() const { return m_ht.hash_function(); } + key_equal key_eq() const { return m_ht.key_eq(); } + + /* + * Other + */ + + /** + * Convert a const_iterator to an iterator. + */ + iterator mutable_iterator(const_iterator pos) { return m_ht.mutable_iterator(pos); } + + friend bool operator==(const robin_set &lhs, const robin_set &rhs) + { + if (lhs.size() != rhs.size()) { + return false; + } + + for (const auto &element_lhs : lhs) { + const auto it_element_rhs = rhs.find(element_lhs); + if (it_element_rhs == rhs.cend()) { + return false; + } + } + + return true; + } + + /** + * Serialize the set through the `serializer` parameter. + * + * The `serializer` parameter must be a function object that supports the + * following call: + * - `template void operator()(const U& value);` where the types + * `std::int16_t`, `std::uint32_t`, `std::uint64_t`, `float` and `Key` must be + * supported for U. + * + * The implementation leaves binary compatibility (endianness, IEEE 754 for + * floats, ...) of the types it serializes in the hands of the `Serializer` + * function object if compatibility is required. + */ + template void serialize(Serializer &serializer) const + { + m_ht.serialize(serializer); + } + + /** + * Deserialize a previously serialized set through the `deserializer` + * parameter. + * + * The `deserializer` parameter must be a function object that supports the + * following call: + * - `template U operator()();` where the types `std::int16_t`, + * `std::uint32_t`, `std::uint64_t`, `float` and `Key` must be supported for + * U. + * + * If the deserialized hash set type is hash compatible with the serialized + * set, the deserialization process can be sped up by setting + * `hash_compatible` to true. To be hash compatible, the Hash, KeyEqual and + * GrowthPolicy must behave the same way than the ones used on the serialized + * set and the StoreHash must have the same value. The `std::size_t` must also + * be of the same size as the one on the platform used to serialize the set. + * If these criteria are not met, the behaviour is undefined with + * `hash_compatible` sets to true. + * + * The behaviour is undefined if the type `Key` of the `robin_set` is not the + * same as the type used during serialization. + * + * The implementation leaves binary compatibility (endianness, IEEE 754 for + * floats, size of int, ...) of the types it deserializes in the hands of the + * `Deserializer` function object if compatibility is required. + */ + template + static robin_set deserialize(Deserializer &deserializer, bool hash_compatible = false) + { + robin_set set(0); + set.m_ht.deserialize(deserializer, hash_compatible); + + return set; + } + + friend bool operator!=(const robin_set &lhs, const robin_set &rhs) + { + return !operator==(lhs, rhs); + } + + friend void swap(robin_set &lhs, robin_set &rhs) { lhs.swap(rhs); } + + private: + ht m_ht; + }; + + /** + * Same as `tsl::robin_set`. + */ + template , class KeyEqual = std::equal_to, + class Allocator = std::allocator, bool StoreHash = false> + using robin_pg_set = + robin_set; + +} // end namespace tsl + +#endif diff --git a/packages/seacas/libraries/aprepro_lib/test-array.stderr.gold b/packages/seacas/libraries/aprepro_lib/test-array.stderr.gold index 86b5ddb7134e..1ad518b3da4f 100644 --- a/packages/seacas/libraries/aprepro_lib/test-array.stderr.gold +++ b/packages/seacas/libraries/aprepro_lib/test-array.stderr.gold @@ -1,19 +1,19 @@ $ Variable = Value -$ {a (array) rows = 27, cols = 21} -$ {b (array) rows = 3, cols = 2} $ {c (array) rows = 2, cols = 3} -$ {d (array) rows = 3, cols = 3} -$ {e (array) rows = 2, cols = 2} -$ {_col = 3} -$ {std (array) rows = 10, cols = 1} -$ {asub_rows = 17} -$ {st (array) rows = 20, cols = 1} $ {_c = 3} -$ {_r = 2} +$ {a (array) rows = 27, cols = 21} +$ {BirthYear = 1958} $ {a_rows = 27} -$ {BirthYear = 1958} -$ {asub (array) rows = 17, cols = 21} +$ {asub_rows = 17} +$ {std (array) rows = 10, cols = 1} +$ {b (array) rows = 3, cols = 2} +$ {Greg = "Is the author of this code"} (immutable) $ {_therow = 2} +$ {_r = 2} +$ {asub (array) rows = 17, cols = 21} +$ {_col = 3} +$ {e (array) rows = 2, cols = 2} +$ {d (array) rows = 3, cols = 3} $ {et (array) rows = 2, cols = 2} -$ {Greg = "Is the author of this code"} (immutable) +$ {st (array) rows = 20, cols = 1} diff --git a/packages/seacas/libraries/exodus/include/doxygen.h b/packages/seacas/libraries/exodus/include/doxygen.h index 3c6eb9defb8a..b6b93235ac83 100644 --- a/packages/seacas/libraries/exodus/include/doxygen.h +++ b/packages/seacas/libraries/exodus/include/doxygen.h @@ -35,7 +35,7 @@ For bug reports, documentation errors, and enhancement suggestions, contact: \section license License The EXODUS library is licensed under the BSD open source license. - Copyright(C) 1999-2020 National Technology & Engineering Solutions + Copyright(C) 1999-2021 National Technology & Engineering Solutions of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S. Government retains certain rights in this software. @@ -409,7 +409,6 @@ element attributes, node sets, side sets, and object properties. @example ../test/testcp_nl.c @example ../test/testcp_tran.c @example ../test/testcpd.c -@example ../test/testrd-groups.c @example ../test/testrd-long-name.c @example ../test/testrd-nfaced.c @example ../test/testrd-nsided.c diff --git a/packages/seacas/libraries/exodus/include/exodusII_cfg.h.in b/packages/seacas/libraries/exodus/include/exodusII_cfg.h.in index ade7371a22f1..2b5090a63e4b 100644 --- a/packages/seacas/libraries/exodus/include/exodusII_cfg.h.in +++ b/packages/seacas/libraries/exodus/include/exodusII_cfg.h.in @@ -1,4 +1,4 @@ -# Copyright(C) 1999-2020 National Technology & Engineering Solutions +# Copyright(C) 1999-2021 National Technology & Engineering Solutions # of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with # NTESS, the U.S. Government retains certain rights in this software. # @@ -7,17 +7,16 @@ #ifndef __exodusII_cfg_h #define __exodusII_cfg_h -#if defined(_WIN32) && !defined(WIN32) -# define WIN32 -#endif - #cmakedefine EXODUSII_BUILD_SHARED_LIBS -#if defined(WIN32) && defined(EXODUSII_BUILD_SHARED_LIBS) +#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || \ + defined(__MINGW32__) || defined(_WIN64) || defined(__MINGW64__) +#if defined(EXODUSII_BUILD_SHARED_LIBS) # if defined(exoIIc_EXPORTS) # define EXODUS_EXPORT __declspec( dllexport ) extern # else # define EXODUS_EXPORT __declspec( dllimport ) extern # endif +#endif #else # define EXODUS_EXPORT extern #endif diff --git a/packages/seacas/libraries/exodus/src/ex_utils.c b/packages/seacas/libraries/exodus/src/ex_utils.c index 0a638672c310..8f74098d083d 100644 --- a/packages/seacas/libraries/exodus/src/ex_utils.c +++ b/packages/seacas/libraries/exodus/src/ex_utils.c @@ -56,9 +56,11 @@ extern int H5get_libversion(unsigned *, unsigned *, unsigned *); #endif #endif +#if 0 #if NC_HAS_PNETCDF extern char *ncmpi_inq_libvers(); #endif +#endif /*! \ingroup Utilities @@ -124,8 +126,12 @@ const char *ex_config(void) #endif #if NC_HAS_PNETCDF { +#if 0 char *libver = ncmpi_inq_libvers(); j += sprintf(buffer + j, "\t\tParallel IO enabled via PnetCDF (%s)\n", libver); +#else + j += sprintf(buffer + j, "\t\tParallel IO enabled via PnetCDF.\n"); +#endif } #else j += sprintf(buffer + j, "\t\tParallel IO *NOT* enabled via PnetCDF\n"); diff --git a/packages/seacas/libraries/ioss/src/Ioss_CodeTypes.h b/packages/seacas/libraries/ioss/src/Ioss_CodeTypes.h index 82c12ec3c62c..5905dbb81ed9 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_CodeTypes.h +++ b/packages/seacas/libraries/ioss/src/Ioss_CodeTypes.h @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2020 National Technology & Engineering Solutions +// Copyright(C) 1999-2021 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -13,7 +13,12 @@ #include #include -#if defined(_MSC_VER) +#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || \ + defined(__MINGW32__) || defined(_WIN64) || defined(__MINGW64__) +#define __IOSS_WINDOWS__ 1 +#endif + +#if defined(__IOSS_WINDOWS__) #ifdef _WIN64 #define ssize_t __int64 #else diff --git a/packages/seacas/libraries/ioss/src/Ioss_CopyDatabase.C b/packages/seacas/libraries/ioss/src/Ioss_CopyDatabase.C index 9476d6f535a2..78011a62f6cd 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_CopyDatabase.C +++ b/packages/seacas/libraries/ioss/src/Ioss_CopyDatabase.C @@ -16,7 +16,7 @@ #include // For Sleep... -#if defined(_WIN32) +#if defined(__IOSS_WINDOWS__) #define WIN32_LEAN_AND_MEAN #define NOMINMAX #include diff --git a/packages/seacas/libraries/ioss/src/Ioss_Decomposition.h b/packages/seacas/libraries/ioss/src/Ioss_Decomposition.h index 9d95597900b9..5ffddf008f0a 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_Decomposition.h +++ b/packages/seacas/libraries/ioss/src/Ioss_Decomposition.h @@ -645,8 +645,8 @@ namespace Ioss { std::vector exportNodeCount; std::vector exportNodeIndex; - std::vector - importNodeMap; // Where to put each imported nodes data in the list of all data... + // Where to put each imported nodes data in the list of all data... + std::vector importNodeMap; std::vector importNodeCount; std::vector importNodeIndex; diff --git a/packages/seacas/libraries/ioss/src/Ioss_FileInfo.C b/packages/seacas/libraries/ioss/src/Ioss_FileInfo.C index b51a9e8b1151..f29e37f639d0 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_FileInfo.C +++ b/packages/seacas/libraries/ioss/src/Ioss_FileInfo.C @@ -13,9 +13,7 @@ #include #include -#ifndef _WIN32 -#include -#else +#if defined(__IOSS_WINDOWS__) #include #include #define access _access @@ -27,6 +25,8 @@ #define S_ISREG(m) (((m)&_S_IFMT) == _S_IFREG) #define S_ISDIR(m) (((m)&_S_IFMT) == _S_IFDIR) #endif +#else +#include #endif #ifdef SEACAS_HAVE_MPI @@ -156,7 +156,7 @@ namespace Ioss { //: Returns TRUE if we are pointing to a symbolic link bool FileInfo::is_symlink() const { -#ifndef _WIN32 +#if !defined(__IOSS_WINDOWS__) struct stat s { }; @@ -289,7 +289,7 @@ namespace Ioss { std::string FileInfo::realpath() const { -#ifdef _WIN32 +#if defined(__IOSS_WINDOWS__) char *path = _fullpath(nullptr, filename_.c_str(), _MAX_PATH); #else char *path = ::realpath(filename_.c_str(), nullptr); @@ -325,7 +325,7 @@ namespace Ioss { struct stat st; if (stat(path_root.c_str(), &st) != 0) { -#ifdef _WIN32 +#if defined(__IOSS_WINDOWS__) if (mkdir(path_root.c_str()) != 0 && errno != EEXIST) { #else const int mode = 0777; // Users umask will be applied to this. diff --git a/packages/seacas/libraries/ioss/src/Ioss_Getline.c b/packages/seacas/libraries/ioss/src/Ioss_Getline.c index 8a740b955d7c..ada6f330aa04 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_Getline.c +++ b/packages/seacas/libraries/ioss/src/Ioss_Getline.c @@ -1,6 +1,6 @@ /* - * Copyright (C) 1991, 1992, 1993, 2020, 2021 by Chris Thewalt (thewalt@ce.berkeley.edu) + * Copyright (C) 1991, 1992, 1993, 2021 by Chris Thewalt (thewalt@ce.berkeley.edu) * * Permission to use, copy, modify, and distribute this software * for any purpose and without fee is hereby granted, provided @@ -19,114 +19,47 @@ * Note: This version has been updated by Mike Gleason */ -#if defined(_WIN32) +#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || \ + defined(__MINGW32__) || defined(_WIN64) #define __windows__ 1 #include -#include -#include #include -#include -#include #define NOMINMAX #include -#define strcasecmp stricmp -#define strncasecmp strnicmp #define sleep(a) Sleep(a * 1000) -#ifndef S_ISREG -#define S_ISREG(m) (((m)&_S_IFMT) == _S_IFREG) -#define S_ISDIR(m) (((m)&_S_IFMT) == _S_IFDIR) -#endif -#ifndef open -#define open _open +#ifndef write #define write _write #define read _read -#define close _close -#define lseek _lseek -#define stat _stat -#define lstat _stat -#define fstat _fstat -#define dup _dup -#define utime _utime -#define utimbuf _utimbuf #endif -#ifndef unlink -#define unlink remove -#endif -#define NO_SIGNALS 1 -#define LOCAL_PATH_DELIM '\\' -#define LOCAL_PATH_DELIM_STR "\\" -#define LOCAL_PATH_ALTDELIM '/' -#define IsLocalPathDelim(c) ((c == LOCAL_PATH_DELIM) || (c == LOCAL_PATH_ALTDELIM)) -#define UNC_PATH_PREFIX "\\\\" -#define IsUNCPrefixed(s) (IsLocalPathDelim(s[0]) && IsLocalPathDelim(s[1])) -#define pid_t int - #else +#ifndef __unix__ #define __unix__ 1 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#define HAVE_TERMIOS_H 1 -#ifdef HAVE_TERMIOS_H /* use HAVE_TERMIOS_H interface */ +#endif + #include struct termios new_termios, old_termios; -#else /* not HAVE_TERMIOS_H */ -#include -#ifdef TIOCSETN /* use BSD interface */ -#include -struct sgttyb new_tty, old_tty; -struct tchars tch; -struct ltchars ltch; -#else /* use SYSV interface */ -#include -struct termio new_termio, old_termio; -#endif /* TIOCSETN */ -#endif /* HAVE_TERMIOS_H */ -#define LOCAL_PATH_DELIM '/' -#define LOCAL_PATH_DELIM_STR "/" -#define _StrFindLocalPathDelim(a) strchr(a, LOCAL_PATH_DELIM) -#define _StrRFindLocalPathDelim(a) strrchr(a, LOCAL_PATH_DELIM) -#define IsLocalPathDelim(c) (c == LOCAL_PATH_DELIM) #endif /********************* C library headers ********************************/ #include -#include +#include #include #include #include -#include -#include -#include #include -extern int kill(pid_t pid, int sig); - -#define _io_getline_c_ 1 #include "Ioss_Getline.h" -static int io_gl_tab(char *buf, int offset, int *loc, size_t bufsize); +#define IO_GL_BUF_SIZE 1024 /******************** external interface *********************************/ -io_gl_in_hook_proc io_gl_in_hook = NULL; -io_gl_out_hook_proc io_gl_out_hook = NULL; -io_gl_tab_hook_proc io_gl_tab_hook = io_gl_tab; -io_gl_strlen_proc io_gl_strlen = (io_gl_strlen_proc)strlen; -io_gl_tab_completion_proc io_gl_completion_proc = NULL; -int io_gl_filename_quoting_desired = -1; /* default to unspecified */ -const char * io_gl_filename_quote_characters = " \t*?<>|;&()[]$`"; -int io_gl_ellipses_during_completion = 1; -int io_gl_completion_exact_match_extra_char; -char io_gl_buf[IO_GL_BUF_SIZE]; /* input buffer */ +int io_gl_filename_quoting_desired = -1; /* default to unspecified */ +const char *io_gl_filename_quote_characters = " \t*?<>|;&()[]$`"; +int io_gl_ellipses_during_completion = 1; +char io_gl_buf[IO_GL_BUF_SIZE]; /* input buffer */ /******************** internal interface *********************************/ @@ -139,15 +72,7 @@ static int io_gl_overwrite = 0; /* overwrite mode */ static int io_gl_pos, io_gl_cnt = 0; /* position and size of input */ static char io_gl_killbuf[IO_GL_BUF_SIZE] = ""; /* killed text */ static const char *io_gl_prompt; /* to save the prompt string */ -static char io_gl_intrc = 0; /* keyboard SIGINT char */ -static char io_gl_quitc = 0; /* keyboard SIGQUIT char */ -static char io_gl_suspc = 0; /* keyboard SIGTSTP char */ -static char io_gl_dsuspc = 0; /* delayed SIGTSTP char */ -static int io_gl_search_mode = 0; /* search mode flag */ -static char ** io_gl_matchlist = NULL; -static char * io_gl_home_dir = NULL; -static int io_gl_vi_preferred = -1; -static int io_gl_vi_mode = 0; +static int io_gl_search_mode = 0; /* search mode flag */ static void io_gl_init(void); /* prepare to edit a line */ static void io_gl_cleanup(void); /* to undo io_gl_init */ @@ -159,18 +84,15 @@ static void io_gl_addchar(int c); /* install specified char */ static void io_gl_del(int loc, int); /* del, either left (-1) or cur (0) */ static void io_gl_error(const char *const buf); /* write error msg and die */ static void io_gl_fixup(const char *prompt, int change, - int cursor); /* fixup state variables and screen */ -static int io_gl_getc(void); /* read one char from terminal */ -static int io_gl_getcx(int); /* read one char from terminal, if available before timeout */ -static void io_gl_kill(int pos); /* delete to EOL */ -static void io_gl_newline(void); /* handle \n or \r */ -static void io_gl_putc(int c); /* write one char to terminal */ + int cursor); /* fixup state variables and screen */ +static int io_gl_getc(void); /* read one char from terminal */ +static void io_gl_kill(int pos); /* delete to EOL */ +static void io_gl_newline(void); /* handle \n or \r */ +static void io_gl_putc(int c); /* write one char to terminal */ static void io_gl_puts(const char *const buf); /* write a line to terminal */ static void io_gl_redraw(void); /* issue \n and redraw all */ static void io_gl_transpose(void); /* transpose two chars */ static void io_gl_yank(void); /* yank killed text */ -static void io_gl_word(int direction); /* move a word */ -static void io_gl_killword(int direction); static void hist_init(void); /* initializes hist pointers */ static char *hist_next(void); /* return ptr to next item */ @@ -183,8 +105,6 @@ static void search_back(int new_search); /* look back for current string */ static void search_forw(int new_search); /* look forw for current string */ static void io_gl_beep(void); /* try to play a system beep sound */ -static int io_gl_do_tab_completion(char *buf, int *loc, size_t bufsize); - static char *copy_string(char *dest, char const *source, long int elements) { char *d; @@ -204,16 +124,7 @@ static char *copy_string(char *dest, char const *source, long int elements) static void io_gl_char_init(void) /* turn off input echo */ { #ifdef __unix__ -#ifdef HAVE_TERMIOS_H /* Use POSIX */ tcgetattr(0, &old_termios); - io_gl_intrc = old_termios.c_cc[VINTR]; - io_gl_quitc = old_termios.c_cc[VQUIT]; -#ifdef VSUSP - io_gl_suspc = old_termios.c_cc[VSUSP]; -#endif -#ifdef VDSUSP - io_gl_dsuspc = old_termios.c_cc[VDSUSP]; -#endif new_termios = old_termios; new_termios.c_iflag &= ~(BRKINT | ISTRIP | IXON | IXOFF); new_termios.c_iflag |= (IGNBRK | IGNPAR); @@ -221,43 +132,13 @@ static void io_gl_char_init(void) /* turn off input echo */ new_termios.c_cc[VMIN] = 1; new_termios.c_cc[VTIME] = 0; tcsetattr(0, TCSANOW, &new_termios); -#elif defined(TIOCSETN) /* BSD */ - ioctl(0, TIOCGETC, &tch); - ioctl(0, TIOCGLTC, <ch); - io_gl_intrc = tch.t_intrc; - io_gl_quitc = tch.t_quitc; - io_gl_suspc = ltch.t_suspc; - io_gl_dsuspc = ltch.t_dsuspc; - ioctl(0, TIOCGETP, &old_tty); - new_tty = old_tty; - new_tty.sg_flags |= RAW; - new_tty.sg_flags &= ~ECHO; - ioctl(0, TIOCSETN, &new_tty); -#else /* SYSV */ - ioctl(0, TCGETA, &old_termio); - io_gl_intrc = old_termio.c_cc[VINTR]; - io_gl_quitc = old_termio.c_cc[VQUIT]; - new_termio = old_termio; - new_termio.c_iflag &= ~(BRKINT | ISTRIP | IXON | IXOFF); - new_termio.c_iflag |= (IGNBRK | IGNPAR); - new_termio.c_lflag &= ~(ICANON | ISIG | ECHO); - new_termio.c_cc[VMIN] = 1; - new_termio.c_cc[VTIME] = 0; - ioctl(0, TCSETA, &new_termio); -#endif #endif /* __unix__ */ } static void io_gl_char_cleanup(void) /* undo effects of io_gl_char_init */ { #ifdef __unix__ -#ifdef HAVE_TERMIOS_H tcsetattr(0, TCSANOW, &old_termios); -#elif defined(TIOCSETN) /* BSD */ - ioctl(0, TIOCSETN, &old_tty); -#else /* SYSV */ - ioctl(0, TCSETA, &old_termio); -#endif #endif /* __unix__ */ } @@ -348,75 +229,6 @@ static int io_gl_getc(void) return c; } -#ifdef __unix__ - -static int io_gl_getcx(int tlen) -/* Get a character without echoing it to screen, timing out - * after tlen tenths of a second. - */ -{ - fd_set ss; - struct timeval tv; - - for (errno = 0;;) { - FD_ZERO(&ss); - FD_SET(0, &ss); /* set STDIN_FILENO */ - tv.tv_sec = tlen / 10; - tv.tv_usec = (tlen % 10) * 100000L; - int result = select(1, &ss, NULL, NULL, &tv); - if (result == 1) { - /* ready */ - break; - } - if (result == 0) { - errno = ETIMEDOUT; - return (-2); - } - else if (errno != EINTR) { - return (-1); - } - } - - for (errno = 0;;) { - char ch; - int c = read(0, &ch, 1); - if (c == 1) { - return ((int)ch); - } - if (errno != EINTR) { - break; - } - } - - return (-1); -} /* io_gl_getcx */ - -#endif /* __unix__ */ - -#ifdef __windows__ - -static int io_gl_getcx(int tlen) -{ - int c = (-2); - tlen -= 2; /* Adjust for 200ms overhead */ - if (tlen < 1) - tlen = 1; - for (int i = 0; i < tlen; i++) { - if (_kbhit()) { - c = (int)_getch(); - if ((c == 0) || (c == 0xE0)) { - /* Read key code */ - c = (int)_getch(); - c = pc_keymap(c); - } - } - (void)SleepEx((DWORD)(tlen * 100), FALSE); - } - return (c); -} /* io_gl_getcx */ - -#endif /* __windows__ */ - static void io_gl_putc(int c) { char ch = (char)(unsigned char)c; @@ -458,7 +270,6 @@ static void io_gl_init(void) io_gl_setwidth(w); } hist_init(); - io_gl_completion_proc = io_gl_local_filename_completion_proc; } if (isatty(0) == 0 || isatty(1) == 0) io_gl_error("\n*** Error: getline(): not interactive, use stdio.\n"); @@ -493,33 +304,10 @@ void io_gl_setwidth(int w) char *io_getline_int(const char *prompt) { - char vi_countbuf[32]; - -#ifdef __unix__ - int sig; -#endif - - /* Even if it appears that "vi" is preferred, we - * don't start in io_gl_vi_mode. They need to hit - * ESC to go into vi command mode. - */ - io_gl_vi_mode = 0; - int vi_count = 0; - int vi_delete = 0; - if (io_gl_vi_preferred < 0) { - io_gl_vi_preferred = 0; - char *cp = (char *)getenv("EDITOR"); - if (cp != NULL) - io_gl_vi_preferred = (strstr(cp, "vi") != NULL); - } - io_gl_init(); io_gl_prompt = (prompt) ? prompt : ""; io_gl_buf[0] = '\0'; - if (io_gl_in_hook) - io_gl_in_hook(io_gl_buf); io_gl_fixup(io_gl_prompt, -2, IO_GL_BUF_SIZE); - int lastch = 0; #ifdef __windows__ FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE)); @@ -529,139 +317,7 @@ char *io_getline_int(const char *prompt) while ((c = io_gl_getc()) >= 0) { io_gl_extent = 0; /* reset to full extent */ if (isprint(c)) { - if (io_gl_vi_mode > 0) { - /* "vi" emulation -- far from perfect, - * but reasonably functional. - */ - vi: - for (int count = 0;;) { - if (isdigit(c)) { - if (vi_countbuf[sizeof(vi_countbuf) - 2] == '\0') - vi_countbuf[strlen(vi_countbuf)] = (char)c; - } - else if (vi_countbuf[0] != '\0') { - vi_count = atoi(vi_countbuf); - memset(vi_countbuf, 0, sizeof(vi_countbuf)); - } - switch (c) { - case 'b': io_gl_word(-1); break; - case 'w': - if (vi_delete) { - io_gl_killword(1); - } - else { - io_gl_word(1); - } - break; - case 'h': /* left */ - if (vi_delete) { - if (io_gl_pos > 0) { - io_gl_fixup(io_gl_prompt, -1, io_gl_pos - 1); - io_gl_del(0, 1); - } - } - else { - io_gl_fixup(io_gl_prompt, -1, io_gl_pos - 1); - } - break; - case ' ': - case 'l': /* right */ - if (vi_delete) { - io_gl_del(0, 1); - } - else { - io_gl_fixup(io_gl_prompt, -1, io_gl_pos + 1); - } - break; - case 'k': /* up */ - copy_string(io_gl_buf, hist_prev(), IO_GL_BUF_SIZE); - if (io_gl_in_hook) - io_gl_in_hook(io_gl_buf); - io_gl_fixup(io_gl_prompt, 0, IO_GL_BUF_SIZE); - break; - case 'j': /* down */ - copy_string(io_gl_buf, hist_next(), IO_GL_BUF_SIZE); - if (io_gl_in_hook) - io_gl_in_hook(io_gl_buf); - io_gl_fixup(io_gl_prompt, 0, IO_GL_BUF_SIZE); - break; - case 'd': - if (vi_delete == 1) { - io_gl_kill(0); - vi_count = 1; - vi_delete = 0; - io_gl_vi_mode = 0; - goto vi_break; - } - else { - vi_delete = 1; - goto vi_break; - } - break; - case '^': /* start of line */ - if (vi_delete) { - vi_count = io_gl_pos; - io_gl_fixup(io_gl_prompt, -1, 0); - for (c = 0; c < vi_count; c++) { - if (io_gl_cnt > 0) - io_gl_del(0, 0); - } - vi_count = 1; - vi_delete = 0; - } - else { - io_gl_fixup(io_gl_prompt, -1, 0); - } - break; - case '$': /* end of line */ - if (vi_delete) { - io_gl_kill(io_gl_pos); - } - else { - int loc = (int)strlen(io_gl_buf); - if (loc > 1) - loc--; - io_gl_fixup(io_gl_prompt, -1, loc); - } - break; - case 'p': /* paste after */ - io_gl_fixup(io_gl_prompt, -1, io_gl_pos + 1); - io_gl_yank(); - break; - case 'P': /* paste before */ io_gl_yank(); break; - case 'r': /* replace character */ - io_gl_buf[io_gl_pos] = (char)io_gl_getc(); - io_gl_fixup(io_gl_prompt, io_gl_pos, io_gl_pos); - vi_count = 1; - break; - case 'R': - io_gl_overwrite = 1; - io_gl_vi_mode = 0; - break; - case 'i': - case 'I': - io_gl_overwrite = 0; - io_gl_vi_mode = 0; - break; - case 'o': - case 'O': - case 'a': - case 'A': - io_gl_overwrite = 0; - io_gl_fixup(io_gl_prompt, -1, io_gl_pos + 1); - io_gl_vi_mode = 0; - break; - } - count++; - if (count >= vi_count) - break; - } - vi_count = 1; - vi_delete = 0; - vi_break: - continue; - } - else if (io_gl_search_mode) { + if (io_gl_search_mode) { search_addchar(c); } else { @@ -717,29 +373,7 @@ char *io_getline_int(const char *prompt) case '\177': io_gl_del(-1, 0); /* ^H and DEL */ break; - case '\t': /* TAB */ - if (io_gl_completion_proc) { - int tmp = io_gl_pos; - io_gl_buf[sizeof(io_gl_buf) - 1] = '\0'; - int loc = io_gl_do_tab_completion(io_gl_buf, &tmp, sizeof(io_gl_buf)); - io_gl_buf[sizeof(io_gl_buf) - 1] = '\0'; - if (loc >= 0 || tmp != io_gl_pos) - io_gl_fixup(io_gl_prompt, /* loc */ -2, tmp); - if (lastch == '\t') { - c = 0; - lastch = 0; - } - } - else if (io_gl_tab_hook) { - int tmp = io_gl_pos; - io_gl_buf[sizeof(io_gl_buf) - 1] = '\0'; - int loc = - io_gl_tab_hook(io_gl_buf, (int)io_gl_strlen(io_gl_prompt), &tmp, sizeof(io_gl_buf)); - io_gl_buf[sizeof(io_gl_buf) - 1] = '\0'; - if (loc >= 0 || tmp != io_gl_pos) - io_gl_fixup(io_gl_prompt, loc, tmp); - } - break; + case '\t': /* TAB */ break; case '\013': io_gl_kill(io_gl_pos); /* ^K */ break; @@ -748,8 +382,6 @@ char *io_getline_int(const char *prompt) break; case '\016': /* ^N */ copy_string(io_gl_buf, hist_next(), IO_GL_BUF_SIZE); - if (io_gl_in_hook) - io_gl_in_hook(io_gl_buf); io_gl_fixup(io_gl_prompt, 0, IO_GL_BUF_SIZE); break; case '\017': @@ -757,8 +389,6 @@ char *io_getline_int(const char *prompt) break; case '\020': /* ^P */ copy_string(io_gl_buf, hist_prev(), IO_GL_BUF_SIZE); - if (io_gl_in_hook) - io_gl_in_hook(io_gl_buf); io_gl_fixup(io_gl_prompt, 0, IO_GL_BUF_SIZE); break; case '\022': @@ -776,90 +406,12 @@ char *io_getline_int(const char *prompt) case '\031': io_gl_yank(); /* ^Y */ break; - case '\033': /* ansi arrow keys */ - c = io_gl_getcx(3); - if (c == '[') { - switch (c = io_gl_getc()) { - case 'A': /* up */ - copy_string(io_gl_buf, hist_prev(), IO_GL_BUF_SIZE); - if (io_gl_in_hook) - io_gl_in_hook(io_gl_buf); - io_gl_fixup(io_gl_prompt, 0, IO_GL_BUF_SIZE); - break; - case 'B': /* down */ - copy_string(io_gl_buf, hist_next(), IO_GL_BUF_SIZE); - if (io_gl_in_hook) - io_gl_in_hook(io_gl_buf); - io_gl_fixup(io_gl_prompt, 0, IO_GL_BUF_SIZE); - break; - case 'C': - io_gl_fixup(io_gl_prompt, -1, io_gl_pos + 1); /* right */ - break; - case 'D': - io_gl_fixup(io_gl_prompt, -1, io_gl_pos - 1); /* left */ - break; - default: - io_gl_beep(); /* who knows */ - break; - } - } - else if ((io_gl_vi_preferred == 0) && ((c == 'f') || (c == 'F'))) { - io_gl_word(1); - } - else if ((io_gl_vi_preferred == 0) && ((c == 'b') || (c == 'B'))) { - io_gl_word(-1); - } - else { - /* enter vi command mode */ - if (io_gl_vi_mode == 0) { - io_gl_vi_mode = 1; - vi_count = 1; - vi_delete = 0; - memset(vi_countbuf, 0, sizeof(vi_countbuf)); - if (io_gl_pos > 0) - io_gl_fixup(io_gl_prompt, -2, io_gl_pos - 1); /* left 1 char */ - /* Don't bother if the line is empty. */ - if (io_gl_cnt > 0) { - /* We still have to use the char read! */ - goto vi; - } - io_gl_vi_mode = 0; - } - io_gl_beep(); - } - break; - default: /* check for a terminal signal */ -#ifdef __unix__ - if (c > 0) { /* ignore 0 (reset above) */ - sig = 0; -#ifdef SIGINT - if (c == io_gl_intrc) - sig = SIGINT; -#endif -#ifdef SIGQUIT - if (c == io_gl_quitc) - sig = SIGQUIT; -#endif -#ifdef SIGTSTP - if (c == io_gl_suspc || c == io_gl_dsuspc) - sig = SIGTSTP; -#endif - if (sig != 0) { - io_gl_cleanup(); - kill(0, sig); - io_gl_init(); - io_gl_redraw(); - c = 0; - } - } -#endif /* __unix__ */ + default: if (c > 0) io_gl_beep(); break; } } - if (c > 0) - lastch = c; } io_gl_cleanup(); io_gl_buf[0] = '\0'; @@ -942,10 +494,6 @@ static void io_gl_newline(void) if (io_gl_cnt >= IO_GL_BUF_SIZE - 1) io_gl_error("\n*** Error: getline(): input buffer overflow\n"); - if (io_gl_out_hook) { - change = io_gl_out_hook(io_gl_buf); - len = strlen(io_gl_buf); - } if (loc > len) loc = len; io_gl_fixup(io_gl_prompt, change, loc); /* must do this before appending \n */ @@ -965,7 +513,7 @@ static void io_gl_del(int loc, int killsave) if ((loc == -1 && io_gl_pos > 0) || (loc == 0 && io_gl_pos < io_gl_cnt)) { int j = 0; for (int i = io_gl_pos + loc; i < io_gl_cnt; i++) { - if ((j == 0) && (killsave != 0) && (io_gl_vi_mode != 0)) { + if ((j == 0) && (killsave != 0)) { io_gl_killbuf[0] = io_gl_buf[i]; io_gl_killbuf[1] = '\0'; j = 1; @@ -991,69 +539,6 @@ static void io_gl_kill(int pos) io_gl_beep(); } -static void io_gl_killword(int direction) -{ - int pos = io_gl_pos; - int startpos = io_gl_pos; - int tmp; - int i; - - if (direction > 0) { /* forward */ - while (pos < io_gl_cnt && !isspace(io_gl_buf[pos])) - pos++; - while (pos < io_gl_cnt && isspace(io_gl_buf[pos])) - pos++; - } - else { /* backward */ - if (pos > 0) - pos--; - while (pos > 0 && isspace(io_gl_buf[pos])) - pos--; - while (pos > 0 && !isspace(io_gl_buf[pos])) - pos--; - if (pos < io_gl_cnt && isspace(io_gl_buf[pos])) /* move onto word */ - pos++; - } - if (pos < startpos) { - tmp = pos; - pos = startpos; - startpos = tmp; - } - memcpy(io_gl_killbuf, io_gl_buf + startpos, (size_t)(pos - startpos)); - io_gl_killbuf[pos - startpos] = '\0'; - if (pos - startpos - 1 >= 0 && isspace(io_gl_killbuf[pos - startpos - 1])) { - io_gl_killbuf[pos - startpos - 1] = '\0'; - } - io_gl_fixup(io_gl_prompt, -1, startpos); - for (i = 0, tmp = pos - startpos; i < tmp; i++) - io_gl_del(0, 0); -} /* io_gl_killword */ - -static void io_gl_word(int direction) - -/* move forward or backward one word */ -{ - int pos = io_gl_pos; - - if (direction > 0) { /* forward */ - while (pos < io_gl_cnt && !isspace(io_gl_buf[pos])) - pos++; - while (pos < io_gl_cnt && isspace(io_gl_buf[pos])) - pos++; - } - else { /* backward */ - if (pos > 0) - pos--; - while (pos > 0 && isspace(io_gl_buf[pos])) - pos--; - while (pos > 0 && !isspace(io_gl_buf[pos])) - pos--; - if (pos < io_gl_cnt && isspace(io_gl_buf[pos])) /* move onto word */ - pos++; - } - io_gl_fixup(io_gl_prompt, -1, pos); -} - static void io_gl_redraw(void) /* emit a newline, reset and redraw prompt and current input line */ { @@ -1096,11 +581,11 @@ static void io_gl_fixup(const char *prompt, int change, int cursor) io_gl_puts(prompt); copy_string(last_prompt, prompt, 80); change = 0; - io_gl_width = io_gl_termw - io_gl_strlen(prompt); + io_gl_width = io_gl_termw - strlen(prompt); } else if (strcmp(prompt, last_prompt) != 0) { - l1 = io_gl_strlen(last_prompt); - l2 = io_gl_strlen(prompt); + l1 = strlen(last_prompt); + l2 = strlen(prompt); io_gl_cnt = io_gl_cnt + l1 - l2; copy_string(last_prompt, prompt, 80); io_gl_putc('\r'); @@ -1192,24 +677,6 @@ static void io_gl_fixup(const char *prompt, int change, int cursor) io_gl_pos = cursor; } -static int io_gl_tab(char *buf, int offset, int *loc, size_t bufsize) -/* default tab handler, acts like tabstops every 8 cols */ -{ - int i, count, len; - - len = strlen(buf); - count = 8 - (offset + *loc) % 8; - for (i = len; i >= *loc; i--) - if (i + count < (int)bufsize) - buf[i + count] = buf[i]; - for (i = 0; i < count; i++) - if (*loc + i < (int)bufsize) - buf[*loc + i] = ' '; - i = *loc; - *loc = i + count; - return i; -} - /******************* History stuff **************************************/ #ifndef HIST_SIZE @@ -1313,46 +780,6 @@ static char *hist_save(const char *p) return s; } -void io_gl_histsavefile(const char *const path) -{ - FILE *fp = fopen(path, -#if defined(__windows__) || defined(MSDOS) - "wt" -#else - "w" -#endif - ); - if (fp != NULL) { - for (int i = 2; i < HIST_SIZE; i++) { - int j = (hist_pos + i) % HIST_SIZE; - char *p = hist_buf[j]; - if ((p == NULL) || (*p == '\0')) - continue; - fprintf(fp, "%s\n", p); - } - fclose(fp); - } -} /* io_gl_histsavefile */ - -void io_gl_histloadfile(const char *const path) -{ - FILE *fp = fopen(path, -#if defined(__windows__) || defined(MSDOS) - "rt" -#else - "r" -#endif - ); - if (fp != NULL) { - char line[256]; - memset(line, 0, sizeof(line)); - while (fgets(line, sizeof(line) - 2, fp) != NULL) { - io_gl_histadd(line); - } - fclose(fp); - } -} /* io_gl_histloadfile */ - /******************* Search stuff **************************************/ static char search_prompt[101]; /* prompt includes search string */ @@ -1430,8 +857,6 @@ static void search_term(void) io_gl_search_mode = 0; if (io_gl_buf[0] == 0) /* not found, reset hist list */ hist_pos = hist_last; - if (io_gl_in_hook) - io_gl_in_hook(io_gl_buf); io_gl_fixup(io_gl_prompt, 0, io_gl_pos); } @@ -1512,613 +937,3 @@ static void io_gl_beep(void) io_gl_putc('\007'); #endif } /* io_gl_beep */ - -static int io_gl_do_tab_completion(char *buf, int *loc, size_t bufsize) -{ - /* Zero out the rest of the buffer, so we can move stuff around - * and know we'll still be NUL-terminated. - */ - size_t llen = strlen(buf); - memset(buf + llen, 0, bufsize - llen); - bufsize -= 4; /* leave room for a NUL, space, and two quotes. */ - char * curposp = buf + *loc; - int wasateol = (*curposp == '\0'); - size_t lenaftercursor = llen - (curposp - buf); - if (io_gl_ellipses_during_completion != 0) { - char ellipsessave[4]; - memcpy(ellipsessave, curposp, (size_t)4); - memcpy(curposp, "... ", (size_t)4); - io_gl_fixup(io_gl_prompt, io_gl_pos, io_gl_pos + 3); - memcpy(curposp, ellipsessave, (size_t)4); - } - - int qmode = 0; - char *qstart = NULL; - char *lastspacestart = NULL; - char *matchpfx = NULL; - - char *cp = buf; - while (cp < curposp) { - int c = (int)*cp++; - if (c == '\0') - break; - if ((c == '"') || (c == '\'')) { - if (qmode == c) { - /* closing quote; end it. */ - qstart = NULL; - qmode = 0; - } - else if (qmode != 0) { - /* just treat it as a regular char. */ - } - else { - /* start new quote group. */ - qmode = c; - qstart = cp - 1; - } - } - else if ((isspace(c)) && (qmode == 0)) { - /* found a non-quoted space. */ - lastspacestart = cp - 1; - } - else { - /* regular char */ - } - } - - char *startp; - if (qstart != NULL) - startp = qstart + 1; - else if (lastspacestart != NULL) - startp = lastspacestart + 1; - else - startp = buf; - - cp = startp; - size_t mlen = (curposp - cp); - - matchpfx = (char *)malloc(mlen + 1); - memcpy(matchpfx, cp, mlen); - matchpfx[mlen] = '\0'; - -#define IO_GL_COMPLETE_VECTOR_BLOCK_SIZE 64 - - int nused = 0; - int ntoalloc = IO_GL_COMPLETE_VECTOR_BLOCK_SIZE; - char **newio_gl_matchlist = (char **)malloc((size_t)(sizeof(char *) * (ntoalloc + 1))); - if (newio_gl_matchlist == NULL) { - free(matchpfx); - io_gl_beep(); - return 0; - } - io_gl_matchlist = newio_gl_matchlist; - int nalloced = ntoalloc; - for (int i = nused; i <= nalloced; i++) - io_gl_matchlist[i] = NULL; - - io_gl_completion_exact_match_extra_char = ' '; - for (;; nused++) { - if (nused == nalloced) { - ntoalloc += IO_GL_COMPLETE_VECTOR_BLOCK_SIZE; - newio_gl_matchlist = - (char **)realloc((char *)io_gl_matchlist, (size_t)(sizeof(char *) * (ntoalloc + 1))); - if (newio_gl_matchlist == NULL) { - /* not enough memory to expand list -- abort */ - for (int i = 0; i < nused; i++) - free(io_gl_matchlist[i]); - free(io_gl_matchlist); - io_gl_matchlist = NULL; - io_gl_beep(); - free(matchpfx); - return 0; - } - io_gl_matchlist = newio_gl_matchlist; - nalloced = ntoalloc; - for (int i = nused; i <= nalloced; i++) - io_gl_matchlist[i] = NULL; - } - cp = io_gl_completion_proc(matchpfx, nused); - io_gl_matchlist[nused] = cp; - if (cp == NULL) - break; - } - - if (io_gl_ellipses_during_completion != 0) { - io_gl_fixup(io_gl_prompt, io_gl_pos, io_gl_pos); - io_gl_puts(" "); - } - - /* We now have an array strings, whose last element is NULL. */ - char *strtoadd = NULL; - char *strtoadd1 = NULL; - - int addquotes = (io_gl_filename_quoting_desired > 0) || - ((io_gl_filename_quoting_desired < 0) && - (io_gl_completion_proc == io_gl_local_filename_completion_proc)); - - if (nused == 1) { - /* Exactly one match. */ - strtoadd = io_gl_matchlist[0]; - } - else if ((nused > 1) && (mlen > 0)) { - /* Find the greatest amount that matches. */ - size_t glen; - for (glen = 1;; glen++) { - int allmatch = 1; - for (int i = 1; i < nused; i++) { - if (io_gl_matchlist[0][glen] != io_gl_matchlist[i][glen]) { - allmatch = 0; - break; - } - } - if (allmatch == 0) - break; - } - strtoadd1 = (char *)malloc(glen + 1); - if (strtoadd1 != NULL) { - memcpy(strtoadd1, io_gl_matchlist[0], glen); - strtoadd1[glen] = '\0'; - strtoadd = strtoadd1; - } - } - - if (strtoadd != NULL) { - if ((qmode == 0) && (addquotes != 0)) { - if (strpbrk(strtoadd, io_gl_filename_quote_characters) != NULL) { - qmode = (strchr(strtoadd, '"') == NULL) ? '"' : '\''; - memmove(curposp + 1, curposp, lenaftercursor + 1 /* NUL */); - curposp++; - *startp++ = (char)qmode; - } - } - size_t startoff = (size_t)(startp - buf); - size_t amt = strlen(strtoadd); - if ((amt + startoff + lenaftercursor) >= bufsize) - amt = bufsize - (amt + startoff + lenaftercursor); - memmove(curposp + amt - mlen, curposp, lenaftercursor + 1 /* NUL */); - curposp += amt - mlen; - memcpy(startp, strtoadd, amt); - if (nused == 1) { - /* Exact match. */ - if (qmode != 0) { - /* Finish the quoting. */ - memmove(curposp + 1, curposp, lenaftercursor + 1 /* NUL */); - curposp++; - buf[amt + startoff] = (char)qmode; - amt++; - } - memmove(curposp + 1, curposp, lenaftercursor + 1 /* NUL */); - curposp++; - buf[amt + startoff] = (char)io_gl_completion_exact_match_extra_char; - amt++; - } - else if ((!wasateol) && (!isspace(*curposp))) { - /* Not a full match, but insert a - * space for better readability. - */ - memmove(curposp + 1, curposp, lenaftercursor + 1 /* NUL */); - curposp++; - buf[amt + startoff] = ' '; - } - *loc = (int)(startoff + amt); - - if (strtoadd1 != NULL) - free(strtoadd1); - } - - /* Don't need this any more. */ - for (int i = 0; i < nused; i++) - free(io_gl_matchlist[i]); - free(io_gl_matchlist); - io_gl_matchlist = NULL; - free(matchpfx); - - return 0; -} /* io_gl_do_tab_completion */ - -void io_gl_tab_completion(io_gl_tab_completion_proc proc) -{ - if (proc == NULL) - proc = io_gl_local_filename_completion_proc; /* default proc */ - io_gl_completion_proc = proc; -} /* io_gl_tab_completion */ - -#ifndef _StrFindLocalPathDelim -static char *_StrRFindLocalPathDelim(const char *src) /* TODO: optimize */ -{ - const char *last = NULL; - for (;;) { - int c = *src++; - if (c == '\0') - break; - if (IsLocalPathDelim(c)) - last = src - 1; - } - - return ((char *)last); -} /* StrRFindLocalPathDelim */ -#endif /* Windows */ - -void io_gl_set_home_dir(const char *homedir) -{ - if (io_gl_home_dir != NULL) { - free(io_gl_home_dir); - io_gl_home_dir = NULL; - } - - if (homedir == NULL) { -#ifdef __windows__ - const char *homedrive = getenv("HOMEDRIVE"); - const char *homepath = getenv("HOMEPATH"); - if ((homedrive != NULL) && (homepath != NULL)) { - size_t len = strlen(homedrive) + strlen(homepath) + 1; - io_gl_home_dir = (char *)malloc(len); - if (io_gl_home_dir != NULL) { - copy_string(io_gl_home_dir, homedrive, len); - strcat(io_gl_home_dir, homepath); - return; - } - } - - char wdir[64]; - wdir[0] = '\0'; - if (GetWindowsDirectory(wdir, sizeof(wdir) - 1) < 1) - (void)copy_string(wdir, ".", sizeof(wdir)); - else if (wdir[1] == ':') { - wdir[2] = '\\'; - wdir[3] = '\0'; - } - homedir = wdir; -#else - char *cp = (char *)getlogin(); - if (cp == NULL) { - cp = (char *)getenv("LOGNAME"); - if (cp == NULL) - cp = (char *)getenv("USER"); - } - struct passwd *pw = NULL; - if (cp != NULL) - pw = getpwnam(cp); - if (pw == NULL) - pw = getpwuid(getuid()); - if (pw == NULL) - return; /* hell with it */ - homedir = pw->pw_dir; -#endif - } - - size_t len = strlen(homedir) + /* NUL */ 1; - io_gl_home_dir = (char *)malloc(len); - if (io_gl_home_dir != NULL) { - memcpy(io_gl_home_dir, homedir, len); - } -} /* io_gl_set_home_dir */ - -#ifdef __unix__ - -char *io_gl_local_filename_completion_proc(const char *start, int idx) -{ - static DIR * dir = NULL; - static int filepfxoffset; - static size_t filepfxlen; - - if (idx == 0) { - if (dir != NULL) { - /* shouldn't get here! */ - closedir(dir); - dir = NULL; - } - } - - if (dir == NULL) { - const char *dirtoopen; - char * dirtoopen1 = NULL; - char * cp = _StrRFindLocalPathDelim(start); - if (cp == start) { - dirtoopen = LOCAL_PATH_DELIM_STR; /* root dir */ - filepfxoffset = 1; - } - else if (cp == NULL) { - dirtoopen = "."; - filepfxoffset = 0; - } - else { - size_t len = strlen(start) + 1; - dirtoopen1 = (char *)malloc(len); - if (dirtoopen1 == NULL) - return NULL; - memcpy(dirtoopen1, start, len); - len = (cp - start); - dirtoopen1[len] = '\0'; - dirtoopen = dirtoopen1; - filepfxoffset = (int)((cp + 1) - start); - } - - if (strcmp(dirtoopen, "~") == 0) { - if (io_gl_home_dir == NULL) - io_gl_set_home_dir(NULL); - if (io_gl_home_dir == NULL) { - if (dirtoopen1 != NULL) - free(dirtoopen1); - return (NULL); - } - dirtoopen = io_gl_home_dir; - } - - dir = opendir(dirtoopen); - if (dirtoopen1 != NULL) - free(dirtoopen1); - - const char *filepfx = start + filepfxoffset; - filepfxlen = strlen(filepfx); - } - - if (dir != NULL) { - /* assumes "start" is same for each iteration. */ - const char *filepfx = start + filepfxoffset; - - for (;;) { - struct dirent *dent = readdir(dir); - if (dent == NULL) { - /* no more items */ - closedir(dir); - dir = NULL; - - if (idx == 1) { - /* There was exactly one match. - * In this special case, we - * want to append a / instead - * of a space. - */ - char *cp = io_gl_matchlist[0]; - if ((cp[0] == '~') && ((cp[1] == '\0') || (IsLocalPathDelim(cp[1])))) { - size_t len = strlen(cp + 1) + /* NUL */ 1; - size_t len2 = strlen(io_gl_home_dir); - if (IsLocalPathDelim(io_gl_home_dir[len2 - 1])) - len2--; - cp = (char *)realloc(io_gl_matchlist[0], len + len2); - if (cp == NULL) { - cp = io_gl_matchlist[0]; - } - else { - memmove(cp + len2, cp + 1, len); - memcpy(cp, io_gl_home_dir, len2); - io_gl_matchlist[0] = cp; - } - } - struct stat st; - if ((stat(cp, &st) == 0) && (S_ISDIR(st.st_mode))) - io_gl_completion_exact_match_extra_char = LOCAL_PATH_DELIM; - } - return NULL; - } - - const char *name = dent->d_name; - if ((name[0] == '.') && ((name[1] == '\0') || ((name[1] == '.') && (name[2] == '\0')))) - continue; /* Skip . and .. */ - - if ((filepfxlen == 0) || (strncmp(name, filepfx, filepfxlen) == 0)) { - /* match */ - size_t len = strlen(name); - char * cp = (char *)malloc(filepfxoffset + len + 1 /* spare */ + 1 /* NUL */); - *cp = '\0'; - if (filepfxoffset > 0) - memcpy(cp, start, (size_t)filepfxoffset); - memcpy(cp + filepfxoffset, name, len + 1); - return (cp); - } - } - } - - return NULL; -} /* io_gl_local_filename_completion_proc */ - -#endif /* __unix__ */ - -#ifdef __windows__ - -char *io_gl_local_filename_completion_proc(const char *start, int idx) -{ - static HANDLE searchHandle = NULL; - static int filepfxoffset; - static size_t filepfxlen; - - WIN32_FIND_DATA ffd; - DWORD dwErr; - char * cp, *c2, ch; - const char * filepfx; - const char * dirtoopen; - - if (idx == 0) { - if (searchHandle != NULL) { - /* shouldn't get here! */ - FindClose(searchHandle); - searchHandle = NULL; - } - } - - if (searchHandle == NULL) { - char *dirtoopen1 = NULL; - char *dirtoopen2 = NULL; - cp = _StrRFindLocalPathDelim(start); - if (cp == start) { - dirtoopen = LOCAL_PATH_DELIM_STR; /* root dir */ - filepfxoffset = 1; - } - else if (cp == NULL) { - dirtoopen = "."; - filepfxoffset = 0; - } - else { - size_t len = strlen(start) + 1; - dirtoopen1 = (char *)malloc(len); - if (dirtoopen1 == NULL) - return NULL; - memcpy(dirtoopen1, start, len); - len = (cp - start); - dirtoopen1[len] = '\0'; - dirtoopen = dirtoopen1; - filepfxoffset = (int)((cp + 1) - start); - } - - if (strcmp(dirtoopen, "~") == 0) { - if (io_gl_home_dir == NULL) - io_gl_set_home_dir(NULL); - if (io_gl_home_dir == NULL) - return (NULL); - dirtoopen = io_gl_home_dir; - } - - size_t len = strlen(dirtoopen); - dirtoopen2 = (char *)malloc(len + 8); - if (dirtoopen2 == NULL) { - if (dirtoopen1 != NULL) - free(dirtoopen1); - return NULL; - } - - memcpy(dirtoopen2, dirtoopen, len + 1); - if (dirtoopen2[len - 1] == LOCAL_PATH_DELIM) - memcpy(dirtoopen2 + len, "*.*", (size_t)4); - else - memcpy(dirtoopen2 + len, "\\*.*", (size_t)5); - - /* "Open" the directory. */ - memset(&ffd, 0, sizeof(ffd)); - searchHandle = FindFirstFile(dirtoopen2, &ffd); - - free(dirtoopen2); - if (dirtoopen1 != NULL) - free(dirtoopen1); - - if (searchHandle == INVALID_HANDLE_VALUE) { - return NULL; - } - - filepfx = start + filepfxoffset; - filepfxlen = strlen(filepfx); - } - else { - /* assumes "start" is same for each iteration. */ - filepfx = start + filepfxoffset; - goto next; - } - - for (;;) { - - const char *name = ffd.cFileName; - if ((name[0] == '.') && ((name[1] == '\0') || ((name[1] == '.') && (name[2] == '\0')))) - goto next; /* Skip . and .. */ - - if ((filepfxlen == 0) || (strnicmp(name, filepfx, filepfxlen) == 0)) { - /* match */ - size_t len = strlen(name); - cp = (char *)malloc(filepfxoffset + len + 4 /* spare */ + 1 /* NUL */); - *cp = '\0'; - if (filepfxoffset > 0) - memcpy(cp, start, filepfxoffset); - memcpy(cp + filepfxoffset, name, len + 1); - if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - /* Embed file type with name. */ - c2 = cp + filepfxoffset + len + 1; - *c2++ = '\0'; - *c2++ = 'd'; - *c2 = '\0'; - } - else { - c2 = cp + filepfxoffset + len + 1; - *c2++ = '\0'; - *c2++ = '-'; - *c2 = '\0'; - } - return (cp); - } - - next: - if (!FindNextFile(searchHandle, &ffd)) { - dwErr = GetLastError(); - if (dwErr != ERROR_NO_MORE_FILES) { - FindClose(searchHandle); - searchHandle = NULL; - return NULL; - } - - /* no more items */ - FindClose(searchHandle); - searchHandle = NULL; - - if (idx == 1) { - /* There was exactly one match. - * In this special case, we - * want to append a \ instead - * of a space. - */ - cp = io_gl_matchlist[0]; - ch = (char)cp[strlen(cp) + 2]; - if (ch == (char)'d') - io_gl_completion_exact_match_extra_char = LOCAL_PATH_DELIM; - - if ((cp[0] == '~') && ((cp[1] == '\0') || (IsLocalPathDelim(cp[1])))) { - size_t len = strlen(cp + 1) + /* NUL */ 1; - size_t len2 = strlen(io_gl_home_dir); - if (IsLocalPathDelim(io_gl_home_dir[len2 - 1])) - len2--; - cp = (char *)realloc(io_gl_matchlist[0], len + len2 + 4); - if (cp == NULL) { - cp = io_gl_matchlist[0]; - } - else { - memmove(cp + len2, cp + 1, len); - memcpy(cp, io_gl_home_dir, len2); - c2 = cp + len + len2; - *c2++ = '\0'; - *c2++ = ch; - *c2 = '\0'; - io_gl_matchlist[0] = cp; - } - } - } - break; - } - } - return (NULL); -} /* io_gl_local_filename_completion_proc */ - -char *io_gl_win_getpass(const char *const prompt, char *const pass, int dsize) -{ - FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE)); - ZeroMemory(pass, (DWORD)sizeof(dsize)); - dsize--; - - if ((prompt != NULL) && (prompt[0] != '\0')) - _cputs(prompt); - - char *cp; - for (cp = pass;;) { - int c = (int)_getch(); - if ((c == '\r') || (c == '\n')) - break; - if ((c == '\010') || (c == '\177')) { - /* ^H and DEL */ - if (cp > pass) { - *--cp = '\0'; - _putch('\010'); - _putch(' '); - _putch('\010'); - } - } - else if (cp < (pass + dsize)) { - _putch('*'); - *cp++ = c; - } - } - _putch('\r'); - _putch('\n'); - Sleep(40); - FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE)); - - *cp = '\0'; - return (pass); -} /* io_gl_getpass */ - -#endif /* __windows__ */ diff --git a/packages/seacas/libraries/ioss/src/Ioss_Getline.h b/packages/seacas/libraries/ioss/src/Ioss_Getline.h index 55e39588a0c2..79179db6dabc 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_Getline.h +++ b/packages/seacas/libraries/ioss/src/Ioss_Getline.h @@ -1,6 +1,6 @@ /* - * Copyright (C) 1991, 1992, 1993, 2020 by Chris Thewalt (thewalt@ce.berkeley.edu) + * Copyright (C) 1991, 1992, 1993 by Chris Thewalt (thewalt@ce.berkeley.edu) * * Permission to use, copy, modify, and distribute this software * for any purpose and without fee is hereby granted, provided @@ -18,48 +18,13 @@ #ifndef IOSS_GETLINE_H #define IOSS_GETLINE_H -/* unix systems can #define POSIX to use termios, otherwise - * the bsd or sysv interface will be used - */ - -#define IO_GL_BUF_SIZE 1024 - #ifdef __cplusplus extern "C" { #endif -typedef size_t (*io_gl_strwidth_proc)(char *); -typedef int (*io_gl_in_hook_proc)(char *); -typedef int (*io_gl_out_hook_proc)(char *); -typedef int (*io_gl_tab_hook_proc)(char *, int, int *, size_t); -typedef size_t (*io_gl_strlen_proc)(const char *); -typedef char *(*io_gl_tab_completion_proc)(const char *, int); - -char *io_getline_int(const char *); /* read a line of input */ -void io_gl_setwidth(int); /* specify width of screen */ -void io_gl_histadd(const char *); /* adds entries to hist */ -void io_gl_strwidth(io_gl_strwidth_proc); /* to bind io_gl_strlen */ -void io_gl_tab_completion(io_gl_tab_completion_proc); -char *io_gl_local_filename_completion_proc(const char *, int); -void io_gl_set_home_dir(const char *homedir); -void io_gl_histsavefile(const char *const path); -void io_gl_histloadfile(const char *const path); -char *io_gl_win_getpass(const char *const prompt, char *const pass, int dsize); - -#ifndef _io_getline_c_ - -extern io_gl_in_hook_proc io_gl_in_hook; -extern io_gl_out_hook_proc io_gl_out_hook; -extern io_gl_tab_hook_proc io_gl_tab_hook; -extern io_gl_strlen_proc io_gl_strlen; -extern io_gl_tab_completion_proc io_gl_completion_proc; -extern int io_gl_filename_quoting_desired; -extern const char * io_gl_filename_quote_characters; -extern int io_gl_ellipses_during_completion; -extern int io_gl_completion_exact_match_extra_char; -extern char io_gl_buf[IO_GL_BUF_SIZE]; - -#endif /* ! io_getline_c_ */ +char *io_getline_int(const char *); /* read a line of input */ +void io_gl_setwidth(int); /* specify width of screen */ +void io_gl_histadd(const char *); /* adds entries to hist */ #ifdef __cplusplus } /* close brackets on extern "C" declaration */ diff --git a/packages/seacas/libraries/ioss/src/Ioss_Glob.h b/packages/seacas/libraries/ioss/src/Ioss_Glob.h index 8c403a060419..e049229b033d 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_Glob.h +++ b/packages/seacas/libraries/ioss/src/Ioss_Glob.h @@ -72,7 +72,7 @@ namespace glob { private: StateType type_; - Automata & states_; + Automata &states_; std::vector next_states_; String matched_str_; }; @@ -1126,7 +1126,7 @@ namespace glob { AstNodePtr ParserGroup() { typename GroupNode::GroupType type; - Token & tk = NextToken(); + Token &tk = NextToken(); switch (tk.Kind()) { case TokenKind::LPAREN: type = GroupNode::GroupType::BASIC; break; @@ -1258,7 +1258,7 @@ namespace glob { private: void ExecConcat(AstNode *node, Automata &automata) { - ConcatNode * concat_node = static_cast *>(node); + ConcatNode *concat_node = static_cast *>(node); std::vector> &basic_globs = concat_node->GetBasicGlobs(); for (auto &basic_glob : basic_globs) { @@ -1323,7 +1323,7 @@ namespace glob { { SetItemsNode *set_node = static_cast *>(node); std::vector>> vec; - auto & items = set_node->GetItems(); + auto &items = set_node->GetItems(); for (auto &item : items) { vec.push_back(std::move(ProcessSetItem(item.get()))); } @@ -1340,7 +1340,7 @@ namespace glob { } else if (node->GetType() == AstNode::Type::RANGE) { RangeNode *range_node = static_cast *>(node); - CharNode * start_node = static_cast *>(range_node->GetStart()); + CharNode *start_node = static_cast *>(range_node->GetStart()); CharNode *end_node = static_cast *>(range_node->GetEnd()); @@ -1356,7 +1356,7 @@ namespace glob { void ExecGroup(AstNode *node, Automata &automata) { GroupNode *group_node = static_cast *>(node); - AstNode * union_node = group_node->GetGlob(); + AstNode *union_node = group_node->GetGlob(); std::vector>> automatas = ExecUnion(union_node); typename StateGroup::Type state_group_type{}; @@ -1387,7 +1387,7 @@ namespace glob { std::vector>> ExecUnion(AstNode *node) { UnionNode *union_node = static_cast *>(node); - auto & items = union_node->GetItems(); + auto &items = union_node->GetItems(); std::vector>> vec_automatas; for (auto &item : items) { std::unique_ptr> automata_ptr(new Automata); diff --git a/packages/seacas/libraries/ioss/src/Ioss_IOFactory.C b/packages/seacas/libraries/ioss/src/Ioss_IOFactory.C index 890e1d75654b..066b1bd8cfd4 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_IOFactory.C +++ b/packages/seacas/libraries/ioss/src/Ioss_IOFactory.C @@ -131,7 +131,7 @@ std::string Ioss::IOFactory::show_configuration() fmt::join(Ioss::valid_decomp_methods(), ", ")); { char version[MPI_MAX_LIBRARY_VERSION_STRING]; - int length = 0; + int length = 0; MPI_Get_library_version(version, &length); fmt::print(config, "MPI Version: {}\n", version); } diff --git a/packages/seacas/libraries/ioss/src/Ioss_Utils.C b/packages/seacas/libraries/ioss/src/Ioss_Utils.C index f44c47764d36..b2705b4fe855 100644 --- a/packages/seacas/libraries/ioss/src/Ioss_Utils.C +++ b/packages/seacas/libraries/ioss/src/Ioss_Utils.C @@ -26,7 +26,7 @@ #include #include -#ifndef _WIN32 +#if !defined(__IOSS_WINDOWS__) #include #include #endif @@ -42,7 +42,7 @@ #endif // For memory utilities... -#if defined(_WIN32) +#if defined(__IOSS_WINDOWS__) #define WIN32_LEAN_AND_MEAN #define NOMINMAX #if 0 @@ -776,7 +776,7 @@ void Ioss::Utils::get_fields(int64_t entity_count, // The number of objects in t std::string Ioss::Utils::platform_information() { -#ifndef _WIN32 +#if !defined(__IOSS_WINDOWS__) struct utsname sys_info { }; @@ -794,7 +794,7 @@ size_t Ioss::Utils::get_memory_info() { // Code from http://nadeausoftware.com/sites/NadeauSoftware.com/files/getRSS.c size_t memory_usage = 0; -#if defined(_WIN32) +#if defined(__IOSS_WINDOWS__) #if 0 /* Windows -------------------------------------------------- */ PROCESS_MEMORY_COUNTERS info; @@ -862,7 +862,7 @@ size_t Ioss::Utils::get_hwm_memory_info() { // Code from http://nadeausoftware.com/sites/NadeauSoftware.com/files/getRSS.c size_t memory_usage = 0; -#if defined(_WIN32) +#if defined(__IOSS_WINDOWS__) #if 0 /* Windows -------------------------------------------------- */ PROCESS_MEMORY_COUNTERS info; diff --git a/packages/seacas/libraries/ioss/src/cgns/Iocgns_DatabaseIO.C b/packages/seacas/libraries/ioss/src/cgns/Iocgns_DatabaseIO.C index a77cd1598b1c..e69a6ffd281f 100644 --- a/packages/seacas/libraries/ioss/src/cgns/Iocgns_DatabaseIO.C +++ b/packages/seacas/libraries/ioss/src/cgns/Iocgns_DatabaseIO.C @@ -30,7 +30,7 @@ #include #include #include -#ifndef _WIN32 +#if !defined(__IOSS_WINDOWS__) #include #endif #include diff --git a/packages/seacas/libraries/ioss/src/cgns/Iocgns_ParallelDatabaseIO.C b/packages/seacas/libraries/ioss/src/cgns/Iocgns_ParallelDatabaseIO.C index 27b0c1d12a32..aae4991f8fc1 100644 --- a/packages/seacas/libraries/ioss/src/cgns/Iocgns_ParallelDatabaseIO.C +++ b/packages/seacas/libraries/ioss/src/cgns/Iocgns_ParallelDatabaseIO.C @@ -378,7 +378,7 @@ namespace Iocgns { if (n_bases != 1) { std::ostringstream errmsg; fmt::print(errmsg, - "CGNS: Too many bases ({}); only support files with a single bases at this time", + "CGNS: Too many bases ({}); only support files with a single base at this time", n_bases); IOSS_ERROR(errmsg); } diff --git a/packages/seacas/libraries/ioss/src/cgns/Iocgns_Utils.C b/packages/seacas/libraries/ioss/src/cgns/Iocgns_Utils.C index c487c5c60f65..648f469a5cd5 100644 --- a/packages/seacas/libraries/ioss/src/cgns/Iocgns_Utils.C +++ b/packages/seacas/libraries/ioss/src/cgns/Iocgns_Utils.C @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -57,7 +58,7 @@ Iocgns::Utils::cgns_error(file_ptr, __FILE__, __func__, __LINE__, -1); \ } -#ifdef _WIN32 +#if defined(__IOSS_WINDOWS__) #ifdef _MSC_VER #define strncasecmp strnicmp #endif diff --git a/packages/seacas/libraries/ioss/src/exodus/Ioex_ParallelDatabaseIO.C b/packages/seacas/libraries/ioss/src/exodus/Ioex_ParallelDatabaseIO.C index 19c0e4b57777..6dd866672b72 100644 --- a/packages/seacas/libraries/ioss/src/exodus/Ioex_ParallelDatabaseIO.C +++ b/packages/seacas/libraries/ioss/src/exodus/Ioex_ParallelDatabaseIO.C @@ -449,7 +449,7 @@ namespace Ioex { // buggy mpiio code. Therefore, we always do chdir call. Maybe in several // years, we can remove this code and everything will work... -#ifndef _WIN32 +#if !defined(__IOSS_WINDOWS__) Ioss::FileInfo file(filename); std::string path = file.pathname(); filename = file.tailname(); @@ -497,7 +497,7 @@ namespace Ioex { } } -#ifndef _WIN32 +#if !defined(__IOSS_WINDOWS__) if (!path.empty()) { chdir(current_cwd); } @@ -570,7 +570,7 @@ namespace Ioex { std::string filename = get_dwname(); -#ifndef _WIN32 +#if !defined(__IOSS_WINDOWS__) Ioss::FileInfo file(filename); std::string path = file.pathname(); filename = file.tailname(); @@ -614,7 +614,7 @@ namespace Ioex { } } -#ifndef _WIN32 +#if !defined(__IOSS_WINDOWS__) chdir(current_cwd); std::free(current_cwd); #endif diff --git a/packages/seacas/libraries/ioss/src/faodel/Iofaodel_Utils.C b/packages/seacas/libraries/ioss/src/faodel/Iofaodel_Utils.C index c60aeba90570..542d8c4c920f 100644 --- a/packages/seacas/libraries/ioss/src/faodel/Iofaodel_Utils.C +++ b/packages/seacas/libraries/ioss/src/faodel/Iofaodel_Utils.C @@ -441,7 +441,7 @@ namespace Iofaodel { } std::set get_entity_names(const std::vector &keys, - const std::string & target) + const std::string &target) { std::set names; for (auto k : keys) { diff --git a/packages/seacas/libraries/ioss/src/faodel/Iofaodel_Utils.h b/packages/seacas/libraries/ioss/src/faodel/Iofaodel_Utils.h index ec23d96d22f9..ee53baf06b95 100644 --- a/packages/seacas/libraries/ioss/src/faodel/Iofaodel_Utils.h +++ b/packages/seacas/libraries/ioss/src/faodel/Iofaodel_Utils.h @@ -114,8 +114,9 @@ namespace Iofaodel { std::string to_string(const Ioss::Field::RoleType &t); std::string to_string(const Ioss::EntityType &t); - std::string get_entity_name(const kelpie::Key &k, std::string target); - std::set get_entity_names(const std::vector &keys, std::string target); + std::string get_entity_name(const kelpie::Key &k, const std::string &target); + std::set get_entity_names(const std::vector &keys, + const std::string &target); } // namespace Iofaodel diff --git a/packages/seacas/libraries/ioss/src/main/cgns_decomp.C b/packages/seacas/libraries/ioss/src/main/cgns_decomp.C index 2bdb4390efa3..3691c65d2250 100644 --- a/packages/seacas/libraries/ioss/src/main/cgns_decomp.C +++ b/packages/seacas/libraries/ioss/src/main/cgns_decomp.C @@ -8,6 +8,21 @@ #undef NDEBUG #include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + #include #include #include @@ -23,27 +38,13 @@ #include #include #include -#ifndef _WIN32 +#if !defined(__IOSS_WINDOWS__) #include #endif #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - #include #include diff --git a/packages/seacas/libraries/ioss/src/utest/Utst_map.C b/packages/seacas/libraries/ioss/src/utest/Utst_map.C index 04ad921d7704..0d78680b4bbb 100644 --- a/packages/seacas/libraries/ioss/src/utest/Utst_map.C +++ b/packages/seacas/libraries/ioss/src/utest/Utst_map.C @@ -1,10 +1,11 @@ -// Copyright(C) 1999-2020 National Technology & Engineering Solutions +// Copyright(C) 1999-2021 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // // See packages/seacas/LICENSE for details #define CATCH_CONFIG_MAIN +#include #include #include #include @@ -93,8 +94,12 @@ TEST_CASE("test sequential map with offset", "[sequential offset]") Ioss::Map my_map; my_map.set_size(count); - std::vector init(count); - std::vector offsets{0, 123, 8589934592}; + std::vector init(count); +#if defined(__IOSS_WINDOWS__) + std::vector offsets{0, 123, 858993459}; +#else + std::vector offsets{0, 123, 8589934592}; +#endif std::vector sections{"offset0", "offset123", "offsetBIG"}; for (size_t i = 0; i < offsets.size(); i++) { diff --git a/packages/seacas/libraries/ioss/src/utest/Utst_utils.C b/packages/seacas/libraries/ioss/src/utest/Utst_utils.C index 45a74c6e290c..9e9062256caa 100644 --- a/packages/seacas/libraries/ioss/src/utest/Utst_utils.C +++ b/packages/seacas/libraries/ioss/src/utest/Utst_utils.C @@ -7,6 +7,7 @@ #define CATCH_CONFIG_MAIN #include +#include #include #include #include @@ -54,7 +55,9 @@ TEST_CASE("number_width", "[number_width]") REQUIRE(9 == Ioss::Utils::number_width(1'000'000, true)); REQUIRE(10 == Ioss::Utils::number_width(1'111'111'111)); REQUIRE(13 == Ioss::Utils::number_width(1'111'111'111, true)); +#if !defined(__IOSS_WINDOWS__) REQUIRE(15 == Ioss::Utils::number_width(111'111'111'111, true)); +#endif } } diff --git a/packages/seacas/libraries/ioss/src/visualization/CMakeLists.txt b/packages/seacas/libraries/ioss/src/visualization/CMakeLists.txt index 14f8a6555f5d..627a5b02b22e 100644 --- a/packages/seacas/libraries/ioss/src/visualization/CMakeLists.txt +++ b/packages/seacas/libraries/ioss/src/visualization/CMakeLists.txt @@ -15,9 +15,11 @@ INCLUDE_DIRECTORIES( "${CMAKE_CURRENT_BINARY_DIR}/../" ) -IF(${TPL_ENABLE_DLlib}) - ADD_DEFINITIONS(-DIOSS_DLOPEN_ENABLED) -ENDIF () +if (NOT CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + IF(${TPL_ENABLE_DLlib}) + ADD_DEFINITIONS(-DIOSS_DLOPEN_ENABLED) + ENDIF () +endif() TRIBITS_ADD_LIBRARY( Iovs diff --git a/packages/seacas/libraries/ioss/src/visualization/utils/Iovs_Utils.C b/packages/seacas/libraries/ioss/src/visualization/utils/Iovs_Utils.C index 45a6e3e94da6..390e65ab80f8 100644 --- a/packages/seacas/libraries/ioss/src/visualization/utils/Iovs_Utils.C +++ b/packages/seacas/libraries/ioss/src/visualization/utils/Iovs_Utils.C @@ -4,6 +4,7 @@ // // See packages/seacas/LICENSE for details +#include #include #include #include @@ -11,19 +12,21 @@ #include #include -#ifdef IOSS_DLOPEN_ENABLED -#include +#if defined(__IOSS_WINDOWS__) +#ifndef NOMINMAX +#define NOMINMAX #endif - -#ifndef _WIN32 +#include +#else #include #endif -#include -#ifdef _WIN32 -#include +#ifdef IOSS_DLOPEN_ENABLED +#include #endif +#include + namespace Iovs { std::string persistentLdLibraryPathEnvForCatalyst = ""; @@ -342,7 +345,7 @@ namespace Iovs { else { persistentLdLibraryPathEnvForCatalyst = paraviewPythonZipFilePath + ":" + existingPythonpath; } -#ifdef _WIN32 +#if defined(__IOSS_WINDOWS__) SetEnvironmentVariableA("PYTHONPATH", persistentLdLibraryPathEnvForCatalyst.c_str()); #else setenv("PYTHONPATH", persistentLdLibraryPathEnvForCatalyst.c_str(), 1); @@ -387,7 +390,7 @@ namespace Iovs { IOSS_ERROR(errmsg); } -#ifdef _WIN32 +#if defined(__IOSS_WINDOWS__) char *cbuf = _fullpath(nullptr, sierraInsDir.c_str(), _MAX_PATH); #else char *cbuf = realpath(sierraInsDir.c_str(), nullptr); @@ -403,7 +406,7 @@ namespace Iovs { IOSS_ERROR(errmsg); } -#ifdef _WIN32 +#if defined(__IOSS_WINDOWS__) { std::ostringstream errmsg; errmsg << "This code is not yet supported on windows...\n"; diff --git a/packages/seacas/libraries/supes/ext_lib/excpus.c b/packages/seacas/libraries/supes/ext_lib/excpus.c index 7b17cdf05c61..d9ae473b91fe 100644 --- a/packages/seacas/libraries/supes/ext_lib/excpus.c +++ b/packages/seacas/libraries/supes/ext_lib/excpus.c @@ -28,9 +28,6 @@ void excpus_(FTNREAL *cpusec) #if defined(aix) || defined(__VACPP__) || defined(hpux) || defined(sgi) || defined(__osf__) || \ defined(__linux__) || defined(__APPLE__) || defined(__CYGWIN__) -#include -#include - #if defined(__NO_CYGWIN_OPTION__) #define NOMINMAX #include diff --git a/packages/seacas/libraries/supes/ext_lib/exparm.c b/packages/seacas/libraries/supes/ext_lib/exparm.c index a1d8d46c53fe..cfb5fe9a6d66 100644 --- a/packages/seacas/libraries/supes/ext_lib/exparm.c +++ b/packages/seacas/libraries/supes/ext_lib/exparm.c @@ -41,7 +41,6 @@ */ #include "fortranc.h" -#include #if defined(__NO_CYGWIN_OPTION__) #define NOMINMAX #include diff --git a/packages/seacas/libraries/supes/ext_lib/getline_int.c b/packages/seacas/libraries/supes/ext_lib/getline_int.c index 5398026d5579..56ce0785d2e6 100644 --- a/packages/seacas/libraries/supes/ext_lib/getline_int.c +++ b/packages/seacas/libraries/supes/ext_lib/getline_int.c @@ -11,122 +11,45 @@ * Note: This version has been updated by Mike Gleason */ -#if defined(WIN32) || defined(_WINDOWS) +#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || \ + defined(__MINGW32__) || defined(_WIN64) || defined(__MINGW64__) + +#define __windows__ 1 #include -#include -#include #include -#include -#include #define NOMINMAX #include -#define strcasecmp stricmp -#define strncasecmp strnicmp #define sleep(a) Sleep(a * 1000) -#ifndef S_ISREG -#define S_ISREG(m) (((m)&_S_IFMT) == _S_IFREG) -#define S_ISDIR(m) (((m)&_S_IFMT) == _S_IFDIR) -#define isatty _isatty -#endif -#ifndef open -#define open _open +#ifndef write #define write _write #define read _read -#define close _close -#define lseek _lseek -#define stat _stat -#define lstat _stat -#define fstat _fstat -#define dup _dup -#define utime _utime -#define utimbuf _utimbuf #endif -#ifndef unlink -#define unlink remove -#endif -#define NO_SIGNALS 1 -#define LOCAL_PATH_DELIM '\\' -#define LOCAL_PATH_DELIM_STR "\\" -#define LOCAL_PATH_ALTDELIM '/' -#define IsLocalPathDelim(c) ((c == LOCAL_PATH_DELIM) || (c == LOCAL_PATH_ALTDELIM)) -#define UNC_PATH_PREFIX "\\\\" -#define IsUNCPrefixed(s) (IsLocalPathDelim(s[0]) && IsLocalPathDelim(s[1])) -#define __windows__ 1 #else + #ifndef __unix__ #define __unix__ 1 #endif -#if defined(AIX) || defined(_AIX) -#define _ALL_SOURCE 1 -#endif -#if defined(HAVE_CONFIG_H) -#include -#else -#/* guess */ -#define HAVE_TERMIOS_H 1 -#endif -#include -#include -#include -#ifdef CAN_USE_SYS_SELECT_H -#include -#endif -#include -#include -#include -#include -#ifdef HAVE_TERMIOS_H /* use HAVE_TERMIOS_H interface */ + #include struct termios new_termios, old_termios; -#else /* not HAVE_TERMIOS_H */ -#include -#ifdef TIOCSETN /* use BSD interface */ -#include -struct sgttyb new_tty, old_tty; -struct tchars tch; -struct ltchars ltch; -#else /* use SYSV interface */ -#include -struct termio new_termio, old_termio; -#endif /* TIOCSETN */ -#endif /* HAVE_TERMIOS_H */ -#define LOCAL_PATH_DELIM '/' -#define LOCAL_PATH_DELIM_STR "/" -#define _StrFindLocalPathDelim(a) strchr(a, LOCAL_PATH_DELIM) -#define _StrRFindLocalPathDelim(a) strrchr(a, LOCAL_PATH_DELIM) -#define IsLocalPathDelim(c) (c == LOCAL_PATH_DELIM) #endif /********************* C library headers ********************************/ #include -#include +#include #include #include #include -#include -#include -#include #include -extern int kill(pid_t pid, int sig); - -#define _getline_c_ 1 #include "getline_int.h" -static int gl_tab(char *buf, int offset, int *loc, size_t bufsize); - /******************** external interface *********************************/ -gl_in_hook_proc gl_in_hook = NULL; -gl_out_hook_proc gl_out_hook = NULL; -gl_tab_hook_proc gl_tab_hook = gl_tab; -gl_strlen_proc gl_strlen = (gl_strlen_proc)strlen; -gl_tab_completion_proc gl_completion_proc = NULL; -int gl_filename_quoting_desired = -1; /* default to unspecified */ -const char * gl_filename_quote_characters = " \t*?<>|;&()[]$`"; -int gl_ellipses_during_completion = 1; -int gl_completion_exact_match_extra_char; -char gl_buf[GL_BUF_SIZE]; /* input buffer */ +int gl_filename_quoting_desired = -1; /* default to unspecified */ +const char *gl_filename_quote_characters = " \t*?<>|;&()[]$`"; +int gl_ellipses_during_completion = 1; +char gl_buf[GL_BUF_SIZE]; /* input buffer */ /******************** internal interface *********************************/ @@ -139,15 +62,7 @@ static int gl_overwrite = 0; /* overwrite mode */ static int gl_pos, gl_cnt = 0; /* position and size of input */ static char gl_killbuf[GL_BUF_SIZE] = ""; /* killed text */ static const char *gl_prompt; /* to save the prompt string */ -static char gl_intrc = 0; /* keyboard SIGINT char */ -static char gl_quitc = 0; /* keyboard SIGQUIT char */ -static char gl_suspc = 0; /* keyboard SIGTSTP char */ -static char gl_dsuspc = 0; /* delayed SIGTSTP char */ -static int gl_search_mode = 0; /* search mode flag */ -static char ** gl_matchlist = NULL; -static char * gl_home_dir = NULL; -static int gl_vi_preferred = -1; -static int gl_vi_mode = 0; +static int gl_search_mode = 0; /* search mode flag */ static void gl_init(void); /* prepare to edit a line */ static void gl_cleanup(void); /* to undo gl_init */ @@ -159,18 +74,15 @@ static void gl_addchar(int c); /* install specified char */ static void gl_del(int loc, int); /* del, either left (-1) or cur (0) */ static void gl_error(const char *const buf); /* write error msg and die */ static void gl_fixup(const char *prompt, int change, - int cursor); /* fixup state variables and screen */ -static int gl_getc(void); /* read one char from terminal */ -static int gl_getcx(int); /* read one char from terminal, if available before timeout */ -static void gl_kill(int pos); /* delete to EOL */ -static void gl_newline(void); /* handle \n or \r */ -static void gl_putc(int c); /* write one char to terminal */ + int cursor); /* fixup state variables and screen */ +static int gl_getc(void); /* read one char from terminal */ +static void gl_kill(int pos); /* delete to EOL */ +static void gl_newline(void); /* handle \n or \r */ +static void gl_putc(int c); /* write one char to terminal */ static void gl_puts(const char *const buf); /* write a line to terminal */ static void gl_redraw(void); /* issue \n and redraw all */ static void gl_transpose(void); /* transpose two chars */ static void gl_yank(void); /* yank killed text */ -static void gl_word(int direction); /* move a word */ -static void gl_killword(int direction); static void hist_init(void); /* initializes hist pointers */ static char *hist_next(void); /* return ptr to next item */ @@ -183,8 +95,6 @@ static void search_back(int new_search); /* look back for current string */ static void search_forw(int new_search); /* look forw for current string */ static void gl_beep(void); /* try to play a system beep sound */ -static int gl_do_tab_completion(char *buf, int *loc, size_t bufsize); - static char *copy_string(char *dest, char const *source, long int elements) { char *d; @@ -204,16 +114,7 @@ static char *copy_string(char *dest, char const *source, long int elements) static void gl_char_init(void) /* turn off input echo */ { #ifdef __unix__ -#ifdef HAVE_TERMIOS_H /* Use POSIX */ tcgetattr(0, &old_termios); - gl_intrc = old_termios.c_cc[VINTR]; - gl_quitc = old_termios.c_cc[VQUIT]; -#ifdef VSUSP - gl_suspc = old_termios.c_cc[VSUSP]; -#endif -#ifdef VDSUSP - gl_dsuspc = old_termios.c_cc[VDSUSP]; -#endif new_termios = old_termios; new_termios.c_iflag &= ~(BRKINT | ISTRIP | IXON | IXOFF); new_termios.c_iflag |= (IGNBRK | IGNPAR); @@ -221,43 +122,13 @@ static void gl_char_init(void) /* turn off input echo */ new_termios.c_cc[VMIN] = 1; new_termios.c_cc[VTIME] = 0; tcsetattr(0, TCSANOW, &new_termios); -#elif defined(TIOCSETN) /* BSD */ - ioctl(0, TIOCGETC, &tch); - ioctl(0, TIOCGLTC, <ch); - gl_intrc = tch.t_intrc; - gl_quitc = tch.t_quitc; - gl_suspc = ltch.t_suspc; - gl_dsuspc = ltch.t_dsuspc; - ioctl(0, TIOCGETP, &old_tty); - new_tty = old_tty; - new_tty.sg_flags |= RAW; - new_tty.sg_flags &= ~ECHO; - ioctl(0, TIOCSETN, &new_tty); -#else /* SYSV */ - ioctl(0, TCGETA, &old_termio); - gl_intrc = old_termio.c_cc[VINTR]; - gl_quitc = old_termio.c_cc[VQUIT]; - new_termio = old_termio; - new_termio.c_iflag &= ~(BRKINT | ISTRIP | IXON | IXOFF); - new_termio.c_iflag |= (IGNBRK | IGNPAR); - new_termio.c_lflag &= ~(ICANON | ISIG | ECHO); - new_termio.c_cc[VMIN] = 1; - new_termio.c_cc[VTIME] = 0; - ioctl(0, TCSETA, &new_termio); -#endif #endif /* __unix__ */ } static void gl_char_cleanup(void) /* undo effects of gl_char_init */ { #ifdef __unix__ -#ifdef HAVE_TERMIOS_H tcsetattr(0, TCSANOW, &old_termios); -#elif defined(TIOCSETN) /* BSD */ - ioctl(0, TIOCSETN, &old_tty); -#else /* SYSV */ - ioctl(0, TCSETA, &old_termio); -#endif #endif /* __unix__ */ } @@ -350,74 +221,6 @@ static int gl_getc(void) return c; } -#ifdef __unix__ - -static int gl_getcx(int tlen) -/* Get a character without echoing it to screen, timing out - * after tlen tenths of a second. - */ -{ - - for (errno = 0;;) { - fd_set ss; - FD_ZERO(&ss); - FD_SET(0, &ss); /* set STDIN_FILENO */ - - struct timeval tv; - tv.tv_sec = tlen / 10; - tv.tv_usec = (tlen % 10) * 100000L; - int result = select(1, &ss, NULL, NULL, &tv); - if (result == 1) { - /* ready */ - break; - } - else if (result == 0) { - errno = ETIMEDOUT; - return (-2); - } - else if (errno != EINTR) { - return (-1); - } - } - - for (errno = 0;;) { - char ch; - int c = read(0, &ch, 1); - if (c == 1) - return ((int)ch); - if (errno != EINTR) - break; - } - - return (-1); -} /* gl_getcx */ - -#endif /* __unix__ */ - -#ifdef __windows__ - -static int gl_getcx(int tlen) -{ - int c = (-2); - tlen -= 2; /* Adjust for 200ms overhead */ - if (tlen < 1) - tlen = 1; - for (int i = 0; i < tlen; i++) { - if (_kbhit()) { - c = (int)_getch(); - if ((c == 0) || (c == 0xE0)) { - /* Read key code */ - c = (int)_getch(); - c = pc_keymap(c); - } - } - (void)SleepEx((DWORD)(tlen * 100), FALSE); - } - return (c); -} /* gl_getcx */ - -#endif /* __windows__ */ - static void gl_putc(int c) { char ch = (char)(unsigned char)c; @@ -493,176 +296,20 @@ void gl_setwidth(int w) char *getline_int(char *prompt) { - int c, lastch; - int count; - char vi_countbuf[32]; - -#ifdef __unix__ - int sig; -#endif - - /* Even if it appears that "vi" is preferred, we - * don't start in gl_vi_mode. They need to hit - * ESC to go into vi command mode. - */ - gl_vi_mode = 0; - int vi_count = 0; - int vi_delete = 0; - if (gl_vi_preferred < 0) { - gl_vi_preferred = 0; - char *cp = (char *)getenv("EDITOR"); - if (cp != NULL) - gl_vi_preferred = (strstr(cp, "vi") != NULL); - } - gl_init(); gl_prompt = (prompt) ? prompt : ""; gl_buf[0] = 0; - if (gl_in_hook) - gl_in_hook(gl_buf); gl_fixup(gl_prompt, -2, GL_BUF_SIZE); - lastch = 0; #ifdef __windows__ FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE)); #endif + int c; while ((c = gl_getc()) >= 0) { gl_extent = 0; /* reset to full extent */ if (isprint(c)) { - if (gl_vi_mode > 0) { - /* "vi" emulation -- far from perfect, - * but reasonably functional. - */ - vi: - for (count = 0;;) { - if (isdigit(c)) { - if (vi_countbuf[sizeof(vi_countbuf) - 2] == '\0') - vi_countbuf[strlen(vi_countbuf)] = (char)c; - } - else if (vi_countbuf[0] != '\0') { - vi_count = atoi(vi_countbuf); - memset(vi_countbuf, 0, sizeof(vi_countbuf)); - } - switch (c) { - case 'b': gl_word(-1); break; - case 'w': - if (vi_delete) { - gl_killword(1); - } - else { - gl_word(1); - } - break; - case 'h': /* left */ - if (vi_delete) { - if (gl_pos > 0) { - gl_fixup(gl_prompt, -1, gl_pos - 1); - gl_del(0, 1); - } - } - else { - gl_fixup(gl_prompt, -1, gl_pos - 1); - } - break; - case ' ': - case 'l': /* right */ - if (vi_delete) { - gl_del(0, 1); - } - else { - gl_fixup(gl_prompt, -1, gl_pos + 1); - } - break; - case 'k': /* up */ - copy_string(gl_buf, hist_prev(), GL_BUF_SIZE); - if (gl_in_hook) - gl_in_hook(gl_buf); - gl_fixup(gl_prompt, 0, GL_BUF_SIZE); - break; - case 'j': /* down */ - copy_string(gl_buf, hist_next(), GL_BUF_SIZE); - if (gl_in_hook) - gl_in_hook(gl_buf); - gl_fixup(gl_prompt, 0, GL_BUF_SIZE); - break; - case 'd': - if (vi_delete == 1) { - gl_kill(0); - vi_count = 1; - vi_delete = 0; - gl_vi_mode = 0; - goto vi_break; - } - else { - vi_delete = 1; - goto vi_break; - } - break; - case '^': /* start of line */ - if (vi_delete) { - vi_count = gl_pos; - gl_fixup(gl_prompt, -1, 0); - for (c = 0; c < vi_count; c++) { - if (gl_cnt > 0) - gl_del(0, 0); - } - vi_count = 1; - vi_delete = 0; - } - else { - gl_fixup(gl_prompt, -1, 0); - } - break; - case '$': /* end of line */ - if (vi_delete) { - gl_kill(gl_pos); - } - else { - int loc = (int)strlen(gl_buf); - if (loc > 1) - loc--; - gl_fixup(gl_prompt, -1, loc); - } - break; - case 'p': /* paste after */ - gl_fixup(gl_prompt, -1, gl_pos + 1); - gl_yank(); - break; - case 'P': /* paste before */ gl_yank(); break; - case 'r': /* replace character */ - gl_buf[gl_pos] = (char)gl_getc(); - gl_fixup(gl_prompt, gl_pos, gl_pos); - vi_count = 1; - break; - case 'R': - gl_overwrite = 1; - gl_vi_mode = 0; - break; - case 'i': - case 'I': - gl_overwrite = 0; - gl_vi_mode = 0; - break; - case 'o': - case 'O': - case 'a': - case 'A': - gl_overwrite = 0; - gl_fixup(gl_prompt, -1, gl_pos + 1); - gl_vi_mode = 0; - break; - } - count++; - if (count >= vi_count) - break; - } - vi_count = 1; - vi_delete = 0; - vi_break: - continue; - } - else if (gl_search_mode) { + if (gl_search_mode) { search_addchar(c); } else { @@ -718,28 +365,7 @@ char *getline_int(char *prompt) case '\177': gl_del(-1, 0); /* ^H and DEL */ break; - case '\t': /* TAB */ - { - int tmp = gl_pos; - if (gl_completion_proc) { - gl_buf[sizeof(gl_buf) - 1] = '\0'; - int loc = gl_do_tab_completion(gl_buf, &tmp, sizeof(gl_buf)); - gl_buf[sizeof(gl_buf) - 1] = '\0'; - if (loc >= 0 || tmp != gl_pos) - gl_fixup(gl_prompt, /* loc */ -2, tmp); - if (lastch == '\t') { - c = 0; - lastch = 0; - } - } - else if (gl_tab_hook) { - gl_buf[sizeof(gl_buf) - 1] = '\0'; - int loc = gl_tab_hook(gl_buf, (int)gl_strlen(gl_prompt), &tmp, sizeof(gl_buf)); - gl_buf[sizeof(gl_buf) - 1] = '\0'; - if (loc >= 0 || tmp != gl_pos) - gl_fixup(gl_prompt, loc, tmp); - } - } break; + case '\t': /* TAB */ break; case '\013': gl_kill(gl_pos); /* ^K */ break; @@ -748,8 +374,6 @@ char *getline_int(char *prompt) break; case '\016': /* ^N */ copy_string(gl_buf, hist_next(), GL_BUF_SIZE); - if (gl_in_hook) - gl_in_hook(gl_buf); gl_fixup(gl_prompt, 0, GL_BUF_SIZE); break; case '\017': @@ -757,8 +381,6 @@ char *getline_int(char *prompt) break; case '\020': /* ^P */ copy_string(gl_buf, hist_prev(), GL_BUF_SIZE); - if (gl_in_hook) - gl_in_hook(gl_buf); gl_fixup(gl_prompt, 0, GL_BUF_SIZE); break; case '\022': @@ -776,90 +398,12 @@ char *getline_int(char *prompt) case '\031': gl_yank(); /* ^Y */ break; - case '\033': /* ansi arrow keys */ - c = gl_getcx(3); - if (c == '[') { - switch (c = gl_getc()) { - case 'A': /* up */ - copy_string(gl_buf, hist_prev(), GL_BUF_SIZE); - if (gl_in_hook) - gl_in_hook(gl_buf); - gl_fixup(gl_prompt, 0, GL_BUF_SIZE); - break; - case 'B': /* down */ - copy_string(gl_buf, hist_next(), GL_BUF_SIZE); - if (gl_in_hook) - gl_in_hook(gl_buf); - gl_fixup(gl_prompt, 0, GL_BUF_SIZE); - break; - case 'C': - gl_fixup(gl_prompt, -1, gl_pos + 1); /* right */ - break; - case 'D': - gl_fixup(gl_prompt, -1, gl_pos - 1); /* left */ - break; - default: - gl_beep(); /* who knows */ - break; - } - } - else if ((gl_vi_preferred == 0) && ((c == 'f') || (c == 'F'))) { - gl_word(1); - } - else if ((gl_vi_preferred == 0) && ((c == 'b') || (c == 'B'))) { - gl_word(-1); - } - else { - /* enter vi command mode */ - if (gl_vi_mode == 0) { - gl_vi_mode = 1; - vi_count = 1; - vi_delete = 0; - memset(vi_countbuf, 0, sizeof(vi_countbuf)); - if (gl_pos > 0) - gl_fixup(gl_prompt, -2, gl_pos - 1); /* left 1 char */ - /* Don't bother if the line is empty. */ - if (gl_cnt > 0) { - /* We still have to use the char read! */ - goto vi; - } - gl_vi_mode = 0; - } - gl_beep(); - } - break; - default: /* check for a terminal signal */ -#ifdef __unix__ - if (c > 0) { /* ignore 0 (reset above) */ - sig = 0; -#ifdef SIGINT - if (c == gl_intrc) - sig = SIGINT; -#endif -#ifdef SIGQUIT - if (c == gl_quitc) - sig = SIGQUIT; -#endif -#ifdef SIGTSTP - if (c == gl_suspc || c == gl_dsuspc) - sig = SIGTSTP; -#endif - if (sig != 0) { - gl_cleanup(); - kill(0, sig); - gl_init(); - gl_redraw(); - c = 0; - } - } -#endif /* __unix__ */ + default: if (c > 0) gl_beep(); break; } } - if (c > 0) - lastch = c; } gl_cleanup(); gl_buf[0] = 0; @@ -941,10 +485,6 @@ static void gl_newline(void) if (gl_cnt >= GL_BUF_SIZE - 1) gl_error("\n*** Error: getline(): input buffer overflow\n"); - if (gl_out_hook) { - change = gl_out_hook(gl_buf); - len = strlen(gl_buf); - } if (loc > len) loc = len; gl_fixup(gl_prompt, change, loc); /* must do this before appending \n */ @@ -964,7 +504,7 @@ static void gl_del(int loc, int killsave) if ((loc == -1 && gl_pos > 0) || (loc == 0 && gl_pos < gl_cnt)) { int j = 0; for (int i = gl_pos + loc; i < gl_cnt; i++) { - if ((j == 0) && (killsave != 0) && (gl_vi_mode != 0)) { + if ((j == 0) && (killsave != 0)) { gl_killbuf[0] = gl_buf[i]; gl_killbuf[1] = '\0'; j = 1; @@ -990,65 +530,6 @@ static void gl_kill(int pos) gl_beep(); } -static void gl_killword(int direction) -{ - int pos = gl_pos; - if (direction > 0) { /* forward */ - while (pos < gl_cnt && !isspace(gl_buf[pos])) - pos++; - while (pos < gl_cnt && isspace(gl_buf[pos])) - pos++; - } - else { /* backward */ - if (pos > 0) - pos--; - while (pos > 0 && isspace(gl_buf[pos])) - pos--; - while (pos > 0 && !isspace(gl_buf[pos])) - pos--; - if (pos < gl_cnt && isspace(gl_buf[pos])) /* move onto word */ - pos++; - } - int startpos = gl_pos; - if (pos < startpos) { - int tmp = pos; - pos = startpos; - startpos = tmp; - } - memcpy(gl_killbuf, gl_buf + startpos, (size_t)(pos - startpos)); - gl_killbuf[pos - startpos] = '\0'; - if (isspace(gl_killbuf[pos - startpos - 1])) - gl_killbuf[pos - startpos - 1] = '\0'; - gl_fixup(gl_prompt, -1, startpos); - for (int i = 0, tmp = pos - startpos; i < tmp; i++) - gl_del(0, 0); -} /* gl_killword */ - -static void gl_word(int direction) - -/* move forward or backward one word */ -{ - int pos = gl_pos; - - if (direction > 0) { /* forward */ - while (pos < gl_cnt && !isspace(gl_buf[pos])) - pos++; - while (pos < gl_cnt && isspace(gl_buf[pos])) - pos++; - } - else { /* backward */ - if (pos > 0) - pos--; - while (pos > 0 && isspace(gl_buf[pos])) - pos--; - while (pos > 0 && !isspace(gl_buf[pos])) - pos--; - if (pos < gl_cnt && isspace(gl_buf[pos])) /* move onto word */ - pos++; - } - gl_fixup(gl_prompt, -1, pos); -} - static void gl_redraw(void) /* emit a newline, reset and redraw prompt and current input line */ { @@ -1091,11 +572,11 @@ static void gl_fixup(const char *prompt, int change, int cursor) gl_puts(prompt); copy_string(last_prompt, prompt, 80 - 1); change = 0; - gl_width = gl_termw - gl_strlen(prompt); + gl_width = gl_termw - strlen(prompt); } else if (strcmp(prompt, last_prompt) != 0) { - l1 = gl_strlen(last_prompt); - l2 = gl_strlen(prompt); + l1 = strlen(last_prompt); + l2 = strlen(prompt); gl_cnt = gl_cnt + l1 - l2; copy_string(last_prompt, prompt, 80 - 1); gl_putc('\r'); @@ -1187,22 +668,6 @@ static void gl_fixup(const char *prompt, int change, int cursor) gl_pos = cursor; } -static int gl_tab(char *buf, int offset, int *loc, size_t bufsize) -/* default tab handler, acts like tabstops every 8 cols */ -{ - int len = strlen(buf); - int count = 8 - (offset + *loc) % 8; - for (int i = len; i >= *loc; i--) - if (i + count < (int)bufsize) - buf[i + count] = buf[i]; - for (int i = 0; i < count; i++) - if (*loc + i < (int)bufsize) - buf[*loc + i] = ' '; - int i = *loc; - *loc = i + count; - return i; -} - /******************* History stuff **************************************/ #ifndef HIST_SIZE @@ -1306,46 +771,6 @@ static char *hist_save(char *p) return s; } -void gl_histsavefile(const char *const path) -{ - FILE *fp = fopen(path, -#if defined(__windows__) || defined(MSDOS) - "wt" -#else - "w" -#endif - ); - if (fp != NULL) { - for (int i = 2; i < HIST_SIZE; i++) { - int j = (hist_pos + i) % HIST_SIZE; - char *p = hist_buf[j]; - if ((p == NULL) || (*p == '\0')) - continue; - fprintf(fp, "%s\n", p); - } - fclose(fp); - } -} /* gl_histsavefile */ - -void gl_histloadfile(const char *const path) -{ - FILE *fp = fopen(path, -#if defined(__windows__) || defined(MSDOS) - "rt" -#else - "r" -#endif - ); - if (fp != NULL) { - char line[256]; - memset(line, 0, sizeof(line)); - while (fgets(line, sizeof(line) - 2, fp) != NULL) { - gl_histadd(line); - } - fclose(fp); - } -} /* gl_histloadfile */ - /******************* Search stuff **************************************/ static char search_prompt[101]; /* prompt includes search string */ @@ -1423,8 +848,6 @@ static void search_term(void) gl_search_mode = 0; if (gl_buf[0] == 0) /* not found, reset hist list */ hist_pos = hist_last; - if (gl_in_hook) - gl_in_hook(gl_buf); gl_fixup(gl_prompt, 0, gl_pos); } @@ -1506,619 +929,3 @@ static void gl_beep(void) gl_putc('\007'); #endif } /* gl_beep */ - -static int gl_do_tab_completion(char *buf, int *loc, size_t bufsize) -{ - int i; - int allmatch; - - /* Zero out the rest of the buffer, so we can move stuff around - * and know we'll still be NUL-terminated. - */ - size_t llen = strlen(buf); - memset(buf + llen, 0, bufsize - llen); - bufsize -= 4; /* leave room for a NUL, space, and two quotes. */ - char * curposp = buf + *loc; - int wasateol = (*curposp == '\0'); - size_t lenaftercursor = llen - (curposp - buf); - if (gl_ellipses_during_completion != 0) { - char ellipsessave[4]; - memcpy(ellipsessave, curposp, (size_t)4); - memcpy(curposp, "... ", (size_t)4); - gl_fixup(gl_prompt, gl_pos, gl_pos + 3); - memcpy(curposp, ellipsessave, (size_t)4); - } - - int qmode = 0; - char *qstart = NULL; - char *lastspacestart = NULL; - char *matchpfx = NULL; - - char *cp = buf; - while (cp < curposp) { - int c = (int)*cp++; - if (c == '\0') - break; - if ((c == '"') || (c == '\'')) { - if (qmode == c) { - /* closing quote; end it. */ - qstart = NULL; - qmode = 0; - } - else if (qmode != 0) { - /* just treat it as a regular char. */ - } - else { - /* start new quote group. */ - qmode = c; - qstart = cp - 1; - } - } - else if ((isspace(c)) && (qmode == 0)) { - /* found a non-quoted space. */ - lastspacestart = cp - 1; - } - else { - /* regular char */ - } - } - - char *startp; - if (qstart != NULL) - startp = qstart + 1; - else if (lastspacestart != NULL) - startp = lastspacestart + 1; - else - startp = buf; - - cp = startp; - size_t mlen = (curposp - cp); - - matchpfx = (char *)malloc(mlen + 1); - memcpy(matchpfx, cp, mlen); - matchpfx[mlen] = '\0'; - -#define GL_COMPLETE_VECTOR_BLOCK_SIZE 64 - - int nused = 0; - int ntoalloc = GL_COMPLETE_VECTOR_BLOCK_SIZE; - char **newgl_matchlist = (char **)malloc((size_t)(sizeof(char *) * (ntoalloc + 1))); - if (newgl_matchlist == NULL) { - free(matchpfx); - gl_beep(); - return 0; - } - gl_matchlist = newgl_matchlist; - int nalloced = ntoalloc; - for (i = nused; i <= nalloced; i++) - gl_matchlist[i] = NULL; - - gl_completion_exact_match_extra_char = ' '; - for (;; nused++) { - if (nused == nalloced) { - ntoalloc += GL_COMPLETE_VECTOR_BLOCK_SIZE; - newgl_matchlist = - (char **)realloc((char *)gl_matchlist, (size_t)(sizeof(char *) * (ntoalloc + 1))); - if (newgl_matchlist == NULL) { - /* not enough memory to expand list -- abort */ - for (i = 0; i < nused; i++) - free(gl_matchlist[i]); - free(gl_matchlist); - gl_matchlist = NULL; - gl_beep(); - free(matchpfx); - return 0; - } - gl_matchlist = newgl_matchlist; - nalloced = ntoalloc; - for (i = nused; i <= nalloced; i++) - gl_matchlist[i] = NULL; - } - cp = gl_completion_proc(matchpfx, nused); - gl_matchlist[nused] = cp; - if (cp == NULL) - break; - } - - if (gl_ellipses_during_completion != 0) { - gl_fixup(gl_prompt, gl_pos, gl_pos); - gl_puts(" "); - } - - /* We now have an array strings, whose last element is NULL. */ - char *strtoadd = NULL; - char *strtoadd1 = NULL; - - int addquotes = (gl_filename_quoting_desired > 0) || - ((gl_filename_quoting_desired < 0) && - (gl_completion_proc == gl_local_filename_completion_proc)); - - if (nused == 1) { - /* Exactly one match. */ - strtoadd = gl_matchlist[0]; - } - else if ((nused > 1) && (mlen > 0)) { - /* Find the greatest amount that matches. */ - size_t glen = 1; - for (glen = 1;; glen++) { - allmatch = 1; - for (i = 1; i < nused; i++) { - if (gl_matchlist[0][glen] != gl_matchlist[i][glen]) { - allmatch = 0; - break; - } - } - if (allmatch == 0) - break; - } - strtoadd1 = (char *)malloc(glen + 1); - if (strtoadd1 != NULL) { - memcpy(strtoadd1, gl_matchlist[0], glen); - strtoadd1[glen] = '\0'; - strtoadd = strtoadd1; - } - } - - if (strtoadd != NULL) { - if ((qmode == 0) && (addquotes != 0)) { - if (strpbrk(strtoadd, gl_filename_quote_characters) != NULL) { - qmode = (strchr(strtoadd, '"') == NULL) ? '"' : '\''; - memmove(curposp + 1, curposp, lenaftercursor + 1 /* NUL */); - curposp++; - *startp++ = (char)qmode; - } - } - size_t startoff = (size_t)(startp - buf); - size_t amt = strlen(strtoadd); - if ((amt + startoff + lenaftercursor) >= bufsize) - amt = bufsize - (amt + startoff + lenaftercursor); - memmove(curposp + amt - mlen, curposp, lenaftercursor + 1 /* NUL */); - curposp += amt - mlen; - memcpy(startp, strtoadd, amt); - if (nused == 1) { - /* Exact match. */ - if (qmode != 0) { - /* Finish the quoting. */ - memmove(curposp + 1, curposp, lenaftercursor + 1 /* NUL */); - curposp++; - buf[amt + startoff] = (char)qmode; - amt++; - } - memmove(curposp + 1, curposp, lenaftercursor + 1 /* NUL */); - curposp++; - buf[amt + startoff] = (char)gl_completion_exact_match_extra_char; - amt++; - } - else if ((!wasateol) && (!isspace(*curposp))) { - /* Not a full match, but insert a - * space for better readability. - */ - memmove(curposp + 1, curposp, lenaftercursor + 1 /* NUL */); - curposp++; - buf[amt + startoff] = ' '; - } - *loc = (int)(startoff + amt); - - if (strtoadd1 != NULL) - free(strtoadd1); - } - - /* Don't need this any more. */ - for (i = 0; i < nused; i++) - free(gl_matchlist[i]); - free(gl_matchlist); - gl_matchlist = NULL; - free(matchpfx); - - return 0; -} /* gl_do_tab_completion */ - -void gl_tab_completion(gl_tab_completion_proc proc) -{ - if (proc == NULL) - proc = gl_local_filename_completion_proc; /* default proc */ - gl_completion_proc = proc; -} /* gl_tab_completion */ - -#ifndef _StrFindLocalPathDelim -static char *_StrRFindLocalPathDelim(const char *src) /* TODO: optimize */ -{ - const char *last = NULL; - for (;;) { - int c = *src++; - if (c == '\0') - break; - if (IsLocalPathDelim(c)) - last = src - 1; - } - - return ((char *)last); -} /* StrRFindLocalPathDelim */ -#endif /* Windows */ - -void gl_set_home_dir(const char *homedir) -{ - if (gl_home_dir != NULL) { - free(gl_home_dir); - gl_home_dir = NULL; - } - - if (homedir == NULL) { -#ifdef __windows__ - const char *homedrive = getenv("HOMEDRIVE"); - const char *homepath = getenv("HOMEPATH"); - if ((homedrive != NULL) && (homepath != NULL)) { - size_t len = strlen(homedrive) + strlen(homepath) + 1; - gl_home_dir = (char *)malloc(len); - if (gl_home_dir != NULL) { - copy_string(gl_home_dir, homedrive, len); - strcat(gl_home_dir, homepath); - return; - } - } - - char wdir[64]; - wdir[0] = '\0'; - if (GetWindowsDirectory(wdir, sizeof(wdir) - 1) < 1) - (void)copy_string(wdir, ".", sizeof(wdir)); - else if (wdir[1] == ':') { - wdir[2] = '\\'; - wdir[3] = '\0'; - } - homedir = wdir; -#else - char *cp = (char *)getlogin(); - if (cp == NULL) { - cp = (char *)getenv("LOGNAME"); - if (cp == NULL) - cp = (char *)getenv("USER"); - } - struct passwd *pw = NULL; - if (cp != NULL) - pw = getpwnam(cp); - if (pw == NULL) - pw = getpwuid(getuid()); - if (pw == NULL) - return; /* hell with it */ - homedir = pw->pw_dir; -#endif - } - - size_t len = strlen(homedir) + /* NUL */ 1; - gl_home_dir = (char *)malloc(len); - if (gl_home_dir != NULL) { - memcpy(gl_home_dir, homedir, len); - } -} /* gl_set_home_dir */ - -#ifdef __unix__ - -char *gl_local_filename_completion_proc(const char *start, int idx) -{ - static DIR * dir = NULL; - static int filepfxoffset; - static size_t filepfxlen; - - if (idx == 0) { - if (dir != NULL) { - /* shouldn't get here! */ - closedir(dir); - dir = NULL; - } - } - - if (dir == NULL) { - const char *dirtoopen; - char * dirtoopen1 = NULL; - char * cp = _StrRFindLocalPathDelim(start); - if (cp == start) { - dirtoopen = LOCAL_PATH_DELIM_STR; /* root dir */ - filepfxoffset = 1; - } - else if (cp == NULL) { - dirtoopen = "."; - filepfxoffset = 0; - } - else { - size_t len = strlen(start) + 1; - dirtoopen1 = (char *)malloc(len); - if (dirtoopen1 == NULL) - return NULL; - memcpy(dirtoopen1, start, len); - len = (cp - start); - dirtoopen1[len] = '\0'; - dirtoopen = dirtoopen1; - filepfxoffset = (int)((cp + 1) - start); - } - - if (strcmp(dirtoopen, "~") == 0) { - if (gl_home_dir == NULL) - gl_set_home_dir(NULL); - if (gl_home_dir == NULL) { - if (dirtoopen1 != NULL) - free(dirtoopen1); - return (NULL); - } - dirtoopen = gl_home_dir; - } - - dir = opendir(dirtoopen); - if (dirtoopen1 != NULL) - free(dirtoopen1); - - const char *filepfx = start + filepfxoffset; - filepfxlen = strlen(filepfx); - } - - if (dir != NULL) { - /* assumes "start" is same for each iteration. */ - const char *filepfx = start + filepfxoffset; - - for (;;) { - struct dirent *dent = readdir(dir); - if (dent == NULL) { - /* no more items */ - closedir(dir); - dir = NULL; - - if (idx == 1) { - /* There was exactly one match. - * In this special case, we - * want to append a / instead - * of a space. - */ - char *cp = gl_matchlist[0]; - if ((cp[0] == '~') && ((cp[1] == '\0') || (IsLocalPathDelim(cp[1])))) { - size_t len = strlen(cp + 1) + /* NUL */ 1; - size_t len2 = strlen(gl_home_dir); - if (IsLocalPathDelim(gl_home_dir[len2 - 1])) - len2--; - cp = (char *)realloc(gl_matchlist[0], len + len2); - if (cp == NULL) { - cp = gl_matchlist[0]; - } - else { - memmove(cp + len2, cp + 1, len); - memcpy(cp, gl_home_dir, len2); - gl_matchlist[0] = cp; - } - } - struct stat st; - if ((stat(cp, &st) == 0) && (S_ISDIR(st.st_mode))) - gl_completion_exact_match_extra_char = LOCAL_PATH_DELIM; - } - return NULL; - } - - const char *name = dent->d_name; - if ((name[0] == '.') && ((name[1] == '\0') || ((name[1] == '.') && (name[2] == '\0')))) - continue; /* Skip . and .. */ - - if ((filepfxlen == 0) || (strncmp(name, filepfx, filepfxlen) == 0)) { - /* match */ - size_t len = strlen(name); - char * cp = (char *)malloc(filepfxoffset + len + 1 /* spare */ + 1 /* NUL */); - *cp = '\0'; - if (filepfxoffset > 0) - memcpy(cp, start, (size_t)filepfxoffset); - memcpy(cp + filepfxoffset, name, len + 1); - return (cp); - } - } - } - - return NULL; -} /* gl_local_filename_completion_proc */ - -#endif /* __unix__ */ - -#ifdef __windows__ - -char *gl_local_filename_completion_proc(const char *start, int idx) -{ - static HANDLE searchHandle = NULL; - static int filepfxoffset; - static size_t filepfxlen; - - WIN32_FIND_DATA ffd; - DWORD dwErr; - char * cp, *c2, ch; - const char * filepfx; - const char * dirtoopen, *name; - char * dirtoopen1, *dirtoopen2; - size_t len, len2; - - if (idx == 0) { - if (searchHandle != NULL) { - /* shouldn't get here! */ - FindClose(searchHandle); - searchHandle = NULL; - } - } - - if (searchHandle == NULL) { - dirtoopen1 = NULL; - dirtoopen2 = NULL; - cp = _StrRFindLocalPathDelim(start); - if (cp == start) { - dirtoopen = LOCAL_PATH_DELIM_STR; /* root dir */ - filepfxoffset = 1; - } - else if (cp == NULL) { - dirtoopen = "."; - filepfxoffset = 0; - } - else { - len = strlen(start) + 1; - dirtoopen1 = (char *)malloc(len); - if (dirtoopen1 == NULL) - return NULL; - memcpy(dirtoopen1, start, len); - len = (cp - start); - dirtoopen1[len] = '\0'; - dirtoopen = dirtoopen1; - filepfxoffset = (int)((cp + 1) - start); - } - - if (strcmp(dirtoopen, "~") == 0) { - if (gl_home_dir == NULL) - gl_set_home_dir(NULL); - if (gl_home_dir == NULL) - return (NULL); - dirtoopen = gl_home_dir; - } - - len = strlen(dirtoopen); - dirtoopen2 = (char *)malloc(len + 8); - if (dirtoopen2 == NULL) { - if (dirtoopen1 != NULL) - free(dirtoopen1); - return NULL; - } - - memcpy(dirtoopen2, dirtoopen, len + 1); - if (dirtoopen2[len - 1] == LOCAL_PATH_DELIM) - memcpy(dirtoopen2 + len, "*.*", (size_t)4); - else - memcpy(dirtoopen2 + len, "\\*.*", (size_t)5); - - /* "Open" the directory. */ - memset(&ffd, 0, sizeof(ffd)); - searchHandle = FindFirstFile(dirtoopen2, &ffd); - - free(dirtoopen2); - if (dirtoopen1 != NULL) - free(dirtoopen1); - - if (searchHandle == INVALID_HANDLE_VALUE) { - return NULL; - } - - filepfx = start + filepfxoffset; - filepfxlen = strlen(filepfx); - } - else { - /* assumes "start" is same for each iteration. */ - filepfx = start + filepfxoffset; - goto next; - } - - for (;;) { - - name = ffd.cFileName; - if ((name[0] == '.') && ((name[1] == '\0') || ((name[1] == '.') && (name[2] == '\0')))) - goto next; /* Skip . and .. */ - - if ((filepfxlen == 0) || (strnicmp(name, filepfx, filepfxlen) == 0)) { - /* match */ - len = strlen(name); - cp = (char *)malloc(filepfxoffset + len + 4 /* spare */ + 1 /* NUL */); - *cp = '\0'; - if (filepfxoffset > 0) - memcpy(cp, start, filepfxoffset); - memcpy(cp + filepfxoffset, name, len + 1); - if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - /* Embed file type with name. */ - c2 = cp + filepfxoffset + len + 1; - *c2++ = '\0'; - *c2++ = 'd'; - *c2 = '\0'; - } - else { - c2 = cp + filepfxoffset + len + 1; - *c2++ = '\0'; - *c2++ = '-'; - *c2 = '\0'; - } - return (cp); - } - - next: - if (!FindNextFile(searchHandle, &ffd)) { - dwErr = GetLastError(); - if (dwErr != ERROR_NO_MORE_FILES) { - FindClose(searchHandle); - searchHandle = NULL; - return NULL; - } - - /* no more items */ - FindClose(searchHandle); - searchHandle = NULL; - - if (idx == 1) { - /* There was exactly one match. - * In this special case, we - * want to append a \ instead - * of a space. - */ - cp = gl_matchlist[0]; - ch = (char)cp[strlen(cp) + 2]; - if (ch == (char)'d') - gl_completion_exact_match_extra_char = LOCAL_PATH_DELIM; - - if ((cp[0] == '~') && ((cp[1] == '\0') || (IsLocalPathDelim(cp[1])))) { - len = strlen(cp + 1) + /* NUL */ 1; - len2 = strlen(gl_home_dir); - if (IsLocalPathDelim(gl_home_dir[len2 - 1])) - len2--; - cp = (char *)realloc(gl_matchlist[0], len + len2 + 4); - if (cp == NULL) { - cp = gl_matchlist[0]; - } - else { - memmove(cp + len2, cp + 1, len); - memcpy(cp, gl_home_dir, len2); - c2 = cp + len + len2; - *c2++ = '\0'; - *c2++ = ch; - *c2 = '\0'; - gl_matchlist[0] = cp; - } - } - } - break; - } - } - return (NULL); -} /* gl_local_filename_completion_proc */ - -char *gl_win_getpass(const char *const prompt, char *const pass, int dsize) -{ - char *cp; - - FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE)); - ZeroMemory(pass, (DWORD)sizeof(dsize)); - dsize--; - - if ((prompt != NULL) && (prompt[0] != '\0')) - _cputs(prompt); - - for (cp = pass;;) { - int c = (int)_getch(); - if ((c == '\r') || (c == '\n')) - break; - if ((c == '\010') || (c == '\177')) { - /* ^H and DEL */ - if (cp > pass) { - *--cp = '\0'; - _putch('\010'); - _putch(' '); - _putch('\010'); - } - } - else if (cp < (pass + dsize)) { - _putch('*'); - *cp++ = c; - } - } - _putch('\r'); - _putch('\n'); - Sleep(40); - FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE)); - - *cp = '\0'; - return (pass); -} /* gl_getpass */ - -#endif /* __windows__ */ diff --git a/packages/seacas/libraries/supes/ext_lib/getline_int.h b/packages/seacas/libraries/supes/ext_lib/getline_int.h index 4af9fc4c9654..dfa51b41dd82 100644 --- a/packages/seacas/libraries/supes/ext_lib/getline_int.h +++ b/packages/seacas/libraries/supes/ext_lib/getline_int.h @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2020 National Technology & Engineering Solutions + * Copyright(C) 1999-2021 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * @@ -9,45 +9,10 @@ #ifndef GETLINE_H #define GETLINE_H -#include - -/* unix systems can #define POSIX to use termios, otherwise - * the bsd or sysv interface will be used - */ - #define GL_BUF_SIZE 1024 -typedef size_t (*gl_strwidth_proc)(char *); -typedef int (*gl_in_hook_proc)(char *); -typedef int (*gl_out_hook_proc)(char *); -typedef int (*gl_tab_hook_proc)(char *, int, int *, size_t); -typedef size_t (*gl_strlen_proc)(const char *); -typedef char *(*gl_tab_completion_proc)(const char *, int); - -char *getline_int(char *); /* read a line of input */ -void gl_setwidth(int); /* specify width of screen */ -void gl_histadd(char *); /* adds entries to hist */ -void gl_strwidth(gl_strwidth_proc); /* to bind gl_strlen */ -void gl_tab_completion(gl_tab_completion_proc); -char *gl_local_filename_completion_proc(const char *, int); -void gl_set_home_dir(const char *homedir); -void gl_histsavefile(const char *const path); -void gl_histloadfile(const char *const path); -char *gl_win_getpass(const char *const prompt, char *const pass, int dsize); - -#ifndef _getline_c_ - -extern gl_in_hook_proc gl_in_hook; -extern gl_out_hook_proc gl_out_hook; -extern gl_tab_hook_proc gl_tab_hook; -extern gl_strlen_proc gl_strlen; -extern gl_tab_completion_proc gl_completion_proc; -extern int gl_filename_quoting_desired; -extern const char * gl_filename_quote_characters; -extern int gl_ellipses_during_completion; -extern int gl_completion_exact_match_extra_char; -extern char gl_buf[GL_BUF_SIZE]; - -#endif /* ! _getline_c_ */ +char *getline_int(char *); /* read a line of input */ +void gl_setwidth(int); /* specify width of screen */ +void gl_histadd(char *); /* adds entries to hist */ #endif /* GETLINE_H */ diff --git a/packages/seacas/libraries/suplib/addlog.c b/packages/seacas/libraries/suplib/addlog.c index 1279fbc2b0cb..edc247675214 100644 --- a/packages/seacas/libraries/suplib/addlog.c +++ b/packages/seacas/libraries/suplib/addlog.c @@ -1,24 +1,28 @@ /* - * Copyright(C) 1999-2020 National Technology & Engineering Solutions + * Copyright(C) 1999-2021 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * * See packages/seacas/LICENSE for details */ +#if !defined(WIN32) && !defined(__WIN32__) && !defined(_WIN32) && !defined(_MSC_VER) && \ + !defined(__MINGW32__) && !defined(_WIN64) && !defined(__MINGW64__) +/* Currently we just disable this functionality for windows-based systems... */ #include #include -#if !defined(__CYGWIN__) -#include + +#include #include + #include #include -#endif #ifndef __USE_XOPEN #define __USE_XOPEN #endif #include +#endif #if defined(ADDC_) void addlog_(char *name, int len) @@ -26,72 +30,70 @@ void addlog_(char *name, int len) void addlog(char *name, int len) #endif { -#if !defined(__CYGWIN__) +#if !defined(WIN32) && !defined(__WIN32__) && !defined(_WIN32) && !defined(_MSC_VER) && \ + !defined(__MINGW32__) && !defined(_WIN64) && !defined(__MINGW64__) #define LEN 512 - char time_string[LEN]; - char log_string[LEN]; - char codename[LEN]; - - double u_time, s_time; - struct utsname sys_info; - const char * username = NULL; - /* Don't log information if this environment variable is set */ if (getenv("SEACAS_NO_LOGGING") != NULL) { fprintf(stderr, "SEACAS Audit logging disabled via SEACAS_NO_LOGGING setting.\n"); return; } - username = getlogin(); - if (username == NULL) { - username = getenv("LOGNAME"); - } - if (username == NULL) { - username = "UNKNOWN"; - } + /* Now try to find the $ACCESS/etc/audit.log file */ + /* Don't need to try too hard since information is not critical; just useful */ + char *access_dir = getenv("ACCESS"); + if (access_dir != NULL) { + char filename[LEN]; + snprintf(filename, LEN, "%s/etc/audit.log", access_dir); + if (0 == access(filename, W_OK)) { + FILE *audit = fopen(filename, "a"); + if (audit != NULL) { + const char *codename = strrchr(name, '/'); - { - int i; - for (i = 0; i < len; i++) - codename[i] = name[i]; - codename[len] = '\0'; - } + const char *username = getlogin(); + if (username == NULL) { + username = getenv("LOGNAME"); + } + if (username == NULL) { + username = "UNKNOWN"; + } - { - time_t calendar_time = time(NULL); - struct tm *local_time = localtime(&calendar_time); - strftime(time_string, LEN, "%a %b %d %H:%M:%S %Z %Y", local_time); - } + if (codename == NULL) { + codename = name; + } + else { + codename++; + } - { - struct rusage rusage; - getrusage(RUSAGE_SELF, &rusage); - u_time = rusage.ru_utime.tv_sec + rusage.ru_utime.tv_usec / 1.0e6; - s_time = rusage.ru_stime.tv_sec + rusage.ru_stime.tv_usec / 1.0e6; - } + char time_string[LEN]; + time_t calendar_time = time(NULL); + struct tm *local_time = localtime(&calendar_time); + strftime(time_string, LEN, "%a %b %d %H:%M:%S %Z %Y", local_time); - uname(&sys_info); + int ticks_per_second; + struct tms time_buf; + times(&time_buf); + ticks_per_second = sysconf(_SC_CLK_TCK); + double u_time = (double)(time_buf.tms_utime + time_buf.tms_cutime) / ticks_per_second; + double s_time = (double)(time_buf.tms_stime + time_buf.tms_cstime) / ticks_per_second; - snprintf(log_string, LEN, "%s %s %s %.3fu %.3fs 0:00.00 0.0%% 0+0k 0+0io 0pf+0w %s\n", codename, - username, time_string, u_time, s_time, sys_info.nodename) < 0 - ? abort() - : (void)0; + struct utsname sys_info; + uname(&sys_info); - /* Now try to find the $ACCESS/etc/audit.log file */ - /* Don't need to try too hard since information is not critical; just useful */ - { - char *access_dir = getenv("ACCESS"); - if (access_dir != NULL) { - char filename[LEN]; - snprintf(filename, LEN, "%s/etc/audit.log", access_dir); - if (0 == access(filename, W_OK)) { - FILE *audit = fopen(filename, "a"); - if (audit != NULL) { - fprintf(audit, "%s", log_string); - fclose(audit); - } + char log_string[LEN]; + snprintf(log_string, LEN, "%s %s %s %.3fu %.3fs 0:00.00 0.0%% 0+0k 0+0io 0pf+0w %s\n", + codename, username, time_string, u_time, s_time, sys_info.nodename) < 0 + ? abort() + : (void)0; + + fprintf(audit, "%s", log_string); + fclose(audit); } } } +#else + /* Try to avoid unused variable warning/error on windows-based system */ + (void)name; + (void)len; #endif } diff --git a/packages/seacas/libraries/suplib_c/add_to_log.c b/packages/seacas/libraries/suplib_c/add_to_log.c index 0329754a6b51..2dba28e92d7b 100644 --- a/packages/seacas/libraries/suplib_c/add_to_log.c +++ b/packages/seacas/libraries/suplib_c/add_to_log.c @@ -6,12 +6,15 @@ * See packages/seacas/LICENSE for details */ +#if !defined(WIN32) && !defined(__WIN32__) && !defined(_WIN32) && !defined(_MSC_VER) && \ + !defined(__MINGW32__) && !defined(_WIN64) && !defined(__MINGW64__) +/* Currently we just disable this functionality for windows-based systems... */ #include #include -#if !defined(_WIN64) && !defined(WIN32) && !defined(_WINDOWS) && !defined(_MSC_VER) + #include #include -#endif + #include #include @@ -19,10 +22,12 @@ #define __USE_XOPEN #endif #include +#endif void add_to_log(const char *my_name, double elapsed) { -#if !defined(_WIN64) && !defined(WIN32) && !defined(_WINDOWS) && !defined(_MSC_VER) +#if !defined(WIN32) && !defined(__WIN32__) && !defined(_WIN32) && !defined(_MSC_VER) && \ + !defined(__MINGW32__) && !defined(_WIN64) && !defined(__MINGW64__) #define LEN 512 /* Don't log information if this environment variable is set */ if (getenv("SEACAS_NO_LOGGING") != NULL) { @@ -86,5 +91,9 @@ void add_to_log(const char *my_name, double elapsed) } } } +#else + /* Try to avoid unused variable warning/error on windows-based system */ + (void)my_name; + (void)elapsed; #endif } diff --git a/packages/seacas/libraries/suplib_c/open_file_limit.c b/packages/seacas/libraries/suplib_c/open_file_limit.c index 97fe238487c9..749e41d87dbd 100644 --- a/packages/seacas/libraries/suplib_c/open_file_limit.c +++ b/packages/seacas/libraries/suplib_c/open_file_limit.c @@ -4,21 +4,27 @@ // // See packages/seacas/LICENSE for details +#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || \ + defined(__MINGW32__) || defined(_WIN64) || defined(__MINGW64__) +#include +#else #include #include +#endif int open_file_limit() { // Returns maximum number of files that one process can have open // at one time. (POSIX) -#if !defined(_WIN64) && !defined(WIN32) && !defined(_WINDOWS) && !defined(_MSC_VER) +#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || \ + defined(__MINGW32__) || defined(_WIN64) || defined(__MINGW64__) + int fdmax = _getmaxstdio(); +#else int fdmax = sysconf(_SC_OPEN_MAX); if (fdmax == -1) { // POSIX indication that there is no limit on open files... fdmax = INT_MAX; } -#else - int fdmax = _getmaxstdio(); #endif // File descriptors are assigned in order (0,1,2,3,...) on a per-process diff --git a/packages/seacas/libraries/suplib_c/term_width.c b/packages/seacas/libraries/suplib_c/term_width.c index 4df76fbb758a..ebcebe4be89a 100644 --- a/packages/seacas/libraries/suplib_c/term_width.c +++ b/packages/seacas/libraries/suplib_c/term_width.c @@ -1,5 +1,5 @@ /* - * Copyright(C) 1999-2020 National Technology & Engineering Solutions + * Copyright(C) 1999-2021 National Technology & Engineering Solutions * of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with * NTESS, the U.S. Government retains certain rights in this software. * @@ -8,7 +8,8 @@ #define _POSIX_SOURCE #include -#if defined(_WIN64) || defined(WIN32) || defined(_WINDOWS) || defined(_MSC_VER) +#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || \ + defined(__MINGW32__) || defined(_WIN64) || defined(__MINGW64__) #include #define NOMINMAX #include diff --git a/packages/seacas/libraries/suplib_cpp/FileInfo.C b/packages/seacas/libraries/suplib_cpp/FileInfo.C index 25da6c111d1e..38201351fdac 100644 --- a/packages/seacas/libraries/suplib_cpp/FileInfo.C +++ b/packages/seacas/libraries/suplib_cpp/FileInfo.C @@ -1,4 +1,4 @@ -// Copyright(C) 1999-2020 National Technology & Engineering Solutions +// Copyright(C) 1999-2021 National Technology & Engineering Solutions // of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with // NTESS, the U.S. Government retains certain rights in this software. // @@ -6,11 +6,16 @@ #include #include +#include #include -#ifndef _MSC_VER -#include -#else +#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || \ + defined(__MINGW32__) || defined(_WIN64) || defined(__MINGW64__) +#define __SUP_WINDOWS__ 1 +#endif + +#if defined(__SUP_WINDOWS__) +#include #include #define access _access #define R_OK 4 /* Test for read permission. */ @@ -21,6 +26,8 @@ #define S_ISREG(m) (((m)&_S_IFMT) == _S_IFREG) #define S_ISDIR(m) (((m)&_S_IFMT) == _S_IFDIR) #endif +#else +#include #endif #include @@ -108,7 +115,7 @@ bool FileInfo::is_dir() const //: Returns TRUE if we are pointing to a symbolic link bool FileInfo::is_symlink() const { -#if !defined(_WIN64) && !defined(WIN32) && !defined(_WINDOWS) && !defined(_MSC_VER) +#if !defined(__SUP_WINDOWS__) struct stat s { }; @@ -241,7 +248,7 @@ std::string FileInfo::basename() const std::string FileInfo::realpath() const { -#if defined(_WIN64) || defined(WIN32) || defined(_WINDOWS) || defined(_MSC_VER) +#if defined(__SUP_WINDOWS__) char *path = _fullpath(nullptr, filename_.c_str(), _MAX_PATH); #else char *path = ::realpath(filename_.c_str(), nullptr); diff --git a/packages/seacas/libraries/suplib_cpp/hwm.C b/packages/seacas/libraries/suplib_cpp/hwm.C index 568025ce8fa4..8f0dde6c993d 100644 --- a/packages/seacas/libraries/suplib_cpp/hwm.C +++ b/packages/seacas/libraries/suplib_cpp/hwm.C @@ -1,5 +1,10 @@ // For memory utilities... -#if defined(_WIN32) +#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || \ + defined(__MINGW32__) || defined(_WIN64) || defined(__MINGW64__) +#define __SUP_WINDOWS__ 1 +#endif + +#if defined(__SUP_WINDOWS__) #define WIN32_LEAN_AND_MEAN #define NOMINMAX #if 0 @@ -34,7 +39,7 @@ size_t get_hwm_memory_info() { // Code from http://nadeausoftware.com/sites/NadeauSoftware.com/files/getRSS.c size_t memory_usage = 0; -#if defined(_WIN32) +#if defined(__SUP_WINDOWS__) #if 0 /* Windows -------------------------------------------------- */ PROCESS_MEMORY_COUNTERS info; diff --git a/packages/seacas/scripts/pconjoin.in b/packages/seacas/scripts/pconjoin.in index 169f5eea667e..afd5e956b7a9 100644 --- a/packages/seacas/scripts/pconjoin.in +++ b/packages/seacas/scripts/pconjoin.in @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright(C) 1999-2020 National Technology & Engineering Solutions +# Copyright(C) 1999-2021 National Technology & Engineering Solutions # of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with # NTESS, the U.S. Government retains certain rights in this software. # @@ -8,8 +8,8 @@ ######################################################################## function usage { cat < --basename -- ...normal conjoin options... - conjoinp --auto -- ...normal conjoin options... +Usage: pconjoin --proc_count --basename -- ...normal conjoin options... + pconjoin --auto -- ...normal conjoin options... Given a set of decomposed files with multiple topology changes (e.g., there are 'results.e-s????.42.{0..41}' variants of the files) @@ -20,10 +20,10 @@ Usage: conjoinp --proc_count --basename -- ...normal co without the '-s000?' portion (file.e.42.21) NOTE: Any "normal conjoin options" must be separated by a '--' - or they will be treated as options to conjoinp and probably + or they will be treated as options to pconjoin and probably ignored. - ->->-> Send email to gdsjaar@sandia.gov for conjoinp support.<-<-<- + ->->-> Send email to gdsjaar@sandia.gov for pconjoin support.<-<-<- Uses: GNU Parallel, O. Tange (2018): GNU Parallel 2018, Mar 2018, ISBN 9781387509881, @@ -86,7 +86,7 @@ GETOPT=${ACCESS_BIN}/getopt.seacas TEMP=`${GETOPT} -o hp:n:f:a: -a \ --long help,proc_count:,basename:,auto: \ - -n 'conjoinp' -- "$@"` + -n 'pconjoin' -- "$@"` # Note the quotes around `$TEMP': they are essential! eval set -- "$TEMP" @@ -118,5 +118,5 @@ then echo "${txtred}ERROR During conjoin execution. Check error output above and rerun${txtrst}" exit 1 else - echo "${txtgrn}...conjoinp successful execution${txtrst}" + echo "${txtgrn}...pconjoin successful execution${txtrst}" fi