From ecbcd45ab2cfe614d155707892869e03ecfb264e Mon Sep 17 00:00:00 2001 From: Nicolas Cornu Date: Thu, 12 Sep 2024 14:55:11 +0200 Subject: [PATCH] Use fmt as backend for Printf/Fprintf (#3074) * Move Fprintf and Printf in utils/logger.hpp * Make sections.c a c++ file * Remove nrnpy_pr for only Printf (same function) * Use fmt::ptr everywhere this is needed --- src/ivoc/ivocmain.cpp | 2 +- src/ivoc/ivocvect.cpp | 2 + src/ivoc/matrix.cpp | 2 + src/ivoc/strfun.cpp | 2 +- src/neuron/container/soa_identifier.hpp | 2 +- src/nrncvode/cvodeobj.cpp | 14 ++-- src/nrncvode/netcvode.cpp | 13 ++-- src/nrncvode/tqueue.cpp | 7 +- src/nrniv/multisplit.cpp | 13 ++-- .../callbacks/nrncore_callbacks.cpp | 1 - src/nrnmpi/memory_usage.cpp | 3 +- src/nrnmpi/nrnmpi_dynam.cpp | 3 +- src/nrnpython/nrnpy_hoc.cpp | 4 +- src/oc/axis.cpp | 2 + src/oc/code.cpp | 4 +- src/oc/code2.cpp | 2 + src/oc/debug.cpp | 4 +- src/oc/fileio.cpp | 74 +------------------ src/oc/hoc.cpp | 2 +- src/oc/hocdec.h | 2 - src/oc/oc_ansi.h | 2 - src/oc/parse.ypp | 2 + src/oc/plot.cpp | 4 +- src/oc/symbol.cpp | 4 +- src/parallel/bbssrv2mpi.cpp | 2 + src/utils/logger.hpp | 25 +++++++ test/api/CMakeLists.txt | 2 +- test/api/{sections.c => sections.cpp} | 2 +- 28 files changed, 89 insertions(+), 112 deletions(-) create mode 100644 src/utils/logger.hpp rename test/api/{sections.c => sections.cpp} (98%) diff --git a/src/ivoc/ivocmain.cpp b/src/ivoc/ivocmain.cpp index 3c57815cd5..226b37cf11 100644 --- a/src/ivoc/ivocmain.cpp +++ b/src/ivoc/ivocmain.cpp @@ -42,7 +42,7 @@ void iv_display_scale(float); #include #endif -#include +#include "utils/logger.hpp" #if 1 void pr_profile(); diff --git a/src/ivoc/ivocvect.cpp b/src/ivoc/ivocvect.cpp index a938593d06..1ffb1eba95 100644 --- a/src/ivoc/ivocvect.cpp +++ b/src/ivoc/ivocvect.cpp @@ -36,6 +36,8 @@ #include "gui-redirect.h" +#include "utils/logger.hpp" + #ifndef PI #ifndef M_PI #define M_PI 3.14159265358979323846 diff --git a/src/ivoc/matrix.cpp b/src/ivoc/matrix.cpp index 3c66406403..90b0aeef1e 100644 --- a/src/ivoc/matrix.cpp +++ b/src/ivoc/matrix.cpp @@ -8,6 +8,8 @@ #include "parse.hpp" #include "ivocvect.h" +#include "utils/logger.hpp" + #define EPS hoc_epsilon Symbol* nrn_matrix_sym; // also used in oc/hoc_oop.cpp diff --git a/src/ivoc/strfun.cpp b/src/ivoc/strfun.cpp index 91114a9aef..21b78dee78 100644 --- a/src/ivoc/strfun.cpp +++ b/src/ivoc/strfun.cpp @@ -15,7 +15,7 @@ #include #endif -#include +#include "utils/logger.hpp" extern Objectdata* hoc_top_level_data; extern Symlist* hoc_built_in_symlist; diff --git a/src/neuron/container/soa_identifier.hpp b/src/neuron/container/soa_identifier.hpp index 8a1f7331e2..6b8ed98d42 100644 --- a/src/neuron/container/soa_identifier.hpp +++ b/src/neuron/container/soa_identifier.hpp @@ -11,7 +11,7 @@ #include #include -#include +#include "utils/logger.hpp" #include "hocdec.h" diff --git a/src/nrncvode/cvodeobj.cpp b/src/nrncvode/cvodeobj.cpp index e99619d7fb..5c662ec4b7 100644 --- a/src/nrncvode/cvodeobj.cpp +++ b/src/nrncvode/cvodeobj.cpp @@ -1066,7 +1066,7 @@ int Cvode::cvode_init(double) { // printf("CVodeReInit\n"); if (err != SUCCESS) { Printf("Cvode %p %s CVReInit error %d\n", - this, + fmt::ptr(this), secname(ctd_[0].v_node_[ctd_[0].rootnodecount_]->sec), err); return err; @@ -1082,7 +1082,7 @@ int Cvode::cvode_init(double) { CVodeMalloc(mem_, pf_, t0_, y_, CV_SV, &ncv_->rtol_, atolnvec_); if (err != SUCCESS) { Printf("Cvode %p %s CVodeMalloc error %d\n", - this, + fmt::ptr(this), secname(ctd_[0].v_node_[ctd_[0].rootnodecount_]->sec), err); return err; @@ -1302,7 +1302,7 @@ int Cvode::cvode_advance_tn(neuron::model_sorted_token const& sorted_token) { #if PRINT_EVENT if (net_cvode_instance->print_event_ > 1) { Printf("Cvode::cvode_advance_tn %p %d initialize_=%d tstop=%.20g t_=%.20g to ", - this, + fmt::ptr(this), nth_ ? nth_->id : 0, initialize_, tstop_, @@ -1322,7 +1322,7 @@ int Cvode::cvode_advance_tn(neuron::model_sorted_token const& sorted_token) { #endif if (err < 0) { Printf("CVode %p %s advance_tn failed, err=%d.\n", - this, + fmt::ptr(this), secname(ctd_[0].v_node_[ctd_[0].rootnodecount_]->sec), err); pf_(t_, y_, nullptr, &opaque); @@ -1344,7 +1344,7 @@ int Cvode::cvode_interpolate(double tout) { #if PRINT_EVENT if (net_cvode_instance->print_event_ > 1) { Printf("Cvode::cvode_interpolate %p %d initialize_%d t=%.20g to ", - this, + fmt::ptr(this), nth_ ? nth_->id : 0, initialize_, t_); @@ -1365,7 +1365,7 @@ int Cvode::cvode_interpolate(double tout) { #endif if (err < 0) { Printf("CVode %p %s interpolate failed, err=%d.\n", - this, + fmt::ptr(this), secname(ctd_[0].v_node_[ctd_[0].rootnodecount_]->sec), err); return err; @@ -1409,7 +1409,7 @@ N_Vector Cvode::acorvec() { void Cvode::statistics() { #if 1 Printf("\nCvode instance %p %s statistics : %d %s states\n", - this, + fmt::ptr(this), secname(ctd_[0].v_node_[ctd_[0].rootnodecount_]->sec), neq_, (use_daspk_ ? "IDA" : "CVode")); diff --git a/src/nrncvode/netcvode.cpp b/src/nrncvode/netcvode.cpp index b0ad67a1a0..27d7e9bbf0 100644 --- a/src/nrncvode/netcvode.cpp +++ b/src/nrncvode/netcvode.cpp @@ -3493,7 +3493,7 @@ void NetCvode::local_retreat(double t, Cvode* cv) { if (print_event_) { Printf("microstep local retreat from %g (cvode_%p is at %g) for event onset=%g\n", cv->tqitem_->t_, - cv, + fmt::ptr(cv), cv->t_, t); } @@ -3502,7 +3502,10 @@ void NetCvode::local_retreat(double t, Cvode* cv) { tq->move(cv->tqitem_, t); #if PRINT_EVENT if (print_event_ > 1) { - Printf("after target solve time for %p is %g , dt=%g\n", cv, cv->time(), nt_dt); + Printf("after target solve time for %p is %g , dt=%g\n", + fmt::ptr(cv), + cv->time(), + nt_dt); } #endif } else { @@ -3519,7 +3522,7 @@ void NetCvode::retreat(double t, Cvode* cv) { if (print_event_) { Printf("microstep retreat from %g (cvode_%p is at %g) for event onset=%g\n", tq ? cv->tqitem_->t_ : cv->t_, - cv, + fmt::ptr(cv), cv->t_, t); } @@ -3530,7 +3533,7 @@ void NetCvode::retreat(double t, Cvode* cv) { } #if PRINT_EVENT if (print_event_ > 1) { - Printf("after target solve time for %p is %g , dt=%g\n", cv, cv->time(), dt); + Printf("after target solve time for %p is %g , dt=%g\n", fmt::ptr(cv), cv->time(), dt); } #endif } @@ -5577,7 +5580,7 @@ static int trajec_buffered(NrnThread& nt, if (err) { Fprintf(stderr, "Pointer %p of PlayRecord type %d ignored because not a Range Variable", - static_cast(pd), + fmt::ptr(static_cast(pd)), pr->type()); } } diff --git a/src/nrncvode/tqueue.cpp b/src/nrncvode/tqueue.cpp index 9010ae6c43..ffc7c8e2ef 100644 --- a/src/nrncvode/tqueue.cpp +++ b/src/nrncvode/tqueue.cpp @@ -48,7 +48,12 @@ static void prnt(const TQItem* b, int level) { for (i = 0; i < level; ++i) { Printf(" "); } - Printf("%g %c %d Q=%p D=%p\n", b->t_, b->data_ ? 'x' : 'o', b->cnt_, b, b->data_); + Printf("%g %c %d Q=%p D=%p\n", + b->t_, + b->data_ ? 'x' : 'o', + b->cnt_, + fmt::ptr(b), + fmt::ptr(b->data_)); } TQueue::TQueue(TQItemPool* tp, int mkmut) { diff --git a/src/nrniv/multisplit.cpp b/src/nrniv/multisplit.cpp index f37e9ac2fe..f9b9531d78 100644 --- a/src/nrniv/multisplit.cpp +++ b/src/nrniv/multisplit.cpp @@ -1872,20 +1872,23 @@ void MultiSplitControl::prstruct() { m.tag_); if (m.nnode_) { Printf(" nodeindex=%p nodeindex_buffer = %p\n", - m.nodeindex_, - nodeindex_buffer_); + fmt::ptr(m.nodeindex_), + fmt::ptr(nodeindex_buffer_)); } } Printf(" ndbsize=%d i nodeindex_buffer_=%p nodeindex_rthost_=%p\n", ndbsize, - nodeindex_buffer_, - nodeindex_rthost_); + fmt::ptr(nodeindex_buffer_), + fmt::ptr(nodeindex_rthost_)); if (ndbsize) { for (int i = 0; i < ndbsize; ++i) { Printf(" %d %d %d\n", i, nodeindex_buffer_[i], nodeindex_rthost_[i]); } } - Printf(" tbsize=%d trecvbuf_=%p tsendbuf_=%p\n", tbsize, trecvbuf_, tsendbuf_); + Printf(" tbsize=%d trecvbuf_=%p tsendbuf_=%p\n", + tbsize, + fmt::ptr(trecvbuf_), + fmt::ptr(tsendbuf_)); Printf("\n"); } } diff --git a/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.cpp b/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.cpp index 62bb7f1a14..158ae0c028 100644 --- a/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.cpp +++ b/src/nrniv/nrncore_write/callbacks/nrncore_callbacks.cpp @@ -1018,7 +1018,6 @@ static void set_info(TQItem* tqi, Fprintf(stderr, "WARNING: CVode.event(...) for delivery at time step nearest %g discarded. " "CoreNEURON cannot presently handle interpreter events (rank %d, thread %d).\n", - nrnmpi_myid, tdeliver, nrnmpi_myid, tid); diff --git a/src/nrnmpi/memory_usage.cpp b/src/nrnmpi/memory_usage.cpp index 42c4479305..084a572939 100644 --- a/src/nrnmpi/memory_usage.cpp +++ b/src/nrnmpi/memory_usage.cpp @@ -14,8 +14,7 @@ #include -#include "hocdec.h" -#include +#include "utils/logger.hpp" #include "neuron/container/memory_usage.hpp" diff --git a/src/nrnmpi/nrnmpi_dynam.cpp b/src/nrnmpi/nrnmpi_dynam.cpp index 56da507e88..0f8eb4d8f0 100644 --- a/src/nrnmpi/nrnmpi_dynam.cpp +++ b/src/nrnmpi/nrnmpi_dynam.cpp @@ -17,8 +17,7 @@ #include "nrnmpi.h" -#include "hocdec.h" -#include +#include "utils/logger.hpp" extern char* cxx_char_alloc(size_t); extern std::string corenrn_mpi_library; diff --git a/src/nrnpython/nrnpy_hoc.cpp b/src/nrnpython/nrnpy_hoc.cpp index 4950c35c7b..d81ddbe05f 100644 --- a/src/nrnpython/nrnpy_hoc.cpp +++ b/src/nrnpython/nrnpy_hoc.cpp @@ -381,7 +381,7 @@ int hocobj_pushargs(PyObject* args, std::vector& s2free) { Py2NRNString str(po, /* disable_release */ true); if (str.err()) { // Since Python error has been set, need to clear, or hoc_execerror - // printing with nrnpy_pr will generate a + // printing with Printf will generate a // Exception ignored on calling ctypes callback function. // So get the message, clear, and make the message // part of the execerror. @@ -399,7 +399,7 @@ int hocobj_pushargs(PyObject* args, std::vector& s2free) { // the object which can raise an error for nrn.Section, nrn.Segment, // etc. if the internal Section is invalid (Section.prop == NULL). // That, in consequence, will generate an - // Exception ignored on calling ctypes callback function: #include "gui-redirect.h" +#include "utils/logger.hpp" + #define CLIP 1e9 #define XS 500. #define YS 400. diff --git a/src/oc/code.cpp b/src/oc/code.cpp index 05c157b61d..d112fb7bb3 100644 --- a/src/oc/code.cpp +++ b/src/oc/code.cpp @@ -2371,9 +2371,9 @@ int hoc_araypt(Symbol* sp, int type) { // pop top value from stack, print it void hoc_print() { - nrnpy_pr("\t"); + Printf("\t"); hoc_prexpr(); - nrnpy_pr("\n"); + Printf("\n"); } // print numeric value diff --git a/src/oc/code2.cpp b/src/oc/code2.cpp index 7f158c6910..679c396cdb 100644 --- a/src/oc/code2.cpp +++ b/src/oc/code2.cpp @@ -14,6 +14,8 @@ #include "nrnfilewrap.h" #include +#include "utils/logger.hpp" + int units_on_flag_; diff --git a/src/oc/debug.cpp b/src/oc/debug.cpp index 81cf005677..2f8aeb5626 100644 --- a/src/oc/debug.cpp +++ b/src/oc/debug.cpp @@ -5,9 +5,11 @@ #include "equation.h" #include +#include "utils/logger.hpp" + int hoc_zzdebug; -#define prcod(c1, c2) else if (p->pf == c1) Printf("%p %p %s", p, p->pf, c2) +#define prcod(c1, c2) else if (p->pf == c1) Printf("%p %p %s", fmt::ptr(p), fmt::ptr(p->pf), c2) void hoc_debug(void) /* print the machine */ { diff --git a/src/oc/fileio.cpp b/src/oc/fileio.cpp index e577129480..140b53eed0 100644 --- a/src/oc/fileio.cpp +++ b/src/oc/fileio.cpp @@ -15,7 +15,6 @@ #include #include "nrnfilewrap.h" - extern char* neuron_home; NrnFILEWrap* hoc_frin; @@ -751,7 +750,7 @@ void hoc_Chdir(void) { } int nrn_is_python_extension; -static int (*nrnpy_pr_stdoe_callback)(int, char*); +int (*nrnpy_pr_stdoe_callback)(int, char*); static int (*nrnpy_pass_callback)(); extern "C" void nrnpy_set_pr_etal(int (*cbpr_stdoe)(int, char*), int (*cbpass)()) { @@ -762,78 +761,9 @@ extern "C" void nrnpy_set_pr_etal(int (*cbpr_stdoe)(int, char*), int (*cbpass)() void nrnpy_pass() { if (nrnpy_pass_callback) { if ((*nrnpy_pass_callback)() != 1) { - hoc_execerror("nrnpy_pass", 0); - } - } -} - -static int vnrnpy_pr_stdoe(FILE* stream, const char* fmt, va_list ap) { - int size = 0; - char* p = NULL; - - if (!nrnpy_pr_stdoe_callback || (stream != stderr && stream != stdout)) { - size = vfprintf(stream, fmt, ap); - return size; - } - - /* Determine required size */ - va_list apc; -#ifndef va_copy -#if defined(__GNUC__) || defined(__clang__) -#define va_copy(dest, src) __builtin_va_copy(dest, src) -#else -#define va_copy(dest, src) (dest = src) -#endif -#endif - va_copy(apc, ap); - size = vsnprintf(p, size, fmt, apc); - va_end(apc); - - if (size < 0) - return 0; - - size++; /* For '\0' */ - p = static_cast(malloc(size)); - if (p == NULL) - return 0; - - size = vsnprintf(p, size, fmt, ap); - if (size < 0) { - free(p); - return 0; - } - - // if any non-ascii translate to '?' or nrnpy_pr will raise an exception. - if (stream == stderr) { - for (int i = 0; p[i] != '\0'; ++i) { - if (!isascii((unsigned char) p[i])) { - p[i] = '?'; - } + hoc_execerror("nrnpy_pass", nullptr); } } - - (*nrnpy_pr_stdoe_callback)((stream == stderr) ? 2 : 1, p); - - free(p); - return size; -} - -int nrnpy_pr(const char* fmt, ...) { - int n; - va_list ap; - va_start(ap, fmt); - n = vnrnpy_pr_stdoe(stdout, fmt, ap); - va_end(ap); - return n; -} - -int Fprintf(FILE* stream, const char* fmt, ...) { - int n; - va_list ap; - va_start(ap, fmt); - n = vnrnpy_pr_stdoe(stream, fmt, ap); - va_end(ap); - return n; } /** printf style specification of hoc_execerror message. (512 char limit) **/ diff --git a/src/oc/hoc.cpp b/src/oc/hoc.cpp index 615ee6711e..fee82add88 100644 --- a/src/oc/hoc.cpp +++ b/src/oc/hoc.cpp @@ -32,7 +32,7 @@ #include #include -#include +#include "utils/logger.hpp" /* for eliminating "ignoreing return value" warnings. */ int nrnignore; diff --git a/src/oc/hocdec.h b/src/oc/hocdec.h index a8f5b31826..eb328950f0 100644 --- a/src/oc/hocdec.h +++ b/src/oc/hocdec.h @@ -263,7 +263,6 @@ int ilint; #define Strncat cplint = strncat #define Strcpy cplint = strcpy #define Strncpy cplint = strncpy -#define Printf ilint = printf #else #undef IGNORE #define IGNORE(arg) arg @@ -272,7 +271,6 @@ int ilint; #define Strncat strncat #define Strcpy strcpy #define Strncpy strncpy -#define Printf nrnpy_pr #endif using neuron::Sprintf; diff --git a/src/oc/oc_ansi.h b/src/oc/oc_ansi.h index 0279449376..0b95fc8732 100644 --- a/src/oc/oc_ansi.h +++ b/src/oc/oc_ansi.h @@ -419,8 +419,6 @@ int hoc_pid(); int hoc_ired(const char*, int, int, int); double hoc_xred(const char*, double, double, double); int hoc_sred(const char*, char*, char*); -int nrnpy_pr(const char* fmt, ...); -int Fprintf(std::FILE*, const char* fmt, ...); void nrnpy_pass(); void hoc_free_allobjects(cTemplate*, Symlist*, Objectdata*); int nrn_is_cable(); diff --git a/src/oc/parse.ypp b/src/oc/parse.ypp index 715715f58d..9a6a8a6d36 100755 --- a/src/oc/parse.ypp +++ b/src/oc/parse.ypp @@ -17,6 +17,8 @@ struct Symbol; #include "equation.h" #include "nrnfilewrap.h" +#include "utils/logger.hpp" + void* nrn_parsing_pysec_; #if LINT diff --git a/src/oc/plot.cpp b/src/oc/plot.cpp index a0bffdcec6..8ded28119a 100644 --- a/src/oc/plot.cpp +++ b/src/oc/plot.cpp @@ -3,6 +3,8 @@ #include "hocdec.h" #include "oc_ansi.h" +#include "utils/logger.hpp" + /*LINTLIBRARY*/ #undef IGNORE #if LINT @@ -114,7 +116,7 @@ void hoc_plprint(const char* s) { #endif } else if (!text) { - nrnpy_pr("%s", s); + Printf("%s", s); } if (hardplot && hpdev && text && strlen(s)) { hard_text_preamble(); diff --git a/src/oc/symbol.cpp b/src/oc/symbol.cpp index 5c68322626..e606dc6cb0 100644 --- a/src/oc/symbol.cpp +++ b/src/oc/symbol.cpp @@ -23,6 +23,8 @@ #include #endif +#include "utils/logger.hpp" + Symlist* hoc_built_in_symlist = nullptr; /* keywords, built-in functions, all name linked into hoc. Look in this list last */ Symlist* hoc_top_level_symlist = nullptr; /* all user names seen at top-level @@ -39,7 +41,7 @@ void print_symlist(const char* s, Symlist* tab) { Printf("%s\n", s); if (tab) for (Symbol* sp = tab->first; sp != nullptr; sp = sp->next) { - Printf("%s %p\n", sp->name, sp); + Printf("%s %p\n", sp->name, fmt::ptr(sp)); } } diff --git a/src/parallel/bbssrv2mpi.cpp b/src/parallel/bbssrv2mpi.cpp index 3da195fac7..1d2d4b6822 100644 --- a/src/parallel/bbssrv2mpi.cpp +++ b/src/parallel/bbssrv2mpi.cpp @@ -9,6 +9,8 @@ #include "bbsimpl.h" #include "hocdec.h" //Printf +#include "utils/logger.hpp" + void nrnbbs_context_wait(); BBSDirectServer* BBSDirectServer::server_; diff --git a/src/utils/logger.hpp b/src/utils/logger.hpp new file mode 100644 index 0000000000..9a10e182c6 --- /dev/null +++ b/src/utils/logger.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include + +extern int (*nrnpy_pr_stdoe_callback)(int, char*); + +template +int Fprintf(FILE* stream, const char* fmt, Args... args) { + if (nrnpy_pr_stdoe_callback && (stream == stdout || stream == stderr)) { + std::string message = fmt::sprintf(fmt, std::forward(args)...); + nrnpy_pr_stdoe_callback(stream == stdout ? 1 : 2, message.data()); + return message.size(); + } + return fmt::fprintf(stream, fmt, args...); +} + +template +int Printf(const char* fmt, Args... args) { + if (nrnpy_pr_stdoe_callback) { + std::string message = fmt::sprintf(fmt, std::forward(args)...); + nrnpy_pr_stdoe_callback(1, message.data()); + return message.size(); + } + return fmt::printf(fmt, args...); +} diff --git a/test/api/CMakeLists.txt b/test/api/CMakeLists.txt index 2ebc7d9105..52ffa5be18 100644 --- a/test/api/CMakeLists.txt +++ b/test/api/CMakeLists.txt @@ -1,4 +1,4 @@ -foreach(api_test_file hh_sim.cpp netcon.cpp sections.c vclamp.cpp) +foreach(api_test_file hh_sim.cpp netcon.cpp sections.cpp vclamp.cpp) string(REPLACE "." "_" api_test_name "${api_test_file}") add_executable(${api_test_name} ${api_test_file}) cpp_cc_configure_sanitizers(TARGET ${api_test_name}) diff --git a/test/api/sections.c b/test/api/sections.cpp similarity index 98% rename from test/api/sections.c rename to test/api/sections.cpp index 1571bbcc6c..fbf1c4e3e8 100644 --- a/test/api/sections.c +++ b/test/api/sections.cpp @@ -5,7 +5,7 @@ #include #include -void modl_reg(){}; +extern "C" void modl_reg(){}; int main(void) { static const char* argv[] = {"sections", "-nogui", "-nopython", NULL};