1 //******************************************************************************
2 ///
3 /// @file base/messenger.cpp
4 ///
5 /// @todo What's in here?
6 ///
7 /// @copyright
8 /// @parblock
9 ///
10 /// Persistence of Vision Ray Tracer ('POV-Ray') version 3.8.
11 /// Copyright 1991-2018 Persistence of Vision Raytracer Pty. Ltd.
12 ///
13 /// POV-Ray is free software: you can redistribute it and/or modify
14 /// it under the terms of the GNU Affero General Public License as
15 /// published by the Free Software Foundation, either version 3 of the
16 /// License, or (at your option) any later version.
17 ///
18 /// POV-Ray is distributed in the hope that it will be useful,
19 /// but WITHOUT ANY WARRANTY; without even the implied warranty of
20 /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 /// GNU Affero General Public License for more details.
22 ///
23 /// You should have received a copy of the GNU Affero General Public License
24 /// along with this program. If not, see <http://www.gnu.org/licenses/>.
25 ///
26 /// ----------------------------------------------------------------------------
27 ///
28 /// POV-Ray is based on the popular DKB raytracer version 2.12.
29 /// DKBTrace was originally written by David K. Buck.
30 /// DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
31 ///
32 /// @endparblock
33 ///
34 //******************************************************************************
35
36 // Unit header file must be the first file included within POV-Ray *.cpp files (pulls in config)
37 #include "base/messenger.h"
38
39 // C++ variants of standard C header files
40 #include <cstdarg>
41 #include <cstdio>
42 #include <cstring>
43
44 #include "base/pov_err.h"
45
46 // this must be the last file included
47 #include "base/povdebug.h"
48
49 namespace pov_base
50 {
51
GenericMessenger(unsigned int wl,const char * sn)52 GenericMessenger::GenericMessenger(unsigned int wl, const char *sn) :
53 warningLevel(wl),
54 stageName(sn)
55 {}
56
~GenericMessenger()57 GenericMessenger::~GenericMessenger()
58 {}
59
UserDebug(const char * text)60 void GenericMessenger::UserDebug(const char *text)
61 {
62 SendMessage(kMessageClass_UserDebug, kWarningNone, text);
63 }
64
Info(const char * format,...)65 void GenericMessenger::Info(const char *format, ...)
66 {
67 WarningLevel level = kWarningGeneral;
68 if(warningLevel < level)
69 return;
70
71 va_list marker;
72 char localvsbuffer[1024];
73
74 sprintf(localvsbuffer, "%s Info: ", stageName);
75
76 va_start(marker, format);
77 std::vsnprintf(localvsbuffer + strlen(localvsbuffer), sizeof(localvsbuffer) - strlen(localvsbuffer), format, marker);
78 va_end(marker);
79
80 CleanupString(localvsbuffer);
81
82 SendMessage(kMessageClass_Info, level, localvsbuffer);
83 }
84
InfoAt(const UCS2 * filename,POV_LONG line,POV_LONG column,POV_OFF_T offset,const char * format,...)85 void GenericMessenger::InfoAt(const UCS2 *filename, POV_LONG line, POV_LONG column, POV_OFF_T offset, const char *format, ...)
86 {
87 WarningLevel level = kWarningGeneral;
88 if(warningLevel < level)
89 return;
90
91 va_list marker;
92 char localvsbuffer[1024];
93
94 sprintf(localvsbuffer, "%s Info: ", stageName);
95
96 va_start(marker, format);
97 std::vsnprintf(localvsbuffer + strlen(localvsbuffer), sizeof(localvsbuffer) - strlen(localvsbuffer), format, marker);
98 va_end(marker);
99
100 CleanupString(localvsbuffer);
101
102 SendMessage(kMessageClass_Info, level, localvsbuffer, filename, line, column, offset);
103 }
104
Warning(WarningLevel level,const char * format,...)105 void GenericMessenger::Warning(WarningLevel level, const char *format,...)
106 {
107 if(warningLevel < level)
108 return;
109
110 va_list marker;
111 char localvsbuffer[1024];
112
113 sprintf(localvsbuffer, "%s Warning: ", stageName);
114
115 va_start(marker, format);
116 std::vsnprintf(localvsbuffer + strlen(localvsbuffer), sizeof(localvsbuffer) - strlen(localvsbuffer), format, marker);
117 va_end(marker);
118
119 CleanupString(localvsbuffer);
120
121 SendMessage(kMessageClass_Warning, level, localvsbuffer);
122 }
123
WarningAt(WarningLevel level,const UCS2 * filename,POV_LONG line,POV_LONG column,POV_OFF_T offset,const char * format,...)124 void GenericMessenger::WarningAt(WarningLevel level, const UCS2 *filename, POV_LONG line, POV_LONG column, POV_OFF_T offset, const char *format, ...)
125 {
126 if(warningLevel < level)
127 return;
128
129 va_list marker;
130 char localvsbuffer[1024];
131
132 sprintf(localvsbuffer, "%s Warning: ", stageName);
133
134 va_start(marker, format);
135 std::vsnprintf(localvsbuffer + strlen(localvsbuffer), sizeof(localvsbuffer) - strlen(localvsbuffer), format, marker);
136 va_end(marker);
137
138 CleanupString(localvsbuffer);
139
140 SendMessage(kMessageClass_Warning, level, localvsbuffer, filename, line, column, offset);
141 }
142
PossibleError(const char * format,...)143 void GenericMessenger::PossibleError(const char *format,...)
144 {
145 if(warningLevel == 0)
146 return;
147
148 va_list marker;
149 char localvsbuffer[1024];
150
151 sprintf(localvsbuffer, "Possible %s Error: ", stageName);
152
153 va_start(marker, format);
154 std::vsnprintf(localvsbuffer + strlen(localvsbuffer), sizeof(localvsbuffer) - strlen(localvsbuffer), format, marker);
155 va_end(marker);
156
157 CleanupString(localvsbuffer);
158
159 SendMessage(kMessageClass_PossibleError, kWarningNone, localvsbuffer);
160 }
161
PossibleErrorAt(const UCS2 * filename,POV_LONG line,POV_LONG column,POV_OFF_T offset,const char * format,...)162 void GenericMessenger::PossibleErrorAt(const UCS2 *filename, POV_LONG line, POV_LONG column, POV_OFF_T offset, const char *format, ...)
163 {
164 if(warningLevel == 0)
165 return;
166
167 va_list marker;
168 char localvsbuffer[1024];
169
170 sprintf(localvsbuffer, "Possible %s Error: ", stageName);
171
172 va_start(marker, format);
173 std::vsnprintf(localvsbuffer + strlen(localvsbuffer), sizeof(localvsbuffer) - strlen(localvsbuffer), format, marker);
174 va_end(marker);
175
176 CleanupString(localvsbuffer);
177
178 SendMessage(kMessageClass_PossibleError, kWarningNone, localvsbuffer, filename, line, column, offset);
179 }
180
181 // filename defaults to `nullptr`, and line, column, and offset default to -1
SendError(const char * format,va_list arglist,const UCS2 * filename,POV_LONG line,POV_LONG column,POV_OFF_T offset)182 std::string GenericMessenger::SendError(const char *format, va_list arglist, const UCS2 *filename, POV_LONG line, POV_LONG column, POV_OFF_T offset)
183 {
184 char localvsbuffer[1024];
185
186 sprintf(localvsbuffer, "%s Error: ", stageName);
187 std::vsnprintf(localvsbuffer + strlen(localvsbuffer), sizeof(localvsbuffer) - strlen(localvsbuffer), format, arglist);
188 CleanupString(localvsbuffer);
189
190 SendMessage(kMessageClass_Error, kWarningNone, localvsbuffer, filename, line, column, offset);
191
192 return std::string(localvsbuffer);
193 }
194
Error(const char * format,...)195 void GenericMessenger::Error(const char *format, ...)
196 {
197 va_list marker;
198
199 va_start(marker, format);
200 std::string text = SendError(format, marker);
201 va_end(marker);
202
203 // Terminate by throwing an exception with the notification flag already set
204 pov_base::Exception ex(__FUNCTION__, __FILE__, __LINE__, text); // TODO - this location information isn't too helpful
205 ex.frontendnotified(true);
206 throw ex;
207 }
208
Error(const Exception & ex,const char * format,...)209 void GenericMessenger::Error(const Exception& ex, const char *format, ...)
210 {
211 va_list marker;
212
213 // if the front-end has been told about this exception already, we don't want to tell it again
214 // (we presume that the text given by format and its parameters relate to that exception)
215 // this form of frontendnotified() doesn't change the state of ex
216 if (ex.frontendnotified())
217 throw ex;
218
219 va_start(marker, format);
220 SendError(format, marker);
221 va_end(marker);
222
223 // now take a copy of ex and set its notification flag, then throw that.
224 pov_base::Exception local_ex(ex);
225 local_ex.frontendnotified(true);
226 throw local_ex;
227 }
228
Error(Exception & ex,const char * format,...)229 void GenericMessenger::Error(Exception& ex, const char *format, ...)
230 {
231 va_list marker;
232
233 // if the front-end has been told about this exception already, we don't want to tell it again
234 // (we presume that the text given by format and its parameters relate to that exception)
235 // this form of frontendnotified() sets the notified state of ex
236 if (ex.frontendnotified(true))
237 throw ex;
238
239 va_start(marker, format);
240 SendError(format, marker);
241 va_end(marker);
242
243 // Terminate
244 throw ex;
245 }
246
ErrorAt(const UCS2 * filename,POV_LONG line,POV_LONG column,POV_OFF_T offset,const char * format,...)247 void GenericMessenger::ErrorAt(const UCS2 *filename, POV_LONG line, POV_LONG column, POV_OFF_T offset, const char *format, ...)
248 {
249 va_list marker;
250
251 va_start(marker, format);
252 std::string text = SendError(format, marker, filename, line, column, offset);
253 va_end(marker);
254
255 // Terminate by throwing an exception with the notification flag already set
256 pov_base::Exception ex(__FUNCTION__, __FILE__, __LINE__, text); // TODO - this location information isn't too helpful
257 ex.frontendnotified(true);
258
259 throw ex;
260 }
261
ErrorAt(const Exception & ex,const UCS2 * filename,POV_LONG line,POV_LONG column,POV_OFF_T offset,const char * format,...)262 void GenericMessenger::ErrorAt(const Exception& ex, const UCS2 *filename, POV_LONG line, POV_LONG column, POV_OFF_T offset, const char *format, ...)
263 {
264 va_list marker;
265
266 if (ex.frontendnotified())
267 throw ex;
268
269 va_start(marker, format);
270 SendError(format, marker, filename, line, column, offset);
271 va_end(marker);
272
273 pov_base::Exception local_ex(ex);
274 local_ex.frontendnotified(true);
275 throw local_ex;
276 }
277
ErrorAt(Exception & ex,const UCS2 * filename,POV_LONG line,POV_LONG column,POV_OFF_T offset,const char * format,...)278 void GenericMessenger::ErrorAt(Exception& ex, const UCS2 *filename, POV_LONG line, POV_LONG column, POV_OFF_T offset, const char *format, ...)
279 {
280 va_list marker;
281
282 if (ex.frontendnotified(true))
283 throw ex;
284
285 va_start(marker, format);
286 SendError(format, marker, filename, line, column, offset);
287 va_end(marker);
288
289 throw ex;
290 }
291
CleanupString(char * str)292 void GenericMessenger::CleanupString(char *str)
293 {
294 while(*str != 0)
295 {
296 if(*str == '\n')
297 *str = ' ';
298 str++;
299 }
300 }
301
302 }
303