diff --git a/.cvskeywords b/.cvskeywords index c50dc065d8..7789ef63ab 100644 --- a/.cvskeywords +++ b/.cvskeywords @@ -1,10 +1,3 @@ -./library/windows/win32-io-internals.factor:! $Id: win32-io-internals.factor,v 1.15 2006/01/28 20:49:31 spestov Exp $ -./library/windows/win32-io.factor:! $Id: win32-io.factor,v 1.4 2005/07/23 06:11:07 eiz Exp $ -./library/windows/win32-stream.factor:! $Id: win32-stream.factor,v 1.16 2006/01/28 20:49:31 spestov Exp $ -./library/windows/win32-errors.factor:! $Id: win32-errors.factor,v 1.11 2005/12/22 02:30:00 erg Exp $ -./library/windows/win32-server.factor:! $Id: win32-server.factor,v 1.13 2006/01/28 20:49:31 spestov Exp $ -./library/windows/winsock.factor:! $Id: winsock.factor,v 1.8 2005/09/12 15:10:33 erg Exp $ -./library/bootstrap/win32-io.factor:! $Id: win32-io.factor,v 1.10 2005/09/29 19:26:32 eiz Exp $ -./native/s48_bignum.c:$Id: s48_bignum.c,v 1.12 2005/12/21 02:36:52 spestov Exp $ -./native/s48_bignumint.h:$Id: s48_bignumint.h,v 1.14 2005/12/21 02:36:52 spestov Exp $ -./native/s48_bignum.h:$Id: s48_bignum.h,v 1.13 2005/12/21 02:36:52 spestov Exp $ +./vm/bignum.h:$Id: s48_bignum.h,v 1.13 2005/12/21 02:36:52 spestov Exp $ +./vm/bignumint.h:$Id: s48_bignumint.h,v 1.14 2005/12/21 02:36:52 spestov Exp $ +./vm/bignum.c:$Id: s48_bignum.c,v 1.12 2005/12/21 02:36:52 spestov Exp $ diff --git a/Factor.app/Contents/Info.plist b/Factor.app/Contents/Info.plist index b683a88475..686c996b1f 100644 --- a/Factor.app/Contents/Info.plist +++ b/Factor.app/Contents/Info.plist @@ -12,5 +12,59 @@ Factor CFBundlePackageType APPL + CFBundleDocumentTypes + + + CFBundleTypeExtensions + + * + + CFBundleTypeName + Any + CFBundleTypeRole + Viewer + CFBundleTypeOSTypes + + **** + + + + NSServices + + + NSMenuItem + + default + Factor/Evaluate in Listener + + NSMessage + evalInListener + NSPortName + Factor + NSSendTypes + + NSStringPboardType + + + + NSMenuItem + + default + Factor/Evaluate Selection + + NSMessage + evalToString + NSPortName + Factor + NSSendTypes + + NSStringPboardType + + NSReturnTypes + + NSStringPboardType + + + diff --git a/Makefile b/Makefile index 19f65506da..517848de85 100644 --- a/Makefile +++ b/Makefile @@ -3,82 +3,51 @@ CC = gcc BINARY = f IMAGE = factor.image BUNDLE = Factor.app -DISK_IMAGE_DIR = Factor-0.82 -DISK_IMAGE = Factor-0.82.dmg +DISK_IMAGE_DIR = Factor-0.83 +DISK_IMAGE = Factor-0.83.dmg ifdef DEBUG - DEFAULT_CFLAGS = -g + CFLAGS = -g STRIP = touch else - DEFAULT_CFLAGS = -Wall -O3 -ffast-math -fomit-frame-pointer $(SITE_CFLAGS) + CFLAGS = -Wall -O3 -ffast-math -fomit-frame-pointer $(SITE_CFLAGS) STRIP = strip endif -DEFAULT_LIBS = -lm - ifdef NO_UI - UNIX_UI_LIBS = + X11_UI_LIBS = else - UNIX_UI_LIBS = -lfreetype -lGL -lGLU -L/usr/X11R6/lib -lX11 + X11_UI_LIBS = -lfreetype -lGL -lGLU -L/usr/X11R6/lib -lX11 endif -WINDOWS_OBJS = native/windows/ffi.o \ - native/windows/file.o \ - native/windows/misc.o \ - native/windows/run.o \ - native/windows/memory.o - -UNIX_OBJS = native/unix/file.o \ - native/unix/signal.o \ - native/unix/ffi.o \ - native/unix/memory.o \ - native/unix/icache.o - -MACOSX_OBJS = $(UNIX_OBJS) \ - native/macosx/run.o \ - native/macosx/mach_signal.o - -GENERIC_UNIX_OBJS = $(UNIX_OBJS) \ - native/unix/run.o - -ifdef WINDOWS - PLAF_OBJS = $(WINDOWS_OBJS) - PLAF_SUFFIX = .exe -else - ifdef MACOSX - PLAF_OBJS = $(MACOSX_OBJS) - else - PLAF_OBJS = $(GENERIC_UNIX_OBJS) - endif +ifdef CONFIG + include $(CONFIG) endif -OBJS = $(PLAF_OBJS) native/array.o native/bignum.o \ - native/s48_bignum.o \ - native/complex.o native/cons.o native/error.o \ - native/factor.o native/fixnum.o \ - native/float.o native/gc.o \ - native/image.o native/memory.o \ - native/misc.o native/primitives.o \ - native/ratio.o native/relocate.o \ - native/run.o \ - native/sbuf.o native/stack.o \ - native/string.o native/cards.o native/vector.o \ - native/word.o native/compiler.o \ - native/alien.o native/dll.o \ - native/boolean.o \ - native/debug.o \ - native/hashtable.o \ - native/io.o \ - native/wrapper.o \ - native/ffi_test.o +OBJS = $(PLAF_OBJS) \ + vm/alien.o \ + vm/bignum.o \ + vm/debug.o \ + vm/factor.o \ + vm/ffi_test.o \ + vm/image.o \ + vm/io.o \ + vm/math.o \ + vm/memory.o \ + vm/primitives.o \ + vm/run.o \ + vm/stack.o \ + vm/types.o default: @echo "Run 'make' with one of the following parameters:" @echo "" - @echo "bsd" - @echo "linux" + @echo "freebsd" + @echo "linux-x86" + @echo "linux-amd64" @echo "linux-ppc" - @echo "macosx" + @echo "macosx-x86" + @echo "macosx-ppc" @echo "solaris" @echo "windows" @echo "" @@ -91,30 +60,46 @@ default: @echo "" @echo "export SITE_CFLAGS=\"-march=pentium4 -ffast-math\"" -bsd: - $(MAKE) $(BINARY) \ - CFLAGS="$(DEFAULT_CFLAGS) -export-dynamic -pthread" \ - LIBS="$(DEFAULT_LIBS) $(UI_LIBS)" +freebsd: + $(MAKE) $(BINARY) CONFIG=vm/Config.freebsd + +macosx-freetype: + ln -sf libfreetype.6.dylib \ + Factor.app/Contents/Frameworks/libfreetype.dylib + +macosx-ppc: macosx-freetype + $(MAKE) $(BINARY) CONFIG=vm/Config.macosx.ppc + +macosx-x86: macosx-freetype + $(MAKE) $(BINARY) CONFIG=vm/Config.macosx + +linux-x86 linux-amd64: + $(MAKE) $(BINARY) CONFIG=vm/Config.linux $(STRIP) $(BINARY) -macosx: - $(MAKE) $(BINARY) \ - CFLAGS="$(DEFAULT_CFLAGS)" \ - LIBS="$(DEFAULT_LIBS) -framework Cocoa -framework OpenGL -lfreetype" \ - MACOSX=y +linux-ppc: + $(MAKE) $(BINARY) CONFIG=vm/Config.linux.ppc + $(STRIP) $(BINARY) + +solaris solaris-x86 solaris-amd64: + $(MAKE) $(BINARY) CONFIG=vm/Config.solaris + $(STRIP) $(BINARY) + +windows: + $(MAKE) $(BINARY) CONFIG=vm/Config.windows macosx.app: cp $(BINARY) $(BUNDLE)/Contents/MacOS/Factor rm -rf $(BUNDLE)/Contents/Resources/ mkdir -p $(BUNDLE)/Contents/Resources/fonts/ - cp -R fonts/*.ttf $(BUNDLE)/Contents/Resources/fonts/ chmod +x cp_dir - find doc library contrib examples \( -name '*.factor' \ + find doc library contrib examples fonts \( -name '*.factor' \ -o -name '*.facts' \ -o -name '*.txt' \ -o -name '*.html' \ + -o -name '*.ttf' \ -o -name '*.js' \) \ -exec ./cp_dir {} $(BUNDLE)/Contents/Resources/{} \; @@ -131,41 +116,20 @@ macosx.app: Factor.app/Contents/MacOS/Factor macosx.dmg: - rm -f $(DISK_IMAGE) + rm $(DISK_IMAGE) rm -rf $(DISK_IMAGE_DIR) mkdir $(DISK_IMAGE_DIR) cp -R $(BUNDLE) $(DISK_IMAGE_DIR)/$(BUNDLE) hdiutil create -srcfolder "$(DISK_IMAGE_DIR)" -fs HFS+ \ -volname "$(DISK_IMAGE_DIR)" "$(DISK_IMAGE)" -linux linux-x86 linux-amd64: - $(MAKE) $(BINARY) \ - CFLAGS="$(DEFAULT_CFLAGS) -export-dynamic" \ - LIBS="-ldl $(DEFAULT_LIBS) $(UNIX_UI_LIBS)" - $(STRIP) $(BINARY) - -linux-ppc: - $(MAKE) $(BINARY) \ - CFLAGS="$(DEFAULT_CFLAGS) -export-dynamic -mregnames" \ - LIBS="-ldl $(DEFAULT_LIBS) $(UNIX_UI_LIBS)" - $(STRIP) $(BINARY) - -solaris solaris-x86: - $(MAKE) $(BINARY) \ - CFLAGS="$(DEFAULT_CFLAGS) -D_STDC_C99 -Drestrict=\"\" " \ - LIBS="-ldl -lsocket -lnsl $(DEFAULT_LIBS) -R/opt/PM/lib -R/opt/csw/lib -R/usr/local/lib -R/usr/sfw/lib -R/usr/X11R6/lib -R/opt/sfw/lib $(UNIX_UI_LIBS)" - $(STRIP) $(BINARY) - -windows: - $(MAKE) $(BINARY) \ - CFLAGS="$(DEFAULT_CFLAGS) -DWINDOWS" \ - LIBS="$(DEFAULT_LIBS)" WINDOWS=y - f: $(OBJS) $(CC) $(LIBS) $(CFLAGS) -o $@$(PLAF_SUFFIX) $(OBJS) clean: - rm -f $(OBJS) + rm -f $(OBJS) $(UNIX_OBJS) $(WINDOWS_OBJS) $(MACOSX_OBJS) + rm -rf $(BUNDLE)/Contents/Resources/ + rm -f $(BUNDLE)/Contents/MacOS/Factor .c.o: $(CC) -c $(CFLAGS) -o $@ $< @@ -175,8 +139,3 @@ clean: .m.o: $(CC) -c $(CFLAGS) -o $@ $< - -boot: - echo "USE: image \"$(ARCH)\" make-image bye" | ./f factor.image - ./f boot.image.$(ARCH) $(BOOTSTRAP_FLAGS) - diff --git a/README.txt b/README.txt index 602262a74c..3d7042bcac 100644 --- a/README.txt +++ b/README.txt @@ -13,7 +13,6 @@ implementation. It is not an introduction to the language itself. - Running Factor on Mac OS X - Running Factor on Windows - Source organization -- Learning Factor - Community - Credits @@ -23,19 +22,21 @@ Factor is fully supported on the following platforms: Linux/x86 Linux/AMD64 + Mac OS X/x86 Mac OS X/PowerPC - Solaris/x86 - Microsoft Windows 2000 or later + MS Windows XP The following platforms should work, but are not tested on a regular basis: FreeBSD/x86 FreeBSD/AMD64 - Linux/PowerPC + Solaris/x86 Solaris/AMD64 + Linux/PowerPC -Other platforms are not supported. +Please donate time or hardware if you wish to see Factor running on +other platforms. * Compiling Factor @@ -47,12 +48,13 @@ Factor requires gcc 3.4 or later. On x86, it /will not/ build using gcc Run 'make' (or 'gmake' on non-Linux platforms) with one of the following parameters to build the Factor runtime: - bsd - linux + freebsd + linux-x86 + linux-amd64 linux-ppc - macosx + macosx-x86 + macosx-ppc solaris - windows The following options can be given to make: @@ -76,9 +78,10 @@ Compilation will yield an executable named 'f'. * Building Factor -The Factor source distribution ships with three boot image files: +The Factor source distribution ships with four boot image files: boot.image.x86 + boot.image.pentium4 -- uses SSE2, only for Pentium 4 and later boot.image.ppc boot.image.amd64 @@ -89,9 +92,6 @@ The system is bootstrapped with the following command line: ./f boot.image. -Additional options may be specified to load external C libraries; see -the next section for details. - Bootstrap can take a while, depending on your system. When the process completes, a 'factor.image' file will be generated. Note that this image is both CPU and OS-specific, so in general cannot be shared between @@ -141,29 +141,22 @@ between PowerPC Macs. * Running Factor on Windows -On Windows, double-clicking f.exe will start running the Win32-based UI -with the factor.image in the same directory as the executable. +If you did not download the binary package, you can bootstrap Factor in +the command prompt: -Bootstrap runs in a Windows command prompt, however after bootstrapping -only the UI can be used. + f.exe boot.image.pentium4 (or boot.image.x86) + +Once bootstrapped, double-clicking f.exe starts the Factor UI. There is +no option to run the listener in the command prompt on Windows. * Source organization doc/ - the developer's handbook, and various other bits and pieces - native/ - sources for the Factor runtime, written in C - library/ - sources for the library, written in Factor contrib/ - various handy libraries not part of the core examples/ - small examples illustrating various language features fonts/ - TrueType fonts used by UI - -* Learning Factor - -The UI has a tutorial and defailed reference documentation. You can -browse it in the UI or by running the HTTP server (contrib/httpd). - -You can browse the source code; it is organized into small, -well-commented files and should be easy to follow once you have a good -grasp of the language. + library/ - sources for the library, written in Factor + vm/ - sources for the Factor runtime, written in C * Community @@ -179,7 +172,9 @@ The following people have contributed code to the Factor core: Slava Pestov: Lead developer Alex Chapman: OpenGL binding -Doug Coleman: Mersenne Twister random number generator +Doug Coleman: Mersenne Twister RNG, Windows port +Eduardo Cavazos: X11 binding +Joshua Grams: PowerPC instruction cache flush code Mackenzie Straight: Windows port Trent Buck: Debian package diff --git a/TODO.FACTOR.txt b/TODO.FACTOR.txt index 5dd3e978bf..670151e50d 100644 --- a/TODO.FACTOR.txt +++ b/TODO.FACTOR.txt @@ -1,78 +1,129 @@ -should fix in 0.82: - -- another i/o bug: on factorcode eventually all i/o times out -- get factor running on mac intel - + io: +- unix i/o: problems with passing f to syscalls +- factorcode httpd started using 99% CPU, but still received connections; + closing read-fds solved it +- sometimes darcs get fails with the httpd - gdb triggers 'mutliple i/o ops on port' error -- stream server can hang because of exception handler limitations -- better i/o scheduler -- yield in a loop starves i/o - "localhost" 50 won't fail -+ ui/help: ++ ui: -- clicks sent twice -- speed up ideas: - - only do clipping for certain gadgets - - use glRect -- polish OS X menu bar code -- help search -- reimplement clicking input -- reimplement tab completion -- x11 input methods +- "benchmark/help" runs out of memory +- shortcuts: + - find a listener + - find a browser + - find a help window + - they'll either focus such a window, or if the current window is of + that type, cycle +- thumb min size +- support x11's large selections, if needed +- own-selection violates ICCCM +- one-column table doesn't need borders...? +- make-frame should compile +- editor: + - undo and redo + - transpose char/word/line + - autoscroll + - page up/down + - search and replace + - only redraw visible lines + - more efficient multi-line inserts + - editor should support stream output protocol + - scroll to caret + - better listener multi-line expression handling + - history doesn't work in a good way if you ^K the input + - history: move caret to end +- finish gui stepper +- cocoa: windows are not updated while resizing +- graphical module manager tool +- add some handy services: + - base conversion + - search help for selection +- make factor a services client +- services do not launch if factor not running +- grid slows down with 2000 lines +- integrated error documentation +- roundoff is still not quite right with tracks +- 'show' doesn't work if invoked from a listener on an object which is + itself inspected in the listener +- ui uses too much cpu time idling +- see if its possible to only repaint dirty regions - x11 title bars are funny -- cocoa: - - don't multiplex in the event loop if there is no pending i/o - - horizontal scrolling -- fix mouse-overs... -- display lists -- saving the image should save window configuration -- make the UI look better, something like this: - http://twb.ath.cx/~twb/darcs/OBSOLETE/factor/final.html -- fix remaining HTML stream issues -- fix up the min thumb size hack -- automatically update help graph when adding/removing articles/words -- document conventions -- new turtle graphics tutorial -- better line spacing in ui and html -- tabular formatting - for inspector, changes and $values in help -- grid layout -- variable width word wrap - fix top level window positioning -- changing window titles +- prettyprinter's highlighting of non-leaves doesn't really work +- rollover is not updated on window focus changes +- x11 input methods +- cocoa: + - horizontal wheel scrolling + - polish OS X menu bar code +- variable width word wrap +- slider needs to be modelized + ++ module system: + +- 'see' should show tuple constructors +- forgetting a class should remove its methods from all generic words + - offer to remove generic words which are not called and have no + methods +- forgetting a tuple class should forget the constructor +- seeing a tuple class should show the constructor +- C types should be words + - TYPEDEF: float { ... } { ... } ; ==> \ float T{ c-type ... } "c-type" swp + - TYPEDEF: float FTFloat ; ==> \ float \ FTFloat "c-type" swp + - make typedef aliasing explicit +- seeing a C struct word should show its def +- see by itself only shows the G: def +- { class generic } see supports forms: + { f generic } to show all methods + { class f } to show all methods +- modularize core +- TUPLE: module files tests articles article main ; +- methods: remember their file/line +- { class generic } jedit, reload DTRT +- requesting a list of assets loaded from a specific file +- T{ link f "foo" "bar" } see +- T{ link f "foo" "bar" } jedit +- T{ link f "foo" "bar" } reload +- generic 'define ( asset def -- )' +- file out +- make 'forget' generic + compiler/ffi: -- free up r11, r12 as a vreg on ppc -- float= on powerpc doesn't consider nans equal -- intrinsic fixnum>float float>fixnum -- win64 port -- amd64 %unbox-struct -- constant branch folding -- core foundation should use unicode strings -- alien>utf16-string, utf16-string>alien words -- can only be called with an alien? -- remove , , set-char*-nth, set-ushort*-nth since they - have incorrect semantics -- complex float type -- complex float intrinsics -- remove literal table -- C functions returning structs by value -- FIELD: char key_vector[32]; -- FIELD: union { char b[20]; short s[10]; long l[5]; } data; -- MEMBER: long pad[24]; -- C structs: use new-style string mode parsing +- nasty inference regressions - [ [ dup call ] dup call ] infer hangs - the invalid recursion form case needs to be fixed, for inlines too -- code gc +- instead of decompiling words, add them to a 'recompile' set; compiler + treats words in the recompile set as if they were not compiled +- mac intel: struct returns from objc methods +- see if alien calls can be made faster +- faster sequence= for UI - fix compiled gc check + - there was a performance hit, investigate + - float boxing and overflow checks need a gc check too +- constant branch folding +- type inference at branch merge points +- float= doesn't consider nans equal +- intrinsic fixnum>float float>fixnum +- remove literal table +- C functions returning structs by value +- code gc +- infer which variables are read, written in a quotation + misc: -- 3 >n fep -- code walker & exceptions +- consider: swap tail --> tail, swap head --> head +- mach_signal: fault address reporting is not reliable - slice: if sequence or seq start is changed, abstraction violation -- make 3.4 bits>double an error -- code walker and callbacks is broken? +- hashed generic method dispatch +- fix this: + + [ 1 2 3 4 5 6 7 8 9 10 10 10 10 10 10 10 10 10 10 11 11 11 113 ] . +[ 1 2 3 4 5 6 7 8 9 10 10 10 10 10 10 10 10 10 10 11 11 11 113 +] + +- code walker & exceptions -- test and debug problems +- break: perhaps use current stdio to run break listener +- httpd search tools +- remaining HTML issues need fixing diff --git a/boot.image.amd64 b/boot.image.amd64 index 34932e70f4..575c825d9f 100644 Binary files a/boot.image.amd64 and b/boot.image.amd64 differ diff --git a/boot.image.pentium4 b/boot.image.pentium4 index 8b7bb2d9cd..097495da0b 100644 Binary files a/boot.image.pentium4 and b/boot.image.pentium4 differ diff --git a/boot.image.ppc b/boot.image.ppc index 2608f0bed6..dab4b482ca 100644 Binary files a/boot.image.ppc and b/boot.image.ppc differ diff --git a/boot.image.x86 b/boot.image.x86 index 60c9bce931..135b12b90a 100644 Binary files a/boot.image.x86 and b/boot.image.x86 differ diff --git a/contrib/README.txt b/contrib/README.txt index f946b02a65..29c8d34db0 100644 --- a/contrib/README.txt +++ b/contrib/README.txt @@ -1,43 +1,32 @@ This directory contains Factor code that is not part of the core library, but is useful enough to ship with the Factor distribution. -- contrib/aim/ -- AOL Instant Messenger client library (Doug Coleman) +Modules can be loaded from the listener: -- contrib/algebra/ -- infix math syntax (Daniel Ehrenberg) + "modulename" require -- contrib/cairo/ -- cairo bindings (Sampo Vuori) +Credits: -- contrib/concurrency/ -- Erlang/Termite-style concurrency (Chris Double) - -- contrib/cont-responder/ -- additional examples and tools for the - continuation-based web framework (Chris Double) - -- contrib/crypto/ -- MD5 and SHA1 cryptographic hashes (Doug Coleman) - -- contrib/factory/ -- X11 window manager (Eduardo Cavazos) - -- contrib/httpd/ -- HTTP server and client (Slava Pestov, Chris Double) - -- contrib/math/ -- extended math library (Doug Coleman) - -- contrib/parser-combinators/ -- Lazy lists and Haskell-style parser - combinators (Chris Double) - -- contrib/postgresql/ -- PostgreSQL binding (Doug Coleman) - -- contrib/random-tester/ -- Random compiler tester (Doug Coleman) - -- contrib/space-invaders/ -- Intel 8080-based Space Invaders arcade - machine emulator (Chris Double) - -- contrib/sqlite/ -- SQLite binding (Chris Double) - -- contrib/x11 -- X Window System client library (Eduardo Cavazos) - -- contrib/coroutines.factor -- coroutines (Chris Double) - -- contrib/dlists.factor -- double-linked-lists (Mackenzie Straight) - -- contrib/splay-trees.factor -- Splay trees (Mackenzie Straight) - -- contrib/xml.factor -- XML parser and writer (Daniel Ehrenberg) +- automata -- Graphics demo for the UI (Eduardo Cavazos) +- boids -- Graphics demo for the UI (Eduardo Cavazos) +- cairo -- cairo bindings (Sampo Vuori) +- calendar -- timestamp/calendar with timezones (Doug Coleman) +- concurrency -- Erlang/Termite-style concurrency (Chris Double) +- coroutines -- coroutines (Chris Double) +- crypto -- Various cryptographic algorithms (Doug Coleman) +- dlists -- double-linked-lists (Mackenzie Straight) +- factory -- X11 window manager (Eduardo Cavazos) +- gap-buffer -- Efficient text editor buffer (Alex Chapman) +- hexdump -- Hexdump routine (Doug Coleman) +- httpd -- Web framework (HTTP server, client, XML parser, HTML generation...) (Slava Pestov, Chris Double, Daniel Ehrenberg) +- lazy-lists -- Lazy evaluation lists (Chris Double, Matthew Willis) +- math -- extended math library (Doug Coleman, Slava Pestov) +- parser-combinators -- Haskell-style parser combinators (Chris Double) +- postgresql -- PostgreSQL binding (Doug Coleman) +- process -- Run external programs (Slava Pestov) +- random-tester -- Random compiler tester (Doug Coleman) +- slate -- Graphics canvas for the UI (Eduardo Cavazos) +- space-invaders -- Intel 8080-based Space Invaders arcade machine emulator (Chris Double) +- splay-trees -- Splay trees (Mackenzie Straight) +- sqlite -- SQLite binding (Chris Double) +- x11 -- X Window System client library (Eduardo Cavazos) diff --git a/contrib/aim/aim.factor b/contrib/aim/aim.factor deleted file mode 100644 index 53c6df656a..0000000000 --- a/contrib/aim/aim.factor +++ /dev/null @@ -1,1082 +0,0 @@ -! All Talk - -IN: aim-internals -USING: kernel sequences lists prettyprint strings namespaces math threads vectors errors parser interpreter test io crypto words hashtables inspector aim-internals generic queues arrays ; - -SYMBOL: username -SYMBOL: password -SYMBOL: conn -SYMBOL: seq-num -SYMBOL: stage-num -SYMBOL: login-key -SYMBOL: aim-chat-ip -SYMBOL: aim-chat-port -SYMBOL: auth-code -! snac -SYMBOL: family -SYMBOL: opcode -SYMBOL: snac-flags -SYMBOL: snac-request-id -SYMBOL: extra-data - -SYMBOL: name -SYMBOL: message -SYMBOL: encoding -SYMBOL: warning -SYMBOL: buddy-hash-name -SYMBOL: buddy-hash-id -SYMBOL: group-hash-name -SYMBOL: group-hash-id -SYMBOL: banned-hash-name -SYMBOL: banned-hash-id -SYMBOL: channel -SYMBOL: icbm-cookie -SYMBOL: message-type -SYMBOL: my-ip -SYMBOL: blue-ip -SYMBOL: file-transfer-cancelled -SYMBOL: direct-connect-cancelled -SYMBOL: remote-internal-ip -SYMBOL: remote-external-ip -SYMBOL: ssi-length -SYMBOL: modify-queue - -TUPLE: group name id ; -TUPLE: buddy name id gid capabilities buddy-icon online ; - -: aim-login-server "login.oscar.aol.com" ; inline -: icq-login-server "login.icq.com" ; inline -: login-port 5190 ; inline -: client-md5-string "AOL Instant Messenger (SM)" ; inline -: client-id-string "AOL Instant Messenger, version 5.5 3595/WIN32" ; inline -: client-id-num HEX: 109 ; inline -: client-major-ver 5 ; inline -: client-minor-ver 5 ; inline -: client-lesser-ver 0 ; inline -: client-build-num 3595 ; inline -: client-distro-num 260 ; inline -: client-language "en" ; inline -: client-country "us" ; inline -: client-ssi-flag 1 ; inline -: client-charset "text/aolrtf; charset=\"us-ascii\"" ; inline -: file-transfer-url "http://dynamic.aol.com/cgi/redir?http://www.aol.com/aim/filetransfer/antivirus.html" ; inline -: aim-file-server-port 5190 ; inline - -! Family names from ethereal -: family-names -H{ - { 1 "Generic" } { 2 "Location" } { 3 "Buddylist" } - { 4 "Messaging" } { 6 "Invitation" } { 8 "Popup" } - { 9 "BOS" } { 10 "User Lookup" } { 11 "Stats" } - { 12 "Translate" } { 19 "SSI" } { 21 "ICQ" } - { 34 "Unknown Family" } } ; - -: sanitize-name ( name -- name ) HEX: 20 swap remove >lower ; - -: hash-swap ( hash -- hash ) - hash>alist [ first2 swap 2array ] map alist>hash ; - -: 2list>hash ( keys values -- hash ) - H{ } clone -rot [ swap pick set-hash ] 2each ; - -: capability-names -H{ - { "Unknown1" HEX: 094601054c7f11d18222444553540000 } - { "Games" HEX: 0946134a4c7f11d18222444553540000 } - { "Send Buddy List" HEX: 0946134b4c7f11d18222444553540000 } - { "Chat" HEX: 748f2420628711d18222444553540000 } - { "AIM/ICQ Interoperability" HEX: 0946134d4c7f11d18222444553540000 } - { "Voice Chat" HEX: 094613414c7f11d18222444553540000 } - { "iChat" HEX: 094600004c7f11d18222444553540000 } - { "Send File" HEX: 094613434c7f11d18222444553540000 } - { "Unknown2" HEX: 094601ff4c7f11d18222444553540000 } - { "Live Video" HEX: 094601014c7f11d18222444553540000 } - { "Direct Instant Messaging" HEX: 094613454c7f11d18222444553540000 } - { "Unknown3" HEX: 094601034c7f11d18222444553540000 } - { "Buddy Icon" HEX: 094613464c7f11d18222444553540000 } - { "Add-Ins" HEX: 094613474c7f11d18222444553540000 } -} ; - -SYMBOL: capability-names-hash-swapped -: capability-values capability-names-hash-swapped get ; - -: capability-abbrevs -H{ - { CHAR: A "Voice" } - { CHAR: C "Send File" } - { CHAR: E "AIM Direct IM" } - { CHAR: F "Buddy Icon" } - { CHAR: G "Add-Ins" } - { CHAR: H "Get File" } - { CHAR: K "Send Buddy List" } -} ; - -: aim-errors -H{ - { 1 "Invalid SNAC header." } - { 2 "Server rate limit exceeded." } - { 3 "Client rate limit exceeded." } - { 4 "Recipient is not logged in." } - { 5 "Requested service unavailable." } - { 6 "Requested service not defined." } - { 7 "You sent obsolete SNAC." } - { 8 "Not supported by server." } - { 9 "Not supported by client." } - { 10 "Refused by client." } - { 11 "Reply too big." } - { 12 "Responses lost." } - { 13 "Request denied." } - { 14 "Incorrect SNAC format." } - { 15 "Insufficient rights." } - { 16 "In local permit/deny. (recipient blocked)" } - { 17 "Sender too evil." } - { 18 "Receiver too evil." } - { 19 "User temporarily unavailable." } - { 20 "No match." } - { 22 "List overflow." } - { 23 "Request ambiguous." } - { 24 "Server queue full." } - { 25 "Not while on AOL." } -} ; - - -: initialize-aim ( username password -- ) - password set username set - H{ } clone buddy-hash-name set - H{ } clone buddy-hash-id set - H{ } clone group-hash-name set - H{ } clone group-hash-id set - H{ } clone banned-hash-name set - H{ } clone banned-hash-id set - modify-queue set - HEX: 7fff random-int seq-num set - capability-names hash-swap capability-names-hash-swapped set - 1 stage-num set ; - -: prepend-aim-protocol ( data -- ) - [ - HEX: 2a >byte - stage-num get >byte - seq-num get >short - ] "" make - seq-num get dup HEX: 7fff >= [ 0 ] [ 1+ ] if seq-num set - swap dup >r length (>short) r> append append ; - -: (send-aim) ( str -- ) - "Sending: " print - dup hexdump - conn get [ stream-write ] keep stream-flush ; - -: send-aim ( data -- ) - make-packet prepend-aim-protocol (send-aim) terpri ; - -: with-aim ( quot -- ) - conn get swap with-unscoped-stream ; - -: read-aim ( -- bc ) - [ - [ - head-byte drop - head-byte drop - head-short drop - head-short head-string - ] with-aim - ] catch [ "Socket error" print throw ] when - "Received: " write dup hexdump ; - -: make-snac ( fam subtype flags req-id -- ) - 4vector { (>short) (>short) (>short) (>int) } papply % ; - -: parse-snac ( stream -- ) - head-short family set - head-short opcode set - head-short snac-flags set - head-int snac-request-id set - snac-flags get HEX: 8000 bitand 0 > [ - head-short head-string extra-data set - extra-data get "Extra data: " writeln hexdump - ] when ; - -: (unhandled-opcode) ( str -- ) - ! "Family: " write family get >hex write - ! ", opcode: " write opcode get >hex writeln - head-contents hexdump ; - -: unhandled-opcode ( -- ) - "Unhandled opcode!" writeln (unhandled-opcode) ; - -: incomplete-opcode ( -- ) - "Incomplete handling: " write (unhandled-opcode) ; - -: unhandled-family-opcode ( -- ) - "Unhandled family: " write family get unparse writeln - unhandled-opcode ; - -GENERIC: get-buddy -M: integer get-buddy ( bid -- ) - buddy-hash-id get hash ; -M: object get-buddy ( name -- ) - sanitize-name buddy-hash-name get hash ; - -GENERIC: get-group -M: integer get-group ( bid -- ) - group-hash-id get hash ; -M: object get-group ( name -- ) - sanitize-name group-hash-name get hash ; - -GENERIC: get-banned -M: integer get-banned ( bid -- ) - banned-hash-id get hash ; -M: object get-banned ( name -- ) - sanitize-name banned-hash-name get hash ; - -: buddy-name? ( name -- bool ) - get-buddy >boolean ; - -: group-name? ( name -- bool ) - get-group >boolean ; - -: banned-name? ( name -- bool ) - get-banned >boolean ; - -: random-buddy-id ( -- id ) - HEX: fff0 random-int 1+ dup get-buddy [ drop random-buddy-id ] when ; - -: random-group-id ( -- id ) - HEX: fff0 random-int 1+ dup get-group [ drop random-group-id ] when ; - - -! Events -: buddy-signon ( name -- ) - get-buddy dup [ t swap set-buddy-online ] [ drop "Can't find buddy in buddylist: " write name get writeln ] if ; - -: buddy-signoff ( name -- ) - get-buddy dup [ f swap set-buddy-online ] [ drop "Can't find buddy in buddylist: " write name get writeln ] if ; - -: print-buddylist - ! group-list get [ [ buddy-name , ] each ] { } make - ! [ buddylist get hash-keys string-sort [ , ] each ] { } make [ drop ] simple-outliner ; - ; - -: family-table ( -- hash ) H{ } ; - -: FAMILY: ( -- fam# ) - scan hex> swons dup car family-table hash dup [ - drop - ] [ - drop H{ } clone over car family-table set-hash - ] if ; parsing - -: OPCODE: ( fam# -- ) - car family-table hash word scan hex> rot set-hash f ; parsing - - -! Generic, Capabilities -: send-generic-capabilities - [ - 1 HEX: 17 0 HEX: 17 make-snac - [ 1 4 HEX: 13 3 2 1 3 1 4 1 6 1 8 1 9 1 HEX: a 1 HEX: b 1 ] - [ >short ] each - ] send-aim ; - -: (handle-supported-families) - unscoped-stream get empty? [ - head-short family-names hash . - (handle-supported-families) - ] unless ; - -! : unscoped-stream get empty? [ - ! head-short - ! [ - ! head-short - ! head-short head-string [ - ! cond - ! ] with-unscoped-stream - ! ] repeat - ! ] unless ; - -: handle-supported-families - "Families: " print - (handle-supported-families) - send-generic-capabilities - ; FAMILY: 1 OPCODE: 3 - -: send-requests ( -- ) - ! Self Info Request - [ 1 HEX: e 0 HEX: e make-snac ] send-aim - - ! Request Rights - [ HEX: 13 2 0 2 make-snac ] send-aim - - ! Request List - [ HEX: 13 4 0 HEX: 3efb0004 make-snac ] send-aim - - ! Location, Request Rights - [ 2 2 0 2 make-snac ] send-aim - - ! Buddylist Service, Rights Request - [ 3 2 0 2 make-snac ] send-aim - - ! Messaging, Request Parameter Info - [ 4 4 0 4 make-snac ] send-aim - - ! Privacy Management Service, Rights Query - [ 9 2 0 2 make-snac ] send-aim ; - -: handle-1-7 - [ - 1 8 0 8 make-snac - head-short dup [ - ! "Rate Classes: " write - head-short >short ! rate class id - head-int drop ! window size - head-int drop ! clear level - head-int drop ! alert level - head-int drop ! limit level - head-int drop ! disconnect level - head-int drop ! current level - head-int drop ! max level - head-int drop ! last time - head-byte drop ! current state - ] repeat - [ - head-short drop ( rate class id again ) - ! Pairs - head-short [ head-int drop ] repeat - ] repeat - ] send-aim ( BOS, Rights Query ) - send-requests ; FAMILY: 1 OPCODE: 7 - -: handle-capabilities - unscoped-stream get empty? [ - head-u128 capability-values hash dup [ "Unknown Capability" nip ] unless - writeln handle-capabilities - ] unless ; - - - -SYMBOL: saved-cond -: (process-tlv) ( -- ) - head-short dup warning set - head-short head-string [ - saved-cond get cond - ] with-unscoped-stream ; - -: process-tlv ( cond -- ) - saved-cond set - unscoped-stream get empty? [ - drop - ] [ - head-short drop - head-short [ (process-tlv) ] repeat - ] if ; - -: process-tlv-loop ( cond -- ) - saved-cond set - unscoped-stream get empty? [ - (process-tlv) - saved-cond get process-tlv-loop - ] unless ; - - -! for inside a loop -: (process-tlv-loop2) ( cond -- ) - head-byte - head-byte drop - head-short head-string [ - saved-cond get cond - ] with-unscoped-stream ; - -! useful inside a tlv handler -: process-tlv-loop2 ( cond -- ) - saved-cond set - unscoped-stream get empty? [ - (process-tlv-loop2) - saved-cond get process-tlv-loop2 - ] unless ; - -: (handle-online-info) - unscoped-stream get empty? [ - head-byte head-string name set - head-short drop - head-short - [ - head-short - head-short head-string [ - { - { [ dup 1 = ] [ drop head-short "Class: " write unparse writeln ] } - { [ dup 3 = ] [ drop head-int "Time went online: " write unparse writeln ] } - { [ dup 4 = ] [ drop head-short "Unknown4: " write unparse writeln ] } - { [ dup 5 = ] [ drop head-int "Time registered: " write unparse writeln ] } - { [ dup 10 = ] [ drop head-int int>ip "IP: " write writeln ] } - { [ dup 13 = ] [ drop handle-capabilities ] } - { [ dup 15 = ] [ drop head-int "Idle: " write unparse writeln ] } - { [ dup 20 = ] [ drop head-byte "Unknown20: " write unparse writeln ] } - ! { [ dup 29 = ] [ drop ] } - { [ dup 30 = ] [ drop head-int "Unknown30: " write unparse writeln ] } - { [ dup 34 = ] [ drop head-short "Unknown32: " write unparse writeln ] } - { [ t ] [ " Unhandled tlv 1h-fh: " write unparse writeln head-contents hexdump ] } - } cond - ] with-unscoped-stream - ] repeat (handle-online-info) - ] unless ; - -: handle-online-info - (handle-online-info) - ; FAMILY: 1 OPCODE: f - -! message of the day -: handle-1-13 - 7 [ head-short drop ] repeat - ! Generic, Rate Info Request - [ 1 6 0 6 make-snac ] send-aim ; FAMILY: 1 OPCODE: 13 - -! capabilities ack -: handle-1-18 - "Unhandled ack: " write head-contents writeln ; FAMILY: 1 OPCODE: 18 - -: handle-1-21 - ! AIM Email - ! [ 1 4 HEX: 02cc 4 make-snac HEX: 18 >short ] send-aim - - ! AIM Location - ! [ 2 HEX: b HEX: 446d HEX: b make-snac username get length >byte username get % ] send-aim - - ! head-short - ! [ - ! head-short - ! head-short head-string [ - ! { - ! ! { [ ] [ ] } - ! { [ t ] [ " Unhandled tlv 1h-21h: " write unparse writeln head-contents hexdump ] } - ! } cond - ! ] with-unscoped-stream - ! ] repeat - ; FAMILY: 1 OPCODE: 21 - - -: handle-2-1 - head-short aim-errors hash "Error: " write writeln - ; FAMILY: 2 OPCODE: 1 - - -: handle-29 - unscoped-stream get empty? [ - "(29)" print - head-short drop - head-byte drop - head-byte head-string drop - handle-29 - ] unless ; - -: handle-abbrev-capabilities - unscoped-stream get empty? [ - head-short .h - handle-abbrev-capabilities - ] unless ; - -: handle-buddy-status - head-byte head-string name set - { - { [ dup 1 = ] [ drop name get write head-short HEX: 20 bitand 1 > [ " is away." ] [ " is online." ] if writeln ] } - { [ dup 2 = ] [ drop "Member since: " write head-short unparse writeln ] } - { [ dup 3 = ] [ drop name get write " went online at " write head-int unparse writeln name get buddy-signon ] } - { [ dup 4 = ] [ drop name get write " has been idle for " write head-short unparse write " minutes." writeln ] } - { [ dup 6 = ] [ drop name get write ": (6): " write head-short unparse write " " write head-short unparse writeln ] } - { [ dup 13 = ] [ drop "Capabilities3:" print handle-capabilities ] } - { [ dup 14 = ] [ drop "Capabilities4:" print handle-capabilities ] } - { [ dup 15 = ] [ drop name get write " has been online for " write head-int unparse write " seconds." writeln ] } - { [ dup 25 = ] [ drop "Abbreviated capabilities: " write handle-abbrev-capabilities ] } - { [ dup 27 = ] [ drop "(27): " write 4 [ head-int unparse write " " write ] repeat terpri ] } - { [ dup 29 = ] [ drop handle-29 ] } - { [ t ] [ " Unhandled tlv 3h-bh: " write unparse writeln head-contents hexdump ] } - } process-tlv ; FAMILY: 3 OPCODE: b - -! : handle-4-5 - ! ; FAMILY: 4 OPCODE: 5 - -: handle-buddy-signoff ( -- ) - head-byte head-string name set - { - { [ dup 1 = ] [ drop name get write " signed off." writeln name get buddy-signoff ] } - { [ dup HEX: 1d = ] [ drop ] } - { [ t ] [ "Unhandled tlv 3h-ch: " write unparse writeln head-contents hexdump ] } - } process-tlv ; FAMILY: 3 OPCODE: c - -: parse-family-4h-header - extra-data get [ - head-short drop - head-short drop - head-short drop - ] with-unscoped-stream ; - - - -: handle-file-transfer-start-tlvs - unscoped-stream get empty? [ - head-short - head-short head-string [ - dup unparse write ": " write - { - { [ dup 2 = ] [ drop head-int int>ip dup my-ip set "my ip: " write write ] } - { [ dup 3 = ] [ drop head-int int>ip dup blue-ip set "blue.aol ip: " write write ] } - { [ dup 4 = ] [ drop head-int unparse write ] } - { [ dup 5 = ] [ drop head-short unparse write ] } - { [ dup 10 = ] [ drop head-short unparse write ] } - { [ dup 11 = ] [ drop head-short unparse . "Transfer cancelled" print file-transfer-cancelled on ] } - { [ dup 12 = ] [ drop head-contents message set "Message: " write message get writeln ] } - { [ dup 13 = ] [ drop head-contents encoding set ] } - { [ dup 14 = ] [ drop head-short unparse write ] } - { [ dup 15 = ] [ drop ( do nothing ) ] } - { [ dup 22 = ] [ drop head-int unparse write ] } - { [ dup 23 = ] [ drop head-short unparse write ] } - { [ dup 10001 = ] [ drop head-contents write ] } - { [ dup 10002 = ] [ drop head-contents write ] } - { [ t ] [ "Unhandled file transfer tlv: " write unparse writeln head-contents hexdump ] } - } cond terpri - ] with-unscoped-stream - handle-file-transfer-start-tlvs - ] unless ; - -: send-file-transfer-start - "STARTING FILE TRANSFER" print - [ - 4 6 0 HEX: 778f0006 make-snac - icbm-cookie get >longlong - 2 >short - name get length >byte - name get % - 5 >short - 56 >short - 0 >short - icbm-cookie get >longlong - "Send File" capability-names hash >u128 - 10 >short 2 >short 2 >short - 2 >short 4 >short 0 >int - 22 >short 4 >short HEX: ffffffff >int ! gateway? - 3 >short 4 >short 0 >int - ] send-aim ; - -: handle-chat-start-tlvs - unscoped-stream get empty? [ - head-short - head-short head-string [ - dup unparse write ": " write - { - { [ dup 10 = ] [ drop head-short unparse write ] } - { [ dup 12 = ] [ drop head-contents message set ] } - { [ dup 13 = ] [ drop head-contents encoding set ] } - { [ dup 14 = ] [ drop head-byte unparse write ] } - { [ dup 15 = ] [ drop ( do nothing ) ] } - { [ dup 10001 = ] [ drop head-contents hexdump ] } - { [ t ] [ "Unhandled chat transfer tlv: " write unparse writeln head-contents hexdump ] } - } cond terpri - ] with-unscoped-stream - handle-chat-start-tlvs - ] unless ; - -: handle-direct-start-tlvs - unscoped-stream get empty? [ - head-short - head-short head-string [ - dup unparse write ": " write - { - { [ dup 2 = ] [ drop head-int int>ip dup remote-internal-ip set "remote internal ip: " write write ] } - { [ dup 3 = ] [ drop head-int int>ip dup remote-external-ip set "remote external? ip: " write write ] } - { [ dup 4 = ] [ drop head-int int>ip dup my-ip set "my? ip: " write write ] } - { [ dup 5 = ] [ drop head-short unparse "port?" write write ] } - { [ dup 10 = ] [ drop head-short unparse write ] } - { [ dup 11 = ] [ drop head-short unparse write direct-connect-cancelled set ] } - { [ dup 15 = ] [ drop ( do nothing ) ] } - { [ dup 22 = ] [ drop head-int unparse write ] } - { [ dup 23 = ] [ drop head-short unparse "port?" write write ] } - { [ t ] [ "Unhandled direct transfer tlv: " write unparse writeln head-contents hexdump ] } - } cond terpri - ] with-unscoped-stream - handle-direct-start-tlvs - ] unless ; - -: send-direct-connect-start - ; - -: send-auth-file-transfer - [ - 0 >short - 1 >short - "Send File" capability-names hash >u128 - 0 >short - ] send-aim ; - -: connect-aim-file-transfer-server - "205.188.210.203" aim-file-server-port ; - - -: handle-file-transfer-start - head-short message-type set - head-longlong icbm-cookie set - head-u128 capability-values hash - { - { [ dup "Send File" = ] - [ . file-transfer-cancelled off - handle-file-transfer-start-tlvs - file-transfer-cancelled get [ send-file-transfer-start ] unless - ] } - { [ dup "Chat" = ] [ . handle-chat-start-tlvs - "Chat join message: " write message get writeln ] } - { [ dup "AIM Direct IM" = ] [ . handle-direct-start-tlvs - direct-connect-cancelled get [ send-direct-connect-start ] unless - ] } - { [ t ] [ "Unsupported capability in channel 2: " write writeln head-contents hexdump ] } - } cond ; - -: parse-message-text ( -- str ) - head-short drop head-short drop head-contents ; - -: handle-incoming-message ( -- ) - parse-family-4h-header - head-longlong drop - head-short channel set - head-byte head-string name set - { - { [ dup 1 = ] [ drop head-short drop ] } - { [ dup 2 = ] [ drop 15 head-string drop ] } - { [ dup 3 = ] [ drop ] } - { [ dup 15 = ] [ drop ] } - { [ dup 29 = ] [ drop ] } - { [ t ] [ "Unknown tlv: " write unparse writeln head-contents hexdump ] } - } process-tlv - { - { [ dup 2 = ] [ drop - { - { [ dup 1 = ] [ drop parse-message-text message set ] } - { [ dup 5 = ] [ drop ] } - { [ t ] [ "Unknown frag: " write unparse writeln unscoped-stream get contents hexdump ] } - } process-tlv-loop2 ] } - { [ dup 5 = ] [ drop handle-file-transfer-start ] } - { [ dup 11 = ] [ drop ] } - { [ t ] [ "Unhandled chunk: " write unparse writeln head-contents hexdump ] } - } process-tlv-loop - - channel get 1 = [ - "Incoming msg from " write name get write ": " write - "Warning: " write warning get 10 /f unparse write "%" writeln - "Message: " write message get writeln - ] when ; FAMILY: 4 OPCODE: 7 - -! : handle-4-12 - ! head-short 2 / [ head-short drop ] repeat - ! head-cstring drop - ! head-short drop - ! head-byte head-string - ! ; FAMILY: 4 OPCODE: 12 - -: handle-typing-message ( -- ) - parse-family-4h-header - head-longlong drop - head-short channel set - head-byte head-string write - head-short - { - { [ dup 0 = ] [ drop " has an empty textbox." writeln ] } - { [ dup 1 = ] [ drop " has entered text." writeln ] } - { [ dup 2 = ] [ drop " is typing..." writeln ] } - { [ t ] [ " does 4h.14h unknown: " write unparse writeln ] } - } cond ; FAMILY: 4 OPCODE: 14 - -! : handle-9-3 - ! ; FAMILY: 9 OPCODE: 3 - -: handle-b-2 - head-short "Send status report every: " write unparse write " hours" writeln - head-short "Unknown: " write unparse writeln - ; FAMILY: b OPCODE: 2 - -! : handle-19-3 - ! ; FAMILY: 13 OPCODE: 3 - -SYMBOL: gid ! group id -SYMBOL: bid ! buddy id -SYMBOL: type -: handle-19-6 - head-byte drop ! ssi version, probably 0 - head-short [ - head-short head-string name set name get . - head-short gid set gid get . - head-short bid set bid get . - head-short type set type get . ! type 0 is a buddy, 1 is a group - "TLV CHAIN DATA: " print - head-short head-string hexdump ! short short data - - type get - { - { [ dup 0 = ] [ drop name get bid get gid get V{ } clone f f - dup name get sanitize-name buddy-hash-name get set-hash bid get buddy-hash-id get set-hash ] } - { [ dup 1 = ] [ drop name get dup length 0 = [ drop ] [ gid get - dup name get sanitize-name group-hash-name get set-hash gid get group-hash-id get set-hash ] if ] } - { [ dup 3 = ] [ drop name get bid get gid get V{ } clone f f - dup name get sanitize-name banned-hash-name get set-hash bid get banned-hash-id get set-hash ] } - { [ t ] [ drop "Unknown 19-6 type" print ] } - } cond - ] repeat - head-short drop ! unknown or timestamp - head-short drop ! unknown or timestamp - - snac-flags get 0 = [ - ! SSI, Activate - [ HEX: 13 7 0 7 make-snac ] send-aim - ! Set User Info. Capabilities! - ! if you send this packet correctly you get capabilities - ! and others' capabilities turn into letters instead of u128s - [ - 2 4 0 4 make-snac - 5 >short - capability-values hash-keys length 16 * >short ! size - capability-values hash-keys [ >u128 ] each - 6 >short 6 >short 4 >short 2 >short 2 >short - ] send-aim - - ! Set ICBM Parameter - [ - 4 2 0 2 make-snac - 0 >int - HEX: b >short - HEX: 1f40 >short - HEX: 03e7 >short - HEX: 03e7 >short - 0 >int - ] send-aim - - ! Client Ready - [ - 1 2 0 2 make-snac - [ - HEX: 1 HEX: 4 HEX: 110 HEX: 8f1 - HEX: 13 HEX: 3 HEX: 110 HEX: 8f1 - HEX: 2 HEX: 1 HEX: 110 HEX: 8f1 - HEX: 3 HEX: 1 HEX: 110 HEX: 8f1 - HEX: 4 HEX: 4 HEX: 110 HEX: 8f1 - HEX: 6 HEX: 1 HEX: 110 HEX: 8f1 - HEX: 8 HEX: 1 HEX: 104 HEX: 8f1 - HEX: 9 HEX: 1 HEX: 110 HEX: 8f1 - HEX: a HEX: 1 HEX: 110 HEX: 8f1 - HEX: b HEX: 1 HEX: 110 HEX: 8f1 - ] [ >short ] each - ] send-aim - - ! Process - ] when ; FAMILY: 13 OPCODE: 6 - - -: parse-server ( ip:port -- ) - ":" split [ first ] keep second string>number aim-chat-port set aim-chat-ip set ; - -: handle-login-packet ( -- ) - unscoped-stream get empty? [ - head-short head-short swap - { - { [ dup 5 = ] [ drop head-string parse-server ] } - { [ dup 6 = ] [ drop head-string auth-code set ] } - { [ t ] [ drop head-string drop ] } - } cond - handle-login-packet - ] unless ; FAMILY: 17 OPCODE: 3 - -: password-md5 ( password -- md5 ) - login-key get - password get string>md5 append - client-md5-string append - string>md5 >string ; - -: respond-login-key-packet ( -- ) - [ - HEX: 17 HEX: 2 0 0 make-snac - 1 >short - username get length >short - username get % - - ! password hash chunk - HEX: 25 >short - HEX: 10 >short - password-md5 % - - HEX: 4c >short - HEX: 00 >short - HEX: 03 >short client-id-string length >short client-id-string % - HEX: 16 >short HEX: 02 >short client-id-num >short - HEX: 17 >short HEX: 02 >short client-major-ver >short - HEX: 18 >short HEX: 02 >short client-minor-ver >short - HEX: 19 >short HEX: 02 >short client-lesser-ver >short - HEX: 1a >short HEX: 02 >short client-build-num >short - HEX: 14 >short HEX: 04 >short client-distro-num >int - HEX: 0f >short client-language length >short client-language % - HEX: 0e >short client-country length >short client-country % - HEX: 4a >short HEX: 01 >short client-ssi-flag >byte - ] send-aim ; - -: handle-login-key-packet ( -- ) - head-short head-string login-key set - respond-login-key-packet ; FAMILY: 17 OPCODE: 7 - -: handle-packet ( packet -- ) - - [ - parse-snac - "Family: " write family get >hex write - ", Opcode: " write opcode get >hex writeln - family get family-table hash dup [ - opcode get swap hash dup [ - execute - ] [ - unhandled-opcode drop - ] if - ] [ - unhandled-family-opcode - drop - ] if - unscoped-stream get empty? [ incomplete-opcode ] unless - ] with-unscoped-stream ; - -! Login -: send-first-login ( -- ) - [ 1 >int ] send-aim ; - -: send-first-request-auth ( -- ) - 2 stage-num set - [ - HEX: 17 HEX: 6 0 0 make-snac - 1 >short - username get length >short - username get % - HEX: 4b >short - HEX: 00 >short - HEX: 5a >short - HEX: 00 >short - ] send-aim ; - -! AIM Chat Server -: send-second-login - [ - 1 >int - 6 >short - auth-code get length >short - auth-code get % - ] send-aim ; - -: first-server - ! first server - 1 stage-num set - aim-login-server login-port conn set - - send-first-login read-aim drop - - ! normal transmission stage - send-first-request-auth read-aim handle-packet - read-aim handle-packet - read-aim drop ! handle-packet - conn get stream-close ; - -: second-server - aim-chat-ip get aim-chat-port get conn set - 1 stage-num set - HEX: 7fff random-int seq-num set - send-second-login read-aim drop - 2 stage-num set ; - -: handle-loop ( -- ) - read-aim handle-packet terpri handle-loop ; - -: connect-aim ( -- ) - first-server - aim-chat-ip get - [ "No aim server received (too many logins, try again later)" throw ] unless - second-server [ handle-loop ] in-thread ; - -IN: aim - -! Commands -: send-im ( name message -- ) - message set - name set - [ - 4 6 0 HEX: 7c3a0006 make-snac - "1973973" >cstring - 1 >short - name get length >byte - name get % - 2 >short - - [ - 5 >byte 1 >byte 3 >short 1 >byte 1 >byte 2 >byte - HEX: 101 >short - message get length 4 + >short - 0 >short - HEX: ffff >short - message get % - ] make-packet - dup length >short % - 3 >short 0 >short 6 >short 0 >short - ] send-aim ; - -: query-info ( name -- ) - name set - [ - 2 HEX: 15 0 HEX: 29cb0015 make-snac - 1 >int - name get length >byte - name get % - ] send-aim ; - -: query-away ( name -- ) - name set - [ - 2 HEX: 15 0 HEX: 29cb0015 make-snac - 2 >int - name get length >byte - name get % - ] send-aim ; - -: set-away ( message -- ) - message set - [ - 2 4 0 4 make-snac - 3 >short - client-charset length >short - client-charset % - 4 >short - message get length >short - message get % - ] send-aim ; - -: return-from-away ( -- ) - [ - 2 4 0 4 make-snac - 4 >short - 0 >short - ] send-aim ; - -: set-info ( message -- ) - message set - ! [ 2 9 0 HEX: 63e40000 ] send-aim - [ - 2 4 0 4 make-snac - 1 >short - client-charset length >short - client-charset % - 2 >short - message get length >short - message get % - ] send-aim ; - -: buddylist-edit-start - [ HEX: 13 HEX: 11 0 HEX: 11 make-snac ] send-aim ; - -: buddylist-edit-stop - [ HEX: 13 HEX: 12 0 HEX: 12 make-snac ] send-aim ; - - -! add, delete groups, move buddies from group to group -! parse buddy list - -: add-group ( name -- ) - dup name set modify-queue get enque - buddylist-edit-start - [ - HEX: 13 8 0 HEX: 4fb20008 make-snac - name get length >short - name get % - random-group-id >short - 0 >short ! buddy id - 1 >short ! buddy type - 0 >short ! tlv len - ] send-aim ; - -: delete-group ( name -- ) - dup name set modify-queue get enque - buddylist-edit-start - [ - HEX: 13 HEX: a 0 HEX: 5086000a make-snac - name get length >short - name get % - name get get-group group-id >short - 0 >short - 1 >short - 0 >short - ] send-aim ; - -! TODO: make sure buddy doesnt already exist, makd sure group exists -: add-buddy ( name group -- ) - group set - dup name set modify-queue get enque - buddylist-edit-start - [ - HEX: 13 9 0 HEX: 72470009 make-snac - 0 >short - 0 >short - 0 >short - 1 >short - 6 >short - HEX: c8 >short - 2 >short - HEX: 6dc5 >short - ] send-aim - - [ - HEX: 13 8 0 HEX: 5b2f0008 make-snac - name get length >short - name get % - group get get-group group-id >short - random-buddy-id >short - 0 >short ! buddy type - 0 >short ! tlv len - ] send-aim ; - -: delete-buddy ( name -- ) - dup name set modify-queue get enque - buddylist-edit-start - [ - HEX: 13 HEX: a 0 HEX: 5086000a make-snac - name get length >short - name get % - name get get-buddy dup buddy-gid >short - buddy-id >short - 0 >short - 0 >short - ] send-aim ; - -: modify-buddylist ( name -- ) - ! dup buddy-name? [ dup name set dup buddy-id bid set buddy-gid gid set ] when - ! dup group-name? [ dup name set dup group-id gid set 0 bid set ] when - ! dup banned-name? [ dup name set dup buddy-id bid set buddy-gid gid set ] when - ! [ - ! HEX: 13 9 0 HEX: 6e190009 make-snac - ! name get dup length >short % - ! gid get >short - ! 0 >short - ! 1 >short ! group type = 1 - - ! "members of this group" tlv - ! 8 >short - ! HEX: c8 >short - ! 4 >short - ! HEX: 4e833ea8 >int - ! ] send-aim ; - drop ; - -IN: aim-internals -: buddylist-error - ; FAMILY: 13 OPCODE: b - -: buddylist-ack - ! modify-queue get deque modify-buddylist - buddylist-edit-stop ; FAMILY: 13 OPCODE: d - -IN: aim - -: run ( username password -- ) - initialize-aim connect-aim ; - ! [ initialize-aim connect-aim ] with-scope ; - -! my aim test account. you can use it. -: run-test-account - "FactorTest" "factoraim" run ; - diff --git a/contrib/aim/load.factor b/contrib/aim/load.factor deleted file mode 100644 index a6ab7a2a8f..0000000000 --- a/contrib/aim/load.factor +++ /dev/null @@ -1,9 +0,0 @@ -IN: scratchpad -USING: kernel parser sequences words compiler ; - -"/contrib/crypto/load.factor" run-resource - -{ - "net-bytes" - "aim" -} [ "/contrib/aim/" swap ".factor" append3 run-resource ] each diff --git a/contrib/aim/net-bytes.factor b/contrib/aim/net-bytes.factor deleted file mode 100644 index 5efbfa65c8..0000000000 --- a/contrib/aim/net-bytes.factor +++ /dev/null @@ -1,189 +0,0 @@ -IN: aim-internals -USING: kernel sequences lists prettyprint strings namespaces math threads vectors errors parser interpreter test io crypto arrays ; - -SYMBOL: big-endian t big-endian set -SYMBOL: unscoped-stream -SYMBOL: unscoped-stack - -! Examples: -! 1 2 3 4 4 >nvector . -! { 1 2 3 4 } - -! { 1 2 3 4 } { >byte >short >int >long } papply . -! "\u0001\0\u0002\0\0\0\u0003\0\0\0\0\0\0\0\u0004" - -! [ 1 >short 6 >long ] make-packet . -! "\0\u0001\0\0\0\0\0\0\0\u0006" - -: int>ip ( n -- str ) - [ HEX: ff000000 over bitand -24 shift unparse % CHAR: . , - HEX: 00ff0000 over bitand -16 shift unparse % CHAR: . , - HEX: 0000ff00 over bitand -8 shift unparse % CHAR: . , - HEX: 000000ff bitand unparse % ] "" make ; - - -! doesn't compile -! : >nvector ( elems n -- ) - ! { } clone swap [ drop swap add ] each reverse ; - -: 4vector ( elems -- ) - V{ } clone 4 [ drop swap add ] each reverse ; - -! TODO: make this work for types other than "" -: papply ( seq seq -- seq ) - [ [ 2array >list call % ] 2each ] "" make ; - -: writeln ( string -- ) - write terpri ; - -! NEEDS REFACTORING, GOSH! -! Hexdump -: (print-offset) ( lineno -- ) - 16 * >hex 8 CHAR: 0 pad-left write "h: " write ; - -: (print-hex-digit) ( digit -- ) - >hex 2 CHAR: 0 pad-left write ; - -: (print-hex-line) ( lineno string -- ) - over (print-offset) - dup length dup 16 = - [ [ 2dup swap nth (print-hex-digit) " " write ] repeat ] ! full line - [ ! partial line - [ 2dup swap nth (print-hex-digit) " " write ] repeat - dup length 16 swap - [ " " write ] repeat - ] if - dup length - [ 2dup swap nth dup printable? [ write1 ] [ "." write drop ] if ] repeat - terpri drop ; - -: (num-full-lines) ( bytes -- ) - length 16 / floor ; - -: (get-slice) ( lineno bytes -- ) - >r dup 16 * dup 16 + r> ; - -: (get-last-slice) ( bytes -- ) - dup length dup 16 mod - over length rot ; - -: (print-bytes) ( bytes -- ) - dup (num-full-lines) [ over (get-slice) (print-hex-line) ] repeat - dup (num-full-lines) over (get-last-slice) dup empty? [ 3drop ] [ (print-hex-line) 2drop ] if ; - -: (print-length) ( len -- ) - [ - "Length: " % - dup unparse % - ", " % - >hex % - "h\n" % - ] "" make write ; - -: hexdump ( str -- ) - dup length (print-length) (print-bytes) ; - - - -: save-current-scope - unscoped-stack get [ V{ } clone unscoped-stack set ] unless - swap dup unscoped-stream set unscoped-stack get push ; - -: set-previous-scope - unscoped-stack get dup length 1 > [ - [ pop ] keep nip peek unscoped-stream set ] [ - pop drop - ] if ; - -: with-unscoped-stream ( stream quot -- ) - save-current-scope catch set-previous-scope - [ dup [ unscoped-stream get stream-close ] when rethrow ] when ; - -: close-unscoped-stream ( -- ) - unscoped-stream get stream-close ; - -: >endian ( obj n -- str ) - big-endian get [ >be ] [ >le ] if ; - -: endian> ( obj n -- str ) - big-endian get [ be> ] [ le> ] if ; - -: (>byte) ( byte -- str ) - unit >string ; - -: (>short) ( short -- str ) - 2 >endian ; - -: (>int) ( int -- str ) - 4 >endian ; - -: (>longlong) ( longlong -- str ) - 8 >endian ; - -: (>u128) ( u128 -- str ) - 16 >endian ; - -: (>cstring) ( str -- str ) - "\0" append ; - -: >byte ( byte -- ) - (>byte) % ; - -: >short ( short -- ) - (>short) % ; - -: >int ( int -- ) - (>int) % ; - -: >longlong ( longlong -- ) - (>longlong) % ; - -: >u128 ( u128 -- ) - (>u128) % ; - -: >cstring ( str -- ) - (>cstring) % ; - - -! doesn't compile -! : make-packet ( quot -- ) - ! depth >r call depth r> - [ drop append ] each ; -: make-packet - "" make ; - -: (head-short) ( str -- short ) - 2 swap head endian> ; -: (head-int) ( str -- int ) - 4 swap head endian> ; -: (head-longlong) ( str -- longlong ) - 8 swap head endian> ; -: (head-u128) ( str -- u128 ) - 16 swap head endian> ; - -! 8 bits -: head-byte ( -- byte ) - 1 unscoped-stream get stream-read first ; - -! 16 bits -: head-short ( -- short ) - 2 unscoped-stream get stream-read (head-short) ; - -! 32 bits -: head-int ( -- int ) - 4 unscoped-stream get stream-read (head-int) ; - -! 64 bits -: head-longlong ( -- longlong ) - 8 unscoped-stream get stream-read (head-longlong) ; - -! 128 bits -: head-u128 ( -- u128 ) - 16 unscoped-stream get stream-read (head-u128) ; - -: head-string ( n -- str ) - unscoped-stream get stream-read >string ; - -! : head-cstring ( -- str ) - ! head-byte ] - -: head-contents ( -- str ) - unscoped-stream get contents ; - diff --git a/contrib/all.factor b/contrib/all.factor new file mode 100644 index 0000000000..e8037bf4de --- /dev/null +++ b/contrib/all.factor @@ -0,0 +1,10 @@ +USING: kernel modules words ; + +REQUIRES: automata boids cairo calendar concurrency coroutines +crypto dlists embedded gap-buffer hexdump httpd math postgresql process +random-tester slate splay-trees sqlite topology units vars ; + +"x11" vocab [ + "factory" require + "x11" require +] when diff --git a/contrib/automata.factor b/contrib/automata.factor new file mode 100644 index 0000000000..60d0754a45 --- /dev/null +++ b/contrib/automata.factor @@ -0,0 +1,188 @@ +! Copyright (C) 2006 Eduardo Cavazos. + +! To run: +! USE: automata +! automata-window + +REQUIRES: math slate vars ; + +USING: parser kernel hashtables namespaces sequences math io +math-contrib threads strings arrays prettyprint +gadgets gadgets-editors gadgets-frames gadgets-buttons gadgets-grids +vars slate ; + +IN: automata + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +! set-rule +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +: char>digit ( c -- i ) 48 - ; + +: string>digits ( s -- seq ) >array [ char>digit ] map ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +SYMBOL: rule SYMBOL: rule-number + +: init-rule ( -- ) 8 rule set ; + +: rule-keys ( -- { ... } ) +{ { 1 1 1 } + { 1 1 0 } + { 1 0 1 } + { 1 0 0 } + { 0 1 1 } + { 0 1 0 } + { 0 0 1 } + { 0 0 0 } } ; + +: rule-values ( n -- seq ) >bin 8 CHAR: 0 pad-left string>digits ; + +: set-rule ( n -- ) +dup rule-number set +rule-values rule-keys [ rule get set-hash ] 2each ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +! step-capped-line +! step-wrapped-line +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +: 3nth ( n seq -- slice ) >r dup 3 + r> ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +: map3-i ( seq -- i ) length 2 - ; + +: map3-quot ( quot -- quot ) [ swap 3nth ] swap append ; + +: map3 ( seq quot -- seq ) over map3-i swap map3-quot map-with ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +: last ( seq -- elt ) dup length 1- swap nth ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +: pattern>state ( { a b c } -- state ) rule get hash ; + +: cap-line ( line -- 0-line-0 ) { 0 } swap append { 0 } append ; + +: wrap-line ( a-line-z -- za-line-za ) +dup last 1array swap dup first 1array append append ; + +: step-line ( line -- new-line ) [ >array pattern>state ] map3 ; + +: step-capped-line ( line -- new-line ) cap-line step-line ; + +: step-wrapped-line ( line -- new-line ) wrap-line step-line ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +! Display the rule +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +: random-line ( -- line ) window-width [ drop 2 random-int ] map ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +: center-i ( -- i ) window-width dup 2 / >fixnum ; + +: center-line ( -- line ) center-i window-width [ = [ 1 ] [ 0 ] if ] map-with ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +! show-line +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +: show-point ( { x y } p -- ) 1 = [ draw-point ] [ drop ] if ; + +: (show-line) ( { x y } line -- ) [ dupd show-point { 1 0 } v+ ] each drop ; + +: show-line ( y line -- ) 0 rot 2array swap (show-line) yield ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +! run-rule +! start-random +! start-center +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +VAR: last-line + +: estimate-capacity ( -- ) window-width window-height * 2 * capacity set ; + +: check-capacity ( -- ) +"capacity: " write capacity get number>string write terpri +"dlist length: " write dlist get length number>string write terpri ; + +: start-slate ( -- ) +estimate-capacity reset-slate +white set-clear-color black set-color clear-window ; + +: finish-slate ( -- ) check-capacity flush-dlist flush-slate ; + +: run-line ( line y -- line ) swap tuck show-line step-capped-line ; + +: run-lines ( -- ) last-line> window-height [ run-line ] each >last-line ; + +: run-rule ( -- ) start-slate run-lines finish-slate ; + +: start-random ( -- ) random-line >last-line run-rule ; + +: start-center ( -- ) center-line >last-line run-rule ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +: random-item ( seq -- item ) dup length random-int swap nth ; + +: interesting ( -- seq ) +{ 18 22 26 30 41 45 54 60 73 75 82 86 89 90 97 101 102 105 106 107 109 + 110 120 121 122 124 126 129 137 146 147 149 150 151 153 154 161 165 } ; + + +: mild ( -- seq ) +{ 6 9 11 57 62 74 118 } ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +! : automata ( -- ) +! dup self set "Cellular Automata" open-titled-window +! init-rule interesting random-item set-rule 1000 sleep start-random ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +! automata-window +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +: bind-button ( ns button -- ) +tuck button-quot \ bind 3array >quotation swap set-button-quot ; + +VARS: ns editor frame ; + +: init-slate ( -- ) t over set-gadget-clipped? self set ; + +: init-editor ( -- ) "" >editor ; + +: set-editor-rule ( n -- ) number>string editor> set-editor-text ; + +: open-rule ( -- ) editor> editor-text string>number set-rule start-center ; + +: automata-window ( -- ) + >frame +[ ] make-hash >ns +ns> [ init-rule init-slate init-editor ] bind +ns> [ editor> ] bind 1array +ns> +{ { "Open" [ open-rule ] } + { "Center" [ start-center ] } + { "Random" [ start-random ] } + { "Continue" [ run-rule ] } } +[ first2 tuck bind-button ] +map-with append make-pile 1 over set-pack-fill +frame> @left grid-add +ns> [ self get ] bind +frame> @center grid-add +frame> "Cellular Automata" open-titled-window +1000 sleep +ns> [ interesting random-item set-editor-rule open-rule ] bind ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +PROVIDE: automata ; \ No newline at end of file diff --git a/contrib/boids.factor b/contrib/boids.factor new file mode 100644 index 0000000000..b4c827617a --- /dev/null +++ b/contrib/boids.factor @@ -0,0 +1,423 @@ +! Eduardo Cavazos - wayo.cavazos@gmail.com + +! To run the demo do: +! USE: boids +! boids-window +! +! There are currently a few bugs. To work around them and to get better +! results, increase the size of the window (larger than 400x400 is +! good). Then press the "Reset" button to start the demo over. + +REQUIRES: math slate vars ; + +USING: generic threads namespaces math kernel sequences arrays gadgets + math-contrib slate vars ; + +IN: boids + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +SYMBOL: separation-radius +SYMBOL: alignment-radius +SYMBOL: cohesion-radius + +SYMBOL: separation-view-angle +SYMBOL: alignment-view-angle +SYMBOL: cohesion-view-angle + +SYMBOL: separation-weight +SYMBOL: alignment-weight +SYMBOL: cohesion-weight + +: init-variables ( -- ) +25 separation-radius set +50 alignment-radius set +75 cohesion-radius set + +180 separation-view-angle set +180 alignment-view-angle set +180 cohesion-view-angle set + +1.0 separation-weight set +1.0 alignment-weight set +1.0 cohesion-weight set ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +SYMBOL: world-size + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +TUPLE: boid pos vel ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +VAR: time-slice + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +! random-boid and random-boids +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +: random-range ( a b -- n ) 1 + dupd swap - random-int + ; + +: random-pos ( -- pos ) world-size get [ random-int ] map ; + +: random-vel ( -- vel ) 2 >array [ drop -10 10 random-range ] map ; + +: random-boid ( -- boid ) random-pos random-vel ; + +: random-boids ( n -- boids ) [ drop random-boid ] map ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +SYMBOL: boids + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +! draw-boid +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +: boid-point-a ( boid -- a ) boid-pos ; + +: boid-point-b ( boid -- b ) dup boid-pos swap boid-vel normalize 20 v*n v+ ; + +: boid-points ( boid -- point-a point-b ) dup boid-point-a swap boid-point-b ; + +: draw-boid ( boid -- ) boid-points draw-line ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +: distance ( boid boid -- n ) boid-pos swap boid-pos v- norm ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +: constrain ( n a b -- n ) rot min max ; + +: angle-between ( vec vec -- angle ) +2dup v. -rot norm swap norm * / -1 1 constrain acos rad>deg ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +: relative-position ( self other -- v ) boid-pos swap boid-pos v- ; + +: relative-angle ( self other -- angle ) +over boid-vel -rot relative-position angle-between ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +: vsum ( vector-of-vectors --- vec ) { 0 0 } [ v+ ] reduce ; + +: vaverage ( seq-of-vectors -- seq ) dup vsum swap length v/n ; + +: average-position ( boids -- pos ) [ boid-pos ] map vaverage ; + +: average-velocity ( boids -- vel ) [ boid-vel ] map vaverage ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +: subset-with ( obj seq quot -- seq ) [ dupd ] swap append subset ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +: within-radius? ( self other radius -- ? ) >r distance r> <= ; + +: within-view-angle? ( self other view-angle -- ? ) + >r relative-angle r> 2 / <= ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +: within-separation-radius? ( self other -- ? ) + separation-radius get within-radius? ; + +: within-separation-view? ( self other -- ? ) + separation-view-angle get within-view-angle? ; + +: within-separation-neighborhood? ( self other -- ? ) + [ eq? not ] 2keep + [ within-separation-radius? ] 2keep + within-separation-view? + and and ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +: within-alignment-radius? ( self other -- ? ) + alignment-radius get within-radius? ; + +: within-alignment-view? ( self other -- ? ) + alignment-view-angle get within-view-angle? ; + +: within-alignment-neighborhood? ( self other -- ? ) + [ eq? not ] 2keep + [ within-alignment-radius? ] 2keep + within-alignment-view? + and and ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +: within-cohesion-radius? ( self other -- ? ) + cohesion-radius get within-radius? ; + +: within-cohesion-view? ( self other -- ? ) + cohesion-view-angle get within-view-angle? ; + +: within-cohesion-neighborhood? ( self other -- ? ) + [ eq? not ] 2keep + [ within-cohesion-radius? ] 2keep + within-cohesion-view? + and and ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +: separation-force ( self -- force ) + ! boids get [ within-separation-neighborhood? ] subset-with + boids get [ >r dup r> within-separation-neighborhood? ] subset + dup length 0 = + [ drop drop { 0 0 } ] + [ average-position + >r boid-pos r> v- + normalize + separation-weight get + v*n ] + if ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +: alignment-force ( self -- force ) + ! boids get [ within-alignment-neighborhood? ] subset-with + boids get [ >r dup r> within-alignment-neighborhood? ] subset swap drop + dup length 0 = + [ drop { 0 0 } ] + [ average-velocity + normalize + alignment-weight get + v*n ] + if ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +: cohesion-force ( self -- force ) + ! boids get [ within-cohesion-neighborhood? ] subset-with + boids get [ >r dup r> within-cohesion-neighborhood? ] subset + dup length 0 = + [ drop drop { 0 0 } ] + [ average-position + swap ! avg-pos self + boid-pos v- + normalize + cohesion-weight get + v*n ] + if ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +! F = m a +! +! We let m be equal to 1 so then this is simply: F = a + +: acceleration ( boid -- acceleration ) + dup dup + separation-force rot + alignment-force rot + cohesion-force v+ v+ ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +! iterate-boid +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +: world-width ( -- w ) world-size get first ; + +: world-height ( -- w ) world-size get second ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +: below? ( n a b -- ? ) drop < ; + +: above? ( n a b -- ? ) nip > ; + +: wrap ( n a b -- n ) +{ { [ 3dup below? ] + [ 2nip ] } + { [ 3dup above? ] + [ drop nip ] } + { [ t ] + [ 2drop ] } } +cond ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +: wrap-x ( x -- x ) 0 world-width 1- wrap ; + +: wrap-y ( y -- y ) 0 world-height 1- wrap ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +! : new-pos ( boid -- pos ) +! dup >r boid-pos r> boid-vel time-slice get v*n v+ ; + +! : new-vel ( boid -- vel ) +! dup >r boid-vel r> acceleration time-slice get v*n v+ ; + +! : new-vel ( boid -- vel ) +! dup boid-vel swap acceleration time-slice get v*n v+ ; + +! : wrap-x ( x -- x ) +! dup 0 world-size get nth >= [ drop 0 ] when +! dup 0 < [ drop 0 world-size get nth 1 - ] when ; + +! : wrap-y ( y -- y ) +! dup 1 world-size get nth >= [ drop 0 ] when +! dup 0 < [ drop 1 world-size get nth 1 - ] when ; + +: new-pos ( boid -- pos ) dup boid-vel time-slice> v*n swap boid-pos v+ ; + +! : new-vel ( boid -- vel ) dup acceleration time-slice> v*n swap boid-vel v+ ; + +: new-vel ( boid -- vel ) +dup acceleration time-slice> v*n swap boid-vel v+ normalize ; + +: wrap-pos ( pos -- pos ) first2 wrap-y swap wrap-x swap 2array ; + +: iterate-boid ( self -- self ) dup >r new-pos wrap-pos r> new-vel ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +: iterate-boids ( -- ) boids get [ iterate-boid ] map boids set ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +! : draw-boids ( -- ) boids get [ draw-boid ] each flush-dpy ; + +: draw-boids ( -- ) +reset-slate white set-clear-color black set-color clear-window +boids get [ draw-boid ] each flush-dlist flush-slate ; + +! : run-boids ( -- ) iterate-boids clear-window draw-boids 1 sleep run-boids ; + +SYMBOL: stop? + +: run-boids ( -- ) +self get rect-dim world-size set +iterate-boids draw-boids 1 sleep +stop? get [ ] [ run-boids ] if ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +: boids-go ( -- ) +init-variables +0.1 time-slice set +! 1.0 >min-speed +! 1.0 >max-speed + dup self set open-window +100 capacity set +self get rect-dim world-size set +50 random-boids boids set +1000 sleep +f stop? set +run-boids ; + +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +! Boids ui +! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +USING: gadgets-frames gadgets-labels gadgets-theme gadgets-grids + gadgets-editors gadgets-buttons ; + +! USING: kernel arrays gadgets gadgets-labels gadgets-editors vars ; + +TUPLE: field label editor quot ; + +VAR: field + +C: field ( label-text editor-text quot -- ) +[ field ] +[ field> set-field-quot + field> set-field-editor +