LCOV - code coverage report
Current view: top level - tools - Exception.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 48 51 94.1 %
Date: 2024-10-18 14:00:25 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2012-2023 The plumed team
       3             :    (see the PEOPLE file at the root of the distribution for a list of names)
       4             : 
       5             :    See http://www.plumed.org for more information.
       6             : 
       7             :    This file is part of plumed, version 2.
       8             : 
       9             :    plumed is free software: you can redistribute it and/or modify
      10             :    it under the terms of the GNU Lesser General Public License as published by
      11             :    the Free Software Foundation, either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    plumed is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU Lesser General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU Lesser General Public License
      20             :    along with plumed.  If not, see <http://www.gnu.org/licenses/>.
      21             : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
      22             : #include "Exception.h"
      23             : 
      24             : #if defined(__PLUMED_HAS_EXECINFO)
      25             : #include <execinfo.h>
      26             : #endif
      27             : 
      28             : #include <cstdio>
      29             : #include <cstring>
      30             : #include <cstdlib>
      31             : #include <vector>
      32             : 
      33             : namespace PLMD {
      34             : 
      35             : namespace {
      36             : // see https://www.geeksforgeeks.org/simplify-directory-path-unix-like/
      37             : 
      38             : // function to simplify a Unix - styled
      39             : // absolute path
      40          55 : std::string simplify(const std::string & path)
      41             : {
      42             :   // using vector in place of stack
      43             :   std::vector<std::string> v;
      44          55 :   int n = path.length();
      45             :   std::string ans;
      46         179 :   for (int i = 0; i < n; i++) {
      47         124 :     std::string dir = "";
      48             :     // forming the current directory.
      49        1095 :     while (i < n && path[i] != '/') {
      50         971 :       dir += path[i];
      51         971 :       i++;
      52             :     }
      53             : 
      54             :     // if ".." , we pop.
      55         124 :     if (dir == "..") {
      56           4 :       if (!v.empty())
      57             :         v.pop_back();
      58             :     }
      59         240 :     else if (dir == "." || dir == "") {
      60             :       // do nothing (added for better understanding.)
      61             :     }
      62             :     else {
      63             :       // push the current directory into the vector.
      64         119 :       v.push_back(dir);
      65             :     }
      66             :   }
      67             : 
      68             :   // forming the ans
      69             :   bool first=true;
      70         170 :   for (const auto & i : v) {
      71         115 :     if(!first) ans += "/";
      72             :     first=false;
      73             :     ans += i;
      74             :   }
      75             : 
      76             :   // vector is empty
      77          55 :   if (ans == "")
      78           0 :     return "/";
      79             : 
      80             :   return ans;
      81          55 : }
      82             : 
      83             : }
      84             : 
      85         140 : Exception::Exception()
      86             : {
      87             :   callstack.fill(nullptr);
      88             : #ifdef __PLUMED_HAS_EXECINFO
      89         140 :   callstack_n = backtrace(&callstack[0], callstack.size()-1);
      90         140 :   const char* env=std::getenv("PLUMED_STACK_TRACE");
      91         140 :   if(env && !std::strcmp(env,"yes")) {
      92             :     msg+="\n\n********** STACK DUMP **********\n";
      93           4 :     msg+=stack();
      94             :     msg+="\n********** END STACK DUMP **********\n";
      95             :   }
      96             : #endif
      97         140 : }
      98             : 
      99         397 : Exception& Exception::operator<<(const std::string&msg)
     100             : {
     101         397 :   if(msg.length()>0) {
     102         397 :     if(note) this->msg +="\n";
     103         397 :     this->msg +=msg;
     104         397 :     note=false;
     105             :   }
     106         397 :   return *this;
     107             : }
     108             : 
     109          55 : Exception& Exception::operator<<(const Location&loc)
     110             : {
     111          55 :   if(loc.file) {
     112             :     const std::size_t clinelen=1000;
     113             :     char cline[clinelen];
     114          55 :     std::snprintf(cline,clinelen,"%u",loc.line);
     115          55 :     this->msg += "\n(";
     116             :     try {
     117         110 :       this->msg += simplify(loc.file);
     118           0 :     } catch(...) {
     119             :       // ignore
     120           0 :     }
     121             :     this->msg += ":";
     122             :     this->msg += cline;
     123             :     this->msg += ")";
     124          55 :     if(loc.pretty && loc.pretty[0]) {
     125             :       this->msg += " ";
     126          55 :       this->msg += loc.pretty;
     127             :     }
     128             :   }
     129          55 :   note=true;
     130          55 :   return *this;
     131             : }
     132             : 
     133          11 : Exception& Exception::operator<<(const Assertion&as)
     134             : {
     135          11 :   if(as.assertion) {
     136          11 :     this->msg += "\n+++ assertion failed: ";
     137          11 :     this->msg += as.assertion;
     138             :   }
     139          11 :   note=true;
     140          11 :   return *this;
     141             : }
     142             : 
     143           4 : const char* Exception::stack() const {
     144             : #ifdef __PLUMED_HAS_EXECINFO
     145           4 :   if(stackTrace.length()==0) {
     146           4 :     char** strs = backtrace_symbols(&callstack[0], callstack_n);
     147          39 :     for (int i = 0; i < callstack_n; ++i) {stackTrace+=strs[i]; stackTrace+="\n";}
     148           4 :     free(strs);
     149             :   }
     150             : #endif
     151           4 :   return stackTrace.c_str();
     152             : }
     153             : 
     154             : }
     155             : 
     156             : 

Generated by: LCOV version 1.16