fixes and ~T

This commit is contained in:
Vitor Santos Costa 2016-07-31 10:16:20 -05:00
parent fa26588bbf
commit 57ae30c79c

View File

@ -238,11 +238,16 @@ output is directed to the stream used by format/2.
#include "Yatom.h" #include "Yatom.h"
#include "yapio.h" #include "yapio.h"
#include <stdlib.h> #include <stdlib.h>
#if HAVE_UNISTD_H #if HAVE_UNISTD_H
#include <unistd.h> #include <unistd.h>
#endif #endif
#if HAVE_STDARG_H #if HAVE_STDARG_H
#include <stdarg.h> #include <stdarg.h>
#endif #endif
#ifdef _WIN32 #ifdef _WIN32
#if HAVE_IO_H #if HAVE_IO_H
@ -257,19 +262,21 @@ output is directed to the stream used by format/2.
#define S_ISDIR(x) (((x)&_S_IFDIR) == _S_IFDIR) #define S_ISDIR(x) (((x)&_S_IFDIR) == _S_IFDIR)
#endif #endif
#endif #endif
#include "eval.h" #include "eval.h"
#include "iopreds.h" #include "iopreds.h"
#define FORMAT_MAX_SIZE 1024 #define FORMAT_MAX_SIZE 1024
typedef struct { typedef struct {
Int filler; /* character to dump */ Int filler;
int phys; /* position in buffer */ /* character to dump */
int phys;
/* position in buffer */
int log; /* columnn as wide chsh */ int log; /* columnn as wide chsh */
} gap_t; } gap_t;
typedef struct format_status { typedef struct format_status {
int format_error;
gap_t gap[16]; gap_t gap[16];
// number of octets // number of octets
int phys_start; int phys_start;
@ -278,35 +285,43 @@ typedef struct format_status {
int gapi; int gapi;
} format_info; } format_info;
static bool format_synch(int sno, int sno0, format_info *fg ) { static bool format_synch(int sno, int sno0, format_info *fg) {
int (*f_putc)(int, int); int (*f_putc)(int, int);
const char *s; const char *s;
int n; int n;
if (sno == sno0) {
#if MAY_WRITE
fflush(GLOBAL_Stream[sno].file);
#endif
return true;
}
f_putc = GLOBAL_Stream[sno0].stream_putc; f_putc = GLOBAL_Stream[sno0].stream_putc;
#if MAY_WRITE #if MAY_WRITE
if (fflush(GLOBAL_Stream[sno].file) == 0) { if (fflush(GLOBAL_Stream[sno].file) == 0) {
s = GLOBAL_Stream[sno].nbuf; s = GLOBAL_Stream[sno].nbuf;
n = ftell(GLOBAL_Stream[sno].file); n = ftell(GLOBAL_Stream[sno].file);
fwrite(s, n, 1, GLOBAL_Stream[sno0].file);
rewind(GLOBAL_Stream[sno].file);
fflush(GLOBAL_Stream[sno0].file);
} else } else
return false; return false;
#else #else
s = GLOBAL_Stream[sno].u.mem_string.buf; s = GLOBAL_Stream[sno].u.mem_string.buf;
n = GLOBAL_Stream[sno].u.mem_string.pos; n = GLOBAL_Stream[sno].u.mem_string.pos;
#endif #endif
while (n--)
f_putc(sno0, *s++);
#if MAY_WRITE #if MAY_WRITE
rewind(GLOBAL_Stream[sno].file);
#else #else
while (n--) {
f_putc(sno0, *s++);
}
GLOBAL_Stream[sno].u.mem_string.pos = 0; GLOBAL_Stream[sno].u.mem_string.pos = 0;
#endif #endif
GLOBAL_Stream[sno].linecount = 1; GLOBAL_Stream[sno].linecount = 1;
GLOBAL_Stream[sno].linepos = 0; GLOBAL_Stream[sno].linepos = 0;
GLOBAL_Stream[sno].charcount = 0; GLOBAL_Stream[sno].charcount = 0;
fg->lstart = 0; fg->lstart = 0;
fg->phys_start=0; fg->phys_start = 0;
fg->gapi=0; fg->gapi = 0;
return true; return true;
} }
@ -345,36 +360,36 @@ static bool fill_pads(int sno, int sno0, int total, format_info *fg USES_REGS) {
while (i < phys_end) { while (i < phys_end) {
if (i == padi->phys) { if (i == padi->phys) {
int j; int j;
for (j=0; j < fill_space; j++) for (j = 0; j < fill_space; j++)
f_putc(sno0, padi->filler); f_putc(sno0, padi->filler);
padi++; padi++;
/* last gap??*/ /* last gap??*/
if (padi-fg->gap == fg->gapi) { if (padi - fg->gap == fg->gapi) {
for (j=0; j < fill_space; j++) for (j = 0; j < fill_space; j++)
f_putc(sno0, (padi-1)->filler); f_putc(sno0, (padi - 1)->filler);
} }
} }
f_putc(sno0,buf[i++]); f_putc(sno0, buf[i++]);
} }
// final gap // final gap
if (i == padi->phys) { if (i == padi->phys) {
int j; int j;
for (j=0; j < fill_space+lfill_space; j++) for (j = 0; j < fill_space + lfill_space; j++)
f_putc(sno0, padi->filler); f_putc(sno0, padi->filler);
}; };
#if MAY_WRITE #if MAY_WRITE
rewind(GLOBAL_Stream[sno].file); rewind(GLOBAL_Stream[sno].file);
fflush(GLOBAL_Stream[sno0].file);
#else #else
GLOBAL_Stream[sno].u.mem_string.pos = 0; GLOBAL_Stream[sno].u.mem_string.pos = 0;
#endif #endif
GLOBAL_Stream[sno].linecount = 1; GLOBAL_Stream[sno].linecount = 1;
GLOBAL_Stream[sno].linepos += nchars; GLOBAL_Stream[sno].linepos += nchars;
GLOBAL_Stream[sno].charcount = 0; GLOBAL_Stream[sno].charcount = 0;
fg->phys_start=0; fg->phys_start = 0;
fg->lstart = GLOBAL_Stream[sno].linepos; fg->lstart = GLOBAL_Stream[sno].linepos;
fg->gapi=0; fg->gapi = 0;
return true; return true;
} }
@ -385,8 +400,7 @@ static int format_print_str(Int sno, Int size, Int has_size, Term args,
const unsigned char *pt = UStringOfTerm(args); const unsigned char *pt = UStringOfTerm(args);
while (*pt && (!has_size || size > 0)) { while (*pt && (!has_size || size > 0)) {
utf8proc_int32_t ch; utf8proc_int32_t ch;
pt += get_utf8((unsigned char *)pt, -1, &ch); pt += get_utf8(pt, -1, &ch);
f_putc(sno, ch);
} }
} else { } else {
while (!has_size || size > 0) { while (!has_size || size > 0) {
@ -415,48 +429,6 @@ static int format_print_str(Int sno, Int size, Int has_size, Term args,
return TRUE; return TRUE;
} }
typedef enum { fst_ok, fst_error, fst_too_long } format_cp_res;
static format_cp_res copy_format_string(Term inp, char *out, int max) {
int i = 0;
while (inp != TermNil) {
Term hd;
int ch;
if (IsVarTerm(inp)) {
Yap_Error(INSTANTIATION_ERROR, inp, "format/2");
return fst_error;
}
if (!IsPairTerm(inp)) {
Yap_Error(TYPE_ERROR_LIST, inp, "format/2");
return fst_error;
}
hd = HeadOfTerm(inp);
if (IsVarTerm(hd)) {
Yap_Error(INSTANTIATION_ERROR, hd, "format/2");
return fst_error;
}
if (!IsIntTerm(hd)) {
Yap_Error(TYPE_ERROR_INTEGER, hd, "format/2");
return fst_error;
}
ch = IntOfTerm(hd);
if (ch < 0) {
Yap_Error(DOMAIN_ERROR_NOT_LESS_THAN_ZERO, hd, "format/2");
return fst_error;
}
if (i + 1 == max) {
return fst_too_long;
}
/* we've got a character */
out[i++] = ch;
/* done */
inp = TailOfTerm(inp);
}
out[i] = '\0';
return fst_ok;
}
#define FORMAT_COPY_ARGS_ERROR -1 #define FORMAT_COPY_ARGS_ERROR -1
#define FORMAT_COPY_ARGS_OVERFLOW -2 #define FORMAT_COPY_ARGS_OVERFLOW -2
@ -482,13 +454,14 @@ static Int format_copy_args(Term args, Term *targs, Int tsz) {
static void static void
format_clean_up(int sno, int sno0, format_info *finf, const char *fstr, const Term *targs) { format_clean_up(int sno, int sno0, format_info *finf, const unsigned char *fstr,
if (sno > 0) { const Term *targs) {
format_synch( sno, sno0, finf); if (sno != sno0) {
format_synch(sno, sno0, finf);
Yap_CloseStream(sno); Yap_CloseStream(sno);
} }
if (fstr) { if (fstr) {
Yap_FreeAtomSpace((void *)fstr); free((void *)fstr);
} }
if (targs) if (targs)
Yap_FreeAtomSpace((void *)targs); Yap_FreeAtomSpace((void *)targs);
@ -524,7 +497,7 @@ static Int doformat(volatile Term otail, volatile Term oargs,
int ch; int ch;
Term mytargs[8], *targs; Term mytargs[8], *targs;
Int tnum, targ; Int tnum, targ;
const char *fstr = NULL, *fptr; const unsigned char *fstr, *fptr;
Term args; Term args;
Term tail; Term tail;
int (*f_putc)(int, wchar_t); int (*f_putc)(int, wchar_t);
@ -536,8 +509,6 @@ static Int doformat(volatile Term otail, volatile Term oargs,
Term fmod = CurrentModule; Term fmod = CurrentModule;
bool alloc_fstr = false; bool alloc_fstr = false;
finfo.format_error = FALSE;
if (GLOBAL_Stream[sno0].status & InMemory_Stream_f) { if (GLOBAL_Stream[sno0].status & InMemory_Stream_f) {
old_handler = GLOBAL_Stream[sno].u.mem_string.error_handler; old_handler = GLOBAL_Stream[sno].u.mem_string.error_handler;
GLOBAL_Stream[sno].u.mem_string.error_handler = (void *)&format_botch; GLOBAL_Stream[sno].u.mem_string.error_handler = (void *)&format_botch;
@ -565,31 +536,11 @@ static Int doformat(volatile Term otail, volatile Term oargs,
if (IsVarTerm(tail)) { if (IsVarTerm(tail)) {
Yap_Error(INSTANTIATION_ERROR, tail, "format/2"); Yap_Error(INSTANTIATION_ERROR, tail, "format/2");
return (FALSE); return (FALSE);
} else if (IsPairTerm(tail)) { } else if ((fptr = Yap_TextToUTF8Buffer(tail))) {
int sz = 256; fstr = fptr;
do {
format_cp_res fr;
char *fstr0;
fstr = fptr = fstr0 = Yap_AllocAtomSpace(sz * sizeof(char));
if ((fr = copy_format_string(tail, fstr0, sz)) == fst_ok)
break;
if (fr == fst_error) {
Yap_FreeCodeSpace(fstr0);
fstr = NULL;
return false;
}
sz += 256;
Yap_FreeCodeSpace(fstr0);
fstr = NULL;
} while (TRUE);
alloc_fstr = true; alloc_fstr = true;
} else if (IsAtomTerm(tail)) {
fstr = fptr = RepAtom(AtomOfTerm(tail))->StrOfAE;
} else if (IsStringTerm(tail)) {
fstr = fptr = StringOfTerm(tail);
} else { } else {
Yap_Error(SYSTEM_ERROR_SAVED_STATE, tail, "format/2"); Yap_Error(TYPE_ERROR_TEXT, tail, "format/2");
return false; return false;
} }
if (IsVarTerm(args)) { if (IsVarTerm(args)) {
@ -640,59 +591,57 @@ static Int doformat(volatile Term otail, volatile Term oargs,
} }
// it starts here // it starts here
finfo.format_error = false;
finfo.gapi = 0;
sno0 = sno;
finfo.format_error = false;
finfo.gapi = 0; finfo.gapi = 0;
finfo.phys_start = 0; finfo.phys_start = 0;
finfo.lstart = 0; finfo.lstart = 0;
f_putc = GLOBAL_Stream[sno].stream_wputc; if (true || !(GLOBAL_Stream[sno].status & InMemory_Stream_f))
sno = Yap_OpenBufWriteStream(PASS_REGS1); sno = Yap_OpenBufWriteStream(PASS_REGS1);
f_putc = GLOBAL_Stream[sno0].stream_wputc;
if (sno == -1) { if (sno == -1) {
if (!alloc_fstr) if (!alloc_fstr)
fstr = NULL; fstr = NULL;
if (mytargs == targs) { if (mytargs == targs) {
targs = NULL; targs = NULL;
} }
format_clean_up(sno, sno0, &finfo, (char *)fstr, targs); format_clean_up(sno, sno0, &finfo, fstr, targs);
return false; return false;
} }
while ((ch = *fptr++)) { while ((fptr += get_utf8(fptr, -1, &ch)) && ch) {
Term t = TermNil; Term t = TermNil;
int has_repeats = false; int has_repeats = false;
int repeats = 0; int repeats = 0;
if (ch == '~') { if (ch == '~') {
/* start command */ /* start command */
ch = *fptr++; fptr += get_utf8(fptr, -1, &ch);
if (ch == '*') { if (ch == '*') {
ch = *fptr++; fptr += get_utf8(fptr, -1, &ch);
has_repeats = TRUE; has_repeats = TRUE;
if (targ > tnum - 1) { if (targ > tnum - 1) {
goto do_consistency_error; goto do_format_control_sequence_error;
} }
repeats = fetch_index_from_args(targs[targ++]); repeats = fetch_index_from_args(targs[targ++]);
if (repeats == -1) if (repeats == -1)
goto do_consistency_error; goto do_format_control_sequence_error;
} else if (ch == '`') { } else if (ch == '`') {
/* next character is kept as code */ /* next character is kept as code */
has_repeats = TRUE; has_repeats = TRUE;
repeats = *fptr++; fptr += get_utf8(fptr, -1, &repeats);
ch = *fptr++; fptr += get_utf8(fptr, -1, &ch);
} else if (ch >= '0' && ch <= '9') { } else if (ch >= '0' && ch <= '9') {
has_repeats = TRUE; has_repeats = TRUE;
repeats = 0; repeats = 0;
while (ch >= '0' && ch <= '9') { while (ch >= '0' && ch <= '9') {
repeats = repeats * 10 + (ch - '0'); repeats = repeats * 10 + (ch - '0');
ch = *fptr++; fptr += get_utf8(fptr, -1, &ch);
} }
} }
switch (ch) { switch (ch) {
case 'a': case 'a':
/* print an atom */ /* print an atom */
if (has_repeats || targ > tnum - 1) if (has_repeats || targ > tnum - 1)
goto do_consistency_error; goto do_format_control_sequence_error;
t = targs[targ++]; t = targs[targ++];
if (IsVarTerm(t)) if (IsVarTerm(t))
goto do_instantiation_error; goto do_instantiation_error;
@ -708,7 +657,7 @@ static Int doformat(volatile Term otail, volatile Term oargs,
Int nch, i; Int nch, i;
if (targ > tnum - 1) if (targ > tnum - 1)
goto do_consistency_error; goto do_format_control_sequence_error;
t = targs[targ++]; t = targs[targ++];
if (IsVarTerm(t)) if (IsVarTerm(t))
goto do_instantiation_error; goto do_instantiation_error;
@ -732,7 +681,7 @@ static Int doformat(volatile Term otail, volatile Term oargs,
char *ptr; char *ptr;
if (targ > tnum - 1) if (targ > tnum - 1)
goto do_consistency_error; goto do_format_control_sequence_error;
t = targs[targ++]; t = targs[targ++];
if (IsVarTerm(t)) if (IsVarTerm(t))
goto do_instantiation_error; goto do_instantiation_error;
@ -772,7 +721,7 @@ static Int doformat(volatile Term otail, volatile Term oargs,
sprintf(tmp2, tmp1, fl); sprintf(tmp2, tmp1, fl);
#endif #endif
ptr = tmp2; ptr = tmp2;
while ((ch = *ptr++) != 0) while ((fptr += get_utf8(fptr, -1, &ch)) && ch != 0)
f_putc(sno, ch); f_putc(sno, ch);
Yap_FreeCodeSpace(tmp2); Yap_FreeCodeSpace(tmp2);
} }
@ -781,7 +730,7 @@ static Int doformat(volatile Term otail, volatile Term oargs,
case 'D': case 'D':
/* print a decimal, using weird . stuff */ /* print a decimal, using weird . stuff */
if (targ > tnum - 1) if (targ > tnum - 1)
goto do_consistency_error; goto do_format_control_sequence_error;
t = targs[targ++]; t = targs[targ++];
if (IsVarTerm(t)) if (IsVarTerm(t))
goto do_instantiation_error; goto do_instantiation_error;
@ -878,7 +827,7 @@ static Int doformat(volatile Term otail, volatile Term oargs,
/* print a decimal, using weird . stuff */ /* print a decimal, using weird . stuff */
if (targ > tnum - 1) if (targ > tnum - 1)
goto do_consistency_error; goto do_format_control_sequence_error;
t = targs[targ++]; t = targs[targ++];
if (IsVarTerm(t)) if (IsVarTerm(t))
goto do_instantiation_error; goto do_instantiation_error;
@ -935,7 +884,7 @@ static Int doformat(volatile Term otail, volatile Term oargs,
} }
case 's': case 's':
if (targ > tnum - 1) if (targ > tnum - 1)
goto do_consistency_error; goto do_format_control_sequence_error;
t = targs[targ++]; t = targs[targ++];
if (IsVarTerm(t)) if (IsVarTerm(t))
goto do_instantiation_error; goto do_instantiation_error;
@ -945,12 +894,12 @@ static Int doformat(volatile Term otail, volatile Term oargs,
break; break;
case 'i': case 'i':
if (targ > tnum - 1 || has_repeats) if (targ > tnum - 1 || has_repeats)
goto do_consistency_error; goto do_format_control_sequence_error;
targ++; targ++;
break; break;
case 'k': case 'k':
if (targ > tnum - 1 || has_repeats) if (targ > tnum - 1 || has_repeats)
goto do_consistency_error; goto do_format_control_sequence_error;
t = targs[targ++]; t = targs[targ++];
yhandle_t sl = Yap_StartSlots(); yhandle_t sl = Yap_StartSlots();
Yap_plwrite(t, GLOBAL_Stream + sno, 0, Yap_plwrite(t, GLOBAL_Stream + sno, 0,
@ -961,21 +910,14 @@ static Int doformat(volatile Term otail, volatile Term oargs,
case '@': case '@':
t = targs[targ++]; t = targs[targ++];
{ {
yhandle_t sl0 = Yap_StartSlots(); yhandle_t sl0 = Yap_StartSlots(), s1 = Yap_PushHandle(ARG1),
Int sl = Yap_InitSlot(args); sl = Yap_InitSlots(tnum - targ, targs + targ);
Int sl2;
Int res;
Term ta[2];
Term ts;
ta[0] = fmod; Int res;
ta[1] = t; int os = LOCAL_c_output_stream;
ta[0] = Yap_MkApplTerm(FunctorModule, 2, ta); LOCAL_c_output_stream = sno;
ta[1] = MkVarTerm(); res = Yap_execute_goal(t, 0, fmod, true);
sl2 = Yap_InitSlot(ta[1]); LOCAL_c_output_stream = os;
ts = Yap_MkApplTerm(FunctorGFormatAt, 2, ta);
res = Yap_execute_goal(ts, 0, CurrentModule, true);
args = Yap_GetFromSlot(sl);
if (Yap_HasException()) if (Yap_HasException())
goto ex_handler; goto ex_handler;
if (!res) { if (!res) {
@ -984,19 +926,17 @@ static Int doformat(volatile Term otail, volatile Term oargs,
if (mytargs == targs) { if (mytargs == targs) {
targs = NULL; targs = NULL;
} }
format_clean_up(sno, sno0, &finfo, (char *)fstr, targs); format_clean_up(sno, sno0, &finfo, fstr, targs);
return FALSE; return false;
} }
ts = Yap_GetFromSlot(sl2); ARG1 = Yap_GetFromHandle(s1);
Yap_RecoverHandles(sl, tnum - targ);
Yap_CloseSlots(sl0); Yap_CloseSlots(sl0);
if (!format_print_str(sno, repeats, has_repeats, ts, f_putc)) {
goto do_default_error;
}
} }
break; break;
case 'p': case 'p':
if (targ > tnum - 1 || has_repeats) if (targ > tnum - 1 || has_repeats)
goto do_consistency_error; goto do_format_control_sequence_error;
t = targs[targ++]; t = targs[targ++];
{ {
Int sl = Yap_InitSlot(args); Int sl = Yap_InitSlot(args);
@ -1022,14 +962,14 @@ static Int doformat(volatile Term otail, volatile Term oargs,
if (mytargs == targs) { if (mytargs == targs) {
targs = NULL; targs = NULL;
} }
format_clean_up(sno, sno0, &finfo, (char *)fstr, targs); format_clean_up(sno, sno0, &finfo, fstr, targs);
Yap_RaiseException(); Yap_RaiseException();
return false; return false;
} }
break; break;
case 'q': case 'q':
if (targ > tnum - 1 || has_repeats) if (targ > tnum - 1 || has_repeats)
goto do_consistency_error; goto do_format_control_sequence_error;
t = targs[targ++]; t = targs[targ++];
yhandle_t sl0 = Yap_StartSlots(); yhandle_t sl0 = Yap_StartSlots();
Yap_plwrite(t, GLOBAL_Stream + sno, 0, Yap_plwrite(t, GLOBAL_Stream + sno, 0,
@ -1039,16 +979,30 @@ static Int doformat(volatile Term otail, volatile Term oargs,
break; break;
case 'w': case 'w':
if (targ > tnum - 1 || has_repeats) if (targ > tnum - 1 || has_repeats)
goto do_consistency_error; goto do_format_control_sequence_error;
t = targs[targ++]; t = targs[targ++];
yhandle_t slf = Yap_StartSlots(); yhandle_t slf = Yap_StartSlots();
Yap_plwrite(t, GLOBAL_Stream + sno, 0, Handle_vars_f | To_heap_f, Yap_plwrite(t, GLOBAL_Stream + sno, 0,
Handle_vars_f | To_heap_f,
GLOBAL_MaxPriority); GLOBAL_MaxPriority);
Yap_CloseSlots(slf); Yap_CloseSlots(slf);
break; break;
case 'W':
if (targ > tnum - 2 || has_repeats)
goto do_format_control_sequence_error;
targ -= 2;
{
yhandle_t slf = Yap_StartSlots();
if (!Yap_WriteTerm( sno, targs[1], targs[0] PASS_REGS)) {
Yap_CloseSlots(slf);
goto do_default_error;
};
Yap_CloseSlots(slf);
}
break;
case '~': case '~':
if (has_repeats) if (has_repeats)
goto do_consistency_error; goto do_format_control_sequence_error;
f_putc(sno, (int)'~'); f_putc(sno, (int)'~');
break; break;
case 'n': case 'n':
@ -1057,38 +1011,36 @@ static Int doformat(volatile Term otail, volatile Term oargs,
while (repeats--) { while (repeats--) {
f_putc(sno, (int)'\n'); f_putc(sno, (int)'\n');
} }
format_synch( sno, sno0, &finfo); format_synch(sno, sno0, &finfo);
break; break;
case 'N': case 'N':
if (!has_repeats) if (!has_repeats)
has_repeats = 1; has_repeats = 1;
if (GLOBAL_Stream[sno].linepos != 0) { if (GLOBAL_Stream[sno].linepos != 0) {
f_putc(sno, '\n'); f_putc(sno, '\n');
format_synch( sno, sno0, &finfo); format_synch(sno, sno0, &finfo);
} }
if (repeats > 1) { if (repeats > 1) {
Int i; Int i;
for (i = 1; i < repeats; i++) for (i = 1; i < repeats; i++)
f_putc(sno, '\n'); f_putc(sno, '\n');
} }
format_synch( sno, sno0, &finfo); format_synch(sno, sno0, &finfo);
break; break;
/* padding */ /* padding */
case '|': case '|':
fill_pads(sno, sno0, repeats, &finfo PASS_REGS); fill_pads(sno, sno0, repeats, &finfo PASS_REGS);
break; break;
case '+': case '+':
fill_pads(sno, sno0, finfo.lstart+repeats, &finfo PASS_REGS); fill_pads(sno, sno0, finfo.lstart + repeats, &finfo PASS_REGS);
break; break;
case 't': { case 't': {
#if MAY_WRITE #if MAY_WRITE
if (fflush(GLOBAL_Stream[sno].file) == 0) { if (fflush(GLOBAL_Stream[sno].file) == 0) {
finfo.gap[finfo.gapi].phys = finfo.gap[finfo.gapi].phys = ftell(GLOBAL_Stream[sno].file);
ftell(GLOBAL_Stream[sno].file);
} }
#else #else
finfo.gap[finfo.gapi].phys = finfo.gap[finfo.gapi].phys = GLOBAL_Stream[sno].u.mem_string.pos;
GLOBAL_Stream[sno].u.mem_string.pos;
#endif #endif
finfo.gap[finfo.gapi].log = GLOBAL_Stream[sno].linepos; finfo.gap[finfo.gapi].log = GLOBAL_Stream[sno].linepos;
if (has_repeats) if (has_repeats)
@ -1096,9 +1048,7 @@ static Int doformat(volatile Term otail, volatile Term oargs,
else else
finfo.gap[finfo.gapi].filler = ' '; finfo.gap[finfo.gapi].filler = ' ';
finfo.gapi++; finfo.gapi++;
} } break;
break;
do_instantiation_error: do_instantiation_error:
LOCAL_Error_TYPE = INSTANTIATION_ERROR; LOCAL_Error_TYPE = INSTANTIATION_ERROR;
@ -1118,9 +1068,10 @@ static Int doformat(volatile Term otail, volatile Term oargs,
do_domain_error_radix: do_domain_error_radix:
LOCAL_Error_TYPE = DOMAIN_ERROR_RADIX; LOCAL_Error_TYPE = DOMAIN_ERROR_RADIX;
goto do_default_error; goto do_default_error;
do_consistency_error: do_format_control_sequence_error:
LOCAL_Error_TYPE = DOMAIN_ERROR_FORMAT_CONTROL_SEQUENCE;
default: default:
LOCAL_Error_TYPE = SYSTEM_ERROR_SAVED_STATE; LOCAL_Error_TYPE = YAP_NO_ERROR;
do_default_error: do_default_error:
if (tnum <= 8) if (tnum <= 8)
targs = NULL; targs = NULL;
@ -1133,7 +1084,7 @@ static Int doformat(volatile Term otail, volatile Term oargs,
ta[1] = oargs; ta[1] = oargs;
Yap_Error(LOCAL_Error_TYPE, Yap_Error(LOCAL_Error_TYPE,
Yap_MkApplTerm(Yap_MkFunctor(AtomFormat, 2), 2, ta), Yap_MkApplTerm(Yap_MkFunctor(AtomFormat, 2), 2, ta),
"format/2"); "arguments to format");
} }
if (GLOBAL_Stream[sno].status & InMemory_Stream_f) { if (GLOBAL_Stream[sno].status & InMemory_Stream_f) {
GLOBAL_Stream[sno].u.mem_string.error_handler = old_handler; GLOBAL_Stream[sno].u.mem_string.error_handler = old_handler;
@ -1152,7 +1103,7 @@ static Int doformat(volatile Term otail, volatile Term oargs,
} }
} else { } else {
if (ch == '\n') { if (ch == '\n') {
format_synch( sno, sno0, &finfo); format_synch(sno, sno0, &finfo);
} }
f_putc(sno, ch); f_putc(sno, ch);
} }
@ -1175,6 +1126,27 @@ static Int doformat(volatile Term otail, volatile Term oargs,
return (TRUE); return (TRUE);
} }
static Term memStreamToTerm(int output_stream, Functor f, Term inp) {
const char *s = Yap_MemExportStreamPtr(output_stream);
encoding_t enc = GLOBAL_Stream[output_stream].encoding;
if (f == FunctorAtom) {
return MkAtomTerm(Yap_LookupAtom(s));
} else if (f == FunctorCodes) {
return Yap_CharsToDiffListOfCodes(s, ArgOfTerm(2, inp), enc PASS_REGS);
} else if (f == FunctorCodes1) {
return Yap_CharsToListOfCodes(s, enc PASS_REGS);
} else if (f == FunctorChars) {
return Yap_CharsToDiffListOfAtoms(s, ArgOfTerm(2, inp), enc PASS_REGS);
} else if (f == FunctorChars1) {
return Yap_CharsToListOfAtoms(s, enc PASS_REGS);
} else if (f == FunctorString1) {
return Yap_CharsToString(s, enc PASS_REGS);
}
Yap_Error(DOMAIN_ERROR_FORMAT_OUTPUT, inp, NULL);
return 0L;
}
/** /**
* @pred with_output_to(+ _Ouput_,: _Goal_) * @pred with_output_to(+ _Ouput_,: _Goal_)
@ -1229,6 +1201,7 @@ static Int with_output_to(USES_REGS1) {
Functor f; Functor f;
bool out; bool out;
bool mem_stream = false; bool mem_stream = false;
yhandle_t hdl = Yap_PushHandle(tin);
if (IsVarTerm(tin)) { if (IsVarTerm(tin)) {
Yap_Error(INSTANTIATION_ERROR, tin, "with_output_to/3"); Yap_Error(INSTANTIATION_ERROR, tin, "with_output_to/3");
return false; return false;
@ -1237,6 +1210,7 @@ static Int with_output_to(USES_REGS1) {
(f == FunctorAtom || f == FunctorString || f == FunctorCodes1 || (f == FunctorAtom || f == FunctorString || f == FunctorCodes1 ||
f == FunctorCodes || f == FunctorChars1 || f == FunctorChars)) { f == FunctorCodes || f == FunctorChars1 || f == FunctorChars)) {
output_stream = Yap_OpenBufWriteStream(PASS_REGS1); output_stream = Yap_OpenBufWriteStream(PASS_REGS1);
mem_stream = true;
} else { } else {
/* needs to change LOCAL_c_output_stream for write */ /* needs to change LOCAL_c_output_stream for write */
output_stream = Yap_CheckStream(ARG1, Output_Stream_f, "format/3"); output_stream = Yap_CheckStream(ARG1, Output_Stream_f, "format/3");
@ -1250,42 +1224,27 @@ static Int with_output_to(USES_REGS1) {
LOCAL_c_output_stream = old_out; LOCAL_c_output_stream = old_out;
if (mem_stream) { if (mem_stream) {
Term tat; Term tat;
Term inp = Deref(ARG1); Term inp = Yap_GetFromHandle(hdl);
if (out) { if (out) {
char *s = GLOBAL_Stream[output_stream].nbuf; tat = memStreamToTerm(output_stream, f, inp);
encoding_t enc = GLOBAL_Stream[output_stream].encoding;
s[GLOBAL_Stream[output_stream].nsize] = '\0';
if (f == FunctorAtom) {
tat = MkAtomTerm(Yap_LookupAtom(s));
} else if (f == FunctorCodes) {
tat = Yap_CharsToDiffListOfCodes(s, ArgOfTerm(2, inp), enc PASS_REGS);
} else if (f == FunctorCodes1) {
tat = Yap_CharsToListOfCodes(s, enc PASS_REGS);
} else if (f == FunctorChars) {
tat = Yap_CharsToDiffListOfAtoms(s, ArgOfTerm(2, inp), enc PASS_REGS);
} else if (f == FunctorChars1) {
tat = Yap_CharsToListOfAtoms(s, enc PASS_REGS);
} else if (f == FunctorString1) {
tat = Yap_CharsToString(s, enc PASS_REGS);
} else {
return false;
}
out = Yap_unify(tat, ArgOfTerm(1, inp)); out = Yap_unify(tat, ArgOfTerm(1, inp));
} }
Yap_CloseStream(output_stream);
} }
return out; return out;
} }
static Int format(Term tout, Term tf, Term tas USES_REGS) { static Int format(Term tf, Term tas, Term tout USES_REGS) {
bool mem_stream = false;
int output_stream;
Functor f;
Int out; Int out;
Functor f;
int output_stream;
bool mem_stream = false;
if (IsVarTerm(tout)) { if (IsVarTerm(tout)) {
Yap_Error(INSTANTIATION_ERROR, tout, "format/3"); Yap_Error(INSTANTIATION_ERROR, tout, "format/3");
return false; return false;
} }
yhandle_t hl = Yap_StartHandles(), yo = Yap_PushHandle(tout);
if (IsApplTerm(tout) && (f = FunctorOfTerm(tout)) && if (IsApplTerm(tout) && (f = FunctorOfTerm(tout)) &&
(f == FunctorAtom || f == FunctorString1 || f == FunctorCodes1 || (f == FunctorAtom || f == FunctorString1 || f == FunctorCodes1 ||
f == FunctorCodes || f == FunctorChars1 || f == FunctorChars)) { f == FunctorCodes || f == FunctorChars1 || f == FunctorChars)) {
@ -1296,43 +1255,27 @@ static Int format(Term tout, Term tf, Term tas USES_REGS) {
output_stream = Yap_CheckStream(tout, Output_Stream_f, "format/3"); output_stream = Yap_CheckStream(tout, Output_Stream_f, "format/3");
} }
if (output_stream == -1) { if (output_stream == -1) {
return false;
UNLOCK(GLOBAL_Stream[output_stream].streamlock); UNLOCK(GLOBAL_Stream[output_stream].streamlock);
return false;
} else { } else {
yhandle_t sls = Yap_CurrentSlot();
out = doformat(tf, tas, output_stream PASS_REGS); out = doformat(tf, tas, output_stream PASS_REGS);
Yap_CloseSlots(sls);
UNLOCK(GLOBAL_Stream[output_stream].streamlock); UNLOCK(GLOBAL_Stream[output_stream].streamlock);
}
if (mem_stream) { if (mem_stream) {
Term tat;
Term inp = Deref(ARG1);
if (out) { if (out) {
char *s = GLOBAL_Stream[output_stream].nbuf; Term to = Yap_GetFromHandle(yo);
encoding_t enc = GLOBAL_Stream[output_stream].encoding; Term tat = memStreamToTerm(output_stream, f, to);
s[GLOBAL_Stream[output_stream].nsize] = '\0'; if (tat == 0)
if (f == FunctorAtom) {
tat = MkAtomTerm(Yap_LookupAtom(s));
} else if (f == FunctorCodes) {
tat = Yap_CharsToDiffListOfCodes(s, ArgOfTerm(2, inp), enc PASS_REGS);
} else if (f == FunctorCodes1) {
tat = Yap_CharsToListOfCodes(s, enc PASS_REGS);
} else if (f == FunctorChars) {
tat = Yap_CharsToDiffListOfAtoms(s, ArgOfTerm(2, inp), enc PASS_REGS);
} else if (f == FunctorChars1) {
tat = Yap_CharsToListOfAtoms(s, enc PASS_REGS);
} else if (f == FunctorString1) {
tat = Yap_CharsToString(s, enc PASS_REGS);
} else {
return false; return false;
out = Yap_unify(tat, ArgOfTerm(1, to));
} }
if (!Yap_unify(tat, ArgOfTerm(1, inp)))
return FALSE;
}
Yap_CloseStream(output_stream); Yap_CloseStream(output_stream);
} }
}
Yap_CloseHandles(hl);
return out; return out;
} }
@ -1353,7 +1296,7 @@ static Int format2(USES_REGS1) { /* 'format'(Stream,Control,Args) */
*/ */
static Int format3(USES_REGS1) { static Int format3(USES_REGS1) {
Int res; Int res;
res = format(Deref(ARG1), Deref(ARG2), Deref(ARG3) PASS_REGS); res = format(Deref(ARG2), Deref(ARG3), Deref(ARG1) PASS_REGS);
return res; return res;
} }