home *** CD-ROM | disk | FTP | other *** search
- /*
- *
- * p o r t . c -- ports implementation
- *
- * Copyright ⌐ 1993-1996 Erick Gallesio - I3S-CNRS/ESSI <eg@unice.fr>
- *
- *
- * Permission to use, copy, and/or distribute this software and its
- * documentation for any purpose and without fee is hereby granted, provided
- * that both the above copyright notice and this permission notice appear in
- * all copies and derived works. Fees for distribution or use of this
- * software or derived works may only be charged with express written
- * permission of the copyright holder.
- * This software is provided ``as is'' without express or implied warranty.
- *
- * This software is a derivative work of other copyrighted softwares; the
- * copyright notices of these softwares are placed in the file COPYRIGHTS
- *
- *
- * Author: Erick Gallesio [eg@unice.fr]
- * Creation date: 17-Feb-1993 12:27
- * Last file update: 21-Jul-1996 17:48
- *
- */
- #ifndef WIN32
- # include <sys/ioctl.h>
- # include <sys/time.h>
- # include <ctype.h>
- #endif
-
- #ifdef HAVE_SYS_SELECT_H
- #include <sys/select.h> /* This seems to be useful only for AIX */
- #endif
-
- #ifndef NO_FD_SET
- # define SELECT_MASK fd_set
- #else
- # ifndef _AIX
- typedef long fd_mask;
- # endif
- # if defined(_IBMR2)
- # define SELECT_MASK void
- # else
- # define SELECT_MASK int
- # endif
- #endif
-
- #include "stk.h"
-
- #ifdef WIN32
- /* Provide substitute functions dor WIN32 */
- FILE *popen(char *cmd, char *mode)
- {
- /* Returning NULL will yield an error */
- return NULL;
- }
- void pclose(FILE *f)
- {}
- #endif
-
- /* external vars */
- SCM STk_curr_iport, STk_curr_oport, STk_curr_eport, STk_eof_object;
-
-
- SCM STk_Cfile2port(char *name, FILE *f, int type, int flags)
- {
- SCM z;
-
- NEWCELL(z, type);
- z->storage_as.port.p = (struct port_descr *)
- must_malloc(sizeof(struct port_descr));
- PORT_FILE(z) = f;
- PORT_FLAGS(z) = flags;
- PORT_REVENT(z) = Ntruth;
- PORT_WEVENT(z) = Ntruth;
- PORT_NAME(z) = (char *) must_malloc(strlen(name)+1);
- strcpy(PORT_NAME(z), name);
-
- return z;
- }
-
- static SCM makeport(char *name, int type, char *mode, int error)
- {
- SCM z = Ntruth;
- int flags = 0;
- FILE *f;
- char *full_name;
-
- STk_disallow_sigint();
- if (strncmp(name, "| ", 2)) {
- full_name = CHARS(STk_internal_expand_file_name(name));
-
- if ((f = fopen(full_name, mode)) == NULL) {
- if (error) Err("could not open file", STk_makestring(name));
- else goto Out;
- }
- }
- else {
- full_name = name;
- if ((f = popen(name+1, mode)) == NULL) {
- flags = PIPE_PORT;
- if (error) Err("could not create pipe", STk_makestring(name));
- else goto Out;
- }
- }
-
- z = STk_Cfile2port(full_name, f, type, flags);
-
- Out:
- STk_allow_sigint();
- return(z);
- }
-
- static SCM verify_port(char *who, SCM port, int mode)
- {
- char buff[100];
-
- if (port == UNBOUND) /* test write 'cause of flush */
- port = (mode&F_WRITE) ? STk_curr_oport: STk_curr_iport;
-
- if (!(INP(port) || OUTP(port))) {
- sprintf(buff, "%s: bad port", who);
- Err(buff, port);
- }
- if (PORT_FLAGS(port) & PORT_CLOSED) {
- sprintf(buff, "%s: port is closed", who);
- Err(buff, port);
- }
- if ((mode & F_READ) && INP(port)) return port; /* not else. It can be both */
- if ((mode & F_WRITE) && OUTP(port)) return port;
- Error:
- sprintf(buff, "%s: bad port", who);
- Err(buff, port);
- }
-
- static void closeport(SCM port)
- {
- if (PORT_FLAGS(port) & PORT_CLOSED) return;
-
- STk_disallow_sigint();
-
- if (IPORTP(port) || OPORTP(port)) { /* Not a string port */
- #ifdef USE_TK
- /* For pipe and file ports, delete the fileevent associated to it (if any) */
- Tcl_DeleteFileHandler(Tcl_GetFile((ClientData) fileno(PORT_FILE(port)),
- TCL_UNIX_FD));
- #endif
- if (PORT_FLAGS(port) & PIPE_PORT) /* Pipe port */
- pclose(PORT_FILE(port));
- else /* File port */
- fclose(PORT_FILE(port));
- }
- PORT_FLAGS(port) |= PORT_CLOSED;
- STk_allow_sigint();
- }
-
- void STk_freeport(SCM port)
- {
- STk_disallow_sigint();
- closeport(port);
- free(PORT_NAME(port));
- free(port->storage_as.port.p);
- STk_allow_sigint();
- }
-
- void STk_init_standard_ports(void)
- {
- STk_curr_iport = STk_Cfile2port("*stdin*", STk_stdin, tc_iport, 0);
- STk_gc_protect(&STk_curr_iport);
-
- STk_curr_oport = STk_Cfile2port("*stdout*", STk_stdout, tc_oport, 0);
- STk_gc_protect(&STk_curr_oport);
-
- STk_curr_eport = STk_Cfile2port("*stderr*", STk_stderr, tc_oport, 0);
- STk_gc_protect(&STk_curr_eport);
-
-
- NEWCELL(STk_eof_object, tc_eof);
- STk_gc_protect(&STk_eof_object);
-
- STk_line_counter = 1;
- STk_current_filename = UNBOUND; /* Ubound <=> stdin */
- STk_gc_protect(&STk_current_filename);
- }
-
- /******************************************************************************
- *
- * L O A D stuff
- *
- ******************************************************************************/
- static int do_load(char *full_name)
- {
- FILE *f;
- int c;
-
- if (!STk_dirp(full_name)) {
- f = fopen(full_name, "r");
-
- if (f == NULL) return 0;
-
- if (VCELL(Intern(LOAD_VERBOSE)) != Ntruth)
- fprintf(STk_stderr, ";; Loading file \"%s\"\n", full_name);
-
- /* Just read one character. Assume that file is an object if this
- * character is a control one. Here, I don't try to see if the file magic
- * number has a particular value, since I'm not nure that all platforms
- * use identical conventions
- */
- c = Getc(f); Ungetc(c, f);
- if (c != EOF && ((iscntrl(c)&& c!= '\n') || !isascii(c))) {
- fclose(f);
- STk_load_object_file(full_name);
- }
- else {
- /* file seems not to be an object file. Try to load it as a Scheme file */
- jmp_buf jb, *prev_jb = Top_jmp_buf;
- long prev_context = Error_context;
- SCM previous_file, form;
- int k, previous_line;
-
- /* Save info about current line and file */
- previous_file = STk_current_filename;
- previous_line = STk_line_counter;
- STk_line_counter = 1;
- STk_current_filename = STk_makestring(full_name);
-
- /* save normal error jmpbuf so that eval error don't lead to toplevel */
- /* This permits to close the opened file in case of error */
- /* If in a "catch", keep the ERR_IGNORED bit set */
- if ((k = setjmp(jb)) == 0) {
- Top_jmp_buf = &jb;
-
- for( ; ; ) {
- form = STk_readf(f, FALSE);
- if EQ(form, STk_eof_object) break;
- STk_eval(form, NIL);
- }
- }
- fclose(f);
-
- Top_jmp_buf = prev_jb;
- Error_context = prev_context;
- if (k) /*propagate error */ longjmp(*Top_jmp_buf, k);
-
- /* No error: restore info about current line and file */
- STk_current_filename = previous_file;
- STk_line_counter = previous_line;
- }
- if (VCELL(Intern(LOAD_VERBOSE)) != Ntruth)
- fprintf(STk_stderr, ";; File \"%s\" loaded\n", full_name);
- return 1;
- }
- /* No file found */
- return 0;
- }
-
- static int try_loadfile(char *prefix, char *fname, SCM suffixes)
- {
- char full_name[MAX_PATH_LENGTH], *s;
-
- /* First try to load without suffix */
- if (strlen(prefix) + strlen(fname) + 2 >= MAX_PATH_LENGTH) goto TooLong;
- sprintf(full_name, "%s%s%s", prefix, (*prefix ? "/": ""), fname);
-
- if (do_load(full_name)) return 1;
-
- /* Now try to load file with suffix */
- for ( ; NNULLP(suffixes); suffixes = CDR(suffixes)) {
- /* We are sure that suffixes is a well formed list (ensured by loadfile) */
- if (NSTRINGP(CAR(suffixes))) Err("load: bad suffix component", CAR(suffixes));
- s = CHARS(CAR(suffixes));
-
- if (strlen(prefix)+strlen(fname)+strlen(s)+3 >= MAX_PATH_LENGTH) goto TooLong;
- sprintf(full_name, "%s%s%s.%s", prefix, (*prefix ? "/": ""), fname, s);
-
- if (do_load(full_name)) return 1;
- }
-
- /* No file loaded */
- return 0;
-
- TooLong:
- Err("load: Filename too long", NIL);
- }
-
- SCM STk_loadfile(char *fname, int err_if_absent)
- {
- int len;
- SCM load_path, load_suffixes;
-
- len = strlen(fname);
- load_path = VCELL(Intern(LOAD_PATH));
- load_suffixes = VCELL(Intern(LOAD_SUFFIXES));
-
- if (STk_llength(load_path)<0) Err("load: bad loading path", load_path);
- if (STk_llength(load_suffixes)<0) Err("load: bad set of suffixes", load_suffixes);
-
- #ifdef WIN32
- if ((len > 0 && (fname[0] == '/' || fname[0] == '\\' || fname[0] == '~')) ||
- (len > 1 && fname[0] == '.' && (fname[1] == '/' || fname[1] == '\\')) ||
- (len > 2 && fname[0] == '.' && fname[1] == '.' && (fname[2] == '/' ||
- fname[2]=='\\')) ||
- (len > 1 && isalpha(fname[0]) && fname[1]==':')) {
- #else
- if ((len > 0 && (fname[0] == '/' || fname[0] == '~')) ||
- (len > 1 && fname[0] == '.' && fname[1] == '/') ||
- (len > 2 && fname[0] == '.' && fname[1] == '.' && fname[2] == '/')) {
- #endif
-
- if (fname[0] == '~')
- fname = CHARS(STk_internal_expand_file_name(fname));
-
- if (try_loadfile("", fname, load_suffixes))
- return(err_if_absent? UNDEFINED: Truth);
- }
- else {
- /* Use *load-path* for loading file */
- for ( ; NNULLP(load_path); load_path = CDR(load_path)) {
- if (NSTRINGP(CAR(load_path)))
- Err("load: bad loading path component", CAR(load_path));
-
- if (try_loadfile(CHARS(CAR(load_path)), fname, load_suffixes))
- return(err_if_absent? UNDEFINED: Truth);
- }
- }
-
- /* If we are here, we have been unable to load a file. Report err if needed */
- if (err_if_absent)
- Err("load: cannot open file", STk_makestring(fname));
- return Ntruth;
- }
-
-
- PRIMITIVE STk_input_portp(SCM port)
- {
- return IPORTP(port)? Truth: Ntruth;
- }
-
- PRIMITIVE STk_output_portp(SCM port)
- {
- return OPORTP(port)? Truth: Ntruth;
- }
-
- PRIMITIVE STk_current_input_port(void)
- {
- return STk_curr_iport;
- }
-
- PRIMITIVE STk_current_output_port(void)
- {
- return STk_curr_oport;
- }
-
- PRIMITIVE STk_current_error_port(void)
- {
- return STk_curr_eport;
- }
-
- PRIMITIVE STk_with_input_from_file(SCM string, SCM thunk)
- {
- jmp_buf env, *prev_env = Top_jmp_buf;
- SCM result, prev_iport = STk_curr_iport;
- int prev_context = Error_context;
- int k;
-
- if (NSTRINGP(string)) Err("with-input-from-file: bad string", string);
- if (!STk_is_thunk(thunk)) Err("with-input-from-file: bad thunk", thunk);
-
- STk_curr_iport = UNBOUND; /* will not be changed if opening fails */
-
- if ((k = setjmp(env)) == 0) {
- Top_jmp_buf = &env;
- STk_curr_iport = makeport(CHARS(string), tc_iport, "r", TRUE);
- result = Apply(thunk, NIL);
- }
- /* restore normal error jmpbuf and current input port*/
- if (STk_curr_iport != UNBOUND) closeport(STk_curr_iport);
- STk_curr_iport = prev_iport;
- Top_jmp_buf = prev_env;
- Error_context = prev_context;
-
- if (k) /*propagate error */ longjmp(*Top_jmp_buf, k);
- return result;
- }
-
- PRIMITIVE STk_with_output_to_file(SCM string, SCM thunk)
- {
- jmp_buf env, *prev_env = Top_jmp_buf;
- SCM result, prev_oport = STk_curr_oport;
- int prev_context = Error_context;
- int k;
-
- if (NSTRINGP(string)) Err("with-output-to-file: bad string", string);
- if (!STk_is_thunk(thunk)) Err("with-output-to-file: bad thunk", thunk);
-
- STk_curr_oport = UNBOUND; /* will not be changed if opening fails */
-
- if ((k = setjmp(env)) == 0) {
- Top_jmp_buf = &env;
- STk_curr_oport = makeport(CHARS(string), tc_oport, "w", TRUE);
- result = Apply(thunk, NIL);
- }
- /* restore normal error jmpbuf and current output port*/
- if (STk_curr_oport != UNBOUND) closeport(STk_curr_oport);
- STk_curr_oport = prev_oport;
- Top_jmp_buf = prev_env;
- Error_context = prev_context;
-
- if (k) /*propagate error */ longjmp(*Top_jmp_buf, k);
- return result;
- }
-
-
- PRIMITIVE STk_open_input_file(SCM filename)
- {
- if (NSTRINGP(filename)) Err("open-input-file: bad file name", filename);
- return makeport(CHARS(filename), tc_iport, "r", TRUE);
- }
-
- PRIMITIVE STk_open_output_file(SCM filename)
- {
- if (NSTRINGP(filename)) Err("open-output-file: bad file name", filename);
- return makeport(CHARS(filename), tc_oport, "w", TRUE);
- }
-
- PRIMITIVE STk_close_input_port(SCM port)
- {
- if (!INP(port)) Err("close-input-port: not an input port", port);
- closeport(port);
-
- return UNDEFINED;
- }
-
- PRIMITIVE STk_close_output_port(SCM port)
- {
- if (!OUTP(port)) Err("close-output-port: not an output port", port);
- closeport(port);
-
- return UNDEFINED;
- }
-
- PRIMITIVE STk_read(SCM port)
- {
- port = verify_port("read", port, F_READ);
- return(STk_readf(PORT_FILE(port), FALSE));
- }
-
- PRIMITIVE STk_read_char(SCM port)
- {
- int c;
-
- port = verify_port("read-char", port, F_READ);
- c = Getc(PORT_FILE(port));
- return (c == EOF) ? STk_eof_object : STk_makechar(c);
- }
-
- PRIMITIVE STk_peek_char(SCM port)
- {
- int c;
-
- port = verify_port("peek-char", port, F_READ);
- c = Getc(PORT_FILE(port));
- Ungetc(c, PORT_FILE(port));
- return (c == EOF) ? STk_eof_object : STk_makechar(c);
- }
-
- PRIMITIVE STk_eof_objectp(SCM obj)
- {
- return (obj == STk_eof_object)? Truth : Ntruth;
- }
- #ifdef max
- #undef max
- #endif
- #define max(a,b) ((a)>(b)? (a) : (b))
-
- #ifdef _STDIO_USES_IOSTREAM /* GNU libc */
- # if defined(_IO_STDIO_H) || defined (linux)
- # define READ_DATA_PENDING(fp) (max(0,(fp)->_IO_read_end - (fp)->_IO_read_ptr))
- # else
- # define READ_DATA_PENDING(fp) (max(0,(fp)->_egptr - (fp)->_gptr))
- # endif
- #endif
- #if (!defined (READ_DATA_PENDING)) && defined __SLBF
- # define READ_DATA_PENDING(fp) (max(0,fp->_r))
- #endif
- #if !defined (READ_DATA_PENDING)
- # define READ_DATA_PENDING(fp) (fp->_cnt)
- #endif
-
- #ifdef WIN32
- PRIMITIVE STk_char_readyp(SCM port)
- {
- STk_panic("Not yet implemented!");
- }
- #else
- PRIMITIVE STk_char_readyp(SCM port)
- {
- port = verify_port("char-ready?", port, F_READ);
- if (Eof(PORT_FILE(port))) return Truth;
- if (ISPORTP(port)) /* !eof -> */ return Truth;
- else {
- /* First, see if characters are available in the buffer */
- if (READ_DATA_PENDING(PORT_FILE(port)))
- return Truth;
-
- #ifdef HAVE_SELECT
- {
- SELECT_MASK readfds;
- struct timeval timeout;
- int f = fileno(PORT_FILE(port));
-
- FD_ZERO(&readfds);
- FD_SET(f, &readfds);
- timeout.tv_sec = timeout.tv_usec = 0;
- return (select(f+1, &readfds, NULL, NULL, &timeout)) ? Truth : Ntruth;
- }
- #else
- # ifdef FIONREAD
- {
- int result;
-
- ioctl(fileno(PORT_FILE(port)), FIONREAD, &result);
- return result ? Truth : Ntruth;
- }
- # else
- return Truth;
- # endif
- #endif
- }
- }
- #endif
-
- PRIMITIVE STk_write(SCM expr, SCM port)
- {
- port = verify_port("write", port, F_WRITE);
- STk_print(expr, port, WRT_MODE);
- return UNDEFINED;
- }
-
- PRIMITIVE STk_display(SCM expr, SCM port)
- {
- port = verify_port("display", port, F_WRITE);
- STk_print(expr, port, DSP_MODE);
- return UNDEFINED;
- }
-
- PRIMITIVE STk_newline(SCM port)
- {
- port = verify_port("newline", port, F_WRITE);
- Putc('\n', PORT_FILE(port));
- return UNDEFINED;
- }
-
- PRIMITIVE STk_write_char(SCM c, SCM port)
- {
- if (NCHARP(c)) Err("write-char: not a character", c);
- port = verify_port("write-char", port, F_WRITE);
- Putc(CHAR(c), PORT_FILE(port));
- return UNDEFINED;
- }
-
- /*
- * The name `scheme_load' is needed because of a symbol table conflict
- * in libc. This is bogus, but what do you do.
- */
- PRIMITIVE STk_scheme_load(SCM filename)
- {
- if (NSTRINGP(filename)) Err("load: bad file name", filename);
- return STk_loadfile(CHARS(filename), 1);
- }
-
-
- /*
- *
- * STk bonus
- *
- */
-
- static SCM internal_format(SCM l,int len,int error)/* a very simple and poor one */
- {
- SCM port, fmt;
- int format_in_string = 0;
- char *p;
- FILE *f;
-
- if (error) {
- if (len < 1) Err("error: Bad list of parameters", l);
- format_in_string = 1;
- port = STk_open_output_string();
- len -= 1;
- }
- else {
- if (len < 2) Err("format: Bad list of parameters", l);
- port = CAR(l); l = CDR(l);
- len -= 2;
- }
- fmt = CAR(l); l = CDR(l);
-
- if (BOOLEANP(port)){
- if (port == Truth) port = STk_curr_oport;
- else {
- format_in_string = 1;
- port= STk_open_output_string();
- }
- }
-
- verify_port(error? "error": "format", port, F_WRITE);
- if (NSTRINGP(fmt)) Err("format: bad format string", fmt);
-
- f = PORT_FILE(port);
-
- for(p=CHARS(fmt); *p; p++) {
- if (*p == '~') {
- switch(*(++p)) {
- case 'S':
- case 's':
- case 'A':
- case 'a': if (len-- > 0) {
- STk_print(CAR(l),
- port,
- (tolower(*p) == 's')? WRT_MODE: DSP_MODE);
- l = CDR(l);
- }
- else Err("format: too much ~ in format string", l);
- continue;
- case '%': Putc('\n', f);
- continue;
- case '~': Putc('~', f);
- continue;
- default: Putc('~', f);
- /* NO BREAK */
- }
- }
- Putc(*p, f);
- }
-
- if (NNULLP(l)) Err("format: too few ~ in format string", l);
-
- return format_in_string ? STk_get_output_string(port) : UNDEFINED;
- }
-
- PRIMITIVE STk_format(SCM l, int len)
- {
- return internal_format(l, len, FALSE);
- }
-
- PRIMITIVE STk_error(SCM l, int len)
- {
- /* Set context to ERR_OK but keep the bit indicating if error must be caught */
- Error_context = ERR_OK | (Error_context & ERR_IGNORED);
-
- Err(CHARS(internal_format(l, len, TRUE)), NIL);
- return UNDEFINED; /* for compiler */
- }
-
- PRIMITIVE STk_try_load(SCM filename)
- {
- if (NSTRINGP(filename)) Err("try-load: bad file name", filename);
-
- return STk_loadfile(CHARS(filename), FALSE);
- }
-
- PRIMITIVE STk_open_file(SCM filename, SCM mode)
- {
- int type;
-
-
- if (NSTRINGP(filename)) Err("open-file: bad file name", filename);
- if (NSTRINGP(mode) || CHARS(mode)[1] != '\0') goto Error;
-
- switch (CHARS(mode)[0]) {
- case 'a':
- case 'w': type = tc_oport; break;
- case 'r': type = tc_iport; break;
- default: ;
- Error: Err("open-file: bad mode", mode);
- }
- return(makeport(CHARS(filename), type, CHARS(mode), FALSE));
- }
-
- PRIMITIVE STk_close_port(SCM port)
- {
- if (INP(port) || OUTP(port)) closeport(port);
- else Err("close-port: bad port", port);
- return UNDEFINED;
- }
-
- PRIMITIVE STk_read_line(SCM port)
- {
- FILE *f;
- int c, i, size = 128;
- char *buff = (char *) must_malloc(size);
- SCM res;
-
- port = verify_port("read-line", port, F_READ);
- f = PORT_FILE(port);
- for (i = 0; ; i++) {
- switch (c = Getc(f)) {
- case EOF: if (i == 0) { free(buff); return STk_eof_object; }
- case '\n': res = STk_makestrg(i, buff); free(buff); return res;
- default: if (i == size) {
- size += size / 2;
- buff = must_realloc(buff, size);
- }
- buff[i] = c;
- }
- }
- }
-
- PRIMITIVE STk_flush(SCM port)
- {
- int code;
-
- port = verify_port("flush", port, F_WRITE|F_READ);
- code = fflush(PORT_FILE(port));
-
- if (code == EOF) Err("flush: cannot flush buffer", port);
-
- return UNDEFINED;
- }
-
- /******************************************************************************
- *
- * Autoload stuff
- *
- ******************************************************************************/
-
- static SCM list_of_files = NULL;
-
- static SCM make_autoload(SCM file)
- {
- SCM z;
-
- NEWCELL(z, tc_autoload);
- CAR(z) = file;
- return z;
- }
-
- void STk_do_autoload(SCM var)
- {
- SCM file, autoload;
-
- autoload = VCELL(var); file = CAR(autoload);
-
- /* Retain in a list, files which are currently autoloaded to avoid mult. load */
- if (!list_of_files) {
- list_of_files = NIL;
- STk_gc_protect(&list_of_files);
- }
-
- if (STk_member(file, list_of_files) != Ntruth) return;
- list_of_files = Cons(file, list_of_files);
-
- STk_loadfile(CHARS(file), TRUE);
-
- list_of_files = CDR(list_of_files);
-
- if (TYPEP(VCELL(var), tc_autoload)) {
- Err("autoload: symbol was not defined", var);
- }
- }
-
- PRIMITIVE STk_autoload(SCM l, SCM env, int len)
- {
- SCM file;
-
- if (len < 2) Err("autoload: bad parameter list", l);
-
- file = CAR(l);
- if (NSTRINGP(file)) Err("autoload: bad file name", file);
-
- for (l = CDR(l); NNULLP(l); l = CDR(l)) {
- if (NSYMBOLP(CAR(l))) Err("autoload: bad symbol", CAR(l));
- VCELL(CAR(l)) = make_autoload(file);
- }
- return UNDEFINED;
- }
-
- PRIMITIVE STk_autoloadp(SCM l, SCM env, int len)
- {
- if (len != 1 || NSYMBOLP(CAR(l)))
- Err("autoload?: bad symbol", l);
-
- return TYPEP(CAR(l), tc_autoload) ? Truth: Ntruth;
- }
-
- #ifdef USE_TK
- /******************************************************************************
- *
- * Port event management
- *
- ******************************************************************************/
-
- static void apply_file_closure(SCM closure)
- {
- Apply(closure, NIL);
- }
-
-
- static SCM when_port_ready(SCM port, SCM closure, char *name, int mode)
- {
- char str[50];
- Tcl_File f;
-
- if (NIPORTP(port) && NOPORTP(port)) {
- sprintf(str, "%s: bad port", name);
- STk_err(str, port);
- }
-
- if (closure == UNBOUND) {
- /* Return the current handler closure */
- return ((mode == TCL_READABLE)? PORT_REVENT(port): PORT_WEVENT(port));
- }
-
- f = Tcl_GetFile((ClientData) fileno(PORT_FILE(port)), TCL_UNIX_FD);
-
- if (closure == Ntruth) {
- Tcl_DeleteFileHandler(f);
- if (mode == TCL_READABLE)
- PORT_REVENT(port) = Ntruth;
- else
- PORT_WEVENT(port) = Ntruth;
- }
- else {
- if (STk_procedurep(closure) == Ntruth) {
- sprintf(str, "%s: bad closure", name);
- STk_err(str, closure);
- }
-
- Tcl_CreateFileHandler(f, mode, (Tcl_FileProc *) apply_file_closure,
- (ClientData) closure);
- if (mode == TCL_READABLE)
- PORT_REVENT(port) = closure;
- else
- PORT_WEVENT(port) = closure;
- }
- return UNDEFINED;
- }
-
-
- PRIMITIVE STk_when_port_readable(SCM port, SCM closure)
- {
- return when_port_ready(port, closure, "when-port-readable", TCL_READABLE);
- }
-
-
- PRIMITIVE STk_when_port_writable(SCM port, SCM closure)
- {
- return when_port_ready(port, closure, "when-port-writable", TCL_WRITABLE);
- }
- #endif
-