fix vocabulary mess up in factor plugin, working on non-blocking sockets

cvs
Slava Pestov 2004-08-16 02:45:08 +00:00
parent 171c890597
commit f8e91e95f9
22 changed files with 117 additions and 39 deletions

View File

@ -1,5 +1,7 @@
0.62: 0.62:
- can-read-line?
- client connections broken
- vocabulary section: what is the dictionary? - vocabulary section: what is the dictionary?
- document swons, uncons, unswons - document swons, uncons, unswons
- vector-push/pop examples - vector-push/pop examples
@ -14,7 +16,7 @@
- handle division by zero - handle division by zero
- errors: don't show .factor-rc - errors: don't show .factor-rc
- inspector: sort - inspector: sort
- accept: return socket, instead of printing msg - log-client: fix for native
- telnetd: needs own history - telnetd: needs own history
- multitasking - multitasking

View File

@ -346,6 +346,8 @@ public class FactorReader
*/ */
public Cons parse() throws Exception public Cons parse() throws Exception
{ {
scanner.nextLine();
for(;;) for(;;)
{ {
if(next()) if(next())
@ -378,7 +380,7 @@ public class FactorReader
*/ */
public FactorWord nextWord(boolean define) throws Exception public FactorWord nextWord(boolean define) throws Exception
{ {
Object next = next(true,false); Object next = nextNonEOL(true,false);
if(next == FactorScanner.EOF) if(next == FactorScanner.EOF)
{ {
scanner.error("Unexpected EOF"); scanner.error("Unexpected EOF");
@ -401,16 +403,23 @@ public class FactorReader
boolean start) boolean start)
throws IOException, FactorParseException throws IOException, FactorParseException
{ {
return scanner.next(readNumbers,start,base); Object next = scanner.next(readNumbers,start,base);
if(next == FactorScanner.EOL)
{
scanner.nextLine();
return next(readNumbers,start);
}
else
return next;
} //}}} } //}}}
//{{{ nextNonEOF() method //{{{ nextNonEOL() method
public Object nextNonEOF( public Object nextNonEOL(
boolean readNumbers, boolean readNumbers,
boolean start) boolean start)
throws IOException, FactorParseException throws IOException, FactorParseException
{ {
return scanner.nextNonEOF(readNumbers,start,base); return scanner.nextNonEOL(readNumbers,start,base);
} //}}} } //}}}
//{{{ next() method //{{{ next() method

View File

@ -42,6 +42,11 @@ public class FactorScanner
*/ */
public static final Object EOF = new Object(); public static final Object EOF = new Object();
/**
* Special object returned on EOL.
*/
public static final Object EOL = new Object();
private String filename; private String filename;
private BufferedReader in; private BufferedReader in;
@ -106,7 +111,7 @@ public class FactorScanner
} //}}} } //}}}
//{{{ nextLine() method //{{{ nextLine() method
private void nextLine() throws IOException public void nextLine() throws IOException
{ {
lineNo++; lineNo++;
line = in.readLine(); line = in.readLine();
@ -130,10 +135,10 @@ public class FactorScanner
int base) int base)
throws IOException, FactorParseException throws IOException, FactorParseException
{ {
if(line == null || position == line.length())
nextLine();
if(line == null) if(line == null)
return EOF; return EOF;
if(position == line.length())
return EOL;
for(;;) for(;;)
{ {
@ -142,9 +147,8 @@ public class FactorScanner
// EOL // EOL
if(buf.length() != 0) if(buf.length() != 0)
return word(readNumbers,base); return word(readNumbers,base);
nextLine(); else
if(line == null) return EOL;
return EOF;
} }
char ch = line.charAt(position++); char ch = line.charAt(position++);
@ -178,14 +182,16 @@ public class FactorScanner
} }
} //}}} } //}}}
//{{{ nextNonEOF() method //{{{ nextNonEOL() method
public Object nextNonEOF( public Object nextNonEOL(
boolean readNumbers, boolean readNumbers,
boolean start, boolean start,
int base) int base)
throws IOException, FactorParseException throws IOException, FactorParseException
{ {
Object next = next(readNumbers,start,base); Object next = next(readNumbers,start,base);
if(next == EOL)
error("Unexpected EOL");
if(next == EOF) if(next == EOF)
error("Unexpected EOF"); error("Unexpected EOF");
return next; return next;

View File

@ -47,7 +47,7 @@ public class CharLiteral extends FactorParsingDefinition
public void eval(FactorInterpreter interp, FactorReader reader) public void eval(FactorInterpreter interp, FactorReader reader)
throws IOException, FactorParseException throws IOException, FactorParseException
{ {
String word = (String)reader.nextNonEOF(false,false); String word = (String)reader.nextNonEOL(false,false);
if(word.length() != 1) if(word.length() != 1)
reader.error("Bad character literal: " + word); reader.error("Bad character literal: " + word);
reader.append(new Character(word.charAt(0))); reader.append(new Character(word.charAt(0)));

View File

@ -52,12 +52,12 @@ public class ComplexLiteral extends FactorParsingDefinition
{ {
// Read two numbers // Read two numbers
Number real = FactorJava.toNumber( Number real = FactorJava.toNumber(
reader.nextNonEOF(true,false)); reader.nextNonEOL(true,false));
Number imaginary = FactorJava.toNumber( Number imaginary = FactorJava.toNumber(
reader.nextNonEOF(true,false)); reader.nextNonEOL(true,false));
// Read the end // Read the end
String end = (String)reader.nextNonEOF(false,false); String end = (String)reader.nextNonEOL(false,false);
if(!end.equals(this.end)) if(!end.equals(this.end))
reader.error("Expected " + this.end); reader.error("Expected " + this.end);

View File

@ -47,7 +47,7 @@ public class In extends FactorParsingDefinition
public void eval(FactorInterpreter interp, FactorReader reader) public void eval(FactorInterpreter interp, FactorReader reader)
throws Exception throws Exception
{ {
String next = (String)reader.next(false,false); String next = (String)reader.nextNonEOL(false,false);
reader.setIn(next); reader.setIn(next);
reader.addUse(next); reader.addUse(next);

View File

@ -48,6 +48,6 @@ public class PassThrough extends FactorParsingDefinition
throws Exception throws Exception
{ {
reader.append(reader.intern(word.name reader.append(reader.intern(word.name
+ reader.next(false,false),false)); + reader.nextNonEOL(false,false),false));
} }
} }

View File

@ -47,7 +47,7 @@ public class Use extends FactorParsingDefinition
public void eval(FactorInterpreter interp, FactorReader reader) public void eval(FactorInterpreter interp, FactorReader reader)
throws Exception throws Exception
{ {
String next = (String)reader.next(false,false); String next = (String)reader.nextNonEOL(false,false);
reader.addUse(next); reader.addUse(next);
} //}}} } //}}}

View File

@ -66,6 +66,7 @@ DEFER: port?
DEFER: open-file DEFER: open-file
DEFER: server-socket DEFER: server-socket
DEFER: close-fd DEFER: close-fd
DEFER: add-accept-io-task
DEFER: accept-fd DEFER: accept-fd
DEFER: can-read-line? DEFER: can-read-line?
DEFER: add-read-line-io-task DEFER: add-read-line-io-task
@ -214,6 +215,7 @@ IN: cross-compiler
exit* exit*
server-socket server-socket
close-fd close-fd
add-accept-io-task
accept-fd accept-fd
can-read-line? can-read-line?
add-read-line-io-task add-read-line-io-task

View File

@ -56,3 +56,10 @@ USE: strings
: blocking-read-line ( port -- line ) : blocking-read-line ( port -- line )
dup wait-to-read-line read-line-fd-8 dup [ sbuf>str ] when ; dup wait-to-read-line read-line-fd-8 dup [ sbuf>str ] when ;
: wait-to-accept ( socket -- )
[ swap add-accept-io-task next-io-task drop ( call ) ] callcc0 ;
: blocking-accept ( socket -- host port socket )
dup wait-to-accept accept-fd ;

View File

@ -32,6 +32,7 @@ USE: hashtables
USE: kernel USE: kernel
USE: lists USE: lists
USE: stack USE: stack
USE: strings
USE: vectors USE: vectors
DEFER: namespace DEFER: namespace
@ -77,9 +78,12 @@ DEFER: >n
: set ( value variable -- ) namespace set* ; : set ( value variable -- ) namespace set* ;
: put ( variable value -- ) namespace put* ; : put ( variable value -- ) namespace put* ;
: vars ( -- list ) namespace hash-keys ; : car-str-sort ( list -- list )
: values ( -- list ) namespace hash-values ; [ swap car swap car str-lexi> ] sort ;
: vars-values ( -- list ) namespace hash>alist ;
: vars-values ( -- list ) namespace hash>alist car-str-sort ;
: vars ( -- list ) vars-values [ car ] inject ;
: values ( -- list ) vars-values [ cdr ] inject ;
! We don't have bound objects in native Factor. ! We don't have bound objects in native Factor.
: namespace? hashtable? ; : namespace? hashtable? ;

View File

@ -83,9 +83,12 @@ USE: namespaces
[ "socket" get close-fd ] "fclose" set [ "socket" get close-fd ] "fclose" set
] extend ; ] extend ;
: <client-stream> ( host port socket -- stream )
dup <fd-stream> [ "port" set "client" set ] extend ;
: accept ( server -- client ) : accept ( server -- client )
#! Accept a connection from a server socket. #! Accept a connection from a server socket.
"socket" swap get* accept-fd dup <fd-stream> ; "socket" swap get* blocking-accept <client-stream> ;
: init-stdio ( -- ) : init-stdio ( -- )
stdin stdout <fd-stream> <stdio-stream> "stdio" set ; stdin stdout <fd-stream> <stdio-stream> "stdio" set ;

View File

@ -17,7 +17,7 @@ void primitive_open_file(void)
else else
mode = 0; mode = 0;
fd = open(path,mode); fd = open(path,mode,FILE_MODE);
if(fd < 0) if(fd < 0)
io_error(NULL,__FUNCTION__); io_error(NULL,__FUNCTION__);

View File

@ -1 +1,3 @@
#define FILE_MODE 0600
void primitive_open_file(void); void primitive_open_file(void);

View File

@ -59,6 +59,14 @@ void primitive_add_write_io_task(void)
write_io_tasks,&write_fd_count); write_io_tasks,&write_fd_count);
} }
void primitive_add_accept_io_task(void)
{
PORT* port = untag_port(dpop());
CELL callback = dpop();
add_io_task(IO_TASK_ACCEPT,port,callback,
read_io_tasks,&read_fd_count);
}
void remove_io_task( void remove_io_task(
IO_TASK_TYPE type, IO_TASK_TYPE type,
PORT* port, PORT* port,
@ -166,6 +174,18 @@ CELL perform_io_task(IO_TASK* task)
&write_fd_count); &write_fd_count);
return F; return F;
} }
case IO_TASK_ACCEPT:
remove_io_task(IO_TASK_ACCEPT,port,
read_io_tasks,&read_fd_count);
if(accept_connection(port))
return callback;
else
{
add_io_task(IO_TASK_ACCEPT,port,
callback,read_io_tasks,
&read_fd_count);
return F;
}
default: default:
critical_error("Bad I/O task",task->type); critical_error("Bad I/O task",task->type);
return F; return F;

View File

@ -1,7 +1,8 @@
typedef enum { typedef enum {
IO_TASK_READ_LINE, IO_TASK_READ_LINE,
IO_TASK_READ_COUNT, IO_TASK_READ_COUNT,
IO_TASK_WRITE IO_TASK_WRITE,
IO_TASK_ACCEPT
} IO_TASK_TYPE; } IO_TASK_TYPE;
typedef struct { typedef struct {
@ -28,6 +29,7 @@ IO_TASK* add_io_task(
int* fd_count); int* fd_count);
void primitive_add_read_line_io_task(void); void primitive_add_read_line_io_task(void);
void primitive_add_write_io_task(void); void primitive_add_write_io_task(void);
void primitive_add_accept_io_task(void);
void remove_io_task( void remove_io_task(
IO_TASK_TYPE type, IO_TASK_TYPE type,
PORT* port, PORT* port,

View File

@ -17,6 +17,9 @@ PORT* port(CELL fd)
port->fd = fd; port->fd = fd;
port->buffer = NULL; port->buffer = NULL;
port->line = F; port->line = F;
port->client_host = F;
port->client_port = F;
port->client_socket = F;
port->buf_mode = B_NONE; port->buf_mode = B_NONE;
port->buf_fill = 0; port->buf_fill = 0;
port->buf_pos = 0; port->buf_pos = 0;
@ -60,6 +63,9 @@ void fixup_port(PORT* port)
if(port->buffer != 0) if(port->buffer != 0)
port->buffer = fixup_untagged_string(port->buffer); port->buffer = fixup_untagged_string(port->buffer);
fixup(&port->line); fixup(&port->line);
fixup(&port->client_host);
fixup(&port->client_port);
fixup(&port->client_socket);
} }
void collect_port(PORT* port) void collect_port(PORT* port)
@ -67,4 +73,7 @@ void collect_port(PORT* port)
if(port->buffer != 0) if(port->buffer != 0)
port->buffer = copy_untagged_string(port->buffer); port->buffer = copy_untagged_string(port->buffer);
copy_object(&port->line); copy_object(&port->line);
copy_object(&port->client_host);
copy_object(&port->client_port);
copy_object(&port->client_socket);
} }

View File

@ -7,6 +7,10 @@ typedef struct {
STRING* buffer; STRING* buffer;
/* tagged partial line used by read_line_fd */ /* tagged partial line used by read_line_fd */
CELL line; CELL line;
/* tagged client info used by accept_fd */
CELL client_host;
CELL client_port;
CELL client_socket;
/* one of B_READ, B_WRITE or B_NONE */ /* one of B_READ, B_WRITE or B_NONE */
B_MODE buf_mode; B_MODE buf_mode;
/* top of buffer */ /* top of buffer */

View File

@ -119,6 +119,7 @@ XT primitives[] = {
primitive_exit, primitive_exit,
primitive_server_socket, primitive_server_socket,
primitive_close_fd, primitive_close_fd,
primitive_add_accept_io_task,
primitive_accept_fd, primitive_accept_fd,
primitive_can_read_line, primitive_can_read_line,
primitive_add_read_line_io_task, primitive_add_read_line_io_task,

View File

@ -1,4 +1,4 @@
extern XT primitives[]; extern XT primitives[];
#define PRIMITIVE_COUNT 133 #define PRIMITIVE_COUNT 134
CELL primitive_to_xt(CELL primitive); CELL primitive_to_xt(CELL primitive);

View File

@ -43,25 +43,32 @@ void primitive_server_socket(void)
dpush(tag_object(port(make_server_socket(p)))); dpush(tag_object(port(make_server_socket(p))));
} }
int accept_connection(int sock) CELL accept_connection(PORT* p)
{ {
struct sockaddr_in clientname; struct sockaddr_in clientname;
size_t size = sizeof(clientname); size_t size = sizeof(clientname);
int new = accept(sock,(struct sockaddr *)&clientname,&size); int new = accept(p->fd,(struct sockaddr *)&clientname,&size);
if(new < 0) if(new < 0)
{
if(errno == EAGAIN)
return false;
else
io_error(NULL,__FUNCTION__); io_error(NULL,__FUNCTION__);
}
printf("Connection from host %s, port %hd.\n", p->client_host = tag_object(from_c_string(inet_ntoa(
inet_ntoa(clientname.sin_addr), clientname.sin_addr)));
ntohs(clientname.sin_port)); p->client_port = tag_fixnum(ntohs(clientname.sin_port));
p->client_socket = tag_object(port(new));
return new; return true;
} }
void primitive_accept_fd(void) void primitive_accept_fd(void)
{ {
PORT* p = untag_port(dpop()); PORT* port = untag_port(dpop());
PORT* new = port(accept_connection(p->fd)); dpush(port->client_host);
dpush(tag_object(new)); dpush(port->client_port);
dpush(port->client_socket);
} }

View File

@ -1,4 +1,4 @@
int make_server_socket(CHAR port); int make_server_socket(CHAR port);
void primitive_server_socket(void); void primitive_server_socket(void);
int accept_connection(int sock); CELL accept_connection(PORT* p);
void primitive_accept_fd(void); void primitive_accept_fd(void);