From 3a258ce3f5159f388f6699555a9246eb82cdb01c Mon Sep 17 00:00:00 2001 From: Greg Sjaardema Date: Mon, 19 Jun 2023 08:45:55 -0600 Subject: [PATCH] APREPRO: Add option to output floating point data at full precision Add optional support (enabled if the lib::fmt library is linked in) for printing floating point data using the number of digits required for full precision of the value. The output for {1/4} would be '0.25' The output for {1/3} would be '1.333333..' with enough '3' to fully represent the value. Another way of describing is that if VAL is the internal value of an aprepro variable, then printing VAL and then assigning the variable to VALs printed output would result in no change. This behavior can either be enabled using the `--full_precision` or `-p` option, or by setting the value of the aprepro varible `_FORMAT` to the empty string: {_FORMAT=""} Since this capability is only enabled if the optional lib::fmt library is linked to aprepro, a warning/informational/error message is printed if you try to use the option when it is not supported. --- .../libraries/aprepro_lib/CMakeLists.txt | 4 + .../libraries/aprepro_lib/apr_aprepro.cc | 14 +- .../libraries/aprepro_lib/apr_parser.cc | 21 ++- .../seacas/libraries/aprepro_lib/aprepro.yy | 140 +----------------- .../aprepro_lib/cmake/Dependencies.cmake | 1 + 5 files changed, 40 insertions(+), 140 deletions(-) diff --git a/packages/seacas/libraries/aprepro_lib/CMakeLists.txt b/packages/seacas/libraries/aprepro_lib/CMakeLists.txt index c8d119847d..b34a01963a 100644 --- a/packages/seacas/libraries/aprepro_lib/CMakeLists.txt +++ b/packages/seacas/libraries/aprepro_lib/CMakeLists.txt @@ -15,6 +15,10 @@ IF (${CMAKE_PROJECT_NAME}_ENABLE_SEACASExodus) ADD_DEFINITIONS(-DEXODUS_SUPPORT) ENDIF() +IF (${TPL_ENABLE_fmt}) + ADD_DEFINITIONS(-DFMT_SUPPORT) +ENDIF() + TRIBITS_INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR} ) diff --git a/packages/seacas/libraries/aprepro_lib/apr_aprepro.cc b/packages/seacas/libraries/aprepro_lib/apr_aprepro.cc index 23e02f339a..d501d89017 100644 --- a/packages/seacas/libraries/aprepro_lib/apr_aprepro.cc +++ b/packages/seacas/libraries/aprepro_lib/apr_aprepro.cc @@ -32,7 +32,7 @@ #endif namespace { - const std::string version_string{"6.12 (2023/05/03)"}; + const std::string version_string{"6.13 (2023/06/19)"}; void output_copyright(); @@ -541,6 +541,12 @@ namespace SEAMS { ptr->value.svar = comment; } } + else if (option.find("--full_precision") != std::string::npos || (option[1] == 'p')) { + symrec *ptr = getsym("_FORMAT"); + if (ptr != nullptr) { + ptr->value.svar = ""; + } + } else if (option == "--help" || option == "-h") { std::cerr @@ -569,6 +575,12 @@ namespace SEAMS { << " --info=file: Output INFO messages (e.g. DUMP() output) to file.\n" << " --nowarning or -W: Do not print WARN messages \n" << " --comment=char or -c=char: Change comment character to 'char' \n" +#if defined(FMT_SUPPORT) + << " --full_precision -p: Floating point output uses as many digits as needed.\n" +#else + << " --full_precision -p: (Not supported in this build) Floating point output uses as " + "many digits as needed.\n" +#endif << " --copyright or -C: Print copyright message \n" << " --keep_history or -k: Keep a history of aprepro substitutions.\n" << " (not for general interactive use) \n" diff --git a/packages/seacas/libraries/aprepro_lib/apr_parser.cc b/packages/seacas/libraries/aprepro_lib/apr_parser.cc index 39705890c9..86bb231ec3 100644 --- a/packages/seacas/libraries/aprepro_lib/apr_parser.cc +++ b/packages/seacas/libraries/aprepro_lib/apr_parser.cc @@ -44,6 +44,9 @@ #include "apr_util.h" #include "aprepro.h" +#if defined FMT_SUPPORT +#include +#endif #include #include #include @@ -529,10 +532,22 @@ namespace SEAMS { #line 130 "/Users/gdsjaar/src/seacas/packages/seacas/libraries/aprepro_lib/aprepro.yy" { if (echo) { - static char tmpstr[512]; SEAMS::symrec *format = aprepro.getsym("_FORMAT"); - int len = snprintf(tmpstr, 512, format->value.svar.c_str(), (yystack_[1].value.val)); - aprepro.lexer->LexerOutput(tmpstr, len); + if (format->value.svar.empty()) { +#if defined FMT_SUPPORT + auto tmpstr = fmt::format("{}", (yystack_[1].value.val)); + aprepro.lexer->LexerOutput(tmpstr.c_str(), tmpstr.size()); +#else + yyerror(aprepro, "Empty _FORMAT string -- no output will be printed. Optional " + "Lib::FMT dependency is not enabled."); +#endif + } + else { + static char tmpstr[512]; + int len = + snprintf(tmpstr, 512, format->value.svar.c_str(), (yystack_[1].value.val)); + aprepro.lexer->LexerOutput(tmpstr, len); + } } } #line 644 "apr_parser.cc" diff --git a/packages/seacas/libraries/aprepro_lib/aprepro.yy b/packages/seacas/libraries/aprepro_lib/aprepro.yy index 5adb46d60c..54d88db283 100644 --- a/packages/seacas/libraries/aprepro_lib/aprepro.yy +++ b/packages/seacas/libraries/aprepro_lib/aprepro.yy @@ -1,138 +1,6 @@ -// Copyright(C) 1999-2023 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 -%{ -#include "aprepro.h" -#include "apr_util.h" -#include "apr_array.h" - -#include -#include -#include -#include -#include -#include -#include - -namespace { - void reset_error() - { -#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 - - if (math_errhandling & MATH_ERREXCEPT) { - std::feclearexcept(FE_ALL_EXCEPT); - } - if (math_errhandling & MATH_ERRNO) { - errno = 0; - } -#endif - } -} - -namespace SEAMS { - extern bool echo; - } - - %} - -%require "3.2" - -/* add debug output code to generated parser. disable this for release - * versions. */ -%debug - -/* write out a header file containing the token defines */ -%defines - -/* use newer C++ skeleton file */ -%skeleton "lalr1.cc" - -/* namespace to enclose parser in */ -%define api.prefix {SEAMS} - -/* set the parser's class identifier */ -%define api.parser.class {Parser} - -%define parse.error verbose - -/* aprepro is passed by reference to the parser and to the scanner. This - * provides a simple but effective pure interface, not relying on global - * variables. */ -%parse-param { class Aprepro& aprepro } - -%union { - double val; /* For returning numbers. */ - struct symrec *tptr; /* For returning symbol-table pointers */ - char *string; /* For returning quoted strings */ - struct array *arrval; /* For returning arrays */ -} - -%token NUM /* Simple double precision number */ -%token QSTRING /* Quoted string */ -%token UNDVAR /* Variable and function */ -%token VAR -%token SVAR /* String Variable */ -%token IMMVAR /* Immutable Variable */ -%token IMMSVAR /* Immutable String Variable */ -%token AVAR /* array data [i,j] */ -%token FNCT -%token SFNCT -%token AFNCT -%type exp -%type aexp -%type bool -%type sexp - -%token END 0 "end of file" -%token COMMA LPAR RPAR LBRACK RBRACK LBRACE RBRACE SEMI -/* Precedence (Lowest to Highest) and associativity */ -%right EQUAL -%right EQ_PLUS EQ_MINUS -%right EQ_TIME EQ_DIV -%right EQ_POW -%right QUEST COLON -%left LOR /* Logical OR */ -%left LAND /* Logical AND */ -%left LT GT LE GE EQ NE /* <=, >=, ==, != */ -%left PLU SUB -%left DIV TIM MOD -%left UNARY NOT /* Negation--unary minus/plus */ -%right POW /* Exponentiation */ -%left INC DEC /* increment (++), decrement (--) */ -%left CONCAT /* Concatenate Strings */ - -%{ - -#include "aprepro.h" -#include "apr_scanner.h" - -/* this "connects" the bison parser in aprepro to the flex scanner class - * object. it defines the yylex() function call to pull the next token from the - * current lexer object of the aprepro context. */ -#undef yylex -#define yylex aprepro.lexer->lex - -%} - -/* Grammar Rules: */ -%% -input: /* empty rule */ - | input line -; - -line: '\n' { if (echo) aprepro.lexer->LexerOutput("\n", 1); } - | LBRACE exp RBRACE { if (echo) { - static char tmpstr[512]; - SEAMS::symrec *format = aprepro.getsym("_FORMAT"); - int len = snprintf(tmpstr, 512, format->value.svar.c_str(), $2); - aprepro.lexer->LexerOutput(tmpstr, len); - } + aprepro.lexer->LexerOutput(tmpstr, len); + } + } } | LBRACE sexp RBRACE { if (echo && $2 != NULL) { aprepro.lexer->LexerOutput($2, strlen($2)); @@ -345,7 +213,7 @@ exp: NUM { $$ = $1; } redefined_warning(aprepro, $1); set_type(aprepro, $1, token::VAR); } | AVAR EQUAL exp { $$ = $3; - aprepro.redefine_array($1->value.avar); + aprepro.redefine_array($1->value.avar); $1->value.var= $3; redefined_warning(aprepro, $1); set_type(aprepro, $1, token::VAR); } diff --git a/packages/seacas/libraries/aprepro_lib/cmake/Dependencies.cmake b/packages/seacas/libraries/aprepro_lib/cmake/Dependencies.cmake index 6cbd978ae2..b525232878 100644 --- a/packages/seacas/libraries/aprepro_lib/cmake/Dependencies.cmake +++ b/packages/seacas/libraries/aprepro_lib/cmake/Dependencies.cmake @@ -1,4 +1,5 @@ TRIBITS_PACKAGE_DEFINE_DEPENDENCIES( LIB_OPTIONAL_PACKAGES SEACASExodus + LIB_OPTIONAL_TPLS fmt TEST_OPTIONAL_TPLS Pthread )