2004-07-23 20:35:13 -04:00
|
|
|
#include "factor.h"
|
|
|
|
|
|
2004-07-24 00:54:57 -04:00
|
|
|
void init_io(void)
|
|
|
|
|
{
|
2004-08-12 17:36:36 -04:00
|
|
|
env.user[STDIN_ENV] = port(0);
|
|
|
|
|
env.user[STDOUT_ENV] = port(1);
|
|
|
|
|
env.user[STDERR_ENV] = port(2);
|
2004-07-24 00:54:57 -04:00
|
|
|
}
|
|
|
|
|
|
2004-08-12 23:40:28 -04:00
|
|
|
int read_step(PORT* port)
|
2004-07-23 20:35:13 -04:00
|
|
|
{
|
2004-08-12 23:40:28 -04:00
|
|
|
int amount = read(port->fd,
|
|
|
|
|
port->buffer + 1,
|
|
|
|
|
port->buffer->capacity * 2);
|
2004-07-23 20:35:13 -04:00
|
|
|
|
2004-08-12 17:36:36 -04:00
|
|
|
port->buf_fill = (amount < 0 ? 0 : amount);
|
|
|
|
|
port->buf_pos = 0;
|
2004-07-24 15:11:55 -04:00
|
|
|
|
|
|
|
|
return amount;
|
|
|
|
|
}
|
|
|
|
|
|
2004-08-12 23:40:28 -04:00
|
|
|
READLINE_STAT read_line_step(PORT* port)
|
2004-07-23 20:35:13 -04:00
|
|
|
{
|
2004-07-24 17:37:42 -04:00
|
|
|
int amount;
|
2004-07-24 00:54:57 -04:00
|
|
|
int i;
|
|
|
|
|
int ch;
|
|
|
|
|
|
2004-08-12 23:40:28 -04:00
|
|
|
SBUF* line = port->line;
|
2004-07-23 20:35:13 -04:00
|
|
|
|
2004-08-12 23:40:28 -04:00
|
|
|
if(port->buf_pos >= port->buf_fill)
|
|
|
|
|
{
|
|
|
|
|
amount = read_step(port);
|
2004-07-27 21:12:22 -04:00
|
|
|
|
2004-08-12 23:40:28 -04:00
|
|
|
if(amount < 0)
|
|
|
|
|
io_error(__FUNCTION__);
|
|
|
|
|
else if(amount == 0)
|
|
|
|
|
return READLINE_EOF;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for(i = port->buf_pos; i < port->buf_fill; i++)
|
2004-07-23 20:35:13 -04:00
|
|
|
{
|
2004-08-12 23:40:28 -04:00
|
|
|
ch = bget((CELL)port->buffer + sizeof(STRING) + i);
|
|
|
|
|
if(ch == '\n')
|
2004-07-23 20:35:13 -04:00
|
|
|
{
|
2004-08-12 23:40:28 -04:00
|
|
|
port->buf_pos = i + 1;
|
|
|
|
|
return READLINE_EOL;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
set_sbuf_nth(line,line->top,ch);
|
|
|
|
|
}
|
2004-07-24 17:37:42 -04:00
|
|
|
|
2004-08-12 23:40:28 -04:00
|
|
|
port->buf_pos = port->buf_fill;
|
2004-07-24 17:37:42 -04:00
|
|
|
|
2004-08-12 23:40:28 -04:00
|
|
|
/* We've reached the end of the above loop, without seeing a newline
|
|
|
|
|
or EOF, so read again */
|
|
|
|
|
return READLINE_AGAIN;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
2004-07-23 20:35:13 -04:00
|
|
|
|
2004-08-12 23:40:28 -04:00
|
|
|
for(;;)
|
|
|
|
|
{
|
|
|
|
|
state = read_line_step(port);
|
|
|
|
|
if(state != READLINE_AGAIN)
|
2004-07-24 00:54:57 -04:00
|
|
|
{
|
2004-08-12 23:40:28 -04:00
|
|
|
if(state == READLINE_EOF && line->top == 0)
|
2004-07-24 00:54:57 -04:00
|
|
|
{
|
2004-08-12 23:40:28 -04:00
|
|
|
/* didn't read anything before EOF */
|
|
|
|
|
drepl(F);
|
2004-07-24 00:54:57 -04:00
|
|
|
}
|
|
|
|
|
else
|
2004-08-12 23:40:28 -04:00
|
|
|
drepl(tag_object(sbuf_to_string(line)));
|
|
|
|
|
return;
|
2004-07-24 00:54:57 -04:00
|
|
|
}
|
|
|
|
|
}
|
2004-07-23 20:35:13 -04:00
|
|
|
}
|
|
|
|
|
|
2004-08-12 23:40:28 -04:00
|
|
|
void write_step(PORT* port)
|
2004-08-11 16:56:48 -04:00
|
|
|
{
|
2004-08-12 23:40:28 -04:00
|
|
|
char* chars = (char*)port->buffer + sizeof(STRING);
|
2004-08-11 16:56:48 -04:00
|
|
|
|
2004-08-12 23:40:28 -04:00
|
|
|
FIXNUM amount = write(port->fd,chars + port->buf_pos,
|
|
|
|
|
port->buf_fill - port->buf_pos);
|
2004-08-11 16:56:48 -04:00
|
|
|
|
2004-08-12 23:40:28 -04:00
|
|
|
if(amount < 0)
|
|
|
|
|
io_error(__FUNCTION__);
|
2004-08-11 16:56:48 -04:00
|
|
|
|
2004-08-12 23:40:28 -04:00
|
|
|
port->buf_pos += amount;
|
2004-08-11 16:56:48 -04:00
|
|
|
}
|
|
|
|
|
|
2004-08-12 23:40:28 -04:00
|
|
|
/* keep writing to the stream until everything is written */
|
2004-08-12 17:36:36 -04:00
|
|
|
void flush_buffer(PORT* port)
|
2004-08-11 16:56:48 -04:00
|
|
|
{
|
2004-08-12 17:36:36 -04:00
|
|
|
if(port->buf_mode != B_WRITE || port->buf_fill == 0)
|
2004-08-11 16:56:48 -04:00
|
|
|
return;
|
|
|
|
|
|
2004-08-12 23:40:28 -04:00
|
|
|
for(;;)
|
|
|
|
|
{
|
|
|
|
|
if(port->buf_fill == port->buf_pos)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
write_step(port);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
port->buf_pos = 0;
|
2004-08-12 17:36:36 -04:00
|
|
|
port->buf_fill = 0;
|
2004-08-11 16:56:48 -04:00
|
|
|
}
|
|
|
|
|
|
2004-08-12 17:36:36 -04:00
|
|
|
void write_fd_char_8(PORT* port, FIXNUM ch)
|
2004-07-27 21:12:22 -04:00
|
|
|
{
|
2004-08-11 16:56:48 -04:00
|
|
|
char c = (char)ch;
|
2004-07-27 21:12:22 -04:00
|
|
|
|
2004-08-12 17:36:36 -04:00
|
|
|
init_buffer(port,B_WRITE);
|
2004-07-27 21:12:22 -04:00
|
|
|
|
2004-08-11 16:56:48 -04:00
|
|
|
/* Is the buffer full? */
|
2004-08-12 17:36:36 -04:00
|
|
|
if(port->buf_fill == port->buffer->capacity * CHARS)
|
|
|
|
|
flush_buffer(port);
|
2004-08-11 16:56:48 -04:00
|
|
|
|
2004-08-12 17:36:36 -04:00
|
|
|
bput((CELL)port->buffer + sizeof(STRING) + port->buf_fill,c);
|
|
|
|
|
port->buf_fill++;
|
2004-07-27 21:12:22 -04:00
|
|
|
}
|
|
|
|
|
|
2004-08-12 17:36:36 -04:00
|
|
|
void write_fd_string_8(PORT* port, STRING* str)
|
2004-07-23 20:35:13 -04:00
|
|
|
{
|
|
|
|
|
char* c_str = to_c_string(str);
|
2004-08-11 16:56:48 -04:00
|
|
|
|
2004-08-12 17:36:36 -04:00
|
|
|
init_buffer(port,B_WRITE);
|
2004-08-11 16:56:48 -04:00
|
|
|
|
|
|
|
|
/* Is the string longer than the buffer? */
|
2004-08-12 17:36:36 -04:00
|
|
|
if(str->capacity > port->buffer->capacity * CHARS)
|
2004-08-11 16:56:48 -04:00
|
|
|
{
|
2004-08-12 17:36:36 -04:00
|
|
|
flush_buffer(port);
|
2004-08-12 23:40:28 -04:00
|
|
|
|
|
|
|
|
/* Increase the buffer to fit the string */
|
|
|
|
|
port->buffer = allot_string(str->capacity / CHARS + 1);
|
2004-08-11 16:56:48 -04:00
|
|
|
}
|
2004-08-12 23:40:28 -04:00
|
|
|
/* Is there enough room in the buffer? If not, flush */
|
|
|
|
|
if(port->buf_fill + str->capacity
|
|
|
|
|
> port->buffer->capacity * CHARS)
|
2004-08-11 16:56:48 -04:00
|
|
|
{
|
2004-08-12 23:40:28 -04:00
|
|
|
flush_buffer(port);
|
|
|
|
|
}
|
2004-08-11 16:56:48 -04:00
|
|
|
|
2004-08-12 23:40:28 -04:00
|
|
|
/* Append string to buffer */
|
|
|
|
|
memcpy((void*)((CELL)port->buffer + sizeof(STRING)
|
|
|
|
|
+ port->buf_fill),c_str,str->capacity);
|
2004-08-11 16:56:48 -04:00
|
|
|
|
2004-08-12 23:40:28 -04:00
|
|
|
port->buf_fill += str->capacity;
|
2004-07-27 21:12:22 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void primitive_write_fd_8(void)
|
|
|
|
|
{
|
2004-08-12 17:36:36 -04:00
|
|
|
PORT* port = untag_port(dpop());
|
2004-07-27 21:12:22 -04:00
|
|
|
|
|
|
|
|
CELL text = dpop();
|
2004-07-27 22:52:35 -04:00
|
|
|
CELL type = type_of(text);
|
|
|
|
|
|
|
|
|
|
switch(type)
|
|
|
|
|
{
|
|
|
|
|
case FIXNUM_TYPE:
|
2004-07-31 16:11:30 -04:00
|
|
|
case BIGNUM_TYPE:
|
2004-08-12 17:36:36 -04:00
|
|
|
write_fd_char_8(port,to_fixnum(text));
|
2004-07-27 22:52:35 -04:00
|
|
|
break;
|
|
|
|
|
case STRING_TYPE:
|
2004-08-12 17:36:36 -04:00
|
|
|
write_fd_string_8(port,untag_string(text));
|
2004-07-27 22:52:35 -04:00
|
|
|
break;
|
|
|
|
|
default:
|
2004-07-27 21:12:22 -04:00
|
|
|
type_error(STRING_TYPE,text);
|
2004-07-27 22:52:35 -04:00
|
|
|
break;
|
|
|
|
|
}
|
2004-07-23 20:35:13 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void primitive_flush_fd(void)
|
|
|
|
|
{
|
2004-08-12 17:36:36 -04:00
|
|
|
PORT* port = untag_port(dpop());
|
|
|
|
|
flush_buffer(port);
|
2004-07-24 17:37:42 -04:00
|
|
|
}
|
|
|
|
|
|
2004-08-11 16:56:48 -04:00
|
|
|
void primitive_close_fd(void)
|
2004-07-24 17:37:42 -04:00
|
|
|
{
|
2004-08-12 17:36:36 -04:00
|
|
|
PORT* port = untag_port(dpop());
|
|
|
|
|
flush_buffer(port);
|
|
|
|
|
close(port->fd);
|
2004-07-23 20:35:13 -04:00
|
|
|
}
|