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

View File

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

View File

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

View File

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

View File

@ -52,12 +52,12 @@ public class ComplexLiteral extends FactorParsingDefinition
{
// Read two numbers
Number real = FactorJava.toNumber(
reader.nextNonEOF(true,false));
reader.nextNonEOL(true,false));
Number imaginary = FactorJava.toNumber(
reader.nextNonEOF(true,false));
reader.nextNonEOL(true,false));
// Read the end
String end = (String)reader.nextNonEOF(false,false);
String end = (String)reader.nextNonEOL(false,false);
if(!end.equals(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)
throws Exception
{
String next = (String)reader.next(false,false);
String next = (String)reader.nextNonEOL(false,false);
reader.setIn(next);
reader.addUse(next);

View File

@ -48,6 +48,6 @@ public class PassThrough extends FactorParsingDefinition
throws Exception
{
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)
throws Exception
{
String next = (String)reader.next(false,false);
String next = (String)reader.nextNonEOL(false,false);
reader.addUse(next);
} //}}}

View File

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

View File

@ -56,3 +56,10 @@ USE: strings
: blocking-read-line ( port -- line )
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: lists
USE: stack
USE: strings
USE: vectors
DEFER: namespace
@ -77,9 +78,12 @@ DEFER: >n
: set ( value variable -- ) namespace set* ;
: put ( variable value -- ) namespace put* ;
: vars ( -- list ) namespace hash-keys ;
: values ( -- list ) namespace hash-values ;
: vars-values ( -- list ) namespace hash>alist ;
: car-str-sort ( list -- list )
[ swap car swap car str-lexi> ] sort ;
: 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.
: namespace? hashtable? ;

View File

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

View File

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

View File

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

View File

@ -59,6 +59,14 @@ void primitive_add_write_io_task(void)
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(
IO_TASK_TYPE type,
PORT* port,
@ -166,6 +174,18 @@ CELL perform_io_task(IO_TASK* task)
&write_fd_count);
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:
critical_error("Bad I/O task",task->type);
return F;

View File

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

View File

@ -17,6 +17,9 @@ PORT* port(CELL fd)
port->fd = fd;
port->buffer = NULL;
port->line = F;
port->client_host = F;
port->client_port = F;
port->client_socket = F;
port->buf_mode = B_NONE;
port->buf_fill = 0;
port->buf_pos = 0;
@ -60,6 +63,9 @@ void fixup_port(PORT* port)
if(port->buffer != 0)
port->buffer = fixup_untagged_string(port->buffer);
fixup(&port->line);
fixup(&port->client_host);
fixup(&port->client_port);
fixup(&port->client_socket);
}
void collect_port(PORT* port)
@ -67,4 +73,7 @@ void collect_port(PORT* port)
if(port->buffer != 0)
port->buffer = copy_untagged_string(port->buffer);
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;
/* tagged partial line used by read_line_fd */
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 */
B_MODE buf_mode;
/* top of buffer */

View File

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

View File

@ -1,4 +1,4 @@
extern XT primitives[];
#define PRIMITIVE_COUNT 133
#define PRIMITIVE_COUNT 134
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))));
}
int accept_connection(int sock)
CELL accept_connection(PORT* p)
{
struct sockaddr_in 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(errno == EAGAIN)
return false;
else
io_error(NULL,__FUNCTION__);
}
printf("Connection from host %s, port %hd.\n",
inet_ntoa(clientname.sin_addr),
ntohs(clientname.sin_port));
p->client_host = tag_object(from_c_string(inet_ntoa(
clientname.sin_addr)));
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)
{
PORT* p = untag_port(dpop());
PORT* new = port(accept_connection(p->fd));
dpush(tag_object(new));
PORT* port = untag_port(dpop());
dpush(port->client_host);
dpush(port->client_port);
dpush(port->client_socket);
}

View File

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