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