-CC = gcc
+CC = gcc34
DEFAULT_CFLAGS = -Wall -export-dynamic -g $(SITE_CFLAGS)
DEFAULT_LIBS = -lm
-FFI:\r
-\r
- add a socket timeout\r
- fix error postoning -- not all errors thrown by i/o code are\r
postponed\r
-- quit responder breaks with multithreading\r
\r
+ compiler/ffi:\r
\r
\r
+ listener/plugin:\r
\r
-- clean up listener's action popups\r
- accept multi-line input in listener\r
- don't show listener on certain commands\r
- NPE in ErrorHighlight\r
] catch ;
: httpd-connection ( socket -- )
- #! We're single-threaded in Java Factor, and
- #! multi-threaded in CFactor.
- java? [
- httpd-client
- ] [
- [
- httpd-client
- ] in-thread drop
- ] ifte ;
+ "http-server" get accept [ httpd-client ] in-thread drop ;
-: quit-flag ( -- ? )
- global [ "httpd-quit" get ] bind ;
-
-: clear-quit-flag ( -- )
- global [ "httpd-quit" off ] bind ;
-
-: httpd-loop ( server -- server )
- quit-flag [
- dup dup accept httpd-connection
- httpd-loop
- ] unless ;
+: httpd-loop ( -- )
+ [ httpd-connection ] forever ;
: (httpd) ( port -- )
- <server> [
+ <server> "http-server" set [
httpd-loop
] [
- swap fclose clear-quit-flag rethrow
+ "http-server" get fclose rethrow
] catch ;
: httpd ( port -- )
IN: quit-responder
USE: combinators
-USE: namespaces
-USE: stdio
-USE: stack
-
USE: httpd
USE: httpd-responder
+USE: namespaces
+USE: stack
+USE: stdio
+USE: streams
: quit-prohibited ( -- )
"404 quit prohibited" httpd-error ;
"quit-prohibited" get [
quit-prohibited
] [
- global [ t "httpd-quit" set ] bind
+ "http-server" get fclose
] ifte ;
: f-type 6 ;
: t-type 7 ;
: array-type 8 ;
-: vector-type 9 ;
-: string-type 10 ;
-: sbuf-type 11 ;
-: handle-type 12 ;
-: bignum-type 13 ;
-: float-type 14 ;
+: bignum-type 9 ;
+: float-type 10 ;
+: vector-type 11 ;
+: string-type 12 ;
: immediate ( x tag -- tagged ) swap tag-bits shift bitor ;
: >header ( id -- tagged ) header-tag immediate ;
"/library/format.factor"
"/library/platform/native/unparser.factor"
- "/library/styles.factor"
+ "/library/presentation.factor"
"/library/vocabulary-style.factor"
"/library/prettyprint.factor"
"/library/platform/native/debugger.factor"
: callstack-overflow-error ( obj -- )
drop "Callstack overflow" print ;
+: port-closed-error ( obj -- )
+ "Port closed: " write . ;
+
: kernel-error. ( obj n -- str )
{
expired-error
datastack-overflow-error
callstack-underflow-error
callstack-overflow-error
+ port-closed-error
} vector-nth execute ;
: kernel-error? ( obj -- ? )
: hashcode ( obj -- hash )
#! If two objects are =, they must have equal hashcodes.
{
- nop
- word-hashcode
- cons-hashcode
- default-hashcode
- >fixnum
- >fixnum
- default-hashcode
- default-hashcode
- default-hashcode
- vector-hashcode
- str-hashcode
- sbuf-hashcode
- default-hashcode
- >fixnum
- >fixnum
- default-hashcode
- default-hashcode
+ nop ! 0
+ word-hashcode ! 1
+ cons-hashcode ! 2
+ default-hashcode ! 3
+ >fixnum ! 4
+ >fixnum ! 5
+ default-hashcode ! 6
+ default-hashcode ! 7
+ default-hashcode ! 8
+ >fixnum ! 9
+ >fixnum ! 10
+ vector-hashcode ! 11
+ str-hashcode ! 12
+ sbuf-hashcode ! 13
+ default-hashcode ! 14
+ default-hashcode ! 15
+ default-hashcode ! 16
} generic ;
IN: math DEFER: number= ( defined later... )
: = ( obj obj -- ? )
#! Push t if a is isomorphic to b.
{
- number=
- eq?
- cons=
- eq?
- number=
- number=
- eq?
- eq?
- eq?
- vector=
- str=
- sbuf=
- eq?
- number=
- number=
- eq?
- eq?
- } generic ;
+ number= ! 0
+ eq? ! 1
+ cons= ! 2
+ eq? ! 3
+ number= ! 4
+ number= ! 5
+ eq? ! 6
+ eq? ! 7
+ eq? ! 8
+ number= ! 9
+ number= ! 10
+ vector= ! 11
+ str= ! 12
+ sbuf= ! 13
+ eq? ! 14
+ eq? ! 15
+ eq? ! 16
+ } generic ;
: 2= ( a b c d -- ? )
#! Test if a = c, b = d.
(not-=)
(not-=)
(not-=)
+ bignum=
+ float=
(not-=)
(not-=)
(not-=)
(not-=)
- bignum=
- float=
(not-=)
(not-=)
} 2generic ;
no-method
no-method
no-method
+ bignum+
+ float+
no-method
no-method
no-method
no-method
- bignum+
- float+
no-method
no-method
} 2generic ;
no-method
no-method
no-method
+ bignum-
+ float-
no-method
no-method
no-method
no-method
- bignum-
- float-
no-method
no-method
} 2generic ;
no-method
no-method
no-method
+ bignum*
+ float*
no-method
no-method
no-method
no-method
- bignum*
- float*
no-method
no-method
} 2generic ;
no-method
no-method
no-method
+ ratio
+ float/f
no-method
no-method
no-method
no-method
- ratio
- float/f
no-method
no-method
} 2generic ;
no-method
no-method
no-method
+ bignum/i
no-method
no-method
no-method
no-method
- bignum/i
no-method
no-method
no-method
no-method
no-method
no-method
+ bignum/f
+ float/f
no-method
no-method
no-method
no-method
- bignum/f
- float/f
no-method
no-method
} 2generic ;
no-method
no-method
no-method
+ bignum-mod
no-method
no-method
no-method
no-method
- bignum-mod
no-method
no-method
no-method
no-method
no-method
no-method
+ bignum/mod
no-method
no-method
no-method
no-method
- bignum/mod
no-method
no-method
no-method
no-method
no-method
no-method
+ bignum-bitand
no-method
no-method
no-method
no-method
- bignum-bitand
no-method
no-method
no-method
no-method
no-method
no-method
+ bignum-bitor
no-method
no-method
no-method
no-method
- bignum-bitor
no-method
no-method
no-method
no-method
no-method
no-method
+ bignum-bitxor
no-method
no-method
no-method
no-method
- bignum-bitxor
no-method
no-method
no-method
no-method
no-method
no-method
+ bignum-bitnot
no-method
no-method
no-method
no-method
- bignum-bitnot
no-method
no-method
no-method
no-method
no-method
no-method
+ bignum-shift
no-method
no-method
no-method
no-method
- bignum-shift
no-method
no-method
no-method
no-method
no-method
no-method
+ bignum<
+ float<
no-method
no-method
no-method
no-method
- bignum<
- float<
no-method
no-method
} 2generic ;
no-method
no-method
no-method
+ bignum<=
+ float<=
no-method
no-method
no-method
no-method
- bignum<=
- float<=
no-method
no-method
} 2generic ;
no-method
no-method
no-method
+ bignum>
+ float>
no-method
no-method
no-method
no-method
- bignum>
- float>
no-method
no-method
} 2generic ;
no-method
no-method
no-method
+ bignum>=
+ float>=
no-method
no-method
no-method
no-method
- bignum>=
- float>=
no-method
no-method
} 2generic ;
: #{
#! Read #{ real imaginary #}
scan str>number scan str>number rect> "}" expect parsed ;
+ parsing
! Comments
: ( ")" until parsed-stack-effect ; parsing
[ client-socket | " host port -- in out " ]
[ server-socket | " port -- server " ]
[ close-port | " port -- " ]
- [ add-accept-io-task | " callback server -- " ]
+ [ add-accept-io-task | " server callback -- " ]
[ accept-fd | " server -- host port in out " ]
[ can-read-line? | " port -- ? " ]
[ add-read-line-io-task | " port callback -- " ]
IN: lists : cons? ( obj -- ? ) type 2 eq? ;
IN: math : ratio? ( obj -- ? ) type 4 eq? ;
IN: math : complex? ( obj -- ? ) type 5 eq? ;
-IN: vectors : vector? ( obj -- ? ) type 9 eq? ;
-IN: strings : string? ( obj -- ? ) type 10 eq? ;
-IN: strings : sbuf? ( obj -- ? ) type 11 eq? ;
-IN: io-internals : port? ( obj -- ? ) type 12 eq? ;
-IN: math : bignum? ( obj -- ? ) type 13 eq? ;
-IN: math : float? ( obj -- ? ) type 14 eq? ;
+IN: math : bignum? ( obj -- ? ) type 9 eq? ;
+IN: math : float? ( obj -- ? ) type 10 eq? ;
+IN: vectors : vector? ( obj -- ? ) type 11 eq? ;
+IN: strings : string? ( obj -- ? ) type 12 eq? ;
+IN: strings : sbuf? ( obj -- ? ) type 13 eq? ;
+IN: io-internals : port? ( obj -- ? ) type 14 eq? ;
IN: alien : dll? ( obj -- ? ) type 15 eq? ;
IN: alien : alien? ( obj -- ? ) type 16 eq? ;
[ 6 | "f" ]
[ 7 | "t" ]
[ 8 | "array" ]
- [ 9 | "vector" ]
- [ 10 | "string" ]
- [ 11 | "sbuf" ]
- [ 12 | "port" ]
- [ 13 | "bignum" ]
- [ 14 | "float" ]
+ [ 9 | "bignum" ]
+ [ 10 | "float" ]
+ [ 11 | "vector" ]
+ [ 12 | "string" ]
+ [ 13 | "sbuf" ]
+ [ 14 | "port" ]
[ 15 | "dll" ]
[ 16 | "alien" ]
! These values are only used by the kernel for error
unparse-f
unparse-t
unparse-unknown
+ >dec
+ unparse-float
unparse-unknown
unparse-str
unparse-unknown
unparse-unknown
- >dec
- unparse-float
unparse-unknown
unparse-unknown
} generic ;
: (style) ( name -- style ) "styles" get get* ;
: default-style ( -- style ) "default" (style) ;
-: style ( name -- style )
- (style) [ default-style ] unless* ;
+: style ( name -- style ) (style) [ default-style ] unless* ;
: set-style ( style name -- ) "styles" get set* ;
<namespace> "styles" set
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-IN: words
+IN: presentation
USE: combinators
USE: lists
USE: kernel
USE: namespaces
USE: stack
-USE: presentation
+USE: words
: vocab-style ( vocab -- style )
#! Each vocab has a style object specifying how words are
{
CELL type1 = type_of(obj1);
CELL type2 = type_of(obj2);
+
CELL type;
switch(type1)
void general_error(CELL error, CELL tagged)
{
CELL c = cons(error,cons(tagged,F));
- if(userenv[BREAK_ENV] == 0)
+ if(userenv[BREAK_ENV] == F)
{
/* Crash at startup */
fprintf(stderr,"Error thrown before BREAK_ENV set\n");
#define ERROR_DATASTACK_OVERFLOW (16<<3)
#define ERROR_CALLSTACK_UNDERFLOW (17<<3)
#define ERROR_CALLSTACK_OVERFLOW (18<<3)
+#define ERROR_CLOSED (19<<3)
void fatal_error(char* msg, CELL tagged);
void critical_error(char* msg, CELL tagged);
}
void remove_io_task(
- IO_TASK_TYPE type,
PORT* port,
IO_TASK* io_tasks,
int* fd_count)
*fd_count = *fd_count - 1;
}
-void remove_io_tasks(PORT* port)
-{
- remove_io_task(IO_TASK_READ_LINE,port,
- read_io_tasks,&read_fd_count);
- remove_io_task(IO_TASK_WRITE,port,
- write_io_tasks,&write_fd_count);
-}
-
bool perform_copy_from_io_task(PORT* port, PORT* other_port)
{
if(port->buf_fill == 0)
write_io_tasks,&write_fd_count);
}
-bool set_up_fd_set(fd_set* fdset, int fd_count, IO_TASK* io_tasks)
+/* We set closed to true if there are closed fd's in the set. */
+bool set_up_fd_set(fd_set* fdset, int fd_count, IO_TASK* io_tasks,
+ bool* closed)
{
bool retval = false;
int i;
{
if(typep(PORT_TYPE,io_tasks[i].port))
{
+ if(untag_port(io_tasks[i].port)->closed)
+ *closed = true;
retval = true;
FD_SET(i,fdset);
}
CONS* callbacks = untag_cons(io_tasks[fd].callbacks);
CELL callback = callbacks->car;
if(callbacks->cdr == F)
- remove_io_task(type,port,io_tasks,fd_count);
+ remove_io_task(port,io_tasks,fd_count);
else
io_tasks[fd].callbacks = callbacks->cdr;
return callback;
for(i = 0; i < *fd_count; i++)
{
+ IO_TASK io_task = io_tasks[i];
+
+ if(typep(PORT_TYPE,io_task.port))
+ {
+ PORT* port = untag_port(io_task.port);
+ if(port->closed)
+ {
+ return pop_io_task_callback(
+ io_task.type,port,
+ io_tasks,fd_count);
+ }
+ }
+
if(FD_ISSET(i,fdset))
{
- if(io_tasks[i].port == F)
+ if(io_task.port == F)
critical_error("select() returned fd for non-existent task",i);
else
{
- callback = perform_io_task(&io_tasks[i],
+ callback = perform_io_task(&io_task,
io_tasks,fd_count);
if(callback != F)
return callback;
{
CELL callback;
+ bool closed = false;
+
bool reading = set_up_fd_set(&read_fd_set,
- read_fd_count,read_io_tasks);
+ read_fd_count,read_io_tasks,&closed);
bool writing = set_up_fd_set(&write_fd_set,
- write_fd_count,write_io_tasks);
+ write_fd_count,write_io_tasks,&closed);
- if(!reading && !writing)
+ if(!reading && !writing && !closed)
general_error(ERROR_IO_TASK_NONE,F);
- set_up_fd_set(&except_fd_set,
- read_fd_count,read_io_tasks);
+ set_up_fd_set(&except_fd_set,read_fd_count,read_io_tasks,&closed);
+
+ if(!closed)
+ {
+ select(read_fd_count > write_fd_count
+ ? read_fd_count : write_fd_count,
+ &read_fd_set,&write_fd_set,&except_fd_set,NULL);
+ }
+
+ callback = perform_io_tasks(&read_fd_set,
+ read_io_tasks,&read_fd_count);
- select(read_fd_count > write_fd_count ? read_fd_count : write_fd_count,
- &read_fd_set,&write_fd_set,&except_fd_set,NULL);
-
- callback = perform_io_tasks(&read_fd_set,read_io_tasks,&read_fd_count);
if(callback != F)
return callback;
- return perform_io_tasks(&write_fd_set,write_io_tasks,&write_fd_count);
+ return perform_io_tasks(&write_fd_set,
+ write_io_tasks,&write_fd_count);
}
void primitive_next_io_task(void)
/* This does not flush. */
PORT* port = untag_port(dpop());
close(port->fd);
+ port->closed = true;
}
void collect_io_tasks(void)
IO_TASK* io_tasks,
int* fd_count);
void remove_io_task(
- IO_TASK_TYPE type,
PORT* port,
IO_TASK* io_tasks,
int* fd_count);
PORT* port,
IO_TASK* io_tasks,
int* fd_count);
-bool set_up_fd_set(fd_set* fdset, int fd_count, IO_TASK* io_tasks);
+bool set_up_fd_set(fd_set* fdset, int fd_count, IO_TASK* io_tasks,
+ bool* closed);
CELL perform_io_task(IO_TASK* io_task, IO_TASK* io_tasks, int* fd_count);
CELL perform_io_tasks(fd_set* fdset, IO_TASK* io_tasks, int* fd_count);
CELL next_io_task(void);
/* after image load & save, ports are no longer valid */
if(p->fd == -1)
general_error(ERROR_EXPIRED,tagged);
+ /* if(p->closed)
+ general_error(ERROR_CLOSED,tagged); */
return p;
}
{
PORT* port = allot_object(PORT_TYPE,sizeof(PORT));
port->type = type;
+ port->closed = false;
port->fd = fd;
port->buffer = NULL;
port->line = F;
port->io_error = F;
general_error(ERROR_IO,io_error);
}
+ else if(port->closed)
+ general_error(ERROR_CLOSED,tag_object(port));
}
void primitive_pending_io_error(void)
#define BUF_SIZE (8 * 1024)
-typedef enum { PORT_READ, PORT_RECV, PORT_WRITE, PORT_SPECIAL } PORT_MODE;
+typedef enum {
+ PORT_READ,
+ PORT_RECV,
+ PORT_WRITE,
+ PORT_SPECIAL
+} PORT_MODE;
typedef struct {
CELL header;
- /* one of PORT_READ, PORT_RECV, PORT_WRITE or PORT_SPECIAL */
PORT_MODE type;
+ bool closed;
FIXNUM fd;
STRING* buffer;
/* Error handling. */
sigsetjmp(toplevel, 1);
-
+
for(;;)
{
if(callframe == F)
CELL ds_bot;
/* raw pointer to datastack top */
+/* #define X86_STACK */
+
+#ifdef X86_STACK
+register CELL ds asm("%esi");
+#else
CELL ds;
+#endif
/* raw pointer to callstack bottom */
CELL cs_bot;
/* raw pointer to callstack top */
+#ifdef X86_STACK
+register CELL cs asm("edi");
+#else
CELL cs;
+#endif
/* raw pointer to currently executing word */
WORD* executing;
PORT* p;
maybe_garbage_collection();
p = untag_port(dpop());
+ pending_io_error(p);
dpush(p->client_host);
dpush(p->client_port);
dpush(tag_object(port(PORT_RECV,p->client_socket)));
CELL T;
#define ARRAY_TYPE 8
-#define VECTOR_TYPE 9
-#define STRING_TYPE 10
-#define SBUF_TYPE 11
-#define PORT_TYPE 12
-#define BIGNUM_TYPE 13
-#define FLOAT_TYPE 14
+#define BIGNUM_TYPE 9
+#define FLOAT_TYPE 10
+#define VECTOR_TYPE 11
+#define STRING_TYPE 12
+#define SBUF_TYPE 13
+#define PORT_TYPE 14
#define DLL_TYPE 15
#define ALIEN_TYPE 16