working on native I/O

cvs
Slava Pestov 2004-07-24 21:37:42 +00:00
parent 8b8b770a96
commit b8f516ab2c
19 changed files with 100 additions and 26 deletions

View File

@ -3,7 +3,6 @@
- image output - image output
- 32-bit and 64-bit "bignums" - 32-bit and 64-bit "bignums"
- floats - floats
- i/o error handling
- {...} vectors - {...} vectors
- parsing should be parsing - parsing should be parsing
- describe-word - describe-word

View File

@ -58,6 +58,7 @@ DEFER: accept-fd
DEFER: read-line-fd-8 DEFER: read-line-fd-8
DEFER: write-fd-8 DEFER: write-fd-8
DEFER: flush-fd DEFER: flush-fd
DEFER: shutdown-fd
IN: words IN: words
DEFER: <word> DEFER: <word>
@ -156,6 +157,7 @@ IN: cross-compiler
read-line-fd-8 read-line-fd-8
write-fd-8 write-fd-8
flush-fd flush-fd
shutdown-fd
room room
] [ ] [
swap succ tuck primitive, swap succ tuck primitive,

View File

@ -62,6 +62,7 @@ USE: vectors
"Underflow" "Underflow"
"Bad primitive: " "Bad primitive: "
"Incompatible handle: " "Incompatible handle: "
"I/O error: "
] ?nth ; ] ?nth ;
: ?kernel-error ( cons -- error# param ) : ?kernel-error ( cons -- error# param )

View File

@ -86,9 +86,20 @@ USE: namespaces
[ "socket" get close-fd ] "fclose" set [ "socket" get close-fd ] "fclose" set
] extend ; ] extend ;
: <socket-stream> ( fd -- stream )
#! A slight variation on <fd-stream> that calls shutdown(2)
#! when closed.
dup <fd-stream> [
( -- )
[
"in" get [ dup shutdown-fd close-fd ] when*
( out == in )
] "fclose" set
] extend ;
: accept ( server -- client ) : accept ( server -- client )
#! Accept a connection from a server socket. #! Accept a connection from a server socket.
[ "socket" get ] bind accept-fd dup <fd-stream> ; [ "socket" get ] bind accept-fd <socket-stream> ;
: init-stdio ( -- ) : init-stdio ( -- )
stdin stdout <fd-stream> "stdio" set ; stdin stdout <fd-stream> "stdio" set ;

View File

@ -1,6 +1,6 @@
#include "factor.h" #include "factor.h"
CELL cons(CELL car, CELL cdr) CONS* cons(CELL car, CELL cdr)
{ {
CONS* cons = (CONS*)allot(sizeof(CONS)); CONS* cons = (CONS*)allot(sizeof(CONS));
cons->car = car; cons->car = car;

View File

@ -14,7 +14,7 @@ INLINE CELL tag_cons(CONS* cons)
return RETAG(cons,CONS_TYPE); return RETAG(cons,CONS_TYPE);
} }
CELL cons(CELL car, CELL cdr); CONS* cons(CELL car, CELL cdr);
INLINE CELL car(CELL cons) INLINE CELL car(CELL cons)
{ {

View File

@ -50,5 +50,15 @@ void range_error(CELL tagged, CELL index, CELL max)
{ {
CONS* c = cons(tagged,tag_cons(cons(tag_fixnum(index), CONS* c = cons(tagged,tag_cons(cons(tag_fixnum(index),
tag_cons(cons(tag_fixnum(max),F))))); tag_cons(cons(tag_fixnum(max),F)))));
general_error(ERROR_RANGE,c); 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));
} }

View File

@ -5,6 +5,7 @@
#define ERROR_UNDERFLOW (4<<3) #define ERROR_UNDERFLOW (4<<3)
#define ERROR_BAD_PRIMITIVE (5<<3) #define ERROR_BAD_PRIMITIVE (5<<3)
#define ERROR_HANDLE_INCOMPAT (6<<3) #define ERROR_HANDLE_INCOMPAT (6<<3)
#define ERROR_IO (7<<3)
void fatal_error(char* msg, CELL tagged); void fatal_error(char* msg, CELL tagged);
void critical_error(char* msg, CELL tagged); void critical_error(char* msg, CELL tagged);
@ -13,3 +14,4 @@ void throw_error(CELL object);
void general_error(CELL error, CELL tagged); void general_error(CELL error, CELL tagged);
void type_error(CELL type, CELL tagged); void type_error(CELL type, CELL tagged);
void range_error(CELL tagged, CELL index, CELL max); void range_error(CELL tagged, CELL index, CELL max);
void io_error(const char* func);

View File

@ -12,6 +12,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h> #include <unistd.h>
#define INLINE inline static #define INLINE inline static

View File

@ -29,6 +29,7 @@ void primitive_read_line_fd_8(void)
HANDLE* h = untag_handle(HANDLE_FD,env.dt); HANDLE* h = untag_handle(HANDLE_FD,env.dt);
int fd = h->object; int fd = h->object;
int amount;
int i; int i;
int ch; int ch;
@ -45,7 +46,12 @@ void primitive_read_line_fd_8(void)
{ {
if(h->buf_pos >= h->buf_fill) if(h->buf_pos >= h->buf_fill)
{ {
if(fill_buffer(h,fd,buf) <= 0) amount = fill_buffer(h,fd,buf);
if(amount < 0)
io_error(__FUNCTION__);
if(amount == 0)
{ {
if(line->top == 0) if(line->top == 0)
{ {
@ -82,7 +88,12 @@ void primitive_write_fd_8(void)
int fd = h->object; int fd = h->object;
STRING* str = untag_string(dpop()); STRING* str = untag_string(dpop());
char* c_str = to_c_string(str); char* c_str = to_c_string(str);
write(fd,c_str,str->capacity);
int amount = write(fd,c_str,str->capacity);
if(amount < 0)
io_error(__FUNCTION__);
env.dt = dpop(); env.dt = dpop();
} }
@ -90,6 +101,20 @@ void primitive_flush_fd(void)
{ {
HANDLE* h = untag_handle(HANDLE_FD,env.dt); HANDLE* h = untag_handle(HANDLE_FD,env.dt);
int fd = h->object; int fd = h->object;
fsync(fd);
/* if(fsync(fd) < 0)
io_error(__FUNCTION__); */
env.dt = dpop();
}
void primitive_shutdown_fd(void)
{
HANDLE* h = untag_handle(HANDLE_FD,env.dt);
int fd = h->object;
if(shutdown(fd,SHUT_RDWR) < 0)
io_error(__FUNCTION__);
env.dt = dpop(); env.dt = dpop();
} }

View File

@ -1,8 +1,10 @@
#define LINE_SIZE 80 #define LINE_SIZE 80
#define BUF_SIZE 1024 #define BUF_SIZE 1024
void init_io(void);
void primitive_close_fd(void); void primitive_close_fd(void);
int fill_buffer(HANDLE* h, int fd, STRING* buf); int fill_buffer(HANDLE* h, int fd, STRING* buf);
void primitive_read_line_fd_8(void); void primitive_read_line_fd_8(void);
void primitive_write_fd_8(void); void primitive_write_fd_8(void);
void primitive_flush_fd(void); void primitive_flush_fd(void);
void primitive_shutdown_fd(void);

View File

@ -14,7 +14,12 @@ void primitive_open_file(void)
mode = O_RDONLY; mode = O_RDONLY;
else if(write) else if(write)
mode = O_WRONLY | O_CREAT | O_TRUNC; mode = O_WRONLY | O_CREAT | O_TRUNC;
else
mode = 0;
fd = open(path,mode); fd = open(path,mode);
if(fd < 0)
io_error(__FUNCTION__);
env.dt = handle(HANDLE_FD,fd); env.dt = handle(HANDLE_FD,fd);
} }

View File

@ -87,7 +87,8 @@ XT primitives[] = {
primitive_read_line_fd_8, /* 83 */ primitive_read_line_fd_8, /* 83 */
primitive_write_fd_8, /* 84 */ primitive_write_fd_8, /* 84 */
primitive_flush_fd, /* 85 */ primitive_flush_fd, /* 85 */
primitive_room /* 86 */ primitive_shutdown_fd, /* 86 */
primitive_room /* 87 */
}; };
CELL primitive_to_xt(CELL primitive) CELL primitive_to_xt(CELL primitive)
@ -95,7 +96,7 @@ CELL primitive_to_xt(CELL primitive)
XT xt; XT xt;
if(primitive < 0 || primitive >= PRIMITIVE_COUNT) if(primitive < 0 || primitive >= PRIMITIVE_COUNT)
general_error("Invalid primitive",tag_fixnum(primitive)); general_error(ERROR_BAD_PRIMITIVE,tag_fixnum(primitive));
xt = primitives[primitive]; xt = primitives[primitive];
if((CELL)xt % 8 != 0) if((CELL)xt % 8 != 0)

View File

@ -1,5 +1,5 @@
extern XT primitives[]; extern XT primitives[];
#define PRIMITIVE_COUNT 87 #define PRIMITIVE_COUNT 88
CELL primitive_to_xt(CELL primitive); CELL primitive_to_xt(CELL primitive);

View File

@ -30,7 +30,7 @@ void primitive_set_sbuf_length(void)
FIXNUM length = untag_fixnum(dpop()); FIXNUM length = untag_fixnum(dpop());
sbuf->top = length; sbuf->top = length;
if(length < 0) if(length < 0)
range_error(env.dt,index,length); range_error(env.dt,length,sbuf->top);
else if(length > sbuf->string->capacity) else if(length > sbuf->string->capacity)
sbuf->string = grow_string(sbuf->string,length,F); sbuf->string = grow_string(sbuf->string,length,F);
env.dt = dpop(); /* don't forget this! */ env.dt = dpop(); /* don't forget this! */

View File

@ -5,22 +5,34 @@ int make_server_socket(CHAR port)
int sock; int sock;
struct sockaddr_in name; struct sockaddr_in name;
int reuseaddr = 1;
/* Create the socket */ /* Create the socket */
sock = socket(PF_INET, SOCK_STREAM, 0); sock = socket(PF_INET, SOCK_STREAM, 0);
if(sock < 0) if(sock < 0)
return -1; io_error(__FUNCTION__);
/* Reuse port number */
if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&reuseaddr,sizeof(int)) < 0)
io_error(__FUNCTION__);
/* Give the socket a name */ /* Give the socket a name */
name.sin_family = AF_INET; name.sin_family = AF_INET;
name.sin_port = htons(port); name.sin_port = htons(port);
name.sin_addr.s_addr = htonl(INADDR_ANY); name.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(sock,(struct sockaddr *)&name, sizeof(name)) < 0) if(bind(sock,(struct sockaddr *)&name, sizeof(name)) < 0)
return -1; {
close(sock);
io_error(__FUNCTION__);
}
/* Start listening for connections */ /* Start listening for connections */
if(listen(sock,1) < 0) if(listen(sock,1) < 0)
return -1; {
close(sock);
io_error(__FUNCTION__);
}
return sock; return sock;
} }
@ -38,7 +50,7 @@ int accept_connection(int sock)
int new = accept(sock,(struct sockaddr *)&clientname,&size); int new = accept(sock,(struct sockaddr *)&clientname,&size);
if(new < 0) if(new < 0)
return -1; io_error(__FUNCTION__);
printf("Connection from host %s, port %hd.\n", printf("Connection from host %s, port %hd.\n",
inet_ntoa(clientname.sin_addr), inet_ntoa(clientname.sin_addr),

View File

@ -51,7 +51,7 @@ STRING* grow_string(STRING* string, CELL capacity, CHAR fill)
} }
/* untagged */ /* untagged */
STRING* from_c_string(char* c_string) STRING* from_c_string(const char* c_string)
{ {
CELL length = strlen(c_string); CELL length = strlen(c_string);
STRING* s = allot_string(length); STRING* s = allot_string(length);
@ -59,7 +59,7 @@ STRING* from_c_string(char* c_string)
for(i = 0; i < length; i++) for(i = 0; i < length; i++)
{ {
put(SREF(s,i),c_string); put(SREF(s,i),*c_string);
c_string++; c_string++;
} }
@ -101,7 +101,7 @@ void primitive_string_nth(void)
CELL index = untag_fixnum(dpop()); CELL index = untag_fixnum(dpop());
if(index < 0 || index >= string->capacity) if(index < 0 || index >= string->capacity)
range_error(string,index,string->capacity); range_error(tag_object(string),index,string->capacity);
env.dt = tag_fixnum(string_nth(string,index)); env.dt = tag_fixnum(string_nth(string,index));
} }
@ -160,7 +160,7 @@ void primitive_string_hashcode(void)
INLINE CELL index_of_ch(CELL index, STRING* string, CELL ch) INLINE CELL index_of_ch(CELL index, STRING* string, CELL ch)
{ {
if(index < 0) if(index < 0)
range_error(string,index,string->capacity); range_error(tag_object(string),index,string->capacity);
while(index < string->capacity) while(index < string->capacity)
{ {
@ -201,8 +201,11 @@ INLINE STRING* substring(CELL start, CELL end, STRING* string)
{ {
STRING* result; STRING* result;
if(start < 0 || end < start) if(start < 0)
range_error(string,index,string->capacity); range_error(tag_object(string),start,string->capacity);
if(end < start)
range_error(tag_object(string),end,string->capacity);
result = allot_string(end - start); result = allot_string(end - start);
memcpy(result + 1, memcpy(result + 1,

View File

@ -17,7 +17,7 @@ STRING* string(CELL capacity, CELL fill);
void hash_string(STRING* str); void hash_string(STRING* str);
STRING* grow_string(STRING* string, CELL capacity, CHAR fill); STRING* grow_string(STRING* string, CELL capacity, CHAR fill);
char* to_c_string(STRING* s); char* to_c_string(STRING* s);
STRING* from_c_string(char* c_string); STRING* from_c_string(const char* c_string);
#define SREF(string,index) ((CELL)string + sizeof(STRING) + index * CHARS) #define SREF(string,index) ((CELL)string + sizeof(STRING) + index * CHARS)

View File

@ -30,7 +30,7 @@ void primitive_set_vector_length(void)
FIXNUM length = untag_fixnum(dpop()); FIXNUM length = untag_fixnum(dpop());
vector->top = length; vector->top = length;
if(length < 0) if(length < 0)
range_error(vector,index,length); range_error(tag_object(vector),length,vector->top);
else if(length > vector->array->capacity) else if(length > vector->array->capacity)
vector->array = grow_array(vector->array,length,F); vector->array = grow_array(vector->array,length,F);
env.dt = dpop(); /* don't forget this! */ env.dt = dpop(); /* don't forget this! */
@ -42,7 +42,7 @@ void primitive_vector_nth(void)
CELL index = untag_fixnum(dpop()); CELL index = untag_fixnum(dpop());
if(index < 0 || index >= vector->top) if(index < 0 || index >= vector->top)
range_error(vector,index,vector->top); range_error(tag_object(vector),index,vector->top);
env.dt = array_nth(vector->array,index); env.dt = array_nth(vector->array,index);
} }
@ -64,7 +64,7 @@ void primitive_set_vector_nth(void)
check_non_empty(value); check_non_empty(value);
if(index < 0) if(index < 0)
range_error(vector,index,vector->top); range_error(tag_object(vector),index,vector->top);
else if(index >= vector->top) else if(index >= vector->top)
vector_ensure_capacity(vector,index); vector_ensure_capacity(vector,index);