This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
yap-6.3/C/errors.c

1367 lines
43 KiB
C
Raw Normal View History

/*************************************************************************
2015-09-25 10:57:26 +01:00
* *
* Yap Prolog *
* *
* Yap Prolog Was Developed At Nccup - Universidade Do Porto *
* *
* Copyright L.Damas, V.S.Costa And Universidade Do Porto 1985-1997 *
* *
**************************************************************************
* *
2015-10-18 11:39:25 +01:00
* File: errors.c *
2015-09-25 10:57:26 +01:00
* Last Rev: *
2015-10-18 11:39:25 +01:00
* Mods: *
* Comments: Yap's error handlers *
2015-09-25 10:57:26 +01:00
* *
*************************************************************************/
#include "absmi.h"
#include "yapio.h"
2018-07-23 17:13:51 +01:00
#include "YapStreams.h"
#if HAVE_STDARG_H
#include <stdarg.h>
#endif
#include <stdlib.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#if HAVE_STRING_H
#include <string.h>
#endif
#if HAVE_EXECINFO_H
#include <execinfo.h>
#endif
#include "Foreign.h"
2018-06-14 11:27:43 +01:00
#define set_key_b(k, ks, q, i, t) \
if (strcmp(ks, q) == 0) { \
2018-10-22 12:38:13 +01:00
i->k = ( t == TermTrue ? true : false); \
2018-06-14 11:27:43 +01:00
return i->k || t == TermFalse; \
2018-04-09 02:00:51 +01:00
}
2018-04-07 19:45:18 +01:00
2018-06-14 11:27:43 +01:00
#define set_key_i(k, ks, q, i, t) \
if (strcmp(ks, q) == 0) { \
2019-01-21 01:11:42 +00:00
i->k = IsIntegerTerm(t) ? IntegerOfTerm(t) : 0; \
return IsIntegerTerm(t); \
2018-04-09 02:00:51 +01:00
}
2018-04-07 19:45:18 +01:00
2018-06-14 11:27:43 +01:00
#define set_key_s(k, ks, q, i, t) \
if (strcmp(ks, q) == 0) { \
const char *s = IsAtomTerm(t) ? RepAtom(AtomOfTerm(t))->StrOfAE \
: IsStringTerm(t) ? StringOfTerm(t) : NULL; \
if (s) { \
2018-06-30 14:33:32 +01:00
char *tmp = calloc(1,strlen(s) + 1); \
2018-06-14 11:27:43 +01:00
strcpy(tmp, s); \
i->k = tmp; \
} \
return i->k != NULL; \
2018-04-09 02:00:51 +01:00
}
2018-04-07 19:45:18 +01:00
static bool setErr(const char *q, yap_error_descriptor_t *i, Term t) {
2018-04-09 02:00:51 +01:00
set_key_i(errorNo, "errorNo", q, i, t);
2018-04-07 19:45:18 +01:00
set_key_i(errorClass, "errorClass", q, i, t);
set_key_s(errorAsText, "errorAsText", q, i, t);
2018-04-09 02:00:51 +01:00
set_key_s(errorGoal, "errorGoal", q, i, t);
set_key_s(classAsText, "classAsText", q, i, t);
set_key_i(errorLine, "errorLine", q, i, t);
set_key_s(errorFunction, "errorFunction", q, i, t);
set_key_s(errorFile, "errorFile", q, i, t);
set_key_i(prologPredLine, "prologPredLine", q, i, t);
set_key_s(prologPredName, "prologPredName", q, i, t);
set_key_i(prologPredArity, "prologPredArity", q, i, t);
set_key_s(prologPredModule, "prologPredModule", q, i, t);
set_key_s(prologPredFile, "prologPredFile", q, i, t);
2018-10-22 12:38:13 +01:00
set_key_i(parserPos, "parserPos", q, i, t);
set_key_i(parserLine, "parserLine", q, i, t);
set_key_i(parserFirstLine, "parserFirstLine", q, i, t);
set_key_i(parserLastLine, "parserLastLine", q, i, t);
set_key_s(parserTextA, "parserTextA", q, i, t);
set_key_s(parserTextB, "parserTextB", q, i, t);
set_key_s(parserFile, "parserFile", q, i, t);
set_key_b(parserReadingCode, "parserReadingcode", q, i, t);
2018-04-09 02:00:51 +01:00
set_key_b(prologConsulting, "prologConsulting", q, i, t);
set_key_s(culprit, "culprit", q, i, t);
2018-10-28 10:10:40 +00:00
set_key_s(prologStack, "prologStack", q, i, t);
2018-04-09 02:00:51 +01:00
set_key_s(errorMsg, "errorMsg", q, i, t);
set_key_i(errorMsgLen, "errorMsgLen", q, i, t);
2018-04-07 19:45:18 +01:00
return false;
}
2018-09-13 13:35:37 +01:00
#define query_key_b(k, ks, q, i) \
2018-09-11 01:50:17 +01:00
if (strcmp(ks, q) == 0) { \
2018-06-14 11:27:43 +01:00
return i->k ? TermTrue : TermFalse; \
2018-04-09 02:00:51 +01:00
}
2018-04-04 01:37:15 +01:00
2018-09-11 01:50:17 +01:00
#define query_key_i(k, ks, q, i) \
if (strcmp(ks, q) == 0) { \
2018-06-14 11:27:43 +01:00
return MkIntegerTerm(i->k); \
2018-04-09 02:00:51 +01:00
}
2018-04-04 01:37:15 +01:00
2018-09-11 01:50:17 +01:00
#define query_key_s(k, ks, q, i) \
if (strcmp(ks, q) == 0 ) \
2019-01-21 01:11:42 +00:00
{ if (i->k) return MkAtomTerm(Yap_LookupAtom(i->k)); else return TermEmptyAtom; }
2018-09-11 01:50:17 +01:00
2018-07-02 15:20:17 +01:00
#define query_key_t(k, ks, q, i) \
if (strcmp(ks, q) == 0) { \
2018-09-11 01:50:17 +01:00
if (i->k == NULL) return TermNil; \
2018-07-02 15:20:17 +01:00
Term t; if((t = Yap_BufferToTerm(i->k, TermNil) ) == 0 ) return TermNil; return t; }
2018-04-04 01:37:15 +01:00
2019-02-27 04:23:21 +00:00
static yap_error_descriptor_t *CopyException(yap_error_descriptor_t *t);
2018-04-04 01:37:15 +01:00
static Term queryErr(const char *q, yap_error_descriptor_t *i) {
2018-04-09 02:00:51 +01:00
query_key_i(errorNo, "errorNo", q, i);
2018-04-04 01:37:15 +01:00
query_key_i(errorClass, "errorClass", q, i);
query_key_s(errorAsText, "errorAsText", q, i);
2018-07-02 15:20:17 +01:00
query_key_t(errorGoal, "errorGoal", q, i);
2018-04-09 02:00:51 +01:00
query_key_s(classAsText, "classAsText", q, i);
query_key_i(errorLine, "errorLine", q, i);
query_key_s(errorFunction, "errorFunction", q, i);
query_key_s(errorFile, "errorFile", q, i);
query_key_i(prologPredLine, "prologPredLine", q, i);
query_key_s(prologPredName, "prologPredName", q, i);
query_key_i(prologPredArity, "prologPredArity", q, i);
query_key_s(prologPredModule, "prologPredModule", q, i);
query_key_s(prologPredFile, "prologPredFile", q, i);
2018-10-22 12:38:13 +01:00
query_key_i(parserPos, "parserPos", q, i);
query_key_i(parserLine, "parserLine", q, i);
query_key_i(parserFirstLine, "parserFirstLine", q, i);
query_key_i(parserLastLine, "parserLastLine", q, i);
query_key_s(parserTextA, "parserTextA", q, i);
query_key_s(parserTextB, "parserTextB", q, i);
query_key_s(parserFile, "parserFile", q, i);
query_key_b(parserReadingCode, "parserReadingCode", q, i);
2018-04-09 02:00:51 +01:00
query_key_b(prologConsulting, "prologConsulting", q, i);
2018-10-28 10:10:40 +00:00
query_key_s(prologStack, "prologStack", q, i);
query_key_s(culprit, "culprit", q, i);
2018-04-09 02:00:51 +01:00
query_key_s(errorMsg, "errorMsg", q, i);
query_key_i(errorMsgLen, "errorMsgLen", q, i);
2018-04-07 19:45:18 +01:00
return TermNil;
2018-04-04 01:37:15 +01:00
}
2018-04-09 02:00:51 +01:00
static void print_key_b(const char *key, bool v) {
2018-04-02 14:49:45 +01:00
const char *b = v ? "true" : "false";
2018-04-09 02:00:51 +01:00
fprintf(stderr, "%s: %s\n", key, b);
2018-04-02 14:49:45 +01:00
}
2018-04-09 02:00:51 +01:00
static void print_key_i(const char *key, YAP_Int v) {
fprintf(stderr, "%s: " Int_FORMAT "\n", key, v);
2018-04-02 14:49:45 +01:00
}
2018-04-09 02:00:51 +01:00
static void print_key_s(const char *key, const char *v) {
fprintf(stderr, "%s: %s\n", key, v);
2018-04-02 14:49:45 +01:00
}
2018-04-07 19:45:18 +01:00
static void printErr(yap_error_descriptor_t *i) {
2018-04-02 14:49:45 +01:00
if (i->errorNo == YAP_NO_ERROR) {
return;
}
2018-04-09 02:00:51 +01:00
print_key_i("errorNo", i->errorNo);
2018-06-30 14:33:32 +01:00
print_key_i("errorClass", (i->errorClass = Yap_errorClass(i->errorNo)));
print_key_s("errorAsText", (i->errorAsText=Yap_errorName(i->errorNo) ) );
2018-04-09 02:00:51 +01:00
print_key_s("errorGoal", i->errorGoal);
2018-06-30 14:33:32 +01:00
print_key_s("classAsText", (i->classAsText=Yap_errorClassName(i->errorClass)));
2018-06-14 11:27:43 +01:00
print_key_i("errorLine", i->errorLine);
2018-04-09 02:00:51 +01:00
print_key_s("errorFunction", i->errorFunction);
print_key_s("errorFile", i->errorFile);
print_key_i("prologPredLine", i->prologPredLine);
print_key_s("prologPredName", i->prologPredName);
print_key_i("prologPredArity", i->prologPredArity);
print_key_s("prologPredModule", i->prologPredModule);
print_key_s("prologPredFile", i->prologPredFile);
2018-10-22 12:38:13 +01:00
print_key_i("parserPos", i->parserPos);
print_key_i("parserLine", i->parserLine);
print_key_i("parserFirstLine", i->parserFirstLine);
print_key_i("parserLastLine", i->parserLastLine);
print_key_s("parserTextA", i->parserTextA);
print_key_s("parserTextB", i->parserTextB);
print_key_s("parserFile", i->parserFile);
print_key_b("parserReadingCode", i->parserReadingCode);
2018-04-09 02:00:51 +01:00
print_key_b("prologConsulting", i->prologConsulting);
print_key_s("culprit", i->culprit);
2018-10-28 10:10:40 +00:00
print_key_s("prologStack", i->prologStack);
2018-04-07 19:45:18 +01:00
if (i->errorMsgLen) {
2018-04-09 02:00:51 +01:00
print_key_s("errorMsg", i->errorMsg);
print_key_i("errorMsgLen", i->errorMsgLen);
2018-04-07 19:45:18 +01:00
}
2018-04-02 14:49:45 +01:00
}
2018-04-09 02:00:51 +01:00
static YAP_Term add_key_b(const char *key, bool v, YAP_Term o0) {
2018-04-02 14:49:45 +01:00
YAP_Term tkv[2];
tkv[1] = v ? TermTrue : TermFalse;
tkv[0] = MkStringTerm(key);
2018-04-09 02:00:51 +01:00
Term node = Yap_MkApplTerm(FunctorEq, 2, tkv);
2018-04-02 14:49:45 +01:00
return MkPairTerm(node, o0);
}
2018-04-09 02:00:51 +01:00
static YAP_Term add_key_i(const char *key, YAP_Int v, YAP_Term o0) {
2018-04-02 14:49:45 +01:00
YAP_Term tkv[2];
tkv[1] = MkIntegerTerm(v), tkv[0] = MkStringTerm(key);
2018-04-09 02:00:51 +01:00
Term node = Yap_MkApplTerm(FunctorEq, 2, tkv);
2018-04-02 14:49:45 +01:00
return MkPairTerm(node, o0);
}
2018-04-09 02:00:51 +01:00
static YAP_Term add_key_s(const char *key, const char *v, YAP_Term o0) {
2018-04-02 14:49:45 +01:00
Term tkv[2];
2018-04-09 02:00:51 +01:00
if (!v || v[0] == '\0')
2018-04-02 14:49:45 +01:00
return o0;
tkv[1] = MkStringTerm(v), tkv[0] = MkStringTerm(key);
2018-04-09 02:00:51 +01:00
Term node = Yap_MkApplTerm(FunctorEq, 2, tkv);
2018-04-02 14:49:45 +01:00
return MkPairTerm(node, o0);
}
2018-04-07 19:45:18 +01:00
static Term err2list(yap_error_descriptor_t *i) {
2018-04-02 14:49:45 +01:00
Term o = TermNil;
if (i->errorNo == YAP_NO_ERROR) {
return o;
}
2018-04-09 02:00:51 +01:00
o = add_key_i("errorNo", i->errorNo, o);
2018-04-02 14:49:45 +01:00
o = add_key_i("errorClass", i->errorClass, o);
o = add_key_s("errorAsText", i->errorAsText, o);
2018-04-09 02:00:51 +01:00
o = add_key_s("errorGoal", i->errorGoal, o);
o = add_key_s("classAsText", i->classAsText, o);
o = add_key_i("errorLineq", i->errorLine, o);
o = add_key_s("errorFunction", i->errorFunction, o);
o = add_key_s("errorFile", i->errorFile, o);
o = add_key_i("prologPredLine", i->prologPredLine, o);
o = add_key_s("prologPredName", i->prologPredName, o);
o = add_key_i("prologPredArity", i->prologPredArity, o);
o = add_key_s("prologPredModule", i->prologPredModule, o);
o = add_key_s("prologPredFile", i->prologPredFile, o);
2018-10-22 12:38:13 +01:00
o = add_key_i("parserPos", i->parserPos, o);
o = add_key_i("parserLine", i->parserLine, o);
o = add_key_i("parserFirstLine", i->parserFirstLine, o);
o = add_key_i("parserLastLine", i->parserLastLine, o);
o = add_key_s("parserTextA", i->parserTextA, o);
o = add_key_s("parserTextB", i->parserTextB, o);
o = add_key_s("parserFile", i->parserFile, o);
o = add_key_b("parserReadingCode", i->parserReadingCode, o);
2018-04-09 02:00:51 +01:00
o = add_key_b("prologConsulting", i->prologConsulting, o);
o = add_key_s("culprit", i->culprit, o);
2018-10-28 10:10:40 +00:00
o = add_key_s("prologStack", i->prologStack, o);
2018-04-07 19:45:18 +01:00
if (i->errorMsgLen) {
2018-04-09 02:00:51 +01:00
o = add_key_s("errorMsg", i->errorMsg, o);
o = add_key_i("errorMsgLen", i->errorMsgLen, o);
2018-04-07 19:45:18 +01:00
}
return o;
2018-04-02 14:49:45 +01:00
}
2015-09-25 10:57:26 +01:00
bool Yap_Warning(const char *s, ...) {
2015-10-05 10:29:07 +01:00
CACHE_REGS
2018-06-14 11:27:43 +01:00
va_list ap;
2015-10-05 10:29:07 +01:00
PredEntry *pred;
bool rc;
Term ts[2];
2017-10-18 01:02:52 +01:00
const char *fmt;
2015-10-05 10:29:07 +01:00
char tmpbuf[MAXPATHLEN];
2018-04-04 15:55:45 +01:00
yap_error_number err;
2015-10-18 11:39:25 +01:00
2017-10-02 08:58:51 +01:00
LOCAL_DoingUndefp = true;
2018-04-04 15:55:45 +01:00
if (LOCAL_PrologMode & InErrorMode && (err = LOCAL_ActiveError->errorNo)) {
2018-04-09 02:00:51 +01:00
fprintf(stderr, "%% Warning %s WITHIN ERROR %s %s\n", s,
Yap_errorClassName(Yap_errorClass(err)), Yap_errorName(err));
2018-04-03 18:31:51 +01:00
Yap_RestartYap(1);
}
LOCAL_PrologMode |= InErrorMode;
2015-10-18 11:39:25 +01:00
pred = RepPredProp(PredPropByFunc(FunctorPrintMessage,
PROLOG_MODULE)); // PROCEDURE_print_message2
2015-10-05 10:29:07 +01:00
va_start(ap, s);
2017-10-18 01:02:52 +01:00
fmt = va_arg(ap, char *);
if (fmt != NULL) {
2015-10-05 10:29:07 +01:00
#if HAVE_VSNPRINTF
2017-10-18 01:02:52 +01:00
vsnprintf(tmpbuf, MAXPATHLEN - 1, fmt, ap);
2015-10-05 10:29:07 +01:00
#else
2017-10-18 01:02:52 +01:00
(void)vsprintf(tmpbuf, fmt, ap);
2015-10-05 10:29:07 +01:00
#endif
2018-02-24 14:39:17 +00:00
} else {
2015-10-05 10:29:07 +01:00
return false;
2018-02-24 14:39:17 +00:00
}
2015-10-05 10:29:07 +01:00
va_end(ap);
if (pred->OpcodeOfPred == UNDEF_OPCODE || pred->OpcodeOfPred == FAIL_OPCODE) {
2015-12-15 09:18:36 +00:00
fprintf(stderr, "warning message: %s\n", tmpbuf);
LOCAL_DoingUndefp = false;
2018-04-07 19:45:18 +01:00
LOCAL_PrologMode &= ~InErrorMode;
return false;
2015-12-15 09:18:36 +00:00
}
ts[1] = MkAtomTerm(AtomWarning);
ts[0] = MkAtomTerm(Yap_LookupAtom(tmpbuf));
2015-10-05 10:29:07 +01:00
rc = Yap_execute_pred(pred, ts, true PASS_REGS);
2018-04-03 18:31:51 +01:00
LOCAL_PrologMode &= ~InErrorMode;
return rc;
2015-06-19 01:30:13 +01:00
}
2018-02-21 13:02:20 +00:00
2018-04-09 02:00:51 +01:00
void Yap_InitError__(const char *file, const char *function, int lineno,
yap_error_number e, Term t, ...) {
2018-02-21 13:02:20 +00:00
CACHE_REGS
2018-06-14 11:27:43 +01:00
va_list ap;
2018-02-21 13:02:20 +00:00
va_start(ap, t);
const char *fmt;
2019-02-21 21:03:44 +00:00
char *tmpbuf=NULL;
2018-02-21 13:02:20 +00:00
fmt = va_arg(ap, char *);
if (fmt != NULL) {
2019-02-21 21:03:44 +00:00
tmpbuf = malloc(MAXPATHLEN);
2018-02-21 13:02:20 +00:00
#if HAVE_VSNPRINTF
vsnprintf(tmpbuf, MAXPATHLEN - 1, fmt, ap);
#else
(void)vsprintf(tmpbuf, fmt, ap);
#endif
} else
return;
va_end(ap);
2018-04-02 14:49:45 +01:00
if (LOCAL_ActiveError->errorNo != YAP_NO_ERROR) {
2018-04-17 17:47:40 +01:00
yap_error_number err = LOCAL_ActiveError->errorNo;
fprintf(stderr, "%% Warning %s WITHIN ERROR %s %s\n", Yap_errorName(e),
Yap_errorClassName(Yap_errorClass(err)), Yap_errorName(err));
2018-06-14 11:27:43 +01:00
return;
}
2016-10-20 04:44:59 +01:00
LOCAL_ActiveError->errorNo = e;
LOCAL_ActiveError->errorFile = NULL;
LOCAL_ActiveError->errorFunction = NULL;
LOCAL_ActiveError->errorLine = 0;
2019-02-21 21:03:44 +00:00
if (fmt && tmpbuf) {
2018-02-21 13:02:20 +00:00
LOCAL_Error_Size = strlen(tmpbuf);
2016-10-20 04:44:59 +01:00
LOCAL_ActiveError->errorMsg = malloc(LOCAL_Error_Size + 1);
2018-10-22 12:38:13 +01:00
strcpy((char *)LOCAL_ActiveError->errorMsg, tmpbuf);
} else {
LOCAL_Error_Size = 0;
}
}
2015-06-19 01:30:13 +01:00
2015-09-25 10:57:26 +01:00
bool Yap_PrintWarning(Term twarning) {
CACHE_REGS
2018-06-14 11:27:43 +01:00
PredEntry *pred = RepPredProp(PredPropByFunc(
FunctorPrintMessage, PROLOG_MODULE)); // PROCEDURE_print_message2;
2019-02-27 04:23:21 +00:00
if (twarning)
2018-06-25 13:44:09 +01:00
__android_log_print(ANDROID_LOG_INFO, "YAPDroid ", " warning(%s)",
2019-04-03 17:08:12 +01:00
Yap_TermToBuffer(twarning, Quote_illegal_f | Ignore_ops_f | Handle_cyclics_f));
Term cmod = (CurrentModule == PROLOG_MODULE ? TermProlog : CurrentModule);
bool rc;
Term ts[2], err;
2015-10-18 11:39:25 +01:00
2019-02-27 04:23:21 +00:00
if (twarning && LOCAL_PrologMode & InErrorMode &&
2018-10-22 12:38:13 +01:00
LOCAL_ActiveError->errorClass != WARNING &&
2019-02-27 04:23:21 +00:00
(err = LOCAL_ActiveError->errorNo) ) {
fprintf(stderr, "%% Warning %s while processing error: %s %s\n",
2018-07-10 23:21:19 +01:00
Yap_TermToBuffer(twarning,
2018-08-15 01:29:20 +01:00
Quote_illegal_f | Ignore_ops_f),
2018-06-14 11:27:43 +01:00
Yap_errorClassName(Yap_errorClass(err)), Yap_errorName(err));
return false;
}
2018-04-03 18:31:51 +01:00
LOCAL_PrologMode |= InErrorMode;
if (pred->OpcodeOfPred == UNDEF_OPCODE || pred->OpcodeOfPred == FAIL_OPCODE) {
2018-11-14 09:35:24 +00:00
fprintf(stderr, "%s:%ld/* d:%d warning */:\n",
LOCAL_ActiveError->errorFile,
LOCAL_ActiveError->errorLine, 0 );
2019-02-27 04:23:21 +00:00
if (!twarning)
twarning = Yap_MkFullError();
2018-11-14 09:35:24 +00:00
Yap_DebugPlWriteln(twarning);
LOCAL_DoingUndefp = false;
2018-04-07 19:45:18 +01:00
LOCAL_PrologMode &= ~InErrorMode;
CurrentModule = cmod;
return false;
}
2019-02-27 04:23:21 +00:00
if (!twarning)
twarning = Yap_MkFullError();
ts[1] = twarning;
ts[0] = MkAtomTerm(AtomWarning);
2018-06-14 11:27:43 +01:00
rc = Yap_execute_pred(pred, ts, true PASS_REGS);
LOCAL_within_print_message = false;
2018-04-03 18:31:51 +01:00
LOCAL_PrologMode &= ~InErrorMode;
return rc;
2019-01-31 11:52:03 +00:00
}
bool Yap_HandleError__(const char *file, const char *function, int lineno,
const char *s, ...) {
CACHE_REGS
2018-06-14 11:27:43 +01:00
yap_error_number err = LOCAL_Error_TYPE;
2015-01-26 04:02:46 +00:00
const char *serr;
2015-10-18 11:39:25 +01:00
arity_t arity = 2;
if (LOCAL_ErrorMessage) {
serr = LOCAL_ErrorMessage;
} else {
2015-01-26 04:02:46 +00:00
serr = s;
}
2018-06-14 11:27:43 +01:00
if (P != FAILCODE) {
if (P->opc == Yap_opcode(_try_c) || P->opc == Yap_opcode(_try_userc) ||
P->opc == Yap_opcode(_retry_c) || P->opc == Yap_opcode(_retry_userc)) {
arity = P->y_u.OtapFs.p->ArityOfPE;
} else {
arity = PREVOP(P, Osbpp)->y_u.Osbpp.p->ArityOfPE;
}
}
switch (err) {
2015-10-18 11:39:25 +01:00
case RESOURCE_ERROR_STACK:
if (!Yap_gc(arity, ENV, gc_P(P, CP))) {
2018-04-09 02:00:51 +01:00
Yap_Error__(false, file, function, lineno, RESOURCE_ERROR_STACK, ARG1,
serr);
2016-01-31 11:54:45 +00:00
return false;
2015-10-18 11:39:25 +01:00
}
LOCAL_PrologMode = UserMode;
2016-01-31 11:54:45 +00:00
return true;
2015-10-18 11:39:25 +01:00
case RESOURCE_ERROR_AUXILIARY_STACK:
if (LOCAL_MAX_SIZE < (char *)AuxSp - AuxBase) {
LOCAL_MAX_SIZE += 1024;
}
if (!Yap_ExpandPreAllocCodeSpace(0, NULL, TRUE)) {
/* crash in flames */
2018-04-09 02:00:51 +01:00
Yap_Error__(false, file, function, lineno, RESOURCE_ERROR_AUXILIARY_STACK,
ARG1, serr);
2016-01-31 11:54:45 +00:00
return false;
2015-10-18 11:39:25 +01:00
}
LOCAL_PrologMode = UserMode;
2016-01-31 11:54:45 +00:00
return true;
2015-10-18 11:39:25 +01:00
case RESOURCE_ERROR_HEAP:
if (!Yap_growheap(FALSE, 0, NULL)) {
2018-04-09 02:00:51 +01:00
Yap_Error__(false, file, function, lineno, RESOURCE_ERROR_HEAP, ARG2,
serr);
2016-01-31 11:54:45 +00:00
return false;
2015-10-18 11:39:25 +01:00
}
default:
2019-01-31 11:52:03 +00:00
2018-04-09 13:42:06 +01:00
if (LOCAL_PrologMode == UserMode)
2018-06-14 11:27:43 +01:00
Yap_ThrowError__(file, function, lineno, err, LOCAL_RawTerm, serr);
2018-04-17 17:47:40 +01:00
else
LOCAL_PrologMode &= ~InErrorMode;
2016-01-31 11:54:45 +00:00
return false;
}
}
2015-09-25 10:57:26 +01:00
int Yap_SWIHandleError(const char *s, ...) {
CACHE_REGS
2018-06-14 11:27:43 +01:00
yap_error_number err = LOCAL_Error_TYPE;
char *serr;
2015-10-18 11:39:25 +01:00
2018-10-22 12:38:13 +01:00
if (s) {
serr = (char *)s;
}
switch (err) {
2015-10-18 11:39:25 +01:00
case RESOURCE_ERROR_STACK:
if (!Yap_gc(2, ENV, gc_P(P, CP))) {
Yap_Error(RESOURCE_ERROR_STACK, TermNil, serr);
2015-09-25 10:57:26 +01:00
return (FALSE);
2015-10-18 11:39:25 +01:00
}
return TRUE;
case RESOURCE_ERROR_AUXILIARY_STACK:
if (LOCAL_MAX_SIZE < (char *)AuxSp - AuxBase) {
LOCAL_MAX_SIZE += 1024;
}
if (!Yap_ExpandPreAllocCodeSpace(0, NULL, TRUE)) {
/* crash in flames */
Yap_Error(RESOURCE_ERROR_AUXILIARY_STACK, ARG1, serr);
return FALSE;
}
2018-03-29 22:33:53 +01:00
return true;
2015-10-18 11:39:25 +01:00
case RESOURCE_ERROR_HEAP:
2018-03-29 22:33:53 +01:00
if (!Yap_growheap(false, 0, NULL)) {
2015-10-18 11:39:25 +01:00
Yap_Error(RESOURCE_ERROR_HEAP, ARG2, serr);
2018-03-29 22:33:53 +01:00
return false;
2015-10-18 11:39:25 +01:00
}
default:
2016-10-20 04:44:59 +01:00
Yap_Error(err, TermNil, serr);
2018-03-29 22:33:53 +01:00
return false;
}
}
2015-09-25 10:57:26 +01:00
void Yap_RestartYap(int flag) {
2012-02-07 15:18:43 +00:00
CACHE_REGS
#if PUSH_REGS
2018-06-14 11:27:43 +01:00
restore_absmi_regs(&Yap_standard_regs);
#endif
2018-03-29 22:33:53 +01:00
siglongjmp(*LOCAL_RestartEnv, flag);
}
2015-09-25 10:57:26 +01:00
static void error_exit_yap(int value) {
CACHE_REGS
2018-06-14 11:27:43 +01:00
if (!(LOCAL_PrologMode & BootMode)) {
2015-10-18 11:39:25 +01:00
#if DEBUG
#endif
2018-06-14 11:27:43 +01:00
}
fprintf(stderr, "\n Exiting ....\n");
2016-03-29 01:55:12 +01:00
#if HAVE_BACKTRACE
2016-05-14 11:34:27 +01:00
void *callstack[256];
int i;
int frames = backtrace(callstack, 256);
char **strs = backtrace_symbols(callstack, frames);
2016-05-14 11:34:27 +01:00
fprintf(stderr, "Execution stack:\n");
for (i = 0; i < frames; ++i) {
fprintf(stderr, " %s\n", strs[i]);
}
free(strs);
2016-03-29 01:55:12 +01:00
#endif
2016-05-14 11:34:27 +01:00
Yap_exit(value);
}
/* This needs to be a static because I can't trust the stack (WIN32), and
2016-05-14 11:34:27 +01:00
I can't trust the Yap stacks (error) */
#define YAP_BUF_SIZE 512
static char tmpbuf[YAP_BUF_SIZE];
2015-09-25 10:57:26 +01:00
// error classes: based on OSI errors.
//
// - The extra argument says whether there different instances
//
// - Events are treated within the same pipeline as errors.
//
#undef BEGIN_ERROR_CLASSES
#undef ECLASS
#undef END_ERROR_CLASSES
#undef BEGIN_ERRORS
#undef E0
#undef E
2018-04-17 17:47:40 +01:00
#undef E1
2015-09-25 10:57:26 +01:00
#undef E2
#undef END_ERRORS
2018-06-14 11:27:43 +01:00
#define BEGIN_ERROR_CLASSES() \
static Atom mkerrorct(yap_error_class_number c) { \
switch (c) {
2015-09-25 10:57:26 +01:00
2018-06-14 11:27:43 +01:00
#define ECLASS(CL, A, B) \
case CL: \
return Yap_LookupAtom(A);
2011-10-03 01:01:14 +01:00
2018-06-14 11:27:43 +01:00
#define END_ERROR_CLASSES() \
} \
return NULL; \
}
2011-10-03 01:01:14 +01:00
2018-06-14 11:27:43 +01:00
#define BEGIN_ERRORS() \
static Term mkerrort(yap_error_number e, Term culprit, Term info) { \
2018-10-08 13:51:17 +01:00
if (!e || !info) return TermNil; \
switch (e) {
2015-10-18 11:39:25 +01:00
2018-06-14 11:27:43 +01:00
#define E0(A, B) \
case A: { \
Term ft[2]; \
ft[0] = MkAtomTerm(mkerrorct(B)); \
ft[1] = info; \
return Yap_MkApplTerm(FunctorError, 2, ft); \
2018-04-09 02:00:51 +01:00
}
2016-05-14 11:34:27 +01:00
2018-06-14 11:27:43 +01:00
#define E(A, B, C) \
case A: { \
Term ft[2], nt[2]; \
nt[0] = MkAtomTerm(Yap_LookupAtom(C)); \
nt[1] = MkVarTerm(); \
Yap_unify(nt[1], culprit); \
ft[0] = Yap_MkApplTerm(Yap_MkFunctor(mkerrorct(B), 2), 2, nt); \
ft[1] = info; \
return Yap_MkApplTerm(FunctorError, 2, ft); \
2018-04-09 02:00:51 +01:00
}
2016-05-14 11:34:27 +01:00
2018-06-14 11:27:43 +01:00
#define E1(A, B, C) \
case A: { \
Term ft[2], nt[1]; \
nt[0] = MkVarTerm(); \
Yap_unify(nt[0], culprit); \
ft[0] = Yap_MkApplTerm(Yap_MkFunctor(Yap_LookupAtom(C), 1), 1, nt); \
ft[1] = info; \
return Yap_MkApplTerm(FunctorError, 2, ft); \
2018-04-17 17:47:40 +01:00
}
2018-06-14 11:27:43 +01:00
#define E2(A, B, C, D) \
case A: { \
Term ft[2], nt[3]; \
nt[0] = MkAtomTerm(Yap_LookupAtom(C)); \
nt[1] = MkAtomTerm(Yap_LookupAtom(D)); \
nt[2] = MkVarTerm(); \
Yap_unify(nt[2], culprit); \
ft[0] = Yap_MkApplTerm(Yap_MkFunctor(mkerrorct(B), 3), 3, nt); \
ft[1] = info; \
return Yap_MkApplTerm(FunctorError, 2, ft); \
2018-04-02 14:49:45 +01:00
}
2016-05-14 11:34:27 +01:00
2018-06-14 11:27:43 +01:00
#define END_ERRORS() \
} \
return TermNil; \
}
2015-09-25 10:57:26 +01:00
#include "YapErrors.h"
2018-04-03 18:31:51 +01:00
2018-10-22 12:38:13 +01:00
/// add a new error descriptor, either to the top of the stack,
/// or replacing the top;
bool Yap_pushErrorContext(bool link , yap_error_descriptor_t *new_error) {
2018-06-14 11:27:43 +01:00
memset(new_error, 0, sizeof(yap_error_descriptor_t));
2018-10-22 12:38:13 +01:00
if (link)
new_error->top_error = LOCAL_ActiveError;
2018-06-14 11:27:43 +01:00
LOCAL_ActiveError = new_error;
return true;
2016-10-20 04:44:59 +01:00
}
2018-04-02 14:49:45 +01:00
/* static void */
/* reset_error_description(void) { */
/* yap_error_descriptor_t *bf = LOCAL_ActiveError->top_error; */
/* if (Yap_HasException()) */
/* memset(LOCAL_ActiveError, 0, sizeof(*LOCAL_ActiveError)); */
/* LOCAL_ActiveError->top_error = bf; */
/* } */
2018-04-16 14:54:53 +01:00
yap_error_descriptor_t *Yap_popErrorContext(bool mdnew, bool pass) {
2018-07-02 15:20:17 +01:00
yap_error_descriptor_t *e = LOCAL_ActiveError, *ep = LOCAL_ActiveError->top_error;
2018-06-14 11:27:43 +01:00
// last block
2018-07-02 15:20:17 +01:00
LOCAL_ActiveError = ep;
if (e->errorNo && !ep->errorNo && pass) {
2018-07-17 11:43:57 +01:00
yap_error_descriptor_t *epp = ep->top_error;
2018-07-02 15:20:17 +01:00
memmove(ep, e, sizeof(*e));
ep->top_error = epp;
2018-06-14 11:27:43 +01:00
}
2018-07-02 15:20:17 +01:00
return LOCAL_ActiveError;
2016-10-20 04:44:59 +01:00
}
2018-06-14 11:27:43 +01:00
/**
2018-05-13 12:59:17 +01:00
* Throw an error directly to the error handler
2018-06-14 11:27:43 +01:00
*
2018-05-13 12:59:17 +01:00
* @param file where
* @param function who
* @param lineno when
* @param type what, error code
* @param where how, user information
*/
void Yap_ThrowError__(const char *file, const char *function, int lineno,
2016-12-10 07:07:57 +00:00
yap_error_number type, Term where, ...) {
va_list ap;
char tmpbuf[MAXPATHLEN];
2016-12-10 07:07:57 +00:00
va_start(ap, where);
2017-10-18 01:02:52 +01:00
char *fmt = va_arg(ap, char *);
if (fmt != NULL) {
#if HAVE_VSNPRINTF
2017-10-18 01:02:52 +01:00
(void)vsnprintf(tmpbuf, MAXPATHLEN - 1, fmt, ap);
#else
2017-10-18 01:02:52 +01:00
(void)vsprintf(tnpbuf, fmt, ap);
#endif
2016-12-10 07:07:57 +00:00
// fprintf(stderr, "warning: ");
2018-03-29 22:33:53 +01:00
Yap_Error__(true, file, function, lineno, type, where, tmpbuf);
} else {
2018-10-31 13:56:27 +00:00
Yap_Error__(true, file, function, lineno, type, where, NULL);
2018-03-29 22:33:53 +01:00
}
2018-05-16 00:00:12 +01:00
if (LOCAL_RestartEnv && !LOCAL_delay) {
2018-03-29 22:33:53 +01:00
Yap_RestartYap(5);
2018-04-09 02:00:51 +01:00
}
2018-04-07 19:45:18 +01:00
Yap_exit(5);
}
2018-06-14 11:27:43 +01:00
/**
2018-05-13 12:59:17 +01:00
* complete delayed error.
2018-06-14 11:27:43 +01:00
*
2018-05-13 12:59:17 +01:00
*/
void Yap_ThrowExistingError(void) {
if (LOCAL_RestartEnv) {
Yap_RestartYap(5);
}
Yap_exit(5);
}
2018-10-22 12:38:13 +01:00
Term Yap_MkFullError(void)
{
2019-02-27 04:23:21 +00:00
yap_error_descriptor_t *i = CopyException(Yap_local.ActiveError);
2018-10-22 12:38:13 +01:00
i->errorAsText = Yap_errorName( i->errorNo );
i->errorClass = Yap_errorClass( i-> errorNo );
i->classAsText = Yap_errorClassName(i->errorClass);
return mkerrort(i->errorNo, TermNil , MkSysError(i) );
}
2018-06-14 11:27:43 +01:00
bool Yap_MkErrorRecord(yap_error_descriptor_t *r, const char *file,
const char *function, int lineno, yap_error_number type,
2018-09-10 17:06:13 +01:00
Term where, const char *s) {
if (!Yap_pc_add_location(r, P, B, ENV))
2018-05-20 00:47:27 +01:00
Yap_env_add_location(r, CP, B, ENV, 0);
2018-09-11 01:50:17 +01:00
if (where == 0L || where == TermNil) {
2018-05-20 00:47:27 +01:00
r->culprit = NULL;
} else {
r->culprit = Yap_TermToBuffer(
2018-08-15 01:29:20 +01:00
where, Quote_illegal_f | Ignore_ops_f);
2018-06-14 11:27:43 +01:00
}
2018-10-22 12:38:13 +01:00
if (type != SYNTAX_ERROR && LOCAL_consult_level > 0) {
r->parserFile = Yap_ConsultingFile(PASS_REGS1)->StrOfAE;
r->parserLine = Yap_source_line_no();
2018-05-20 00:47:27 +01:00
}
r->errorNo = type;
r->errorAsText = Yap_errorName(type);
r->errorClass = Yap_errorClass(type);
2018-06-14 11:27:43 +01:00
r->classAsText = Yap_errorClassName(r->errorClass);
2018-05-20 00:47:27 +01:00
r->errorLine = lineno;
r->errorFunction = function;
r->errorFile = file;
2018-10-23 10:09:17 +01:00
r->prologConsulting = Yap_Consulting();
2018-05-20 00:47:27 +01:00
LOCAL_PrologMode |= InErrorMode;
Yap_ClearExs();
// first, obtain current location
2018-10-22 12:38:13 +01:00
2018-05-20 00:47:27 +01:00
// sprintf(LOCAL_FileNameBuf, "%s:%d in C-function %s ", file, lineno,
// function);
// tf = MkAtomTerm(Yap_LookupAtom(LOCAL_FileNameBuf));
#if DEBUG_STRICT
if (Yap_heap_regs && !(LOCAL_PrologMode & BootMode))
fprintf(stderr, "***** Processing Error %d (%lx,%x) %s***\n", type,
(unsigned long int)LOCAL_Signals, LOCAL_PrologMode, fmt);
else
fprintf(stderr, "***** Processing Error %d (%x) %s***\n", type,
LOCAL_PrologMode, fmt);
#endif
if (r->errorNo == SYNTAX_ERROR) {
r->errorClass = SYNTAX_ERROR_CLASS;
} else if (r->errorNo == SYNTAX_ERROR_NUMBER) {
r->errorClass = SYNTAX_ERROR_CLASS;
r->errorNo = SYNTAX_ERROR;
}
if (type == INTERRUPT_EVENT) {
fprintf(stderr, "%% YAP exiting: cannot handle signal %d\n",
(int)IntOfTerm(where));
Yap_exit(1);
}
// fprintf(stderr, "warning: ");
2018-05-24 12:00:10 +01:00
if (s && s[0]) {
2018-10-22 12:38:13 +01:00
char *ns;
2018-06-14 11:27:43 +01:00
r->errorMsgLen = strlen(s) + 1;
2018-10-22 12:38:13 +01:00
ns = malloc(r->errorMsgLen);
strcpy(ns, s);
r->errorMsg = ns;
2018-06-14 11:27:43 +01:00
} else {
2018-05-20 00:47:27 +01:00
r->errorMsgLen = 0;
2018-06-14 11:27:43 +01:00
r->errorMsg = 0;
}
return true;
2018-05-20 00:47:27 +01:00
}
2015-09-25 10:57:26 +01:00
/**
2016-05-14 11:34:27 +01:00
* @brief Yap_Error
2015-09-25 10:57:26 +01:00
* This function handles errors in the C code. Check errors.yap for the
*corresponding Prolog code.
*
* @param file C source
* @param function C function
* @param lineno C exact line
* @param type the error ID (in YAP this is a single integer)
* @param where the culprit
* @return usually FAILCODE
*
* In a good day, the error handler's job is to generate a throw. This includes:
* - constructing an ISO style error term;
* - constructing a list with all available info on the bug
* - generating the throw
* - forcing backtracking in order to restart.
*
* In a bad day, it has to deal with OOM, abort, and errors within errorts.
*
*/
2018-04-09 02:00:51 +01:00
yamop *Yap_Error__(bool throw, const char *file, const char *function,
int lineno, yap_error_number type, Term where, ...) {
2018-04-07 19:45:18 +01:00
CACHE_REGS
2018-06-14 11:27:43 +01:00
va_list ap;
2018-04-07 19:45:18 +01:00
char *fmt;
2019-02-21 21:03:44 +00:00
char *s = NULL;
2018-05-20 00:47:27 +01:00
2018-06-14 11:27:43 +01:00
switch (type) {
case SYSTEM_ERROR_INTERNAL: {
fprintf(stderr, "%% Internal YAP Error: %s exiting....\n", tmpbuf);
// serious = true;
if (LOCAL_PrologMode & BootMode) {
fprintf(stderr, "%% YAP crashed while booting %s\n", tmpbuf);
} else {
2018-09-10 17:06:13 +01:00
Yap_output_bug_location(P, FIND_PRED_FROM_ANYWHERE, YAP_BUF_SIZE);
2018-06-14 11:27:43 +01:00
if (tmpbuf[0]) {
fprintf(stderr, "%% Bug found while executing %s\n", tmpbuf);
}
2018-04-16 14:54:53 +01:00
#if HAVE_BACKTRACE
2018-06-14 11:27:43 +01:00
void *callstack[256];
int i;
int frames = backtrace(callstack, 256);
char **strs = backtrace_symbols(callstack, frames);
fprintf(stderr, "Execution stack:\n");
for (i = 0; i < frames; ++i) {
fprintf(stderr, " %s\n", strs[i]);
2018-04-16 14:54:53 +01:00
}
2018-06-14 11:27:43 +01:00
free(strs);
#endif
2018-04-16 14:54:53 +01:00
}
2018-06-14 11:27:43 +01:00
error_exit_yap(1);
}
case SYSTEM_ERROR_FATAL: {
fprintf(stderr, "%% Fatal YAP Error: %s exiting....\n", tmpbuf);
error_exit_yap(1);
}
case INTERRUPT_EVENT: {
error_exit_yap(1);
}
case ABORT_EVENT:
// fun = FunctorDollarVar;
// serious = true;
LOCAL_ActiveError->errorNo = ABORT_EVENT;
Yap_JumpToEnv();
P = FAILCODE;
LOCAL_PrologMode &= ~InErrorMode;
return P;
case CALL_COUNTER_UNDERFLOW_EVENT:
/* Do a long jump */
LOCAL_ReductionsCounterOn = FALSE;
LOCAL_PredEntriesCounterOn = FALSE;
LOCAL_RetriesCounterOn = FALSE;
LOCAL_ActiveError->errorNo = CALL_COUNTER_UNDERFLOW_EVENT;
Yap_JumpToEnv();
P = FAILCODE;
LOCAL_PrologMode &= ~InErrorMode;
return P;
case PRED_ENTRY_COUNTER_UNDERFLOW_EVENT:
/* Do a long jump */
LOCAL_ReductionsCounterOn = FALSE;
LOCAL_PredEntriesCounterOn = FALSE;
LOCAL_RetriesCounterOn = FALSE;
LOCAL_ActiveError->errorNo = PRED_ENTRY_COUNTER_UNDERFLOW_EVENT;
Yap_JumpToEnv();
P = FAILCODE;
LOCAL_PrologMode &= ~InErrorMode;
return P;
case RETRY_COUNTER_UNDERFLOW_EVENT:
/* Do a long jump */
LOCAL_ReductionsCounterOn = FALSE;
LOCAL_PredEntriesCounterOn = FALSE;
LOCAL_RetriesCounterOn = FALSE;
LOCAL_ActiveError->errorNo = RETRY_COUNTER_UNDERFLOW_EVENT;
Yap_JumpToEnv();
P = FAILCODE;
LOCAL_PrologMode &= ~InErrorMode;
return P;
default:
va_start(ap, where);
fmt = va_arg(ap, char *);
if (fmt != NULL) {
2019-02-21 21:03:44 +00:00
s = malloc(MAXPATHLEN);
2015-10-05 10:29:07 +01:00
#if HAVE_VSNPRINTF
2018-06-14 11:27:43 +01:00
(void)vsnprintf(s, MAXPATHLEN - 1, fmt, ap);
2015-10-05 10:29:07 +01:00
#else
2018-06-14 11:27:43 +01:00
(void)vsprintf(s, fmt, ap);
2015-10-05 10:29:07 +01:00
#endif
2018-06-14 11:27:43 +01:00
va_end(ap);
break;
}
2018-04-07 19:45:18 +01:00
}
2018-06-14 11:27:43 +01:00
Yap_MkErrorRecord(LOCAL_ActiveError, file, function, lineno, type, where, s);
if (where == 0 || where == TermNil) {
2018-04-07 19:45:18 +01:00
LOCAL_ActiveError->culprit = 0;
}
2018-04-09 02:00:51 +01:00
if (P == (yamop *)(FAILCODE)) {
2018-04-07 19:45:18 +01:00
LOCAL_PrologMode &= ~InErrorMode;
return P;
}
/* PURE_ABORT may not have set where correctly, BootMode may not have the data
* terms ready */
if (type == ABORT_EVENT || LOCAL_PrologMode & BootMode) {
LOCAL_PrologMode &= ~AbortMode;
LOCAL_PrologMode &= ~InErrorMode;
/* make sure failure will be seen at next port */
// no need to lock & unlock
if (LOCAL_PrologMode & AsyncIntMode)
Yap_signal(YAP_FAIL_SIGNAL);
P = FAILCODE;
} else {
/* Exit Abort Mode, if we were there */
LOCAL_PrologMode &= ~AbortMode;
LOCAL_PrologMode |= InErrorMode;
}
2015-10-05 10:29:07 +01:00
2015-06-19 01:30:13 +01:00
#ifdef DEBUG
2018-04-07 19:45:18 +01:00
// DumpActiveGoals( USES_REGS1 );
#endif /* DEBUG */
2018-10-28 10:10:40 +00:00
if (LOCAL_ActiveError->errorNo!= SYNTAX_ERROR)
2018-10-29 10:24:32 +00:00
LOCAL_ActiveError->prologStack=Yap_dump_stack();
2016-05-14 11:34:27 +01:00
CalculateStackGap(PASS_REGS1);
2015-10-18 11:39:25 +01:00
#if DEBUG
2017-10-18 01:02:52 +01:00
// DumpActiveGoals( PASS_REGS1 );
2015-10-18 11:39:25 +01:00
#endif
2016-05-14 11:34:27 +01:00
/* wait if we we are in user code,
2015-10-18 11:39:25 +01:00
it's up to her to decide */
2018-05-16 00:00:12 +01:00
if (LOCAL_delay)
return P;
2018-01-18 14:47:27 +00:00
if (LOCAL_DoingUndefp) {
2018-06-25 13:44:09 +01:00
LOCAL_DoingUndefp = false;
2018-04-09 02:00:51 +01:00
LOCAL_Signals = 0;
2019-02-27 04:23:21 +00:00
yap_error_descriptor_t *co = CopyException( LOCAL_ActiveError );
Yap_PrintWarning(MkErrorTerm(Yap_GetException( co )));
2018-03-29 22:33:53 +01:00
return P;
2018-01-18 14:47:27 +00:00
}
2018-06-14 11:27:43 +01:00
// LOCAL_ActiveError = Yap_GetException();
2018-04-09 02:00:51 +01:00
// reset_error_description();
2018-04-07 19:45:18 +01:00
if (!throw) {
2018-04-02 14:49:45 +01:00
Yap_JumpToEnv();
2018-06-18 10:25:17 +01:00
pop_text_stack(LOCAL_MallocDepth+1);
2018-04-07 19:45:18 +01:00
}
LOCAL_PrologMode = UserMode;
2016-05-14 11:34:27 +01:00
return P;
}
2018-04-07 19:45:18 +01:00
static Int close_error(USES_REGS1) {
2018-05-27 00:47:03 +01:00
if (!LOCAL_CommittedError)
return true;
LOCAL_CommittedError->errorNo = YAP_NO_ERROR;
2018-06-27 11:38:42 +01:00
LOCAL_ErrorMessage = NULL;
2018-05-27 00:47:03 +01:00
free(LOCAL_CommittedError);
LOCAL_CommittedError = NULL;
2018-04-07 19:45:18 +01:00
return true;
}
#undef BEGIN_ERROR_CLASSES
#undef ECLASS
#undef END_ERROR_CLASSES
#undef BEGIN_ERRORS
#undef E0
#undef E
2018-04-17 17:47:40 +01:00
#undef E1
2018-04-07 19:45:18 +01:00
#undef E2
#undef END_ERRORS
#define BEGIN_ERROR_CLASSES() typedef enum aux_class {
#define ECLASS(CL, A, B) CL##__,
2018-06-14 11:27:43 +01:00
#define END_ERROR_CLASSES() \
} \
aux_class_t;
2018-04-07 19:45:18 +01:00
#define BEGIN_ERRORS()
#define E0(X, Y)
#define E(X, Y, Z)
2018-04-17 17:47:40 +01:00
#define E1(X, Y, Z)
2018-04-07 19:45:18 +01:00
#define E2(X, Y, Z, W)
#define END_ERRORS()
#include <YapErrors.h>
#undef BEGIN_ERROR_CLASSES
#undef ECLASS
#undef END_ERROR_CLASSES
#undef BEGIN_ERRORS
#undef E0
#undef E
2018-04-17 17:47:40 +01:00
#undef E1
2018-04-07 19:45:18 +01:00
#undef E2
#undef END_ERRORS
#define BEGIN_ERROR_CLASSES() static const char *c_error_class_name[] = {
#define ECLASS(CL, A, B) A,
2018-06-14 11:27:43 +01:00
#define END_ERROR_CLASSES() \
NULL \
2018-04-07 19:45:18 +01:00
}
typedef struct c_error_info {
int class;
const char *name;
} c_error_t;
#define BEGIN_ERRORS() static struct c_error_info c_error_list[] = {
#define E0(X, Y) {Y##__, ""},
#define E(X, Y, Z) {Y##__, Z},
2018-04-17 17:47:40 +01:00
#define E1(X, Y, Z) {Y##__, Z},
2018-04-07 19:45:18 +01:00
#define E2(X, Y, Z, W) {Y##__, Z " " W},
2018-06-14 11:27:43 +01:00
#define END_ERRORS() \
{ YAPC_NO_ERROR, "" } \
} \
2018-04-07 19:45:18 +01:00
;
#include <YapErrors.h>
2018-06-30 14:33:32 +01:00
#include <iopreds.h>
2018-04-07 19:45:18 +01:00
yap_error_class_number Yap_errorClass(yap_error_number e) {
return c_error_list[e].class;
}
const char *Yap_errorName(yap_error_number e) { return c_error_list[e].name; }
const char *Yap_errorClassName(yap_error_class_number e) {
return c_error_class_name[e];
}
2018-06-14 11:27:43 +01:00
yap_error_descriptor_t *Yap_GetException(yap_error_descriptor_t *i) {
2018-04-07 19:45:18 +01:00
CACHE_REGS
2018-06-14 11:27:43 +01:00
if (i->errorNo != YAP_NO_ERROR) {
yap_error_descriptor_t *t = LOCAL_ActiveError,
2018-06-30 14:33:32 +01:00
*nt = calloc(1,sizeof(yap_error_descriptor_t));
memmove(nt, t, sizeof(yap_error_descriptor_t));
2018-06-14 11:27:43 +01:00
return nt;
}
2018-04-07 19:45:18 +01:00
return 0;
}
2018-07-17 11:43:57 +01:00
void Yap_PrintException(yap_error_descriptor_t *i) {
printErr(LOCAL_ActiveError);
}
2018-04-07 19:45:18 +01:00
bool Yap_RaiseException(void) {
2018-06-17 10:44:38 +01:00
if (LOCAL_ActiveError == NULL ||
LOCAL_ActiveError->errorNo == YAP_NO_ERROR)
2018-04-07 19:45:18 +01:00
return false;
2018-06-17 10:44:38 +01:00
Yap_RestartYap(5);
2018-06-26 11:07:07 +01:00
return false;
2018-06-17 10:44:38 +01:00
//return Yap_JumpToEnv();
2018-04-07 19:45:18 +01:00
}
bool Yap_ResetException(yap_error_descriptor_t *i) {
// reset error descriptor
2018-04-09 02:00:51 +01:00
if (!i)
2019-02-21 21:03:44 +00:00
i = LOCAL_ActiveError;
2018-04-07 19:45:18 +01:00
yap_error_descriptor_t *bf = i->top_error;
memset(i, 0, sizeof(*i));
i->top_error = bf;
return true;
}
2018-06-14 11:27:43 +01:00
static Int reset_exception(USES_REGS1) { return Yap_ResetException(worker_id); }
2018-04-07 19:45:18 +01:00
2019-02-27 04:23:21 +00:00
2018-04-09 02:00:51 +01:00
Term MkErrorTerm(yap_error_descriptor_t *t) {
if (t->errorClass == EVENT)
2018-04-07 19:45:18 +01:00
return t->errorRawTerm;
2018-07-03 12:42:33 +01:00
Term tc = t->culprit ? Yap_BufferToTerm(t->culprit, TermNil) : TermNil;
if (tc == 0)
tc = MkAtomTerm(Yap_LookupAtom(t->culprit));
2018-04-09 02:00:51 +01:00
return mkerrort(t->errorNo,
2018-07-03 12:42:33 +01:00
tc,
2018-04-09 02:00:51 +01:00
err2list(t));
2018-04-07 19:45:18 +01:00
}
2019-02-27 04:23:21 +00:00
static yap_error_descriptor_t *CopyException(yap_error_descriptor_t *t) {
yap_error_descriptor_t *n = malloc( sizeof( yap_error_descriptor_t ));
memcpy(n, t, sizeof( yap_error_descriptor_t ) );
return n;
}
2018-04-07 19:45:18 +01:00
static Int read_exception(USES_REGS1) {
yap_error_descriptor_t *t = AddressOfTerm(Deref(ARG1));
Term rc = MkErrorTerm(t);
// Yap_DebugPlWriteln(rc);
return Yap_unify(ARG2, rc);
}
2018-06-28 12:48:29 +01:00
static Int print_exception(USES_REGS1) {
2018-06-30 14:33:32 +01:00
Term t1 = Deref(ARG1);
if (IsAddressTerm(t1)) {
yap_error_descriptor_t *t = AddressOfTerm(t1);
2019-01-30 10:44:28 +00:00
if (t->parserFile && t->parserLine) {
fprintf(stderr,"\n%s:%ld:0 error: while parsing %s\n\n", t->parserFile, t->parserLine,t->errorAsText);
} else if (t->prologPredFile && t->prologPredLine) {
fprintf(stderr,"\n%s:%ld:0 error: while running %s\n\n", t->prologPredFile, t->prologPredLine,t->errorAsText);
} else if (t->errorFile && t->errorLine) {
fprintf(stderr,"\n%s:%ld:0 error: while executing %s\n\n", t->errorFile, t->errorLine,t->errorAsText);
}
2018-06-30 14:33:32 +01:00
printErr(t);
} else {
return Yap_WriteTerm(LOCAL_c_error_stream,t1,TermNil PASS_REGS);
}
2018-06-28 12:48:29 +01:00
// Yap_DebugPlWriteln(rc);
return true;
}
2018-04-07 19:45:18 +01:00
static Int query_exception(USES_REGS1) {
2018-10-23 10:09:17 +01:00
const char *query = NULL;
2018-04-07 19:45:18 +01:00
Term t;
2018-04-09 02:00:51 +01:00
2018-04-07 19:45:18 +01:00
if (IsAtomTerm((t = Deref(ARG1))))
query = RepAtom(AtomOfTerm(t))->StrOfAE;
if (IsStringTerm(t))
query = StringOfTerm(t);
2018-04-09 02:00:51 +01:00
if (!IsAddressTerm(Deref(ARG2)))
2018-04-07 19:45:18 +01:00
return false;
yap_error_descriptor_t *y = AddressOfTerm(Deref(ARG2));
2018-11-14 09:35:24 +00:00
// if (IsVarTerm(t3)) {
2018-04-07 19:45:18 +01:00
Term rc = queryErr(query, y);
// Yap_DebugPlWriteln(rc);
return Yap_unify(ARG3, rc);
2018-10-23 10:09:17 +01:00
// } else {
// return setErr(query, y, t3);
// }
2018-04-07 19:45:18 +01:00
}
2018-11-14 09:35:24 +00:00
static Int set_exception(USES_REGS1) {
const char *query = NULL;
Term t;
if (IsAtomTerm((t = Deref(ARG1))))
query = RepAtom(AtomOfTerm(t))->StrOfAE;
if (IsStringTerm(t))
query = StringOfTerm(t);
if (!IsAddressTerm(Deref(ARG2)))
return false;
yap_error_descriptor_t *y = AddressOfTerm(Deref(ARG2));
Term t3 = Deref(ARG3);
if (IsVarTerm(t3)) {
return false;
} else {
return setErr(query, y, t3);
}
}
2018-06-28 12:48:29 +01:00
2018-04-07 19:45:18 +01:00
static Int drop_exception(USES_REGS1) {
yap_error_descriptor_t *t = AddressOfTerm(Deref(ARG1));
free(t);
return true;
2018-04-09 02:00:51 +01:00
}
2018-04-07 19:45:18 +01:00
static Int new_exception(USES_REGS1) {
2018-06-14 11:27:43 +01:00
Term t = MkSysError(calloc(1, sizeof(yap_error_descriptor_t)));
2018-04-09 02:00:51 +01:00
return Yap_unify(ARG1, t);
}
2018-04-07 19:45:18 +01:00
2018-06-14 11:27:43 +01:00
static Int get_exception(USES_REGS1) {
2018-04-07 19:45:18 +01:00
yap_error_descriptor_t *i;
Term t;
2018-04-09 02:00:51 +01:00
2018-05-27 00:47:03 +01:00
if (LOCAL_ActiveError->errorNo != YAP_NO_ERROR) {
i = Yap_GetException(LOCAL_ActiveError);
Yap_ResetException(LOCAL_ActiveError);
LOCAL_PrologMode = UserMode;
if (i->errorRawTerm &&
2018-06-14 11:27:43 +01:00
(i->errorClass == EVENT || i->errorNo == SYNTAX_ERROR)) {
2018-04-07 19:45:18 +01:00
t = i->errorRawTerm;
} else if (i->culprit != NULL) {
2018-10-08 13:51:17 +01:00
Term culprit = Yap_BufferToTerm(i->culprit, TermNil);
if (culprit == 0) culprit = TermNil;
t = mkerrort(i->errorNo,culprit ,
2018-04-09 02:00:51 +01:00
MkSysError(i));
} else {
t = mkerrort(i->errorNo, TermNil, MkSysError(i));
}
2018-06-14 11:27:43 +01:00
return Yap_unify(ARG1, t);
}
2018-04-07 19:45:18 +01:00
return false;
}
yap_error_descriptor_t *event(Term t, yap_error_descriptor_t *i) {
i->errorNo = ERROR_EVENT;
i->errorClass = EVENT;
i->errorRawTerm = Yap_SaveTerm(t);
return i;
}
2018-04-09 02:00:51 +01:00
yap_error_descriptor_t *Yap_UserError(Term t, yap_error_descriptor_t *i) {
Term n = t;
bool found = false, wellformed = true;
2018-06-25 13:44:09 +01:00
if (!IsApplTerm(t) || FunctorOfTerm(t) != FunctorError) {
LOCAL_Error_TYPE = THROW_EVENT;
LOCAL_ActiveError->errorClass = EVENT;
LOCAL_ActiveError->errorAsText = Yap_errorName(THROW_EVENT);
LOCAL_ActiveError->classAsText =
Yap_errorClassName(Yap_errorClass(THROW_EVENT));
LOCAL_ActiveError->errorRawTerm = Yap_SaveTerm(t);
LOCAL_ActiveError->culprit = NULL;
} else if (i->errorNo != YAP_NO_ERROR && i->errorNo != ERROR_EVENT) {
LOCAL_Error_TYPE = i->errorNo;
LOCAL_ActiveError->errorClass = Yap_errorClass(i->errorNo);
LOCAL_ActiveError->errorAsText = Yap_errorName(i->errorNo);
LOCAL_ActiveError->classAsText =
Yap_errorClassName(Yap_errorClass(i->errorNo));
LOCAL_ActiveError->errorRawTerm = Yap_SaveTerm(t);
LOCAL_ActiveError->culprit = NULL;
} else {
2018-06-14 11:27:43 +01:00
Term t1, t2;
t1 = ArgOfTerm(1, t);
t2 = ArgOfTerm(2, t);
// LOCAL_Error_TYPE = ERROR_EVENT;
wellformed = wellformed && (i->errorAsText != NULL);
if (wellformed) {
int j;
for (j = 0; j < sizeof(c_error_list) / sizeof(struct c_error_info); j++) {
if (!strcmp(c_error_list[j].name, i->errorAsText) &&
(c_error_list[j].class == 0 ||
!strcmp(i->classAsText,
c_error_class_name[c_error_list[j].class]))) {
if (c_error_list[j].class != PERMISSION_ERROR ||
(t1 = ArgOfTerm(2, t1) && IsAtomTerm(t1) &&
!strcmp(c_error_list[j].name,
RepAtom(AtomOfTerm(t1))->StrOfAE) &&
c_error_list[j].class != EVENT)) {
i->errorNo = j;
i->errorClass = c_error_list[j].class;
found = true;
break;
}
}
2018-06-14 11:27:43 +01:00
}
} else if (IsAtomTerm(t1)) {
const char *err = RepAtom(AtomOfTerm(t1))->StrOfAE;
if (!strcmp(err, "instantiation_error")) {
i->errorClass = INSTANTIATION_ERROR_CLASS;
i->classAsText = "instantiation_error";
i->errorAsText = "instantiation_error";
i->errorNo = INSTANTIATION_ERROR;
found = true;
} else if (!strcmp(err, "uninstantiation_error")) {
i->errorClass = UNINSTANTIATION_ERROR_CLASS;
i->classAsText = "uninstantiation_error";
i->errorAsText = "uninstantiation_error";
i->errorNo = UNINSTANTIATION_ERROR;
found = true;
2018-04-09 02:00:51 +01:00
}
}
if (i->errorAsText && i->errorAsText[0]) {
char *errs = malloc(strlen(i->errorAsText) + 1);
strcpy(errs, i->errorAsText);
i->errorAsText = errs;
2018-04-07 19:45:18 +01:00
}
if (!found) {
return event(t, i);
2018-04-09 02:00:51 +01:00
}
if (found) {
n = t2;
}
2018-06-14 11:27:43 +01:00
i->errorGoal = Yap_TermToBuffer(
2018-08-15 01:29:20 +01:00
n, Quote_illegal_f | Ignore_ops_f );
2018-04-09 02:00:51 +01:00
}
Yap_prolog_add_culprit(i PASS_REGS);
return i;
2018-04-07 19:45:18 +01:00
}
2018-04-09 02:00:51 +01:00
static Int is_boolean(USES_REGS1) {
Term t = Deref(ARG1);
// Term Context = Deref(ARG2)Yap_Error(INSTANTIATION_ERROR, t, NULL);;
if (IsVarTerm(t)) {
Yap_Error(INSTANTIATION_ERROR, t, NULL);
return false;
}
return t == TermTrue || t == TermFalse;
}
static Int is_atom(USES_REGS1) {
Term t = Deref(ARG1);
// Term Context = Deref(ARG2)Yap_Error(INSTANTIATION_ERROR, t, NULL);;
if (IsVarTerm(t)) {
Yap_Error(INSTANTIATION_ERROR, t, NULL);
return false;
}
return IsAtomTerm(t);
}
static Int is_callable(USES_REGS1) {
Term G = Deref(ARG1);
// Term Context = Deref(ARG2);
while (true) {
if (IsVarTerm(G)) {
2019-04-10 18:51:40 +01:00
//Yap_ThrowError(INSTANTIATION_ERROR, G, NULL);
return false;
}
if (IsApplTerm(G)) {
Functor f = FunctorOfTerm(G);
if (IsExtensionFunctor(f)) {
2018-08-15 01:29:20 +01:00
Yap_ThrowError(TYPE_ERROR_CALLABLE, G, NULL);
}
if (f == FunctorModule) {
2018-06-14 11:27:43 +01:00
Term tm = ArgOfTerm(1, G);
if (IsVarTerm(tm)) {
2018-08-15 01:29:20 +01:00
Yap_ThrowError(INSTANTIATION_ERROR, G, NULL);
2018-06-14 11:27:43 +01:00
return false;
}
if (!IsAtomTerm(tm)) {
2018-08-15 01:29:20 +01:00
Yap_ThrowError(TYPE_ERROR_CALLABLE, G, NULL);
2018-06-14 11:27:43 +01:00
return false;
}
G = ArgOfTerm(2, G);
} else {
2018-06-14 11:27:43 +01:00
return true;
}
} else if (IsPairTerm(G) || IsAtomTerm(G)) {
return true;
} else {
2018-08-15 01:29:20 +01:00
Yap_ThrowError(TYPE_ERROR_CALLABLE, G, NULL);
return false;
}
}
return false;
}
2019-01-21 01:11:42 +00:00
/**
* @pred is_predicate_indicator( Term, Module, Name, Arity )
*
* This predicates can be used to verify if Term is a predicate indicator, that is of the form:
* + Name/Arity
* + Name//Arity-2
* + Module:Name/Arity
* + Module:Name//Arity-2
*
* if it is, it will extract the predicate's module, name, and arity.
2019-03-31 11:45:03 +01:00
*
* Note: this will now accept both mod:(a/n) and
* (mod:a)/n as valid.
2019-01-21 01:11:42 +00:00
*/
static Int get_predicate_indicator(USES_REGS1) {
Term G = Deref(ARG1);
// Term Context = Deref(ARG2);
Term mod = CurrentModule;
G = Yap_YapStripModule(G, &mod);
if (IsVarTerm(G)) {
2019-01-21 01:11:42 +00:00
Yap_ThrowError(INSTANTIATION_ERROR, G, NULL);
}
if (!IsVarTerm(mod) && !IsAtomTerm(mod)) {
Yap_Error(TYPE_ERROR_ATOM, G, NULL);
return false;
}
if (IsApplTerm(G)) {
Functor f = FunctorOfTerm(G);
if (IsExtensionFunctor(f)) {
2019-01-21 01:11:42 +00:00
Yap_ThrowError(TYPE_ERROR_PREDICATE_INDICATOR, G, NULL);
}
if (f == FunctorSlash || f == FunctorDoubleSlash) {
2019-01-21 01:11:42 +00:00
Term name = ArgOfTerm(1,G), arity = ArgOfTerm(2,G);
2019-03-31 11:45:03 +01:00
name = Yap_YapStripModule (name, &mod);
2019-01-21 01:11:42 +00:00
if (IsVarTerm(name)) {
Yap_ThrowError(INSTANTIATION_ERROR, name, NULL);
} else if (!IsAtomTerm(name)) {
Yap_ThrowError(TYPE_ERROR_ATOM, name, NULL);
}
if (IsVarTerm(arity)) {
Yap_ThrowError(INSTANTIATION_ERROR, arity, NULL);
} else if (!IsIntegerTerm(arity)) {
Yap_ThrowError(TYPE_ERROR_INTEGER, arity, NULL);
} else {
Int ar = IntegerOfTerm(arity);
if (ar < 0) {
Yap_ThrowError(DOMAIN_ERROR_NOT_LESS_THAN_ZERO, arity, NULL);
}
if ( f == FunctorDoubleSlash) {
arity = MkIntegerTerm(ar+2);
}
return Yap_unify(mod, ARG2) &&
Yap_unify(name, ARG3) &&
Yap_unify(arity, ARG4);
}
}
}
2019-01-21 01:11:42 +00:00
Yap_ThrowError(TYPE_ERROR_PREDICATE_INDICATOR, G, NULL);
return false;
}
void Yap_InitErrorPreds(void) {
CACHE_REGS
2018-10-31 00:35:49 +00:00
Yap_InitCPred("$print_exception", 1, print_exception, 0);
2018-06-14 11:27:43 +01:00
Yap_InitCPred("$reset_exception", 1, reset_exception, 0);
2018-04-07 19:45:18 +01:00
Yap_InitCPred("$new_exception", 1, new_exception, 0);
Yap_InitCPred("$get_exception", 1, get_exception, 0);
2018-11-14 09:35:24 +00:00
Yap_InitCPred("$set_exception", 3, set_exception, 0);
2018-04-07 19:45:18 +01:00
Yap_InitCPred("$read_exception", 2, read_exception, 0);
Yap_InitCPred("$query_exception", 3, query_exception, 0);
Yap_InitCPred("$drop_exception", 1, drop_exception, 0);
Yap_InitCPred("$close_error", 0, close_error, HiddenPredFlag);
2019-01-21 01:11:42 +00:00
Yap_InitCPred("is_boolean", 1, is_boolean, TestPredFlag);
Yap_InitCPred("is_callable", 1, is_callable, TestPredFlag);
Yap_InitCPred("is_atom", 1, is_atom, TestPredFlag);
Yap_InitCPred("get_predicate_indicator", 4, get_predicate_indicator, 0);
}