fix vocabulary mess up in factor plugin, working on non-blocking sockets
parent
171c890597
commit
f8e91e95f9
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)));
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
} //}}}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ;
|
||||
|
||||
|
|
|
@ -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? ;
|
||||
|
|
|
@ -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 ;
|
||||
|
|
|
@ -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__);
|
||||
|
||||
|
|
|
@ -1 +1,3 @@
|
|||
#define FILE_MODE 0600
|
||||
|
||||
void primitive_open_file(void);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
extern XT primitives[];
|
||||
#define PRIMITIVE_COUNT 133
|
||||
#define PRIMITIVE_COUNT 134
|
||||
|
||||
CELL primitive_to_xt(CELL primitive);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue