1 /********************* */
2 /*! \file exception.cpp
3 ** \verbatim
4 ** Top contributors (to current version):
5 ** Tim King, Morgan Deters, Andres Noetzli
6 ** This file is part of the CVC4 project.
7 ** Copyright (c) 2009-2019 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.\endverbatim
11 **
12 ** \brief CVC4's exception base class and some associated utilities
13 **
14 ** CVC4's exception base class and some associated utilities.
15 **/
16
17 #include "base/exception.h"
18
19 #include <cstdarg>
20 #include <cstdio>
21 #include <cstdlib>
22 #include <cstring>
23 #include <string>
24
25 #include "base/cvc4_assert.h"
26
27 using namespace std;
28
29 namespace CVC4 {
30
31 thread_local LastExceptionBuffer* LastExceptionBuffer::s_currentBuffer = NULL;
32
LastExceptionBuffer()33 LastExceptionBuffer::LastExceptionBuffer() : d_contents(NULL) {}
34
~LastExceptionBuffer()35 LastExceptionBuffer::~LastExceptionBuffer() {
36 if(d_contents != NULL){
37 free(d_contents);
38 d_contents = NULL;
39 }
40 }
41
setContents(const char * string)42 void LastExceptionBuffer::setContents(const char* string) {
43 if(d_contents != NULL){
44 free(d_contents);
45 d_contents = NULL;
46 }
47
48 if(string != NULL){
49 d_contents = strdup(string);
50 }
51 }
52
53 const char* IllegalArgumentException::s_header = "Illegal argument detected";
54
formatVariadic()55 std::string IllegalArgumentException::formatVariadic() {
56 return std::string();
57 }
58
formatVariadic(const char * format,...)59 std::string IllegalArgumentException::formatVariadic(const char* format, ...) {
60 va_list args;
61 va_start(args, format);
62
63 int n = 512;
64 char* buf = NULL;
65
66 for (int i = 0; i < 2; ++i){
67 Assert(n > 0);
68 if(buf != NULL){
69 delete [] buf;
70 }
71 buf = new char[n];
72
73 va_list args_copy;
74 va_copy(args_copy, args);
75 int size = vsnprintf(buf, n, format, args);
76 va_end(args_copy);
77
78 if(size >= n){
79 buf[n-1] = '\0';
80 n = size + 1;
81 } else {
82 break;
83 }
84 }
85 // buf is not NULL is an invariant.
86 // buf is also 0 terminated.
87 Assert(buf != NULL);
88 std::string result(buf);
89 delete [] buf;
90 va_end(args);
91 return result;
92 }
93
format_extra(const char * condStr,const char * argDesc)94 std::string IllegalArgumentException::format_extra(const char* condStr, const char* argDesc){
95 return ( std::string("`") + argDesc + "' is a bad argument"
96 + (*condStr == '\0' ? std::string() :
97 ( std::string("; expected ") +
98 condStr + " to hold" )) );
99 }
100
construct(const char * header,const char * extra,const char * function,const char * tail)101 void IllegalArgumentException::construct(const char* header, const char* extra,
102 const char* function, const char* tail) {
103 // try building the exception msg with a smallish buffer first,
104 // then with a larger one if sprintf tells us to.
105 int n = 512;
106 char* buf;
107
108 for(;;) {
109 buf = new char[n];
110
111 int size;
112 if(extra == NULL) {
113 size = snprintf(buf, n, "%s\n%s\n%s",
114 header, function, tail);
115 } else {
116 size = snprintf(buf, n, "%s\n%s\n\n %s\n%s",
117 header, function, extra, tail);
118 }
119
120 if(size < n) {
121 break;
122 } else {
123 // size >= n
124 // try again with a buffer that's large enough
125 n = size + 1;
126 delete [] buf;
127 }
128 }
129
130 setMessage(string(buf));
131
132 #ifdef CVC4_DEBUG
133 LastExceptionBuffer* buffer = LastExceptionBuffer::getCurrent();
134 if(buffer != NULL){
135 if(buffer->getContents() == NULL) {
136 buffer->setContents(buf);
137 }
138 }
139 #endif /* CVC4_DEBUG */
140 delete [] buf;
141 }
142
construct(const char * header,const char * extra,const char * function)143 void IllegalArgumentException::construct(const char* header, const char* extra,
144 const char* function) {
145 // try building the exception msg with a smallish buffer first,
146 // then with a larger one if sprintf tells us to.
147 int n = 256;
148 char* buf;
149
150 for(;;) {
151 buf = new char[n];
152
153 int size;
154 if(extra == NULL) {
155 size = snprintf(buf, n, "%s.\n%s\n",
156 header, function);
157 } else {
158 size = snprintf(buf, n, "%s.\n%s\n\n %s\n",
159 header, function, extra);
160 }
161
162 if(size < n) {
163 break;
164 } else {
165 // try again with a buffer that's large enough
166 n = size + 1;
167 delete [] buf;
168 }
169 }
170
171 setMessage(string(buf));
172
173 #ifdef CVC4_DEBUG
174 LastExceptionBuffer* buffer = LastExceptionBuffer::getCurrent();
175 if(buffer != NULL){
176 if(buffer->getContents() == NULL) {
177 buffer->setContents(buf);
178 }
179 }
180 #endif /* CVC4_DEBUG */
181 delete [] buf;
182 }
183
184 } /* namespace CVC4 */
185