YAP 7.1.0
errors.c
Go to the documentation of this file.
1/*************************************************************************
2 * *
3 * Yap Prolog *
4 * *
5 * Yap Prolog Was Deeloped At Nccup - Universidade Do Porto *
6 * *
7 * Copyright L.Damas, V.S.Costa And Universidade Do Porto 1985-1997 *
8 * *
9 **************************************************************************
10 * *
11 * File: errors.c *
12 * Last Rev: *
13 * Mods: *
14 * Comments: Yap's error handlers *
15 * *
16 *************************************************************************/
17
64#include "Yap.h"
65#include "YapDefs.h"
66#include "YapInterface.h"
67#include "YapStreams.h"
68#include "YapTags.h"
69#include "Yapproto.h"
70#include "absmi.h"
71#include "yapio.h"
72#if HAVE_STDARG_H
73#include <stdarg.h>
74#endif
75#include <stdlib.h>
76#if HAVE_UNISTD_H
77#include <unistd.h>
78#endif
79#if HAVE_STRING_H
80#include <string.h>
81#endif
82#if HAVE_EXECINFO_H
83#include <execinfo.h>
84#endif
85#include "Foreign.h"
86
87void Yap_RestartYap(int flag)
88{
89 CACHE_REGS
90#if PUSH_REGS
91 restore_absmi_regs(&Yap_standard_regs);
92#endif
93 siglongjmp(*LOCAL_RestartEnv, flag);
94}
95
96extern Term MkErrorTerm(yap_error_descriptor_t *t);
97
98#define set_key_b(k, ks, q, i, t) \
99 if (strcmp(ks, q) == 0) \
100 { \
101 i->k = (t == TermTrue ? true : false); \
102 return i->k || t == TermFalse; \
103 }
104
105#define set_key_i(k, ks, q, i, t) \
106 if (strcmp(ks, q) == 0) \
107 { \
108 i->k = IsIntegerTerm(t) ? IntegerOfTerm(t) : 0; \
109 return IsIntegerTerm(t); \
110 }
111
112#define set_key_s(k, ks, q, i, t) \
113 if (strcmp(ks, q) == 0) \
114 { \
115 const char *s = IsAtomTerm(t) ? RepAtom(AtomOfTerm(t))->StrOfAE \
116 : IsStringTerm(t) ? StringOfTerm(t) : NULL; \
117 if (s && s[0]) \
118 { \
119 char *tmp = calloc(1, strlen(s) + 1); \
120 strcpy(tmp, s); \
121 i->k = tmp; \
122 } \
123 return i->k != NULL; \
124 }
125
126#define set_key_t(k, ks, q, i, t) \
127 if (strcmp(ks, q) == 0) \
128 { \
129 i->k = Yap_SaveTerm(t); \
130 return i->k != 0L; \
131 }
132
133static bool setErr(const char *q, yap_error_descriptor_t *i, Term t)
134{
135 set_key_i(errorNo, "errorNo", q, i, t);
136 set_key_i(errorClass, "errorClass", q, i, t);
137 set_key_s(errorAsText, "errorAsText", q, i, t);
138 set_key_s(classAsText, "classAsText", q, i, t);
139 set_key_i(errorLine, "errorLine", q, i, t);
140 set_key_s(errorFunction, "errorFunction", q, i, t);
141 set_key_s(errorFile, "errorFile", q, i, t);
142 set_key_i(prologPredLine, "prologPredLine", q, i, t);
143 set_key_s(prologPredName, "prologPredName", q, i, t);
144 set_key_i(prologPredArity, "prologPredArity", q, i, t);
145 set_key_s(prologPredModule, "prologPredModule", q, i, t);
146 set_key_s(prologPredFile, "prologPredFile", q, i, t);
147 set_key_i(parserPos, "parserPos", q, i, t);
148 set_key_i(parserLine, "parserLine", q, i, t);
149 set_key_i(parserFirstLine, "parserFirstLine", q, i, t);
150 set_key_i(parserLastLine, "parserLastLine", q, i, t);
151 set_key_s(parserTextA, "parserTextA", q, i, t);
152 set_key_i(parserTextB, "parserTextB", q, i, t);
153 set_key_s(parserFile, "parserFile", q, i, t);
154 set_key_b(parserReadingCode, "parserReadingcode", q, i, t);
155 set_key_b(prologConsulting, "prologConsulting", q, i, t);
156 set_key_s(culprit, "culprit", q, i, t);
157
158 set_key_s(prologStack, "prologStack", q, i, t);
159 set_key_s(errorMsg, "errorMsg", q, i, t);
160 return false;
161}
162
163#define query_key_b(k, ks, q, i) \
164 if (strcmp(ks, q) == 0) \
165 { \
166 return i->k ? TermTrue : TermFalse; \
167 }
168
169#define query_key_i(k, ks, q, i) \
170 if (strcmp(ks, q) == 0) \
171 { \
172 return MkIntegerTerm(i->k); \
173 }
174
175#define query_key_s(k, ks, q, i) \
176 if (strcmp(ks, q) == 0) \
177 { \
178 if (i->k && i->k[0] != '\0') \
179 return MkAtomTerm(Yap_LookupAtom(i->k)); \
180 else \
181 return TermEmptyAtom; \
182 }
183
184#define query_key_t(k, ks, q, i) \
185 if (strcmp(ks, q) == 0) \
186 { \
187 Term t; \
188 if ((t = i->k) == 0) \
189 return TermNil; \
190 return t; \
191 }
192
193static Term queryErr(const char *q, yap_error_descriptor_t *i)
194{
195 query_key_i(errorNo, "errorNo", q, i);
196 query_key_i(errorClass, "errorClass", q, i);
197 query_key_s(errorAsText, "errorAsText", q, i);
198 query_key_s(classAsText, "classAsText", q, i);
199 query_key_i(errorLine, "errorLine", q, i);
200 query_key_s(errorFunction, "errorFunction", q, i);
201 query_key_s(errorFile, "errorFile", q, i);
202 query_key_i(prologPredLine, "prologPredLine", q, i);
203 query_key_s(prologPredName, "prologPredName", q, i);
204 query_key_i(prologPredArity, "prologPredArity", q, i);
205 query_key_s(prologPredModule, "prologPredModule", q, i);
206 query_key_s(prologPredFile, "prologPredFile", q, i);
207 query_key_i(parserLine, "parserLine", q, i);
208 query_key_i(parserFirstLine, "parserFirstLine", q, i);
209 query_key_i(parserLastLine, "parserLastLine", q, i);
210 query_key_s(parserTextA, "parserTextA", q, i);
211 query_key_i(parserTextB, "parserTextB", q, i);
212 query_key_s(parserFile, "parserFile", q, i);
213 query_key_b(parserReadingCode, "parserReadingCode", q, i);
214 query_key_b(prologConsulting, "prologConsulting", q, i);
215 query_key_s(prologStack, "prologStack", q, i);
216 query_key_s(culprit, "culprit", q, i);
217 query_key_s(errorMsg, "errorMsg", q, i);
218 return TermNil;
219}
220
221static void print_key_b(FILE *of, const char *key, bool v)
222{
223 const char *b = v ? "true" : "false";
224 fprintf(of, "%s: %s\n", key, b);
225}
226
227static void print_key_i(FILE *of, const char *key, YAP_Int v)
228{
229 fprintf(of, "%s: " Int_FORMAT "\n", key, v);
230}
231
232static void print_key_s(FILE *of, const char *key, const char *v)
233{
234 if (v && v[0])
235 fprintf(of, "%s: %s\n", key, v);
236}
237
238static void print_key_t(FILE *of, const char *key, YAP_Term v)
239{
240 if (v)
241 fprintf(of, "%s: %s\n", key, Yap_TermToBuffer(v, Quote_illegal_f | Ignore_ops_f | Handle_cyclics_f));
242}
243
244static void printErr(yap_error_descriptor_t *i, FILE *out)
245{
246
247 if (i->errorNo == YAP_NO_ERROR)
248 {
249 return;
250 }
251 print_key_s(out, "errorAsText", (i->errorAsText ? i->errorAsText : Yap_errorName(i->errorNo) ));
252 print_key_s(out, "classAsText",
253 (i->classAsText ? i->classAsText: Yap_errorClassName(i->errorClass)));
254 print_key_i(out, "parserPos", i->parserPos);
255 print_key_i(out, "parserLine", i->parserLine);
256 print_key_i(out, "parserFirstLine", i->parserFirstLine);
257 print_key_i(out, "parserLastLine", i->parserLastLine);
258 print_key_s(out, "parserTextA", i->parserTextA);
259 print_key_i(out, "parserTextB", i->parserTextB);
260 print_key_s(out, "parserFile", i->parserFile);
261 print_key_i(out, "errorNo", i->errorNo);
262 print_key_s(out, "errorClass", (i->classAsText ? i->classAsText: Yap_errorClassName(i->errorClass)));
263 print_key_i(out, "errorLine", i->errorLine);
264 print_key_s(out, "errorFunction", i->errorFunction);
265 print_key_s(out, "errorFile", i->errorFile);
266 print_key_i(out, "prologPredLine", i->prologPredLine);
267 print_key_s(out, "prologPredName", i->prologPredName);
268 print_key_i(out, "prologPredArity", i->prologPredArity);
269 print_key_s(out, "prologPredModule", i->prologPredModule);
270 print_key_s(out, "prologPredFile", i->prologPredFile);
271 print_key_b(out, "parserReadingCode", i->parserReadingCode);
272 print_key_b(out, "prologConsulting", i->prologConsulting);
273 print_key_s(out, "culprit", i->culprit);
274 print_key_s(out, "prologStack", i->prologStack);
275 print_key_t(out, "errorUserterm", i->errorUserTerm);
276 print_key_s(out, "errorMsg", i->errorMsg);
277 print_key_i(out, "errorMsgLen", i->errorMsgLen);
278}
279
280static YAP_Term add_key_b(const char *key, bool v, YAP_Term o0)
281{
282 YAP_Term tkv[2];
283 tkv[1] = v ? TermTrue : TermFalse;
284 tkv[0] = MkAtomTerm(Yap_LookupAtom(key));
285 Term node = Yap_MkApplTerm(FunctorEq, 2, tkv);
286 return MkPairTerm(node, o0);
287}
288
289static YAP_Term add_key_i(const char *key, YAP_Int v, YAP_Term o0)
290{
291 YAP_Term tkv[2];
292 tkv[1] = MkIntegerTerm(v), tkv[0] = MkAtomTerm(Yap_LookupAtom(key));
293 Term node = Yap_MkApplTerm(FunctorEq, 2, tkv);
294 return MkPairTerm(node, o0);
295}
296
297static YAP_Term add_key_s(const char *key, const char *v, YAP_Term o0)
298{
299 Term tkv[2];
300 if (!v || v[0]=='\0')
301 return o0;
302 if (v && v)
303 tkv[1] = MkStringTerm(v);
304 tkv[0] = MkAtomTerm(Yap_LookupAtom(key));
305 Term node = Yap_MkApplTerm(FunctorEq, 2, tkv);
306 return MkPairTerm(node, o0);
307}
308
309static YAP_Term add_key_t(const char *key, YAP_Term v, YAP_Term o0)
310{
311 if (!v)
312 return o0;
313 return v;
314}
315
316static Term err2list(yap_error_descriptor_t *i)
317{
318 Term o = TermNil;
319 if (i->errorNo == YAP_NO_ERROR)
320 {
321 return o;
322 }
323 o = add_key_i("errorNo", i->errorNo, o);
324 o = add_key_i("errorClass", i->errorClass, o);
325 o = add_key_s("errorAsText", i->errorAsText, o);
326 o = add_key_s("classAsText", i->classAsText, o);
327 o = add_key_i("errorLine", i->errorLine, o);
328 o = add_key_s("errorFunction", i->errorFunction, o);
329 o = add_key_s("errorFile", i->errorFile, o);
330 o = add_key_i("prologPredLine", i->prologPredLine, o);
331 o = add_key_s("prologPredName", i->prologPredName, o);
332 o = add_key_i("prologPredArity", i->prologPredArity, o);
333 o = add_key_s("prologPredModule", i->prologPredModule, o);
334 o = add_key_s("prologPredFile", i->prologPredFile, o);
335 o = add_key_i("parserPos", i->parserPos, o);
336 o = add_key_i("parserLine", i->parserLine, o);
337 o = add_key_i("parserFirstLine", i->parserFirstLine, o);
338 o = add_key_i("parserLastLine", i->parserLastLine, o);
339 o = add_key_s("parserTextA", i->parserTextA, o);
340 o = add_key_i("parserTextB", i->parserTextB, o);
341 o = add_key_s("parserFile", i->parserFile, o);
342 o = add_key_b("parserReadingCode", i->parserReadingCode, o);
343 o = add_key_b("prologConsulting", i->prologConsulting, o);
344 o = add_key_s("culprit", i->culprit, o);
345 o = add_key_s("prologStack", i->prologStack, o);
346 o = add_key_t("errorUserterm", i->errorUserTerm, o);
347 o = add_key_s("errorMsg", i->errorMsg, o);
348 return o;
349}
350
351void Yap_do_warning__(const char *file, const char *function, int line,
352 yap_error_number type, Term t, ...)
353{
354 CACHE_REGS
355 char tmpbuf[PATH_MAX];
356 va_list ap;
357 PredEntry *p;
358 Term ts[2];
359 const char *fmt;
360 return;
361 yap_error_descriptor_t *e = calloc(1, sizeof(yap_error_descriptor_t));
362 Yap_MkErrorRecord(e, file, function, line, type, t, "discontiguous warning");
363 p = RepPredProp(PredPropByFunc(FunctorPrintMessage,
364 PROLOG_MODULE)); // PROCEDURE_print_message2
365 if (p->ArityOfPE)
366 {
367 //sc[0] = t;
368 // sc[1] = MkSysError(e);
369 va_start(ap, t);
370 fmt = va_arg(ap, char *);
371 if (fmt != NULL)
372 {
373#if HAVE_VSNPRINTF
374 vsnprintf(tmpbuf, PATH_MAX - 1, fmt, ap);
375#else
376 (void)vsprintf(tmpbuf, fmt, ap);
377#endif
378 va_end(ap);
379 ts[1] = MkAtomTerm(AtomWarning);
380 ts[0] = MkAtomTerm(Yap_LookupAtom(tmpbuf));
381 Yap_execute_pred(p, ts, true PASS_REGS);
382 LOCAL_PrologMode &= ~InErrorMode;
383 }
384 }
385}
386
387bool Yap_Warning(const char *s, ...)
388{
389 CACHE_REGS
390 va_list ap;
391 PredEntry *pred;
392 bool rc;
393 Term ts[2];
394 const char *fmt;
395 char tmpbuf[PATH_MAX];
396 yap_error_number err;
397
398 if (LOCAL_DoingUndefp)
399 return false;
400 LOCAL_DoingUndefp = true;
401
402 if (LOCAL_PrologMode & InErrorMode && (err = LOCAL_ActiveError->errorNo))
403 {
404 fprintf(stderr, "%% Warning %s WITHIN ERROR %s %s\n", s,
405 LOCAL_ActiveError->classAsText,
406 LOCAL_ActiveError->errorAsText);
407 return false;
408
409 }
410 LOCAL_PrologMode |= InErrorMode;
411 pred = RepPredProp(PredPropByFunc(FunctorPrintMessage,
412 PROLOG_MODULE)); // PROCEDURE_print_message2
413 va_start(ap, s);
414 fmt = va_arg(ap, char *);
415 if (fmt != NULL)
416 {
417#if HAVE_VSNPRINTF
418 vsnprintf(tmpbuf, PATH_MAX - 1, fmt, ap);
419#else
420 (void)vsprintf(tmpbuf, fmt, ap);
421#endif
422 }
423 else
424 {
425 LOCAL_DoingUndefp = false;
426 LOCAL_PrologMode &= ~InErrorMode;
427 return false;
428 }
429 va_end(ap);
430 if (pred->OpcodeOfPred == UNDEF_OPCODE || pred->OpcodeOfPred == FAIL_OPCODE)
431 {
432 fprintf(stderr, "warning message: %s\n", tmpbuf);
433 LOCAL_DoingUndefp = false;
434 LOCAL_PrologMode &= ~InErrorMode;
435 return false;
436 }
437
438 ts[1] = MkAtomTerm(AtomWarning);
439 ts[0] = MkAtomTerm(Yap_LookupAtom(tmpbuf));
440 rc = Yap_execute_pred(pred, ts, true PASS_REGS);
441 LOCAL_PrologMode &= ~InErrorMode;
442 return rc;
443}
444
445void Yap_InitError__(const char *file, const char *function, int lineno,
446 yap_error_number e, Term t, ...)
447{
448 CACHE_REGS
449 va_list ap;
450 va_start(ap, t);
451 const char *fmt;
452 char *tmpbuf = NULL;
453
454 fmt = va_arg(ap, char *);
455 if (fmt != NULL)
456 {
457 tmpbuf = malloc(PATH_MAX);
458#if HAVE_VSNPRINTF
459 vsnprintf(tmpbuf, PATH_MAX - 1, fmt, ap);
460#else
461 (void)vsprintf(tmpbuf, fmt, ap);
462#endif
463 }
464 else
465 return;
466 va_end(ap);
467 if (LOCAL_ActiveError->errorNo != YAP_NO_ERROR)
468 {
469 yap_error_number err = LOCAL_ActiveError->errorNo;
470 fprintf(stderr, "%% Warning %s WITHIN ERRORR\n", Yap_errorName(err));
471 return;
472 }
473 LOCAL_ActiveError->errorNo = e;
474 LOCAL_ActiveError->errorFile = NULL;
475 LOCAL_ActiveError->errorFunction = NULL;
476 LOCAL_ActiveError->errorLine = 0;
477 if (fmt && fmt[0] && tmpbuf)
478 {
479 LOCAL_ActiveError->errorMsg = malloc(strlen(tmpbuf) + 1);
480 strcpy((char *)LOCAL_ActiveError->errorMsg, tmpbuf);
481 }
482 else
483 { LOCAL_ActiveError->errorMsg = NULL;
484 }
485 ARG1 = TermNil;
486}
487
488bool Yap_PrintWarning(Term twarning)
489{
490 CACHE_REGS
491 if (LOCAL_DoingUndefp)
492 {
493 P = FAILCODE;
494 return false;
495 }
496
497 PredEntry *pred = RepPredProp(PredPropByFunc(
498 FunctorPrintMessage, PROLOG_MODULE)); // PROCEDURE_print_message2;
499 if (twarning)
500 __android_log_print(ANDROID_LOG_INFO, "YAPDroid ", " warning(%s)",
501 Yap_TermToBuffer(twarning, Quote_illegal_f |
502 Ignore_ops_f |
503 Handle_cyclics_f));
504
505 bool rc;
506 if (pred->OpcodeOfPred == UNDEF_OPCODE || pred->OpcodeOfPred == FAIL_OPCODE)
507 {
508 fprintf(stderr, "%s:%ld/* d:%d warning */:\n", LOCAL_ActiveError->errorFile,
509 LOCAL_ActiveError->errorLine, 0);
510 }
511 ARG2 = twarning;
512 ARG1 = MkAtomTerm(AtomWarning);
513 LOCAL_PrologMode &= ~InErrorMode;
514 rc = Yap_execute_pred(pred, NULL, true PASS_REGS);
515 LOCAL_within_print_message = false;
516 return rc;
517}
518
519bool Yap_HandleError__(const char *file, const char *function, int lineno,
520 const char *s, ...)
521{
522 CACHE_REGS
523 yap_error_number err = LOCAL_Error_TYPE;
524 const char *serr;
525
526 if (LOCAL_ErrorMessage)
527 {
528 serr = LOCAL_ErrorMessage;
529 }
530 else
531 {
532 serr = s;
533 }
534 switch (err)
535 {
536 case RESOURCE_ERROR_STACK:
537 if (!Yap_dogc(PASS_REGS1))
538 {
539 Yap_Error__(false, file, function, lineno, RESOURCE_ERROR_STACK, ARG1,
540 serr);
541 return false;
542 }
543 LOCAL_PrologMode = UserMode;
544 return true;
545 case RESOURCE_ERROR_AUXILIARY_STACK:
546 if (LOCAL_MAX_SIZE < (char *)AuxSp - AuxBase)
547 {
548 LOCAL_MAX_SIZE += 1024;
549 }
550 if (!Yap_ExpandPreAllocCodeSpace(0, NULL, TRUE))
551 {
552 /* crash in flames */
553 Yap_Error__(false, file, function, lineno, RESOURCE_ERROR_AUXILIARY_STACK,
554 ARG1, serr);
555 return false;
556 }
557 LOCAL_PrologMode = UserMode;
558 return true;
559 case RESOURCE_ERROR_HEAP:
560 if (!Yap_growheap(FALSE, 0, NULL))
561 {
562 Yap_Error__(false, file, function, lineno, RESOURCE_ERROR_HEAP, ARG2,
563 serr);
564 return false;
565 }
566 default:
567
568 if (LOCAL_PrologMode == UserMode)
569 {
570 Yap_ThrowError__(file, function, lineno, err, 0, NULL);
571 }
572 else
573 LOCAL_PrologMode &= ~InErrorMode;
574 return false;
575 }
576}
577
578int Yap_SWIHandleError(const char *s, ...)
579{
580 CACHE_REGS
581 yap_error_number err = LOCAL_Error_TYPE;
582 char *serr;
583
584 if (s)
585 {
586 serr = (char *)s;
587 }
588 switch (err)
589 {
590 case RESOURCE_ERROR_STACK:
591 if (!Yap_dogc(PASS_REGS1))
592 {
593 Yap_Error(RESOURCE_ERROR_STACK, TermNil, serr);
594 return (FALSE);
595 }
596 return TRUE;
597 case RESOURCE_ERROR_AUXILIARY_STACK:
598 if (LOCAL_MAX_SIZE < (char *)AuxSp - AuxBase)
599 {
600 LOCAL_MAX_SIZE += 1024;
601 }
602 if (!Yap_ExpandPreAllocCodeSpace(0, NULL, TRUE))
603 {
604 /* crash in flames */
605 Yap_Error(RESOURCE_ERROR_AUXILIARY_STACK, ARG1, serr);
606 return FALSE;
607 }
608 return true;
609 case RESOURCE_ERROR_HEAP:
610 if (!Yap_growheap(false, 0, NULL))
611 {
612 Yap_Error(RESOURCE_ERROR_HEAP, ARG2, serr);
613 return false;
614 }
615 default:
616 Yap_Error(err, TermNil, serr);
617 return false;
618 }
619}
620
621static void error_exit_yap(int value)
622{
623 CACHE_REGS
624 if (!(LOCAL_PrologMode & BootMode))
625 {
626
627#if DEBUG
628#endif
629 }
630 fprintf(stderr, "\n Exiting ....\n");
631#if HAVE_BACKTRACE
632 void *callstack = malloc(64 * K);
633 int i;
634 int frames = backtrace(callstack, 64 * K - 1);
635 char **strs = backtrace_symbols(callstack, frames);
636 fprintf(stderr, "%% C-Execution stack:\n");
637 for (i = 0; i < frames; ++i)
638 {
639 fprintf(stderr, "%% %s\n", strs[i]);
640 }
641 free(strs);
642#endif
643 Yap_exit(value);
644}
645
646/* This needs to be a static because I can't trust the stack (WIN32), and
647 I can't trust the Yap stacks (error) */
648#define YAP_BUF_SIZE 512
649
650static char tmpbuf[YAP_BUF_SIZE];
651
652// error classes: based on OSI errors.
653//
654// - The extra argument says whether there different instances
655//
656// - Events are treated within the same pipeline as errors.
657//
658
659#undef BEGIN_ERROR_CLASSES
660#undef ECLASS
661#undef END_ERROR_CLASSES
662#undef BEGIN_ERRORS
663#undef E0
664#undef E
665#undef E1
666#undef E2
667#undef END_ERRORS
668
669#define BEGIN_ERROR_CLASSES() \
670 static Atom mkerrorct(yap_error_class_number c) \
671 { \
672 switch (c) \
673 {
674
675#define ECLASS(CL, A, B) \
676 case CL: \
677 return Yap_LookupAtom(A);
678
679#define END_ERROR_CLASSES() \
680 } \
681 return NULL; \
682 }
683
684#define BEGIN_ERRORS() \
685 static Term mkerrort(yap_error_number e, Term culprit, Term info) \
686 { \
687 if (!e) e= USER_DEFINED_ERROR; \
688 if (!info) info = TermNil; \
689 switch (e) \
690 {
691
692#define E0(A, B, C) \
693 case A: \
694 { \
695 Term ft[2]; \
696 ft[0] = MkAtomTerm(Yap_LookupAtom(C "_error")); \
697 ft[1] = info; \
698 return Yap_MkApplTerm(FunctorError, 2, ft); \
699 }
700
701#define E(A, B, C) \
702 case A: \
703 { \
704 Term ft[2], nt[2]; \
705 nt[0] = MkAtomTerm(Yap_LookupAtom(C)); \
706 nt[1] = MkVarTerm(); \
707 if (culprit) Yap_unify(nt[1], culprit); \
708 ft[0] = Yap_MkApplTerm(Yap_MkFunctor(mkerrorct(B), 2), 2, nt); \
709 ft[1] = info; \
710 return Yap_MkApplTerm(FunctorError, 2, ft); \
711 }
712
713#define E1(A, B, C) \
714 case A: \
715 { \
716 Term ft[2], nt[1]; \
717 nt[0] = MkVarTerm(); \
718 if (culprit) Yap_unify(nt[0], culprit); \
719 ft[0] = Yap_MkApplTerm(Yap_MkFunctor(Yap_LookupAtom(C), 1), 1, nt); \
720 ft[1] = info; \
721 return Yap_MkApplTerm(FunctorError, 2, ft); \
722 }
723
724#define E2(A, B, C, D) \
725 case A: \
726 { \
727 Term ft[2], nt[3]; \
728 nt[0] = MkAtomTerm(Yap_LookupAtom(C)); \
729 nt[1] = MkAtomTerm(Yap_LookupAtom(D)); \
730 nt[2] = MkVarTerm(); \
731 if (culprit) Yap_unify(nt[2], culprit); \
732 ft[0] = Yap_MkApplTerm(Yap_MkFunctor(mkerrorct(B), 3), 3, nt); \
733 ft[1] = info; \
734 return Yap_MkApplTerm(FunctorError, 2, ft); \
735 }
736
737#define END_ERRORS() \
738 } \
739 return TermNil; \
740 }
741
742#include "YapErrors.h"
743
747{
748
749 memset(new_error, 0, sizeof(yap_error_descriptor_t));
750 if (link)
751 new_error->top_error = LOCAL_ActiveError;
752 LOCAL_ActiveError = new_error;
753 return old_error;
754}
755
756/* static void */
757/* reset_error_description(void) { */
758/* yap_error_descriptor_t *bf = LOCAL_ActiveError->top_error; */
759/* if (Yap_HasException()) */
760/* memset(LOCAL_ActiveError, 0, sizeof(*LOCAL_ActiveError)); */
761/* LOCAL_ActiveError->top_error = bf; */
762/* } */
763yap_error_descriptor_t *Yap_popErrorContext(bool mdnew, bool pass, yap_error_descriptor_t *old_error)
764{
765 yap_error_descriptor_t *e = LOCAL_ActiveError,
766 *ep = LOCAL_ActiveError->top_error;
767 // last block
768 LOCAL_ActiveError = ep;
769 if (e->errorNo && !ep->errorNo && pass)
770 {
771 yap_error_descriptor_t *epp = ep->top_error;
772 memmove(ep, e, sizeof(*e));
773 ep->top_error = epp;
774 }
775 return old_error;
776}
777
778
779
789void Yap_ThrowError__(const char *file, const char *function, int lineno,
790 yap_error_number type, Term where, const char *msg, ...)
791{
792 va_list ap;
793 char tmpbuf[PATH_MAX];
794
795 if ( LOCAL_ActiveError->errorNo)
796 {
797
798 fprintf(stderr, "%s:%d:0 %s() caused a %s while processing error or warning!!!!!\n\n", file, lineno, function, Yap_errorName(type));
799 return;
800 }
801 else
802 {
803 LOCAL_ActiveError->errorUserTerm = 0 ;
804 if (msg != NULL)
805 {
806 va_start(ap,msg);
807#if HAVE_VSNPRINTF
808 (void)vsnprintf(tmpbuf, PATH_MAX - 1, msg, ap);
809#else
810 (void)vsprintf(tmpbuf, mag, ap);
811#endif
812
813 }
814 else
815 {
816 tmpbuf[0] = '\0';
817
818 }
819 Yap_Error__(true, file, function, lineno, type, where, tmpbuf);
820 }
821
822 Yap_ThrowExistingError();
823
824}
825
826// complete delayed error.
827
828void Yap_ThrowExistingError(void)
829{
830 if (LOCAL_RestartEnv ||
831 IsNonVarTerm(Yap_GetGlobal(AtomZip)))
832 {
833 P = FAILCODE;
834 Yap_RestartYap(5);
835 }
836 Yap_exit(5);
837}
838
840
842{
843 Term et = MkAddressTerm(i);
844 return Yap_MkApplTerm(FunctorException, 1, &et);
845}
846
847
854{
855 if (i == NULL)
856 i = (Yap_local.ActiveError);
857
858 memset(i,0, sizeof(*Yap_local.ActiveError));
859 if (i->errorNo != USER_DEFINED_ERROR) {
860 i->errorAsText = Yap_errorName(i->errorNo);
861 i->errorClass = Yap_errorClass(i->errorNo);
862 i->classAsText = Yap_errorClassName(i->errorClass);
863 }
864 Term culprit = TermNil;
865
866 if (i->culprit_t)
867 culprit = i->culprit_t;
868 else if (i->culprit_t)
869 culprit = Yap_BufferToTerm(i->culprit, TermNil);
870 else if (i->errorMsg)
871 culprit = MkStringTerm(i->errorMsg);
872
873 return mkerrort(i->errorNo, culprit, MkSysError(i));
874
875}
876
883 const char *function, int lineno, yap_error_number type,
884 Term where, const char *s)
885{
886 if (!Yap_pc_add_location(r, P, B, ENV))
887 Yap_env_add_location(r, CP, B, ENV, 0);
888 if (where == 0L )
889 {
890 r->culprit_t = TermNone;
891 r->culprit = NULL;
892 }
893 else
894 {
895 r->culprit_t = Yap_SaveTerm(where);
896 r->culprit = Yap_TermToBuffer(where, Quote_illegal_f | Handle_vars_f | Handle_cyclics_f);
897 }
898 if (type != SYNTAX_ERROR && LOCAL_consult_level > 0)
899 {
900 r->parserFile = Yap_ConsultingFile(PASS_REGS1)->StrOfAE;
901 r->parserLine = Yap_source_line_no();
902 r->parserPos = Yap_source_line_pos();
903 } else {
904 r->parserFile = NULL;
905 r->parserLine = 1;
906 r->parserPos = 0;
907 }
908 r->errorNo = type;
909 r->errorAsText = Yap_errorName(type);
910 r->errorClass = Yap_errorClass(type);
911 r->classAsText = Yap_errorClassName(r->errorClass);
912 r->errorLine = lineno;
913 r->errorFunction = function;
914 r->errorFile = file;
915 r->prologConsulting = Yap_ConsultingFile();
916 LOCAL_PrologMode |= InErrorMode;
917 Yap_ClearExs();
918 // first, obtain current location
919
920#if 0
921 sprintf(LOCAL_FileNameBuf, "%s:%d in C-function %s ", file, lineno,
922 function);
923 tf = MkAtomTerm(Yap_LookupAtom(LOCAL_FileNameBuf));
924#if DEBUG_STRICT
925 if (Yap_heap_regs && !(LOCAL_PrologMode & BootMode))
926 fprintf(stderr, "***** Processing Error %d (%lx,%x) %s***\n", type,
927 (unsigned long int)LOCAL_Signals, LOCAL_PrologMode, fmt);
928 else
929 fprintf(stderr, "***** Processing Error %d (%x) %s***\n", type,
930 LOCAL_PrologMode, fmt);
931#endif
932#endif
933 if (r->errorNo == SYNTAX_ERROR)
934 {
935 r->errorClass = SYNTAX_ERROR_CLASS;
936 }
937 else if (r->errorNo == SYNTAX_ERROR_NUMBER)
938 {
939 r->errorClass = SYNTAX_ERROR_CLASS;
940 r->errorNo = SYNTAX_ERROR;
941 }
942 if (type == INTERRUPT_EVENT)
943 {
944 fprintf(stderr, "%% YAP exiting: cannot handle signal %d\n",
945 (int)IntOfTerm(where));
946 Yap_exit(1);
947 }
948 if (s && s[0])
949 {
950 char *ns;
951 ns = malloc(strlen(s)+1);
952 strcpy(ns, s);
953 r->errorMsg = ns;
954 }
955 else
956 {
957 r->errorMsg = 0;
958 }
959 return true;
960}
981yamop *Yap_Error__(bool throw, const char *file, const char *function,
982 int lineno, yap_error_number type, Term where, ...)
983{
984 CACHE_REGS
985 va_list ap;
986 char *fmt;
987 char *s = NULL;
988
989 switch (type)
990 {
991 case SYSTEM_ERROR_INTERNAL:
992 {
993 fprintf(stderr, "%% Internal YAP Error: %s exiting....\n", tmpbuf);
994 if (LOCAL_PrologMode & BootMode)
995 {
996 fprintf(stderr, "%% YAP crashed while booting %s\n", tmpbuf);
997 }
998 else
999 {
1000 if (tmpbuf[0])
1001 {
1002 fprintf(stderr, "%% Bug found while executing %s\n", tmpbuf);
1003 }
1004#if HAVE_BACKTRACE
1005 void *callstack[256];
1006 int i;
1007 int frames = backtrace(callstack, 256);
1008 char **strs = backtrace_symbols(callstack, frames);
1009 fprintf(stderr, "Execution stack:\n");
1010 for (i = 0; i < frames; ++i)
1011 {
1012 fprintf(stderr, " %s\n", strs[i]);
1013 }
1014 free(strs);
1015#endif
1016 }
1017 error_exit_yap(1);
1018 }
1019 case SYSTEM_ERROR_FATAL:
1020 {
1021 fprintf(stderr, "%% Fatal YAP Error: %s exiting....\n", tmpbuf);
1022 error_exit_yap(1);
1023 }
1024 case INTERRUPT_EVENT:
1025 {
1026 error_exit_yap(1);
1027 }
1028 case USER_DEFINED_EVENT:
1029 case THROW_EVENT:
1030 {
1031 LOCAL_ActiveError->errorUserTerm = TermNil;
1032 }
1033 break;
1034 case ABORT_EVENT:
1035 {
1036 // fun = FunctorDollarVar;
1037 // serious = true;
1038 LOCAL_ActiveError->errorNo = ABORT_EVENT;
1039 P = FAILCODE;
1040 LOCAL_PrologMode &= ~InErrorMode;
1041 }
1042 break;
1043 case CALL_COUNTER_UNDERFLOW_EVENT:
1044 // Do a long jump
1045 LOCAL_ReductionsCounterOn = FALSE;
1046 LOCAL_PredEntriesCounterOn = FALSE;
1047 LOCAL_RetriesCounterOn = FALSE;
1048 LOCAL_ActiveError->errorNo = CALL_COUNTER_UNDERFLOW_EVENT;
1049 Yap_JumpToEnv();
1050 P = FAILCODE;
1051 LOCAL_PrologMode &= ~InErrorMode;
1052 return P;
1053 case PRED_ENTRY_COUNTER_UNDERFLOW_EVENT:
1054 // Do a long jump
1055 LOCAL_ReductionsCounterOn = FALSE;
1056 LOCAL_PredEntriesCounterOn = FALSE;
1057 LOCAL_RetriesCounterOn = FALSE;
1058 LOCAL_ActiveError->errorNo = PRED_ENTRY_COUNTER_UNDERFLOW_EVENT;
1059 Yap_JumpToEnv();
1060 P = FAILCODE;
1061 LOCAL_PrologMode &= ~InErrorMode;
1062 return P;
1063 case RETRY_COUNTER_UNDERFLOW_EVENT:
1064 // Do a long jump
1065 LOCAL_ReductionsCounterOn = FALSE;
1066 LOCAL_PredEntriesCounterOn = FALSE;
1067 LOCAL_RetriesCounterOn = FALSE;
1068 LOCAL_ActiveError->errorNo = RETRY_COUNTER_UNDERFLOW_EVENT;
1069 Yap_JumpToEnv();
1070 P = FAILCODE;
1071 LOCAL_PrologMode &= ~InErrorMode;
1072 return P;
1073 default:
1074 va_start(ap, where);
1075 fmt = va_arg(ap, char *);
1076 if (fmt != NULL)
1077 {
1078 s = malloc(PATH_MAX);
1079#if HAVE_VSNPRINTF
1080 (void)vsnprintf(s, PATH_MAX - 1, fmt, ap);
1081#else
1082 (void)vsprintf(s, fmt, ap);
1083#endif
1084 va_end(ap);
1085 break;
1086 }
1087 }
1088 Yap_MkErrorRecord(LOCAL_ActiveError, file, function, lineno, type, where, s);
1089 if (P == (yamop *)(FAILCODE))
1090 {
1091 LOCAL_PrologMode &= ~InErrorMode;
1092 return P;
1093 }
1094 // PURE_ABORT may not have set where correctly, BootMode may not have the data
1095 // terms ready
1096 if (type == ABORT_EVENT || LOCAL_PrologMode & BootMode)
1097 {
1098 LOCAL_PrologMode &= ~AbortMode;
1099 LOCAL_PrologMode &= ~InErrorMode;
1100 // make sure failure will be seen at next port
1101 // no need to lock & unlock
1102 if (LOCAL_PrologMode & AsyncIntMode)
1103 Yap_signal(YAP_FAIL_SIGNAL);
1104 P = FAILCODE;
1105 }
1106 else
1107 {
1108 // Exit Abort Mode, if we were there
1109 LOCAL_PrologMode &= ~AbortMode;
1110 LOCAL_PrologMode |= InErrorMode;
1111 }
1112
1113#ifdef DEBUG
1114 //DumpActiveGoals( USES_REGS1 );
1115#endif // DEBUG
1116#if 0
1117 if (LOCAL_ActiveError->errorNo != SYNTAX_ERROR &&
1118 trueLocalPrologFlag(STACK_DUMP_ON_ERROR_FLAG) )
1119 LOCAL_ActiveError->prologStack = Yap_dump_stack();
1120#else
1121 LOCAL_ActiveError->prologStack = NULL;
1122#endif
1123 CalculateStackGap(PASS_REGS1);
1124#if DEBUG
1125 //DumpActiveGoals( PASS_REGS1 );
1126#endif
1127 //wait if we we are in user code,
1128 // it's up to her to decide
1129 if (LOCAL_delay)
1130 return P;
1131 if (LOCAL_DoingUndefp)
1132 {
1133 LOCAL_DoingUndefp = false;
1134 LOCAL_Signals = 0;
1135 // yap_error_descriptor_t *co = CopyException(LOCAL_ActiveError);
1136 Yap_PrintWarning(Yap_MkFullError(NULL));
1137 return P;
1138 }
1139 if (!LOCAL_ActiveError) {
1140 LOCAL_ActiveError = Yap_GetException();
1141 }
1142 Yap_JumpToEnv();
1143 // reset_error_description();
1144 pop_text_stack(LOCAL_MallocDepth + 1);
1145 if (throw)
1146 {
1147 LOCAL_Error_TYPE = type;
1149 } else {
1150 LOCAL_Error_TYPE = YAP_NO_ERROR;
1151 LOCAL_ActiveError->culprit = NULL;
1152
1153
1154
1155
1156 LOCAL_PrologMode = UserMode;
1157 }
1158 return P;
1159}
1160
1161static Int close_error(USES_REGS1)
1162{
1163 if (!LOCAL_CommittedError)
1164 return true;
1165 LOCAL_CommittedError->errorNo = YAP_NO_ERROR;
1166 memset(LOCAL_CommittedError, 0, sizeof(yap_error_descriptor_t));
1167 LOCAL_ErrorMessage = NULL;
1168 free(LOCAL_CommittedError);
1169 LOCAL_CommittedError = NULL;
1170 return true;
1171}
1172
1173#undef BEGIN_ERROR_CLASSES
1174#undef ECLASS
1175#undef END_ERROR_CLASSES
1176#undef BEGIN_ERRORS
1177#undef E0
1178#undef E
1179#undef E1
1180#undef E2
1181#undef END_ERRORS
1182
1183#define BEGIN_ERROR_CLASSES() typedef enum aux_class \
1184 {
1185
1186#define ECLASS(CL, A, B) CL##__,
1187
1188#define END_ERROR_CLASSES() \
1189 } \
1190 aux_class_t;
1191
1192#define BEGIN_ERRORS()
1193#define E0(X, Y, Z)
1194#define E(X, Y, Z)
1195#define E1(X, Y, Z)
1196#define E2(X, Y, Z, W)
1197#define END_ERRORS()
1198
1199#include <YapErrors.h>
1200
1201#undef BEGIN_ERROR_CLASSES
1202#undef ECLASS
1203#undef END_ERROR_CLASSES
1204#undef BEGIN_ERRORS
1205#undef E0
1206#undef E
1207#undef E1
1208#undef E2
1209#undef END_ERRORS
1210
1211#define BEGIN_ERROR_CLASSES() static const char *c_error_class_name[] = {
1212
1213#define ECLASS(CL, A, B) A,
1214
1215#define END_ERROR_CLASSES() \
1216 NULL \
1217 }
1218
1219typedef struct c_error_info
1220{
1221 int errnb;
1222 int class;
1223 const char *name;
1224} c_error_t;
1225
1226#define BEGIN_ERRORS() static struct c_error_info c_error_list[] = {
1227#define E0(X, Y, Z) {X, Y##__, Z},
1228#define E(X, Y, Z) {X, Y##__, Z},
1229#define E1(X, Y, Z) {X, Y##__, Z},
1230#define E2(X, Y, Z, W) {X, Y##__, Z " " W},
1231#define END_ERRORS() \
1232 { \
1233 0, YAPC_NO_ERROR, "" \
1234 } \
1235 } \
1236 ;
1237
1238#include <YapErrors.h>
1239#include <iopreds.h>
1240
1241yap_error_class_number Yap_errorClass(yap_error_number e)
1242{
1243 return c_error_list[e].class;
1244}
1245
1246yap_error_class_number Yap_errorClassNumber(const char *s)
1247{
1248 Int i = 1;
1249 while (c_error_class_name[i] &&
1250 strcmp(c_error_class_name[i], s) != 0)
1251 {
1252 i++;
1253 }
1254 if (!c_error_class_name[i])
1255 return USER_DEFINED_ERROR_CLASS;
1256 return i;
1257}
1258char *Yap_errorClassName(yap_error_class_number e)
1259{
1260 return (char *)c_error_class_name[e];
1261}
1262
1263static Int reset_exception(USES_REGS1) { return Yap_ResetException(NULL); }
1264
1265Term MkErrorTerm(yap_error_descriptor_t *t)
1266{
1267 if (t==NULL) {
1268 t = LOCAL_ActiveError;
1269 }
1270 if (t->errorUserTerm)
1271 return t->errorUserTerm;
1272 /* if (t->errorNo == THROW_EVENT || t->errorNo == ERROR_EVENT) */
1273/* { */
1274/* if (t->errorMsg) */
1275/* return Yap_BufferToTerm(t->errorMsg, TermNil); */
1276/* } */
1277
1278 Term tc = t->culprit_t ? t->culprit_t :
1279 t->culprit ? Yap_BufferToTerm(t->culprit, TermNil) : TermNone;
1280 if (IsVarTerm(tc)) tc=TermNil;
1281 Term o;
1282 if (t->errorNo == USER_DEFINED_ERROR) {
1283 Term ft[2];
1284 ft[0] = tc;
1285 ft[1] = err2list(t);
1286 o = Yap_MkApplTerm(FunctorError, 2, ft);
1287 } else {
1288 o = mkerrort(t->errorNo, tc, err2list(t));
1289 }
1290 return o;
1291}
1292
1293
1294
1295Term Yap_MkPrologError(Term t, yap_error_descriptor_t * i)
1296{
1297
1298
1299 if (i == NULL)
1300 i = LOCAL_ActiveError;
1301 if (!IsApplTerm(t) || FunctorOfTerm(t) != FunctorError)
1302 return t;
1303 i->errorUserTerm = Yap_SaveTerm(t);
1304 i->errorNo = THROW_EVENT;
1305 /* just allow the easy way out, if needed */
1306 if (IsApplTerm(t) && FunctorOfTerm(t) == FunctorError) {
1307 Term t1 = ArgOfTerm(1, t);
1308 i->errorClass = USER_DEFINED_ERROR_CLASS;
1309 i->errorNo = USER_DEFINED_ERROR;
1310 if (IsAtomTerm(t1)) {
1311 i->classAsText = i->errorAsText = RepAtom(AtomOfTerm(t1))->StrOfAE;
1312 i->errorClass = Yap_errorClassNumber(i->classAsText);
1313 if (i->errorClass == INSTANTIATION_ERROR_CLASS)
1314 i->errorNo = INSTANTIATION_ERROR;
1315 } else if (IsApplTerm(t1)) {
1316 char *s1 = NULL;
1317 Functor f = FunctorOfTerm(t1);
1318 arity_t a = ArityOfFunctor(f);
1319 i->classAsText = RepAtom(NameOfFunctor(f))->StrOfAE;
1320 i->errorClass = Yap_errorClassNumber(i->classAsText);
1321 Term t11 = ArgOfTerm(1, t1);
1322 if (IsAtomTerm(t11)) {
1323 i->errorAsText = RepAtom(AtomOfTerm(t11))->StrOfAE;
1324 i->errorNo = Yap_errorNumber(i->errorClass, i->errorAsText);
1325}
1326 char *s2 = NULL;
1327 s1 = i->errorAsText;
1328 if (a == 1) {
1329 i->errorAsText = i->classAsText;
1330 } else if (a == 3) {
1331 Term t12 = ArgOfTerm(2, t1);
1332 if (IsAtomTerm(t12)) {
1333 s2 = RepAtom(AtomOfTerm(t12))->StrOfAE;
1334 char *buf = i->errorAsText = malloc(strlen(s1) + strlen(s2) + 2);
1335 strcpy(buf, s1);
1336 strcat(buf, " ");
1337 strcat(buf, s2);
1338 i->errorNo = Yap_errorNumber(i->errorClass, i->errorAsText);
1339
1340 }
1341 } else if (IsAtomTerm(t11)) { // a ==2
1342
1343 i->errorNo = Yap_errorNumber(i->errorClass, i->errorAsText);
1344 }
1345 }
1346 }
1347 return 0;
1348 }
1349
1350
1378{
1379 CACHE_REGS
1380 if (LOCAL_ActiveError->errorNo)
1381 return LOCAL_ActiveError;
1382 else
1383 return NULL;
1384}
1385
1390{
1391 CACHE_REGS
1392 yap_error_descriptor_t *t = LOCAL_ActiveError,
1393 *nt = calloc(1, sizeof(yap_error_descriptor_t));
1394 memmove(nt, t, sizeof(yap_error_descriptor_t));
1395 return nt;
1396}
1397
1402{
1403 FILE *of = GLOBAL_Stream[LOCAL_c_output_stream].file ? GLOBAL_Stream[LOCAL_c_output_stream].file : stderr;
1404 printErr(LOCAL_ActiveError, of);
1405}
1406
1411{
1412 if (LOCAL_ActiveError->errorNo) {
1413 P=FAILCODE;
1414 Yap_JumpToEnv();
1415 Yap_RestartYap(5);
1416 // DsBTerm *dbt = Yap_RefToException();
1417 return true;
1418 }
1419 return false;
1420}
1421
1426{
1427 // reset error descriptor
1428 if (!i)
1429 i = LOCAL_ActiveError;
1430 i = memset(i, 0, sizeof(yap_error_descriptor_t));
1431 LOCAL_PrologMode &= ~InErrorMode;
1432 return true;
1433}
1434
1439{
1440 // reset error descriptor
1441 memcpy(LOCAL_ActiveError, i, sizeof(yap_error_descriptor_t));
1442 LOCAL_PrologMode |= InErrorMode;
1443 return true;
1444}
1445
1446static Int read_exception(USES_REGS1)
1447{
1448 yap_error_descriptor_t *t = AddressOfTerm(Deref(ARG1));
1449 if (t==nullptr)
1450 return false;
1451 Term rc = err2list(t);
1452 // Yap_DebugPlWriteln(rc);
1453 return Yap_unify(ARG2, rc);
1454}
1455
1456static Int print_exception(USES_REGS1)
1457{
1458 Term t1 = Deref(ARG1);
1459 if (IsAddressTerm(t1))
1460 {
1461 FILE *of = GLOBAL_Stream[LOCAL_c_error_stream].file ? GLOBAL_Stream[LOCAL_c_error_stream].file : stderr;
1462 yap_error_descriptor_t *t = AddressOfTerm(t1);
1463 if (t->parserFile && t->parserLine)
1464 {
1465 fprintf(of, "\n%s:%ld:0 error: while parsing %s\n\n", t->parserFile,
1466 t->parserLine, t->errorAsText);
1467 }
1468 else if (t->prologPredFile && t->prologPredLine)
1469 {
1470 fprintf(of, "\n%s:%ld:0 error: while running %s\n\n",
1471 t->prologPredFile, t->prologPredLine, t->errorAsText);
1472 }
1473 else if (t->errorFile && t->errorLine)
1474 {
1475 fprintf(of, "\n%s:%ld:0 error: while executing %s\n\n", t->errorFile,
1476 t->errorLine, t->errorAsText);
1477 }
1478 printErr(t, of);
1479 }
1480 else
1481 {
1482 return Yap_WriteTerm(LOCAL_c_error_stream, t1, TermNil PASS_REGS);
1483 }
1484 // Yap_DebugPlWriteln(rc);
1485 return true;
1486}
1487
1488static Int query_exception(USES_REGS1)
1489{
1490 const char *query = NULL;
1491 Term t;
1492
1493 if (IsAtomTerm((t = Deref(ARG1))))
1494 query = RepAtom(AtomOfTerm(t))->StrOfAE;
1495 if (IsStringTerm(t))
1496 query = StringOfTerm(t);
1497 if (!IsAddressTerm(Deref(ARG2)))
1498 return false;
1499 yap_error_descriptor_t *y = AddressOfTerm(Deref(ARG2));
1500 // if (IsVarTerm(t3)) {
1501 Term rc = queryErr(query, y);
1502 // Yap_DebugPlWriteln(rc);
1503 return Yap_unify(ARG3, rc);
1504 // } else {
1505 // return setErr(query, y, t3);
1506 // }
1507}
1508
1509static Int set_exception(USES_REGS1)
1510{
1511 const char *query = NULL;
1512 Term t;
1513
1514 if (IsAtomTerm((t = Deref(ARG1))))
1515 query = RepAtom(AtomOfTerm(t))->StrOfAE;
1516 if (IsStringTerm(t))
1517 query = StringOfTerm(t);
1518 if (!IsAddressTerm(Deref(ARG1)))
1519 return false;
1520 yap_error_descriptor_t *y = AddressOfTerm(Deref(ARG2));
1521 Term t3 = Deref(ARG3);
1522 if (IsVarTerm(t3))
1523 {
1524 return false;
1525 }
1526 else
1527 {
1528 return setErr(query, y, t3);
1529 }
1530}
1531
1532static Int
1533drop_exception(USES_REGS1)
1534{
1535 Term tn;
1536 bool rc=false;
1537 if (LOCAL_Error_TYPE) {
1538 if ( LOCAL_ActiveError->errorNo != USER_DEFINED_ERROR &&
1539 LOCAL_ActiveError->errorUserTerm) {
1540 rc = Yap_unify(LOCAL_ActiveError->errorUserTerm, ARG1);
1541 } else { tn = MkErrorTerm(LOCAL_ActiveError);
1542
1543 rc = Yap_unify(tn, ARG1);
1544 }
1545
1546 memset(LOCAL_ActiveError, 0, sizeof(*LOCAL_ActiveError));
1547 }
1548 LOCAL_PrologMode &= ~InErrorMode;
1549 return rc;
1550}
1551
1552static Int new_exception(USES_REGS1)
1553{
1554 Term t =MkSysError(calloc(1, sizeof(yap_error_descriptor_t)));
1555 return Yap_unify(ARG1, t);
1556}
1557
1558bool Yap_get_exception(USES_REGS1)
1559{
1560 Term tn = Yap_GetGlobal(AtomZip);
1561 if (!IsVarTerm(tn) && tn != TermNil)
1562 return true;
1563 return false;
1564}
1565
1570yap_error_number Yap_errorNumber(yap_error_class_number c, const char *s)
1571{
1572 Int i = 1;
1573
1574 while (c_error_list[i].name)
1575 {
1576 if (c_error_list[i].class == USER_DEFINED_ERROR_CLASS)
1577 // we will never find it, but we found it!
1578 return USER_DEFINED_ERROR;
1579 if (c_error_list[i].class != c)
1580 {
1581 i++;
1582 continue;
1583 }
1584 // same class
1585 if (strcmp(c_error_list[i].name, s) == 0)
1586 // found it!
1587 break;
1588 i++;
1589 }
1590 return i;
1591}
1592
1593char *Yap_errorName(yap_error_number e) {if (e != USER_DEFINED_ERROR)
1594 return (char*)c_error_list[e].name;
1595 return NULL;}
1596
1598{
1599 i->errorNo = ERROR_EVENT;
1600 i->errorClass = EVENT;
1601
1602 return i;
1603}
1604
1608/* @addtogroup ErrorBuiltins
1609
1610@{
1611
1612*/
1613
1614Int is_nonvar__(const char *file, const char *function, int lineno, Term t USES_REGS)
1615{
1616 // Term Context = Deref(ARG2)Yap_Error(INSTANTIATION_ERROR, t, NULL);;
1617 if (IsVarTerm(t))
1618 {
1619 Yap_ThrowError(INSTANTIATION_ERROR, t, NULL);
1620 return false;
1621 }
1622 return t == TermTrue || t == TermFalse;
1623}
1624
1631static Int is_nonvar1(USES_REGS1)
1632{
1633 Term t = Deref(ARG1);
1634 return is_nonvar__(__FILE__,__FUNCTION__,__LINE__,t PASS_REGS);
1635}
1636
1637bool is_boolean__(const char *file, const char *function, int lineno, Term t USES_REGS)
1638{
1639 // Term Context = Deref(ARG2)Yap_Error(INSTANTIATION_ERROR, t, NULL);;
1640 if (IsVarTerm(t))
1641 {
1642 Yap_ThrowError__(file, function, lineno, INSTANTIATION_ERROR, t, NULL);
1643 return false;
1644 }
1645 return t == TermTrue || t == TermFalse;
1646}
1647
1648static Int is_boolean1(USES_REGS1)
1649{
1650 Term t = Deref(ARG1);
1651 return is_boolean__(__FILE__,__FUNCTION__,__LINE__,t PASS_REGS);
1652}
1653
1654bool must_be_boolean__(const char *file, const char *function, int lineno, Term t USES_REGS)
1655{
1656 // Term Context = Deref(ARG2)Yap_Error(INSTANTIATION_ERROR, t, NULL);;
1657 if (IsVarTerm(t))
1658 {
1659 Yap_ThrowError__(file, function, lineno, INSTANTIATION_ERROR, t, NULL);
1660 return false;
1661 }
1662 if ( t == TermTrue || t == TermFalse )
1663 return true;
1664 else {
1665 Yap_ThrowError__(file, function, lineno, TYPE_ERROR_BOOLEAN, t, NULL);
1666 return false;
1667 }
1668
1669}
1670
1671static Int must_be_boolean1(USES_REGS1)
1672{
1673 Term t = Deref(ARG1);
1674 return must_be_boolean__(__FILE__,__FUNCTION__,__LINE__,t PASS_REGS);
1675}
1676
1677
1678bool is_atom__(const char *file, const char *function, int lineno, Term t USES_REGS)
1679{
1680 // Term Context = Deref(ARG2)Yap_Error(INSTANTIATION_ERROR, t, NULL);;
1681 if (IsVarTerm(t))
1682 {
1683 Yap_ThrowError__( file, function, lineno, INSTANTIATION_ERROR, t, NULL);
1684 return false;
1685 }
1686 return IsAtomTerm(t);
1687}
1688
1689static Int is_atom1( USES_REGS1 )
1690{
1691 Term t = Deref(ARG1);
1692 return is_atom__(__FILE__,__FUNCTION__,__LINE__,t PASS_REGS);
1693}
1694
1695
1696bool must_be_atom__(const char *file, const char *function, int lineno, Term t USES_REGS)
1697{
1698 // Term Context = Deref(ARG2)Yap_Error(INSTANTIATION_ERROR, t, NULL);;
1699 if (IsVarTerm(t))
1700 {
1701 Yap_ThrowError__( file, function, lineno, INSTANTIATION_ERROR, t, NULL);
1702 return false;
1703 }
1704 if (IsAtomTerm(t))
1705 return true;
1706 else {
1707 Yap_ThrowError__(file, function, lineno, TYPE_ERROR_ATOM, t, NULL);
1708 return false;
1709 }
1710}
1711
1712static Int must_be_atom1( USES_REGS1 )
1713{
1714 Term t = Deref(ARG1);
1715 return must_be_atom__(__FILE__,__FUNCTION__,__LINE__,t PASS_REGS);
1716}
1717
1724bool is_list__(const char *file, const char *function, int lineno, Term list USES_REGS)
1725{
1726 Term *tailp;
1727 // Term Context = Deref(ARG2);
1728 Int n = Yap_SkipList(&list, &tailp);
1729 if (IsVarTerm(*tailp))
1730 Yap_ThrowError__(file, function, lineno, INSTANTIATION_ERROR, list, NULL);
1731 if (*tailp != TermNil || n < 0)
1732 {
1733 return false;
1734 }
1735 return true;
1736}
1737
1738static Int is_list1( USES_REGS1 )
1739{
1740 Term t = Deref(ARG1);
1741 return is_list__(__FILE__,__FUNCTION__,__LINE__,t PASS_REGS);
1742}
1743
1744bool must_be_list__(const char *file, const char *function, int lineno, Term list USES_REGS)
1745{
1746 Term *tailp;
1747 // Term Context = Deref(ARG2);
1748 Int n = Yap_SkipList(&list, &tailp);
1749 if (IsVarTerm(*tailp))
1750 Yap_ThrowError__(file, function, lineno, INSTANTIATION_ERROR, list, NULL);
1751 if (*tailp != TermNil || n < 0)
1752 {
1753 return false;
1754 }
1755 return true;
1756}
1757
1758static Int must_be_list1( USES_REGS1 )
1759{
1760 Term t = Deref(ARG1);
1761 return must_be_list__(__FILE__,__FUNCTION__,__LINE__,t PASS_REGS);
1762}
1763
1771Int callable(USES_REGS1)
1772{
1773 Term t = Deref(ARG1);
1774 if (IsVarTerm(t))
1775 {
1776
1777 return false;
1778 }
1779 Term mod = CurrentModule;
1780 if (mod == 0)
1781 mod = TermProlog;
1782 Term G = Yap_StripModule(Deref(ARG1), &mod);
1783 // Term Context = Deref(ARG2);
1784 if (IsVarTerm(mod))
1785 {
1786 return false;
1787 }
1788 else if (!IsAtomTerm(mod))
1789 {
1790 return false;
1791 }
1792 if (IsVarTerm(G))
1793 {
1794 return false;
1795 }
1796 if (IsApplTerm(G))
1797 {
1798 Functor f = FunctorOfTerm(G);
1799 if (IsExtensionFunctor(f))
1800 {
1801 return false;
1802 }
1803 else
1804 {
1805 return true;
1806 }
1807 }
1808 else if (IsPairTerm(G) || IsAtomTerm(G))
1809 {
1810 return true;
1811 }
1812 else
1813 {
1814 return false;
1815 }
1816}
1817
1825bool is_callable__(const char *file, const char *function, int lineno, Term t USES_REGS)
1826{
1827 // Term Context = Deref(ARG2)Yap_Error(INSTANTIATION_ERROR, t, NULL);;
1828 if (IsVarTerm(t))
1829 {
1830 Yap_ThrowError__( file, function, lineno, INSTANTIATION_ERROR, t, NULL);
1831 return false;
1832 }
1833 Term mod = CurrentModule;
1834 if (mod == 0)
1835 mod = TermProlog;
1836 Term G = Yap_StripModule(Deref(ARG1), &mod);
1837 // Term Context = Deref(ARG2);
1838 if (IsVarTerm(mod))
1839 {
1840 Yap_ThrowError__( file, function, lineno, INSTANTIATION_ERROR, mod, NULL);
1841 return false;
1842 }
1843 else if (!IsAtomTerm(mod))
1844 {
1845 return false;
1846 }
1847 if (IsVarTerm(G))
1848 {
1849 Yap_ThrowError__( file, function, lineno, INSTANTIATION_ERROR, G, NULL);
1850 return false;
1851 }
1852 if (IsApplTerm(G))
1853 {
1854 Functor f = FunctorOfTerm(G);
1855 if (IsExtensionFunctor(f))
1856 {
1857 return false;
1858 }
1859 else
1860 {
1861 return true;
1862 }
1863 }
1864 else if (IsPairTerm(G) || IsAtomTerm(G))
1865 {
1866 return true;
1867 }
1868 else
1869 {
1870 return false;
1871 }
1872}
1873
1874static Int is_callable1( USES_REGS1 )
1875{
1876 Term t = Deref(ARG1);
1877 return is_callable__(__FILE__,__FUNCTION__,__LINE__,t PASS_REGS);
1878}
1879
1880bool Yap_callable(Term t)
1881{
1882 Term mod = CurrentModule;
1883 if (mod == 0)
1884 mod = TermProlog;
1885 Term G = Yap_StripModule(Deref(t), &mod); // Term Context = Deref(ARG2);
1886 if (IsVarTerm(mod))
1887 {
1888 return false;
1889 }
1890 else if (!IsAtomTerm(mod))
1891 {
1892 return false;
1893 }
1894 if (IsVarTerm(G))
1895 {
1896 return false;
1897 }
1898 if (IsApplTerm(G))
1899 {
1900 Functor f = FunctorOfTerm(G);
1901 if (IsExtensionFunctor(f))
1902 {
1903 return false;
1904 }
1905 else
1906 {
1907 return true;
1908 }
1909 }
1910 else if (IsPairTerm(G) || IsAtomTerm(G))
1911 {
1912 return true;
1913 }
1914 else
1915 {
1916 return false;
1917 }
1918}
1919
1925static Int must_be_callable1(USES_REGS1)
1926{
1927 Term mod = CurrentModule;
1928 if (mod == 0)
1929 mod = TermProlog;
1930 Term G = Yap_StripModule(Deref(ARG1), &mod);
1931 // Term Context = Deref(ARG2);
1932 if (IsVarTerm(mod))
1933 {
1934 Yap_ThrowError(INSTANTIATION_ERROR, G, NULL);
1935 return false;
1936 }
1937 else if (!IsAtomTerm(mod))
1938 {
1939 Yap_ThrowError(TYPE_ERROR_ATOM, mod, NULL);
1940 return false;
1941 }
1942 if (IsVarTerm(G))
1943 {
1944 Yap_ThrowError(INSTANTIATION_ERROR, G, NULL);
1945 return false;
1946 }
1947 if (IsApplTerm(G))
1948 {
1949 Functor f = FunctorOfTerm(G);
1950 if (IsExtensionFunctor(f))
1951 {
1952 Yap_ThrowError(TYPE_ERROR_CALLABLE, G, NULL);
1953 }
1954 else
1955 {
1956 return true;
1957 }
1958 }
1959 else if (IsPairTerm(G) || IsAtomTerm(G))
1960 {
1961 return true;
1962 }
1963 else
1964 {
1965 Yap_ThrowError(TYPE_ERROR_CALLABLE, G, NULL);
1966 return false;
1967 }
1968 return true;
1969}
1970
1971
1978{
1979 if (IsVarTerm(t))
1980 {
1981 Yap_ThrowError(INSTANTIATION_ERROR, t, "");
1982 }
1983 if (t == TermNil || IsPairTerm(t))
1984 {
1985 return;
1986 }
1987 Yap_ThrowError(TYPE_ERROR_LIST, t, "");
1988}
1989
1994static Int must_be_bound1(USES_REGS1)
1995{
1996 Term t = Deref(ARG1);
1997 // Term Context = Deref(ARG2);
1998 if (IsVarTerm(t))
1999 Yap_ThrowError(INSTANTIATION_ERROR, ARG1, NULL);
2000 return true;
2001}
2002
2007static Int must_be_ground1(USES_REGS1)
2008{
2009 Term t = Deref(ARG1);
2010 // Term Context = Deref(ARG2);
2011 if (!Yap_IsGroundTerm(t))
2012 Yap_ThrowError(INSTANTIATION_ERROR, ARG1, NULL);
2013 return true;
2014}
2015
2031static Int must_be_predicate_indicator1(USES_REGS1)
2032{
2033 Term G = Deref(ARG1);
2034 // Term Context = Deref(ARG2);
2035 Term mod = CurrentModule;
2036
2037 G = Yap_YapStripModule(G, &mod);
2038 if (!mod) mod = TermProlog;
2039 if (IsVarTerm(G))
2040 {
2041 Yap_ThrowError(INSTANTIATION_ERROR, G, NULL);
2042 }
2043 if (!IsVarTerm(mod) && !IsAtomTerm(mod))
2044 {
2045 Yap_Error(TYPE_ERROR_ATOM, G, NULL);
2046 return false;
2047 }
2048 if (IsApplTerm(G))
2049 {
2050 Functor f = FunctorOfTerm(G);
2051 if (IsExtensionFunctor(f))
2052 {
2053 Yap_ThrowError(TYPE_ERROR_PREDICATE_INDICATOR, G, NULL);
2054 }
2055 if (f == FunctorSlash || f == FunctorDoubleSlash)
2056 {
2057 Term name = ArgOfTerm(1, G), arity = ArgOfTerm(2, G);
2058 name = Yap_YapStripModule(name, &mod);
2059 if (!mod) mod = TermProlog;
2060 if (IsVarTerm(name))
2061 {
2062 Yap_ThrowError(INSTANTIATION_ERROR, name, NULL);
2063 }
2064 else if (!IsAtomTerm(name))
2065 {
2066 Yap_ThrowError(TYPE_ERROR_ATOM, name, NULL);
2067 }
2068 if (IsVarTerm(arity))
2069 {
2070 Yap_ThrowError(INSTANTIATION_ERROR, arity, NULL);
2071 }
2072 else if (!IsIntegerTerm(arity))
2073 {
2074 Yap_ThrowError(TYPE_ERROR_INTEGER, arity, NULL);
2075 }
2076 else
2077 {
2078 Int ar = IntegerOfTerm(arity);
2079 if (ar < 0)
2080 {
2081 Yap_ThrowError(DOMAIN_ERROR_NOT_LESS_THAN_ZERO, arity, NULL);
2082 }
2083 if (f == FunctorDoubleSlash)
2084 {
2085 arity = MkIntegerTerm(ar + 2);
2086 }
2087 return Yap_unify(mod, ARG2) && Yap_unify(name, ARG3) &&
2088 Yap_unify(arity, ARG4);
2089 }
2090 }
2091 }
2092 Yap_ThrowError(TYPE_ERROR_PREDICATE_INDICATOR, G, NULL);
2093 return false;
2094}
2095
2096void Yap_InitErrorPreds(void)
2097{
2098 CACHE_REGS
2099 Yap_InitCPred("$print_exception", 1, print_exception, 0);
2100 Yap_InitCPred("print_exception", 1, print_exception, 0);
2101 Yap_InitCPred("$reset_exception", 1, reset_exception, 0);
2102
2103 Yap_InitCPred("$new_exception", 1, new_exception, 0);
2104 Yap_InitCPred("$set_exception", 3, set_exception, 0);
2105 Yap_InitCPred("$read_exception", 2, read_exception, 0);
2106 Yap_InitCPred("$query_exception", 3, query_exception, 0);
2107 Yap_InitCPred("$drop_exception", 1, drop_exception, 0);
2108 Yap_InitCPred("$close_error", 1, close_error, HiddenPredFlag);
2109
2110 /* Test predicates */
2111 Yap_InitCPred("callable", 1, callable, TestPredFlag);
2112 Yap_InitCPred("is_bound", 1, is_nonvar1, TestPredFlag);
2113 Yap_InitCPred("is_boolean", 1, is_boolean1, TestPredFlag);
2114 Yap_InitCPred("is_atom", 1, is_atom1, TestPredFlag);
2115 Yap_InitCPred("is_boolean", 1, is_boolean1, TestPredFlag);
2116 Yap_InitCPred("is_callable", 1, is_callable1, TestPredFlag);
2117 Yap_InitCPred("is_list", 1, is_list1, TestPredFlag);
2118 Yap_InitCPred("is_nonvar", 1, is_nonvar1, TestPredFlag);
2119
2120 Yap_InitCPred("must_be_atom", 1, must_be_atom1, TestPredFlag);
2121 Yap_InitCPred("must_be_boolean", 1, must_be_boolean1, TestPredFlag);
2122 Yap_InitCPred("must_be_bound", 1, must_be_bound1, TestPredFlag);
2123 Yap_InitCPred("must_be_callable", 1, must_be_callable1, TestPredFlag);
2124 Yap_InitCPred("must_be_ground", 1, must_be_ground1, TestPredFlag);
2125 Yap_InitCPred("must_be_list", 1, must_be_list1, TestPredFlag);
2126
2127 Yap_InitCPred("is_list", 1, is_list1, TestPredFlag);
2128 Yap_InitCPred("must_be_predicate_indicator", 4, must_be_predicate_indicator1, 0);
2129}
2130
load_foreign_files/3 has works for the following configurations:
Main definitions.
void Yap_must_be_list(Term t)
Dereferenced term t must start as a list:
Definition: errors.c:1977
bool Yap_ResetException(yap_error_descriptor_t *i)
clean up (notice that the code ensures ActiveError exists on exit
Definition: errors.c:1425
void Yap_PrintException(yap_error_descriptor_t *i)
print descriptor to user_output/stdout
Definition: errors.c:1401
yap_error_descriptor_t * Yap_PeekException(void)
is an error active?
Definition: errors.c:1377
bool Yap_RaiseException()
let's go
Definition: errors.c:1410
yap_error_number Yap_errorNumber(yap_error_class_number c, const char *s)
given a string(s, lookup for a corresponding error class r numbe
Definition: errors.c:1570
bool Yap_RestartException(yap_error_descriptor_t *i)
clean up (notice that the code ensures ActiveError exists on exit
Definition: errors.c:1438
yap_error_descriptor_t * Yap_GetException(void)
clone Active Error
Definition: errors.c:1389
Term Yap_MkFullError(yap_error_descriptor_t *i)
convert a C-error to a Prolog term:
Definition: errors.c:853
yamop * Yap_Error__(bool throw, const char *file, const char *function, int lineno, yap_error_number type, Term where,...)
Yap_Error This function handles errors in the C code.
Definition: errors.c:981
void Yap_ThrowError__(const char *file, const char *function, int lineno, yap_error_number type, Term where, const char *msg,...)
Throw an error directly to the error handler.
Definition: errors.c:789
Term MkSysError(yap_error_descriptor_t *i)
Wrap the error descriptor as exception/2.
Definition: errors.c:841
yap_error_descriptor_t * Yap_pushErrorContext(bool link, yap_error_descriptor_t *new_error, yap_error_descriptor_t *old_error)
add a new error descriptor, either to the top of the stack, or as the top;
Definition: errors.c:746
bool Yap_MkErrorRecord(yap_error_descriptor_t *r, const char *file, const char *function, int lineno, yap_error_number type, Term where, const char *s)
complete an error descriptor:
Definition: errors.c:882
Definition: Yatom.h:544
all we need to know about an error/throw
Definition: YapError.h:205
uintptr_t parserPos
syntax and other parsing errors
Definition: YapError.h:233
const char * errorFunction
C-function.
Definition: YapError.h:218
const char * errorFile
C-file.
Definition: YapError.h:220
yap_error_number errorNo
error identifier
Definition: YapError.h:207
yap_error_class_number errorClass
kind of error: derived from errorNo;
Definition: YapError.h:209
char * classAsText
errorClass as text
Definition: YapError.h:213
char * errorAsText
errorNo as text
Definition: YapError.h:211
bool prologConsulting
whether we are consulting
Definition: YapError.h:245
intptr_t errorLine
c-code that generated the error C-line
Definition: YapError.h:216
Definition: amidefs.h:264