Branch data Line data Source code
1 : : /****************************************************************************** 2 : : * Top contributors (to current version): 3 : : * Gereon Kremer, Morgan Deters, Tim King 4 : : * 5 : : * This file is part of the cvc5 project. 6 : : * 7 : : * Copyright (c) 2009-2024 by the authors listed in the file AUTHORS 8 : : * in the top-level source directory and their institutional affiliations. 9 : : * All rights reserved. See the file COPYING in the top-level source 10 : : * directory for licensing information. 11 : : * **************************************************************************** 12 : : * 13 : : * Wrappers to handle memory management of streams. 14 : : * 15 : : * This file contains wrappers to handle special cases of managing memory 16 : : * related to streams stored in options. 17 : : */ 18 : : 19 : : #include "options/managed_streams.h" 20 : : 21 : : #include <string.h> 22 : : 23 : : #include <cerrno> 24 : : #include <fstream> 25 : : #include <iostream> 26 : : #include <sstream> 27 : : 28 : : #include "options/option_exception.h" 29 : : 30 : : namespace cvc5::internal { 31 : : 32 : 374 : std::string cvc5_errno_failreason() 33 : : { 34 : : #if HAVE_STRERROR_R 35 : : #if STRERROR_R_CHAR_P 36 : : if (errno != 0) 37 : : { 38 : : // GNU version of strerror_r: *might* use the given buffer, 39 : : // or might not. It returns a pointer to buf, or not. 40 : : char buf[80]; 41 : : return std::string(strerror_r(errno, buf, sizeof buf)); 42 : : } 43 : : else 44 : : { 45 : : return "unknown reason"; 46 : : } 47 : : #else /* STRERROR_R_CHAR_P */ 48 : : if (errno != 0) 49 : : { 50 : : // XSI version of strerror_r: always uses the given buffer. 51 : : // Returns an error code. 52 : : char buf[80]; 53 : : if (strerror_r(errno, buf, sizeof buf) == 0) 54 : : { 55 : : return std::string(buf); 56 : : } 57 : : else 58 : : { 59 : : // some error occurred while getting the error string 60 : : return "unknown reason"; 61 : : } 62 : : } 63 : : else 64 : : { 65 : : return "unknown reason"; 66 : : } 67 : : #endif /* STRERROR_R_CHAR_P */ 68 : : #else /* HAVE_STRERROR_R */ 69 : 374 : return "unknown reason"; 70 : : #endif /* HAVE_STRERROR_R */ 71 : : } 72 : : 73 : : namespace detail { 74 : : 75 : 302 : std::unique_ptr<std::ostream> openOStream(const std::string& filename) 76 : : { 77 : 302 : errno = 0; 78 : 302 : std::unique_ptr<std::ostream> res = std::make_unique<std::ofstream>(filename); 79 [ + - ][ + - ]: 302 : if (!res || !*res) [ + - ] 80 : : { 81 : 604 : std::stringstream ss; 82 : 302 : ss << "Cannot open file: `" << filename << "': " << cvc5_errno_failreason(); 83 : 302 : throw OptionException(ss.str()); 84 : : } 85 : 0 : return res; 86 : : } 87 : 72 : std::unique_ptr<std::istream> openIStream(const std::string& filename) 88 : : { 89 : 72 : errno = 0; 90 : 72 : std::unique_ptr<std::istream> res = std::make_unique<std::ifstream>(filename); 91 [ + - ][ + - ]: 72 : if (!res || !*res) [ + - ] 92 : : { 93 : 144 : std::stringstream ss; 94 : 72 : ss << "Cannot open file: `" << filename << "': " << cvc5_errno_failreason(); 95 : 72 : throw OptionException(ss.str()); 96 : : } 97 : 0 : return res; 98 : : } 99 : : } // namespace detail 100 : : 101 : 133025 : ManagedErr::ManagedErr() : ManagedStream(&std::cerr, "stderr") {} 102 : 160 : bool ManagedErr::specialCases(const std::string& value) 103 : : { 104 [ + - ][ - + ]: 160 : if (value == "stderr" || value == "--") [ - + ] 105 : : { 106 : 0 : d_nonowned = &std::cerr; 107 : 0 : d_owned.reset(); 108 : 0 : d_description = "stderr"; 109 : 0 : return true; 110 : : } 111 [ + + ]: 160 : else if (value == "stdout") 112 : : { 113 : 2 : d_nonowned = &std::cout; 114 : 2 : d_owned.reset(); 115 : 2 : d_description = "stdout"; 116 : 2 : return true; 117 : : } 118 : 158 : return false; 119 : : } 120 : : 121 : 132938 : ManagedIn::ManagedIn() : ManagedStream(&std::cin, "stdin") {} 122 : 73 : bool ManagedIn::specialCases(const std::string& value) 123 : : { 124 [ + + ][ - + ]: 73 : if (value == "stdin" || value == "--") [ + + ] 125 : : { 126 : 1 : d_nonowned = &std::cin; 127 : 1 : d_owned.reset(); 128 : 1 : d_description = "stdin"; 129 : 1 : return true; 130 : : } 131 : 72 : return false; 132 : : } 133 : : 134 : 265875 : ManagedOut::ManagedOut() : ManagedStream(&std::cout, "stdout") {} 135 : 145 : bool ManagedOut::specialCases(const std::string& value) 136 : : { 137 [ + - ][ - + ]: 145 : if (value == "stdout" || value == "--") [ - + ] 138 : : { 139 : 0 : d_nonowned = &std::cout; 140 : 0 : d_owned.reset(); 141 : 0 : d_description = "stdout"; 142 : 0 : return true; 143 : : } 144 [ + + ]: 145 : else if (value == "stderr") 145 : : { 146 : 1 : d_nonowned = &std::cerr; 147 : 1 : d_owned.reset(); 148 : 1 : d_description = "stderr"; 149 : 1 : return true; 150 : : } 151 : 144 : return false; 152 : : } 153 : : 154 : : } // namespace cvc5::internal