-export CC=gcc34
-export CFLAGS="-lm -pedantic -Wall -Winline -O3 -march=pentium4 -fomit-frame-pointer"
+export CC=gcc
+export CFLAGS="-lm -g -Wall -Wno-long-long -Wno-inline"
$CC $CFLAGS -o f native/*.c
-
-strip f
DEFER: server-socket
DEFER: close-fd
DEFER: accept-fd
+DEFER: can-read-line?
+DEFER: add-read-line-io-task
DEFER: read-line-fd-8
+DEFER: can-write?
+DEFER: add-write-io-task
DEFER: write-fd-8
-DEFER: flush-fd
+DEFER: next-io-task
IN: parser
DEFER: str>float
server-socket
close-fd
accept-fd
+ can-read-line?
+ add-read-line-io-task
read-line-fd-8
+ can-write?
+ add-write-io-task
write-fd-8
- flush-fd
+ next-io-task
room
os-env
millis
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
IN: io-internals
+USE: combinators
+USE: continuations
USE: kernel
USE: namespaces
-USE: combinators
+USE: stack
+USE: strings
: stdin 0 getenv ;
: stdout 1 getenv ;
: stderr 2 getenv ;
+
+: flush-fd ( port -- )
+ [ swap add-write-io-task next-io-task drop ( call ) ] callcc0 ;
+
+: wait-to-write ( len port -- )
+ tuck can-write? [ drop ] [ flush-fd ] ifte ;
+
+: blocking-write ( str port -- )
+ over
+ dup string? [ str-length ] [ drop 1 ] ifte
+ over wait-to-write write-fd-8 ;
+
+: fill-fd ( port -- )
+ [ swap add-read-line-io-task next-io-task drop ( call ) ] callcc0 ;
+
+: wait-to-read-line ( port -- )
+ dup can-read-line? [ drop ] [ fill-fd ] ifte ;
+
+: blocking-read-line ( port -- line )
+ dup wait-to-read-line read-line-fd-8 dup [ sbuf>str ] when ;
IN: streams
USE: combinators
+USE: continuations
USE: io-internals
USE: errors
USE: kernel
"in" set
( str -- )
- [ "out" get write-fd-8 ] "fwrite" set
+ [ "out" get blocking-write ] "fwrite" set
( -- str )
- [
- "in" get read-line-fd-8
- ] "freadln" set
+ [ "in" get dup [ blocking-read-line ] when ] "freadln" set
( -- )
- [
- "out" get [ flush-fd ] when*
- ] "fflush" set
+ [ "out" get [ flush-fd ] when* ] "fflush" set
( -- )
[
"in" get [ close-fd ] when*
- "out" get [ close-fd ] when*
+ "out" get [ dup flush-fd close-fd ] when*
] "fclose" set
] extend ;
-: <file-stream> ( path read? write? -- stream )
- open-file dup <fd-stream> ;
-
: <filecr> ( path -- stream )
- t f <file-stream> ;
+ t f open-file f <fd-stream> ;
: <filecw> ( path -- stream )
- f t <file-stream> ;
+ f t open-file f swap <fd-stream> ;
: <filebr> ( path -- stream )
- t f <file-stream> ;
+ <filecr> ;
: <filebw> ( path -- stream )
- f t <file-stream> ;
+ <filecw> ;
: <server> ( port -- stream )
#! Starts listening on localhost:port. Returns a stream that
void fatal_error(char* msg, CELL tagged)
{
- printf("Fatal error: %s %ld\n",msg,tagged);
+ fprintf(stderr,"Fatal error: %s %ld\n",msg,tagged);
exit(1);
}
void critical_error(char* msg, CELL tagged)
{
- printf("Critical error: %s %ld\n",msg,tagged);
+ fprintf(stderr,"Critical error: %s %ld\n",msg,tagged);
save_image("factor.crash.image");
exit(1);
}
tag_cons(cons(tag_fixnum(max),F)))));
general_error(ERROR_RANGE,tag_cons(c));
}
-
-void io_error(const char* func)
-{
- STRING* function = from_c_string(func);
- STRING* error = from_c_string(strerror(errno));
-
- CONS* c = cons(tag_object(function),tag_cons(
- cons(tag_object(error),F)));
- general_error(ERROR_IO,tag_cons(c));
-}
void general_error(CELL error, CELL tagged);
void type_error(CELL type, CELL tagged);
void range_error(CELL tagged, CELL index, CELL max);
-void io_error(const char* func);
init_arena(DEFAULT_ARENA);
load_image(argv[1]);
init_stacks();
+ init_iomux();
init_io();
run();
void init_io(void)
{
- env.user[STDIN_ENV] = port(0);
- set_nonblocking(0);
- env.user[STDOUT_ENV] = port(1);
- set_nonblocking(1);
- env.user[STDERR_ENV] = port(2);
- /* set_nonblocking(2); */
+ env.user[STDIN_ENV] = tag_object(port(0));
+ env.user[STDOUT_ENV] = tag_object(port(1));
+ env.user[STDERR_ENV] = tag_object(port(2));
+}
+
+bool can_read_line(PORT* port)
+{
+ return false;
+}
+
+void primitive_can_read_line(void)
+{
+ PORT* port = untag_port(dpop());
+ dpush(tag_boolean(can_read_line(port)));
}
/* Return true if something was read */
if(amount == -1)
{
if(errno != EAGAIN)
- io_error(__FUNCTION__);
+ io_error(port,__FUNCTION__);
return false;
}
else
}
}
-READLINE_STAT read_line_step(PORT* port)
+bool read_line_step(PORT* port)
{
int i;
char ch;
- SBUF* line = port->line;
-
- if(port->buf_pos >= port->buf_fill)
- {
- if(!read_step(port))
- return READLINE_WAIT;
-
- if(port->buf_fill == 0)
- return READLINE_EOF;
- }
+ SBUF* line = untag_sbuf(port->line);
for(i = port->buf_pos; i < port->buf_fill; i++)
{
if(ch == '\n')
{
port->buf_pos = i + 1;
- return READLINE_EOL;
+ return true;
}
else
set_sbuf_nth(line,line->top,ch);
/* We've reached the end of the above loop, without seeing a newline
or EOF, so read again */
- return READLINE_AGAIN;
+ return false;
}
void primitive_read_line_fd_8(void)
{
PORT* port = untag_port(dpeek());
- SBUF* line;
- READLINE_STAT state;
-
- init_buffer(port,B_READ);
- if(port->line == NULL)
- port->line = sbuf(LINE_SIZE);
- else
- port->line->top = 0;
- line = port->line;
-
- add_io_task(IO_TASK_READ_LINE,port,F);
-
- for(;;)
- {
- state = read_line_step(port);
- if(state == READLINE_WAIT)
- iomux();
- else if(state == READLINE_EOF && line->top == 0)
- {
- /* didn't read anything before EOF */
- drepl(F);
- break;
- }
- else if(state == READLINE_EOL)
- {
- drepl(tag_object(sbuf_to_string(line)));
- break;
- }
- }
+ drepl(port->line);
+ port->line = F;
- remove_io_task(IO_TASK_READ_LINE,port);
}
/* Return true if write was done */
if(amount == -1)
{
if(errno != EAGAIN)
- io_error(__FUNCTION__);
+ io_error(port,__FUNCTION__);
return false;
}
else
}
}
-/* keep writing to the stream until everything is written */
-void flush_buffer(PORT* port)
+bool can_write(PORT* port, FIXNUM len)
{
- IO_TASK* task;
- if(port->buf_mode != B_WRITE || port->buf_fill == 0)
- return;
+ CELL buf_capacity;
- task = add_io_task(IO_TASK_WRITE,port,F);
-
- for(;;)
+ switch(port->buf_mode)
{
- if(port->buf_fill == port->buf_pos)
- break;
-
- if(!write_step(port))
- iomux();
+ case B_NONE:
+ return true;
+ case B_READ_LINE:
+ return false;
+ case B_WRITE:
+ buf_capacity = port->buffer->capacity * CHARS;
+ /* Is the string longer than the buffer? */
+ if(port->buf_fill == 0 && len > buf_capacity)
+ {
+ /* Increase the buffer to fit the string */
+ port->buffer = allot_string(len / CHARS + 1);
+ return true;
+ }
+ else
+ return (port->buf_fill + len <= buf_capacity);
+ default:
+ critical_error("Bad buf_mode",port->buf_mode);
+ return false;
}
+}
- remove_io_task(IO_TASK_WRITE,port);
-
- port->buf_pos = 0;
- port->buf_fill = 0;
+void primitive_can_write(void)
+{
+ PORT* port = untag_port(dpop());
+ FIXNUM len = to_fixnum(dpop());
+ dpush(tag_boolean(can_write(port,len)));
}
void write_fd_char_8(PORT* port, FIXNUM ch)
{
char c = (char)ch;
- init_buffer(port,B_WRITE);
+ if(!can_write(port,1))
+ io_error(port,__FUNCTION__);
- /* Is the buffer full? */
- if(port->buf_fill == port->buffer->capacity * CHARS)
- flush_buffer(port);
+ init_buffer(port,B_WRITE);
bput((CELL)port->buffer + sizeof(STRING) + port->buf_fill,c);
port->buf_fill++;
void write_fd_string_8(PORT* port, STRING* str)
{
- char* c_str = to_c_string(str);
+ char* c_str;
- init_buffer(port,B_WRITE);
+ /* Note this ensures the buffer is large enough to fit the string */
+ if(!can_write(port,str->capacity))
+ io_error(port,__FUNCTION__);
- /* Is the string longer than the buffer? */
- if(str->capacity > port->buffer->capacity * CHARS)
- {
- flush_buffer(port);
+ init_buffer(port,B_WRITE);
- /* Increase the buffer to fit the string */
- port->buffer = allot_string(str->capacity / CHARS + 1);
- }
- /* Is there enough room in the buffer? If not, flush */
- if(port->buf_fill + str->capacity
- > port->buffer->capacity * CHARS)
- {
- flush_buffer(port);
- }
+ c_str = to_c_string(str);
/* Append string to buffer */
memcpy((void*)((CELL)port->buffer + sizeof(STRING)
}
}
-void primitive_flush_fd(void)
-{
- PORT* port = untag_port(dpop());
- flush_buffer(port);
-}
-
void primitive_close_fd(void)
{
+ /* This does not flush. */
PORT* port = untag_port(dpop());
- flush_buffer(port);
close(port->fd);
}
-void set_nonblocking(int fd)
+void io_error(PORT* port, const char* func)
{
- if(fcntl(fd,F_SETFL,O_NONBLOCK,1) == -1)
- io_error(__FUNCTION__);
+ STRING* function = from_c_string(func);
+ STRING* error = from_c_string(strerror(errno));
+
+ CONS* c = cons(tag_object(function),tag_cons(
+ cons(tag_object(error),F)));
+
+ general_error(ERROR_IO,tag_cons(c));
}
#define LINE_SIZE 80
#define BUF_SIZE (32 * 1024)
+bool can_read_line(PORT* port);
+void primitive_can_read_line(void);
bool read_step(PORT* port);
+bool read_line_step(PORT* port);
-/* read_line_step() return values */
-typedef enum {
- READLINE_WAIT, /* means we have to wait for more I/O */
- READLINE_AGAIN,
- READLINE_EOL,
- READLINE_EOF
-} READLINE_STAT;
-
-READLINE_STAT read_line_step(PORT* port);
bool write_step(PORT* port);
void flush_buffer(PORT* port);
void init_io(void);
void primitive_read_line_fd_8(void);
+bool can_write(PORT* port, FIXNUM len);
+void primitive_can_write(void);
void write_fd_char_8(PORT* port, FIXNUM ch);
void write_fd_string_8(PORT* port, STRING* str);
void primitive_write_fd_8(void);
-void primitive_flush_fd(void);
void primitive_close_fd(void);
-void set_nonblocking(int fd);
+void io_error(PORT* port, const char* func);
int fd;
if(read && write)
- mode = O_RDWR | O_CREAT | O_NONBLOCK;
+ mode = O_RDWR | O_CREAT;
else if(read)
- mode = O_RDONLY | O_NONBLOCK;
+ mode = O_RDONLY;
else if(write)
- mode = O_WRONLY | O_CREAT | O_TRUNC | O_NONBLOCK;
+ mode = O_WRONLY | O_CREAT | O_TRUNC;
else
- mode = O_NONBLOCK;
+ mode = 0;
fd = open(path,mode);
if(fd < 0)
- io_error(__FUNCTION__);
+ io_error(NULL,__FUNCTION__);
- dpush(port(fd));
+ dpush(tag_object(port(fd)));
}
FD_ZERO(fdset);
for(i = 0; i < FD_SETSIZE; i++)
{
- read_io_tasks[i].port = F;
- read_io_tasks[i].callback = F;
+ io_tasks[i].port = F;
+ io_tasks[i].callback = F;
}
}
init_io_tasks(&write_fd_set,write_io_tasks);
}
-IO_TASK* add_io_task_impl(
+IO_TASK* add_io_task(
IO_TASK_TYPE type,
PORT* port,
CELL callback,
{
int fd = port->fd;
+ /* if(io_tasks[fd].port != F)
+ critical_error("Adding I/O task twice",fd); */
+
io_tasks[fd].type = type;
io_tasks[fd].port = tag_object(port);
io_tasks[fd].callback = callback;
return &io_tasks[fd];
}
-IO_TASK* add_io_task(IO_TASK_TYPE type, PORT* port, CELL callback)
+void primitive_add_read_line_io_task(void)
{
- switch(type)
- {
- case IO_TASK_READ_LINE:
- case IO_TASK_READ_COUNT:
- return add_io_task_impl(type,port,callback,
- read_io_tasks,&read_fd_count);
- case IO_TASK_WRITE:
- return add_io_task_impl(type,port,callback,
- write_io_tasks,&write_fd_count);
- default:
- fatal_error("Invalid IO_TASK_TYPE",type);
- return NULL;
- }
+ PORT* port = untag_port(dpop());
+ CELL callback = dpop();
+ add_io_task(IO_TASK_READ_LINE,port,callback,
+ read_io_tasks,&read_fd_count);
}
-void remove_io_task_impl(
+void primitive_add_write_io_task(void)
+{
+ PORT* port = untag_port(dpop());
+ CELL callback = dpop();
+ add_io_task(IO_TASK_WRITE,port,callback,
+ write_io_tasks,&write_fd_count);
+}
+
+void remove_io_task(
IO_TASK_TYPE type,
PORT* port,
IO_TASK* io_tasks,
*fd_count = *fd_count - 1;
}
-void remove_io_task(IO_TASK_TYPE type, PORT* port)
+void remove_io_tasks(PORT* port)
{
- switch(type)
+ remove_io_task(IO_TASK_READ_LINE,port,
+ read_io_tasks,&read_fd_count);
+ remove_io_task(IO_TASK_WRITE,port,
+ write_io_tasks,&write_fd_count);
+}
+
+bool set_up_fd_set(fd_set* fdset, int fd_count, IO_TASK* io_tasks)
+{
+ bool retval = false;
+ int i;
+
+ FD_ZERO(fdset);
+
+ for(i = 0; i < fd_count; i++)
{
- case IO_TASK_READ_LINE:
- case IO_TASK_READ_COUNT:
- remove_io_task_impl(type,port,read_io_tasks,&read_fd_count);
- break;
- case IO_TASK_WRITE:
- remove_io_task_impl(type,port,write_io_tasks,&write_fd_count);
- break;
+ if(typep(PORT_TYPE,io_tasks[i].port))
+ {
+ retval = true;
+ FD_SET(i,fdset);
+ }
+ }
+
+ return retval;
+}
+
+bool perform_read_line_io_task(PORT* port)
+{
+ init_buffer(port,B_READ_LINE);
+ if(port->buf_pos >= port->buf_fill)
+ {
+ if(!read_step(port))
+ return false;
+ }
+
+ if(port->buf_fill == 0)
+ {
+ /* EOF */
+ port->line = F;
+ return true;
}
+ else
+ return read_line_step(port);
}
-void perform_io_task(IO_TASK* task)
+bool perform_write_io_task(PORT* port)
{
- if(task->port == F)
- return;
+ init_buffer(port,B_WRITE);
+ if(write_step(port))
+ {
+ if(port->buf_pos == port->buf_fill)
+ {
+ /* All written */
+ port->buf_pos = 0;
+ port->buf_fill = 0;
+ return true;
+ }
+ }
+ return false;
+}
+CELL perform_io_task(IO_TASK* task)
+{
+ PORT* port = untag_port(task->port);
+ CELL callback = task->callback;
switch(task->type)
{
case IO_TASK_READ_LINE:
-
- break;
+ remove_io_task(IO_TASK_READ_LINE,port,
+ read_io_tasks,&read_fd_count);
+ if(perform_read_line_io_task(port))
+ return callback;
+ else
+ {
+ add_io_task(IO_TASK_READ_LINE,port,
+ callback,read_io_tasks,
+ &read_fd_count);
+ return F;
+ }
case IO_TASK_WRITE:
- write_step(untag_port(task->port));
- break;
+ remove_io_task(IO_TASK_WRITE,port,
+ write_io_tasks,&write_fd_count);
+ if(perform_write_io_task(port))
+ return callback;
+ else
+ {
+ add_io_task(IO_TASK_WRITE,port,
+ callback,write_io_tasks,
+ &write_fd_count);
+ return F;
+ }
default:
critical_error("Bad I/O task",task->type);
- break;
+ return F;
}
}
-bool set_up_fd_set(fd_set* fdset, IO_TASK* io_tasks)
+CELL perform_io_tasks(fd_set* fdset, int fd_count, IO_TASK* io_tasks)
{
- bool retval = false;
-
int i;
- for(i = 0; i < read_fd_count; i++)
+ CELL callback;
+
+ for(i = 0; i < fd_count; i++)
{
- if(read_io_tasks[i].port != F)
+ if(FD_ISSET(i,fdset))
{
- retval = true;
- FD_SET(i,&read_fd_set);
+ if(io_tasks[i].port == F)
+ critical_error("select() returned fd for non-existent task",i);
+ else
+ {
+ callback = perform_io_task(&io_tasks[i]);
+ if(callback != F)
+ return callback;
+ }
}
}
-
- return retval;
+
+ return F;
}
/* Wait for I/O and return a callback. */
-CELL iomux(void)
+CELL next_io_task(void)
{
- bool reading = set_up_fd_set(&read_fd_set,read_io_tasks);
- bool writing = set_up_fd_set(&write_fd_set,write_io_tasks);
+ bool reading = set_up_fd_set(&read_fd_set,
+ read_fd_count,read_io_tasks);
+ bool writing = set_up_fd_set(&write_fd_set,
+ write_fd_count,write_io_tasks);
+
+ CELL callback;
if(!reading && !writing)
- fatal_error("iomux() called with no IO tasks",0);
+ critical_error("next_io_task() called with no IO tasks",0);
select(read_fd_count > write_fd_count
? read_fd_count : write_fd_count,
(writing ? &write_fd_set : NULL),
NULL,NULL);
- /* for(i = 0; i < read_fd_count; i++)
- perform_io_task(&read_io_tasks[i]);
+ callback = perform_io_tasks(&read_fd_set,read_fd_count,read_io_tasks);
+ if(callback != F)
+ return callback;
- for(i = 0; i < write_fd_count; i++)
- perform_io_task(&write_io_tasks[i]); */
+ return perform_io_tasks(&write_fd_set,write_fd_count,write_io_tasks);
+}
- return F;
+void primitive_next_io_task(void)
+{
+ dpush(next_io_task());
}
void collect_io_tasks(void)
void init_io_tasks(fd_set* fd_set, IO_TASK* io_tasks);
void init_iomux(void);
-IO_TASK* add_io_task_impl(
+IO_TASK* add_io_task(
IO_TASK_TYPE type,
PORT* port,
CELL callback,
IO_TASK* io_tasks,
int* fd_count);
-IO_TASK* add_io_task(IO_TASK_TYPE type, PORT* port, CELL callback);
-void remove_io_task_impl(
+void primitive_add_read_line_io_task(void);
+void primitive_add_write_io_task(void);
+void remove_io_task(
IO_TASK_TYPE type,
PORT* port,
IO_TASK* io_tasks,
int* fd_count);
-void remove_io_task(IO_TASK_TYPE type, PORT* port);
-void perform_io_task(IO_TASK* task);
-bool set_up_fd_set(fd_set* fdset, IO_TASK* io_tasks);
-CELL iomux(void);
+void remove_io_tasks(PORT* port);
+bool set_up_fd_set(fd_set* fdset, int fd_count, IO_TASK* io_tasks);
+bool perform_read_line_io_task(PORT* port);
+bool perform_write_io_task(PORT* port);
+CELL perform_io_task(IO_TASK* task);
+CELL perform_io_tasks(fd_set* fdset, int fd_count, IO_TASK* io_tasks);
+CELL next_io_task(void);
+void primitive_next_io_task(void);
void collect_io_tasks(void);
return p;
}
-CELL port(CELL fd)
+PORT* port(CELL fd)
{
PORT* port = allot_object(PORT_TYPE,sizeof(PORT));
port->fd = fd;
port->buffer = NULL;
- port->line = NULL;
+ port->line = F;
port->buf_mode = B_NONE;
port->buf_fill = 0;
port->buf_pos = 0;
- return tag_object(port);
+
+ if(fcntl(port->fd,F_SETFL,O_NONBLOCK,1) == -1)
+ io_error(port,__FUNCTION__);
+
+ return port;
}
void primitive_portp(void)
{
port->buf_fill = port->buf_pos = 0;
port->buf_mode = mode;
+
+ if(mode == B_READ_LINE)
+ port->line = tag_object(sbuf(LINE_SIZE));
+ }
+ else if(port->buf_mode == B_READ_LINE)
+ {
+ if(port->line == F)
+ port->line = tag_object(sbuf(LINE_SIZE));
+ else
+ untag_sbuf(port->line)->top = 0;
}
}
port->fd = -1;
if(port->buffer != 0)
port->buffer = fixup_untagged_string(port->buffer);
- if(port->line != 0)
- {
- port->line = (SBUF*)((CELL)port->line
- + (active->base - relocation_base));
- }
+ fixup(&port->line);
}
void collect_port(PORT* port)
{
if(port->buffer != 0)
port->buffer = copy_untagged_string(port->buffer);
- if(port->line != 0)
- {
- port->line = (SBUF*)copy_untagged_object(
- port->line,sizeof(SBUF));
- }
+ copy_object(&port->line);
}
/* Buffer mode */
-typedef enum { B_READ, B_WRITE, B_NONE } B_MODE;
+typedef enum { B_READ_LINE, B_WRITE, B_NONE } B_MODE;
typedef struct {
CELL header;
FIXNUM fd;
STRING* buffer;
- /* partial line used by read_line_fd */
- SBUF* line;
+ /* tagged partial line used by read_line_fd */
+ CELL line;
/* one of B_READ, B_WRITE or B_NONE */
B_MODE buf_mode;
/* top of buffer */
} PORT;
PORT* untag_port(CELL tagged);
-CELL port(CELL fd);
+PORT* port(CELL fd);
void init_buffer(PORT* port, int mode);
void primitive_portp(void);
void fixup_port(PORT* port);
primitive_server_socket,
primitive_close_fd,
primitive_accept_fd,
+ primitive_can_read_line,
+ primitive_add_read_line_io_task,
primitive_read_line_fd_8,
+ primitive_can_write,
+ primitive_add_write_io_task,
primitive_write_fd_8,
- primitive_flush_fd,
+ primitive_next_io_task,
primitive_room,
primitive_os_env,
primitive_millis,
extern XT primitives[];
-#define PRIMITIVE_COUNT 129
+#define PRIMITIVE_COUNT 133
CELL primitive_to_xt(CELL primitive);
sock = socket(PF_INET, SOCK_STREAM, 0);
if(sock < 0)
- io_error(__FUNCTION__);
+ io_error(NULL,__FUNCTION__);
/* Reuse port number */
if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&reuseaddr,sizeof(int)) < 0)
- io_error(__FUNCTION__);
+ io_error(NULL,__FUNCTION__);
/* Give the socket a name */
name.sin_family = AF_INET;
if(bind(sock,(struct sockaddr *)&name, sizeof(name)) < 0)
{
close(sock);
- io_error(__FUNCTION__);
+ io_error(NULL,__FUNCTION__);
}
/* Start listening for connections */
if(listen(sock,1) < 0)
{
close(sock);
- io_error(__FUNCTION__);
+ io_error(NULL,__FUNCTION__);
}
return sock;
void primitive_server_socket(void)
{
CHAR p = (CHAR)to_fixnum(dpop());
- dpush(port(make_server_socket(p)));
+ dpush(tag_object(port(make_server_socket(p))));
}
int accept_connection(int sock)
int new = accept(sock,(struct sockaddr *)&clientname,&size);
if(new < 0)
- io_error(__FUNCTION__);
-
- set_nonblocking(new);
+ io_error(NULL,__FUNCTION__);
printf("Connection from host %s, port %hd.\n",
inet_ntoa(clientname.sin_addr),
void primitive_accept_fd(void)
{
PORT* p = untag_port(dpop());
- dpush(port(accept_connection(p->fd)));
+ PORT* new = port(accept_connection(p->fd));
+ dpush(tag_object(new));
}