diff --git a/C/c_interface.c b/C/c_interface.c index 031258335..68ac337a9 100755 --- a/C/c_interface.c +++ b/C/c_interface.c @@ -2153,6 +2153,7 @@ X_API Term YAP_Read(FILE *f) { return o; } + X_API Term YAP_ReadFromStream(int sno) { Term o; @@ -2162,6 +2163,15 @@ X_API Term YAP_ReadFromStream(int sno) { return o; } +X_API Term YAP_ReadClauseFromStream(int sno) { + Term o; + + BACKUP_MACHINE_REGS(); + o = Yap_read_term(sno, TermNil, -1); + RECOVER_MACHINE_REGS(); + return o; +} + X_API void YAP_Write(Term t, FILE *f, int flags) { BACKUP_MACHINE_REGS(); int sno = Yap_OpenStream(f, NULL, TermNil, Output_Stream_f); @@ -2271,7 +2281,7 @@ static void do_bootfile(char *bootfilename USES_REGS) { CACHE_REGS YAP_Reset(YAP_FULL_RESET); Yap_StartSlots(); - t = YAP_ReadFromStream(bootfile); + t = YAP_ReadClauseFromStream(bootfile); // Yap_DebugPlWrite(t);fprintf(stderr, "\n"); if (t == 0) { fprintf(stderr, diff --git a/include/YapInterface.h b/include/YapInterface.h index 12de0bebf..92fb31d92 100755 --- a/include/YapInterface.h +++ b/include/YapInterface.h @@ -1866,8 +1866,14 @@ extern X_API YAP_Int YAP_FastInit(char saved_state[]); #define IOSTREAM void #endif /* FPL_STREAM_H */ +/// read a Prolog term from an operating system stream $s$. extern X_API YAP_Term YAP_Read(FILE *s); +/// read a Prolog term from a Prolog opened stream $s$. Check YAP_OpenStream() for how to open +/// Prolog streams in `C`. +extern X_API YAP_Term YAP_ReadFromStream(int s); + +/// read a Prolog clause from a Prolog opened stream $s$. Similar to YAP_ReadFromStream() but takes /// default options from read_clause/3. extern X_API YAP_Term YAP_ReadFromStream(int s); extern X_API void YAP_Write(YAP_Term t,FILE *s,int); @@ -1878,12 +1884,6 @@ extern X_API int YAP_InitConsult(int mode, const char *filename, int *previous_s extern X_API void YAP_EndConsult(int s, int *previous_sno); -#ifndef _PL_STREAM_H -// if we don't know what a stream is, just don't assume nothing about the pointer -#undef IOSTREAM -#endif /* FPL_STREAM_H */ - - extern X_API void YAP_Exit(int); /* void YAP_PutValue(YAP_Atom, YAP_Term) */ diff --git a/os/console.c b/os/console.c index 7096d1bec..a5b03cfdc 100644 --- a/os/console.c +++ b/os/console.c @@ -89,8 +89,9 @@ is_same_tty2 (USES_REGS1) } void -Yap_ConsoleOps( StreamDesc *s ) +Yap_ConsoleOps( StreamDesc *s, bool recursive ) { + if (!recursive) Yap_DefaultStreamOps( s ); /* the putc routine only has to check it is putting out a newline */ s->stream_putc = ConsolePutc; @@ -162,15 +163,15 @@ ConsoleGetc(int sno) if (LOCAL_PrologMode & AbortMode) { Yap_Error(ABORT_EVENT, TermNil, ""); LOCAL_ErrorMessage = "Abort"; - return console_post_process_eof(s); + return EOF; } goto restart; } else { LOCAL_PrologMode &= ~ConsoleGetcMode; } if (ch == EOF) - return console_post_process_eof(s); - return console_post_process_read_char(ch, s); + return EOF; + return ch; } /** @pred prompt1(+ _A__) @@ -199,10 +200,8 @@ prompt1 ( USES_REGS1 ) /** @pred prompt(- _A_,+ _B_) - Changes YAP input prompt from _A_ to _B_, active on *next* standard input interaction. - */ static Int prompt ( USES_REGS1 ) @@ -223,6 +222,21 @@ prompt ( USES_REGS1 ) return (TRUE); } +/** @pred ensure_prompting + +Make sure we have a prompt at this point, even if we have to +introduce a new line. + +*/ +static Int +ensure_prompting ( USES_REGS1 ) +{ /* prompt(Old,New) */ +if (!LOCAL_newline) { + GLOBAL_Stream[2].stream_wputc(2, 10); // hack! +} +return true; +} + int Yap_GetCharForSIGINT(void) { @@ -250,6 +264,7 @@ void Yap_InitConsole(void) { Yap_InitCPred ("prompt1", 1, prompt1, SafePredFlag|SyncPredFlag); Yap_InitCPred ("$is_same_tty", 2, is_same_tty2, SafePredFlag|SyncPredFlag|HiddenPredFlag); Yap_InitCPred ("prompt", 2, prompt, SafePredFlag|SyncPredFlag); + Yap_InitCPred ("$ensure_prompting", 0, ensure_prompting, SafePredFlag|SyncPredFlag); } diff --git a/os/getw.h b/os/getw.h new file mode 100644 index 000000000..d06fe0d8f --- /dev/null +++ b/os/getw.h @@ -0,0 +1,203 @@ + +/// compose a wide char from a sequence of getchars +/// this is a slow lane routine, called if no specialised code +/// isavailable. +static int GETW(int sno) { + StreamDesc *st = GLOBAL_Stream + sno; + int ch = GETC(); + + if (ch == -1) + return post_process_weof(st); + + switch (st->encoding) { + case ENC_OCTET: + // no error detection, all characters are ok. + case ENC_ISO_LATIN1: + return post_process_read_wchar(ch, 1, st); + // 7 bits code, anything above is bad news + case ENC_ISO_ASCII: + if (ch & 0x80) { + /* error */ + } + return post_process_read_wchar(ch, 1, st); + // default OS encoding, depends on locale. + case ENC_ISO_ANSI: { + char buf[8]; + int out; + int wch; + mbstate_t mbstate; + + memset((void *)&(mbstate), 0, sizeof(mbstate_t)); + buf[0] = ch; + int n=1; + while ((out = mbrtowc(&wch, buf, 1, &(mbstate))) != 1) { + int ch = buf[0] = GETC(); + n++; + if (ch == -1) + return post_process_weof(st); + } + return post_process_read_wchar(wch, n, st); + } +// UTF-8 works o 8 bits. +case ENC_ISO_UTF8: { + int wch; + unsigned char buf[8]; + + if (ch < 0x80) { + return post_process_read_wchar(ch, 1, st); + } + // if ((ch - 0xc2) > (0xf4-0xc2)) return UTF8PROC_ERROR_INVALIDUTF8; + if (ch < 0xe0) { // 2-byte sequence + // Must have valid continuation character + int c1 = buf[0] = GETC(); + if (c1 == -1) + return post_process_weof(st); + // if (!utf_cont(*str)) return UTF8PROC_ERROR_INVALIDUTF8; + wch = ((ch & 0x1f)<<6) | (c1 & 0x3f); + return post_process_read_wchar(wch, 2, st); + } + if (ch < 0xf0) { // 3-byte sequence + //if ((str + 1 >= end) || !utf_cont(*str) || !utf_cont(str[1])) + // return UTF8PROC_ERROR_INVALIDUTF8; + // Check for surrogate chars + //if (ch == 0xed && *str > 0x9f) + // return UTF8PROC_ERROR_INVALIDUTF8; + int c1 = GETC(); + if (c1 == -1) + return post_process_weof(st); + int c2 = GETC(); + if (c2 == -1) + return post_process_weof(st); + wch = ((ch & 0xf)<<12) | ((c1 & 0x3f)<<6) | (c2 & 0x3f); + return post_process_read_wchar(wch, 3, st); + } else { + int c1 = GETC(); + if (c1 == -1) + return post_process_weof(st); + int c2 = GETC(); + if (c2 == -1) + return post_process_weof(st); + int c3 = GETC(); + if (c3 == -1) + return post_process_weof(st); + wch = ((ch & 7)<<18) | ((c1 & 0x3f)<<12) | ((c2 & 0x3f)<<6) | (c3 & 0x3f); + return post_process_read_wchar(wch, 4, st); + } + } +case ENC_UTF16_LE: // check http://unicode.org/faq/utf_bom.html#utf16-3 + // little-endian: start with big shot + { + int wch; + int c1 = GETC(); + if (c1 == -1) + return post_process_weof(st); + wch = (c1 << 8) + ch; + if (wch >= 0xd800 && wch < 0xdc00) { + int c2 = GETC(); + if (c2 == -1) + return post_process_weof(st); + int c3 = GETC(); + if (c3 == -1) + return post_process_weof(st); + wch = wch + (((c3 << 8) + c2)<= 0xd800 && wch < 0xdc00) { + int c3 = GETC(); + if (c3 == -1) + return post_process_weof(st); + int c2 = GETC(); + if (c2 == -1) + return post_process_weof(st); + wch = (((c3 << 8) + c2) << 10) + wch + SURROGATE_OFFSET; + return post_process_read_wchar(wch, 4, st); + } + return post_process_read_wchar(wch, 2, st); + } + + case ENC_UCS2_BE: // check http://unicode.org/faq/utf_bom.html#utf16-3 + // little-endian: start with big shot + { + int wch; + int c1 = GETC(); + if (c1 == -1) + return post_process_weof(st); + wch = (c1) + (ch<<8); + return post_process_read_wchar(wch, 2, st); + } + + +case ENC_UCS2_LE: // check http://unicode.org/faq/utf_bom.html#utf16-3 + // little-endian: start with big shot + { + int wch; + int c1 = GETC(); + if (c1 == -1) + return post_process_weof(st); + wch = (c1 << 8) + ch; + + return post_process_read_wchar(wch, 2, st); + } + +case ENC_ISO_UTF32_BE: // check http://unicode.org/faq/utf_bom.html#utf16-3 + // little-endian: start with big shot + { + int wch = ch; + { + int c1 = GETC(); + if (c1 == -1) + return post_process_weof(st); + wch = wch + c1; + } + { + int c1 = GETC(); + if (c1 == -1) + return post_process_weof(st); + wch = (wch << 8 )+c1; + } + { + int c1 = GETC(); + if (c1 == -1) + return post_process_weof(st); + wch = (wch << 8) +c1; + } + return post_process_read_wchar(wch, 4, st); + } +case ENC_ISO_UTF32_LE: // check http://unicode.org/faq/utf_bom.html#utf16-3 + // little-endian: start with big shot + { + int wch = ch; + { + int c1 = GETC(); + if (c1 == -1) + return post_process_weof(st); + wch += c1<<8; + } + { + int c1 = GETC(); + if (c1 == -1) + return post_process_weof(st); + wch += c1<<16; + } + { + int c1 = GETC(); + if (c1 == -1) + return post_process_weof(st); + wch += c1<<24; + } + return post_process_read_wchar(wch, 4, st); + } + } +} diff --git a/os/iopreds.c b/os/iopreds.c index 64ac8d721..e4a05bb79 100644 --- a/os/iopreds.c +++ b/os/iopreds.c @@ -96,7 +96,17 @@ static char SccsId[] = "%W% %G%"; #endif #include "iopreds.h" -static int get_wchar(int); + +#define GETW get_wchar_from_FILE +#define GETC() fgetwc(st->file) +#include "getw.h" + +#undef GETW +#undef GETC +#define GETW get_wchar +#define GETC() st->stream_getc(sno) +#include "getw.h" + static int get_wchar_from_file(int); FILE *Yap_stdin; @@ -180,10 +190,13 @@ static bool is_file_errors(Term t) { void Yap_DefaultStreamOps(StreamDesc *st) { st->stream_wputc = put_wchar; - if (!(st->status & (Tty_Stream_f | Reset_Eof_Stream_f | Promptable_Stream_f))) - st->stream_wgetc = get_wchar_from_file; - else + if (st->status & (Promptable_Stream_f)) { st->stream_wgetc = get_wchar; + Yap_ConsoleOps(st, true); + } else if (st->encoding == LOCAL_encoding) { + st->stream_wgetc = get_wchar_from_file; + } else + st->stream_wgetc = get_wchar_from_FILE; if (GLOBAL_CharConversionTable != NULL) st->stream_wgetc_for_read = ISOWGetc; else @@ -250,15 +263,8 @@ static void unix_upd_stream_info(StreamDesc *s) { s->status |= Seekable_Stream_f; } -GetsFunc PlGetsFunc(void) { - if (GLOBAL_CharConversionTable) - return DefaultGets; - else - return PlGets; -} static void InitFileIO(StreamDesc *s) { - s->stream_gets = PlGetsFunc(); if (s->status & Socket_Stream_f) { /* Console is a socket and socket will prompt */ Yap_ConsoleSocketOps(s); @@ -273,14 +279,16 @@ static void InitFileIO(StreamDesc *s) { } else { /* check if our console is promptable: may be tty or pipe */ if (s->status & (Promptable_Stream_f)) { - Yap_ConsoleOps(s); + Yap_ConsoleOps(s, false); } else { /* we are reading from a file, no need to check for prompts */ s->stream_putc = FilePutc; s->stream_wputc = put_wchar; s->stream_getc = PlGetc; - s->stream_gets = PlGetsFunc(); - s->stream_wgetc = get_wchar_from_file; + if (s->encoding == LOCAL_encoding) + s->stream_wgetc = get_wchar_from_file; + else + s->stream_wgetc = get_wchar_from_FILE; } } s->stream_wputc = put_wchar; @@ -571,12 +579,11 @@ int ResetEOF(StreamDesc *s) { } else if (s->status & InMemory_Stream_f) { Yap_MemOps(s); } else if (s->status & Promptable_Stream_f) { - Yap_ConsoleOps(s); + Yap_ConsoleOps(s, false); } else { s->stream_getc = PlGetc; Yap_DefaultStreamOps(s); - s->stream_gets = PlGetsFunc(); - } + } /* next, reset our own error indicator */ s->status &= ~Eof_Stream_f; /* try reading again */ @@ -597,7 +604,7 @@ static int EOFWGetc(int sno) { return EOF; } if (ResetEOF(s)) { - Yap_ConsoleOps(s); + Yap_ConsoleOps(s, false); return (s->stream_wgetc(sno)); } return EOF; @@ -613,7 +620,7 @@ static int EOFGetc(int sno) { return EOF; } if (ResetEOF(s)) { - Yap_ConsoleOps(s); + Yap_ConsoleOps(s, false); return s->stream_getc(sno); } return EOF; @@ -633,9 +640,12 @@ int console_post_process_eof(StreamDesc *s) { } /* check if we read a newline or an EOF */ -int post_process_read_char(int ch, StreamDesc *s) { - ++s->charcount; - ++s->linepos; +int post_process_read_wchar(int ch, ssize_t n, StreamDesc *s) { + if (ch == EOF) { + return post_process_weof(s); + } + s->charcount += n; + s->linepos += n; if (ch == '\n') { ++s->linecount; s->linepos = 0; @@ -646,22 +656,12 @@ int post_process_read_char(int ch, StreamDesc *s) { return ch; } -/* check if we read a newline or an EOF */ -int post_process_eof(StreamDesc *s) { - if (!ResetEOF(s)) { - s->status |= Eof_Stream_f; - s->stream_wgetc = EOFWGetc; - s->stream_getc = EOFGetc; - s->stream_wgetc_for_read = EOFWGetc; - } - return EOFCHAR; -} int post_process_weof(StreamDesc *s) { if (!ResetEOF(s)) { s->status |= Eof_Stream_f; s->stream_wgetc = EOFWGetc; - s->stream_wgetc = EOFWGetc; + s->stream_getc = EOFGetc; s->stream_wgetc_for_read = EOFWGetc; } return EOFCHAR; @@ -684,249 +684,16 @@ int EOFWPeek(int sno) { return EOFWGetc(sno); } post_process_read_char, something to think about */ int PlGetc(int sno) { StreamDesc *s = &GLOBAL_Stream[sno]; - Int ch; - ch = fgetc(s->file); - if (ch == EOF) { - return post_process_eof(s); - } - return post_process_read_char(ch, s); + return fgetc(s->file); } -/* standard routine, it should read from anything pointed by a FILE *. - It could be made more efficient by doing our own buffering and avoiding - post_process_read_char, something to think about. It assumes codification in 8 - bits. */ -int PlGets(int sno, UInt size, char *buf) { - register StreamDesc *s = &GLOBAL_Stream[sno]; - UInt len; - - if (fgets(buf, size, s->file) == NULL) { - return post_process_eof(s); - } - len = strlen(buf); - s->charcount += len - 1; - post_process_read_char(buf[len - 2], s); - return strlen(buf); -} - -/* standard routine, it should read from anything pointed by a FILE *. - It could be made more efficient by doing our own buffering and avoiding - post_process_read_char, something to think about */ -int DefaultGets(int sno, UInt size, char *buf) { - StreamDesc *s = &GLOBAL_Stream[sno]; - char ch; - char *pt = buf; - - if (!size) - return 0; - while ((ch = *buf++ = s->stream_getc(sno)) != -1 && ch != 10 && --size) - ; - *buf++ = '\0'; - return (buf - pt) - 1; -} - -/// compose a wide char from a sequence of getchars \ -// this is a slow lane routine, called if no specialised code -// isavailable. -static int get_wchar(int sno) { - StreamDesc *st = GLOBAL_Stream + sno; - int ch = st->stream_getc(sno); - - if (ch == -1) - return post_process_weof(st); - - switch (st->encoding) { - case ENC_OCTET: - return ch; - // no error detection, all characters are ok. - case ENC_ISO_LATIN1: - return ch; - // 7 bits code, anything above is bad news - case ENC_ISO_ASCII: - if (ch & 0x80) { - /* error */ - } - return ch; - // default OS encoding, depends on locale. - case ENC_ISO_ANSI: { - char buf[8]; - int out; - int wch; - mbstate_t mbstate; - - memset((void *)&(mbstate), 0, sizeof(mbstate_t)); - buf[0] = ch; - while ((out = mbrtowc(&wch, buf, 1, &(mbstate))) != 1) { - int ch = buf[0] = st->stream_getc(sno); - if (ch == -1) - return post_process_weof(st); - } - return wch; - } -// UTF-8 works o 8 bits. -case ENC_ISO_UTF8: { - unsigned char buf[8]; - - if (ch < 0x80) { - return ch; - } - // if ((ch - 0xc2) > (0xf4-0xc2)) return UTF8PROC_ERROR_INVALIDUTF8; - if (ch < 0xe0) { // 2-byte sequence - // Must have valid continuation character - int c1 = buf[0] = st->stream_getc(sno); - if (c1 == -1) - return post_process_weof(st); - // if (!utf_cont(*str)) return UTF8PROC_ERROR_INVALIDUTF8; - return ((ch & 0x1f)<<6) | (c1 & 0x3f); - } - if (ch < 0xf0) { // 3-byte sequence - //if ((str + 1 >= end) || !utf_cont(*str) || !utf_cont(str[1])) - // return UTF8PROC_ERROR_INVALIDUTF8; - // Check for surrogate chars - //if (ch == 0xed && *str > 0x9f) - // return UTF8PROC_ERROR_INVALIDUTF8; - int c1 = st->stream_getc(sno); - if (c1 == -1) - return post_process_weof(st); - int c2 = st->stream_getc(sno); - if (c2 == -1) - return post_process_weof(st); - return ((ch & 0xf)<<12) | ((c1 & 0x3f)<<6) | (c2 & 0x3f); - } else { - int c1 = st->stream_getc(sno); - if (c1 == -1) - return post_process_weof(st); - int c2 = st->stream_getc(sno); - if (c2 == -1) - return post_process_weof(st); - int c3 = st->stream_getc(sno); - if (c3 == -1) - return post_process_weof(st); - return ((ch & 7)<<18) | ((c1 & 0x3f)<<12) | ((c2 & 0x3f)<<6) | (c3 & 0x3f); - } - } -case ENC_UTF16_LE: // check http://unicode.org/faq/utf_bom.html#utf16-3 - // little-endian: start with big shot - { - int wch; - int c1 = st->stream_getc(sno); - if (c1 == -1) - return post_process_weof(st); - wch = (c1 << 8) + ch; - if (wch >= 0xd800 && wch < 0xdc00) { - int c2 = st->stream_getc(sno); - if (c2 == -1) - return post_process_weof(st); - int c3 = st->stream_getc(sno); - if (c3 == -1) - return post_process_weof(st); - wch = wch + (((c3 << 8) + c2)<stream_getc(sno); - if (c1 == -1) - return post_process_weof(st); - wch = (c1) + (ch<<8); - if (wch >= 0xd800 && wch < 0xdc00) { - int c3 = st->stream_getc(sno); - if (c3 == -1) - return post_process_weof(st); - int c2 = st->stream_getc(sno); - if (c2 == -1) - return post_process_weof(st); - wch = (((c3 << 8) + c2) << 10) + wch + SURROGATE_OFFSET; - } - return wch; - } - - case ENC_UCS2_BE: // check http://unicode.org/faq/utf_bom.html#utf16-3 - // little-endian: start with big shot - { - int wch; - int c1 = st->stream_getc(sno); - if (c1 == -1) - return post_process_weof(st); - wch = (c1) + (ch<<8); - return wch; - } - - -case ENC_UCS2_LE: // check http://unicode.org/faq/utf_bom.html#utf16-3 - // little-endian: start with big shot - { - int wch; - int c1 = st->stream_getc(sno); - if (c1 == -1) - return post_process_weof(st); - wch = (c1 << 8) + ch; - - return wch; - } - -case ENC_ISO_UTF32_BE: // check http://unicode.org/faq/utf_bom.html#utf16-3 - // little-endian: start with big shot - { - int wch = ch; - { - int c1 = st->stream_getc(sno); - if (c1 == -1) - return post_process_weof(st); - wch = wch + c1; - } - { - int c1 = st->stream_getc(sno); - if (c1 == -1) - return post_process_weof(st); - wch = (wch << 8 )+c1; - } - { - int c1 = st->stream_getc(sno); - if (c1 == -1) - return post_process_weof(st); - wch = (wch << 8) +c1; - } - return wch; - } -case ENC_ISO_UTF32_LE: // check http://unicode.org/faq/utf_bom.html#utf16-3 - // little-endian: start with big shot - { - int wch = ch; - { - int c1 = st->stream_getc(sno); - if (c1 == -1) - return post_process_weof(st); - wch += c1<<8; - } - { - int c1 = st->stream_getc(sno); - if (c1 == -1) - return post_process_weof(st); - wch += c1<<16; - } - { - int c1 = st->stream_getc(sno); - if (c1 == -1) - return post_process_weof(st); - wch += c1<<24; - } - return wch; - } - } -} // layered version - static int get_wchar__(int sno) { return get_wchar(sno); } + static int get_wchar__(int sno) { return fgetwc(GLOBAL_Stream[sno].file); } static int get_wchar_from_file(int sno) { - return post_process_read_char(get_wchar__(sno), GLOBAL_Stream + sno); + return post_process_read_wchar(get_wchar__(sno), 1, GLOBAL_Stream + sno); } #ifndef MB_LEN_MAX @@ -1214,23 +981,23 @@ case ENC_ISO_UTF32_LE: // check http://unicode.org/faq/utf_bom.html#utf16-3 static void check_bom(int sno, StreamDesc *st) { int ch1, ch2, ch3, ch4; - ch1 = st->stream_getc(sno); + ch1 = fgetc(st->file); switch (ch1) { case 0x00: { - ch2 = st->stream_getc(sno); + ch2 = fgetc(st->file); if (ch2 != 0x00) { ungetc(ch1, st->file); ungetc(ch2, st->file); return; } else { - ch3 = st->stream_getc(sno); + ch3 = fgetc(st->file); if (ch3 == EOFCHAR || ch3 != 0xFE) { ungetc(ch1, st->file); ungetc(ch2, st->file); ungetc(ch3, st->file); return; } else { - ch4 = st->stream_getc(sno); + ch4 = fgetc(st->file); if (ch4 == EOFCHAR || ch3 != 0xFF) { ungetc(ch1, st->file); ungetc(ch2, st->file); @@ -1246,7 +1013,7 @@ case ENC_ISO_UTF32_LE: // check http://unicode.org/faq/utf_bom.html#utf16-3 } } case 0xFE: { - ch2 = st->stream_getc(sno); + ch2 = fgetc(st->file); if (ch2 != 0xFF) { ungetc(ch1, st->file); ungetc(ch2, st->file); @@ -1258,17 +1025,17 @@ case ENC_ISO_UTF32_LE: // check http://unicode.org/faq/utf_bom.html#utf16-3 } } case 0xFF: { - ch2 = st->stream_getc(sno); + ch2 = fgetc(st->file); if (ch2 != 0xFE) { ungetc(ch1, st->file); ungetc(ch2, st->file); return; } else { - ch3 = st->stream_getc(sno); + ch3 = fgetc(st->file); if (ch3 != 0x00) { ungetc(ch3, st->file); } else { - ch4 = st->stream_getc(sno); + ch4 = fgetc(st->file); if (ch4 == 0x00) { st->status |= HAS_BOM_f; st->encoding = ENC_ISO_UTF32_LE; @@ -1284,13 +1051,13 @@ case ENC_ISO_UTF32_LE: // check http://unicode.org/faq/utf_bom.html#utf16-3 return; } case 0xEF: - ch2 = st->stream_getc(sno); + ch2 = fgetc(st->file); if (ch2 != 0xBB) { ungetc(ch1, st->file); ungetc(ch2, st->file); return; } else { - ch3 = st->stream_getc(sno); + ch3 = fgetc(st->file); if (ch3 != 0xBF) { ungetc(ch1, st->file); ungetc(ch2, st->file); @@ -1334,7 +1101,7 @@ case ENC_ISO_UTF32_LE: // check http://unicode.org/faq/utf_bom.html#utf16-3 Yap_PipeOps(st); Yap_DefaultStreamOps(st); } else if (flags & Tty_Stream_f) { - Yap_ConsoleOps(st); + Yap_ConsoleOps(st, false); Yap_DefaultStreamOps(st); } else { st->stream_putc = FilePutc; @@ -1342,7 +1109,6 @@ case ENC_ISO_UTF32_LE: // check http://unicode.org/faq/utf_bom.html#utf16-3 unix_upd_stream_info(st); Yap_DefaultStreamOps(st); } - st->stream_gets = PlGetsFunc(); return true; } @@ -1747,7 +1513,6 @@ case ENC_ISO_UTF32_LE: // check http://unicode.org/faq/utf_bom.html#utf16-3 st->stream_putc = NullPutc; st->stream_wputc = put_wchar; st->stream_getc = PlGetc; - st->stream_gets = PlGets; st->stream_wgetc = get_wchar; st->stream_wgetc_for_read = get_wchar; st->user_name = MkAtomTerm(st->name = AtomDevNull); @@ -1896,7 +1661,7 @@ case ENC_ISO_UTF32_LE: // check http://unicode.org/faq/utf_bom.html#utf16-3 if (s->status & Pipe_Stream_f) { Yap_ConsolePipeOps(s); } else - Yap_ConsoleOps(s); + Yap_ConsoleOps(s, false); return (TRUE); } diff --git a/os/iopreds.h b/os/iopreds.h index 080d93784..4fbfc0a95 100644 --- a/os/iopreds.h +++ b/os/iopreds.h @@ -203,20 +203,16 @@ typedef struct stream_desc { } u; Int charcount, linecount, linepos; stream_flags_t status; - int och; #if defined(YAPOR) || defined(THREADS) lockvar streamlock; /* protect stream access */ #endif - int (*stream_putc)(int, int); /* function the stream uses for writing */ - int (*stream_getc)(int); /* function the stream uses for reading */ - GetsFunc stream_gets; /* function the stream uses for reading a sequence of - characters */ - /* function the stream uses for parser. It may be different if the ISO - character conversion is on */ - int (*stream_wgetc_for_read)(int); - int (*stream_wgetc)(int); - int (*stream_wputc)(int, wchar_t); - encoding_t encoding; + int (*stream_putc)(int, int); /** function the stream uses for writing a single octet */ + int (*stream_wputc)(int, wchar_t); /** function the stream uses for writing a character */ + int (*stream_getc)(int); /** function the stream uses for reading an octet. */ + int (*stream_wgetc)(int); /** function the stream uses for reading a character. */ + + int (*stream_wgetc_for_read)(int); /* function the stream uses for parser. It may be different from above if the ISO character conversion is on */ + encoding_t encoding; /** current encoding for stream */ } StreamDesc; static inline bool IsStreamTerm(Term t) { @@ -274,8 +270,8 @@ void Yap_ConsolePipeOps(StreamDesc *st); void Yap_SocketOps(StreamDesc *st); void Yap_ConsoleSocketOps(StreamDesc *st); bool Yap_ReadlineOps(StreamDesc *st); -int Yap_OpenBufWriteStream(USES_REGS1); -void Yap_ConsoleOps(StreamDesc *s); +int Yap_OpenBufWriteStream(USES_REGS1); +void Yap_ConsoleOps(StreamDesc *s, bool recursive); void Yap_InitRandomPreds(void); void Yap_InitSignalPreds(void); @@ -309,8 +305,7 @@ Term Yap_syntax_error(TokEntry *tokptr, int sno); int console_post_process_read_char(int, StreamDesc *); int console_post_process_eof(StreamDesc *); -int post_process_read_char(int, StreamDesc *); -int post_process_eof(StreamDesc *); +int post_process_read_wchar(int, ssize_t, StreamDesc *); int post_process_weof(StreamDesc *); bool is_same_tty(FILE *f1, FILE *f2); diff --git a/os/pipes.c b/os/pipes.c index b09dd7559..ef8c8c279 100644 --- a/os/pipes.c +++ b/os/pipes.c @@ -172,7 +172,7 @@ PipeGetc(int sno) int count; count = read(s->u.pipe.fd, &c, sizeof(char)); if (count == 0) { - return post_process_eof(s); + return EOF; } else if (count > 0) { ch = c; } else { @@ -181,9 +181,9 @@ PipeGetc(int sno) #else Yap_Error(SYSTEM_ERROR_INTERNAL, TermNil, "at pipe getc"); #endif - return post_process_eof(s); + return EOF; } - return post_process_read_char(ch, s); + return ch; } void diff --git a/os/readterm.c b/os/readterm.c index 7b601b131..3c5580cf1 100644 --- a/os/readterm.c +++ b/os/readterm.c @@ -734,7 +734,6 @@ static parser_state_t scanEOF(FEnv *fe, int inp_stream) { fe->t = 0; if (fe->tp && !Yap_unify(fe->tp, fe->tpos)) fe->t = 0; - post_process_eof(GLOBAL_Stream + inp_stream); #if DEBUG if (GLOBAL_Option['p' - 'a' + 1]) { fprintf(stderr, "[ end_of_file %p ]\n", GLOBAL_Stream[inp_stream].name); @@ -1082,7 +1081,7 @@ static xarg *setClauseReadEnv(Term opts, FEnv *fe, struct renv *re, static Int read_clause2(USES_REGS1) { Term rc; yhandle_t h = Yap_InitSlot(ARG1); - rc = Yap_read_term(LOCAL_c_input_stream, Deref(ARG2), 2); + rc = Yap_read_term(LOCAL_c_input_stream, Deref(ARG2), -2); Term tf = Yap_GetFromSlot(h); Yap_RecoverSlots(1, h); return rc && Yap_unify(tf, rc); diff --git a/os/readutil.c b/os/readutil.c index 7c367c7f8..e09a6a835 100644 --- a/os/readutil.c +++ b/os/readutil.c @@ -33,9 +33,10 @@ static Int rl_to_codes(Term TEnd, int do_as_binary, int arity USES_REGS) { int sno = Yap_CheckStream (ARG1, Input_Stream_f, "read_line_to_codes/2"); + StreamDesc *st = GLOBAL_Stream+sno; Int status; UInt max_inp, buf_sz, sz; - char *buf; + int *buf; bool binary_stream; if (sno < 0) @@ -47,15 +48,28 @@ rl_to_codes(Term TEnd, int do_as_binary, int arity USES_REGS) return Yap_unify_constant(ARG2, MkAtomTerm (AtomEof)); } max_inp = (ASP-HR)/2-1024; - buf = (char *)TR; - buf_sz = (char *)LOCAL_TrailTop-buf; + buf = (int *)TR; + buf_sz = (int *)LOCAL_TrailTop-buf; while (TRUE) { if ( buf_sz > max_inp ) { buf_sz = max_inp; } - if (do_as_binary && !binary_stream) + if (do_as_binary && !binary_stream) { GLOBAL_Stream[sno].status |= Binary_Stream_f; - sz = GLOBAL_Stream[sno].stream_gets(sno, buf_sz, buf); + } + if (st->status & Binary_Stream_f) { + char *b = (char *)TR; + sz = fread( b,1 , buf_sz, GLOBAL_Stream[sno].file); + } else { + int ch; + int *pt = buf; + do { + *pt++ = ch = st->stream_wgetc_for_read(sno); + if (pt+1 == buf+buf_sz) + break; + } while (ch != '\n'); + sz = pt-buf; + } if (do_as_binary && !binary_stream) GLOBAL_Stream[sno].status &= ~Binary_Stream_f; if (sz == -1 || sz == 0) { @@ -117,7 +131,8 @@ read_line_to_string( USES_REGS1 ) int sno = Yap_CheckStream (ARG1, Input_Stream_f, "read_line_to_codes/2"); Int status; UInt max_inp, buf_sz; - char *buf; + int *buf; + StreamDesc *st = GLOBAL_Stream+sno; if (sno < 0) return FALSE; @@ -127,15 +142,27 @@ read_line_to_string( USES_REGS1 ) return Yap_unify_constant(ARG2, MkAtomTerm (AtomEof)); } max_inp = (ASP-HR)/2-1024; - buf = (char *)TR; - buf_sz = (char *)LOCAL_TrailTop-buf; + buf = (int *)TR; + buf_sz = (int *)LOCAL_TrailTop-buf; while (true) { size_t sz; if ( buf_sz > max_inp ) { buf_sz = max_inp; } - sz = GLOBAL_Stream[sno].stream_gets(sno, buf_sz, buf); + if (st->status & Binary_Stream_f) { + char *b = (char *)TR; + sz = fread( b,1 , buf_sz, GLOBAL_Stream[sno].file); + } else { + int ch; + int *pt = buf; + do { + *pt++ = ch = st->stream_wgetc_for_read(sno); + if (pt+1 == buf+buf_sz) + break; + } while (ch != '\n'); + sz = pt-buf; + } if (sz == -1 || sz == 0) { if (GLOBAL_Stream[sno].status & Eof_Stream_f) { UNLOCK(GLOBAL_Stream[sno].streamlock); diff --git a/os/sockets.c b/os/sockets.c index c88d44851..11509c2c7 100644 --- a/os/sockets.c +++ b/os/sockets.c @@ -103,7 +103,7 @@ SocketGetc(int sno) #endif if (count == 0) { s->u.socket.flags = closed_socket; - return post_process_eof(s); + return EOF; } else if (count > 0) { ch = c; } else { @@ -114,9 +114,9 @@ SocketGetc(int sno) Yap_Error(SYSTEM_ERROR_INTERNAL, TermNil, "(socket_getc)"); #endif - return post_process_eof(s); + return EOF; } - return post_process_read_char(ch, s); + return ch; } /* @@ -158,7 +158,7 @@ ConsoleSocketGetc(int sno) Yap_Error(SYSTEM_ERROR_INTERNAL, TermNil, "read"); return console_post_process_eof(s); } - return console_post_process_read_char(ch, s); + return ch; } /* static */ diff --git a/os/streams.c b/os/streams.c index 23f22820e..4340341bd 100644 --- a/os/streams.c +++ b/os/streams.c @@ -140,7 +140,6 @@ int GetFreeStreamD(void) { LOCK(GLOBAL_Stream[sno].streamlock); UNLOCK(GLOBAL_StreamDescLock); GLOBAL_Stream[sno].encoding = LOCAL_encoding; - GLOBAL_Stream[sno].och = '\0'; return sno; } @@ -648,7 +647,8 @@ static Int cont_stream_property(USES_REGS1) { /* current_stream */ if (p == STREAM_PROPERTY_END ) { // move to next existing stream LOCK(GLOBAL_StreamDescLock); - while (++i < MaxStreams && GLOBAL_Stream[i].status & Free_Stream_f) ; + while (++i < MaxStreams && GLOBAL_Stream[i].status & Free_Stream_f) + {} UNLOCK(GLOBAL_StreamDescLock); if (i < MaxStreams) { EXTRA_CBACK_ARG(2, 1) = MkIntTerm(i); @@ -1221,7 +1221,6 @@ static Int return (FALSE); } GLOBAL_Stream[sno].stream_getc = PlGetc; - GLOBAL_Stream[sno].stream_gets = PlGetsFunc(); } else if (FunctorOfTerm(tin) == FunctorStreamEOS) { if (IsVarTerm(tp = ArgOfTerm(1, tin))) { UNLOCK(GLOBAL_Stream[sno].streamlock); @@ -1245,8 +1244,7 @@ static Int return (FALSE); } GLOBAL_Stream[sno].stream_getc = PlGetc; - GLOBAL_Stream[sno].stream_gets = PlGetsFunc(); - /* reset the counters */ + /* reset the counters */ GLOBAL_Stream[sno].linepos = 0; GLOBAL_Stream[sno].linecount = 1; GLOBAL_Stream[sno].charcount = 0;