16static char SccsId[] =
"%W% %G%";
62#if HAVE_SYS_SELECT_H && !_MSC_VER && !defined(__MINGW32__)
63#include <sys/select.h>
81#define strncat(X, Y, Z) strcat(X, Y)
84#define strncpy(X, Y, Z) strcpy(X, Y)
86#if _MSC_VER || defined(__MINGW32__)
92#define S_ISDIR(x) (((x)&_S_IFDIR) == _S_IFDIR)
100#if _MSC_VER || defined(__MINGW32__)
101#define SYSTEM_STAT _stat
104#define SYSTEM_STAT stat
107 bool IsStreamTerm(Term t) {
108 return !IsVarTerm(t) &&
110 (IsApplTerm(t) && (FunctorOfTerm(t) == FunctorStream)));
114void count_output_char(
int ch,
StreamDesc *s) {
117 if (mpwshell && (sno == StdOutStream || sno == StdErrStream) &&
118 !(s->status & Null_Stream_f)) {
119 putc(MPWSEP, s->file);
120 if (!(GLOBAL_Stream[LOCAL_output_stream].status & Null_Stream_f))
127 s->linestart = s->charcount;
133static void CloseStream(
int sno);
135FILE *Yap_GetInputStream(Term t,
const char *msg) {
136 int sno = Yap_CheckStream(t, Input_Stream_f, msg);
139 if (!(GLOBAL_Stream[sno].status &
140 (Tty_Stream_f | Socket_Stream_f | Pipe_Stream_f)))
141 rc = GLOBAL_Stream[sno].file;
144 UNLOCK(GLOBAL_Stream[sno].streamlock);
148FILE *Yap_GetOutputStream(Term t,
const char *msg) {
149 int sno = Yap_CheckStream(t, Output_Stream_f, msg);
152 if (!(GLOBAL_Stream[sno].status & (Tty_Stream_f | Socket_Stream_f)))
153 rc = GLOBAL_Stream[sno].file;
156 UNLOCK(GLOBAL_Stream[sno].streamlock);
160int GetFreeStreamD(
void) {
162 LOCK(GLOBAL_StreamDescLock);
164 for (sno = 0; sno < MaxStreams; ++sno) {
165 if (GLOBAL_Stream[sno].status & Free_Stream_f) {
170 void *callstack[256];
174 for (i=7; i< sno; i++)
175 fprintf(stderr,
" %d %x\n", i,GLOBAL_Stream[i].status);
177 fprintf(stderr,
"++++ got %d\n", sno);
178 int frames = backtrace(callstack, 256);
179 char **strs = backtrace_symbols(callstack, frames);
180 fprintf(stderr,
"Execution stack:\n");
181 for (i = 0; i < 5; ++i) {
182 fprintf(stderr,
" %s\n", strs[i]);
186 if (sno == MaxStreams) {
187 UNLOCK(GLOBAL_StreamDescLock);
190 LOCK(GLOBAL_Stream[sno].streamlock);
191 GLOBAL_Stream[sno].status &= ~Free_Stream_f;
192 UNLOCK(GLOBAL_StreamDescLock);
193 GLOBAL_Stream[sno].encoding = LOCAL_encoding;
197int Yap_GetFreeStreamD(
void) {
return GetFreeStreamD(); }
199int Yap_FirstFreeStreamD(
void) {
201 for (i=3; i<MaxStreams; ++i) {
202 if (GLOBAL_Stream[i].status & Free_Stream_f) {
212bool Yap_clearInput(
int sno) {
213 if (!(GLOBAL_Stream[sno].status & Tty_Stream_f) || sno < 3)
215 if (GLOBAL_Stream[sno].
vfs) {
216 GLOBAL_Stream[sno].vfs->flush(sno);
220 if (GLOBAL_Stream[sno].status & Readline_Stream_f)
221 return Yap_readline_clear_pending_input(GLOBAL_Stream + sno);
225 return fpurge(GLOBAL_Stream[sno].file) == 0;
227 return tcflush(fileno(GLOBAL_Stream[sno].file), TCIOFLUSH) == 0;
229 return fflush(GLOBAL_Stream[sno].file) == 0;
234bool Yap_flush(
int sno) {
235 if (!(GLOBAL_Stream[sno].status & Tty_Stream_f))
237 if (GLOBAL_Stream[sno].
vfs) {
238 GLOBAL_Stream[sno].vfs->flush(sno);
241 return fflush(GLOBAL_Stream[sno].file) == 0;
244static Int clear_input(USES_REGS1) {
246 Yap_CheckStream(ARG1, Input_Stream_f | Socket_Stream_f,
"clear_input/1");
248 UNLOCK(GLOBAL_Stream[sno].streamlock);
249 return Yap_clearInput(sno);
252static Term lineCount(
int sno) {
255 if (GLOBAL_Stream[sno].status & Tty_Stream_f) {
260 if (GLOBAL_Stream[sno].status & Socket_Stream_f)
261 my_stream = AtomSocket;
264 if (GLOBAL_Stream[sno].status & Pipe_Stream_f)
265 my_stream = AtomPipe;
266 else if (GLOBAL_Stream[sno].status & InMemory_Stream_f)
267 my_stream = AtomCharsio;
269 my_stream = GLOBAL_Stream[sno].name;
270 for (i = 0; i < MaxStreams; i++) {
271 if ((GLOBAL_Stream[i].status &
272 (Socket_Stream_f | Pipe_Stream_f | InMemory_Stream_f)) &&
273 !(GLOBAL_Stream[i].status & (Free_Stream_f)) &&
274 GLOBAL_Stream[i].name == my_stream)
275 no += GLOBAL_Stream[i].linecount - 1;
277 tout = MkIntTerm(no);
279 tout = MkIntTerm(GLOBAL_Stream[sno].linecount);
280 UNLOCK(GLOBAL_Stream[sno].streamlock);
284static Int stream_flags(USES_REGS1) {
287 if (IsVarTerm(trm) || !IsIntTerm(trm))
289 return (Yap_unify_constant(ARG2,
290 MkIntTerm(GLOBAL_Stream[IntOfTerm(trm)].status)));
293static Int p_check_stream(USES_REGS1) {
294 Term mode = Deref(ARG2);
295 int sno = Yap_CheckStream(
296 ARG1, AtomOfTerm(mode) == AtomRead ? Input_Stream_f : Output_Stream_f,
299 UNLOCK(GLOBAL_Stream[sno].streamlock);
303static Int p_check_if_stream(USES_REGS1) {
304 int sno = Yap_CheckStream(ARG1,
305 Input_Stream_f | Output_Stream_f | Append_Stream_f |
309 UNLOCK(GLOBAL_Stream[sno].streamlock);
314is_input(
int sno USES_REGS) {
315 bool rc = GLOBAL_Stream[sno].status & Input_Stream_f;
320is_output(
int sno USES_REGS) {
321 bool rc = GLOBAL_Stream[sno].status & (Output_Stream_f | Append_Stream_f);
326has_bom(
int sno, Term t2 USES_REGS) {
327 bool rc = GLOBAL_Stream[sno].status & HAS_BOM_f;
328 if (!IsVarTerm(t2) && !booleanFlag(t2)) {
333 return Yap_unify_constant(t2, TermTrue);
335 return Yap_unify_constant(t2, TermFalse);
340has_reposition(
int sno,
342 bool rc = GLOBAL_Stream[sno].status & Seekable_Stream_f;
343 if (!IsVarTerm(t2) && !booleanFlag(t2)) {
348 return Yap_unify_constant(t2, TermTrue);
350 return Yap_unify_constant(t2, TermFalse);
354bool Yap_SetCurInpPos(
355 int sno, Int pos USES_REGS) {
357 if (GLOBAL_Stream[sno].
vfs) {
358 if (GLOBAL_Stream[sno].
vfs->
seek &&
359 GLOBAL_Stream[sno].vfs->seek(sno, 0L, SEEK_END) == -1) {
360 UNLOCK(GLOBAL_Stream[sno].streamlock);
361 PlIOError(SYSTEM_ERROR_INTERNAL, pos,
362 "fseek failed for set_stream_position/2: %s", strerror(errno));
365 }
else if (fseek(GLOBAL_Stream[sno].file, pos, SEEK_SET) == -1) {
366 UNLOCK(GLOBAL_Stream[sno].streamlock);
367 PlIOError(SYSTEM_ERROR_INTERNAL, MkIntegerTerm(0),
368 "fseek failed for set_stream_position/2: %s", strerror(errno));
374Atom Yap_guessFileName(FILE *file,
int sno,
size_t max) {
376 Atom at = Yap_LookupAtom(
"mem");
379 int f = fileno(file);
381 Atom at = Yap_LookupAtom(
"fmem");
385 int i = push_text_stack();
387 size_t maxs = Yap_Max(1023, max - 1);
390 if ((len = snprintf(path, 1023,
"/proc/self/fd/%d", f)) >= 0 &&
391 (len = readlink(path, nameb, maxs)) > 0) {
393 Atom at = Yap_LookupAtom(nameb);
398 size_t maxs = Yap_Max(1023, max - 1);
399 char *nameb =
Malloc(maxs + 1);
400 if (fcntl(f, F_GETPATH, nameb) != -1) {
401 Atom at = Yap_LookupAtom(nameb);
406 TCHAR *path =
Malloc(MAX_PATH + 1), *nameb =
Malloc(MAX_PATH + 1);
408 if (!GetFullPathName(path, MAX_PATH, nameb, NULL)) {
413 unsigned char *ptr = (
unsigned char *)nameb;
414 for (i = 0; i < strlen(path); i++)
415 ptr += put_utf8(ptr, path[i]);
417 Atom at = Yap_LookupAtom(nameb);
422 if (!StreamName(sno)) {
426 return AtomOfTerm(StreamName(sno));
429static Int representation_error(
int sno, Term t2 USES_REGS) {
430 stream_flags_t flags =
431 GLOBAL_Stream[sno].status & (RepError_Xml_f | RepError_Prolog_f);
433 if (!IsVarTerm(t2) && isatom(t2)) {
436 if (flags & RepError_Xml_f) {
437 return Yap_unify(t2, TermXml);
439 if (flags & RepError_Prolog_f) {
440 return Yap_unify(t2, TermProlog);
442 return Yap_unify(t2, TermError);
445static Int file_name(
int sno, Term t2 USES_REGS) {
446 return Yap_unify_constant(t2, MkAtomTerm(GLOBAL_Stream[sno].name));
449static Int file_no(
int sno, Term t2 USES_REGS) {
450 int f = Yap_GetStreamFd(sno);
451 Term rc = MkIntTerm(f);
452 if (!IsVarTerm(t2) && !IsIntTerm(t2)) {
455 return Yap_unify_constant(t2, rc);
458static bool SetCloseOnAbort(
int sno,
bool close) {
460 GLOBAL_Stream[sno].status |= DoNotCloseOnAbort_Stream_f;
462 GLOBAL_Stream[sno].status &= ~DoNotCloseOnAbort_Stream_f;
467static Int has_close_on_abort(
468 int sno, Term t2 USES_REGS) {
469 bool rc = GLOBAL_Stream[sno].status & DoNotCloseOnAbort_Stream_f;
470 if (!IsVarTerm(t2)) {
471 return t2 == (rc ? TermTrue : TermFalse);
474 return Yap_unify_constant(t2, TermTrue);
476 return Yap_unify_constant(t2, TermFalse);
483 const char *s = enc_name(GLOBAL_Stream[sno].
encoding);
484 return Yap_unify(t2, MkAtomTerm(Yap_LookupAtom(s)));
490 stream_flags_t flags =
491 GLOBAL_Stream[sno].status & (Past_Eof_Stream_f | Eof_Stream_f);
492 if (!IsVarTerm(t2) && !(isatom(t2))) {
495 if (flags & Past_Eof_Stream_f)
496 return Yap_unify(t2, MkAtomTerm(AtomPast));
497 if (flags & Eof_Stream_f)
498 return Yap_unify(t2, MkAtomTerm(AtomAt));
499 return Yap_unify(t2, MkAtomTerm(AtomAltNot));
502static bool stream_mode(
int sno, Term t2 USES_REGS) {
504 stream_flags_t flags = GLOBAL_Stream[sno].status;
505 if (!IsVarTerm(t2) && !(isatom(t2))) {
508 if (flags & Input_Stream_f)
509 return Yap_unify(t2, TermRead);
510 if (flags & Append_Stream_f)
511 return Yap_unify(t2, TermWrite);
512 if (flags & Output_Stream_f)
513 return Yap_unify(t2, TermWrite);
520 stream_flags_t flags = GLOBAL_Stream[sno].status & (Tty_Stream_f);
521 if (!IsVarTerm(t2) && !(isatom(t2))) {
524 if (flags & Tty_Stream_f)
525 return Yap_unify(t2, TermTrue);
526 return Yap_unify(t2, TermFalse);
532 stream_flags_t flags = GLOBAL_Stream[sno].status & (Binary_Stream_f);
533 if (!IsVarTerm(t2) && !(isatom(t2))) {
536 if (flags & Binary_Stream_f)
537 return Yap_unify(t2, TermBinary);
538 return Yap_unify(t2, TermText);
542stream_position(
int sno,
544 Term tout = StreamPosition(sno);
545 return Yap_unify(t2, tout);
548static bool stream_line_count(
549 int sno, Term t2 USES_REGS) {
550 Term tout = lineCount(sno);
551 return Yap_unify(t2, tout);
554static bool stream_line_number(
555 int sno, Term t2 USES_REGS) {
556 Term tout = MkIntegerTerm(GLOBAL_Stream[sno].linecount);
557 return Yap_unify(t2, tout);
561SetBuffering(
int sno,
Atom at) {
562 if (at == AtomFull) {
563 if (setvbuf(GLOBAL_Stream[sno].file, NULL, _IOFBF, 0) < 0)
564 return PlIOError(SYSTEM_ERROR_INTERNAL, Yap_MkStream(sno),
565 "could not set buffer");
566 }
else if (at == AtomLine) {
567 if (setvbuf(GLOBAL_Stream[sno].file, NULL, _IOLBF, 0) < 0)
568 return PlIOError(SYSTEM_ERROR_INTERNAL, Yap_MkStream(sno),
569 "could not set line buffering");
570 }
else if (at == AtomFalse) {
571 if (setvbuf(GLOBAL_Stream[sno].file, NULL, _IONBF, 0) < 0)
572 return PlIOError(SYSTEM_ERROR_INTERNAL, Yap_MkStream(sno),
573 "could not set disable buffering");
576 LOCAL_Error_TYPE = DOMAIN_ERROR_OUT_OF_RANGE;
577 LOCAL_ErrorMessage =
"in set_stream/2:buffer";
583static bool SetBuffer(
int sno,
585 if (setvbuf(GLOBAL_Stream[sno].file, NULL, _IOFBF, sz) < 0) {
586 return PlIOError(SYSTEM_ERROR_INTERNAL, Yap_MkStream(sno),
587 "could not set buffer");
595 stream_flags_t flags =
596 GLOBAL_Stream[sno].status &
597 (Eof_Error_Stream_f | Reset_Eof_Stream_f | Push_Eof_Stream_f);
598 if (!IsVarTerm(t2) && !(isatom(t2))) {
601 if (flags & Eof_Error_Stream_f) {
602 return Yap_unify(t2, TermError);
604 if (flags & Reset_Eof_Stream_f) {
605 return Yap_unify(t2, TermReset);
607 return Yap_unify(t2, TermEOfCode);
610#define STREAM_PROPERTY_DEFS() \
611 PAR("alias", filler, STREAM_PROPERTY_ALIAS) \
612 , PAR("bom", filler, STREAM_PROPERTY_BOM), \
613 PAR("close_on_abort", filler, STREAM_PROPERTY_CLOSE_ON_ABORT), \
614 PAR("encoding", filler, STREAM_PROPERTY_ENCODING), \
615 PAR("end_of_stream", filler, STREAM_PROPERTY_END_OF_STREAM), \
616 PAR("eof_action", filler, STREAM_PROPERTY_EOF_ACTION), \
617 PAR("file_name", filler, STREAM_PROPERTY_FILE_NAME), \
618 PAR("file_no", filler, STREAM_PROPERTY_FILE_NO), \
619 PAR("input", ok, STREAM_PROPERTY_INPUT), \
620 PAR("line_count", ok, STREAM_PROPERTY_LINE_COUNT), \
621 PAR("line_number", ok, STREAM_PROPERTY_LINE_NUMBER), \
622 PAR("mode", filler, STREAM_PROPERTY_MODE), \
623 PAR("output", filler, STREAM_PROPERTY_OUTPUT), \
624 PAR("position", isatom, STREAM_PROPERTY_POSITION), \
625 PAR("reposition", filler, STREAM_PROPERTY_REPOSITION), \
626 PAR("representation_errors", filler, \
627 STREAM_PROPERTY_REPRESENTATION_ERRORS), \
628 PAR("type", filler, STREAM_PROPERTY_TYPE), \
629 PAR("tty", filler, STREAM_PROPERTY_TTY), \
630 PAR(NULL, ok, STREAM_PROPERTY_END)
632#define PAR(x, y, z) z
634typedef enum stream_property_enum_choices {
635 STREAM_PROPERTY_DEFS()
636} stream_property_choices_t;
640#define PAR(x, y, z) \
643static const param_t stream_property_defs[] = {STREAM_PROPERTY_DEFS()};
646static bool do_stream_property(
int sno,
647 xarg *args USES_REGS) {
648 stream_property_choices_t i;
651 for (i = 0; i < STREAM_PROPERTY_END; i++) {
654 case STREAM_PROPERTY_ALIAS: {
655 Term ta = args[STREAM_PROPERTY_ALIAS].tvalue;
656 rc = rc & Yap_FetchStreamAlias(sno, ta PASS_REGS);
658 case STREAM_PROPERTY_BOM:
659 rc = rc && has_bom(sno, args[STREAM_PROPERTY_BOM].tvalue PASS_REGS);
661 case STREAM_PROPERTY_CLOSE_ON_ABORT:
664 sno, args[STREAM_PROPERTY_CLOSE_ON_ABORT].tvalue PASS_REGS);
666 case STREAM_PROPERTY_ENCODING:
668 has_encoding(sno, args[STREAM_PROPERTY_ENCODING].tvalue PASS_REGS);
670 case STREAM_PROPERTY_END_OF_STREAM:
673 args[STREAM_PROPERTY_END_OF_STREAM].tvalue PASS_REGS);
675 case STREAM_PROPERTY_EOF_ACTION:
677 eof_action(sno, args[STREAM_PROPERTY_EOF_ACTION].tvalue PASS_REGS);
679 case STREAM_PROPERTY_FILE_NAME:
681 file_name(sno, args[STREAM_PROPERTY_FILE_NAME].tvalue PASS_REGS);
683 case STREAM_PROPERTY_FILE_NO:
684 rc = rc && file_no(sno, args[STREAM_PROPERTY_FILE_NO].tvalue PASS_REGS);
686 case STREAM_PROPERTY_INPUT:
687 rc = rc && is_input(sno PASS_REGS);
689 case STREAM_PROPERTY_LINE_NUMBER:
690 rc = rc && stream_line_number(
691 sno, args[STREAM_PROPERTY_LINE_NUMBER].tvalue PASS_REGS);
693 case STREAM_PROPERTY_LINE_COUNT:
694 rc = rc && stream_line_count(
695 sno, args[STREAM_PROPERTY_LINE_COUNT].tvalue PASS_REGS);
697 case STREAM_PROPERTY_MODE:
699 rc && stream_mode(sno, args[STREAM_PROPERTY_MODE].tvalue PASS_REGS);
701 case STREAM_PROPERTY_OUTPUT:
702 rc = rc && is_output(sno PASS_REGS);
704 case STREAM_PROPERTY_POSITION:
705 rc = rc && stream_position(
706 sno, args[STREAM_PROPERTY_POSITION].tvalue PASS_REGS);
708 case STREAM_PROPERTY_REPOSITION:
709 rc = rc && has_reposition(
710 sno, args[STREAM_PROPERTY_REPOSITION].tvalue PASS_REGS);
712 case STREAM_PROPERTY_REPRESENTATION_ERRORS:
714 representation_error(
716 args[STREAM_PROPERTY_REPRESENTATION_ERRORS].tvalue PASS_REGS);
718 case STREAM_PROPERTY_TYPE:
720 rc && stream_type(sno, args[STREAM_PROPERTY_TYPE].tvalue PASS_REGS);
722 case STREAM_PROPERTY_TTY:
723 rc = rc && stream_tty(sno, args[STREAM_PROPERTY_TTY].tvalue PASS_REGS);
725 case STREAM_PROPERTY_END:
727 Yap_ThrowError(DOMAIN_ERROR_SET_STREAM_OPTION, ARG1,
"bad option to stream_property/2" );
736static xarg *generate_property(
int sno, Term t2,
737 stream_property_choices_t p USES_REGS) {
738 if (p == STREAM_PROPERTY_INPUT)
739 Yap_unify(t2, MkAtomTerm(AtomInput));
740 else if (p == STREAM_PROPERTY_OUTPUT)
741 Yap_unify(t2, MkAtomTerm(AtomOutput));
743 Functor f = Yap_MkFunctor(Yap_LookupAtom(stream_property_defs[p].name), 1);
744 Yap_unify(t2, Yap_MkNewApplTerm(f, 1));
746 return Yap_ArgListToVector(t2, stream_property_defs, STREAM_PROPERTY_END,
747 NULL,DOMAIN_ERROR_STREAM_PROPERTY_OPTION);
750static Int cont_stream_property(USES_REGS1) {
753 int i = IntOfTerm(EXTRA_CBACK_ARG(2, 1));
754 stream_property_choices_t p = STREAM_PROPERTY_END;
756 Term t2 = Deref(ARG2);
757 Term t1 = Deref(ARG1);
760 p = IntOfTerm(EXTRA_CBACK_ARG(2, 2));
761 args = generate_property(i, t2, p++ PASS_REGS);
763 EXTRA_CBACK_ARG(2, 2) = MkIntTerm(p % STREAM_PROPERTY_END);
766 args = Yap_ArgListToVector(t2, stream_property_defs, STREAM_PROPERTY_END,NULL,
767 DOMAIN_ERROR_STREAM_PROPERTY_OPTION);
770 if (LOCAL_Error_TYPE != YAP_NO_ERROR) {
771 if (LOCAL_Error_TYPE == DOMAIN_ERROR_GENERIC_ARGUMENT)
772 LOCAL_Error_TYPE = DOMAIN_ERROR_STREAM_PROPERTY_OPTION;
773 Yap_ThrowError(LOCAL_Error_TYPE, t2, NULL);
778 LOCK(GLOBAL_Stream[i].streamlock);
779 if (IsAtomTerm(args[STREAM_PROPERTY_ALIAS].tvalue)) {
781 i = Yap_CheckAlias(AtomOfTerm(args[STREAM_PROPERTY_ALIAS].tvalue));
782 UNLOCK(GLOBAL_Stream[i].streamlock);
784 if (i < 0 || !Yap_unify(ARG1, Yap_MkStream(i))) {
790 LOCK(GLOBAL_Stream[i].streamlock);
791 rc = do_stream_property(i, args PASS_REGS);
792 UNLOCK(GLOBAL_Stream[i].streamlock);
793 if (!det && IsVarTerm(t1)) {
795 rc = Yap_unify(ARG1, Yap_MkStream(i));
796 if (p == STREAM_PROPERTY_END) {
798 LOCK(GLOBAL_StreamDescLock);
799 while (++i < MaxStreams && GLOBAL_Stream[i].status & Free_Stream_f) {
801 UNLOCK(GLOBAL_StreamDescLock);
802 if (i < MaxStreams) {
803 EXTRA_CBACK_ARG(2, 1) = MkIntTerm(i);
813 det = det || (p == STREAM_PROPERTY_END);
829static Int stream_property(USES_REGS1) {
830 Term t1 = Deref(ARG1);
831 Term t2 = Deref(ARG2);
836 EXTRA_CBACK_ARG(2, 1) = MkIntTerm(0);
837 EXTRA_CBACK_ARG(2, 2) = MkIntTerm(0);
838 if (!IsVarTerm(t1)) {
842 i = Yap_CheckStream(t1, Input_Stream_f | Output_Stream_f | Append_Stream_f,
845 UNLOCK(GLOBAL_Stream[i].streamlock);
847 Yap_ThrowError(DOMAIN_ERROR_STREAM, t1,
"bad stream descriptor");
849 Yap_ThrowError(DOMAIN_ERROR_STREAM, t1,
"bad stream descriptor");
852 EXTRA_CBACK_ARG(2, 1) = MkIntTerm(i);
854 return cont_stream_property(PASS_REGS1);
856 args = Yap_ArgListToVector(Deref(ARG2), stream_property_defs,
859 DOMAIN_ERROR_STREAM_PROPERTY_OPTION);
861 if (LOCAL_Error_TYPE != YAP_NO_ERROR) {
862 if (LOCAL_Error_TYPE == DOMAIN_ERROR_PROLOG_FLAG)
863 LOCAL_Error_TYPE = DOMAIN_ERROR_STREAM_PROPERTY_OPTION;
864 Yap_Error(LOCAL_Error_TYPE, ARG2, NULL);
867 UNLOCK(GLOBAL_Stream[i].streamlock);
870 if (do_stream_property(i, args PASS_REGS)) {
871 UNLOCK(GLOBAL_Stream[i].streamlock);
875 UNLOCK(GLOBAL_Stream[i].streamlock);
880 return cont_stream_property(PASS_REGS1);
884#define SET_STREAM_DEFS() \
885 PAR("alias", isatom, SET_STREAM_ALIAS) \
886 , PAR("buffer", booleanFlag, SET_STREAM_BUFFER), \
887 PAR("buffer_size", nat, SET_STREAM_BUFFER_SIZE), \
888 PAR("close_on_abort", booleanFlag, SET_STREAM_CLOSE_ON_ABORT), \
889 PAR("encoding", isatom, SET_STREAM_ENCODING), \
890 PAR("eof_action", isatom, SET_STREAM_EOF_ACTION), \
891 PAR("file_name", isatom, SET_STREAM_FILE_NAME), \
892 PAR("line_position", nat, SET_STREAM_LINE_POSITION), \
893 PAR("newline", filler, SET_STREAM_NEWLINE), \
894 PAR("record_position", isatom, SET_STREAM_RECORD_POSITION), \
895 PAR("representation_errors", isatom, SET_STREAM_REPRESENTATION_ERRORS), \
896 PAR("type", isatom, SET_STREAM_TYPE), \
897 PAR("tty", filler, SET_STREAM_TTY), PAR(NULL, ok, SET_STREAM_END)
899#define PAR(x, y, z) z
901typedef enum set_stream_enum_choices {
903} set_stream_enum_choices_t;
907#define PAR(x, y, z) \
910static const param_t set_stream_defs[] = {SET_STREAM_DEFS()};
913static bool do_set_stream(
int sno,
914 Term opts USES_REGS) {
916 set_stream_enum_choices_t i;
919 args = Yap_ArgListToVector(opts, set_stream_defs, SET_STREAM_END,
920 NULL,DOMAIN_ERROR_SET_STREAM_OPTION);
922 if (LOCAL_Error_TYPE != YAP_NO_ERROR) {
923 if (LOCAL_Error_TYPE == DOMAIN_ERROR_GENERIC_ARGUMENT)
924 LOCAL_Error_TYPE = DOMAIN_ERROR_SET_STREAM_OPTION;
925 Yap_Error(LOCAL_Error_TYPE, opts, NULL);
927 UNLOCK(GLOBAL_Stream[sno].streamlock);
930 for (i = 0; i < SET_STREAM_END; i++) {
932 Term t = args[i].tvalue;
934 case SET_STREAM_ALIAS:
935 rc = rc && Yap_AddAlias(AtomOfTerm(t), sno);
937 case SET_STREAM_BUFFER:
938 rc = rc && SetBuffering(sno, AtomOfTerm(t));
940 case SET_STREAM_BUFFER_SIZE:
941 rc = rc && SetBuffer(sno, IntegerOfTerm(t));
943 case SET_STREAM_CLOSE_ON_ABORT:
946 sno, (args[SET_STREAM_CLOSE_ON_ABORT].tvalue == TermTrue));
948 case SET_STREAM_ENCODING: {
949 Term t2 = args[SET_STREAM_ENCODING].tvalue;
950 Atom atEnc = AtomOfTerm(t2);
951 GLOBAL_Stream[sno].encoding =
952 enc_id(atEnc->StrOfAE, (GLOBAL_Stream[sno].status & HAS_BOM_f
953 ? GLOBAL_Stream[sno].encoding
955 Yap_DefaultStreamOps(GLOBAL_Stream + sno);
957 case SET_STREAM_EOF_ACTION: {
958 Term t2 = args[SET_STREAM_EOF_ACTION].tvalue;
959 if (t2 == TermError) {
960 GLOBAL_Stream[sno].status |= Eof_Error_Stream_f;
961 GLOBAL_Stream[sno].status &= ~Reset_Eof_Stream_f;
962 }
else if (t2 == TermReset) {
963 GLOBAL_Stream[sno].status &= ~Eof_Error_Stream_f;
964 GLOBAL_Stream[sno].status |= Reset_Eof_Stream_f;
965 }
else if (t2 == TermEOfCode) {
966 GLOBAL_Stream[sno].status &= ~Eof_Error_Stream_f;
967 GLOBAL_Stream[sno].status &= ~Reset_Eof_Stream_f;
969 LOCAL_Error_TYPE = DOMAIN_ERROR_OUT_OF_RANGE;
970 LOCAL_ErrorMessage =
"in set_stream/2:eof_action";
974 case SET_STREAM_FILE_NAME:
975 GLOBAL_Stream[sno].user_name = args[SET_STREAM_FILE_NAME].tvalue;
977 case SET_STREAM_LINE_POSITION:
978 GLOBAL_Stream[sno].charcount =
979 GLOBAL_Stream[sno].linestart +
980 IntegerOfTerm(args[SET_STREAM_FILE_NAME].tvalue);
982 case SET_STREAM_NEWLINE:
985 case SET_STREAM_RECORD_POSITION:
986 if (args[SET_STREAM_RECORD_POSITION].tvalue == TermTrue)
987 GLOBAL_Stream[sno].status |= Seekable_Stream_f;
989 GLOBAL_Stream[sno].status &= ~Seekable_Stream_f;
991 case SET_STREAM_REPRESENTATION_ERRORS: {
992 Term t2 = args[SET_STREAM_EOF_ACTION].tvalue;
994 GLOBAL_Stream[sno].status |= RepError_Xml_f;
995 GLOBAL_Stream[sno].status &= ~RepError_Prolog_f;
996 }
else if (t2 == TermError) {
997 GLOBAL_Stream[sno].status &= ~RepError_Xml_f;
998 GLOBAL_Stream[sno].status |= RepError_Prolog_f;
999 }
else if (t2 == TermEOfCode) {
1000 GLOBAL_Stream[sno].status &= ~RepError_Xml_f;
1001 GLOBAL_Stream[sno].status |= RepError_Prolog_f;
1003 LOCAL_Error_TYPE = DOMAIN_ERROR_OUT_OF_RANGE;
1004 LOCAL_ErrorMessage =
"in set_stream/2:eof_action";
1008 case SET_STREAM_TYPE:
1009 rc &= stream_type(sno, args[SET_STREAM_TYPE].tvalue PASS_REGS);
1011 case SET_STREAM_TTY:
1012 rc &= stream_tty(sno, args[SET_STREAM_TTY].tvalue PASS_REGS);
1014 case SET_STREAM_END:
1021 UNLOCK(GLOBAL_Stream[sno].streamlock);
1025static Int set_stream(USES_REGS1) {
1027 Yap_CheckStream(ARG1, Input_Stream_f | Output_Stream_f | Append_Stream_f,
1028 "set_stream_position/2");
1032 return do_set_stream(sno, Deref(ARG2) PASS_REGS);
1039void Yap_CloseStreams(
void) {
1043 for (sno = 3; sno < MaxStreams; ++sno) {
1044 if (GLOBAL_Stream[sno].status & Free_Stream_f)
1055void Yap_CloseTemporaryStreams(
int min) {
1059 for (sno = min+1; sno < MaxStreams; ++sno) {
1060 if (GLOBAL_Stream[sno].status & Free_Stream_f)
1062 if (GLOBAL_Stream[sno].status & (CloseOnException_Stream_f))
1067static void CloseStream(
int sno) {
1077 if ((me = GLOBAL_Stream[sno].
vfs) != NULL &&
1078 GLOBAL_Stream[sno].file == NULL) {
1082 GLOBAL_Stream[sno].vfs = NULL;
1083 }
else if (GLOBAL_Stream[sno].file &&
1084 (GLOBAL_Stream[sno].status & Popen_Stream_f)) {
1085 pclose(GLOBAL_Stream[sno].file);
1086 }
else if (GLOBAL_Stream[sno].file &&
1087 !(GLOBAL_Stream[sno].status & (Null_Stream_f | Socket_Stream_f |
1088 InMemory_Stream_f | Pipe_Stream_f)))
1089 fclose(GLOBAL_Stream[sno].file);
1091 else if (GLOBAL_Stream[sno].status & (Socket_Stream_f)) {
1092 Yap_CloseSocket(GLOBAL_Stream[sno].u.socket.fd,
1093 GLOBAL_Stream[sno].u.socket.flags,
1094 GLOBAL_Stream[sno].u.socket.domain);
1097 else if (GLOBAL_Stream[sno].status & Pipe_Stream_f) {
1098 close(GLOBAL_Stream[sno].u.pipe.fd);
1099 }
else if (GLOBAL_Stream[sno].status & (InMemory_Stream_f)) {
1100 Yap_CloseMemoryStream(sno);
1102 Yap_ReleaseStream(sno);
1112void Yap_CloseStream__(
const char *file,
1113 const char *
function,
int lineno,
1118void Yap_ReleaseStream(
int sno) {
1120 GLOBAL_Stream[sno].status = Free_Stream_f;
1121 GLOBAL_Stream[sno].user_name = 0;
1123 GLOBAL_Stream[sno].vfs = NULL;
1124 GLOBAL_Stream[sno].file = NULL;
1126 if (LOCAL_c_input_stream == sno) {
1127 LOCAL_c_input_stream = Yap_FindStreamForAlias(AtomUserIn);
1129 if (LOCAL_c_output_stream == sno) {
1130 LOCAL_c_output_stream = Yap_FindStreamForAlias(AtomUserOut);
1132 if (LOCAL_c_error_stream == sno) {
1133 LOCAL_c_error_stream = Yap_FindStreamForAlias(AtomUserErr);
1149static Int current_input(USES_REGS1) {
1150 Term t1 = Deref(ARG1);
1151 if (IsVarTerm(t1)) {
1152 Term t = Yap_MkStream(LOCAL_c_input_stream);
1153 YapBind(VarOfTerm(t1), t);
1155 }
else if (!IsApplTerm(t1) || FunctorOfTerm(t1) != FunctorStream ||
1156 !IsIntTerm((t1 = ArgOfTerm(1, t1)))) {
1157 Yap_Error(DOMAIN_ERROR_STREAM, t1,
"current_input/1");
1160 return LOCAL_c_input_stream == IntOfTerm(t1);
1164bool Yap_SetInputStream(Term sd) {
1165 int sno = Yap_CheckStream(sd, Input_Stream_f,
"set_input/1");
1168 UNLOCK(GLOBAL_Stream[sno].streamlock);
1181static Int set_input(USES_REGS1) {
1182 return Yap_SetInputStream(ARG1);
1193static Int current_output(USES_REGS1) {
1194 Term t1 = Deref(ARG1);
1195 if (IsVarTerm(t1)) {
1196 Term t = Yap_MkStream(LOCAL_c_output_stream);
1197 YapBind(VarOfTerm(t1), t);
1199 }
else if (!IsApplTerm(t1) || FunctorOfTerm(t1) != FunctorStream ||
1200 !IsIntTerm((t1 = ArgOfTerm(1, t1)))) {
1201 Yap_Error(DOMAIN_ERROR_STREAM, t1,
"current_output/1");
1204 return (LOCAL_c_output_stream == IntOfTerm(t1));
1216static Int current_error(USES_REGS1) {
1217 Term t1 = Deref(ARG1);
1218 if (IsVarTerm(t1)) {
1219 Term t = Yap_MkStream(LOCAL_c_error_stream);
1220 YapBind(VarOfTerm(t1), t);
1222 }
else if (!IsApplTerm(t1) || FunctorOfTerm(t1) != FunctorStream ||
1223 !IsIntTerm((t1 = ArgOfTerm(1, t1)))) {
1224 Yap_Error(DOMAIN_ERROR_STREAM, t1,
"current_error/1");
1227 return (LOCAL_c_error_stream == IntOfTerm(t1));
1231bool Yap_SetOutputStream(Term sd) {
1233 Yap_CheckStream(sd, Output_Stream_f | Append_Stream_f,
"set_output/2");
1236 UNLOCK(GLOBAL_Stream[sno].streamlock);
1241bool Yap_SetErrorStream(Term sd) {
1243 Yap_CheckStream(sd, Output_Stream_f | Append_Stream_f,
"set_error/2");
1246 LOCAL_c_error_stream = sno;
1247 UNLOCK(GLOBAL_Stream[sno].streamlock);
1260static Int set_error(USES_REGS1) {
1261 return Yap_SetErrorStream(ARG1);
1274static Int set_output(USES_REGS1) {
1275 return Yap_SetOutputStream(Deref(ARG1));
1278static Int p_user_file_name(USES_REGS1) {
1281 Yap_CheckStream(Deref(ARG1), Input_Stream_f | Output_Stream_f | Append_Stream_f,
1282 "user_file_name/2");
1285 tout = Yap_StreamUserName(sno);
1286 UNLOCK(GLOBAL_Stream[sno].streamlock);
1287 return (Yap_unify_constant(ARG2, tout));
1290static Int p_file_name(USES_REGS1) {
1292 int sno = Yap_CheckStream(
1293 Deref(ARG1), Input_Stream_f | Output_Stream_f | Append_Stream_f,
"file_name/2");
1297 if (GLOBAL_Stream[sno].status & Socket_Stream_f)
1298 tout = MkAtomTerm(AtomSocket);
1301 if (GLOBAL_Stream[sno].status & Pipe_Stream_f)
1302 tout = MkAtomTerm(AtomPipe);
1303 else if (GLOBAL_Stream[sno].status & InMemory_Stream_f)
1304 tout = MkAtomTerm(AtomCharsio);
1306 tout = MkAtomTerm(GLOBAL_Stream[sno].name);
1307 UNLOCK(GLOBAL_Stream[sno].streamlock);
1308 return Yap_unify_constant(ARG2, tout);
1311static Int line_count(USES_REGS1) {
1314 Yap_CheckStream(Deref(ARG1), Input_Stream_f | Output_Stream_f | Append_Stream_f,
1315 "current_line_number/2");
1318 tout = lineCount(sno);
1319 return (Yap_unify_constant(ARG2, tout));
1322static Int line_position(USES_REGS1) {
1325 Yap_CheckStream(Deref(ARG1), Input_Stream_f | Output_Stream_f | Append_Stream_f,
1329 if (GLOBAL_Stream[sno].status & Tty_Stream_f) {
1332 Atom my_stream = GLOBAL_Stream[sno].name;
1333 tout = MkIntTerm(0);
1335 tout = MkIntTerm((1+GLOBAL_Stream[sno].charcount )-
1336 GLOBAL_Stream[sno].linestart) ;
1337 UNLOCK(GLOBAL_Stream[sno].streamlock);
1338 return (Yap_unify_constant(ARG2, tout));
1341static Int character_count(USES_REGS1) {
1344 Yap_CheckStream(ARG1, Input_Stream_f | Output_Stream_f | Append_Stream_f,
1345 "character_count/2");
1348 if (GLOBAL_Stream[sno].status & Tty_Stream_f) {
1351 Atom my_stream = GLOBAL_Stream[sno].name;
1352 for (i = 0; i < MaxStreams; i++) {
1353 if (!(GLOBAL_Stream[i].status & Free_Stream_f) &&
1354 GLOBAL_Stream[i].name == my_stream)
1355 no += GLOBAL_Stream[i].charcount;
1357 tout = MkIntTerm(no);
1358 }
else if (GLOBAL_Stream[sno].status & Null_Stream_f)
1359 tout = MkIntTerm(GLOBAL_Stream[sno].charcount);
1361 tout = MkIntTerm(ftell(GLOBAL_Stream[sno].file));
1362 UNLOCK(GLOBAL_Stream[sno].streamlock);
1363 return (Yap_unify_constant(ARG2, tout));
1367 p_show_stream_flags(USES_REGS1) {
1370 Yap_CheckStream(ARG1, Input_Stream_f | Output_Stream_f | Append_Stream_f,
1371 "stream_property/2");
1374 tout = MkIntTerm(GLOBAL_Stream[sno].status);
1375 UNLOCK(GLOBAL_Stream[sno].streamlock);
1376 return (Yap_unify(ARG2, tout));
1379Term Yap_StreamPosition(
int sno) {
return StreamPosition(sno); }
1381static Int p_show_stream_position(
1385 Yap_CheckStream(ARG1, Input_Stream_f | Output_Stream_f | Append_Stream_f,
1386 "stream_position/2");
1389 tout = StreamPosition(sno);
1390 UNLOCK(GLOBAL_Stream[sno].streamlock);
1391 return Yap_unify(ARG2, tout);
1395 set_stream_position(USES_REGS1) {
1399 Yap_CheckStream(ARG1, Input_Stream_f | Output_Stream_f | Append_Stream_f,
1400 "set_stream_position/2");
1405 if (IsVarTerm(tin)) {
1406 UNLOCK(GLOBAL_Stream[sno].streamlock);
1407 Yap_Error(INSTANTIATION_ERROR, tin,
"set_stream_position/2");
1409 }
else if (!(IsApplTerm(tin))) {
1410 UNLOCK(GLOBAL_Stream[sno].streamlock);
1411 Yap_Error(DOMAIN_ERROR_STREAM_POSITION, tin,
"set_stream_position/2");
1414 if (FunctorOfTerm(tin) == FunctorStreamPos) {
1415 if (IsVarTerm(tp = ArgOfTerm(1, tin))) {
1416 UNLOCK(GLOBAL_Stream[sno].streamlock);
1417 Yap_Error(INSTANTIATION_ERROR, tp,
"set_stream_position/2");
1419 }
else if (!IsIntTerm(tp)) {
1420 UNLOCK(GLOBAL_Stream[sno].streamlock);
1421 Yap_Error(DOMAIN_ERROR_STREAM_POSITION, tin,
"set_stream_position/2");
1424 if (!(GLOBAL_Stream[sno].status & Seekable_Stream_f)) {
1425 UNLOCK(GLOBAL_Stream[sno].streamlock);
1426 Yap_Error(PERMISSION_ERROR_REPOSITION_STREAM, ARG1,
1427 "set_stream_position/2");
1430 char_pos = IntOfTerm(tp);
1431 if (IsVarTerm(tp = ArgOfTerm(2, tin))) {
1432 UNLOCK(GLOBAL_Stream[sno].streamlock);
1433 Yap_Error(INSTANTIATION_ERROR, tp,
"set_stream_position/2");
1435 }
else if (!IsIntTerm(tp)) {
1436 UNLOCK(GLOBAL_Stream[sno].streamlock);
1437 Yap_Error(DOMAIN_ERROR_STREAM_POSITION, tin,
"set_stream_position/2");
1440 GLOBAL_Stream[sno].charcount = char_pos;
1441 if (IsVarTerm(tp = ArgOfTerm(3, tin))) {
1442 UNLOCK(GLOBAL_Stream[sno].streamlock);
1443 Yap_Error(INSTANTIATION_ERROR, tp,
"set_stream_position/2");
1445 }
else if (!IsIntTerm(tp)) {
1446 UNLOCK(GLOBAL_Stream[sno].streamlock);
1447 Yap_Error(DOMAIN_ERROR_STREAM_POSITION, tin,
"set_stream_position/2");
1450 int linecount = IntOfTerm(tp);
1451 GLOBAL_Stream[sno].linestart = char_pos-linecount;
1452 if (fseek(GLOBAL_Stream[sno].file, (
long)(char_pos), 0) == -1) {
1453 UNLOCK(GLOBAL_Stream[sno].streamlock);
1454 Yap_Error(SYSTEM_ERROR_INTERNAL, tp,
1455 "fseek failed for set_stream_position/2");
1458 GLOBAL_Stream[sno].stream_getc = PlGetc;
1459 }
else if (FunctorOfTerm(tin) == FunctorStreamEOS) {
1460 if (IsVarTerm(tp = ArgOfTerm(1, tin))) {
1461 UNLOCK(GLOBAL_Stream[sno].streamlock);
1462 Yap_Error(INSTANTIATION_ERROR, tp,
"set_stream_position/2");
1464 }
else if (tp != MkAtomTerm(AtomAt)) {
1465 UNLOCK(GLOBAL_Stream[sno].streamlock);
1466 Yap_Error(DOMAIN_ERROR_STREAM_POSITION, tin,
"set_stream_position/2");
1469 if (!(GLOBAL_Stream[sno].status & Seekable_Stream_f)) {
1470 UNLOCK(GLOBAL_Stream[sno].streamlock);
1471 PlIOError(PERMISSION_ERROR_REPOSITION_STREAM, ARG1,
1472 "set_stream_position/2");
1475 if (GLOBAL_Stream[sno].
vfs) {
1476 if (GLOBAL_Stream[sno].
vfs->
seek &&
1477 GLOBAL_Stream[sno].vfs->seek(sno, 0L, SEEK_END) == -1) {
1478 UNLOCK(GLOBAL_Stream[sno].streamlock);
1479 PlIOError(SYSTEM_ERROR_INTERNAL, tp,
1480 "fseek failed for set_stream_position/2: %s",
1484 }
else if (fseek(GLOBAL_Stream[sno].file, 0L, SEEK_END) == -1) {
1485 UNLOCK(GLOBAL_Stream[sno].streamlock);
1486 PlIOError(SYSTEM_ERROR_INTERNAL, tp,
1487 "fseek failed for set_stream_position/2: %s", strerror(errno));
1490 GLOBAL_Stream[sno].stream_getc = PlGetc;
1492 GLOBAL_Stream[sno].linestart = 0;
1493 GLOBAL_Stream[sno].linecount = 1;
1494 GLOBAL_Stream[sno].charcount = 0;
1496 UNLOCK(GLOBAL_Stream[sno].streamlock);
1502static Int p_stream_select(USES_REGS1) {
1503 Term t1 = Deref(ARG1), t2;
1504 fd_set readfds, writefds, exceptfds;
1505 struct timeval timeout, *ptime;
1512 Term tout = TermNil, ti, Head;
1514 if (IsVarTerm(t1)) {
1515 Yap_Error(INSTANTIATION_ERROR, t1,
"stream_select/3");
1518 if (!IsPairTerm(t1)) {
1519 Yap_Error(TYPE_ERROR_LIST, t1,
"stream_select/3");
1524 FD_ZERO(&exceptfds);
1526 while (ti != TermNil) {
1534 Head = HeadOfTerm(ti);
1535 sno = Yap_CheckStream(Head, Input_Stream_f,
"stream_select/3");
1538 fd = GetStreamFd(sno);
1539 FD_SET(fd, &readfds);
1540 UNLOCK(GLOBAL_Stream[sno].streamlock);
1543 ti = TailOfTerm(ti);
1546 if (IsVarTerm(t2)) {
1547 Yap_Error(INSTANTIATION_ERROR, t2,
"stream_select/3");
1550 if (IsAtomTerm(t2)) {
1551 if (t2 == MkAtomTerm(AtomOff)) {
1555 Yap_Error(DOMAIN_ERROR_TIMEOUT_SPEC, t1,
"stream_select/3");
1561 if (!IsApplTerm(t2) || FunctorOfTerm(t2) != FunctorModule) {
1562 Yap_Error(DOMAIN_ERROR_TIMEOUT_SPEC, t2,
"stream_select/3");
1565 t21 = ArgOfTerm(1, t2);
1566 if (IsVarTerm(t21)) {
1567 Yap_Error(INSTANTIATION_ERROR, t2,
"stream_select/3");
1570 if (!IsIntegerTerm(t21)) {
1571 Yap_Error(DOMAIN_ERROR_TIMEOUT_SPEC, t2,
"stream_select/3");
1574 timeout.tv_sec = IntegerOfTerm(t21);
1575 if (timeout.tv_sec < 0) {
1576 Yap_Error(DOMAIN_ERROR_TIMEOUT_SPEC, t2,
"stream_select/3");
1579 t22 = ArgOfTerm(2, t2);
1580 if (IsVarTerm(t22)) {
1581 Yap_Error(INSTANTIATION_ERROR, t2,
"stream_select/3");
1584 if (!IsIntegerTerm(t22)) {
1585 Yap_Error(DOMAIN_ERROR_TIMEOUT_SPEC, t2,
"stream_select/3");
1588 timeout.tv_usec = IntegerOfTerm(t22);
1589 if (timeout.tv_usec < 0) {
1590 Yap_Error(DOMAIN_ERROR_TIMEOUT_SPEC, t2,
"stream_select/3");
1596 if (select(fdmax + 1, &readfds, &writefds, &exceptfds, ptime) < 0) {
1598 Yap_Error(SYSTEM_ERROR_INTERNAL, TermNil,
"stream_select/3 (select: %s)",
1601 Yap_Error(SYSTEM_ERROR_INTERNAL, TermNil,
"stream_select/3 (select)");
1604 while (t1 != TermNil) {
1608 Head = HeadOfTerm(t1);
1609 sno = Yap_CheckStream(Head, Input_Stream_f,
"stream_select/3");
1610 fd = GetStreamFd(sno);
1611 if (FD_ISSET(fd, &readfds))
1612 tout = MkPairTerm(Head, tout);
1614 tout = MkPairTerm(TermNil, tout);
1615 UNLOCK(GLOBAL_Stream[sno].streamlock);
1616 t1 = TailOfTerm(t1);
1619 return (Yap_unify(ARG3, tout));
1623Int Yap_StreamToFileNo(Term t) {
1625 Yap_CheckStream(t, (Input_Stream_f | Output_Stream_f),
"StreamToFileNo");
1626 if (GLOBAL_Stream[sno].status & Pipe_Stream_f) {
1627 UNLOCK(GLOBAL_Stream[sno].streamlock);
1628 return (GLOBAL_Stream[sno].u.pipe.fd);
1630 }
else if (GLOBAL_Stream[sno].status & Socket_Stream_f) {
1631 UNLOCK(GLOBAL_Stream[sno].streamlock);
1632 return (GLOBAL_Stream[sno].u.socket.fd);
1634 }
else if (GLOBAL_Stream[sno].status & (Null_Stream_f)) {
1635 UNLOCK(GLOBAL_Stream[sno].streamlock);
1638 UNLOCK(GLOBAL_Stream[sno].streamlock);
1639 return (fileno(GLOBAL_Stream[sno].file));
1643static Int p_stream(USES_REGS1) {
1644 Term in = Deref(ARG1);
1648 return (Yap_CheckAlias(AtomOfTerm(in)) >= 0);
1650 return (FunctorOfTerm(in) == FunctorStream);
1654FILE *Yap_FileDescriptorFromStream(Term t) {
1655 int sno = Yap_CheckStream(t, Input_Stream_f | Output_Stream_f,
1656 "FileDescriptorFromStream");
1660 if (GLOBAL_Stream[sno].status &
1661 (Null_Stream_f | Socket_Stream_f | Pipe_Stream_f | Free_Stream_f))
1664 rc = GLOBAL_Stream[sno].file;
1665 UNLOCK(GLOBAL_Stream[sno].streamlock);
1669void Yap_InitBackIO(
void) {
1670 Yap_InitCPredBack(
"stream_property", 2, 2, stream_property,
1671 cont_stream_property, SafePredFlag | SyncPredFlag);
1674void Yap_InitIOStreams(
void) {
1675 Yap_InitCPred(
"$stream_flags", 2, stream_flags,
1676 SafePredFlag | SyncPredFlag | HiddenPredFlag);
1677 Yap_InitCPred(
"$check_stream", 2, p_check_stream,
1678 SafePredFlag | SyncPredFlag | HiddenPredFlag);
1679 Yap_InitCPred(
"$check_stream", 1, p_check_if_stream,
1680 SafePredFlag | SyncPredFlag | HiddenPredFlag | HiddenPredFlag);
1681 Yap_InitCPred(
"line_position", 2, line_position,
1682 SafePredFlag | SyncPredFlag | HiddenPredFlag);
1683 Yap_InitCPred(
"character_count", 2, character_count,
1684 SafePredFlag | SyncPredFlag | HiddenPredFlag);
1685 Yap_InitCPred(
"$show_stream_flags", 2, p_show_stream_flags,
1686 SafePredFlag | SyncPredFlag | HiddenPredFlag);
1687 Yap_InitCPred(
"$user_file_name", 2, p_user_file_name,
1688 SafePredFlag | SyncPredFlag),
1689 Yap_InitCPred(
"$file_name", 2, p_file_name, SafePredFlag | SyncPredFlag),
1690 Yap_InitCPred(
"current_input", 1, current_input,
1691 SafePredFlag | SyncPredFlag);
1692 Yap_InitCPred(
"current_output", 1, current_output,
1693 SafePredFlag | SyncPredFlag);
1694 Yap_InitCPred(
"current_error", 1, current_error,
1695 SafePredFlag | SyncPredFlag);
1696 Yap_InitCPred(
"set_input", 1, set_input, SafePredFlag | SyncPredFlag);
1697 Yap_InitCPred(
"set_output", 1, set_output, SafePredFlag | SyncPredFlag);
1698 Yap_InitCPred(
"set_error", 1, set_error, SafePredFlag | SyncPredFlag);
1699 Yap_InitCPred(
"$stream", 1, p_stream, SafePredFlag | TestPredFlag);
1700 Yap_InitCPred(
"$clear_input", 1, clear_input, SafePredFlag | TestPredFlag);
1703 Yap_InitCPred(
"stream_select", 3, p_stream_select,
1704 SafePredFlag | SyncPredFlag);
1706 Yap_InitCPred(
"line_count", 2, line_count, SafePredFlag | SyncPredFlag);
1707 Yap_InitCPred(
"$show_stream_position", 2, p_show_stream_position,
1708 SafePredFlag | SyncPredFlag | HiddenPredFlag);
1709 Yap_InitCPred(
"set_stream_position", 2, set_stream_position,
1710 SafePredFlag | SyncPredFlag);
1711 Yap_InitCPred(
"set_stream", 2, set_stream, SafePredFlag | SyncPredFlag);
void Yap_SetAlias(Atom arg, int sno)
set arg as an alias to sno, but first check if not done before
bool Yap_DeleteAliases(int sno)
purge all aliases for stream sno
void * Malloc(size_t sz USES_REGS)
allocate a temporary text block
@ encoding
support for coding systens, YAP relies on UTF-8 internally
int64_t(* seek)(int sno, int64_t offset, int whence)
flush a stream
bool(* close)(int sno)
open an object