YAP 7.1.0
write.c
1/*************************************************************************
2 * *
3 * YAP Prolog *
4 * *
5 * Yap Prolog was developed at NCCUP - Universidade do Porto *
6 * *
7 * Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
8 * *
9 **************************************************************************
10 * *
11 * File: write.c * Last
12 *rev: * mods:
13 ** comments: Writing a Prolog Term *
14 * *
15 *************************************************************************/
16#ifdef SCCS
17static char SccsId[] = "%W% %G%";
18#endif
19
20#include "Yap.h"
21#include "YapHeap.h"
22#include "YapText.h"
23#include "Yatom.h"
24#include "clause.h"
25#include "yapio.h"
26#include <math.h>
27#include <stdlib.h>
28#if COROUTINING
29#include "attvar.h"
30#endif
31#include "iopreds.h"
32
33#if HAVE_STRING_H
34#include <string.h>
35#endif
36#if HAVE_CTYPE_H
37#include <ctype.h>
38#endif
39#if HAVE_LOCALE_H
40#include <locale.h>
41#endif
42
43/* describe the type of the previous term to have been written */
44typedef enum {
45 start, /* initialization */
46 separator, /* the previous term was a separator like ',', ')', ... */
47 alphanum, /* the previous term was an atom or number */
48 symbol /* the previous term was a symbol like +, -, *, .... */
49} wtype;
50
51typedef StreamDesc *wrf;
52
53typedef struct union_slots {
54 Int old;
55 Int ptr;
56} uslots;
57
58typedef struct union_direct {
59 Term old;
60 CELL *ptr;
61} udirect;
62
63typedef struct write_globs {
64 StreamDesc *stream;
65 bool Quote_illegal, Ignore_ops, Handle_vars, Handle_old_vars, Use_portray, Portray_delays;
66 bool Keep_terms;
67 bool Write_Loops;
68 bool Write_strings;
69 UInt last_atom_minus;
70 UInt MaxDepth, MaxArgs;
71 wtype lw;
72 CELL *oldH, *hbase;
73 Functor FunctorNumberVars;
74} wglbs;
75
76#define lastw wglb->lw
77#define last_minus wglb->last_atom_minus
78
79static bool callPortray(Term t, int sno USES_REGS) {
80 PredEntry *pe;
81 Int b0 = LCL0 - (CELL *)B;
82
83 UNLOCK(GLOBAL_Stream[sno].streamlock);
84 if ((pe = RepPredProp(Yap_GetPredPropByFunc(FunctorPortray, USER_MODULE))) &&
85 pe->OpcodeOfPred != FAIL_OPCODE && pe->OpcodeOfPred != UNDEF_OPCODE &&
86 Yap_execute_pred(pe, &t, true PASS_REGS)) {
87 choiceptr B0 = (choiceptr)(LCL0 - b0);
88 Yap_fail_all(B0 PASS_REGS);
89 LOCK(GLOBAL_Stream[sno].streamlock);
90 return true;
91 }
92 LOCK(GLOBAL_Stream[sno].streamlock);
93
94 return false;
95}
96
97#define PROTECT(t, F) \
98 { \
99 yhandle_t yt = Yap_InitHandle(t); \
100 F; \
101 t = Yap_PopHandle(yt); \
102 }
103
104
105
106static void wrputn(Int, struct write_globs *);
107static void wrputf(Float, struct write_globs *);
108static void wrputref(void *, int, struct write_globs *);
109static int legalAtom(unsigned char *);
110/*static int LeftOpToProtect(Atom, int);
111 static int RightOpToProtect(Atom, int);*/
112static wtype AtomIsSymbols(unsigned char *);
113static void putAtom(Atom, int, struct write_globs *);
114static void writeTerm(Term, int, int, int, struct write_globs *);
115
116#define wrputc(WF, X) \
117 (X)->stream_wputc(X - GLOBAL_Stream, WF) /* writes a character */
118
119/*
120 protect bracket from merging with previoous character.
121 avoid stuff like not (2,3) -> not(2,3) or
122*/
123static void wropen_bracket(struct write_globs *wglb, int protect) {
124 StreamDesc *stream = wglb->stream;
125
126 if (lastw != separator && protect)
127 wrputc(' ', stream);
128 wrputc('(', stream);
129 lastw = separator;
130}
131
132static void wrclose_bracket(struct write_globs *wglb, int protect) {
133 wrf stream = wglb->stream;
134
135 wrputc(')', stream);
136 lastw = separator;
137}
138
139static int protect_open_number(struct write_globs *wglb, int lm,
140 int minus_required) {
141 wrf stream = wglb->stream;
142
143 if (lastw == symbol && lm && !minus_required) {
144 wropen_bracket(wglb, TRUE);
145 return TRUE;
146 } else if (lastw == alphanum || (lastw == symbol && minus_required)) {
147 wrputc(' ', stream);
148 }
149 return FALSE;
150}
151
152static void protect_close_number(struct write_globs *wglb, int used_bracket) {
153 if (used_bracket) {
154 wrclose_bracket(wglb, TRUE);
155 } else {
156 lastw = alphanum;
157 }
158 last_minus = FALSE;
159}
160
161static void wrputn(Int n,
162 struct write_globs *wglb) /* writes an integer */
163{
164 wrf stream = wglb->stream;
165 char s[256], *s1 = s; /* that should be enough for most integers */
166 int has_minus = (n < 0);
167 int ob;
168
169 ob = protect_open_number(wglb, last_minus, has_minus);
170#if HAVE_SNPRINTF
171 snprintf(s, 256, Int_FORMAT, n);
172#else
173 sprintf(s, Int_FORMAT, n);
174#endif
175 while (*s1)
176 wrputc(*s1++, stream);
177 protect_close_number(wglb, ob);
178}
179
180inline static void wrputs(char *s, StreamDesc *stream) {
181 int c;
182 while ((c = *s++))
183 wrputc(c, stream);
184}
185
186#ifdef USE_GMP
187
188static char *ensure_space(size_t sz) {
189 CACHE_REGS
190 char *s;
191
192 s = (char *)Yap_PreAllocCodeSpace();
193 while (s + sz >= (char *)AuxSp) {
194#if USE_SYSTEM_MALLOC
195 /* may require stack expansion */
196 if (!Yap_ExpandPreAllocCodeSpace(sz, NULL, TRUE)) {
197 s = NULL;
198 break;
199 }
200 s = (char *)Yap_PreAllocCodeSpace();
201#else
202 s = NULL;
203#endif
204 }
205 if (!s) {
206 s = (char *)TR;
207 while (s + sz >= LOCAL_TrailTop) {
208 if (!Yap_growtrail(sz / sizeof(CELL), FALSE)) {
209 s = NULL;
210 break;
211 }
212 s = (char *)TR;
213 }
214 }
215 if (!s) {
216 s = (char *)HR;
217 if (s + sz >= (char *)ASP) {
218 Yap_Error(RESOURCE_ERROR_STACK, TermNil,
219 "not enough space to write bignum: it requires %d bytes", sz);
220 s = NULL;
221 }
222 }
223 return s;
224}
225
226static void write_mpint(MP_INT *big, struct write_globs *wglb) {
227 char *s;
228 int has_minus = mpz_sgn(big);
229 int ob;
230
231 s = ensure_space(3 + mpz_sizeinbase(big, 10));
232 ob = protect_open_number(wglb, last_minus, has_minus);
233 if (!s) {
234 s = mpz_get_str(NULL, 10, big);
235 if (!s)
236 return;
237 wrputs(s, wglb->stream);
238 free(s);
239 } else {
240 mpz_get_str(s, 10, big);
241 wrputs(s, wglb->stream);
242 }
243 protect_close_number(wglb, ob);
244}
245#endif
246
247/* writes a bignum */
248static void writebig(Term t, int p, int depth, int rinfixarg,
249 struct write_globs *wglb) {
250 CELL *pt = RepAppl(t) + 1;
251 CELL big_tag = pt[0];
252
253 if (big_tag == ARRAY_INT || big_tag == ARRAY_FLOAT) {
254 wrputc('{', wglb->stream);
255 wrputs("...", wglb->stream);
256 wrputc('}', wglb->stream);
257 lastw = separator;
258 return;
259#ifdef USE_GMP
260 } else if (big_tag == BIG_INT) {
261 MP_INT *big = Yap_BigIntOfTerm(t);
262 write_mpint(big, wglb);
263 return;
264 } else if (big_tag == BIG_RATIONAL) {
265 Term trat = Yap_RatTermToApplTerm(t);
266 writeTerm(trat, p, depth, rinfixarg, wglb);
267 return;
268#endif
269 } else if (big_tag >= USER_BLOB_START && big_tag < USER_BLOB_END) {
270 YAP_Opaque_CallOnWrite f;
271 CELL blob_info;
272
273 blob_info = big_tag;
274 if (GLOBAL_OpaqueHandlers &&
275 (f = GLOBAL_OpaqueHandlers[blob_info].write_handler)) {
276 (f)(wglb->stream->file, big_tag, ExternalBlobFromTerm(t), 0);
277 return;
278 }
279 }
280 wrputs("0", wglb->stream);
281}
282
283static void wrputf(Float f, struct write_globs *wglb) /* writes a float */
284
285{
286#if THREADS
287 char s[256];
288#endif
289 wrf stream = wglb->stream;
290 int sgn;
291 int ob;
292
293#if HAVE_ISNAN || defined(__WIN32)
294 if (isnan(f)) {
295 wrputs("(nan)", stream);
296 lastw = separator;
297 return;
298 }
299#endif
300 sgn = (f < 0.0);
301#if HAVE_ISINF || defined(_WIN32)
302 if (isinf(f)) {
303 if (sgn) {
304 wrputs("(-inf)", stream);
305 } else {
306 wrputs("(+inf)", stream);
307 }
308 lastw = separator;
309 return;
310 }
311#endif
312 ob = protect_open_number(wglb, last_minus, sgn);
313#if THREADS
314 /* old style writing */
315 int found_dot = FALSE;
316 char *pt = s;
317 int ch;
318 /* always use C locale for writing numbers */
319#if O_LOCALE
320 const unsigned char *decimalpoint =
321 (unsigned char *)localeconv()->decimal_point;
322 size_t l1 = strlen((const char *)decimalpoint + 1);
323#else
324 const unsigned char decimalpoint[2] = ".";
325 size_t l1 = 0;
326#endif
327
328 if (lastw == symbol || lastw == alphanum) {
329 wrputc(' ', stream);
330 }
331 lastw = alphanum;
332 // sprintf(s, "%.15g", f);
333 sprintf(s, floatFormat(), f);
334 while (*pt == ' ')
335 pt++;
336 if (*pt == '-') {
337 wrputc('-', stream);
338 pt++;
339 }
340 while ((ch = *pt) != '\0') {
341 // skip locale
342 if (ch == decimalpoint[0] &&
343 !strncmp(pt + 1, (char *)decimalpoint + 1, l1)) {
344 found_dot = TRUE;
345 pt += l1;
346 ch = '.';
347 }
348 if (ch == 'e' || ch == 'E') {
349 if (!found_dot) {
350 found_dot = TRUE;
351 wrputs(".0", stream);
352 }
353 found_dot = true;
354 }
355 wrputc(ch, stream);
356 pt++;
357 }
358 if (!found_dot) {
359 wrputs(".0", stream);
360 }
361#else
362 char buf[256];
363
364 if (lastw == symbol || lastw == alphanum) {
365 wrputc(' ', stream);
366 }
367 /* use SWI's format_float */
368 snprintf(buf, sizeof(buf)-1, RepAtom(AtomOfTerm(getAtomicGlobalPrologFlag(FLOAT_FORMAT_FLAG)))->StrOfAE,f);
369
370
371 wrputs(buf, stream);
372#endif
373 protect_close_number(wglb, ob);
374}
375
376int Yap_FormatFloat(Float f, char **s, size_t sz) {
377 CACHE_REGS
378 struct write_globs wglb;
379 int sno;
380
381 sno = Yap_open_buf_write_stream(GLOBAL_Stream[LOCAL_c_output_stream].encoding,
382 0);
383 if (sno < 0)
384 return false;
385 wglb.lw = separator;
386 wglb.stream = GLOBAL_Stream + sno;
387 wrputf(f, &wglb);
388 *s = Yap_MemExportStreamPtr(sno);
389 Yap_CloseStream(sno);
390 return true;
391}
392
393/* writes a data base reference */
394static void wrputref(void *ref, int Quote_illegal, struct write_globs *wglb) {
395 char s[256];
396 wrf stream = wglb->stream;
397
398 putAtom(AtomDBref, Quote_illegal, wglb);
399#if defined(__linux__) || defined(__APPLE__)
400#if 1
401 snprintf(s, 255, "(%p)", ref);
402#else
403 sprintf(s, "(%p," UInt_FORMAT ")", ref, ((LogUpdClause *)ref)->ClRefCount);
404#endif
405#else
406#if 1
407 snprintf(s, 255, "(0x%p)", ref);
408#else
409 sprintf(s, "(0x%p," UInt_FORMAT ")", ref, ((LogUpdClause *)ref)->ClRefCount);
410#endif
411#endif
412 wrputs(s, stream);
413 lastw = alphanum;
414}
415
416/* writes a blob (default) */
417static int wrputblob(AtomEntry *ref, int Quote_illegal,
418 struct write_globs *wglb) {
419 wrf stream = wglb->stream;
420 int rc;
421 int Yap_write_blob(AtomEntry * ref, StreamDesc * stream);
422
423 if ((rc = Yap_write_blob(ref, stream))) {
424 return rc;
425 }
426 lastw = alphanum;
427 return 1;
428}
429
430static int legalAtom(unsigned char *s) /* Is this a legal atom ? */
431{
432 wchar_t ch = *s;
433
434 if (ch == '\0')
435 return FALSE;
436 if (Yap_chtype[ch] != LC) {
437 if (ch == '[') {
438 return (s[1] == ']' && !s[2]);
439 } else if (ch == '{') {
440 return (s[1] == '}' && !s[2]);
441 } else if (Yap_chtype[ch] == SL) {
442 return (!s[1]);
443 } else if (ch == '`') {
444 return false;
445 } else if ((ch == ',' || ch == '.') && !s[1]) {
446 return false;
447 } else {
448 if (ch == '/') {
449 if (s[1] == '*')
450 return false;
451 }
452 while (ch) {
453 if (Yap_chtype[ch] != SY) {
454 return false;
455 }
456 ch = *++s;
457 }
458 }
459 return true;
460 } else
461 while ((ch = *++s) != 0)
462 if (Yap_chtype[ch] > NU)
463 return false;
464 return true;
465}
466
467static wtype
468AtomIsSymbols(unsigned char *s) /* Is this atom just formed by symbols ? */
469{
470 int ch;
471 if (Yap_chtype[(int)s[0]] == SL && s[1] == '\0')
472 return (separator);
473 while ((ch = *s++) != '\0') {
474 if (Yap_chtype[ch] != SY)
475 return alphanum;
476 }
477 return symbol;
478}
479
480static void write_quoted(wchar_t ch, wchar_t quote, wrf stream) {
481 CACHE_REGS
482 if (!(Yap_GetModuleEntry(CurrentModule)->flags & M_CHARESCAPE)) {
483 wrputc(ch, stream);
484 if (ch == '\'')
485 wrputc('\'', stream); /* be careful about quotes */
486 return;
487 }
488 if (!(ch < 0xff && chtype(ch) == BS) && ch != '\'' && ch != '\\' &&
489 ch != '`') {
490 wrputc(ch, stream);
491 } else {
492 switch (ch) {
493 case '\\':
494 wrputc('\\', stream);
495 wrputc('\\', stream);
496 break;
497 case '\'':
498 if (ch == quote)
499 wrputc('\\', stream);
500 wrputc(ch, stream);
501 break;
502 case '"':
503 if (ch == quote)
504 wrputc('\\', stream);
505 wrputc(ch, stream);
506 break;
507 case '`':
508 if (ch == quote)
509 wrputc('`', stream);
510 wrputc(ch, stream);
511 break;
512 case 7:
513 wrputc('\\', stream);
514 wrputc('a', stream);
515 break;
516 case '\b':
517 wrputc('\\', stream);
518 wrputc('b', stream);
519 break;
520 case '\t':
521 wrputc('\\', stream);
522 wrputc('t', stream);
523 break;
524 case ' ':
525 case 160:
526 wrputc(' ', stream);
527 break;
528 case '\n':
529 wrputc('\\', stream);
530 wrputc('n', stream);
531 break;
532 case 11:
533 wrputc('\\', stream);
534 wrputc('v', stream);
535 break;
536 case '\r':
537 wrputc('\\', stream);
538 wrputc('r', stream);
539 break;
540 case '\f':
541 wrputc('\\', stream);
542 wrputc('f', stream);
543 break;
544 default:
545 if (ch <= 0xff) {
546 char esc[8];
547
548 /* last backslash in ISO mode */
549 sprintf(esc, "\\%03o\\", ch);
550 wrputs(esc, stream);
551 }
552 }
553 }
554}
555
556static void write_string(const unsigned char *s,
557 struct write_globs *wglb) /* writes an integer */
558{
559 StreamDesc *stream = wglb->stream;
560 utf8proc_int32_t chr, qt;
561 unsigned char *ptr = (unsigned char *)s;
562
563 if (wglb->Write_strings)
564 qt = '`';
565 else
566 qt = '"';
567 wrputc(qt, stream);
568 do {
569 int delta;
570 ptr += (delta = get_utf8(ptr, -1, &chr));
571
572 if (chr == '\0') {
573 break;
574 }
575 if (delta == 0) {
576 chr = *ptr++;
577 }
578 write_quoted(chr, qt, stream);
579 } while (true);
580 wrputc(qt, stream);
581}
582
583/* writes an atom */
584static void putAtom(Atom atom, int Quote_illegal, struct write_globs *wglb) {
585 unsigned char *s;
586 wtype atom_or_symbol;
587 wrf stream = wglb->stream;
588 if (atom == NULL)
589 return;
590 s = RepAtom(atom)->UStrOfAE;
591 if (s[0] == '\0') {
592 if (Quote_illegal) {
593 wrputc('\'', stream);
594 wrputc('\'', stream);
595 }
596 return;
597 }
598 if (IsBlob(atom)) {
599 wrputblob(RepAtom(atom), Quote_illegal, wglb);
600 return;
601 }
602 /* #define CRYPT_FOR_STEVE 1*/
603#ifdef CRYPT_FOR_STEVE
604 if (Yap_GetValue(AtomCryptAtoms) != TermNil &&
605 Yap_GetAProp(atom, OpProperty) == NIL) {
606 char s[16];
607 sprintf(s, "x%x", (CELL)s);
608 wrputs(s, stream);
609 return;
610 }
611#endif
612 /* if symbol then last_minus is important */
613 last_minus = FALSE;
614 atom_or_symbol = AtomIsSymbols(s);
615 if (lastw == atom_or_symbol && atom_or_symbol != separator /* solo */)
616 wrputc(' ', stream);
617 lastw = atom_or_symbol;
618 if (Quote_illegal && !legalAtom(s)) {
619 wrputc('\'', stream);
620 while (*s) {
621 int32_t ch;
622 s += get_utf8(s, -1, &ch);
623 write_quoted(ch, '\'', stream);
624 }
625 wrputc('\'', stream);
626 } else {
627 wrputs((char *)s, stream);
628 }
629}
630
631void Yap_WriteAtom(StreamDesc *s, Atom atom) {
632 struct write_globs wglb;
633 wglb.stream = s;
634 wglb.Quote_illegal = FALSE;
635 putAtom(atom, 0, &wglb);
636}
637
638static int IsCodesTerm(Term string) /* checks whether this is a string */
639{
640 if (IsVarTerm(string))
641 return FALSE;
642 do {
643 Term hd;
644 int ch;
645
646 if (!IsPairTerm(string))
647 return (FALSE);
648 hd = HeadOfTerm(string);
649 if (IsVarTerm(hd))
650 return (FALSE);
651 if (!IsIntTerm(hd))
652 return (FALSE);
653 ch = IntOfTerm(HeadOfTerm(string));
654 if ((ch < ' ' || ch > MAX_ISO_LATIN1) && ch != '\n' && ch != '\t')
655 return (FALSE);
656 string = TailOfTerm(string);
657 if (IsVarTerm(string))
658 return (FALSE);
659 } while (string != TermNil);
660 return (TRUE);
661}
662
663/* writes a string */
664static void putString(Term string, struct write_globs *wglb)
665
666{
667 wrf stream = wglb->stream;
668 wrputc('"', stream);
669 while (string != TermNil) {
670 wchar_t ch = IntOfTerm(HeadOfTerm(string));
671 write_quoted(ch, '"', stream);
672 string = TailOfTerm(string);
673 }
674 wrputc('"', stream);
675 lastw = alphanum;
676}
677
678/* writes a string */
679static void putUnquotedString(Term string, struct write_globs *wglb)
680
681{
682 wrf stream = wglb->stream;
683 while (string != TermNil) {
684 int ch = IntOfTerm(HeadOfTerm(string));
685 wrputc(ch, stream);
686 string = TailOfTerm(string);
687 }
688 lastw = alphanum;
689}
690
691static void write_var(CELL *t, int depth, struct write_globs *wglb) {
692 CACHE_REGS
693 if (lastw == alphanum) {
694 wrputc(' ', wglb->stream);
695 }
696 wrputc('_', wglb->stream);
697 /* make sure we don't get no creepy spaces where they shouldn't be */
698 lastw = separator;
699 if (IsAttVar(t)) {
700 Int vcount = (t - H0);
701 if (wglb->Portray_delays) {
702 exts ext = ExtFromCell(t);
703
704 wglb->Portray_delays = FALSE;
705 if (ext == attvars_ext) {
706 attvar_record *attv = RepAttVar(t);
707 CELL *l = &attv->Future; /* dirty low-level hack, check atts.h */
708
709 wrputs("$AT(", wglb->stream);
710 write_var(t, depth, wglb);
711 wrputc(',', wglb->stream);
712 PROTECT(*t, writeTerm(*l, 999, depth-1, FALSE, wglb));
713 attv = RepAttVar(t);
714 wrputc(',', wglb->stream);
715 l++;
716 writeTerm(*l, 999, depth-1, FALSE, wglb);
717 wrclose_bracket(wglb, TRUE);
718 }
719 wglb->Portray_delays = TRUE;
720 return;
721 }
722 wrputc('D', wglb->stream);
723 wrputn(vcount, wglb);
724 } else {
725 wrputn(((Int)(t - H0)), wglb);
726 }
727}
728
729static void write_list(Term t, int direction, int depth,
730 struct write_globs *wglb) {
731 Term ti;
732
733 while (1) {
734 if (t == TermNil)
735 break;
736 if (depth == 1) {
737 if (lastw == symbol || lastw == separator) {
738 wrputc(' ', wglb->stream);
739 }
740 wrputc('|', wglb->stream);
741 putAtom(Atom3Dots, wglb->Quote_illegal, wglb);
742 return;
743 }
744 depth--;
745 PROTECT(t, writeTerm(HeadOfTerm(t), 999, depth, FALSE, wglb));
746
747 if (depth == 0) {
748 putAtom(Atom3Dots, wglb->Quote_illegal, wglb);
749 return;
750 }
751 ti = TailOfTerm(t);
752 if (IsVarTerm(ti))
753 break;
754 if (!IsPairTerm(ti))
755 break;
756 lastw = separator;
757 wrputc(',', wglb->stream);
758 t = ti;
759 }
760 if (IsPairTerm(ti)) {
761 /* we found an infinite loop */
762 /* keep going on the list */
763 wrputc(',', wglb->stream);
764 write_list(ti, direction, depth-1, wglb);
765 } else if (ti != MkAtomTerm(AtomNil)) {
766 if (lastw == symbol || lastw == separator) {
767 wrputc(' ', wglb->stream);
768 }
769 wrputc('|', wglb->stream);
770 lastw = separator;
771 writeTerm(ti, 999, depth-1, FALSE, wglb);
772 }
773}
774
775static void writeTerm(Term t, int p, int depth, int rinfixarg,
776 struct write_globs *wglb)
777/* term to write */
778/* context priority */
779{
780 CACHE_REGS
781
782 if (depth == 0) {
783 putAtom(Atom3Dots, wglb->Quote_illegal, wglb);
784 return;
785 }
786 t = Deref(t);
787 if (IsVarTerm(t)) {
788 write_var((CELL *)t, depth, wglb);
789 } else if (IsIntTerm(t)) {
790
791 wrputn((Int)IntOfTerm(t), wglb);
792 } else if (IsAtomTerm(t)) {
793 putAtom(AtomOfTerm(t), wglb->Quote_illegal, wglb);
794 } else if (IsPairTerm(t)) {
795 if (wglb->Ignore_ops && false) {
796 wrputs("'.'(", wglb->stream);
797 lastw = separator;
798
799 PROTECT(t, writeTerm(HeadOfTerm(t), 999, depth-1, FALSE, wglb));
800 wrputs(",", wglb->stream);
801 writeTerm(TailOfTerm(t), 999, depth-1, FALSE, wglb);
802 wrclose_bracket(wglb, TRUE);
803 return;
804 }
805 if (wglb->Use_portray)
806 if (callPortray(t, wglb->stream - GLOBAL_Stream PASS_REGS)) {
807 return;
808 }
809 if (trueGlobalPrologFlag(WRITE_STRINGS_FLAG) && IsCodesTerm(t)) {
810 putString(t, wglb);
811 } else {
812 wrputc('[', wglb->stream);
813 lastw = separator;
814 /* we assume t was already saved in the stack */
815 write_list(t, 0, LOCAL_max_depth, wglb);
816 wrputc(']', wglb->stream);
817 lastw = separator;
818 }
819 } else { /* compound term */
820 Functor functor = FunctorOfTerm(t);
821 int Arity;
822 Atom atom;
823 int op, lp, rp;
824
825 if (IsExtensionFunctor(functor)) {
826 switch ((CELL)functor) {
827 case (CELL)FunctorDouble:
828 wrputf(FloatOfTerm(t), wglb);
829 return;
830 case (CELL)FunctorString:
831 write_string(UStringOfTerm(t), wglb);
832 return;
833 case (CELL)FunctorDBRef:
834 wrputref(RefOfTerm(t), wglb->Quote_illegal, wglb);
835 return;
836 case (CELL)FunctorLongInt:
837 wrputn(LongIntOfTerm(t), wglb);
838 return;
839 /* case (CELL)FunctorBigInt: */
840 default:
841 writebig(t, p, depth, rinfixarg, wglb);
842 return;
843 }
844 }
845 Arity = ArityOfFunctor(functor);
846 atom = NameOfFunctor(functor);
847#ifdef SFUNC
848 if (Arity == SFArity) {
849 int argno = 1;
850 CELL *p = ArgsOfSFTerm(t);
851 putAtom(atom, wglb->Quote_illegal, wglb);
852 wropen_bracket(wglb, FALSE);
853 lastw = separator;
854 while (*p) {
855 Int sl = 0;
856
857 while (argno < *p) {
858 wrputc('_', wglb->stream), wrputc(',', wglb->stream);
859 ++argno;
860 }
861 *p++;
862 lastw = separator;
863 /* cannot use the term directly with the SBA */
864 PROTECT(t, writeTerm(*p, 999, depth-1, FALSE, wglb));
865 if (*p)
866 wrputc(',', wglb->stream);
867 argno++;
868 }
869 wrclose_bracket(wglb, TRUE);
870 return;
871 }
872#endif
873 if (wglb->Use_portray) {
874 if (callPortray(t, wglb->stream - GLOBAL_Stream PASS_REGS)) {
875 return;
876 }
877 }
878 if (!wglb->Ignore_ops && Arity == 1 && Yap_IsPrefixOp(atom, &op, &rp)) {
879 Term tright = ArgOfTerm(1, t);
880 int bracket_right = !IsVarTerm(tright) && IsAtomTerm(tright) &&
881 Yap_IsOp(AtomOfTerm(tright));
882 if (op > p) {
883 wropen_bracket(wglb, TRUE);
884 }
885 putAtom(atom, wglb->Quote_illegal, wglb);
886 if (bracket_right) {
887 /* avoid stuff such as \+ (a,b) being written as \+(a,b) */
888 wropen_bracket(wglb, TRUE);
889 } else if (atom == AtomMinus) {
890 last_minus = TRUE;
891 }
892 writeTerm(tright, rp, depth-1, TRUE, wglb);
893 if (bracket_right) {
894 wrclose_bracket(wglb, TRUE);
895 }
896 if (op > p) {
897 wrclose_bracket(wglb, TRUE);
898 }
899 } else if (!wglb->Ignore_ops &&
900 (Arity == 1 ||
901 ((atom == AtomEmptyBrackets || atom == AtomCurly ||
902 atom == AtomEmptySquareBrackets) &&
903 Yap_IsListTerm(ArgOfTerm(1, t)))) &&
904 Yap_IsPosfixOp(atom, &op, &lp)) {
905 Term tleft = ArgOfTerm(1, t);
906
907 int bracket_left, offset;
908
909 if (Arity != 1) {
910 tleft = ArgOfTerm(1, t);
911 offset = 2;
912 } else {
913 tleft = ArgOfTerm(1, t);
914 offset = 1;
915 }
916 bracket_left =
917 !IsVarTerm(tleft) && IsAtomTerm(tleft) && Yap_IsOp(AtomOfTerm(tleft));
918 if (op > p) {
919 /* avoid stuff such as \+ (a,b) being written as \+(a,b) */
920 wropen_bracket(wglb, TRUE);
921 }
922 if (bracket_left) {
923 wropen_bracket(wglb, TRUE);
924 }
925 writeTerm(ArgOfTerm(offset, t), lp, depth-1, rinfixarg, wglb);
926 if (bracket_left) {
927 wrclose_bracket(wglb, TRUE);
928 }
929 if (Arity > 1) {
930 if (atom == AtomEmptyBrackets) {
931 wrputc('(', wglb->stream);
932 } else if (atom == AtomEmptySquareBrackets) {
933 wrputc('[', wglb->stream);
934 } else if (atom == AtomCurly) {
935 wrputc('{', wglb->stream);
936 }
937 lastw = separator;
938 write_list(tleft, 0, depth-1, wglb);
939 if (atom == AtomEmptyBrackets) {
940 wrputc(')', wglb->stream);
941 } else if (atom == AtomEmptySquareBrackets) {
942 wrputc(']', wglb->stream);
943 } else if (atom == AtomCurly) {
944 wrputc('}', wglb->stream);
945 }
946 lastw = separator;
947 } else {
948 putAtom(atom, wglb->Quote_illegal, wglb);
949 }
950 if (op > p) {
951 wrclose_bracket(wglb, TRUE);
952 }
953 } else if (!wglb->Ignore_ops && Arity == 2 &&
954 Yap_IsInfixOp(atom, &op, &lp, &rp)) {
955 Term tleft = ArgOfTerm(1, t);
956 Term tright = ArgOfTerm(2, t);
957 int bracket_left =
958 !IsVarTerm(tleft) && IsAtomTerm(tleft) && Yap_IsOp(AtomOfTerm(tleft));
959 int bracket_right = !IsVarTerm(tright) && IsAtomTerm(tright) &&
960 Yap_IsOp(AtomOfTerm(tright));
961
962 if (op > p) {
963 /* avoid stuff such as \+ (a,b) being written as \+(a,b) */
964 wropen_bracket(wglb, TRUE);
965 lastw = separator;
966 }
967 if (bracket_left) {
968 wropen_bracket(wglb, TRUE);
969 }
970 PROTECT(t, writeTerm(ArgOfTerm(1, t), lp, depth-1, rinfixarg, wglb));
971 if (bracket_left) {
972 wrclose_bracket(wglb, TRUE);
973 }
974 /* avoid quoting commas and bars */
975 if (!strcmp((char *)RepAtom(atom)->StrOfAE, ",")) {
976 wrputc(',', wglb->stream);
977 lastw = separator;
978 } else if (!strcmp((char *)RepAtom(atom)->StrOfAE, "|")) {
979 if (lastw == symbol || lastw == separator) {
980 wrputc(' ', wglb->stream);
981 }
982 wrputc('|', wglb->stream);
983 lastw = separator;
984 } else
985 putAtom(atom, wglb->Quote_illegal, wglb);
986 if (bracket_right) {
987 wropen_bracket(wglb, TRUE);
988 }
989 writeTerm(ArgOfTerm(2, t), rp, depth-1, TRUE, wglb);
990 if (bracket_right) {
991 wrclose_bracket(wglb, TRUE);
992 }
993 if (op > p) {
994 wrclose_bracket(wglb, TRUE);
995 }
996 } else if (
997 functor == wglb->FunctorNumberVars &&
998 (wglb->Handle_vars||
999 (wglb->hbase > RepAppl(t) && wglb->Handle_old_vars))){
1000 Term ti = ArgOfTerm(1, t);
1001 if (lastw == alphanum) {
1002 wrputc(' ', wglb->stream);
1003 }
1004 if ( !IsVarTerm(ti) &&
1005 (IsIntTerm(ti) || IsCodesTerm(ti) || IsAtomTerm(ti) ||
1006 IsStringTerm(ti))) {
1007 if (IsIntTerm(ti)) {
1008 Int k = IntOfTerm(ti);
1009 if (k < 0) {
1010 wrputc('S', wglb->stream);
1011 wrputc('_', wglb->stream);
1012 wrputn(-k, wglb);
1013 lastw = separator;
1014 return;
1015 } else {
1016 wrputc((k % 26) + 'A', wglb->stream);
1017 if (k >= 26) {
1018 /* make sure we don't get confused about our context */
1019 lastw = separator;
1020 wrputn(k / 26, wglb);
1021 } else
1022 lastw = alphanum;
1023 }
1024 } else if (IsAtomTerm(ti)) {
1025 putAtom(AtomOfTerm(ti), FALSE, wglb);
1026 } else if (IsStringTerm(ti)) {
1027 putString(ti, wglb);
1028 } else {
1029 putUnquotedString(ti, wglb);
1030 }
1031 } else {
1032 wrputs("'$VAR'(", wglb->stream);
1033 lastw = separator;
1034 writeTerm(ArgOfTerm(1, t), 999, depth-1, FALSE, wglb);
1035 wrclose_bracket(wglb, TRUE);
1036 }
1037 } else if (!wglb->Ignore_ops && functor == FunctorBraces) {
1038 wrputc('{', wglb->stream);
1039 lastw = separator;
1040 writeTerm(ArgOfTerm(1, t), GLOBAL_MaxPriority, depth-1,FALSE, wglb);
1041 wrputc('}', wglb->stream);
1042 lastw = separator;
1043 } else if (atom == AtomArray) {
1044 wrputc('{', wglb->stream);
1045 lastw = separator;
1046 for (op = 1; op <= Arity; ++op) {
1047 if (op == wglb->MaxArgs) {
1048 wrputs("...", wglb->stream);
1049 break;
1050 }
1051 writeTerm(ArgOfTerm(op, t), 999, depth-1, FALSE, wglb);
1052 if (op != Arity) {
1053 PROTECT(t, writeTerm(ArgOfTerm(op, t), 999, depth-1, FALSE, wglb));
1054 wrputc(',', wglb->stream);
1055 lastw = separator;
1056 }
1057 }
1058 writeTerm(ArgOfTerm(op, t), 999, depth-1, FALSE, wglb);
1059 wrputc('}', wglb->stream);
1060 lastw = separator;
1061 } else {
1062 if (!wglb->Ignore_ops && atom == AtomHeapData) {
1063 Arity = 3 + 2 * IntegerOfTerm(ArgOfTerm(1, t));
1064 }
1065 putAtom(atom, wglb->Quote_illegal, wglb);
1066 lastw = separator;
1067 wropen_bracket(wglb, FALSE);
1068 for (op = 1; op < Arity; ++op) {
1069 if (op == wglb->MaxArgs) {
1070 wrputc('.', wglb->stream);
1071 wrputc('.', wglb->stream);
1072 wrputc('.', wglb->stream);
1073 break;
1074 }
1075 PROTECT(t, writeTerm(ArgOfTerm(op, t), 999, depth-1, FALSE, wglb));
1076 wrputc(',', wglb->stream);
1077 lastw = separator;
1078 }
1079 writeTerm(ArgOfTerm(op, t), 999, depth-1, FALSE, wglb);
1080 wrclose_bracket(wglb, TRUE);
1081 }
1082 }
1083}
1084void Yap_plwrite(Term t, StreamDesc *mywrite, int max_depth, CELL * hbase, int flags,
1085 xarg *args)
1086/* term to be written */
1087/* consumer */
1088/* write options */
1089{
1090 CACHE_REGS
1091
1092 yhandle_t lvl = push_text_stack();
1093 int priority = GLOBAL_MaxPriority;
1094 struct write_globs wglb;
1095 Term cm = CurrentModule;
1096 t = Deref(t);
1097
1098 wglb.oldH = HR;
1099 wglb.hbase = (hbase);
1100 if (args && args[WRITE_PRIORITY].used) {
1101 priority = IntegerOfTerm(args[WRITE_PRIORITY].tvalue);
1102 }
1103 if (args && args[WRITE_MODULE].used) {
1104 CurrentModule = args[WRITE_MODULE].tvalue;
1105 }
1106 if (args && args[WRITE_PRIORITY].used) {
1107 priority = IntegerOfTerm(args[WRITE_PRIORITY].tvalue);
1108 }
1109 if (args && args[WRITE_MODULE].used) {
1110 CurrentModule = args[WRITE_MODULE].tvalue;
1111 }
1112 if (args && args[WRITE_NUMBERVARS].used) {
1113 if (IsIntTerm( args[WRITE_NUMBERVARS].tvalue))
1114 flags |= (Handle_vars_f);
1115 }
1116 /* first tell variable names */
1117 if (args && args[WRITE_VARIABLE_NAMES].used) {
1118 flags = args[WRITE_VARIABLE_NAMES].tvalue == TermTrue ? Named_vars_f|flags : Named_vars_f& ~flags ;
1119}
1120 /* and then name theh rest, with special care on singletons */
1121 if (args && args[WRITE_SINGLETONS].used) {
1122 flags = args[WRITE_SINGLETONS].tvalue == TermTrue ? flags | Singleton_vars_f
1123 : flags & ~Singleton_vars_f;
1124}
1125if (args && args[WRITE_CYCLES].used) {
1126 if (args[WRITE_CYCLES].tvalue == TermTrue) {
1127 flags |= Handle_cyclics_f;
1128 }
1129 if (args[WRITE_CYCLES].tvalue == TermFalse) {
1130 flags &= ~Handle_cyclics_f;
1131 }
1132}
1133 t = Deref(t);
1134 wglb.stream = mywrite;
1135 wglb.Ignore_ops = flags & Ignore_ops_f;
1136 wglb.Write_strings = flags & BackQuote_String_f;
1137 wglb.Use_portray = flags & Use_portray_f;
1138 wglb.Handle_old_vars = flags & (Named_vars_f|Singleton_vars_f);
1139 wglb.Handle_vars = flags & (Handle_vars_f);
1140 wglb.Portray_delays = flags & AttVar_Portray_f;
1141 wglb.Keep_terms = flags & To_heap_f;
1142 wglb.Write_Loops = flags & Handle_cyclics_f;
1143 wglb.Quote_illegal = flags & Quote_illegal_f;
1144 wglb.MaxArgs = max_depth*4;
1145 wglb.lw = separator;
1146 wglb.FunctorNumberVars = Yap_MkFunctor(AtomOfTerm( getAtomicLocalPrologFlag(NUMBERVARS_FUNCTOR_FLAG) ),1);
1147
1148 /* protect slots for portray */
1149 writeTerm(t, priority, LOCAL_max_depth-1, false, &wglb);
1150 if (flags & New_Line_f) {
1151 if (flags & Fullstop_f) {
1152 wrputc('.', wglb.stream);
1153 wrputc('\n', wglb.stream);
1154 } else {
1155 wrputc('\n', wglb.stream);
1156 }
1157 } else {
1158 if (flags & Fullstop_f) {
1159 wrputc('.', wglb.stream);
1160 wrputc(' ', wglb.stream);
1161 }
1162 }
1163
1164 CurrentModule = cm;
1165 pop_text_stack(lvl);
1166}
1167
Main definitions.
@ encoding
support for coding systens, YAP relies on UTF-8 internally
Definition: YapLFlagInfo.h:83
Attributed variales are controlled by the attvar_record.
Definition: attvar.h:49
Definition: Yatom.h:544
Definition: YapFlags.h:152