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/write.c

1298 lines
34 KiB
C
Raw Normal View History

2015-10-05 10:30:47 +01:00
/*************************************************************************
2016-07-31 10:46:51 +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 *
* *
**************************************************************************
* *
* File: write.c *
* Last rev: *
* mods: *
* comments: Writing a Prolog Term *
* *
*************************************************************************/
#ifdef SCCS
2015-02-10 00:03:02 +00:00
static char SccsId[] = "%W% %G%";
#endif
#include "Yap.h"
#include "YapHeap.h"
2015-09-21 23:05:36 +01:00
#include "YapText.h"
2016-03-29 01:55:12 +01:00
#include "Yatom.h"
2010-11-01 21:28:18 +00:00
#include "clause.h"
2016-03-29 01:55:12 +01:00
#include "yapio.h"
#include <math.h>
#include <stdlib.h>
#if COROUTINING
#include "attvar.h"
#endif
2015-06-19 01:30:13 +01:00
#include "iopreds.h"
#if HAVE_STRING_H
#include <string.h>
#endif
#if HAVE_CTYPE_H
#include <ctype.h>
#endif
#if HAVE_LOCALE_H
#include <locale.h>
#endif
/* describe the type of the previous term to have been written */
typedef enum {
2015-06-19 01:30:13 +01:00
start, /* initialization */
2015-02-10 00:03:02 +00:00
separator, /* the previous term was a separator like ',', ')', ... */
alphanum, /* the previous term was an atom or number */
symbol /* the previous term was a symbol like +, -, *, .... */
} wtype;
2015-10-22 00:45:21 +01:00
typedef StreamDesc *wrf;
2009-05-24 21:14:23 +01:00
typedef struct union_slots {
2014-05-15 01:11:26 +01:00
Int old;
Int ptr;
2009-05-24 21:14:23 +01:00
} uslots;
typedef struct union_direct {
2014-05-15 01:11:26 +01:00
Term old;
CELL *ptr;
2009-05-24 21:14:23 +01:00
} udirect;
2015-02-10 00:03:02 +00:00
typedef struct rewind_term {
2014-05-15 01:11:26 +01:00
struct rewind_term *parent;
union {
struct union_slots s;
struct union_direct d;
} u_sd;
2009-05-22 18:24:30 +01:00
} rwts;
typedef struct write_globs {
2015-06-19 01:30:13 +01:00
StreamDesc *stream;
2015-02-10 00:03:02 +00:00
int Quote_illegal, Ignore_ops, Handle_vars, Use_portray, Portray_delays;
int Keep_terms;
int Write_Loops;
int Write_strings;
int last_atom_minus;
UInt MaxDepth, MaxArgs;
wtype lw;
} wglbs;
#define lastw wglb->lw
2012-03-19 08:58:26 +00:00
#define last_minus wglb->last_atom_minus
2015-07-06 11:59:50 +01:00
static bool callPortray(Term t, struct DB_TERM **old_EXp, int sno USES_REGS) {
2014-10-23 01:21:22 +01:00
PredEntry *pe;
2015-02-10 00:03:02 +00:00
Int b0 = LCL0 - (CELL *)B;
2014-10-23 01:21:22 +01:00
2016-03-29 01:55:12 +01:00
*old_EXp = Yap_RefToException();
2015-07-06 11:59:50 +01:00
UNLOCK(GLOBAL_Stream[sno].streamlock);
2015-02-10 00:03:02 +00:00
if ((pe = RepPredProp(Yap_GetPredPropByFunc(FunctorPortray, USER_MODULE))) &&
pe->OpcodeOfPred != FAIL_OPCODE && pe->OpcodeOfPred != UNDEF_OPCODE &&
2015-06-19 01:30:13 +01:00
Yap_execute_pred(pe, &t, true PASS_REGS)) {
2015-02-10 00:03:02 +00:00
choiceptr B0 = (choiceptr)(LCL0 - b0);
2016-03-29 01:55:12 +01:00
if (Yap_HasException() && !*old_EXp)
*old_EXp = Yap_RefToException();
2014-10-23 02:10:55 +01:00
Yap_fail_all(B0 PASS_REGS);
2015-07-06 11:59:50 +01:00
LOCK(GLOBAL_Stream[sno].streamlock);
2014-10-23 01:21:22 +01:00
return true;
}
2015-07-06 11:59:50 +01:00
LOCK(GLOBAL_Stream[sno].streamlock);
2016-03-29 01:55:12 +01:00
if (Yap_HasException() && !*old_EXp)
*old_EXp = Yap_RefToException();
2014-10-23 01:21:22 +01:00
return false;
}
2015-02-10 00:03:02 +00:00
2013-04-25 23:15:04 +01:00
static void wrputn(Int, struct write_globs *);
static void wrputf(Float, struct write_globs *);
static void wrputref(CODEADDR, int, struct write_globs *);
static int legalAtom(unsigned char *);
/*static int LeftOpToProtect(Atom, int);
static int RightOpToProtect(Atom, int);*/
static wtype AtomIsSymbols(unsigned char *);
static void putAtom(Atom, int, struct write_globs *);
2015-02-10 00:03:02 +00:00
static void writeTerm(Term, int, int, int, struct write_globs *,
struct rewind_term *);
2016-07-31 10:46:51 +01:00
#define wrputc(WF, X) \
2015-10-22 00:45:21 +01:00
(X)->stream_wputc(X - GLOBAL_Stream, WF) /* writes a character */
/*
protect bracket from merging with previoous character.
avoid stuff like not (2,3) -> not(2,3) or
2014-05-15 01:11:26 +01:00
*/
2015-02-10 00:03:02 +00:00
static void wropen_bracket(struct write_globs *wglb, int protect) {
2015-06-19 01:30:13 +01:00
StreamDesc *stream = wglb->stream;
2012-03-19 08:58:26 +00:00
2014-05-15 01:11:26 +01:00
if (lastw != separator && protect)
wrputc(' ', stream);
2015-02-10 00:03:02 +00:00
wrputc('(', stream);
2014-05-15 01:11:26 +01:00
lastw = separator;
}
2015-02-10 00:03:02 +00:00
static void wrclose_bracket(struct write_globs *wglb, int protect) {
2014-05-15 01:11:26 +01:00
wrf stream = wglb->stream;
2015-02-10 00:03:02 +00:00
wrputc(')', stream);
2014-05-15 01:11:26 +01:00
lastw = separator;
}
2015-02-10 00:03:02 +00:00
static int protect_open_number(struct write_globs *wglb, int lm,
int minus_required) {
2014-05-15 01:11:26 +01:00
wrf stream = wglb->stream;
if (lastw == symbol && lm && !minus_required) {
wropen_bracket(wglb, TRUE);
return TRUE;
2015-02-10 00:03:02 +00:00
} else if (lastw == alphanum || (lastw == symbol && minus_required)) {
wrputc(' ', stream);
}
2014-05-15 01:11:26 +01:00
return FALSE;
2012-03-19 08:58:26 +00:00
}
2015-02-10 00:03:02 +00:00
static void protect_close_number(struct write_globs *wglb, int used_bracket) {
2014-05-15 01:11:26 +01:00
if (used_bracket) {
wrclose_bracket(wglb, TRUE);
} else {
lastw = alphanum;
}
last_minus = FALSE;
2012-03-19 08:58:26 +00:00
}
2015-02-10 00:03:02 +00:00
static void wrputn(Int n,
struct write_globs *wglb) /* writes an integer */
{
2014-05-15 01:11:26 +01:00
wrf stream = wglb->stream;
2015-02-10 00:03:02 +00:00
char s[256], *s1 = s; /* that should be enough for most integers */
2014-05-15 01:11:26 +01:00
int has_minus = (n < 0);
int ob;
2012-03-19 08:58:26 +00:00
2014-05-15 01:11:26 +01:00
ob = protect_open_number(wglb, last_minus, has_minus);
#if HAVE_SNPRINTF
2014-05-15 01:11:26 +01:00
snprintf(s, 256, Int_FORMAT, n);
#else
2014-05-15 01:11:26 +01:00
sprintf(s, Int_FORMAT, n);
#endif
2014-05-15 01:11:26 +01:00
while (*s1)
wrputc(*s1++, stream);
protect_close_number(wglb, ob);
}
2015-10-22 00:45:21 +01:00
inline static void wrputs(char *s, StreamDesc *stream) {
2015-06-19 01:30:13 +01:00
int c;
2015-10-22 00:45:21 +01:00
while ((c = *s++))
wrputc(c, stream);
2015-06-19 01:30:13 +01:00
}
2015-02-10 00:03:02 +00:00
static void wrputws(wchar_t *s, wrf stream) /* writes a string */
{
2014-05-15 01:11:26 +01:00
while (*s)
wrputc(*s++, stream);
}
2010-05-27 12:24:15 +01:00
#ifdef USE_GMP
2015-02-10 00:03:02 +00:00
static char *ensure_space(size_t sz) {
2014-05-15 01:11:26 +01:00
CACHE_REGS
2016-07-31 10:46:51 +01:00
char *s;
2010-05-27 12:24:15 +01:00
2015-02-10 00:03:02 +00:00
s = (char *)Yap_PreAllocCodeSpace();
while (s + sz >= (char *)AuxSp) {
2010-05-27 12:24:15 +01:00
#if USE_SYSTEM_MALLOC
2014-05-15 01:11:26 +01:00
/* may require stack expansion */
if (!Yap_ExpandPreAllocCodeSpace(sz, NULL, TRUE)) {
s = NULL;
break;
}
2015-02-10 00:03:02 +00:00
s = (char *)Yap_PreAllocCodeSpace();
2010-05-27 12:24:15 +01:00
#else
2014-05-15 01:11:26 +01:00
s = NULL;
2010-05-27 12:24:15 +01:00
#endif
2014-05-15 01:11:26 +01:00
}
if (!s) {
s = (char *)TR;
2015-02-10 00:03:02 +00:00
while (s + sz >= LOCAL_TrailTop) {
if (!Yap_growtrail(sz / sizeof(CELL), FALSE)) {
s = NULL;
break;
2014-05-15 01:11:26 +01:00
}
s = (char *)TR;
}
}
if (!s) {
s = (char *)HR;
2015-02-10 00:03:02 +00:00
if (s + sz >= (char *)ASP) {
2015-09-25 10:57:26 +01:00
Yap_Error(RESOURCE_ERROR_STACK, TermNil,
2015-02-10 00:03:02 +00:00
"not enough space to write bignum: it requires %d bytes", sz);
2014-05-15 01:11:26 +01:00
s = NULL;
}
}
return s;
2010-05-27 12:24:15 +01:00
}
2015-02-10 00:03:02 +00:00
static void write_mpint(MP_INT *big, struct write_globs *wglb) {
2014-05-15 01:11:26 +01:00
char *s;
int has_minus = mpz_sgn(big);
int ob;
2015-02-10 00:03:02 +00:00
s = ensure_space(3 + mpz_sizeinbase(big, 10));
2014-05-15 01:11:26 +01:00
ob = protect_open_number(wglb, last_minus, has_minus);
if (!s) {
s = mpz_get_str(NULL, 10, big);
if (!s)
return;
2015-02-10 00:03:02 +00:00
wrputs(s, wglb->stream);
2014-05-15 01:11:26 +01:00
free(s);
} else {
mpz_get_str(s, 10, big);
2015-02-10 00:03:02 +00:00
wrputs(s, wglb->stream);
2014-05-15 01:11:26 +01:00
}
protect_close_number(wglb, ob);
2010-05-27 12:24:15 +01:00
}
#endif
2015-02-10 00:03:02 +00:00
/* writes a bignum */
static void writebig(Term t, int p, int depth, int rinfixarg,
struct write_globs *wglb, struct rewind_term *rwt) {
CELL *pt = RepAppl(t) + 1;
2014-05-15 01:11:26 +01:00
CELL big_tag = pt[0];
if (big_tag == ARRAY_INT || big_tag == ARRAY_FLOAT) {
wrputc('{', wglb->stream);
wrputs("...", wglb->stream);
wrputc('}', wglb->stream);
lastw = separator;
return;
#ifdef USE_GMP
2015-02-10 00:03:02 +00:00
} else if (big_tag == BIG_INT) {
2014-05-15 01:11:26 +01:00
MP_INT *big = Yap_BigIntOfTerm(t);
write_mpint(big, wglb);
return;
} else if (big_tag == BIG_RATIONAL) {
Term trat = Yap_RatTermToApplTerm(t);
writeTerm(trat, p, depth, rinfixarg, wglb, rwt);
return;
2010-05-27 12:24:15 +01:00
#endif
2014-05-15 01:11:26 +01:00
} else if (big_tag >= USER_BLOB_START && big_tag < USER_BLOB_END) {
Opaque_CallOnWrite f;
CELL blob_info;
blob_info = big_tag - USER_BLOB_START;
if (GLOBAL_OpaqueHandlers &&
2015-02-10 00:03:02 +00:00
(f = GLOBAL_OpaqueHandlers[blob_info].write_handler)) {
2015-06-19 01:30:13 +01:00
(f)(wglb->stream->file, big_tag, ExternalBlobFromTerm(t), 0);
2014-05-15 01:11:26 +01:00
return;
}
}
2015-02-10 00:03:02 +00:00
wrputs("0", wglb->stream);
}
static void wrputf(Float f, struct write_globs *wglb) /* writes a float */
2010-05-27 12:24:15 +01:00
{
2015-06-19 01:30:13 +01:00
#if THREADS
2015-10-22 00:45:21 +01:00
char s[256];
2015-06-19 01:30:13 +01:00
#endif
2015-10-22 00:45:21 +01:00
wrf stream = wglb->stream;
2014-05-15 01:11:26 +01:00
int sgn;
int ob;
#if HAVE_ISNAN || defined(__WIN32)
2014-05-15 01:11:26 +01:00
if (isnan(f)) {
wrputs("(nan)", stream);
lastw = separator;
return;
}
#endif
2015-02-10 00:03:02 +00:00
sgn = (f < 0.0);
#if HAVE_ISINF || defined(_WIN32)
2014-05-15 01:11:26 +01:00
if (isinf(f)) {
if (sgn) {
wrputs("(-inf)", stream);
} else {
wrputs("(+inf)", stream);
}
lastw = separator;
return;
}
#endif
2014-05-15 01:11:26 +01:00
ob = protect_open_number(wglb, last_minus, sgn);
#if THREADS
2014-05-15 01:11:26 +01:00
/* old style writing */
int found_dot = FALSE;
2015-02-10 00:03:02 +00:00
char *pt = s;
2014-05-15 01:11:26 +01:00
int ch;
2016-07-31 10:46:51 +01:00
/* always use C locale for writing numbers */
#if O_LOCALE
2015-02-10 00:03:02 +00:00
const unsigned char *decimalpoint =
2016-07-31 10:46:51 +01:00
(unsigned char *)localeconv()->decimal_point;
2015-02-10 00:03:02 +00:00
size_t l1 = strlen((const char *)decimalpoint + 1);
#else
const unsigned char decimalpoint[2] = ".";
2014-06-11 19:30:44 +01:00
size_t l1 = 0;
#endif
2014-05-15 01:11:26 +01:00
if (lastw == symbol || lastw == alphanum) {
wrputc(' ', stream);
}
lastw = alphanum;
// sprintf(s, "%.15g", f);
2015-11-05 16:35:25 +00:00
sprintf(s, floatFormat(), f);
2014-05-15 01:11:26 +01:00
while (*pt == ' ')
pt++;
if (*pt == '-') {
wrputc('-', stream);
pt++;
}
while ((ch = *pt) != '\0') {
// skip locale
2015-02-10 00:03:02 +00:00
if (ch == decimalpoint[0] &&
!strncmp(pt + 1, (char *)decimalpoint + 1, l1)) {
2014-05-15 01:11:26 +01:00
found_dot = TRUE;
pt += l1;
ch = '.';
}
if (ch == 'e' || ch == 'E') {
if (!found_dot) {
found_dot = TRUE;
2015-02-10 00:03:02 +00:00
wrputs(".0", stream);
2014-05-15 01:11:26 +01:00
}
found_dot = TRUE;
}
wrputc(ch, stream);
pt++;
}
if (!found_dot) {
wrputs(".0", stream);
}
#else
2015-06-19 01:30:13 +01:00
char buf[256];
2014-05-15 01:11:26 +01:00
if (lastw == symbol || lastw == alphanum) {
wrputc(' ', stream);
}
/* use SWI's format_float */
2015-10-22 00:45:21 +01:00
sprintf(buf, (char *)floatFormat(), f);
2015-06-19 01:30:13 +01:00
2014-05-15 01:11:26 +01:00
wrputs(buf, stream);
#endif
2014-05-15 01:11:26 +01:00
protect_close_number(wglb, ob);
}
2015-10-22 00:45:21 +01:00
int Yap_FormatFloat(Float f, char **s, size_t sz) {
CACHE_REGS
2016-07-31 10:46:51 +01:00
struct write_globs wglb;
2015-10-22 00:45:21 +01:00
int sno;
char *so;
sno = Yap_open_buf_write_stream(GLOBAL_Stream[LOCAL_c_output_stream].encoding,
0);
2015-10-22 00:45:21 +01:00
if (sno < 0)
2015-06-19 01:30:13 +01:00
return FALSE;
2016-04-18 16:38:29 +01:00
wglb.lw = separator;
2015-10-22 00:45:21 +01:00
wglb.stream = GLOBAL_Stream + sno;
wrputf(f, &wglb);
2016-04-18 16:38:29 +01:00
wrputc('\0', wglb.stream);
2015-10-22 00:45:21 +01:00
so = Yap_MemExportStreamPtr(sno);
Yap_CloseStream(sno);
*s = so;
2014-05-15 01:11:26 +01:00
return TRUE;
}
/* writes a data base reference */
2015-02-10 00:03:02 +00:00
static void wrputref(CODEADDR ref, int Quote_illegal,
struct write_globs *wglb) {
char s[256];
wrf stream = wglb->stream;
2014-05-15 01:11:26 +01:00
putAtom(AtomDBref, Quote_illegal, wglb);
2010-01-21 15:05:01 +00:00
#if defined(__linux__) || defined(__APPLE__)
2015-02-10 00:03:02 +00:00
sprintf(s, "(%p," UInt_FORMAT ")", ref, ((LogUpdClause *)ref)->ClRefCount);
#else
2015-02-10 00:03:02 +00:00
sprintf(s, "(0x%p," UInt_FORMAT ")", ref, ((LogUpdClause *)ref)->ClRefCount);
#endif
2014-05-15 01:11:26 +01:00
wrputs(s, stream);
lastw = alphanum;
}
2012-02-27 08:53:18 +00:00
/* writes a blob (default) */
2015-02-10 00:03:02 +00:00
static int wrputblob(AtomEntry *ref, int Quote_illegal,
struct write_globs *wglb) {
wrf stream = wglb->stream;
2015-06-19 01:30:13 +01:00
int rc;
2015-10-22 00:45:21 +01:00
int Yap_write_blob(AtomEntry * ref, StreamDesc * stream);
if ((rc = Yap_write_blob(ref, stream))) {
return rc;
}
2014-05-15 01:11:26 +01:00
lastw = alphanum;
return 1;
2012-02-27 08:53:18 +00:00
}
2015-02-10 00:03:02 +00:00
static int legalAtom(unsigned char *s) /* Is this a legal atom ? */
{
2014-05-15 01:11:26 +01:00
wchar_t ch = *s;
if (ch == '\0')
return FALSE;
if (Yap_chtype[ch] != LC) {
if (ch == '[') {
return (s[1] == ']' && !s[2]);
} else if (ch == '{') {
2015-02-10 00:03:02 +00:00
return (s[1] == '}' && !s[2]);
2014-05-15 01:11:26 +01:00
} else if (Yap_chtype[ch] == SL) {
return (!s[1]);
2016-01-03 02:06:09 +00:00
} else if (ch == '`') {
return false;
2014-05-15 01:11:26 +01:00
} else if ((ch == ',' || ch == '.') && !s[1]) {
return false;
2014-05-15 01:11:26 +01:00
} else {
if (ch == '/') {
2015-02-10 00:03:02 +00:00
if (s[1] == '*')
2016-01-03 02:06:09 +00:00
return false;
2014-05-15 01:11:26 +01:00
}
while (ch) {
2015-02-10 00:03:02 +00:00
if (Yap_chtype[ch] != SY) {
2016-01-03 02:06:09 +00:00
return false;
2015-02-10 00:03:02 +00:00
}
ch = *++s;
2014-05-15 01:11:26 +01:00
}
}
2016-01-03 02:06:09 +00:00
return true;
2014-05-15 01:11:26 +01:00
} else
while ((ch = *++s) != 0)
if (Yap_chtype[ch] > NU)
2016-01-03 02:06:09 +00:00
return false;
return true;
}
2015-02-10 00:03:02 +00:00
static wtype
AtomIsSymbols(unsigned char *s) /* Is this atom just formed by symbols ? */
{
2014-05-15 01:11:26 +01:00
int ch;
2016-03-29 01:55:12 +01:00
if (Yap_chtype[(int)s[0]] == SL && s[1] == '\0')
2015-02-10 00:03:02 +00:00
return (separator);
2014-05-15 01:11:26 +01:00
while ((ch = *s++) != '\0') {
if (Yap_chtype[ch] != SY)
return alphanum;
}
return symbol;
}
2015-02-10 00:03:02 +00:00
static void write_quoted(wchar_t ch, wchar_t quote, wrf stream) {
2014-05-15 01:11:26 +01:00
CACHE_REGS
2016-07-31 10:46:51 +01:00
if (!(Yap_GetModuleEntry(CurrentModule)->flags & M_CHARESCAPE)) {
wrputc(ch, stream);
if (ch == '\'')
wrputc('\'', stream); /* be careful about quotes */
return;
}
2015-10-22 00:45:21 +01:00
if (!(ch < 0xff && chtype(ch) == BS) && ch != '\'' && ch != '\\' &&
ch != '`') {
2014-05-15 01:11:26 +01:00
wrputc(ch, stream);
} else {
switch (ch) {
case '\\':
2015-02-10 00:03:02 +00:00
wrputc('\\', stream);
wrputc('\\', stream);
2014-05-15 01:11:26 +01:00
break;
case '\'':
if (ch == quote)
2015-02-10 00:03:02 +00:00
wrputc('\\', stream);
wrputc(ch, stream);
2014-05-15 01:11:26 +01:00
break;
case '"':
if (ch == quote)
2015-02-10 00:03:02 +00:00
wrputc('\\', stream);
wrputc(ch, stream);
break;
case '`':
if (ch == quote)
wrputc('`', stream);
wrputc(ch, stream);
2014-05-15 01:11:26 +01:00
break;
case 7:
2015-02-10 00:03:02 +00:00
wrputc('\\', stream);
wrputc('a', stream);
2014-05-15 01:11:26 +01:00
break;
case '\b':
wrputc('\\', stream);
2015-02-10 00:03:02 +00:00
wrputc('b', stream);
2014-05-15 01:11:26 +01:00
break;
case '\t':
wrputc('\\', stream);
2015-02-10 00:03:02 +00:00
wrputc('t', stream);
2014-05-15 01:11:26 +01:00
break;
case ' ':
case 160:
wrputc(' ', stream);
break;
case '\n':
wrputc('\\', stream);
2015-02-10 00:03:02 +00:00
wrputc('n', stream);
2014-05-15 01:11:26 +01:00
break;
case 11:
wrputc('\\', stream);
2015-02-10 00:03:02 +00:00
wrputc('v', stream);
2014-05-15 01:11:26 +01:00
break;
case '\r':
wrputc('\\', stream);
2015-02-10 00:03:02 +00:00
wrputc('r', stream);
2014-05-15 01:11:26 +01:00
break;
case '\f':
wrputc('\\', stream);
2015-02-10 00:03:02 +00:00
wrputc('f', stream);
2014-05-15 01:11:26 +01:00
break;
default:
2015-02-10 00:03:02 +00:00
if (ch <= 0xff) {
char esc[8];
/* last backslash in ISO mode */
sprintf(esc, "\\%03o\\", ch);
wrputs(esc, stream);
2014-05-15 01:11:26 +01:00
}
}
}
}
2015-09-21 23:05:36 +01:00
static void write_string(const unsigned char *s,
2015-02-10 00:03:02 +00:00
struct write_globs *wglb) /* writes an integer */
2013-12-05 21:26:05 +00:00
{
2015-06-19 01:30:13 +01:00
StreamDesc *stream = wglb->stream;
2015-09-21 23:05:36 +01:00
utf8proc_int32_t chr, qt;
2015-10-22 00:45:21 +01:00
unsigned char *ptr = (unsigned char *)s;
2015-02-10 00:03:02 +00:00
2014-05-15 01:11:26 +01:00
if (wglb->Write_strings)
2015-02-10 00:03:02 +00:00
qt = '`';
2014-05-15 01:11:26 +01:00
else
2015-02-10 00:03:02 +00:00
qt = '"';
wrputc(qt, stream);
2014-05-15 01:11:26 +01:00
do {
2016-02-18 12:10:58 +00:00
ptr += get_utf8(ptr, -1, &chr);
2015-02-10 00:03:02 +00:00
if (chr == '\0')
break;
write_quoted(chr, qt, stream);
2014-05-15 01:11:26 +01:00
} while (TRUE);
2015-02-10 00:03:02 +00:00
wrputc(qt, stream);
2013-12-05 21:26:05 +00:00
}
/* writes an atom */
2015-02-10 00:03:02 +00:00
static void putAtom(Atom atom, int Quote_illegal, struct write_globs *wglb) {
unsigned char *s;
wtype atom_or_symbol;
2014-05-15 01:11:26 +01:00
wrf stream = wglb->stream;
2014-05-15 01:11:26 +01:00
if (IsBlob(atom)) {
2015-02-10 00:03:02 +00:00
wrputblob(RepAtom(atom), Quote_illegal, wglb);
2014-05-15 01:11:26 +01:00
return;
}
2015-02-10 00:03:02 +00:00
if (IsWideAtom(atom)) {
2014-05-15 01:11:26 +01:00
wchar_t *ws = RepAtom(atom)->WStrOfAE;
if (Quote_illegal) {
wrputc('\'', stream);
while (*ws) {
2015-02-10 00:03:02 +00:00
wchar_t ch = *ws++;
write_quoted(ch, '\'', stream);
2014-05-15 01:11:26 +01:00
}
wrputc('\'', stream);
} else {
wrputws(ws, stream);
}
return;
}
2015-02-10 00:03:02 +00:00
s = (unsigned char *)RepAtom(atom)->StrOfAE;
2016-07-31 10:46:51 +01:00
/* #define CRYPT_FOR_STEVE 1*/
2012-02-27 08:53:18 +00:00
#ifdef CRYPT_FOR_STEVE
2015-02-10 00:03:02 +00:00
if (Yap_GetValue(AtomCryptAtoms) != TermNil &&
Yap_GetAProp(atom, OpProperty) == NIL) {
2014-05-15 01:11:26 +01:00
char s[16];
2015-02-10 00:03:02 +00:00
sprintf(s, "x%x", (CELL)s);
2014-05-15 01:11:26 +01:00
wrputs(s, stream);
return;
}
2012-02-27 08:53:18 +00:00
#endif
2014-05-15 01:11:26 +01:00
/* if symbol then last_minus is important */
last_minus = FALSE;
atom_or_symbol = AtomIsSymbols(s);
if (lastw == atom_or_symbol && atom_or_symbol != separator /* solo */)
wrputc(' ', stream);
lastw = atom_or_symbol;
if (Quote_illegal && !legalAtom(s)) {
wrputc('\'', stream);
while (*s) {
wchar_t ch = *s++;
write_quoted(ch, '\'', stream);
}
wrputc('\'', stream);
} else {
wrputs((char *)s, stream);
}
}
2015-06-19 01:30:13 +01:00
void Yap_WriteAtom(StreamDesc *s, Atom atom) {
2015-02-10 00:03:02 +00:00
struct write_globs wglb;
wglb.stream = s;
wglb.Quote_illegal = FALSE;
putAtom(atom, 0, &wglb);
}
2015-02-10 00:03:02 +00:00
static int IsCodesTerm(Term string) /* checks whether this is a string */
{
2014-05-15 01:11:26 +01:00
if (IsVarTerm(string))
return FALSE;
do {
Term hd;
int ch;
2015-02-10 00:03:02 +00:00
if (!IsPairTerm(string))
return (FALSE);
2014-05-15 01:11:26 +01:00
hd = HeadOfTerm(string);
2015-02-10 00:03:02 +00:00
if (IsVarTerm(hd))
return (FALSE);
if (!IsIntTerm(hd))
return (FALSE);
2014-05-15 01:11:26 +01:00
ch = IntOfTerm(HeadOfTerm(string));
if ((ch < ' ' || ch > MAX_ISO_LATIN1) && ch != '\n' && ch != '\t')
2015-02-10 00:03:02 +00:00
return (FALSE);
2014-05-15 01:11:26 +01:00
string = TailOfTerm(string);
2015-02-10 00:03:02 +00:00
if (IsVarTerm(string))
return (FALSE);
2014-05-15 01:11:26 +01:00
} while (string != TermNil);
2015-02-10 00:03:02 +00:00
return (TRUE);
}
/* writes a string */
2015-02-10 00:03:02 +00:00
static void putString(Term string, struct write_globs *wglb)
{
2014-05-15 01:11:26 +01:00
wrf stream = wglb->stream;
wrputc('"', stream);
while (string != TermNil) {
wchar_t ch = IntOfTerm(HeadOfTerm(string));
write_quoted(ch, '"', stream);
string = TailOfTerm(string);
}
wrputc('"', stream);
lastw = alphanum;
}
/* writes a string */
2015-02-10 00:03:02 +00:00
static void putUnquotedString(Term string, struct write_globs *wglb)
{
2014-05-15 01:11:26 +01:00
wrf stream = wglb->stream;
while (string != TermNil) {
int ch = IntOfTerm(HeadOfTerm(string));
wrputc(ch, stream);
string = TailOfTerm(string);
}
lastw = alphanum;
}
2015-02-10 00:03:02 +00:00
static Term from_pointer(CELL *ptr0, struct rewind_term *rwt,
struct write_globs *wglb) {
2014-05-15 01:11:26 +01:00
CACHE_REGS
2016-07-31 10:46:51 +01:00
Term t;
2014-05-15 01:11:26 +01:00
CELL *ptr = ptr0;
while (IsVarTerm(*ptr) && !IsUnboundVar(ptr))
ptr = (CELL *)*ptr;
t = *ptr;
if (wglb->Keep_terms) {
struct rewind_term *x = rwt->parent;
2015-04-13 13:28:17 +01:00
rwt->u_sd.s.old = Yap_InitSlot(t);
rwt->u_sd.s.ptr = Yap_InitSlot((CELL)ptr0);
2014-10-23 01:21:22 +01:00
2014-05-15 01:11:26 +01:00
if (!IsAtomicTerm(t) && !IsVarTerm(t)) {
while (x) {
2016-01-03 02:06:09 +00:00
if (Yap_GetDerefedFromSlot(x->u_sd.s.old) == t)
2015-02-10 00:03:02 +00:00
return TermFoundVar;
x = x->parent;
2014-05-15 01:11:26 +01:00
}
}
} else {
rwt->u_sd.d.old = t;
rwt->u_sd.d.ptr = ptr0;
2015-02-10 00:03:02 +00:00
if (!IsVarTerm(t) && !IsAtomicTerm(t)) {
2014-05-15 01:11:26 +01:00
struct rewind_term *x = rwt->parent;
2015-02-10 00:03:02 +00:00
2014-05-15 01:11:26 +01:00
while (x) {
2015-02-10 00:03:02 +00:00
if (x->u_sd.d.old == t)
return TermFoundVar;
x = x->parent;
2014-05-15 01:11:26 +01:00
}
}
}
return t;
}
2015-02-10 00:03:02 +00:00
static CELL *restore_from_write(struct rewind_term *rwt,
struct write_globs *wglb) {
CACHE_REGS
2016-07-31 10:46:51 +01:00
CELL *ptr;
if (wglb->Keep_terms) {
2016-03-29 01:55:12 +01:00
ptr = Yap_GetPtrFromSlot(rwt->u_sd.s.ptr);
Yap_RecoverSlots(2, rwt->u_sd.s.old);
2015-06-19 01:30:13 +01:00
// 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 */
2015-02-10 00:03:02 +00:00
static void write_var(CELL *t, struct write_globs *wglb,
struct rewind_term *rwt) {
2014-05-15 01:11:26 +01:00
CACHE_REGS
2016-07-31 10:46:51 +01:00
if (lastw == alphanum) {
wrputc(' ', wglb->stream);
}
2014-05-15 01:11:26 +01:00
wrputc('_', wglb->stream);
/* make sure we don't get no creepy spaces where they shouldn't be */
lastw = separator;
if (IsAttVar(t)) {
2015-02-10 00:03:02 +00:00
Int vcount = (t - H0);
2014-05-15 01:11:26 +01:00
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) {
2015-02-10 00:03:02 +00:00
attvar_record *attv = RepAttVar(t);
CELL *l = &attv->Value; /* dirty low-level hack, check atts.h */
wrputs("$AT(", wglb->stream);
write_var(t, wglb, rwt);
wrputc(',', wglb->stream);
writeTerm(from_pointer(l, &nrwt, wglb), 999, 1, FALSE, wglb, &nrwt);
l = restore_from_write(&nrwt, wglb);
wrputc(',', wglb->stream);
l++;
writeTerm(from_pointer(l, &nrwt, wglb), 999, 1, FALSE, wglb, &nrwt);
restore_from_write(&nrwt, wglb);
wrclose_bracket(wglb, TRUE);
2014-05-15 01:11:26 +01:00
}
wglb->Portray_delays = TRUE;
return;
}
wrputc('D', wglb->stream);
2015-02-10 00:03:02 +00:00
wrputn(vcount, wglb);
2014-05-15 01:11:26 +01:00
} else {
2015-02-10 00:03:02 +00:00
wrputn(((Int)(t - H0)), wglb);
2014-05-15 01:11:26 +01:00
}
}
2015-02-10 00:03:02 +00:00
static Term check_infinite_loop(Term t, struct rewind_term *x,
struct write_globs *wglb) {
2014-05-15 01:11:26 +01:00
CACHE_REGS
2016-07-31 10:46:51 +01:00
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;
}
2014-05-15 01:11:26 +01:00
}
return t;
2009-05-22 18:24:30 +01:00
}
2015-02-10 00:03:02 +00:00
static void write_list(Term t, int direction, int depth,
struct write_globs *wglb, struct rewind_term *rwt) {
2014-05-15 01:11:26 +01:00
Term ti;
struct rewind_term nrwt;
nrwt.parent = rwt;
nrwt.u_sd.s.ptr = 0;
while (1) {
int ndirection;
int do_jump;
2015-02-10 00:03:02 +00:00
writeTerm(from_pointer(RepPair(t), &nrwt, wglb), 999, depth + 1, FALSE,
wglb, &nrwt);
2014-05-15 01:11:26 +01:00
t = AbsPair(restore_from_write(&nrwt, wglb));
ti = TailOfTerm(t);
if (IsVarTerm(ti))
break;
if (!IsPairTerm(ti) ||
2015-02-10 00:03:02 +00:00
!IsPairTerm((ti = check_infinite_loop(ti, rwt, wglb))))
2014-05-15 01:11:26 +01:00
break;
2015-02-10 00:03:02 +00:00
ndirection = RepPair(ti) - RepPair(t);
2014-05-15 01:11:26 +01:00
/* 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);
}
2014-05-15 01:11:26 +01:00
wrputc('|', wglb->stream);
putAtom(Atom3Dots, wglb->Quote_illegal, wglb);
return;
}
lastw = separator;
direction = ndirection;
depth++;
if (do_jump)
break;
wrputc(',', wglb->stream);
t = ti;
}
if (IsPairTerm(ti)) {
2015-02-10 00:03:02 +00:00
Term nt = from_pointer(RepPair(t) + 1, &nrwt, wglb);
2014-05-15 01:11:26 +01:00
/* we found an infinite loop */
if (IsAtomTerm(nt)) {
if (lastw == symbol || lastw == separator) {
wrputc(' ', wglb->stream);
}
2015-02-10 00:03:02 +00:00
wrputc('|', wglb->stream);
2014-05-15 01:11:26 +01:00
writeTerm(nt, 999, depth, FALSE, wglb, rwt);
} else {
/* keep going on the list */
2015-02-10 00:03:02 +00:00
wrputc(',', wglb->stream);
2014-05-15 01:11:26 +01:00
write_list(nt, direction, depth, wglb, &nrwt);
}
restore_from_write(&nrwt, wglb);
} else if (ti != MkAtomTerm(AtomNil)) {
2016-03-29 01:55:12 +01:00
if (lastw == symbol || lastw == separator) {
wrputc(' ', wglb->stream);
}
2014-05-15 01:11:26 +01:00
wrputc('|', wglb->stream);
lastw = separator;
2015-02-10 00:03:02 +00:00
writeTerm(from_pointer(RepPair(t) + 1, &nrwt, wglb), 999, depth, FALSE,
wglb, &nrwt);
2014-05-15 01:11:26 +01:00
restore_from_write(&nrwt, wglb);
}
2015-02-10 00:03:02 +00:00
}
2015-02-10 00:03:02 +00:00
static void writeTerm(Term t, int p, int depth, int rinfixarg,
struct write_globs *wglb, struct rewind_term *rwt)
2009-05-24 21:14:23 +01:00
/* term to write */
/* context priority */
2015-02-10 00:03:02 +00:00
{
CACHE_REGS
2016-07-31 10:46:51 +01:00
struct rewind_term nrwt;
2009-05-22 18:24:30 +01:00
nrwt.parent = rwt;
nrwt.u_sd.s.ptr = 0;
2015-10-22 00:45:21 +01:00
if (wglb->MaxDepth != 0 && depth > wglb->MaxDepth) {
putAtom(Atom3Dots, wglb->Quote_illegal, wglb);
return;
}
2016-03-29 01:55:12 +01:00
DBTerm *ex;
Yap_ResetException(worker_id);
t = Deref(t);
if (IsVarTerm(t)) {
2009-05-22 18:24:30 +01:00
write_var((CELL *)t, wglb, &nrwt);
} else if (IsIntTerm(t)) {
2014-06-11 19:30:44 +01:00
2015-02-10 00:03:02 +00:00
wrputn((Int)IntOfTerm(t), wglb);
} else if (IsAtomTerm(t)) {
putAtom(AtomOfTerm(t), wglb->Quote_illegal, wglb);
} else if (IsPairTerm(t)) {
2015-02-10 00:03:02 +00:00
if (wglb->Ignore_ops) {
wrputs("'.'(", wglb->stream);
2011-04-22 15:29:41 +01:00
lastw = separator;
2014-10-23 01:21:22 +01:00
2015-02-10 00:03:02 +00:00
writeTerm(from_pointer(RepPair(t), &nrwt, wglb), 999, depth + 1, FALSE,
wglb, &nrwt);
t = AbsPair(restore_from_write(&nrwt, wglb));
2015-02-10 00:03:02 +00:00
wrputs(",", wglb->stream);
writeTerm(from_pointer(RepPair(t) + 1, &nrwt, wglb), 999, depth + 1,
FALSE, wglb, &nrwt);
2011-04-22 15:29:41 +01:00
restore_from_write(&nrwt, wglb);
wrclose_bracket(wglb, TRUE);
2011-04-22 15:29:41 +01:00
return;
2015-02-10 00:03:02 +00:00
}
2015-10-22 00:45:21 +01:00
if (wglb->Use_portray)
2016-03-29 01:55:12 +01:00
if (callPortray(t, &ex, wglb->stream - GLOBAL_Stream PASS_REGS)) {
Yap_CopyException(ex);
Yap_RaiseException();
2015-10-22 00:45:21 +01:00
return;
2015-06-19 01:30:13 +01:00
}
if (trueGlobalPrologFlag(WRITE_STRINGS_FLAG) && IsCodesTerm(t)) {
putString(t, wglb);
} else {
2012-02-13 23:07:31 +00:00
wrputc('[', wglb->stream);
lastw = separator;
2015-02-10 00:03:02 +00:00
/* we assume t was already saved in the stack */
write_list(t, 0, depth, wglb, rwt);
2012-02-13 23:07:31 +00:00
wrputc(']', wglb->stream);
2015-02-10 00:03:02 +00:00
lastw = separator;
}
2015-02-10 00:03:02 +00:00
} else { /* compound term */
Functor functor = FunctorOfTerm(t);
int Arity;
Atom atom;
int op, lp, rp;
if (IsExtensionFunctor(functor)) {
2015-02-10 00:03:02 +00:00
switch ((CELL)functor) {
2016-03-29 01:55:12 +01:00
case (CELL)FunctorDouble:
2015-02-10 00:03:02 +00:00
wrputf(FloatOfTerm(t), wglb);
return;
2016-03-29 01:55:12 +01:00
case (CELL)FunctorString:
2015-09-21 23:05:36 +01:00
write_string(UStringOfTerm(t), wglb);
2015-02-10 00:03:02 +00:00
return;
2016-03-29 01:55:12 +01:00
case (CELL)FunctorAttVar:
2015-02-10 00:03:02 +00:00
write_var(RepAppl(t) + 1, wglb, &nrwt);
return;
2016-03-29 01:55:12 +01:00
case (CELL)FunctorDBRef:
2015-02-10 00:03:02 +00:00
wrputref(RefOfTerm(t), wglb->Quote_illegal, wglb);
return;
2016-03-29 01:55:12 +01:00
case (CELL)FunctorLongInt:
2015-02-10 00:03:02 +00:00
wrputn(LongIntOfTerm(t), wglb);
return;
2016-07-31 10:46:51 +01:00
/* case (CELL)FunctorBigInt: */
default:
2015-02-10 00:03:02 +00:00
writebig(t, p, depth, rinfixarg, wglb, rwt);
return;
}
}
Arity = ArityOfFunctor(functor);
atom = NameOfFunctor(functor);
#ifdef SFUNC
if (Arity == SFArity) {
2015-02-10 00:03:02 +00:00
int argno = 1;
CELL *p = ArgsOfSFTerm(t);
putAtom(atom, wglb->Quote_illegal, wglb);
wropen_bracket(wglb, FALSE);
lastw = separator;
while (*p) {
2015-02-10 00:03:02 +00:00
Int sl = 0;
while (argno < *p) {
wrputc('_', wglb->stream), wrputc(',', wglb->stream);
++argno;
}
*p++;
lastw = separator;
/* cannot use the term directly with the SBA */
writeTerm(from_pointer(p, &nrwt, wglb), 999, depth + 1, FALSE, wglb,
&nrwt);
p = restore_from_write(&nrwt, wglb) + 1;
if (*p)
wrputc(',', wglb->stream);
argno++;
2014-05-15 01:11:26 +01:00
}
wrclose_bracket(wglb, TRUE);
return;
}
#endif
if (wglb->Use_portray) {
2016-03-29 01:55:12 +01:00
if (callPortray(t, &ex, wglb->stream - GLOBAL_Stream PASS_REGS)) {
Yap_CopyException(ex);
Yap_RaiseException();
2015-02-10 00:03:02 +00:00
return;
2015-06-19 01:30:13 +01:00
}
}
if (!wglb->Ignore_ops && Arity == 1 && Yap_IsPrefixOp(atom, &op, &rp)) {
2015-02-10 00:03:02 +00:00
Term tright = ArgOfTerm(1, t);
int bracket_right = !IsVarTerm(tright) && IsAtomTerm(tright) &&
2016-07-31 10:46:51 +01:00
Yap_IsOp(AtomOfTerm(tright));
if (op > p) {
2015-02-10 00:03:02 +00:00
wropen_bracket(wglb, TRUE);
}
putAtom(atom, wglb->Quote_illegal, wglb);
if (bracket_right) {
2015-02-10 00:03:02 +00:00
/* avoid stuff such as \+ (a,b) being written as \+(a,b) */
wropen_bracket(wglb, TRUE);
2012-03-19 08:58:26 +00:00
} else if (atom == AtomMinus) {
2015-02-10 00:03:02 +00:00
last_minus = TRUE;
}
2015-02-10 00:03:02 +00:00
writeTerm(from_pointer(RepAppl(t) + 1, &nrwt, wglb), rp, depth + 1, TRUE,
wglb, &nrwt);
2009-05-24 21:14:23 +01:00
restore_from_write(&nrwt, wglb);
if (bracket_right) {
2015-02-10 00:03:02 +00:00
wrclose_bracket(wglb, TRUE);
}
if (op > p) {
2015-02-10 00:03:02 +00:00
wrclose_bracket(wglb, TRUE);
}
} else if (!wglb->Ignore_ops &&
2015-02-10 00:03:02 +00:00
(Arity == 1 ||
((atom == AtomEmptyBrackets || atom == AtomEmptyCurlyBrackets ||
atom == AtomEmptySquareBrackets) &&
Yap_IsListTerm(ArgOfTerm(1, t)))) &&
Yap_IsPosfixOp(atom, &op, &lp)) {
2015-02-10 00:03:02 +00:00
Term tleft = ArgOfTerm(1, t);
2015-02-10 00:03:02 +00:00
int bracket_left, offset;
2013-09-13 11:44:26 +01:00
if (Arity != 1) {
2015-02-10 00:03:02 +00:00
tleft = ArgOfTerm(1, t);
offset = 2;
2013-09-13 11:44:26 +01:00
} else {
2015-02-10 00:03:02 +00:00
tleft = ArgOfTerm(1, t);
offset = 1;
2013-09-13 11:44:26 +01:00
}
bracket_left =
2016-07-31 10:46:51 +01:00
!IsVarTerm(tleft) && IsAtomTerm(tleft) && Yap_IsOp(AtomOfTerm(tleft));
if (op > p) {
2015-02-10 00:03:02 +00:00
/* avoid stuff such as \+ (a,b) being written as \+(a,b) */
wropen_bracket(wglb, TRUE);
}
if (bracket_left) {
2015-02-10 00:03:02 +00:00
wropen_bracket(wglb, TRUE);
}
2015-02-10 00:03:02 +00:00
writeTerm(from_pointer(RepAppl(t) + offset, &nrwt, wglb), lp, depth + 1,
rinfixarg, wglb, &nrwt);
2009-05-24 21:14:23 +01:00
restore_from_write(&nrwt, wglb);
if (bracket_left) {
2015-02-10 00:03:02 +00:00
wrclose_bracket(wglb, TRUE);
}
2015-02-10 00:03:02 +00:00
if (Arity > 1) {
if (atom == AtomEmptyBrackets) {
wrputc('(', wglb->stream);
} else if (atom == AtomEmptySquareBrackets) {
wrputc('[', wglb->stream);
} else if (atom == AtomEmptyCurlyBrackets) {
wrputc('{', wglb->stream);
}
lastw = separator;
write_list(tleft, 0, depth, wglb, rwt);
if (atom == AtomEmptyBrackets) {
wrputc(')', wglb->stream);
} else if (atom == AtomEmptySquareBrackets) {
wrputc(']', wglb->stream);
} else if (atom == AtomEmptyCurlyBrackets) {
wrputc('}', wglb->stream);
}
lastw = separator;
2013-07-07 22:15:25 +01:00
} else {
2015-02-10 00:03:02 +00:00
putAtom(atom, wglb->Quote_illegal, wglb);
2013-07-07 22:15:25 +01:00
}
if (op > p) {
2015-02-10 00:03:02 +00:00
wrclose_bracket(wglb, TRUE);
}
2015-02-10 00:03:02 +00:00
} else if (!wglb->Ignore_ops && Arity == 2 &&
Yap_IsInfixOp(atom, &op, &lp, &rp)) {
2015-02-10 00:03:02 +00:00
Term tleft = ArgOfTerm(1, t);
Term tright = ArgOfTerm(2, t);
int bracket_left =
2016-07-31 10:46:51 +01:00
!IsVarTerm(tleft) && IsAtomTerm(tleft) && Yap_IsOp(AtomOfTerm(tleft));
2015-02-10 00:03:02 +00:00
int bracket_right = !IsVarTerm(tright) && IsAtomTerm(tright) &&
2016-07-31 10:46:51 +01:00
Yap_IsOp(AtomOfTerm(tright));
if (op > p) {
2015-02-10 00:03:02 +00:00
/* avoid stuff such as \+ (a,b) being written as \+(a,b) */
wropen_bracket(wglb, TRUE);
lastw = separator;
}
if (bracket_left) {
2015-02-10 00:03:02 +00:00
wropen_bracket(wglb, TRUE);
}
2015-02-10 00:03:02 +00:00
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) {
2015-02-10 00:03:02 +00:00
wrclose_bracket(wglb, TRUE);
}
/* avoid quoting commas and bars */
2015-09-21 23:05:36 +01:00
if (!strcmp((char *)RepAtom(atom)->StrOfAE, ",")) {
2015-02-10 00:03:02 +00:00
wrputc(',', wglb->stream);
lastw = separator;
2015-09-21 23:05:36 +01:00
} else if (!strcmp((char *)RepAtom(atom)->StrOfAE, "|")) {
if (lastw == symbol || lastw == separator) {
wrputc(' ', wglb->stream);
}
2015-02-10 00:03:02 +00:00
wrputc('|', wglb->stream);
lastw = separator;
} else
2015-02-10 00:03:02 +00:00
putAtom(atom, wglb->Quote_illegal, wglb);
if (bracket_right) {
2015-02-10 00:03:02 +00:00
wropen_bracket(wglb, TRUE);
}
2015-02-10 00:03:02 +00:00
writeTerm(from_pointer(RepAppl(t) + 2, &nrwt, wglb), rp, depth + 1, TRUE,
wglb, &nrwt);
2009-05-24 21:14:23 +01:00
restore_from_write(&nrwt, wglb);
if (bracket_right) {
2015-02-10 00:03:02 +00:00
wrclose_bracket(wglb, TRUE);
}
if (op > p) {
2015-02-10 00:03:02 +00:00
wrclose_bracket(wglb, TRUE);
}
2016-03-29 01:55:12 +01:00
} else if (functor == FunctorDollarVar) {
Term ti = ArgOfTerm(1, t);
if (lastw == alphanum) {
2015-02-10 00:03:02 +00:00
wrputc(' ', wglb->stream);
}
2016-03-29 01:55:12 +01:00
if (wglb->Handle_vars && !IsVarTerm(ti) &&
(IsIntTerm(ti) || IsCodesTerm(ti) || IsAtomTerm(ti) ||
IsStringTerm(ti))) {
2015-02-10 00:03:02 +00:00
if (IsIntTerm(ti)) {
Int k = IntOfTerm(ti);
if (k == -1) {
wrputc('_', wglb->stream);
lastw = alphanum;
return;
} else {
wrputc((k % 26) + 'A', wglb->stream);
if (k >= 26) {
/* make sure we don't get confused about our context */
lastw = separator;
wrputn(k / 26, wglb);
} else
lastw = alphanum;
}
} else if (IsAtomTerm(ti)) {
putAtom(AtomOfTerm(ti), FALSE, wglb);
2015-11-05 16:35:25 +00:00
} else if (IsStringTerm(ti)) {
putString(ti, wglb);
2015-02-10 00:03:02 +00:00
} else {
putUnquotedString(ti, wglb);
}
} else {
2015-02-10 00:03:02 +00:00
wrputs("'$VAR'(", wglb->stream);
lastw = separator;
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) {
2012-02-13 23:07:31 +00:00
wrputc('{', wglb->stream);
lastw = separator;
2016-03-29 01:55:12 +01:00
writeTerm(from_pointer(RepAppl(t) + 1, &nrwt, wglb), GLOBAL_MaxPriority,
depth + 1, FALSE, wglb, &nrwt);
2009-05-24 21:14:23 +01:00
restore_from_write(&nrwt, wglb);
2012-02-13 23:07:31 +00:00
wrputc('}', wglb->stream);
lastw = separator;
2015-02-10 00:03:02 +00:00
} else if (atom == AtomArray) {
2012-02-13 23:07:31 +00:00
wrputc('{', wglb->stream);
lastw = separator;
for (op = 1; op <= Arity; ++op) {
2015-02-10 00:03:02 +00:00
if (op == wglb->MaxArgs) {
wrputs("...", wglb->stream);
break;
}
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;
}
2014-05-15 01:11:26 +01:00
}
wrputc('}', wglb->stream);
lastw = separator;
} else {
putAtom(atom, wglb->Quote_illegal, wglb);
lastw = separator;
wropen_bracket(wglb, FALSE);
for (op = 1; op <= Arity; ++op) {
2015-02-10 00:03:02 +00:00
if (op == wglb->MaxArgs) {
wrputc('.', wglb->stream);
wrputc('.', wglb->stream);
wrputc('.', wglb->stream);
break;
}
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;
}
2014-05-15 01:11:26 +01:00
}
wrclose_bracket(wglb, TRUE);
}
}
}
2015-10-22 00:45:21 +01:00
void Yap_plwrite(Term t, StreamDesc *mywrite, int max_depth, int flags,
int priority)
2015-02-10 00:03:02 +00:00
/* term to be written */
/* consumer */
/* write options */
{
2015-08-07 22:57:53 +01:00
CACHE_REGS
2016-07-31 10:46:51 +01:00
struct write_globs wglb;
2015-06-19 01:30:13 +01:00
struct rewind_term rwt;
2016-01-03 02:06:09 +00:00
yhandle_t sls = Yap_CurrentSlot();
2015-06-19 01:30:13 +01:00
if (!mywrite) {
2015-10-22 00:45:21 +01:00
CACHE_REGS
2016-07-31 10:46:51 +01:00
wglb.stream = GLOBAL_Stream + LOCAL_c_error_stream;
2015-06-19 01:30:13 +01:00
} else
2014-05-15 01:11:26 +01:00
wglb.stream = mywrite;
2015-06-19 01:30:13 +01:00
wglb.lw = start;
2014-05-15 01:11:26 +01:00
wglb.last_atom_minus = FALSE;
wglb.Quote_illegal = flags & Quote_illegal_f;
wglb.Handle_vars = flags & Handle_vars_f;
wglb.Use_portray = flags & Use_portray_f;
wglb.Portray_delays = flags & AttVar_Portray_f;
wglb.MaxDepth = max_depth;
wglb.MaxArgs = max_depth;
/* notice: we must have ASP well set when using portray, otherwise
we cannot make recursive Prolog calls */
2015-02-10 00:03:02 +00:00
wglb.Keep_terms = (flags & (Use_portray_f | To_heap_f));
2015-11-05 16:35:25 +00:00
/* initialize wglb */
2014-05-15 01:11:26 +01:00
rwt.parent = NULL;
wglb.Ignore_ops = flags & Ignore_ops_f;
wglb.Write_strings = flags & BackQuote_String_f;
/* protect slots for portray */
writeTerm(from_pointer(&t, &rwt, &wglb), priority, 1, FALSE, &wglb, &rwt);
2015-06-19 01:30:13 +01:00
if (flags & New_Line_f) {
if (flags & Fullstop_f) {
wrputc('.', wglb.stream);
wrputc('\n', wglb.stream);
} else {
wrputc('\n', wglb.stream);
}
} else {
if (flags & Fullstop_f) {
wrputc('.', wglb.stream);
wrputc(' ', wglb.stream);
}
}
2014-05-15 01:11:26 +01:00
restore_from_write(&rwt, &wglb);
2015-10-22 00:45:21 +01:00
Yap_CloseSlots(sls);
}
2015-09-21 23:05:36 +01:00
char *Yap_TermToString(Term t, size_t *lengthp, encoding_t enc, int flags) {
2015-09-21 23:05:36 +01:00
CACHE_REGS
2016-07-31 10:46:51 +01:00
int sno = Yap_open_buf_write_stream(enc, flags);
const char *sf;
2016-09-30 23:10:01 +01:00
DBTerm *e = LOCAL_BallTerm;
2015-09-21 23:05:36 +01:00
if (sno < 0)
2015-10-22 00:45:21 +01:00
return NULL;
2015-09-21 23:05:36 +01:00
LOCAL_c_output_stream = sno;
if (enc)
GLOBAL_Stream[sno].encoding = enc;
else
GLOBAL_Stream[sno].encoding = LOCAL_encoding;
Yap_plwrite(t, GLOBAL_Stream + sno, 0, flags, GLOBAL_MaxPriority);
2016-07-31 10:46:51 +01:00
sf = Yap_MemExportStreamPtr(sno);
2016-09-30 23:10:01 +01:00
size_t len = strlen(sf);
char *new = malloc( len + 1 );
strcpy( new, sf );
2015-10-22 00:45:21 +01:00
Yap_CloseStream(sno);
2016-09-30 23:10:01 +01:00
if (e)
LOCAL_BallTerm = e;
return new;
2015-09-21 23:05:36 +01:00
}