2004-12-10 22:47:03 -05:00
|
|
|
#include "../factor.h"
|
2004-08-20 01:49:14 -04:00
|
|
|
|
|
|
|
/* Return true if write was done */
|
2004-12-10 21:46:42 -05:00
|
|
|
void write_step(F_PORT* port)
|
2004-08-20 01:49:14 -04:00
|
|
|
{
|
2004-12-10 21:46:42 -05:00
|
|
|
BYTE* chars = (BYTE*)untag_string(port->buffer) + sizeof(F_STRING);
|
2004-08-20 01:49:14 -04:00
|
|
|
|
2004-12-10 21:46:42 -05:00
|
|
|
F_FIXNUM amount = write(port->fd,chars + port->buf_pos,
|
2004-08-20 01:49:14 -04:00
|
|
|
port->buf_fill - port->buf_pos);
|
|
|
|
|
|
|
|
if(amount == -1)
|
|
|
|
{
|
|
|
|
if(errno != EAGAIN)
|
2004-08-20 21:16:47 -04:00
|
|
|
postpone_io_error(port,__FUNCTION__);
|
2004-08-20 01:49:14 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
port->buf_pos += amount;
|
|
|
|
}
|
|
|
|
|
2004-12-10 21:46:42 -05:00
|
|
|
bool can_write(F_PORT* port, F_FIXNUM len)
|
2004-08-20 01:49:14 -04:00
|
|
|
{
|
|
|
|
CELL buf_capacity;
|
|
|
|
|
2004-08-24 18:01:36 -04:00
|
|
|
if(port->type != PORT_WRITE)
|
|
|
|
general_error(ERROR_INCOMPATIBLE_PORT,tag_object(port));
|
|
|
|
|
2005-02-20 19:03:37 -05:00
|
|
|
buf_capacity = string_capacity(untag_string(port->buffer)) * CHARS;
|
2004-08-29 01:04:42 -04:00
|
|
|
/* Is the string longer than the buffer? */
|
|
|
|
if(port->buf_fill == 0 && len > buf_capacity)
|
2004-08-20 01:49:14 -04:00
|
|
|
{
|
2004-08-29 01:04:42 -04:00
|
|
|
/* Increase the buffer to fit the string */
|
2004-11-27 22:26:05 -05:00
|
|
|
port->buffer = tag_object(allot_string(len / CHARS + 1));
|
2004-08-29 01:04:42 -04:00
|
|
|
return true;
|
2004-08-20 01:49:14 -04:00
|
|
|
}
|
2004-08-29 01:04:42 -04:00
|
|
|
else
|
|
|
|
return (port->buf_fill + len <= buf_capacity);
|
2004-08-20 01:49:14 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void primitive_can_write(void)
|
|
|
|
{
|
2004-12-10 21:46:42 -05:00
|
|
|
F_PORT* port;
|
|
|
|
F_FIXNUM len;
|
2004-10-12 23:49:43 -04:00
|
|
|
|
|
|
|
maybe_garbage_collection();
|
|
|
|
|
|
|
|
port = untag_port(dpop());
|
|
|
|
len = to_fixnum(dpop());
|
2004-09-02 21:51:19 -04:00
|
|
|
pending_io_error(port);
|
2004-11-08 22:36:51 -05:00
|
|
|
box_boolean(can_write(port,len));
|
2004-08-20 01:49:14 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void primitive_add_write_io_task(void)
|
|
|
|
{
|
2004-10-12 23:49:43 -04:00
|
|
|
CELL callback, port;
|
|
|
|
|
|
|
|
maybe_garbage_collection();
|
|
|
|
|
|
|
|
callback = dpop();
|
|
|
|
port = dpop();
|
2004-08-28 22:25:59 -04:00
|
|
|
add_io_task(IO_TASK_WRITE,port,F,callback,
|
2004-08-20 01:49:14 -04:00
|
|
|
write_io_tasks,&write_fd_count);
|
|
|
|
}
|
|
|
|
|
2004-12-10 21:46:42 -05:00
|
|
|
bool perform_write_io_task(F_PORT* port)
|
2004-08-20 01:49:14 -04:00
|
|
|
{
|
2004-08-23 20:44:58 -04:00
|
|
|
if(port->buf_pos == port->buf_fill || port->io_error != F)
|
2004-08-20 01:49:14 -04:00
|
|
|
{
|
2004-08-23 20:44:58 -04:00
|
|
|
/* Nothing to write */
|
|
|
|
port->buf_pos = 0;
|
|
|
|
port->buf_fill = 0;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
write_step(port);
|
|
|
|
return false;
|
2004-08-20 01:49:14 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-12-10 21:46:42 -05:00
|
|
|
void write_char_8(F_PORT* port, F_FIXNUM ch)
|
2004-08-20 01:49:14 -04:00
|
|
|
{
|
2004-09-02 22:53:50 -04:00
|
|
|
BYTE c = (BYTE)ch;
|
2004-08-20 01:49:14 -04:00
|
|
|
|
2004-09-02 21:51:19 -04:00
|
|
|
pending_io_error(port);
|
|
|
|
|
2004-08-20 01:49:14 -04:00
|
|
|
if(!can_write(port,1))
|
|
|
|
io_error(__FUNCTION__);
|
|
|
|
|
2004-12-10 21:46:42 -05:00
|
|
|
bput((CELL)untag_string(port->buffer) + sizeof(F_STRING) + port->buf_fill,c);
|
2004-08-20 01:49:14 -04:00
|
|
|
port->buf_fill++;
|
|
|
|
}
|
|
|
|
|
2004-08-28 22:25:59 -04:00
|
|
|
/* Caller must ensure buffer is of the right size. */
|
2005-03-03 20:43:55 -05:00
|
|
|
void write_string_raw(F_PORT* port, char* str, CELL len)
|
2004-08-28 22:25:59 -04:00
|
|
|
{
|
|
|
|
/* Append string to buffer */
|
2004-12-10 21:46:42 -05:00
|
|
|
memcpy((void*)((CELL)untag_string(port->buffer) + sizeof(F_STRING)
|
2004-08-28 22:25:59 -04:00
|
|
|
+ port->buf_fill),str,len);
|
|
|
|
|
|
|
|
port->buf_fill += len;
|
|
|
|
}
|
|
|
|
|
2004-12-10 21:46:42 -05:00
|
|
|
void write_string_8(F_PORT* port, F_STRING* str)
|
2004-08-20 01:49:14 -04:00
|
|
|
{
|
2005-02-20 19:03:37 -05:00
|
|
|
CELL capacity = string_capacity(str);
|
2004-08-28 22:25:59 -04:00
|
|
|
|
2004-09-02 21:51:19 -04:00
|
|
|
pending_io_error(port);
|
|
|
|
|
2004-08-20 01:49:14 -04:00
|
|
|
/* Note this ensures the buffer is large enough to fit the string */
|
2005-02-20 19:03:37 -05:00
|
|
|
if(!can_write(port,capacity))
|
2004-08-20 01:49:14 -04:00
|
|
|
io_error(__FUNCTION__);
|
|
|
|
|
2005-02-20 19:03:37 -05:00
|
|
|
write_string_raw(port,to_c_string_unchecked(str),capacity);
|
2004-08-20 01:49:14 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void primitive_write_8(void)
|
|
|
|
{
|
2004-12-10 21:46:42 -05:00
|
|
|
F_PORT* port;
|
2004-10-12 23:49:43 -04:00
|
|
|
CELL text, type;
|
2004-12-10 21:46:42 -05:00
|
|
|
F_STRING* str;
|
2004-08-20 01:49:14 -04:00
|
|
|
|
2004-10-12 23:49:43 -04:00
|
|
|
maybe_garbage_collection();
|
|
|
|
|
|
|
|
port = untag_port(dpop());
|
|
|
|
|
|
|
|
text = dpop();
|
|
|
|
type = type_of(text);
|
|
|
|
|
2004-08-20 21:16:47 -04:00
|
|
|
pending_io_error(port);
|
|
|
|
|
2004-08-20 01:49:14 -04:00
|
|
|
switch(type)
|
|
|
|
{
|
|
|
|
case FIXNUM_TYPE:
|
|
|
|
case BIGNUM_TYPE:
|
|
|
|
write_char_8(port,to_fixnum(text));
|
|
|
|
break;
|
|
|
|
case STRING_TYPE:
|
2004-08-28 22:25:59 -04:00
|
|
|
str = untag_string(text);
|
|
|
|
write_string_8(port,str);
|
2004-08-20 01:49:14 -04:00
|
|
|
break;
|
|
|
|
default:
|
2004-12-27 22:58:43 -05:00
|
|
|
type_error(STRING_TYPE,text);
|
2004-08-20 01:49:14 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|