PEBL 2.2
Psychology Experiment Building Language - Cross-platform psychological experiment development system
PError.cpp
Go to the documentation of this file.
1//* -*- mode:C++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*- */
3// Name: src/utility/PError.cpp
4// Purpose: Utility class for signaling warnings and errors
5// Author: Shane T. Mueller, Ph.D.
6// Copyright: (c) 2003-2026 Shane T. Mueller <smueller@obereed.net>
7// License: GPL 2
8//
9//
10//
11// This file is part of the PEBL project.
12//
13// PEBL is free software; you can redistribute it and/or modify
14// it under the terms of the GNU General Public License as published by
15// the Free Software Foundation; either version 2 of the License, or
16// (at your option) any later version.
17//
18// PEBL 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 General Public License for more details.
22//
23// You should have received a copy of the GNU General Public License
24// along with PEBL; if not, write to the Free Software
25// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27
28#include "PError.h"
29#include "../base/PNode.h"
30#include "../base/Evaluator.h"
31
32#include "../base/Variant.h"
33#include "../base/PComplexData.h"
34
35#ifndef PEBL_VALIDATOR
36#include "../platforms/sdl/SDLUtility.h"
37#endif
38
39#include <iostream>
40#include <string>
41#include <signal.h>
42
43
44#ifdef PEBL_EMSCRIPTEN
45#include <emscripten.h>
46#endif
47
48using std::cout;
49using std::cerr;
50using std::endl;
51using std::string;
52
54
55// Define and initialize the error dialog flag (defaults to true)
57
58// Define and initialize the validator mode flag (defaults to false)
60
61
62void PError::SignalFatalError(const string & message)
63{
64
65 const PNode * node = Evaluator::gEvalNode;
66
67
68
69
71 Variant errorMessage;
72
73 if(node)
74 {
75 errorMessage = Variant("\nError near line ") +
76 Variant(node->GetLineNumber())+
77 Variant(" of file ") +Variant( node->GetFilename()) +Variant(":\n") + message;
78
79
80 }
81 else
82 {
83 errorMessage = Variant("\nError before files are loaded.\n") + message;
84
85 }
86
87
88 //At this point, we'd like to, if possible, make a
89 //pop-up message box in an SDL window.
90 cerr << errorMessage.GetString() << endl;
91
92 // Only show GUI dialog if enabled (disabled for command-line tools)
93#ifndef PEBL_VALIDATOR
95 {
96 PlatformWindow* pw = dynamic_cast<PlatformWindow*>(myEnv->GetWindow(0));
97 if(pw)
98 SDLUtility::PopupErrorBox(pw, errorMessage.GetString().c_str());
99 }
100#endif
101
102 // In validator mode, throw exception instead of exiting
103 // This allows the validator to collect errors and continue
105 {
106 throw std::runtime_error(errorMessage.GetString());
107 }
108
109 raise(SIGTERM);
110 exit(1); // Exit with error code 1 for fatal errors
111#ifdef PEBL_EMSCRIPTEN
112 emscripten_cancel_main_loop();
113 emscripten_force_exit(1);
114
115#endif
116}
117
118
119void PError::SignalWarning(const std::string & message)
120{
121 const PNode * node = Evaluator::gEvalNode;
122 cerr << "Non-fatal Warning in line " << node->GetLineNumber() << " of file " << node->GetFilename() << ":\n\t";
123 cerr << message << endl;
124}
125
126void PError::ExitQuietly(const std::string & message, int exitCode)
127{
128 cerr << message << endl;
129 raise(SIGTERM);
130 exit(exitCode);
131}
132
136void PError::AssertType(Variant v, int type, const string & outsideMessage)
137{
138
139 string message;
140
141 switch(type)
142 {
143
145 if( !v.IsStackSignal())
146 {
147 message = outsideMessage;
148 message += "Wanted stack signal but got a " + GetTypeName(v) + ": " + v.GetString();
149 SignalFatalError(message);
150 }
151
152 break;
153
154
155 case PEAT_FUNCTION:
156 if( !v.IsFunction())
157 {
158 message = outsideMessage;
159 message += "Wanted function but got a " + GetTypeName(v) + ": " + v.GetString();
160 SignalFatalError(message);
161 }
162
163 break;
165 if( !v.IsFunction())
166 {
167 message = outsideMessage;
168 message += "Wanted function pointer but got " + GetTypeName(v) + ": " + v.GetString();
169 SignalFatalError(message);
170 }
171
172 break;
173 case PEAT_NUMBER:
174 if( !v.IsNumber())
175 {
176 message = outsideMessage;
177 message += "Wanted number but got " + GetTypeName(v) + ": " + v.GetString();
178 SignalFatalError(message);
179 }
180 break;
181
182 case PEAT_INTEGER:
183
184 if( !v.IsInteger())
185 {
186 message = outsideMessage;
187 message += "Wanted integer but got " + GetTypeName(v) + ": " + v.GetString();
188 SignalFatalError(message);
189 }
190 break;
191 case PEAT_FLOAT:
192 if( !v.IsNumber())
193 {
194 message = outsideMessage;
195 message +="Wanted floating-point number but got " + GetTypeName(v) + ": "+ v.GetString();
196 SignalFatalError(message);
197 }
198 break;
199
200 case PEAT_STRING:
201 if( !v.IsString())
202 {
203 message = outsideMessage;
204 message +="Wanted string but got " + GetTypeName(v) + ": "+ v.GetString();
205 SignalFatalError(message);
206 }
207 break;
208
209 case PEAT_VARIABLE:
210
211 if( v.IsGlobalVariable() || v.IsLocalVariable())
212 {
213 return;
214 }
215 message = outsideMessage;
216 message +="Wanted variable but got " + GetTypeName(v) + ": "+ v.GetString();
217 SignalFatalError(message);
218
219 break;
220
221
222 case PEAT_AUDIOOUT:
223 if(v.IsComplexData())
224 {
225 if((v.GetComplexData())->IsAudioOut())
226 {
227 //Everything is fine, return without error.
228 return;
229 }
230 }
231 message = outsideMessage;
232 message +="Wanted AudioOut stream but got " + GetTypeName(v) + ": "+ v.GetString();
233 SignalFatalError(message);
234
235 break;
236 case PEAT_COLOR:
237 if(v.IsComplexData())
238 {
239 if((v.GetComplexData())->IsColor())
240 {
241 //Everything is fine, return without error.
242 return;
243 }
244 }
245
246 message = outsideMessage;
247 message +="Wanted PEBL Color but got " + GetTypeName(v) + ": "+ v.GetString();
248 SignalFatalError(message);
249 break;
250
251 case PEAT_ENVIRONMENT:
252
253 if(v.IsComplexData())
254 {
255 if((v.GetComplexData())->IsEnvironment())
256 {
257 //Everything is fine, return without error.
258 return;
259 }
260 }
261 message = outsideMessage;
262 message +="Wanted Environment but got " + GetTypeName(v) + ": "+ v.GetString();
263 SignalFatalError(message);
264
265 break;
266
267 case PEAT_FILESTREAM:
268
269 if(v.IsComplexData())
270 {
271 if((v.GetComplexData())->IsFileStream())
272 {
273 //Everything is fine, return without error.
274 return;
275 }
276 }
277 message = outsideMessage;
278 message +="Wanted FileStream but got " + GetTypeName(v) + ": "+ v.GetString();
279 SignalFatalError(message);
280
281 break;
282
283
284 case PEAT_FONT:
285
286 if(v.IsComplexData())
287 {
288 if((v.GetComplexData())->IsFont())
289 {
290 //Everything is fine, return without error.
291 return;
292 }
293 }
294
295 message = outsideMessage;
296 message +="Wanted font but got " + GetTypeName(v) + ": "+ v.GetString();
297 SignalFatalError(message);
298
299 break;
300
301
302 case PEAT_IMAGEBOX:
303
304 if(v.IsComplexData())
305 {
306 if((v.GetComplexData())->IsImageBox())
307 {
308 //Everything is fine, return without error.
309 return;
310 }
311 }
312 message = outsideMessage;
313 message +="Wanted Image but got " + GetTypeName(v) + ": "+ v.GetString();
314 SignalFatalError(message);
315
316 break;
317
318
319
320 case PEAT_JOYSTICK:
321
322 if(v.IsComplexData())
323 {
324 if((v.GetComplexData())->IsJoystick())
325 {
326 //Everything is fine, return without error.
327 return;
328 }
329 }
330 message = outsideMessage;
331 message +="Wanted Joystick but got " + GetTypeName(v) + ": "+ v.GetString();
332 SignalFatalError(message);
333
334 break;
335
336
337 case PEAT_KEYBOARD:
338
339 if(v.IsComplexData())
340 {
341 if((v.GetComplexData())->IsKeyboard())
342 {
343 //Everything is fine, return without error.
344 return;
345 }
346 }
347 message = outsideMessage;
348 message +="Wanted Keyboard but got " + GetTypeName(v) + ": "+ v.GetString();
349 SignalFatalError(message);
350
351 break;
352
353 case PEAT_LIST:
354
355 if(v.IsComplexData())
356 {
357 if((v.GetComplexData())->IsList())
358 {
359 //Everything is fine, return without error.
360 return;
361 }
362 }
363 message = outsideMessage;
364 message +="Wanted list but got " + GetTypeName(v) + ": "+ v.GetString();
365 SignalFatalError(message);
366
367 break;
368
369
370 case PEAT_WIDGET:
371
372 if(v.IsComplexData())
373 {
374 if((v.GetComplexData())->IsWidget())
375 {
376 //Everything is fine, return without error.
377 return;
378 }
379 }
380 message = outsideMessage;
381 message +="Wanted Widget but got " + GetTypeName(v) + ": "+ v.GetString();
382 SignalFatalError(message);
383
384 break;
385
386
387 case PEAT_OBJECT:
388 if(v.IsComplexData())
389 {
390 //Any complex data is a PEBLObject (except maybe a list?)
391 return;
392 }
393 message = outsideMessage;
394 message +="Wanted Object but got " + GetTypeName(v) + ": "+ v.GetString();
395 SignalFatalError(message);
396
397 break;
398
399
400 case PEAT_WINDOW:
401
402 if(v.IsComplexData())
403 {
404 if((v.GetComplexData())->IsWindow())
405 {
406 //Everything is fine, return without error.
407 return;
408 }
409 }
410 message = outsideMessage;
411 message +="Wanted Window but got " + GetTypeName(v) + ": "+ v.GetString();
412 SignalFatalError(message);
413
414 break;
415
416 case PEAT_TEXTOBJECT:
417
418 if(v.IsComplexData())
419 {
420 if((v.GetComplexData())->IsTextObject())
421 {
422 //Everything is fine, return without error.
423 return;
424 }
425 }
426 message = outsideMessage;
427 message +="Wanted TextObject but got " + GetTypeName(v) + ": " + v.GetString();
428 SignalFatalError(message);
429
430 break;
431
432
433 case PEAT_LABEL:
434
435 if(v.IsComplexData())
436 {
437 if((v.GetComplexData())->IsLabel())
438 {
439 //Everything is fine, return without error.
440 return;
441 }
442 }
443 message = outsideMessage;
444 message +="Wanted Label but got " + GetTypeName(v) + ": " + v.GetString();
445 SignalFatalError(message);
446
447 break;
448
449
450
451 case PEAT_TEXTBOX:
452
453 if(v.IsComplexData())
454 {
455 if((v.GetComplexData())->IsTextBox())
456 {
457 //Everything is fine, return without error.
458 return;
459 }
460 }
461 message = outsideMessage;
462 message +="Wanted Text Box but got " + GetTypeName(v) + ": " + v.GetString();
463 SignalFatalError(message);
464
465 break;
466
468
469 if(v.IsComplexData())
470 {
471 if((v.GetComplexData())->IsNetworkConnection())
472 {
473 //Everything is fine, return without error.
474 return;
475 }
476 }
477 message = outsideMessage;
478 message +="Wanted network but got " + GetTypeName(v) + ": "+ v.GetString();
479 SignalFatalError(message);
480
481 break;
482
483
485
486 if(v.IsComplexData())
487 {
488 if((v.GetComplexData())->IsParallelPort())
489 {
490 //Everything is fine, return without error.
491 return;
492 }
493 }
494 message = outsideMessage;
495 message +="Wanted parallelport but got " + GetTypeName(v) + ": "+ v.GetString();
496 SignalFatalError(message);
497
498 break;
499
500 case PEAT_COMPORT:
501
502 if(v.IsComplexData())
503 {
504 if((v.GetComplexData())->IsComPort())
505 {
506 //Everything is fine, return without error.
507 return;
508 }
509 }
510 message = outsideMessage;
511 message +="Wanted ComPort but got " + GetTypeName(v) + ": "+ v.GetString();
512 SignalFatalError(message);
513
514 break;
515
516 case PEAT_MOVIE:
517
518 if(v.IsComplexData())
519 {
520 if((v.GetComplexData())->IsMovie())
521 {
522 //Everything is fine, return without error.
523 return;
524 }
525 }
526 message = outsideMessage;
527 message +="Wanted Movie but got " + GetTypeName(v) + ": "+ v.GetString();
528 SignalFatalError(message);
529
530 break;
531
532
533 case PEAT_UNDEFINED:
534 default:
535
536 message = outsideMessage;
537 message += string("Undefined type in PErrorAssert: ") + v.GetString();
538 SignalFatalError(message);
539 break;
540 }
541
542}
543
544
545
546
548{
549 //Get the name of the type: if it a complex data type, extract the name from that structure.
550 string typeName;
551 if(v.IsComplexData())
552 {
553 typeName = (v.GetComplexData())->GetTypeName();
554 }
555 else
556 {
557 typeName = v.GetDataTypeName();
558 }
559
560 return typeName;
561}
562
563
564
565
566
PlatformEnvironment * myEnv
Definition PEBL.cpp:189
@ PEAT_KEYBOARD
Definition PError.h:60
@ PEAT_JOYSTICK
Definition PError.h:59
@ PEAT_FUNCTION_POINTER
Definition PError.h:42
@ PEAT_VARIABLE
Definition PError.h:49
@ PEAT_STACK_SIGNAL
Definition PError.h:40
@ PEAT_FONT
Definition PError.h:57
@ PEAT_NETWORKCONNECTION
Definition PError.h:62
@ PEAT_FUNCTION
Definition PError.h:41
@ PEAT_COMPORT
Definition PError.h:65
@ PEAT_TEXTOBJECT
Definition PError.h:66
@ PEAT_LABEL
Definition PError.h:68
@ PEAT_COLOR
Definition PError.h:54
@ PEAT_LIST
Definition PError.h:61
@ PEAT_PARALLELPORT
Definition PError.h:64
@ PEAT_TEXTBOX
Definition PError.h:67
@ PEAT_UNDEFINED
Definition PError.h:39
@ PEAT_INTEGER
Definition PError.h:44
@ PEAT_WIDGET
Definition PError.h:69
@ PEAT_WINDOW
Definition PError.h:70
@ PEAT_STRING
Definition PError.h:46
@ PEAT_OBJECT
Definition PError.h:63
@ PEAT_FLOAT
Definition PError.h:45
@ PEAT_FILESTREAM
Definition PError.h:56
@ PEAT_ENVIRONMENT
Definition PError.h:55
@ PEAT_AUDIOOUT
Definition PError.h:53
@ PEAT_IMAGEBOX
Definition PError.h:58
@ PEAT_NUMBER
Definition PError.h:43
@ PEAT_MOVIE
Definition PError.h:71
static const PNode * gEvalNode
static PCallStack gCallStack
std::ostream & PrintCallStack(std::ostream &out) const
Definition PError.h:114
virtual PWindow * GetWindow(int index=0)
Definition PNode.h:45
int GetLineNumber() const
Definition PNode.h:69
std::string GetFilename() const
Definition PNode.h:68
bool IsComplexData() const
Definition Variant.cpp:984
bool IsGlobalVariable() const
Definition Variant.cpp:964
bool IsString() const
Definition Variant.cpp:948
bool IsStackSignal() const
Definition Variant.cpp:989
bool IsFunction() const
Definition Variant.cpp:970
std::string GetString() const
Definition Variant.cpp:1056
bool IsInteger() const
Definition Variant.cpp:942
PComplexData * GetComplexData() const
Definition Variant.cpp:1299
bool IsNumber() const
This tests whether the Variant is a number (i.e., a float or an integer.)
Definition Variant.cpp:930
bool IsLocalVariable() const
Definition Variant.cpp:959
std::string GetDataTypeName() const
This returns the type as a string.
Definition Variant.cpp:891
Variant SignalFatalError(Variant v)
void ExitQuietly(const std::string &message, int exitCode=0)
Definition PError.cpp:126
void SignalWarning(const std::string &message)
Definition PError.cpp:119
std::string GetTypeName(Variant v)
Definition PError.cpp:547
void AssertType(Variant v, int type, const std::string &outsidemessage)
bool gValidatorMode
Definition PError.cpp:59
void SignalFatalError(const std::string &message)
bool gShowErrorDialogs
Definition PError.cpp:56
int PopupErrorBox(PlatformWindow *pwindow, const char *message)