18static char SccsId[] =
"%W% %G%";
74#if HAVE_SYS_SELECT_H && !_MSC_VER && !defined(__MINGW32__)
76#include <sys/select.h>
103#define strncat(X, Y, Z) strcat(X, Y)
106#define strncpy(X, Y, Z) strcpy(X, Y)
108#if _MSC_VER || defined(__MINGW32__)
114#define S_ISDIR(x) (((x)&_S_IFDIR) == _S_IFDIR)
122static int get_wchar_from_file(
int);
129 char *Yap_VF(
const char *path) {
132 out = (
char *)malloc(MAX_PATH + 1);
133 if (GLOBAL_cwd == NULL || GLOBAL_cwd[0] == 0 ||
134 !Yap_IsAbsolutePath(path,
false)) {
137 strcpy(out, GLOBAL_cwd);
143char *Yap_VFAlloc(
const char *path) {
146 out = (
char *)malloc(MAX_PATH + 1);
147 if (GLOBAL_cwd == NULL || GLOBAL_cwd[0] == 0 ||
148 !Yap_IsAbsolutePath(path,
false)) {
151 strcpy(out, GLOBAL_cwd);
159 if (s->status & Eof_Error_Stream_f) {
162 Yap_ThrowError(PERMISSION_ERROR_INPUT_PAST_END_OF_STREAM, MkAtomTerm(name),
165 }
else if (s->status & Reset_Eof_Stream_f) {
166 s->status &= ~Push_Eof_Stream_f;
171 Yap_DefaultStreamOps(s);
173 s->status &= ~Eof_Stream_f;
177 s->status |= Past_Eof_Stream_f;
183static int EOFWGetc(
int sno) {
186 if (s->status & Push_Eof_Stream_f) {
188 s->status &= ~Push_Eof_Stream_f;
192 Yap_DefaultStreamOps(s);
198static int EOFGetc(
int sno) {
201 if (s->status & Push_Eof_Stream_f) {
203 s->status &= ~Push_Eof_Stream_f;
208 Yap_DefaultStreamOps(s);
214static void unix_upd_stream_info(
StreamDesc *s) {
215 if (s->status & InMemory_Stream_f) {
216 s->status |= Seekable_Stream_f;
220#if _MSC_VER || defined(__MINGW32__)
222 if (_isatty(_fileno(s->file))) {
223 s->status |= Tty_Stream_f | Reset_Eof_Stream_f | Promptable_Stream_f;
225 setvbuf(s->file, NULL, _IONBF, 0);
230 else if (StdErrStream == s - GLOBAL_Stream) {
231 setvbuf(s->file, NULL, _IONBF, 0);
234 s->status |= Seekable_Stream_f;
242 if (s - Stream < 3) {
244 s->status |= Tty_Stream_f | Reset_Eof_Stream_f | Promptable_Stream_f;
253 filedes = fileno(s->file);
254 if (isatty(filedes)) {
257 int rc = ttyname_r(filedes,buf1, MAX_PATH - 1);
259 s->name = Yap_LookupAtom(buf1);
265 s->status |= Tty_Stream_f | Reset_Eof_Stream_f | Promptable_Stream_f;
272 s->status |= Seekable_Stream_f;
280 if (st->status & Eof_Stream_f) {
286 if (GLOBAL_CharConversionTable != NULL)
295 unix_upd_stream_info(st);
298 if (st->
vfs && !st->file) {
308 st->stream_putc = FilePutc;
310 if (st->status & Pipe_Stream_f) {
312 }
else if (st->status & InMemory_Stream_f) {
317 }
else if (st->status & Tty_Stream_f) {
321 if (st->status & (Promptable_Stream_f)) {
325 else if (st->file != NULL && 0 && !(st->status & InMemory_Stream_f)) {
335 if (st->status & Readline_Stream_f) {
355 Yap_DefaultStreamOps(s);
358static void InitStdStream(
int sno, SMALLUNSGN flags, FILE *file,
VFS_t *vfsp) {
368 INIT_LOCK(s->streamlock);
370 unix_upd_stream_info(s);
378 s->user_name = TermUserIn;
381 s->user_name = TermUserOut;
384 s->user_name = TermUserErr;
387 s->user_name = MkAtomTerm(s->name);
389 s->status |= Tty_Stream_f | Promptable_Stream_f;
392 Yap_DefaultStreamOps(s);
394 if (s->status & Tty_Stream_f && sno == 0) {
403void Yap_InitStdStream(
int sno,
unsigned int flags, FILE *file,
VFS_t *vfsp) {
404 InitStdStream(sno, flags, file, vfsp);
407Term Yap_StreamUserName(
int sno) {
410 if (s->user_name != 0L) {
411 return (s->user_name);
413 if ((atname = StreamName(sno)))
418static void InitStdStreams(
void) {
420 if (LOCAL_sockets_io) {
421 InitStdStream(StdInStream, Input_Stream_f, NULL, NULL);
422 InitStdStream(StdOutStream, Output_Stream_f, NULL, NULL);
423 InitStdStream(StdErrStream, Output_Stream_f, NULL, NULL);
425 InitStdStream(StdInStream, Input_Stream_f, stdin, NULL);
426 InitStdStream(StdOutStream, Output_Stream_f, stdout, NULL);
427 InitStdStream(StdErrStream, Output_Stream_f, stderr, NULL);
429 GLOBAL_Stream[StdInStream].name = Yap_LookupAtom(
"user_input");
430 GLOBAL_Stream[StdOutStream].name = Yap_LookupAtom(
"user_output");
431 GLOBAL_Stream[StdErrStream].name = Yap_LookupAtom(
"user_error");
433 if (GLOBAL_Stream[StdInStream].status & Tty_Stream_f &&
434 GLOBAL_Stream[StdOutStream].status & Tty_Stream_f &&
435 GLOBAL_Stream[StdErrStream].status & Tty_Stream_f && !Yap_Embedded) {
436 Yap_InitReadline(TermTrue);
439 LOCAL_c_input_stream = StdInStream;
440 LOCAL_c_output_stream = StdOutStream;
441 LOCAL_c_error_stream = StdErrStream;
444void Yap_InitStdStreams(
void) { InitStdStreams(); }
446Int PlIOError__(
const char *file,
const char *
function,
int lineno,
447 yap_error_number type, Term culprit, ...) {
449 type == RESOURCE_ERROR_MAX_STREAMS ) {
454 va_start(args, culprit);
455 format = va_arg(args,
char *);
457 vsnprintf(who, 1023, format, args);
467 memset(LOCAL_ActiveError, 0,
sizeof(*LOCAL_ActiveError));
468 Yap_SetGlobalVal(AtomZip, MkVarTerm());
474 UnixIOError__(
const char *file,
const char *
function,
int lineno,
475 int error, io_kind_t io_type, Term culprit, ...) {
480 yap_error_number e_type;
482 va_start(args, culprit);
483 format = va_arg(args,
char *);
485 vsnprintf(who, 1023, format, args);
495 case CREATE_DIRECTORY:
496 e_type = PERMISSION_ERROR_CREATE_DIRECTORY;
499 e_type = PERMISSION_ERROR_CREATE_DIRECTORY;
502 e_type = SYSTEM_ERROR_INTERNAL;
507 case CREATE_DIRECTORY:
508 e_type = EXISTENCE_ERROR_DIRECTORY;
511 e_type = EXISTENCE_ERROR_FILE;
514 e_type = SYSTEM_ERROR_INTERNAL;
519 case CREATE_DIRECTORY:
520 e_type = PERMISSION_ERROR_CREATE_DIRECTORY;
523 e_type = PERMISSION_ERROR_CREATE_FILE;
526 e_type = SYSTEM_ERROR_INTERNAL;
530 e_type = SYSTEM_ERROR_INTERNAL;
537 memset(LOCAL_ActiveError, 0,
sizeof(*LOCAL_ActiveError));
543static int eolflg = 1;
545static char my_line[200] = {0};
546static char *lp = my_line;
548FILE *curfile, *Yap_logfile;
554static void InTTYLine(
char *line) {
557 while ((ch = InKey()) !=
'\n' && ch !=
'\r')
568void Yap_DebugSetIFile(
char *fname) {
571 curfile = fopen(fname,
"r");
572 if (curfile == NULL) {
574 Yap_Warning(
"%% YAP open %s for input\n", fname);
578void Yap_DebugEndline() { *lp = 0; }
583 if (curfile != NULL) {
584 if (fgets(my_line, 200, curfile) == 0)
588 if (fgets(my_line, 200, stdin) == NULL) {
594 if ((ch = *lp++) == 0)
595 ch =
'\n', eolflg = 1;
596 if (Yap_Option[
'l' - 96])
597 putc(ch, Yap_logfile);
601int Yap_DebugPutc(FILE *s,
wchar_t ch) {
602 if (Yap_Option[
'l' - 96])
603 (void)putc(ch, Yap_logfile);
604 return (putc(ch, stderr));
607int Yap_DebugPuts(FILE *s,
const char *sch) {
608 if (Yap_Option[
'l' - 96])
609 (void)fputs(sch, Yap_logfile);
610 return fputs(sch, stderr);
613void Yap_DebugErrorPuts(
const char *s) { Yap_DebugPuts(stderr, s); }
615void Yap_DebugPlWrite(Term t) {
617 fprintf(stderr,
"NULL");
618 Yap_plwrite(t, GLOBAL_Stream + 2, 10, HR, 0, NULL);
621void Yap_DebugPlWriteln(Term t) {
624 fprintf(stderr,
"NULL");
625 Yap_plwrite(t, GLOBAL_Stream+LOCAL_c_error_stream , 10, HR, Handle_cyclics_f|Quote_illegal_f, NULL);
626 Yap_DebugPutc(GLOBAL_Stream[LOCAL_c_error_stream].file,
'.');
627 Yap_DebugPutc(GLOBAL_Stream[LOCAL_c_error_stream].file, 10);
630void Yap_DebugErrorPutc(
int c) {
632 Yap_DebugPutc(GLOBAL_Stream[LOCAL_c_error_stream].file, c);
635void Yap_DebugWriteIndicator(
PredEntry *ap) {
637 Term tmod = ap->ModuleOfPred;
641 Yap_DebugPlWrite(MkIntegerTerm(worker_id));
642 Yap_DebugPutc(stderr,
' ');
644 Yap_DebugPutc(stderr,
'>');
645 Yap_DebugPutc(stderr,
'\t');
646 Yap_DebugPlWrite(tmod);
647 Yap_DebugPutc(stderr,
':');
648 if (ap->ModuleOfPred == IDB_MODULE) {
649 Term t = Deref(ARG1);
652 }
else if (IsIntegerTerm(t)) {
656 Atom At = NameOfFunctor(f);
657 Yap_DebugPlWrite(MkAtomTerm(At));
658 Yap_DebugPutc(stderr,
'/');
659 Yap_DebugPlWrite(MkIntegerTerm(ArityOfFunctor(f)));
662 if (ap->ArityOfPE == 0) {
664 Yap_DebugPlWrite(MkAtomTerm(At));
667 Atom At = NameOfFunctor(f);
668 Yap_DebugPlWrite(MkAtomTerm(At));
669 Yap_DebugPutc(stderr,
'/');
670 Yap_DebugPlWrite(MkIntegerTerm(ArityOfFunctor(f)));
674 Yap_DebugPutc(stderr,
'\n');
678int FilePutc(
int sno,
int ch) {
691 count_output_char(ch, s);
695static int NullPutc(
int sno,
int ch) {
702 count_output_char(ch, s);
710 s->status |= Eof_Stream_f;
714 LOCAL_newline =
true;
720int post_process_read_wchar(
int ch,
size_t n,
StreamDesc *s) {
722 return post_process_weof(s);
725 if (GLOBAL_Option[1]) {
727 fprintf(stderr,
"%d %C\n", v, ch);
734 s->linestart = s->charcount;
736 if (!(s->status & Binary_Stream_f))
744 s->status |= Eof_Stream_f;
752void *Yap_RepStreamFromId(
int sno) {
return GLOBAL_Stream + (sno); }
765int EOFWPeek(
int sno) {
return EOFCHAR; }
772 return fgetc(s->file);
776static inline int get_wchar_from_file(
int sno) {
777 return post_process_read_wchar(fgetwc(GLOBAL_Stream[sno].file), 1,
778 GLOBAL_Stream + sno);
785static int handle_write_encoding_error(
int sno,
wchar_t ch) {
786 if (GLOBAL_Stream[sno].status & RepError_Xml_f) {
788 int i = ch, digits = 1;
789 GLOBAL_Stream[sno].stream_putc(sno,
'&');
790 GLOBAL_Stream[sno].stream_putc(sno,
'#');
796 GLOBAL_Stream[sno].stream_putc(sno, i / digits);
800 GLOBAL_Stream[sno].stream_putc(sno,
';');
802 }
else if (GLOBAL_Stream[sno].status & RepError_Prolog_f) {
804 GLOBAL_Stream[sno].stream_putc(sno,
'\\');
805 GLOBAL_Stream[sno].stream_putc(sno,
'u');
806 GLOBAL_Stream[sno].stream_putc(sno, ch >> 24);
807 GLOBAL_Stream[sno].stream_putc(sno, 256 & (ch >> 16));
808 GLOBAL_Stream[sno].stream_putc(sno, 256 & (ch >> 8));
809 GLOBAL_Stream[sno].stream_putc(sno, 256 & ch);
813 Yap_ThrowError(REPRESENTATION_ERROR_CHARACTER, MkIntegerTerm(ch),
814 "charater %ld cannot be encoded in stream %d",
815 (
unsigned long int)ch, sno);
820int put_wchar(
int sno,
wchar_t ch) {
822 switch (GLOBAL_Stream[sno].
encoding) {
824 return GLOBAL_Stream[sno].stream_putc(sno, ch);
827 return handle_write_encoding_error(sno, ch);
829 return GLOBAL_Stream[sno].stream_putc(sno, ch);
832 return handle_write_encoding_error(sno, ch);
834 return GLOBAL_Stream[sno].stream_putc(sno, ch);
836 char buf[MB_LEN_MAX];
840 memset((
void *)&mbstate, 0,
sizeof(mbstate_t));
841 if ((n = wcrtomb(buf, ch, &mbstate)) < 0) {
843 GLOBAL_Stream[sno].stream_putc(sno, ch);
848 for (i = 0; i < n; i++) {
849 GLOBAL_Stream[sno].stream_putc(sno, buf[i]);
855 GLOBAL_Stream[sno].stream_putc(sno, ch);
856 }
else if (ch < 0x800) {
857 GLOBAL_Stream[sno].stream_putc(sno, 0xC0 | ch >> 6);
858 GLOBAL_Stream[sno].stream_putc(sno, 0x80 | (ch & 0x3F));
859 }
else if (ch < 0x10000) {
860 GLOBAL_Stream[sno].stream_putc(sno, 0xE0 | ch >> 12);
861 GLOBAL_Stream[sno].stream_putc(sno, 0x80 | (ch >> 6 & 0x3F));
862 GLOBAL_Stream[sno].stream_putc(sno, 0x80 | (ch & 0x3F));
863 }
else if (ch < 0x200000) {
864 GLOBAL_Stream[sno].stream_putc(sno, 0xF0 | ch >> 18);
865 GLOBAL_Stream[sno].stream_putc(sno, 0x80 | (ch >> 12 & 0x3F));
866 GLOBAL_Stream[sno].stream_putc(sno, 0x80 | (ch >> 6 & 0x3F));
867 GLOBAL_Stream[sno].stream_putc(sno, 0x80 | (ch & 0x3F));
876 GLOBAL_Stream[sno].stream_putc(sno, (ch & 0xff));
877 GLOBAL_Stream[sno].stream_putc(sno, (ch >> 8));
881 uint16_t lead = LEAD_OFFSET + (ich >> 10);
882 uint16_t trail = 0xDC00 + (ich & 0x3FF);
884 GLOBAL_Stream[sno].stream_putc(sno, (trail & 0xff));
885 GLOBAL_Stream[sno].stream_putc(sno, (trail >> 8));
886 GLOBAL_Stream[sno].stream_putc(sno, (lead & 0xff));
887 GLOBAL_Stream[sno].stream_putc(sno, (lead >> 8));
894 GLOBAL_Stream[sno].stream_putc(sno, (ch >> 8));
895 GLOBAL_Stream[sno].stream_putc(sno, (ch & 0xff));
897 uint16_t lead = (uint16_t)LEAD_OFFSET + ((uint16_t)ch >> 10);
898 uint16_t trail = 0xDC00 + ((uint16_t)ch & 0x3FF);
900 GLOBAL_Stream[sno].stream_putc(sno, (lead >> 8));
901 GLOBAL_Stream[sno].stream_putc(sno, (lead & 0xff));
902 GLOBAL_Stream[sno].stream_putc(sno, (trail >> 8));
903 GLOBAL_Stream[sno].stream_putc(sno, (trail & 0xff));
911 GLOBAL_Stream[sno].stream_putc(sno, (ch & 0xff));
912 GLOBAL_Stream[sno].stream_putc(sno, (ch >> 8));
918 GLOBAL_Stream[sno].stream_putc(sno, (ch >> 8));
919 GLOBAL_Stream[sno].stream_putc(sno, (ch & 0xff));
926 case ENC_ISO_UTF32_BE:
927 GLOBAL_Stream[sno].stream_putc(sno, (ch >> 24) & 0xff);
928 GLOBAL_Stream[sno].stream_putc(sno, (ch >> 16) & 0xff);
929 GLOBAL_Stream[sno].stream_putc(sno, (ch >> 8) & 0xff);
930 GLOBAL_Stream[sno].stream_putc(sno, ch & 0xff);
932 case ENC_ISO_UTF32_LE:
933 GLOBAL_Stream[sno].stream_putc(sno, ch & 0xff);
934 GLOBAL_Stream[sno].stream_putc(sno, (ch >> 8) & 0xff);
935 GLOBAL_Stream[sno].stream_putc(sno, (ch >> 16) & 0xff);
936 GLOBAL_Stream[sno].stream_putc(sno, (ch >> 24) & 0xff);
944int Yap_PlGetchar(
void) {
947 GLOBAL_Stream[LOCAL_c_input_stream].stream_getc(LOCAL_c_input_stream));
950int Yap_PlGetWchar(
void) {
952 return get_wchar(LOCAL_c_input_stream);
956int Yap_PlFGetchar(
void) {
958 return (PlGetc(LOCAL_c_input_stream));
961Term Yap_MkStream(
int n) {
964 return (Yap_MkApplTerm(FunctorStream, 1, t));
968Int GetStreamFd(
int sno) {
970 if (GLOBAL_Stream[sno].status & Socket_Stream_f) {
971 return (GLOBAL_Stream[sno].u.socket.fd);
974 if (GLOBAL_Stream[sno].status & Pipe_Stream_f) {
975 return (GLOBAL_Stream[sno].u.pipe.fd);
976 }
else if (GLOBAL_Stream[sno].status & InMemory_Stream_f) {
979 return (fileno(GLOBAL_Stream[sno].file));
982Int Yap_GetStreamFd(
int sno) {
return GetStreamFd(sno); }
984static int binary_file(
const char *file_name) {
986#if _MSC_VER || defined(__MINGW32__)
988 if (_stat(file_name, &ss) != 0)
991 if (stat(file_name, &ss) != 0)
997 return (S_ISDIR(ss.st_mode));
1003static int write_bom(
int sno,
StreamDesc *st) {
1007 if (st->stream_putc(sno, 0xEF) < 0)
1009 if (st->stream_putc(sno, 0xBB) < 0)
1011 if (st->stream_putc(sno, 0xBF) < 0)
1013 st->status |= HAS_BOM_f;
1017 if (st->stream_putc(sno, 0xFE) < 0)
1019 if (st->stream_putc(sno, 0xFF) < 0)
1021 st->status |= HAS_BOM_f;
1025 if (st->stream_putc(sno, 0xFF) < 0)
1027 if (st->stream_putc(sno, 0xFE) < 0)
1029 st->status |= HAS_BOM_f;
1031 case ENC_ISO_UTF32_BE:
1032 if (st->stream_putc(sno, 0x00) < 0)
1034 if (st->stream_putc(sno, 0x00) < 0)
1036 if (st->stream_putc(sno, 0xFE) < 0)
1038 if (st->stream_putc(sno, 0xFF) < 0)
1040 st->status |= HAS_BOM_f;
1042 case ENC_ISO_UTF32_LE:
1043 if (st->stream_putc(sno, 0xFF) < 0)
1045 if (st->stream_putc(sno, 0xFE) < 0)
1047 if (st->stream_putc(sno, 0x00) < 0)
1049 if (st->stream_putc(sno, 0x00) < 0)
1051 st->status |= HAS_BOM_f;
1058static int check_bom(
int sno,
StreamDesc *st) {
1059 int ch1, ch2, ch3, ch4;
1060 if (st->file == NULL) {
1061 Yap_ThrowError(SYSTEM_ERROR_INTERNAL, Yap_MkStream(sno),
1062 "YAP does not support BOM n %x type of files", st->status);
1065 ch1 = fgetc(st->file);
1068 ch2 = fgetc(st->file);
1070 ungetc(ch1, st->file);
1071 ungetc(ch2, st->file);
1074 ch3 = fgetc(st->file);
1075 if (ch3 == EOFCHAR || ch3 != 0xFE) {
1076 ungetc(ch1, st->file);
1077 ungetc(ch2, st->file);
1078 ungetc(ch3, st->file);
1081 ch4 = fgetc(st->file);
1082 if (ch4 == EOFCHAR || ch3 != 0xFF) {
1083 ungetc(ch1, st->file);
1084 ungetc(ch2, st->file);
1085 ungetc(ch3, st->file);
1086 ungetc(ch4, st->file);
1089 st->status |= HAS_BOM_f;
1097 ch2 = fgetc(st->file);
1099 ungetc(ch1, st->file);
1100 ungetc(ch2, st->file);
1103 st->status |= HAS_BOM_f;
1109 ch2 = fgetc(st->file);
1111 ungetc(ch1, st->file);
1112 ungetc(ch2, st->file);
1115 ch3 = fgetc(st->file);
1117 ungetc(ch3, st->file);
1119 ch4 = fgetc(st->file);
1122 st->status |= HAS_BOM_f;
1126 ungetc(ch3, st->file);
1127 ungetc(ch4, st->file);
1131 st->status |= HAS_BOM_f;
1136 ch2 = fgetc(st->file);
1138 ungetc(ch1, st->file);
1139 ungetc(ch2, st->file);
1142 ch3 = fgetc(st->file);
1144 ungetc(ch1, st->file);
1145 ungetc(ch2, st->file);
1146 ungetc(ch3, st->file);
1149 st->status |= HAS_BOM_f;
1155 ungetc(ch1, st->file);
1160bool Yap_initStream__(
const char *file,
const char *f,
int line,
int sno, FILE *fd,
Atom name,
const char *io_mode,
1161 Term file_name, encoding_t
encoding, stream_flags_t flags,
1163 extern void jmp_deb(
int);
1168 __android_log_print(
1169 ANDROID_LOG_INFO,
"YAPDroid",
"init %s %s:%s stream <%d>", io_mode,
1170 CurrentModule == 0 ?
"prolog"
1171 : RepAtom(AtomOfTerm(CurrentModule))->StrOfAE,
1172 RepAtom(name)->StrOfAE, sno);
1173 if (io_mode == NULL)
1174 Yap_ThrowError(PERMISSION_ERROR_NEW_ALIAS_FOR_STREAM, MkIntegerTerm(sno),
1175 "File opened with NULL Permissions");
1176 if (strchr(io_mode,
'a')) {
1177 st->status = Append_Stream_f | Output_Stream_f | flags;
1178 }
else if (strchr(io_mode,
'w')) {
1179 st->status = Output_Stream_f | flags;
1181 if (strchr(io_mode,
'r')) {
1182 st->status = Input_Stream_f | flags;
1184 if (strchr(io_mode,
'b')) {
1185 st->status = Binary_Stream_f | flags;
1193 if (flags & Binary_Stream_f) {
1199 st->name = Yap_guessFileName(fd, sno, MAX_PATH);
1201 Yap_ThrowError(SYSTEM_ERROR_INTERNAL, file_name,
1202 "Yap_guessFileName failed: opening a file without a name");
1203 st->user_name = file_name;
1206 Yap_DefaultStreamOps(st);
1210static bool scan_failed(
int sno,
long pos, encoding_t onc) {
1212 rewind(GLOBAL_Stream[sno].file);
1213 GLOBAL_Stream[sno].encoding = onc;
1215 GLOBAL_Stream[sno].stream_getc(sno);
1223static int scan_a_char_preceeded_by_spaces(
int sno) {
1225 while ((ch = GLOBAL_Stream[sno].stream_getc(sno)) ==
'\0' ||
1231static int scan_a_char(
int sno) {
1233 while ((ch = GLOBAL_Stream[sno].stream_getc(sno)) ==
'\0');
1237static bool scan_check_a_text(
int sno,
const char *txt) {
1238 int i, sz = strlen(txt);
1239 if (scan_a_char_preceeded_by_spaces(sno) != txt[0])
1241 for (i=1; i <sz; i++) {
1242 if (scan_a_char(sno) != txt[i])
1249static bool scan_fetch_a_text(
int sno,
char *txt) {
1250 int ch, i=0, quote = 0;
1251 if (chtype(ch = scan_a_char_preceeded_by_spaces(sno)) == EF)
1253 if (ch ==
'\'' || ch ==
'"' || ch ==
'`') {
1258 while (chtype(ch = scan_a_char(sno))!=EF) {
1266 }
else if (ch ==
')') {
1273 if (chtype(ch) == EF)
1276 ch = scan_a_char_preceeded_by_spaces(sno);
1281 ch = scan_a_char_preceeded_by_spaces(sno);
1289static bool scan_encoding(
int sno,
long pos) {
1290 encoding_t onc = GLOBAL_Stream[sno].encoding;
1294 GLOBAL_Stream[sno].encoding = ENC_ISO_ASCII;
1295 while ((ch=(GLOBAL_Stream[sno].stream_getc(sno)==
'\0'))) l++;
1297 return scan_failed(sno, pos, onc);
1300 while ((ch=(GLOBAL_Stream[sno].stream_getc(sno))==
'\0')) l++;
1302 if (ch!=
'-')
return scan_failed(sno, pos, onc);
1303 if (!scan_check_a_text(sno,
"encoding("))
return scan_failed(sno, pos, onc);
1304 if (!scan_fetch_a_text(sno, txt))
return scan_failed(sno, pos, onc);
1305 GLOBAL_Stream[sno].encoding = enc_id(txt, onc);
1306 while(GLOBAL_Stream[sno].stream_getc(sno)!=
'\n');
1308 GLOBAL_Stream[sno].stream_getc(sno);
1312static bool open_header(
int sno,
Atom open_mode) {
1313 if (open_mode == AtomWrite) {
1315 const char s[] =
"#!";
1319 while ((ch = *ptr++))
1320 GLOBAL_Stream[sno].stream_wputc(sno, ch);
1321 const char *b = Yap_FindExecutable();
1323 while ((ch = *ptr++))
1324 GLOBAL_Stream[sno].stream_wputc(sno, ch);
1325 const char *l =
" -L --\n\n YAP script\n#\n# .\n";
1327 while ((ch = *ptr++))
1328 GLOBAL_Stream[sno].stream_wputc(sno, ch);
1330 }
else if (open_mode == AtomRead) {
1333 while ((ch = Yap_peek(sno)) ==
'#') {
1334 while ((ch = GLOBAL_Stream[sno].stream_wgetc(sno)) != 10 && ch != -1);
1341#define OPEN_DEFS() \
1342 PAR("alias", isatom, OPEN_ALIAS) \
1343 , PAR("bom", booleanFlag, OPEN_BOM), PAR("buffer", isatom, OPEN_BUFFER), \
1344 PAR("close_on_abort", booleanFlag, OPEN_CLOSE_ON_ABORT), \
1345 PAR("create", isatom, OPEN_CREATE), \
1346 PAR("encoding", isatom, OPEN_ENCODING), \
1347 PAR("eof_action", isatom, OPEN_EOF_ACTION), \
1348 PAR("expand_filename", booleanFlag, OPEN_EXPAND_FILENAME), \
1349 PAR("file_name", isatom, OPEN_FILE_NAME), PAR("input", ok, OPEN_INPUT), \
1350 PAR("locale", isatom, OPEN_LOCALE), PAR("lock", isatom, OPEN_LOCK), \
1351 PAR("mode", isatom, OPEN_MODE), PAR("output", ok, OPEN_OUTPUT), \
1352 PAR("representation_errors", booleanFlag, OPEN_REPRESENTATION_ERRORS), \
1353 PAR("reposition", booleanFlag, OPEN_REPOSITION), \
1354 PAR("script", booleanFlag, OPEN_SCRIPT), PAR("type", isatom, OPEN_TYPE), \
1355 PAR("wait", booleanFlag, OPEN_WAIT), PAR(NULL, ok, OPEN_END)
1357#define PAR(x, y, z) z
1358typedef enum open_enum_choices { OPEN_DEFS() } open_choices_t;
1362#define PAR(x, y, z) \
1365static const param_t open_defs[] = {OPEN_DEFS()};
1368static bool fill_stream(
int sno,
StreamDesc *st, Term tin,
const char *io_mode,
1369 Term user_name,
bool *avoid_bomp, encoding_t enc) {
1370 struct vfs *vfsp = NULL;
1373 if (IsAtomTerm(tin))
1374 fname = RepAtom(AtomOfTerm(tin))->StrOfAE;
1375 else if (IsStringTerm(tin))
1376 fname = StringOfTerm(tin);
1382 if ((vfsp = vfs_owner(fname)) != NULL) {
1383 if (vfsp->
open(vfsp, fname, io_mode, sno)) {
1385 user_name = st->user_name;
1387 UNLOCK(st->streamlock);
1388 __android_log_print(
1389 ANDROID_LOG_INFO,
"YAPDroid",
"got %d ", sno);
1391 UNLOCK(st->streamlock);
1392 __android_log_print(
1393 ANDROID_LOG_INFO,
"YAPDroid",
"failed %s ",fname);
1397 st->file = fopen(fname, io_mode);
1398 if (st->file == NULL) {
1399 __android_log_print(
1400 ANDROID_LOG_INFO,
"YAPDroid",
"failed %s ",fname);
1401 UNLOCK(st->streamlock);
1402 if (errno == ENOENT && !strchr(io_mode,
'r')) {
1403 PlIOError(EXISTENCE_ERROR_SOURCE_SINK, tin,
"%s: %s", fname,
1406 PlIOError(PERMISSION_ERROR_OPEN_SOURCE_SINK, tin,
"%s: %s", fname,
1413 }
else if (IsApplTerm(tin)) {
1414 Functor f = FunctorOfTerm(tin);
1415 if (f == FunctorAtom || f == FunctorString || f == FunctorCodes1 ||
1416 f == FunctorCodes || f == FunctorChars1 || f == FunctorChars) {
1417 if (strchr(io_mode,
'w')) {
1418 return Yap_OpenBufWriteStream(PASS_REGS1);
1420 int j = push_text_stack();
1426 buf = Yap_TextTermToText(ArgOfTerm(1,tin) PASS_REGS);
1431 st->nbuf = pop_output_text_stack(j, buf);
1432 Atom nat = Yap_LookupAtom(Yap_StrPrefix(buf, 32));
1433 sno = Yap_open_buf_read_stream(st, buf, st->nsize=(strlen(buf) + 1), &LOCAL_encoding,
1434 MEM_BUF_MALLOC, nat,
1435 MkAtomTerm(NameOfFunctor(f)));
1438 }
else if (!strcmp(RepAtom(NameOfFunctor(f))->StrOfAE,
"popen")) {
1440 int i = push_text_stack();
1441 buf = Yap_TextTermToText(ArgOfTerm(1, tin) PASS_REGS);
1446 st->file = _popen(buf, io_mode);
1448 st->file = popen(buf, io_mode);
1452 st->status |= Popen_Stream_f;
1455 Yap_ThrowError(DOMAIN_ERROR_SOURCE_SINK, tin,
"open");
1458 if (!strchr(io_mode,
'b') && binary_file(fname)) {
1459 st->status |= Binary_Stream_f;
1461 Yap_initStream(sno, st->file, Yap_LookupAtom(fname), io_mode, user_name,
1462 LOCAL_encoding, st->status, vfsp);
1466static Int do_open(Term file_name, Term t2, Term tlist USES_REGS) {
1468 bool avoid_bom =
false, needs_bom =
false;
1471 int sno = GetFreeStreamD();
1473 return (PlIOError(RESOURCE_ERROR_MAX_STREAMS, file_name,
1474 "new stream not available for opening"));
1476 memset(st, 0,
sizeof(*st));
1483 st->status |= HAS_BOM_f;
1485 st->user_name = Deref(file_name);
1486 if (IsVarTerm(file_name)) {
1487 Yap_ThrowError(INSTANTIATION_ERROR, file_name,
1488 "while opening a list of options");
1491 if (IsVarTerm(t2)) {
1492 Yap_ThrowError(INSTANTIATION_ERROR, t2,
"open/3");
1495 if (!IsAtomTerm(t2)) {
1496 if (IsStringTerm(t2)) {
1497 open_mode = Yap_LookupAtom(StringOfTerm(t2));
1499 Yap_ThrowError(TYPE_ERROR_ATOM, t2,
"open/3");
1503 open_mode = AtomOfTerm(t2);
1506xarg * args = Yap_ArgListToVector(tlist, open_defs, OPEN_END, NULL,DOMAIN_ERROR_OPEN_OPTION);
1508 if (LOCAL_Error_TYPE != YAP_NO_ERROR) {
1509 Yap_ThrowError(LOCAL_Error_TYPE, tlist,
"option handling in open/3");
1515 const char *s_encoding;
1516 if (args[OPEN_ENCODING].used) {
1517 tenc = args[OPEN_ENCODING].tvalue;
1518 s_encoding = RepAtom(AtomOfTerm(tenc))->StrOfAE;
1520 s_encoding =
"default";
1523 st->
encoding = enc_id(s_encoding, ENC_OCTET);
1526 bool ok = (args[OPEN_EXPAND_FILENAME].used
1527 ? args[OPEN_EXPAND_FILENAME].tvalue == TermTrue
1530 if (((IsAtomTerm(file_name) &&
1531 (fname0 = RepAtom(AtomOfTerm(file_name))->StrOfAE))) ||
1532 (IsStringTerm(file_name) && (fname0 = StringOfTerm(file_name)))) {
1533 int lvl = push_text_stack();
1535 file_name = MkAtomTerm(Yap_LookupAtom(fname));
1537 pop_text_stack(lvl);
1538 PlIOError(EXISTENCE_ERROR_SOURCE_SINK, ARG1, NULL);
1544 if (open_mode == AtomRead) {
1545 strncpy(io_mode,
"r", 8);
1546 }
else if (open_mode == AtomWrite) {
1547 strncpy(io_mode,
"w", 8);
1548 }
else if (open_mode == AtomAppend) {
1549 strncpy(io_mode,
"a", 8);
1554 if (args[OPEN_TYPE].used) {
1555 Term t = args[OPEN_TYPE].tvalue;
1556 bool bin = (t == TermBinary);
1559 strncat(io_mode,
"b", 8);
1561 st->status |= Binary_Stream_f;
1565 }
else if (t == TermText) {
1567 strncat(io_mode,
"t", 8);
1571 Yap_ThrowError(DOMAIN_ERROR_STREAM_OPTION, t,
1572 "type is ~a, must be one of binary or text", t);
1576 st = &GLOBAL_Stream[sno];
1578 if (!fill_stream(sno, st, file_name, io_mode, st->user_name, &avoid_bom, st->
encoding)) {
1582 if (args[OPEN_BOM].used) {
1583 if (args[OPEN_BOM].tvalue == TermTrue) {
1586 }
else if (args[OPEN_BOM].tvalue == TermFalse) {
1592 (args[OPEN_SCRIPT].used ? args[OPEN_SCRIPT].tvalue == TermTrue :
false);
1594 if (args[OPEN_ALIAS].used) {
1595 Atom al = AtomOfTerm(args[OPEN_ALIAS].tvalue);
1596 if (!Yap_AddAlias(al, sno)) {
1601 if (st - GLOBAL_Stream < 3) {
1602 st->status |= RepError_Prolog_f;
1605 if (open_mode == AtomWrite) {
1606 Yap_SetTextFile(RepAtom(AtomOfTerm(file_name))->StrOfAE);
1611 avoid_bom = avoid_bom || (st->status & Tty_Stream_f);
1612 if (needs_bom && !write_bom(sno, st)) {
1614 }
else if (open_mode == AtomRead) {
1617 bsz = check_bom(sno, st);
1619 if (st->status & HAS_BOM_f) {
1624 st->status & Seekable_Stream_f &&
1626 scan_encoding(sno, bsz);
1628 Yap_DefaultStreamOps(st);
1630 open_header(sno, open_mode);
1634 UNLOCK(st->streamlock);
1636 Term t = Yap_MkStream(sno);
1637 return (Yap_unify(ARG3, t));
1661static Int open3(USES_REGS1) {
1663 return do_open(Deref(ARG1), Deref(ARG2), TermNil PASS_REGS);
1744static Int open4(USES_REGS1) {
1745 return do_open(Deref(ARG1), Deref(ARG2), Deref(ARG4) PASS_REGS);
1748static Int p_file_expansion(USES_REGS1) {
1749 Term file_name = Deref(ARG1);
1752 if (IsVarTerm(file_name)) {
1753 Yap_ThrowError(INSTANTIATION_ERROR, file_name,
"absolute_file_name/3");
1756 int lvl = push_text_stack();
1760 pop_text_stack(lvl);
1761 return (PlIOError(EXISTENCE_ERROR_SOURCE_SINK, file_name,
1762 "absolute_file_name/3"));
1764 bool rc = (Yap_unify(ARG2, MkAtomTerm(Yap_LookupAtom(tmp))));
1765 pop_text_stack(lvl);
1769static Int p_open_null_stream(USES_REGS1) {
1772 int sno = GetFreeStreamD();
1774 Yap_ThrowError(SYSTEM_ERROR_INTERNAL, TermNil,
1775 "new stream not available for open_null_stream/1");
1779 st = &GLOBAL_Stream[sno];
1780 st->status = Append_Stream_f | Output_Stream_f | Null_Stream_f;
1782 st->file = fopen(
"NUL",
"w");
1784 st->file = fopen(
"/dev/null",
"w");
1786 if (st->file == NULL) {
1787 Yap_ThrowError(SYSTEM_ERROR_INTERNAL, TermNil,
1788 "Could not open NULL stream (/dev/null,NUL)");
1794 st->stream_putc = NullPutc;
1799 st->user_name = MkAtomTerm(st->name = AtomDevNull);
1800 UNLOCK(st->streamlock);
1801 t = Yap_MkStream(sno);
1802 return (Yap_unify(ARG1, t));
1805int Yap_OpenStream(Term tin,
const char *io_mode, Term user_name,
1811 sno = GetFreeStreamD();
1813 Yap_ThrowError(RESOURCE_ERROR_MAX_STREAMS, tin,
1814 "new stream not available for opening");
1817 st = GLOBAL_Stream + sno;
1819 bool avoid_bom =
false;
1820 if (fill_stream(sno, st, tin, io_mode, user_name, &avoid_bom,
enc))
1825int Yap_FileStream(FILE *fd,
Atom name, Term file_name,
int flags,
1831 sno = GetFreeStreamD();
1833 Yap_ThrowError(RESOURCE_ERROR_MAX_STREAMS, file_name,
1834 "new stream not available for opening");
1837 if (flags & Output_Stream_f) {
1838 if (flags & Append_Stream_f)
1845 Yap_initStream(sno, fd, name, mode, file_name, LOCAL_encoding, flags, vfsp);
1849#define CheckStream(arg, kind, msg) \
1850 CheckStream__(__FILE__, __FUNCTION__, __LINE__, arg, kind, msg)
1852static int CheckStream__(
const char *file,
const char *f,
int line, Term arg,
1853 int kind,
const char *msg) {
1856 if (IsVarTerm(arg)) {
1857 Yap_ThrowError(INSTANTIATION_ERROR, arg, msg);
1859 }
else if (IsAtomTerm(arg)) {
1860 Atom sname = AtomOfTerm(arg);
1862 if (sname == AtomUser) {
1863 if (kind & Input_Stream_f) {
1864 if (kind & (Output_Stream_f | Append_Stream_f)) {
1866 "ambiguous use of 'user' as <a stream");
1871 sname = AtomUserOut;
1874 if ((sno = Yap_CheckAlias(sname)) < 0) {
1875 UNLOCK(GLOBAL_Stream[sno].streamlock);
1879 LOCK(GLOBAL_Stream[sno].streamlock);
1881 }
else if (IsApplTerm(arg) && FunctorOfTerm(arg) == FunctorStream) {
1882 arg = ArgOfTerm(1, arg);
1883 if (!IsVarTerm(arg) && IsIntegerTerm(arg)) {
1884 sno = IntegerOfTerm(arg);
1887 Yap_ThrowError(TYPE_ERROR_STREAM, arg, msg);
1890 if (sno < 0 || sno > MaxStreams) {
1891 Yap_ThrowError(DOMAIN_ERROR_STREAM_OR_ALIAS, arg, msg);
1894 if (GLOBAL_Stream[sno].status & Free_Stream_f) {
1898 LOCK(GLOBAL_Stream[sno].streamlock);
1899 if ((GLOBAL_Stream[sno].status & Input_Stream_f) &&
1900 !(kind & Input_Stream_f)) {
1901 UNLOCK(GLOBAL_Stream[sno].streamlock);
1905 if ((GLOBAL_Stream[sno].status & (Append_Stream_f | Output_Stream_f)) &&
1906 !(kind & Output_Stream_f)) {
1907 UNLOCK(GLOBAL_Stream[sno].streamlock);
1914int Yap_CheckStream__(
const char *file,
const char *f,
int line, Term arg,
1915 int kind,
const char *msg) {
1916 return CheckStream__(file, f, line, arg, kind, msg);
1919int Yap_CheckTextStream__(
const char *file,
const char *f,
int line, Term arg,
1920 int kind,
const char *msg) {
1922 if ((sno = CheckStream__(file, f, line, arg, kind, msg)) < 0)
1924 if ((GLOBAL_Stream[sno].status & Binary_Stream_f)) {
1925 UNLOCK(GLOBAL_Stream[sno].streamlock);
1926 if (kind == Input_Stream_f)
1930 Yap_ThrowError__(file, f, line, PERMISSION_ERROR_OUTPUT_BINARY_STREAM, arg,
1937int Yap_CheckTextWriteStream__(
const char *file,
const char *f,
int line,
1938 Term arg,
const char *msg) {
1939 int sno, kind = Output_Stream_f;
1940 if ((sno = CheckStream__(file, f, line, arg, kind, msg)) < 0)
1942 if ((GLOBAL_Stream[sno].status & Binary_Stream_f)) {
1943 UNLOCK(GLOBAL_Stream[sno].streamlock);
1944 if (kind & Output_Stream_f)
1948 Yap_ThrowError__(file, f, line, PERMISSION_ERROR_OUTPUT_BINARY_STREAM, arg,
1955int Yap_CheckTextReadStream__(
const char *file,
const char *f,
int line,
1956 Term arg,
const char *msg) {
1957 int sno, kind = Input_Stream_f;
1958 if ((sno = CheckStream__(file, f, line, arg, kind, msg)) < 0)
1960 if ((GLOBAL_Stream[sno].status & Binary_Stream_f)) {
1961 UNLOCK(GLOBAL_Stream[sno].streamlock);
1962 if (kind & Input_Stream_f)
1966 Yap_ThrowError__(file, f, line, PERMISSION_ERROR_OUTPUT_BINARY_STREAM, arg,
1973int Yap_CheckBinaryStream__(
const char *file,
const char *f,
int line, Term arg,
1974 int kind,
const char *msg) {
1976 if ((sno = CheckStream__(file, f, line, arg, kind, msg)) < 0)
1978 if (!(GLOBAL_Stream[sno].status & Binary_Stream_f)) {
1979 UNLOCK(GLOBAL_Stream[sno].streamlock);
1980 if (kind == Input_Stream_f)
1981 Yap_ThrowError__(file, f, line, PERMISSION_ERROR_INPUT_TEXT_STREAM, arg, msg);
1983 Yap_ThrowError__(file, f, line, PERMISSION_ERROR_OUTPUT_TEXT_STREAM, arg, msg);
1990int Yap_GetFreeStreamDForReading(
void) {
1991 int sno = GetFreeStreamD();
1996 s = GLOBAL_Stream + sno;
1997 s->status |= User_Stream_f | Input_Stream_f;
2001 Yap_DefaultStreamOps(s);
2002 UNLOCK(s->streamlock);
2013static Int always_prompt_user(USES_REGS1) {
2016 s->status |= Promptable_Stream_f;
2017 Yap_DefaultStreamOps(s);
2027static Int close1(USES_REGS1) {
2028 int sno = CheckStream(
2029 ARG1, (Input_Stream_f | Output_Stream_f | Socket_Stream_f),
"close/2");
2032 if (sno <= StdErrStream) {
2033 UNLOCK(GLOBAL_Stream[sno].streamlock);
2036 Yap_CloseStream(sno);
2037 UNLOCK(GLOBAL_Stream[sno].streamlock);
2041#define CLOSE_DEFS() \
2042 PAR("force", booleanFlag, CLOSE_FORCE), PAR(NULL, ok, CLOSE_END)
2044#define PAR(x, y, z) z
2046typedef enum close_enum_choices { CLOSE_DEFS() } close_choices_t;
2050#define PAR(x, y, z) \
2053static const param_t close_defs[] = {CLOSE_DEFS()};
2065static Int close2(USES_REGS1) {
2066 Int sno = CheckStream(
2067 ARG1, (Input_Stream_f | Output_Stream_f | Socket_Stream_f),
"close/2");
2071 if (sno <= StdErrStream) {
2072 UNLOCK(GLOBAL_Stream[sno].streamlock);
2075 xarg *args = Yap_ArgListToVector((tlist = Deref(ARG2)), close_defs, CLOSE_END, NULL,
2076 DOMAIN_ERROR_CLOSE_OPTION);
2078 if (LOCAL_Error_TYPE != YAP_NO_ERROR) {
2079 Yap_ThrowError(LOCAL_Error_TYPE, tlist, NULL);
2085 Yap_CloseStream(sno);
2086 UNLOCK(GLOBAL_Stream[sno].streamlock);
2090Term read_line(
int sno) {
2095 if ((ch = GLOBAL_Stream[sno].stream_wgetc(sno)) == 10) {
2098 tail = read_line(sno);
2099 return (MkPairTerm(MkIntTerm(ch), tail));
2104 Yap_stdin = fdopen(argi->inp - 1,
"r");
2105 else if (argi->inp < 0)
2110 Yap_stdout = fdopen(argi->out - 1,
"a");
2111 else if (argi->out < 0)
2114 Yap_stdout = stdout;
2116 Yap_stderr = fdopen(argi->err - 1,
"a");
2120 Yap_stderr = stderr;
2123 for (i = 0; i < MaxStreams; ++i) {
2124 INIT_LOCK(GLOBAL_Stream[i].streamlock);
2125 GLOBAL_Stream[i].status = Free_Stream_f;
2130void Yap_InitIOPreds(
void) {
2132 Yap_InitCPred(
"always_prompt_user", 0, always_prompt_user,
2133 SafePredFlag | SyncPredFlag);
2134 Yap_InitCPred(
"close", 1, close1, SafePredFlag | SyncPredFlag);
2135 Yap_InitCPred(
"close", 2, close2, SafePredFlag | SyncPredFlag);
2136 Yap_InitCPred(
"open", 4, open4, SyncPredFlag);
2137 Yap_InitCPred(
"open", 3, open3, SyncPredFlag);
2138 Yap_InitCPred(
"$file_expansion", 2, p_file_expansion,
2139 SafePredFlag | SyncPredFlag | HiddenPredFlag);
2140 Yap_InitCPred(
"$open_null_stream", 1, p_open_null_stream,
2141 SafePredFlag | SyncPredFlag | HiddenPredFlag);
2142 Yap_InitIOStreams();
2151 Yap_InitWriteTPreds();
2152 Yap_InitReadTPreds();
2154 Yap_InitRandomPreds();
2156 Yap_InitReadlinePreds();
2159 Yap_InitSignalPreds();
2161 Yap_InitTimePreds();
2162 Yap_InitAbsfPreds();
const char * Yap_AbsoluteFile(const char *spec, bool ok)
generate absolute path, if ok first expand SICStus Prolog style
void * Malloc(size_t sz USES_REGS)
allocate a temporary text block
void Yap_ThrowError__(const char *file, const char *function, int lineno, yap_error_number type, Term where, const char *msg,...)
Throw an error directly to the error handler.
@ encoding
support for coding systens, YAP relies on UTF-8 internally
int EOFPeek(int sno)
caled after EOF found a peek, it just calls console_post_process to conclude the job
int(* stream_getc)(int)
function the stream uses for writing a character
int(* stream_wputc)(int, wchar_t)
function the stream uses for writing a single octet
encoding_t encoding
check if the next wide character is available
int(* stream_wgetc)(int)
function the stream uses for reading an octet
int(* stream_wpeek)(int)
check if the next character is available
struct vfs * vfs
function the stream uses for reading a character
int(* stream_wgetc_for_read)(int)
direct handle to stream in that space
int(* stream_peek)(int)
function the stream uses for parser
void *(* open)(struct vfs *, const char *fname, const char *io_mode, int sno)
operations
int(* put_char)(int sno, int ch)
unget an octet from the stream
int(* get_wchar)(int sno)
get an octet from the stream
int(* get_char)(int sno)
close the object
int(* put_wchar)(int sno, int ch)
output an octet to the stream
encoding_t enc
set working directory (may be virtual)