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