Sequence API refactoring, as described in
http://www.jroller.com/page/slava/20050518.
+HTTP server now supports virtual hosting.
+
Factor 0.74:
------------
- investigate if COPYING_GEN needs a fix\r
- faster layout\r
- add a socket timeout\r
-- virtual hosts\r
- keep alive\r
- sleep word\r
- redo new compiler backend for PowerPC\r
- index and index* are very slow with lists\r
- code walker & exceptions\r
- if two tasks write to a unix stream, the buffer can overflow\r
-- rename prettyprint to pprint\r
+- rename prettyprint* to pprint, prettyprint to pp\r
- reader syntax for arrays, byte arrays, displaced aliens\r
- dipping seq-2nmap, seq-2each\r
- array sort\r
- merge inc-d's across VOPs that don't touch the stack\r
- [ EAX 0 ] --> [ EAX ]\r
- intrinsic char-slot set-char-slot integer-slot set-integer-slot\r
-- optimize the generic word prologue\r
- [ [ dup call ] dup call ] infer hangs\r
- more accurate types for various words\r
- declarations\r
displaced, register and other predicates need to inherit from list\r
not cons, and need stronger branch partial eval\r
- optimize away arithmetic dispatch\r
-- dataflow optimizer needs eq not =\r
- the invalid recursion form case needs to be fixed, for inlines too\r
- #jump-f #jump-f-label\r
- re-introduce #target-label => #target optimization\r
%\texttt{array}&$\surd$&&$O(1)$&&&Low-level and unsafe\\
\texttt{list}&&&$O(n)$&$O(1)$&$O(n)$&Functional manipulation\\
\texttt{vector}&$\surd$&$\surd$&$O(1)$&$O(n)$&$O(1)$&Imperitive aggregation\\
-\texttt{sbuf}&$\surd$&$\surd$&$O(1)$&$O(n)$&$O(1)$&Character accumilation\\
+\texttt{sbuf}&$\surd$&$\surd$&$O(1)$&$O(n)$&$O(1)$&Character accumulation\\
\texttt{string}&&&$O(1)$&&&Immutable text strings
\end{tabular}
! Copyright (C) 2004, 2005 Slava Pestov.
! See http://factor.sf.net/license.txt for BSD license.
USING: alien assembler command-line compiler compiler-backend
-io-internals kernel lists math namespaces parser sequences stdio
-unparser words ;
+compiler-frontend io-internals kernel lists math namespaces
+parser sequences stdio unparser words ;
"Compiling base..." print
\ = compile
\ unparse compile
\ scan compile
+ \ optimize compile
\ (generate) compile
] when
over "responder" set
reset-continuation-table
permanent register-continuation root-continuation set
- ] extend swap "httpd-responders" get set-hash ;
+ ] extend swap responders get set-hash ;
: responder-items ( name -- items )
#! Return the table of continuation items for a given responder.
#! Useful for debugging.
- "httpd-responders" get hash [ continuation-table ] bind ;
+ responders get hash [ continuation-table ] bind ;
: simple-page ( title quot -- )
#! Remove all existing responders, and create a blank
#! responder table.
global [
- <namespace> "httpd-responders" set
+ <namespace> responders set
! Runs all unit tests and dumps result to the client. This uses
! a lot of server resources, so disable it on a busy server.
! The root directory is served by...
"file" set-default-responder
- "httpd-vhosts" nest [
- <namespace> "default" set
- ] bind
+ vhosts nest [ <namespace> "default" set ] bind
] bind
[[ "HEAD" "head" ]]
] assoc [ "bad" ] unless* ;
+: host ( -- string )
+ #! The host the current responder was called from.
+ "Host" "header" get assoc ":" split1 drop ;
+
: (handle-request) ( arg cmd -- method path host )
request-method dup "method" set swap
- prepare-url prepare-header
- "Host" "header" get assoc ":" split1 drop ;
+ prepare-url prepare-header host ;
: handle-request ( arg cmd -- )
[ (handle-request) serve-responder ] with-scope ;
: httpd-client ( socket -- )
[
dup log-client [
+ 1 stdio get set-timeout
read-line [ parse-request ] when*
] with-stream
] try ;
USING: hashtables http kernel lists namespaces parser sequences
stdio streams strings ;
+! Variables
+SYMBOL: vhosts
+SYMBOL: responders
+
: print-header ( alist -- )
[ unswons write ": " write url-encode print ] each ;
] extend ;
: vhost ( name -- responder )
- "httpd-vhosts" get hash [ "default" vhost ] unless* ;
+ vhosts get hash [ "default" vhost ] unless* ;
: responder ( name -- responder )
- "httpd-responders" get hash [
- "404" "httpd-responders" get hash
- ] unless* ;
+ responders get hash [ "404" responder ] unless* ;
: set-default-responder ( name -- )
- responder "default" "httpd-responders" get set-hash ;
+ responder "default" responders get set-hash ;
: responder-argument ( argument -- argument )
dup empty? [ drop "default-argument" get ] when ;
: add-responder ( responder -- )
#! Add a responder object to the list.
- "responder" over hash "httpd-responders" get set-hash ;
+ "responder" over hash responders get set-hash ;
: <client> c-stream-error ;
: <server> c-stream-error ;
: accept c-stream-error ;
+: set-timeout c-stream-error ;
: (stream-copy) ( in out -- )
4096 pick stream-read [
"Object type: " write class word. terpri
"Expected type: " write builtin-type word. terpri ;
-: range-error. ( list -- )
- "Range check error" print
- unswons [ "Object: " write . ] when*
- unswons "Minimum index: " write .
- unswons "Requested index: " write .
- car "Maximum index: " write . ;
-
: float-format-error. ( list -- )
"Invalid floating point literal format: " write . ;
io-error.
undefined-word-error.
type-check-error.
- range-error.
float-format-error.
signal-error.
negative-array-size-error.
: server-sockaddr ( port -- sockaddr )
init-sockaddr INADDR_ANY htonl over set-sockaddr-in-addr ;
-: sockopt ( fd level opt -- )
+: sockopt ( fd level opt value -- )
1 <int> "int" c-size setsockopt io-error ;
: server-socket ( port -- fd )
: <socket-stream> ( fd -- stream )
dup f <fd-stream> ;
+: timeout-opt ( fd level opt value -- )
+ "timeval" c-size setsockopt io-error ;
+
IN: streams
C: client-stream ( fd host port -- stream )
: accept ( server -- client )
#! Wait for a client connection.
dup wait-to-accept port-handle do-accept <client-stream> ;
+
+: set-timeout ( timeout client -- )
+ swap 0 make-timeval 2dup
+ >r duplex-stream-out port-handle SOL_SOCKET SO_SNDTIMEO r>
+ timeout-opt
+ >r duplex-stream-in port-handle SOL_SOCKET SO_RCVTIMEO r>
+ timeout-opt ;
: SOL_SOCKET HEX: ffff ;
: SO_REUSEADDR HEX: 4 ;
: SO_OOBINLINE HEX: 100 ;
+: SO_SNDTIMEO HEX: 1005 ;
+: SO_RCVTIMEO HEX: 1006 ;
: INADDR_ANY 0 ;
: POLLOUT HEX: 0004 ;
: SOL_SOCKET 1 ;
+
: SO_REUSEADDR 2 ;
: SO_OOBINLINE 10 ;
+: SO_SNDTIMEO HEX: 15 ;
+: SO_RCVTIMEO HEX: 14 ;
+
: INADDR_ANY 0 ;
: F_SETFL 4 ; ! set file status flags
: SOL_SOCKET HEX: ffff ;
: SO_REUSEADDR HEX: 4 ;
: SO_OOBINLINE HEX: 100 ;
+: SO_SNDTIMEO HEX: 1005 ;
+: SO_RCVTIMEO HEX: 1006 ;
: INADDR_ANY 0 ;
: ntohs ( n -- n )
"ushort" "libc" "ntohs" [ "ushort" ] alien-invoke ;
+
+BEGIN-STRUCT: timeval
+ FIELD: long sec
+ FIELD: long usec
+END-STRUCT
+
+: make-timeval ( sec usec -- timeval )
+ <timeval>
+ [ set-timeval-usec ] keep
+ [ set-timeval-sec ] keep ;
CELL to_cell(CELL x)
{
- F_FIXNUM fixnum;
- F_ARRAY* bignum;
-
switch(type_of(x))
{
case FIXNUM_TYPE:
- fixnum = untag_fixnum_fast(x);
- if(fixnum < 0)
- {
- range_error(F,0,tag_fixnum(fixnum),FIXNUM_MAX);
- return -1;
- }
- else
- return (CELL)fixnum;
- break;
+ return untag_fixnum_fast(x);
case BIGNUM_TYPE:
- bignum = to_bignum(x);
- if(BIGNUM_NEGATIVE_P(bignum))
- {
- range_error(F,0,tag_bignum(bignum),FIXNUM_MAX);
- return -1;
- }
- else
- return s48_bignum_to_long(untag_bignum_fast(x));
+ return s48_bignum_to_long(untag_bignum_fast(x));
default:
type_error(BIGNUM_TYPE,x);
return 0;
CELL c = cons(tag_fixnum(type),cons(tagged,F));
general_error(ERROR_TYPE,c);
}
-
-/* index must be tagged */
-void range_error(CELL tagged, CELL min, CELL index, CELL max)
-{
- CELL c = cons(tagged,cons(tag_cell(min),
- cons(index,cons(tag_cell(max),F))));
- general_error(ERROR_RANGE,c);
-}
#define ERROR_IO (1<<3)
#define ERROR_UNDEFINED_WORD (2<<3)
#define ERROR_TYPE (3<<3)
-#define ERROR_RANGE (4<<3)
-#define ERROR_FLOAT_FORMAT (5<<3)
-#define ERROR_SIGNAL (6<<3)
-#define ERROR_NEGATIVE_ARRAY_SIZE (7<<3)
-#define ERROR_C_STRING (8<<3)
-#define ERROR_FFI (9<<3)
-#define ERROR_HEAP_SCAN (10<<3)
+#define ERROR_FLOAT_FORMAT (4<<3)
+#define ERROR_SIGNAL (5<<3)
+#define ERROR_NEGATIVE_ARRAY_SIZE (6<<3)
+#define ERROR_C_STRING (7<<3)
+#define ERROR_FFI (8<<3)
+#define ERROR_HEAP_SCAN (9<<3)
/* When throw_error throws an error, it sets this global and
longjmps back to the top-level. */
void type_error(CELL type, CELL tagged);
void primitive_throw(void);
void primitive_die(void);
-/* index must be tagged */
-void range_error(CELL tagged, CELL min, CELL index, CELL max);