This commit is contained in:
Vitor Santos Costa
2018-06-01 13:22:13 +01:00
parent 725a0a692a
commit 94a826efcc
9 changed files with 477 additions and 268 deletions

261
C/write.c
View File

@@ -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