1 /* 2 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #include <algorithm> 27 28 #include "ErrorHandling.h" 29 #include "Log.h" 30 31 32 namespace { 33 34 tstring getFilename(const SourceCodePos& pos) { 35 const std::string buf(pos.file); 36 const std::string::size_type idx = buf.find_last_of("\\/"); 37 if (idx == std::string::npos) { 38 return tstrings::fromUtf8(buf); 39 } 40 return tstrings::fromUtf8(buf.substr(idx + 1)); 41 } 42 43 void reportError(const SourceCodePos& pos, const tstring& msg) { 44 Logger::defaultLogger().log(Logger::LOG_ERROR, getFilename(pos).c_str(), 45 pos.lno, tstrings::fromUtf8(pos.func).c_str(), msg); 46 } 47 48 } // namespace 49 50 void reportError(const SourceCodePos& pos, const std::exception& e) { 51 reportError(pos, (tstrings::any() << "Exception with message \'" 52 << e.what() << "\' caught").tstr()); 53 } 54 55 56 void reportUnknownError(const SourceCodePos& pos) { 57 reportError(pos, _T("Unknown exception caught")); 58 } 59 60 61 std::string makeMessage(const std::exception& e, const SourceCodePos& pos) { 62 std::ostringstream printer; 63 printer << getFilename(pos) << "(" << pos.lno << ") at " 64 << pos.func << "(): " 65 << e.what(); 66 return printer.str(); 67 } 68 69 70 namespace { 71 72 bool isNotSpace(int chr) { 73 return isspace(chr) == 0; 74 } 75 76 77 enum TrimMode { 78 TrimLeading = 0x10, 79 TrimTrailing = 0x20, 80 TrimBoth = TrimLeading | TrimTrailing 81 }; 82 83 // Returns position of the last printed character in the given string. 84 // Returns std::string::npos if nothing was printed. 85 size_t printWithoutWhitespaces(std::ostream& out, const std::string& str, 86 TrimMode mode) { 87 std::string::const_reverse_iterator it = str.rbegin(); 88 std::string::const_reverse_iterator end = str.rend(); 89 90 if (mode & TrimLeading) { 91 // skip leading whitespace 92 std::string::const_iterator entry = std::find_if(str.begin(), 93 str.end(), isNotSpace); 94 end = std::string::const_reverse_iterator(entry); 95 } 96 97 if (mode & TrimTrailing) { 98 // skip trailing whitespace 99 it = std::find_if(it, end, isNotSpace); 100 } 101 102 if (it == end) { 103 return std::string::npos; 104 } 105 106 const size_t pos = str.rend() - end; 107 const size_t len = end - it; 108 out.write(str.c_str() + pos, len); 109 return pos + len - 1; 110 } 111 112 } // namespace 113 114 std::string joinErrorMessages(const std::string& a, const std::string& b) { 115 const std::string endPhraseChars(";.,:!?"); 116 const std::string space(" "); 117 const std::string dotAndSpace(". "); 118 119 std::ostringstream printer; 120 printer.exceptions(std::ios::failbit | std::ios::badbit); 121 122 size_t idx = printWithoutWhitespaces(printer, a, TrimTrailing); 123 size_t extra = 0; 124 if (idx < a.size() && endPhraseChars.find(a[idx]) == std::string::npos) { 125 printer << dotAndSpace; 126 extra = dotAndSpace.size(); 127 } else if (idx != std::string::npos) { 128 printer << space; 129 extra = space.size(); 130 } 131 132 idx = printWithoutWhitespaces(printer, b, TrimBoth); 133 134 const std::string str = printer.str(); 135 136 if (std::string::npos == idx && extra) { 137 // Nothing printed from the 'b' message. Backout delimiter string. 138 return str.substr(0, str.size() - extra); 139 } 140 return str; 141 }