2004-12-10 22:47:03 -05:00
|
|
|
#include "../factor.h"
|
2004-08-20 01:49:14 -04:00
|
|
|
|
|
|
|
/* Return true if something was read */
|
2004-12-10 21:46:42 -05:00
|
|
|
bool read_step(F_PORT* port)
|
2004-08-20 01:49:14 -04:00
|
|
|
{
|
2004-12-10 21:46:42 -05:00
|
|
|
F_FIXNUM amount = 0;
|
|
|
|
F_STRING* buffer = untag_string(port->buffer);
|
2004-11-27 22:26:05 -05:00
|
|
|
CELL capacity = buffer->capacity;
|
2004-08-20 01:49:14 -04:00
|
|
|
|
|
|
|
if(port->type == PORT_RECV)
|
|
|
|
{
|
|
|
|
/* try reading OOB data. */
|
2004-11-27 22:26:05 -05:00
|
|
|
amount = recv(port->fd,buffer + 1,capacity * CHARS,MSG_OOB);
|
2004-08-20 01:49:14 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if(amount <= 0)
|
|
|
|
{
|
2004-11-27 22:26:05 -05:00
|
|
|
amount = read(port->fd,buffer + 1,capacity * CHARS);
|
2004-08-20 01:49:14 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if(amount < 0)
|
|
|
|
{
|
|
|
|
if(errno != EAGAIN)
|
2004-08-20 21:16:47 -04:00
|
|
|
{
|
|
|
|
postpone_io_error(port,__FUNCTION__);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return false;
|
2004-08-20 01:49:14 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
port->buf_fill = (amount < 0 ? 0 : amount);
|
|
|
|
port->buf_pos = 0;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-12-10 21:46:42 -05:00
|
|
|
bool read_line_step(F_PORT* port)
|
2004-08-20 01:49:14 -04:00
|
|
|
{
|
|
|
|
int i;
|
2004-09-02 22:53:50 -04:00
|
|
|
BYTE ch;
|
2004-08-20 01:49:14 -04:00
|
|
|
|
2004-12-10 21:46:42 -05:00
|
|
|
F_SBUF* line = untag_sbuf(port->line);
|
|
|
|
F_STRING* buffer = untag_string(port->buffer);
|
2004-08-20 01:49:14 -04:00
|
|
|
|
|
|
|
for(i = port->buf_pos; i < port->buf_fill; i++)
|
|
|
|
{
|
2004-12-10 21:46:42 -05:00
|
|
|
ch = bget((CELL)buffer + sizeof(F_STRING) + i);
|
2004-08-20 01:49:14 -04:00
|
|
|
|
|
|
|
if(ch == '\r')
|
|
|
|
{
|
|
|
|
if(i != port->buf_fill - 1)
|
|
|
|
{
|
2004-11-27 22:26:05 -05:00
|
|
|
ch = bget((CELL)buffer
|
2004-12-10 21:46:42 -05:00
|
|
|
+ sizeof(F_STRING) + i + 1);
|
2004-08-20 01:49:14 -04:00
|
|
|
if(ch == '\n')
|
|
|
|
i++;
|
|
|
|
}
|
2004-08-22 21:56:06 -04:00
|
|
|
|
|
|
|
port->buf_pos = i + 1;
|
|
|
|
port->line_ready = true;
|
|
|
|
return true;
|
2004-08-20 01:49:14 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if(ch == '\n')
|
|
|
|
{
|
|
|
|
port->buf_pos = i + 1;
|
|
|
|
port->line_ready = true;
|
|
|
|
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 */
|
|
|
|
port->buf_pos = port->buf_fill;
|
|
|
|
port->line_ready = false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2004-12-10 21:46:42 -05:00
|
|
|
bool can_read_line(F_PORT* port)
|
2004-08-20 01:49:14 -04:00
|
|
|
{
|
2004-08-20 21:16:47 -04:00
|
|
|
pending_io_error(port);
|
|
|
|
|
2004-08-24 18:01:36 -04:00
|
|
|
if(port->type != PORT_READ && port->type != PORT_RECV)
|
2004-08-24 23:46:55 -04:00
|
|
|
general_error(ERROR_INCOMPATIBLE_PORT,tag_object(port));
|
2004-08-24 18:01:36 -04:00
|
|
|
|
2004-08-20 01:49:14 -04:00
|
|
|
if(port->line_ready)
|
|
|
|
return true;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
init_line_buffer(port,LINE_SIZE);
|
|
|
|
read_line_step(port);
|
|
|
|
return port->line_ready;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void primitive_can_read_line(void)
|
|
|
|
{
|
2004-12-10 21:46:42 -05:00
|
|
|
F_PORT* port = untag_port(dpop());
|
2004-11-08 22:36:51 -05:00
|
|
|
box_boolean(can_read_line(port));
|
2004-08-20 01:49:14 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void primitive_add_read_line_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_READ_LINE,port,F,callback,
|
2004-08-20 01:49:14 -04:00
|
|
|
read_io_tasks,&read_fd_count);
|
|
|
|
|
2004-08-28 22:25:59 -04:00
|
|
|
init_line_buffer(untag_port(port),LINE_SIZE);
|
2004-08-20 01:49:14 -04:00
|
|
|
}
|
|
|
|
|
2004-12-10 21:46:42 -05:00
|
|
|
bool perform_read_line_io_task(F_PORT* port)
|
2004-08-20 01:49:14 -04:00
|
|
|
{
|
|
|
|
if(port->buf_pos >= port->buf_fill)
|
|
|
|
{
|
|
|
|
if(!read_step(port))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(port->buf_fill == 0)
|
|
|
|
{
|
|
|
|
/* EOF */
|
|
|
|
if(port->line != F)
|
|
|
|
{
|
2004-08-22 21:56:06 -04:00
|
|
|
if(untag_sbuf(port->line)->top == 0)
|
2004-08-20 01:49:14 -04:00
|
|
|
port->line = F;
|
|
|
|
}
|
|
|
|
port->line_ready = true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return read_line_step(port);
|
|
|
|
}
|
|
|
|
|
|
|
|
void primitive_read_line_8(void)
|
|
|
|
{
|
2004-12-10 21:46:42 -05:00
|
|
|
F_PORT* port;
|
2004-10-12 23:49:43 -04:00
|
|
|
|
|
|
|
maybe_garbage_collection();
|
|
|
|
|
|
|
|
port = untag_port(dpeek());
|
2004-08-20 21:16:47 -04:00
|
|
|
|
|
|
|
pending_io_error(port);
|
|
|
|
|
2004-08-20 01:49:14 -04:00
|
|
|
if(port->line_ready)
|
|
|
|
{
|
|
|
|
drepl(port->line);
|
|
|
|
port->line = F;
|
|
|
|
port->line_ready = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
io_error(__FUNCTION__);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2004-12-10 21:46:42 -05:00
|
|
|
bool read_count_step(F_PORT* port)
|
2004-08-20 01:49:14 -04:00
|
|
|
{
|
|
|
|
int i;
|
2004-09-02 22:53:50 -04:00
|
|
|
BYTE ch;
|
2004-08-20 01:49:14 -04:00
|
|
|
|
2004-12-10 21:46:42 -05:00
|
|
|
F_SBUF* line = untag_sbuf(port->line);
|
|
|
|
F_STRING* buffer = untag_string(port->buffer);
|
2004-08-20 01:49:14 -04:00
|
|
|
|
|
|
|
for(i = port->buf_pos; i < port->buf_fill; i++)
|
|
|
|
{
|
2004-12-10 21:46:42 -05:00
|
|
|
ch = bget((CELL)buffer + sizeof(F_STRING) + i);
|
2004-08-20 01:49:14 -04:00
|
|
|
set_sbuf_nth(line,line->top,ch);
|
|
|
|
if(line->top == port->count)
|
|
|
|
{
|
|
|
|
port->buf_pos = i + 1;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We've reached the end of the above loop, without seeing enough chars
|
|
|
|
or EOF, so read again */
|
|
|
|
port->buf_pos = port->buf_fill;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2004-12-10 21:46:42 -05:00
|
|
|
bool can_read_count(F_PORT* port, F_FIXNUM count)
|
2004-08-20 01:49:14 -04:00
|
|
|
{
|
2004-08-20 21:16:47 -04:00
|
|
|
pending_io_error(port);
|
|
|
|
|
2004-08-24 18:01:36 -04:00
|
|
|
if(port->type != PORT_READ && port->type != PORT_RECV)
|
2004-08-24 23:46:55 -04:00
|
|
|
general_error(ERROR_INCOMPATIBLE_PORT,tag_object(port));
|
2004-08-24 18:01:36 -04:00
|
|
|
|
2004-08-20 01:49:14 -04:00
|
|
|
if(port->line != F && CAN_READ_COUNT(port,count))
|
|
|
|
return true;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
port->count = count;
|
|
|
|
init_line_buffer(port,count);
|
|
|
|
read_count_step(port);
|
|
|
|
return CAN_READ_COUNT(port,count);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void primitive_can_read_count(void)
|
|
|
|
{
|
2004-12-10 21:46:42 -05:00
|
|
|
F_PORT* port;
|
2004-12-22 22:16:46 -05:00
|
|
|
CELL len;
|
2004-10-12 23:49:43 -04:00
|
|
|
|
|
|
|
maybe_garbage_collection();
|
|
|
|
|
|
|
|
port = untag_port(dpop());
|
2004-12-22 22:16:46 -05:00
|
|
|
len = to_cell(dpop());
|
2004-11-08 22:36:51 -05:00
|
|
|
box_boolean(can_read_count(port,len));
|
2004-08-20 01:49:14 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void primitive_add_read_count_io_task(void)
|
|
|
|
{
|
2004-10-12 23:49:43 -04:00
|
|
|
CELL callback;
|
2004-12-10 21:46:42 -05:00
|
|
|
F_PORT* port;
|
2004-12-22 22:16:46 -05:00
|
|
|
CELL count;
|
2004-10-12 23:49:43 -04:00
|
|
|
|
|
|
|
maybe_garbage_collection();
|
|
|
|
|
|
|
|
callback = dpop();
|
|
|
|
port = untag_port(dpop());
|
2004-12-22 22:16:46 -05:00
|
|
|
count = to_cell(dpop());
|
2004-08-28 22:25:59 -04:00
|
|
|
add_io_task(IO_TASK_READ_COUNT,
|
|
|
|
tag_object(port),F,callback,
|
2004-08-20 01:49:14 -04:00
|
|
|
read_io_tasks,&read_fd_count);
|
|
|
|
|
|
|
|
port->count = count;
|
|
|
|
init_line_buffer(port,count);
|
|
|
|
}
|
|
|
|
|
2004-12-10 21:46:42 -05:00
|
|
|
bool perform_read_count_io_task(F_PORT* port)
|
2004-08-20 01:49:14 -04:00
|
|
|
{
|
|
|
|
if(port->buf_pos >= port->buf_fill)
|
|
|
|
{
|
|
|
|
if(!read_step(port))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(port->buf_fill == 0)
|
|
|
|
return true;
|
|
|
|
else
|
|
|
|
return read_count_step(port);
|
|
|
|
}
|
|
|
|
|
|
|
|
void primitive_read_count_8(void)
|
|
|
|
{
|
2004-12-10 21:46:42 -05:00
|
|
|
F_PORT* port;
|
2004-12-22 22:16:46 -05:00
|
|
|
CELL len;
|
2004-10-12 23:49:43 -04:00
|
|
|
|
|
|
|
maybe_garbage_collection();
|
|
|
|
|
|
|
|
port = untag_port(dpop());
|
2004-12-22 22:16:46 -05:00
|
|
|
len = to_cell(dpop());
|
2004-08-20 01:49:14 -04:00
|
|
|
if(port->count != len)
|
2004-08-24 23:46:55 -04:00
|
|
|
critical_error("read# counts don't match",tag_object(port));
|
2004-08-20 21:16:47 -04:00
|
|
|
|
|
|
|
pending_io_error(port);
|
|
|
|
|
2004-08-20 01:49:14 -04:00
|
|
|
dpush(port->line);
|
|
|
|
port->line = F;
|
|
|
|
port->line_ready = false;
|
|
|
|
}
|