diff --git a/C/write.c b/C/write.c index 0c7c87795..ac7cce3a6 100644 --- a/C/write.c +++ b/C/write.c @@ -51,6 +51,24 @@ typedef enum { typedef StreamDesc *wrf; +typedef struct union_slots { + Int old; + Int ptr; +} uslots; + +typedef struct union_direct { + Term old; + CELL *ptr; +} udirect; + +typedef struct rewind_term { + struct rewind_term *parent; + union { + struct union_slots s; + struct union_direct d; + } u_sd; +} rwts; + typedef struct write_globs { StreamDesc *stream; int Quote_illegal, Ignore_ops, Handle_vars, Use_portray, Portray_delays; @@ -91,7 +109,8 @@ static int legalAtom(unsigned char *); static int RightOpToProtect(Atom, int);*/ static wtype AtomIsSymbols(unsigned char *); static void putAtom(Atom, int, struct write_globs *); -static void writeTerm(Term, int, int, int, struct write_globs *); +static void writeTerm(Term, int, int, int, struct write_globs *, + struct rewind_term *); #define wrputc(WF, X) \ (X)->stream_wputc(X - GLOBAL_Stream, WF) /* writes a character */ @@ -226,7 +245,7 @@ static void write_mpint(MP_INT *big, struct write_globs *wglb) { /* writes a bignum */ static void writebig(Term t, int p, int depth, int rinfixarg, - struct write_globs *wglb) { + struct write_globs *wglb, struct rewind_term *rwt) { CELL *pt = RepAppl(t) + 1; CELL big_tag = pt[0]; @@ -243,7 +262,7 @@ static void writebig(Term t, int p, int depth, int rinfixarg, return; } else if (big_tag == BIG_RATIONAL) { Term trat = Yap_RatTermToApplTerm(t); - writeTerm(trat, p, depth, rinfixarg, wglb); + writeTerm(trat, p, depth, rinfixarg, wglb, rwt); return; #endif } else if (big_tag >= USER_BLOB_START && big_tag < USER_BLOB_END) { @@ -655,9 +674,63 @@ static void putUnquotedString(Term string, struct write_globs *wglb) lastw = alphanum; } +static Term from_pointer(CELL *ptr0, struct rewind_term *rwt, + struct write_globs *wglb) { + CACHE_REGS + Term t; + CELL *ptr = ptr0; + + while (IsVarTerm(*ptr) && !IsUnboundVar(ptr)) + ptr = (CELL *)*ptr; + t = *ptr; + if (wglb->Keep_terms) { + struct rewind_term *x = rwt->parent; + + rwt->u_sd.s.old = Yap_InitSlot(t); + rwt->u_sd.s.ptr = Yap_InitSlot((CELL)ptr0); + + if (!IsAtomicTerm(t) && !IsVarTerm(t)) { + while (x) { + if (Yap_GetDerefedFromSlot(x->u_sd.s.old) == t) + return TermFoundVar; + x = x->parent; + } + } + } else { + rwt->u_sd.d.old = t; + rwt->u_sd.d.ptr = ptr0; + if (!IsVarTerm(t) && !IsAtomicTerm(t)) { + struct rewind_term *x = rwt->parent; + + while (x) { + if (x->u_sd.d.old == t) + return TermFoundVar; + x = x->parent; + } + } + } + return t; +} + +static CELL *restore_from_write(struct rewind_term *rwt, + struct write_globs *wglb) { + CACHE_REGS + CELL *ptr; + + if (wglb->Keep_terms) { + ptr = Yap_GetPtrFromSlot(rwt->u_sd.s.ptr); + Yap_RecoverSlots(2, rwt->u_sd.s.old); + // printf("leak=%d %d\n", LOCALCurSlot,rwt->u_sd.s.old) ; + } else { + ptr = rwt->u_sd.d.ptr; + } + rwt->u_sd.s.ptr = 0; + return ptr; +} /* writes an unbound variable */ -static void write_var(CELL *t, struct write_globs *wglb) { +static void write_var(CELL *t, struct write_globs *wglb, + struct rewind_term *rwt) { CACHE_REGS if (lastw == alphanum) { wrputc(' ', wglb->stream); @@ -669,6 +742,9 @@ static void write_var(CELL *t, struct write_globs *wglb) { Int vcount = (t - H0); if (wglb->Portray_delays) { exts ext = ExtFromCell(t); + struct rewind_term nrwt; + nrwt.parent = rwt; + nrwt.u_sd.s.ptr = 0; wglb->Portray_delays = FALSE; if (ext == attvars_ext) { @@ -677,15 +753,17 @@ static void write_var(CELL *t, struct write_globs *wglb) { CELL *l = &attv->Value; /* dirty low-level hack, check atts.h */ wrputs("$AT(", wglb->stream); - write_var(t, wglb); + write_var(t, wglb, rwt); wrputc(',', wglb->stream); - writeTerm(l[0], 999, 1, FALSE, wglb); + writeTerm(from_pointer(l, &nrwt, wglb), 999, 1, FALSE, wglb, &nrwt); + l = restore_from_write(&nrwt, wglb); wrputc(',', wglb->stream); attv = RepAttVar((CELL *)Yap_GetFromHandle(h)); l = &attv->Value;; l++; - writeTerm(l[1], 999, 1, FALSE, wglb); + writeTerm(from_pointer(l, &nrwt, wglb), 999, 1, FALSE, wglb, &nrwt); + restore_from_write(&nrwt, wglb); wrclose_bracket(wglb, TRUE); } wglb->Portray_delays = TRUE; @@ -698,22 +776,57 @@ static void write_var(CELL *t, struct write_globs *wglb) { } } +static Term check_infinite_loop(Term t, struct rewind_term *x, + struct write_globs *wglb) { + CACHE_REGS + if (wglb->Keep_terms) { + while (x) { + if (Yap_GetFromSlot(x->u_sd.s.old) == t) + return TermFoundVar; + x = x->parent; + } + } else { + while (x) { + if (x->u_sd.d.old == t) + return TermFoundVar; + x = x->parent; + } + } + return t; +} static void write_list(Term t, int direction, int depth, - struct write_globs *wglb) { - yhandle_t h = Yap_InitHandle(t); + struct write_globs *wglb, struct rewind_term *rwt) { + Term ti; + struct rewind_term nrwt; + nrwt.parent = rwt; + nrwt.u_sd.s.ptr = 0; while (1) { - writeTerm(HeadOfTerm(t), 999, depth + 1, FALSE, - wglb); - Yap_DebugPlWriteln(TermNil); - t = Yap_GetFromHandle(h); - t = TailOfTerm(t); - if (IsVarTerm(t)) + int ndirection; + int do_jump; + + writeTerm(from_pointer(RepPair(t), &nrwt, wglb), 999, depth + 1, FALSE, + wglb, &nrwt); + t = AbsPair(restore_from_write(&nrwt, wglb)); + ti = TailOfTerm(t); + if (IsVarTerm(ti)) break; - if (!IsPairTerm(t)) + if (!IsPairTerm(ti) || + !IsPairTerm((ti = check_infinite_loop(ti, rwt, wglb)))) break; - Yap_PutInHandle(h, t); + ndirection = RepPair(ti) - RepPair(t); + /* make sure we're not trapped in loops */ + if (ndirection > 0) { + do_jump = (direction <= 0); + } else if (ndirection == 0) { + wrputc(',', wglb->stream); + putAtom(AtomFoundVar, wglb->Quote_illegal, wglb); + lastw = separator; + return; + } else { + do_jump = (direction >= 0); + } if (wglb->MaxDepth != 0 && depth > wglb->MaxDepth) { if (lastw == symbol || lastw == separator) { wrputc(' ', wglb->stream); @@ -723,28 +836,50 @@ static void write_list(Term t, int direction, int depth, return; } lastw = separator; + direction = ndirection; depth++; + if (do_jump) + break; wrputc(',', wglb->stream); + t = ti; } - if (t !=TermNil) { + if (IsPairTerm(ti)) { + Term nt = from_pointer(RepPair(t) + 1, &nrwt, wglb); + /* we found an infinite loop */ + if (IsAtomTerm(nt)) { + if (lastw == symbol || lastw == separator) { + wrputc(' ', wglb->stream); + } + wrputc('|', wglb->stream); + writeTerm(nt, 999, depth, FALSE, wglb, rwt); + } else { + /* keep going on the list */ + wrputc(',', wglb->stream); + write_list(nt, direction, depth, wglb, &nrwt); + } + restore_from_write(&nrwt, wglb); + } else if (ti != MkAtomTerm(AtomNil)) { if (lastw == symbol || lastw == separator) { wrputc(' ', wglb->stream); } wrputc('|', wglb->stream); lastw = separator; - writeTerm(t, 999, depth, FALSE, - wglb); + writeTerm(from_pointer(RepPair(t) + 1, &nrwt, wglb), 999, depth, FALSE, + wglb, &nrwt); + restore_from_write(&nrwt, wglb); } } static void writeTerm(Term t, int p, int depth, int rinfixarg, - struct write_globs *wglb) + struct write_globs *wglb, struct rewind_term *rwt) /* term to write */ /* context priority */ { CACHE_REGS - yhandle_t h = Yap_InitHandle(t); + struct rewind_term nrwt; + nrwt.parent = rwt; + nrwt.u_sd.s.ptr = 0; if (wglb->MaxDepth != 0 && depth > wglb->MaxDepth) { putAtom(Atom3Dots, wglb->Quote_illegal, wglb); @@ -752,7 +887,7 @@ static void writeTerm(Term t, int p, int depth, int rinfixarg, } t = Deref(t); if (IsVarTerm(t)) { - write_var((CELL *)t, wglb); + write_var((CELL *)t, wglb, &nrwt); } else if (IsIntTerm(t)) { wrputn((Int)IntOfTerm(t), wglb); @@ -763,12 +898,13 @@ static void writeTerm(Term t, int p, int depth, int rinfixarg, wrputs("'.'(", wglb->stream); lastw = separator; - writeTerm(HeadOfTerm(t), 999, depth + 1, FALSE, - wglb); + writeTerm(from_pointer(RepPair(t), &nrwt, wglb), 999, depth + 1, FALSE, + wglb, &nrwt); + t = AbsPair(restore_from_write(&nrwt, wglb)); wrputs(",", wglb->stream); - t = Yap_GetFromHandle(h); - writeTerm(TailOfTerm(t), 999, depth + 1, - FALSE, wglb); + writeTerm(from_pointer(RepPair(t) + 1, &nrwt, wglb), 999, depth + 1, + FALSE, wglb, &nrwt); + restore_from_write(&nrwt, wglb); wrclose_bracket(wglb, TRUE); return; } @@ -782,7 +918,7 @@ static void writeTerm(Term t, int p, int depth, int rinfixarg, wrputc('[', wglb->stream); lastw = separator; /* we assume t was already saved in the stack */ - write_list(t, 0, depth, wglb); + write_list(t, 0, depth, wglb, rwt); wrputc(']', wglb->stream); lastw = separator; } @@ -801,7 +937,7 @@ static void writeTerm(Term t, int p, int depth, int rinfixarg, write_string(UStringOfTerm(t), wglb); return; case (CELL)FunctorAttVar: - write_var(RepAppl(t) + 1, wglb); + write_var(RepAppl(t) + 1, wglb, &nrwt); return; case (CELL)FunctorDBRef: wrputref(RefOfTerm(t), wglb->Quote_illegal, wglb); @@ -811,7 +947,7 @@ static void writeTerm(Term t, int p, int depth, int rinfixarg, return; /* case (CELL)FunctorBigInt: */ default: - writebig(t, p, depth, rinfixarg, wglb); + writebig(t, p, depth, rinfixarg, wglb, rwt); return; } } @@ -834,7 +970,8 @@ static void writeTerm(Term t, int p, int depth, int rinfixarg, *p++; lastw = separator; /* cannot use the term directly with the SBA */ - writeTerm(p, 999, depth + 1, FALSE, wglb); + writeTerm(from_pointer(p, &nrwt, wglb), 999, depth + 1, FALSE, wglb, + &nrwt); p = restore_from_write(&nrwt, wglb) + 1; if (*p) wrputc(',', wglb->stream); @@ -863,8 +1000,10 @@ static void writeTerm(Term t, int p, int depth, int rinfixarg, } else if (atom == AtomMinus) { last_minus = TRUE; } - writeTerm(ArgOfTerm(1,t), rp, depth + 1, TRUE, wglb); - if (bracket_right) { + writeTerm(from_pointer(RepAppl(t) + 1, &nrwt, wglb), rp, depth + 1, TRUE, + wglb, &nrwt); + restore_from_write(&nrwt, wglb); + if (bracket_right) { wrclose_bracket(wglb, TRUE); } if (op > p) { @@ -896,9 +1035,9 @@ static void writeTerm(Term t, int p, int depth, int rinfixarg, if (bracket_left) { wropen_bracket(wglb, TRUE); } - writeTerm(ArgOfTerm(offset,t), lp, depth + 1, - rinfixarg, wglb); - t = Yap_GetFromHandle(h); + writeTerm(from_pointer(RepAppl(t) + offset, &nrwt, wglb), lp, depth + 1, + rinfixarg, wglb, &nrwt); + restore_from_write(&nrwt, wglb); if (bracket_left) { wrclose_bracket(wglb, TRUE); } @@ -911,7 +1050,7 @@ static void writeTerm(Term t, int p, int depth, int rinfixarg, wrputc('{', wglb->stream); } lastw = separator; - write_list(tleft, 0, depth, wglb); + write_list(tleft, 0, depth, wglb, rwt); if (atom == AtomEmptyBrackets) { wrputc(')', wglb->stream); } else if (atom == AtomEmptySquareBrackets) { @@ -943,11 +1082,9 @@ static void writeTerm(Term t, int p, int depth, int rinfixarg, if (bracket_left) { wropen_bracket(wglb, TRUE); } - { - writeTerm(ArgOfTerm(1,t), lp, depth + 1, - rinfixarg, wglb); - t = Yap_GetFromHandle(h); - } + writeTerm(from_pointer(RepAppl(t) + 1, &nrwt, wglb), lp, depth + 1, + rinfixarg, wglb, &nrwt); + t = AbsAppl(restore_from_write(&nrwt, wglb) - 1); if (bracket_left) { wrclose_bracket(wglb, TRUE); } @@ -966,8 +1103,9 @@ static void writeTerm(Term t, int p, int depth, int rinfixarg, if (bracket_right) { wropen_bracket(wglb, TRUE); } - writeTerm(ArgOfTerm(2,t), rp, depth + 1, TRUE, - wglb); + writeTerm(from_pointer(RepAppl(t) + 2, &nrwt, wglb), rp, depth + 1, TRUE, + wglb, &nrwt); + restore_from_write(&nrwt, wglb); if (bracket_right) { wrclose_bracket(wglb, TRUE); } @@ -1007,17 +1145,17 @@ static void writeTerm(Term t, int p, int depth, int rinfixarg, } else { wrputs("'$VAR'(", wglb->stream); lastw = separator; - writeTerm(ArgOfTerm(1,t), 999, depth + 1, - FALSE, wglb); - t = Yap_GetFromHandle(h); + writeTerm(from_pointer(RepAppl(t) + 1, &nrwt, wglb), 999, depth + 1, + FALSE, wglb, &nrwt); + restore_from_write(&nrwt, wglb); wrclose_bracket(wglb, TRUE); } } else if (!wglb->Ignore_ops && functor == FunctorBraces) { wrputc('{', wglb->stream); lastw = separator; - writeTerm(ArgOfTerm(1,t), GLOBAL_MaxPriority, - depth + 1, FALSE, wglb); - t = Yap_GetFromHandle(h); + writeTerm(from_pointer(RepAppl(t) + 1, &nrwt, wglb), GLOBAL_MaxPriority, + depth + 1, FALSE, wglb, &nrwt); + restore_from_write(&nrwt, wglb); wrputc('}', wglb->stream); lastw = separator; } else if (atom == AtomArray) { @@ -1028,9 +1166,9 @@ static void writeTerm(Term t, int p, int depth, int rinfixarg, wrputs("...", wglb->stream); break; } - writeTerm(ArgOfTerm(op,t), 999, depth + 1, - FALSE, wglb); - t = Yap_GetFromHandle(h); + writeTerm(from_pointer(RepAppl(t) + op, &nrwt, wglb), 999, depth + 1, + FALSE, wglb, &nrwt); + t = AbsAppl(restore_from_write(&nrwt, wglb) - op); if (op != Arity) { wrputc(',', wglb->stream); lastw = separator; @@ -1049,9 +1187,9 @@ static void writeTerm(Term t, int p, int depth, int rinfixarg, wrputc('.', wglb->stream); break; } - writeTerm(ArgOfTerm(op,t), 999, depth + 1, - FALSE, wglb); - t = Yap_GetFromHandle(h); + writeTerm(from_pointer(RepAppl(t) + op, &nrwt, wglb), 999, depth + 1, + FALSE, wglb, &nrwt); + restore_from_write(&nrwt, wglb); if (op != Arity) { wrputc(',', wglb->stream); lastw = separator; @@ -1070,7 +1208,8 @@ void Yap_plwrite(Term t, StreamDesc *mywrite, int max_depth, int flags, { CACHE_REGS struct write_globs wglb; - yhandle_t sls = Yap_CurrentSlot(); + struct rewind_term rwt; + yhandle_t sls = Yap_CurrentSlot(); int lvl = push_text_stack(); if (t == 0) @@ -1092,10 +1231,11 @@ void Yap_plwrite(Term t, StreamDesc *mywrite, int max_depth, int flags, we cannot make recursive Prolog calls */ wglb.Keep_terms = (flags & (Use_portray_f | To_heap_f)); /* initialize wglb */ + rwt.parent = NULL; wglb.Ignore_ops = flags & Ignore_ops_f; wglb.Write_strings = flags & BackQuote_String_f; /* protect slots for portray */ - writeTerm(t, priority, 1, FALSE, &wglb); + writeTerm(from_pointer(&t, &rwt, &wglb), priority, 1, FALSE, &wglb, &rwt); if (flags & New_Line_f) { if (flags & Fullstop_f) { wrputc('.', wglb.stream); @@ -1109,6 +1249,7 @@ void Yap_plwrite(Term t, StreamDesc *mywrite, int max_depth, int flags, wrputc(' ', wglb.stream); } } + restore_from_write(&rwt, &wglb); Yap_CloseSlots(sls); pop_text_stack(lvl); } @@ -1122,6 +1263,8 @@ char *Yap_TermToBuffer(Term t, encoding_t enc, int flags) { return NULL; if (t == 0) return NULL; + else + t = Deref(t); if (enc) GLOBAL_Stream[sno].encoding = enc; else diff --git a/H/YapText.h b/H/YapText.h index c11b39f79..fcc102443 100644 --- a/H/YapText.h +++ b/H/YapText.h @@ -16,20 +16,15 @@ *************************************************************************/ #ifndef YAP_TEXT_H #define YAP_TEXT_H - -#if SIZEOF_WCHAR_T == 2 -#define CHARCODE_MAX 0xffff -#else -#define CHARCODE_MAX 0x10ffff -#endif +#include "Yap.h" /* - * This file defines main data-structure for text conversion and + * @file YapText.h + * @brief This file defines main data-structure for text conversion and * mirroring */ -#include "utf8proc.h" -#include "Yap.h" +#include "YapUTF8.h" /// allocate a temporary text block /// @@ -179,165 +174,6 @@ INLINE_ONLY EXTERN inline char_kind_t chtype(Int ch) { #define __android_log_print(...) #endif -INLINE_ONLY inline EXTERN utf8proc_ssize_t get_utf8(const utf8proc_uint8_t *ptr, - size_t n, - utf8proc_int32_t *valp); - -INLINE_ONLY inline EXTERN utf8proc_ssize_t get_utf8(const utf8proc_uint8_t *ptr, - size_t n, - utf8proc_int32_t *valp) { - utf8proc_ssize_t rc = utf8proc_iterate(ptr, n, valp); - if (rc < 0) { - LOCAL_ActiveError->errorNo = REPRESENTATION_ERROR_IN_CHARACTER_CODE; - } - return rc < 1 ? 1 : rc; -} - -INLINE_ONLY inline EXTERN utf8proc_ssize_t put_utf8(utf8proc_uint8_t *ptr, - utf8proc_int32_t val); - -INLINE_ONLY inline EXTERN utf8proc_ssize_t put_utf8(utf8proc_uint8_t *ptr, - utf8proc_int32_t val) { - utf8proc_ssize_t rc = utf8proc_encode_char(val, ptr); - if (rc < 0) { - LOCAL_ActiveError->errorNo = REPRESENTATION_ERROR_CHARACTER_CODE; - } - return rc < 1 ? 1 : rc; -} - -inline static const utf8proc_uint8_t *skip_utf8(const utf8proc_uint8_t *pt, - utf8proc_ssize_t n) { - utf8proc_ssize_t i; - utf8proc_int32_t b; - for (i = 0; i < n; i++) { - utf8proc_ssize_t l = utf8proc_iterate(pt, -1, &b); - if (b == 0) - return pt; - if (l < 0) { - LOCAL_ActiveError->errorNo = REPRESENTATION_ERROR_CHARACTER_CODE; - } else { - pt += l; - } - } - return pt; -} - -inline static utf8proc_ssize_t utf8_nof(utf8proc_int32_t val) { - return utf8proc_charwidth(val); -} - -inline static utf8proc_ssize_t strlen_utf8(const utf8proc_uint8_t *pt) { - utf8proc_ssize_t rc = 0; - utf8proc_int32_t b; - while (true) { - utf8proc_ssize_t l = utf8proc_iterate(pt, -1, &b); - if (b == 0) - return rc; - else if (l > 0) { - pt += l; - rc++; - } else { - LOCAL_ActiveError->errorNo = REPRESENTATION_ERROR_CHARACTER_CODE; - pt++; - } - } - return rc; -} - -inline static utf8proc_ssize_t strlen_latin_utf8(const unsigned char *pt) { - utf8proc_ssize_t rc = 0; - utf8proc_uint8_t b; - while (true) { - utf8proc_ssize_t l = utf8proc_encode_char(*pt, &b); - if (l<0) { - pt++; - } - if (b == 0) - return rc; - pt++; - rc += l; - } - return rc; -} - -inline static utf8proc_ssize_t strnlen_latin_utf8(const unsigned char *pt, - size_t max) { - utf8proc_ssize_t rc = 0; - utf8proc_uint8_t b; - while (true) { - utf8proc_ssize_t l = utf8proc_encode_char(*pt, &b); - if (b == 0) - return rc; - pt++; - if (l > 0) - rc += l; - if (--max == 0) - return rc; - } - return rc; -} - -inline static utf8proc_ssize_t strlen_ucs2_utf8(const wchar_t *pt) { - utf8proc_ssize_t rc = 0; - utf8proc_uint8_t b; - while (true) { - utf8proc_ssize_t l = utf8proc_encode_char(*pt, &b); - if (b == 0) - return rc; - if (l < 0) - continue; - pt++; - rc += l; - } - return rc; -} - -inline static utf8proc_ssize_t strnlen_ucs2_utf8(const wchar_t *pt, - size_t max) { - utf8proc_ssize_t rc = 0; - utf8proc_uint8_t b; - while (true) { - utf8proc_ssize_t l = utf8proc_encode_char(*pt, &b); - if (b == 0) - return rc; - pt++; - rc += l; - if (--max == 0) - return rc; - } - return rc; -} - -inline static int cmpn_utf8(const utf8proc_uint8_t *pt1, - const utf8proc_uint8_t *pt2, utf8proc_ssize_t n) { - utf8proc_ssize_t i; - utf8proc_int32_t b; - for (i = 0; i < n; i++) { - if (pt1[0] != pt2[0]) - return pt1[0] - pt2[0]; - utf8proc_ssize_t l = utf8proc_iterate(pt1, -1, &b); - if (l == 2) { - if (pt1[1] != pt2[1]) - return pt1[1] - pt2[1]; - } else if (l == 3) { - if (pt1[2] != pt2[2]) - return pt1[2] - pt2[2]; - } else if (l == 4) { - if (pt1[3] != pt2[3]) - return pt1[3] - pt2[3]; - } - pt1 += l; - pt2 += l; - } - return 0; -} - -// UTF16 - -#define LEAD_OFFSET ((uint32_t)0xD800 - (uint32_t)(0x10000 >> 10)) -#define SURROGATE_OFFSET \ - ((uint32_t)0x10000 - (uint32_t)(0xD800 << 10) - (uint32_t)0xDC00) - extern const char *Yap_tokText(void *tokptr); extern Term Yap_tokRep(void *tokptr); diff --git a/cmake/Sources.cmake b/cmake/Sources.cmake index 54e4c975e..dcaea42c8 100644 --- a/cmake/Sources.cmake +++ b/cmake/Sources.cmake @@ -206,6 +206,7 @@ set (INCLUDE_HEADERS ${CMAKE_SOURCE_DIR}/include/YapInterface.h ${CMAKE_SOURCE_DIR}/include/YapRegs.h ${CMAKE_SOURCE_DIR}/include/YapStreams.h + ${CMAKE_SOURCE_DIR}/include/YapUTF8.h ${CMAKE_SOURCE_DIR}/include/YapTerm.h ${CMAKE_SOURCE_DIR}/include/c_interface.h ${CMAKE_SOURCE_DIR}/include/clause_list.h diff --git a/include/YapStreams.h b/include/YapStreams.h index 2ff0c9910..4da91faad 100644 --- a/include/YapStreams.h +++ b/include/YapStreams.h @@ -233,6 +233,9 @@ typedef struct stream_desc { struct { const unsigned char *buf, *ptr; } irl; + struct { + unsigned char *buf, *ptr; + } w_irl; void *private_data; } u; struct { diff --git a/include/YapUTF8.h b/include/YapUTF8.h new file mode 100644 index 000000000..83e2bacda --- /dev/null +++ b/include/YapUTF8.h @@ -0,0 +1,198 @@ +/************************************************************************* + * * + * YAP Prolog * + * * + * Yap Prolog was developed at NCCUP - Universidade do Porto * + * * + * Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 * + * * + ************************************************************************** + * * + * File: YapMirror.c * + * Last rev: 5/2/88 * + * mods: * + * comments: Term conversion C implemented support * + * * + *************************************************************************/ +#ifndef YAP_UTF8_H +#define YAP_UTF8_H + +/** + * @file YapUTF8.h + * + * @brief uTF-8 codepoint translation and processing. + * + */ + +#if SIZEOF_WCHAR_T == 2 +#define CHARCODE_MAX 0xffff +#else +#define CHARCODE_MAX 0x10ffff +#endif + +#include "utf8proc.h" + +#ifndef INLINE_ONLY +#define INLINE_ONLY +#endif + +INLINE_ONLY inline EXTERN utf8proc_ssize_t get_utf8(const utf8proc_uint8_t *ptr, + size_t n, + utf8proc_int32_t *valp); + +INLINE_ONLY inline EXTERN utf8proc_ssize_t get_utf8(const utf8proc_uint8_t *ptr, + size_t n, + utf8proc_int32_t *valp) { + utf8proc_ssize_t rc = utf8proc_iterate(ptr, n, valp); + if (rc < 0) { + // LOCAL_ActiveError->errorNo = REPRESENTATION_ERROR_IN_CHARACTER_CODE; + } + return rc < 1 ? 1 : rc; +} + +INLINE_ONLY inline EXTERN utf8proc_ssize_t put_utf8(utf8proc_uint8_t *ptr, + utf8proc_int32_t val); + +INLINE_ONLY inline EXTERN utf8proc_ssize_t put_utf8(utf8proc_uint8_t *ptr, + utf8proc_int32_t val) { + utf8proc_ssize_t rc = utf8proc_encode_char(val, ptr); + if (rc < 0) { + // LOCAL_ActiveError->errorNo = REPRESENTATION_ERROR_CHARACTER_CODE; + } + return rc < 1 ? 1 : rc; +} + +inline static const utf8proc_uint8_t *skip_utf8(const utf8proc_uint8_t *pt, + utf8proc_ssize_t n) { + utf8proc_ssize_t i; + utf8proc_int32_t b; + for (i = 0; i < n; i++) { + utf8proc_ssize_t l = utf8proc_iterate(pt, -1, &b); + if (b == 0) + return pt; + if (l < 0) { + // LOCAL_ActiveError->errorNo = REPRESENTATION_ERROR_CHARACTER_CODE; + } else { + pt += l; + } + } + return pt; +} + +inline static utf8proc_ssize_t utf8_nof(utf8proc_int32_t val) { + return utf8proc_charwidth(val); +} + +inline static utf8proc_ssize_t strlen_utf8(const utf8proc_uint8_t *pt) { + utf8proc_ssize_t rc = 0; + utf8proc_int32_t b; + while (true) { + utf8proc_ssize_t l = utf8proc_iterate(pt, -1, &b); + if (b == 0) + return rc; + else if (l > 0) { + pt += l; + rc++; + } else { + // LOCAL_ActiveError->errorNo = REPRESENTATION_ERROR_CHARACTER_CODE; + pt++; + } + } + return rc; +} + +inline static utf8proc_ssize_t strlen_latin_utf8(const unsigned char *pt) { + utf8proc_ssize_t rc = 0; + utf8proc_uint8_t b; + while (true) { + utf8proc_ssize_t l = utf8proc_encode_char(*pt, &b); + if (l<0) { + pt++; + } + if (b == 0) + return rc; + pt++; + rc += l; + } + return rc; +} + +inline static utf8proc_ssize_t strnlen_latin_utf8(const unsigned char *pt, + size_t max) { + utf8proc_ssize_t rc = 0; + utf8proc_uint8_t b; + while (true) { + utf8proc_ssize_t l = utf8proc_encode_char(*pt, &b); + if (b == 0) + return rc; + pt++; + if (l > 0) + rc += l; + if (--max == 0) + return rc; + } + return rc; +} + +inline static utf8proc_ssize_t strlen_ucs2_utf8(const wchar_t *pt) { + utf8proc_ssize_t rc = 0; + utf8proc_uint8_t b; + while (true) { + utf8proc_ssize_t l = utf8proc_encode_char(*pt, &b); + if (b == 0) + return rc; + if (l < 0) + continue; + pt++; + rc += l; + } + return rc; +} + +inline static utf8proc_ssize_t strnlen_ucs2_utf8(const wchar_t *pt, + size_t max) { + utf8proc_ssize_t rc = 0; + utf8proc_uint8_t b; + while (true) { + utf8proc_ssize_t l = utf8proc_encode_char(*pt, &b); + if (b == 0) + return rc; + pt++; + rc += l; + if (--max == 0) + return rc; + } + return rc; +} + +inline static int cmpn_utf8(const utf8proc_uint8_t *pt1, + const utf8proc_uint8_t *pt2, utf8proc_ssize_t n) { + utf8proc_ssize_t i; + utf8proc_int32_t b; + for (i = 0; i < n; i++) { + if (pt1[0] != pt2[0]) + return pt1[0] - pt2[0]; + utf8proc_ssize_t l = utf8proc_iterate(pt1, -1, &b); + if (l == 2) { + if (pt1[1] != pt2[1]) + return pt1[1] - pt2[1]; + } else if (l == 3) { + if (pt1[2] != pt2[2]) + return pt1[2] - pt2[2]; + } else if (l == 4) { + if (pt1[3] != pt2[3]) + return pt1[3] - pt2[3]; + } + pt1 += l; + pt2 += l; + } + return 0; +} + +// UTF16 + +#define LEAD_OFFSET ((uint32_t)0xD800 - (uint32_t)(0x10000 >> 10)) +#define SURROGATE_OFFSET \ + ((uint32_t)0x10000 - (uint32_t)(0xD800 << 10) - (uint32_t)0xDC00) + +#endif diff --git a/packages/python/pyio.c b/packages/python/pyio.c index 0d2ebe4b3..568ac7125 100644 --- a/packages/python/pyio.c +++ b/packages/python/pyio.c @@ -4,26 +4,46 @@ #include #include "YapStreams.h" +#include "YapUTF8.h" YAP_Term TermErrStream, TermOutStream; +static unsigned char *outbuf, *errbuf; + +static void pyflush( StreamDesc *st) +{ + #if 0 + st->u.w_irl.ptr[0] = '\0'; + fprintf(stderr,"%s\n", st->u.w_irl.buf); + term_t tg = python_acquire_GIL(); + if (st->user_name == TermOutStream){ + PySys_WriteStdout("%s", st->u.w_irl.buf); + } else { + PySys_WriteStderr("%s", st->u.w_irl.buf); + + } + python_release_GIL(tg); + st->u.w_irl.ptr = st->u.w_irl.buf; + #endif + +} + static int py_putc(int sno, int ch) { // PyObject *pyw; // buffer // int pyw_kind; // PyObject *pyw_data; StreamDesc *st = YAP_GetStreamFromId(sno); - if (st->user_name == TermOutStream) { - term_t tg = python_acquire_GIL(); - PySys_WriteStdout("%C", ch); - python_release_GIL(tg); - return ch; - } - if (st->user_name == TermErrStream) { - term_t tg = python_acquire_GIL(); - PySys_WriteStderr("%C", ch); - python_release_GIL(tg); - return ch; +#if 0 + if (false && (st->user_name == TermOutStream || st->user_name == TermErrStream)) { + size_t sz = put_utf8(st->u.w_irl.ptr, ch); + if (sz > 0) { + st->u.w_irl.ptr += sz; + if (ch == '\n' || st->u.w_irl.ptr - st->u.w_irl.buf > 256) + {pyflush(st); } + } + return ch; } + #endif char s[2]; PyObject *err; s[0] = ch; @@ -58,13 +78,20 @@ static void *py_open(VFS_t *me, const char *name, const char *io_mode, } StreamDesc *st = YAP_RepStreamFromId(sno); st->name = YAP_LookupAtom(name); - if (strcmp(name, "sys.stdout") == 0) { + /* if (strcmp(name, "sys.stdout") == 0) { + if (!outbuf) + outbuf = ( unsigned char *)malloc(1024); + st->u.w_irl.ptr = st->u.w_irl.buf = outbuf; st->user_name = TermOutStream; } else if (strcmp(name, "sys.stderr") == 0) { st->user_name = TermErrStream; + if (!errbuf) + errbuf = ( unsigned char *)malloc(1024); + st->u.w_irl.ptr = st->u.w_irl.buf = errbuf; // } else if (strcmp(name, "input") == 0) { //pystream = PyObject_Call(pystream, PyTuple_New(0), NULL); - } else { + } else */ + { st->user_name = YAP_MkAtomTerm(st->name); } st->u.private_data = pystream; @@ -75,10 +102,23 @@ static void *py_open(VFS_t *me, const char *name, const char *io_mode, } +static void py_flush(int sno) { + StreamDesc *s = YAP_GetStreamFromId(sno); + term_t tg = python_acquire_GIL(); + PyObject *flush = PyObject_GetAttrString(s->u.private_data, "flush"); + pyflush(s); + PyObject_CallFunction(flush, NULL); + python_release_GIL(tg); +} + + static bool py_close(int sno) { StreamDesc *st = YAP_RepStreamFromId(sno); + if (st->status & (Output_Stream_f|Append_Stream_f)) + py_flush(sno); if (strcmp(st->name, "sys.stdout") && strcmp(st->name, "sys.stderr")) { Py_XDECREF(st->u.private_data); + st->u.w_irl.buf = st->u.w_irl.ptr = NULL; } st->u.private_data = NULL; st->vfs = NULL; @@ -163,14 +203,6 @@ static int64_t py_seek(int sno, int64_t where, int how) { return PyLong_AsLong(pyr); } -static void py_flush(int sno) { - StreamDesc *s = YAP_GetStreamFromId(sno); - term_t tg = python_acquire_GIL(); - PyObject *flush = PyObject_GetAttrString(s->u.private_data, "flush"); - PyObject_CallFunction(flush, NULL); - python_release_GIL(tg); -} - #if 0 static void python_output(void) { PyObject *stream = string_to_python("sys.stdout", true, NULL); diff --git a/packages/python/yap_kernel/yap_ipython/prolog/jupyter.yap b/packages/python/yap_kernel/yap_ipython/prolog/jupyter.yap index 15dfcd989..0c315ef2d 100644 --- a/packages/python/yap_kernel/yap_ipython/prolog/jupyter.yap +++ b/packages/python/yap_kernel/yap_ipython/prolog/jupyter.yap @@ -34,26 +34,18 @@ jupyter_cell( _Caller, _, Line ) :- jupyter_cell( _Caller, _, [] ) :- !. jupyter_cell( Caller, _, Line ) :- Self := Caller.query, - gated_call( streams(true), - python_query(Self,Line), - Gate, - restreams(Gate) - ). + python_query(Self,Line). -restreams(redo) :- +restreams(call) :- streams(true). restreams(fail) :- streams(false). -restreams(answer) :- - streams(false). +restreams(answer). restreams(exit) :- streams(false). -restreams(!) :- - streams(false). -restreams(external_exception(_)) :- - streams(false). -restreams(exception) :- - streams(false). +restreams(!). +restreams(external_exception(_)). +restreams(exception). jupyter_consult(Text) :- blank( Text ), @@ -83,7 +75,6 @@ streams(false) :- streams(false). streams(true) :- nb_setval(jupyter_cell, true), - start_low_level_trace, \+ current_stream('/python/input',_,_), open('/python/input', read, Input, [alias(user_input),bom(false),script(false)]), assert( cell_stream( Input) ), diff --git a/packages/python/yap_kernel/yap_ipython/yapi.py b/packages/python/yap_kernel/yap_ipython/yapi.py index 1e8bf283e..62c34edcd 100644 --- a/packages/python/yap_kernel/yap_ipython/yapi.py +++ b/packages/python/yap_kernel/yap_ipython/yapi.py @@ -560,6 +560,8 @@ class YAPRun: pg = jupyter_query( self, program, squery) self.query = self.yapeng.query(pg) self.query.answer = {} + self.yapeng.mgoal(streams(False),"user", True) + self.yapeng.mgoal(streams(True),"user", True) while self.query.next(): answer = self.query.answer found = True @@ -568,6 +570,7 @@ class YAPRun: if self.query.port == "exit": self.os = None sys.stderr.writeln('Done, with', self.bindings) + self.yapeng.mgoal(streams(False),"user", True) return True,self.bindings if stop or howmany == self.iterations: return True, self.bindings @@ -576,12 +579,14 @@ class YAPRun: else: self.os = None self.query.close() - self.query = None +`` self.query = None sys.stderr.write('Fail\n') - return True,self.bindings + self.yapeng.mgoal(streams(False),"user", True) + return True,self.bindings except Exception as e: sys.stderr.write('Exception after', self.bindings, '\n') has_raised = True + self.yapeng.mgoal(streams(False),"user", True) return False,[] @@ -628,6 +633,7 @@ class YAPRun: # ask = True # launch the query + info = interactiveshell.ExecutionInfo( raw_cell, store_history, silent, shell_futures) @@ -731,11 +737,10 @@ class YAPRun: # run the new command using the given tracer # - # self.yapeng.mgoal(streams(True),"user", True) # tracer.runfunc(f,self,cell,state) self.jupyter_query( cell ) # state = tracer.runfunc(jupyter_query( self, cell ) ) - # self.yapeng.mgoal(streams(False),"user", True) + self.yapeng.mgoal(streams(False),"user", True) self.shell.last_execution_succeeded = True self.result.result = (True, dicts) diff --git a/pl/top.yap b/pl/top.yap index c4acae77e..9915e846d 100644 --- a/pl/top.yap +++ b/pl/top.yap @@ -502,7 +502,7 @@ write_query_answer( Bindings ) :- format(user_error,'~a',[V]), '$write_output_vars'(VL), format(user_error,' = ', []), - ( yap_flag(toplevel_print_options, Opts) -> + ( yap_flag(toplevel_print_options, Opts) -> write_term(user_error,B,[priority(699)|Opts]) ; write_term(user_error,B,[priority(699)]) ).