Merge branch 'do' of https://github.com/urbit/urbit into do

Conflicts:
	urb/zod/base/ape/bit/core.hook
This commit is contained in:
Henry Ault 2015-05-20 13:50:42 -07:00
commit a4a2f0c789
33 changed files with 1542 additions and 222 deletions

View File

@ -354,7 +354,7 @@ LIBCOMMONMARK=outside/commonmark/build/src/libcmark.a
LIBSCRYPT=outside/scrypt/scrypt.a LIBSCRYPT=outside/scrypt/scrypt.a
all: vere all: urbit
.MAKEFILE-VERSION: Makefile .make.conf .MAKEFILE-VERSION: Makefile .make.conf
@echo "Makefile update." @echo "Makefile update."
@ -363,7 +363,7 @@ all: vere
.make.conf: .make.conf:
@echo "# Set custom configuration here, please!" > ".make.conf" @echo "# Set custom configuration here, please!" > ".make.conf"
vere: $(BIN)/vere urbit: $(BIN)/urbit
meme: $(BIN)/meme meme: $(BIN)/meme
$(LIBUV_MAKEFILE) $(LIBUV_MAKEFILE2): $(LIBUV_MAKEFILE) $(LIBUV_MAKEFILE2):
@ -393,14 +393,14 @@ $(CRE2_OFILES): outside/cre2/src/src/cre2.cpp outside/cre2/src/src/cre2.h $(LIBR
$(V_OFILES): i/v/vere.h $(V_OFILES): i/v/vere.h
ifdef NO_SILENT_RULES ifdef NO_SILENT_RULES
$(BIN)/vere: $(LIBCRE) $(LIBCOMMONMARK) $(VERE_OFILES) $(LIBUV) $(LIBRE2) $(LIBED25519) $(LIBANACHRONISM) $(LIBSCRYPT) $(BIN)/urbit: $(LIBCRE) $(LIBCOMMONMARK) $(VERE_OFILES) $(LIBUV) $(LIBRE2) $(LIBED25519) $(LIBANACHRONISM) $(LIBSCRYPT)
mkdir -p $(BIN) mkdir -p $(BIN)
$(CLD) $(CLDOSFLAGS) -o $(BIN)/vere $(VERE_OFILES) $(LIBUV) $(LIBCRE) $(LIBRE2) $(LIBED25519) $(LIBANACHRONISM) $(LIBS) $(LIBCOMMONMARK) $(LIBSCRYPT) $(CLD) $(CLDOSFLAGS) -o $(BIN)/urbit $(VERE_OFILES) $(LIBUV) $(LIBCRE) $(LIBRE2) $(LIBED25519) $(LIBANACHRONISM) $(LIBS) $(LIBCOMMONMARK) $(LIBSCRYPT)
else else
$(BIN)/vere: $(LIBCRE) $(LIBCOMMONMARK) $(VERE_OFILES) $(LIBUV) $(LIBRE2) $(LIBED25519) $(LIBANACHRONISM) $(LIBSCRYPT) $(BIN)/urbit: $(LIBCRE) $(LIBCOMMONMARK) $(VERE_OFILES) $(LIBUV) $(LIBRE2) $(LIBED25519) $(LIBANACHRONISM) $(LIBSCRYPT)
@echo " CCLD $(BIN)/vere" @echo " CCLD $(BIN)/urbit"
@mkdir -p $(BIN) @mkdir -p $(BIN)
@$(CLD) $(CLDOSFLAGS) -o $(BIN)/vere $(VERE_OFILES) $(LIBUV) $(LIBCRE) $(LIBRE2) $(LIBED25519) $(LIBANACHRONISM) $(LIBS) $(LIBCOMMONMARK) $(LIBSCRYPT) @$(CLD) $(CLDOSFLAGS) -o $(BIN)/urbit $(VERE_OFILES) $(LIBUV) $(LIBCRE) $(LIBRE2) $(LIBED25519) $(LIBANACHRONISM) $(LIBS) $(LIBCOMMONMARK) $(LIBSCRYPT)
endif endif
$(BIN)/meme: $(LIBCRE) $(LIBCOMMONMARK) $(MEME_OFILES) $(LIBUV) $(LIBRE2) $(LIBED25519) $(LIBANACHRONISM) $(LIBSCRYPT) $(BIN)/meme: $(LIBCRE) $(LIBCOMMONMARK) $(MEME_OFILES) $(LIBUV) $(LIBRE2) $(LIBED25519) $(LIBANACHRONISM) $(LIBSCRYPT)
@ -416,24 +416,24 @@ etags:
osxpackage: osxpackage:
$(RM) -r inst $(RM) -r inst
$(MAKE) distclean $(MAKE) distclean
$(MAKE) $(BIN)/vere LIB=/usr/local/lib/urb STATIC=yes $(MAKE) $(BIN)/urbit LIB=/usr/local/lib/urb STATIC=yes
mkdir -p inst/usr/local/lib/urb inst/usr/local/bin mkdir -p inst/usr/local/lib/urb inst/usr/local/bin
cp $(BIN)/vere inst/usr/local/bin cp $(BIN)/urbit inst/usr/local/bin
cp urb/urbit.pill inst/usr/local/lib/urb cp urb/urbit.pill inst/usr/local/lib/urb
cp -R urb/zod inst/usr/local/lib/urb cp -R urb/zod inst/usr/local/lib/urb
pkgbuild --root inst --identifier org.urbit.vere --version 0.2 vere.pkg pkgbuild --root inst --identifier org.urbit.urbit --version 0.2 urbit.pkg
debbuild: debbuild:
$(MAKE) $(BIN)/vere LIB=/usr/share/urb $(MAKE) $(BIN)/urbit LIB=/usr/share/urb
debinstall: debinstall:
mkdir -p $(DESTDIR)/usr/bin $(DESTDIR)/usr/share/urb mkdir -p $(DESTDIR)/usr/bin $(DESTDIR)/usr/share/urb
install -m755 $(BIN)/vere $(DESTDIR)/usr/bin install -m755 $(BIN)/urbit $(DESTDIR)/usr/bin
cp urb/urbit.pill $(DESTDIR)/usr/share/urb cp urb/urbit.pill $(DESTDIR)/usr/share/urb
cp -R urb/zod $(DESTDIR)/usr/share/urb cp -R urb/zod $(DESTDIR)/usr/share/urb
clean: clean:
$(RM) $(VERE_OFILES) $(BIN)/vere vere.pkg $(VERE_DFILES) $(RM) $(VERE_OFILES) $(BIN)/urbit urbit.pkg $(VERE_DFILES)
distclean: clean $(LIBUV_MAKEFILE) distclean: clean $(LIBUV_MAKEFILE)
$(MAKE) -C outside/libuv_0.11 distclean $(MAKE) -C outside/libuv_0.11 distclean

135
demo/commands.txt Normal file
View File

@ -0,0 +1,135 @@
Commands
[from URL bar]
***TBD - Galen/Anton please fill in
[from unix]
For A, to build and boot:
git clone https://github.com/urbit/urbit
cd urbit
make
bin/urbit -T $A -c $A
For A, to kill and restart from checkpoint:
[in new terminal] killall -9 urbit
[in old terminal] urbit $A
For A, to kill, delete checkpoint, and rerun events:
[in new terminal] killall -9 urbit; rm -rf $A/.urb/chk
[in old terminal] urbit $A
For B, to edit /foo/bar/hoon:
*** Philip/anyone, add directions to install vim style
vim urbit/$B/$B/in/$DEMO/foo/bar.hoon
[from talk]
For A, to private-message B (who defaults to talking back):
;~B
To create a channel '%foobar':
;create channel %foobar 'channel description'
[from hood, #]
For A or B, to start tictactoe:
*demo/tictactoe
For A or B, to log in to X's tictactoe:
+~X/tictactoe
To log out:
-~X/tictactoe
[from dojo]
For B, to create a %demo desk for this project:
:+merge %demo ~B %home
For A, to sync and follow B's demo desk:
:+sync %demo ~B %demo
*** - put bitcoin instructions here
[files in script, clay and unix]
The tictactoe app, all three versions:
/=demo=/ape/tictactoe/core/hook
urbit/$X/$X/in/$DEMO/ape/tictactoe/core/hook
version 1 (centralized):
$DEMO/files/1-ape-tictactoe.hoon
version 2 (distributed):
$DEMO/files/2-ape-tictactoe.hoon
version 3 (webified)
$DEMO/files/3-ape-tictactoe.hoon
Helper files needed for version 2:
The %octo-game mark, for game update diffs:
/=demo=/mar/octo-game/door/hook
urbit/$X/$X/in/$DEMO/mar/octo-game/door.hook
$DEMO/files/mar-octo-game.hoon
Helper files needed for version 3:
The %octo-move mark, for moves from the web:
/=demo=/mar/octo-move/door/hook
urbit/$X/$X/in/$DEMO/mar/octo-move/door.hook
$DEMO/files/mar-octo-move.hoon
The HTML generator:
/=demo=/pub/octo/fab/hymn/hook
urbit/$X/$X/in/$DEMO/pub/octo/fab/hymn.hook
$DEMO/files/pub-octo-hymn.hoon
The CSS:
/=demo=/pub/octo/src/main/css
urbit/$X/$X/in/$DEMO/pub/octo/src/main.css
$DEMO/files/pub-octo-main.css
The JS:
/=demo=/pub/octo/src/main/js
urbit/$X/$X/in/$DEMO/pub/octo/src/main.js
$DEMO/files/pub-octo-main.js
[from tictactoe]
To move:
X/Y where X is row, Y is column.
To connect to a remote server (in versions 2 and 3),
specifying the side you will play:
~X x
~X o
To disconnect from a remote server (versions 2 and 3)
~ *** - not well tested
[scripts, to run from branch root directory]
$DEMO/install1.sh - copy in all version 1 (centralized) files
$DEMO/install2.sh - copy in all version 2 (distributed) files
$DEMO/install3.sh - copy in all version 3 (webby) files

View File

@ -0,0 +1,123 @@
:: :: ::
:::: /hook/core/acto/ape :: :: dependencies
:: :: ::
/- *sole :: structure
/+ sole :: library
:: :: ::
:::: :: :: structures
!: :: ::
=> |% :: board logic
++ board ,@ :: one-player bitfield
++ point ,[x=@ y=@] :: coordinate
++ game ,[who=? box=board boo=board] :: game state
++ icon |=(? ?:(+< 'X' 'O')) :: display at
++ bo :: per board
|_ bud=board ::
++ get |=(point =(1 (cut 0 [(off +<) 1] bud))) :: get point
++ off |=(point (add x (mul 3 y))) :: bitfield address
++ set |=(point (con bud (bex (off +<)))) :: set point
++ win %- lien :_ |=(a=@ =(a (dis a bud))) :: test for win
(rip 4 0wl04h0.4A0Aw.4A00s.0e070) ::
-- ::
:: :: ::
:::: :: :: semantics
:: :: ::
++ go :: per game
|_ game ::
++ at |_ point :: per point
++ g +>+< :: game
++ k !|(x o) :: ok move
++ m ?.(k [| g] [& g:t:?:(who y p)]) :: move
++ o (~(get bo boo) +<) :: old at o
++ p .(boo (~(set bo boo) +<)) :: play at o
++ t .(who !who) :: take turn
++ v ?:(x (icon &) ?:(o (icon |) '.')) :: view
++ x (~(get bo box) +<) :: old at x
++ y .(box (~(set bo box) +<)) :: play at x
-- ::
++ res ?: ~(win bo box) `"{~[(icon &)]} wins" :: result
?: ~(win bo boo) `"{~[(icon |)]} wins" ::
?: =(511 (con boo box)) `"tie :-(" ~ ::
++ row |= y=@ :~ (add y '1') :: print row
' ' ~(v at y 0) ::
' ' ~(v at y 1) ::
' ' ~(v at y 2) ::
== ::
++ tab ~["+ 1 2 3" (row 0) (row 1) (row 2)] :: print table
-- ::
-- ::
:: :: ::
:::: :: :: server
:: :: ::
=> |% :: arvo structures
++ axle ,[%0 eye=face gam=game] :: agent state
++ card ,[%diff lime] :: update
++ face (pair (list ,@c) (map bone sole-share)) :: interface
++ lime ,[%sole-effect sole-effect] :: console update
++ move (pair bone card) :: cause and action
-- ::
=> |% :: parsers
++ colm (cook |=(a=@ (sub a '1')) (shim '1' '3')) :: row or column
++ come ;~(plug colm ;~(pfix fas colm)) :: coordinate
-- ::
|_ [hid=hide moz=(list move) axle] :: per agent
++ et ::
|_ [from say=sole-share] :: per console
++ abet +>(q.eye (~(put by q.eye) ost say)) :: continue
++ amok +>(q.eye (~(del by q.eye) ost)) :: discontinue
++ beep (emit %bel ~) :: bad user
++ delt |= cal=sole-change :: input line change
=^ cul say (remit:sole cal good) ::
?~ cul (park:abet(p.eye buf.say) | ~) ::
abet:beep:(emit det/u.cul) ::
++ emit |= fec=sole-effect ^+ +> :: send effect
+>(moz [[ost %diff %sole-effect fec] moz]) ::
++ emil |= fex=(list sole-effect) :: send effects
?~(fex +> $(fex t.fex, +> (emit i.fex))) ::
++ good |=((list ,@c) -:(rose (tufa +<) come)) :: valid input
++ kick |= point :: move command
=^ dud gam ~(m ~(at go gam) +<) ::
?. dud abet:beep =+ mus=~(res go gam) ::
(park:abet(gam ?^(mus *game gam)) %2 mus) ::
++ line =^ cal say (transmit:sole set/p.eye) :: update command
(emit %det cal) ::
++ make =+ dur=(rust (tufa p.eye) come) ::
?~ dur abet:beep ::
(kick:line(p.eye ~) +.dur) ::
++ mean |=((unit tape) ?~(+< +> (emit txt/+<+))) :: optional message
++ play |= lev=?(%0 %1 %2) :: update by level
?-(lev %0 +>, %1 line, %2 line:show:prom) ::
++ plow |= [lev=?(%0 %1 %2) mus=(unit tape)] :: complete print
abet:(mean:(play lev) mus) ::
++ prom %^ emit %pro %& :- %tictactoe :: update prompt
": {~[(icon who.gam)]} to move (row/col): " ::
++ rend (turn `wall`~(tab go gam) |=(tape txt/+<)) :: table print
++ show (emit %mor rend) :: update board
++ sole ~(. cs say) :: console library
++ work |= act=sole-action :: console input
?:(?=(%det -.act) (delt +.act) make) ::
-- ::
++ abet [(flop moz) .(moz ~)] :: resolve core
++ flet |=(from ~(. et +< (~(got by q.eye) ost))) :: in old client
++ fret |=(from ~(. et +< *sole-share)) :: in new client
++ pals %+ turn (pale hid (prix /sole)) |= sink :: per console
[[p=p.+< q=q.+<] r=(~(got by q.eye) p.+<)] ::
++ park |= [lev=?(%0 %1 %2) mus=(unit tape)] :: general update
=+ pals |- ^+ +>.^$ ?~ +< +>.^$ ::
$(+< t.+<, +>.^$ (~(plow et i.+<) lev mus)) ::
:: :: ::
:::: :: :: events
:: :: ::
++ peer-sole :: console subscribe
|= [from *] =< abet ::
(plow:(fret +<-) %2 ~) ::
++ poke-sole-action :: console input
|= [from act=sole-action] =< abet ::
(work:(flet +<-) act) ::
++ prep |= [from old=(unit ,[(list move) axle])] :: initialize
=< abet ?~ old +> =< (park %2 ~) ::
+>(+<+ u.old) ::
++ pull-sole :: disconnect console
|= [from *] =< abet ::
amok:(flet +<-) ::
--

View File

@ -0,0 +1,174 @@
:: :: ::
:::: /hook/core/acto/ape :: :: dependencies
:: :: ::
/- *sole :: structures
/+ sole :: libraries
:: :: ::
:::: :: :: structures
!: :: ::
=> |% :: board logic
++ board ,@ :: one-player bitfield
++ point ,[x=@ y=@] :: coordinate
++ game ,[who=? box=board boo=board] :: game state
++ icon |=(? ?:(+< 'X' 'O')) :: display at
++ bo :: per board
|_ bud=board ::
++ get |=(point =(1 (cut 0 [(off +<) 1] bud))) :: get point
++ off |=(point (add x (mul 3 y))) :: bitfield address
++ set |=(point (con bud (bex (off +<)))) :: set point
++ win %- lien :_ |=(a=@ =(a (dis a bud))) :: test for win
(rip 4 0wl04h0.4A0Aw.4A00s.0e070) :: with bitmasks
-- ::
++ go :: per game
|_ game ::
++ at |_ point :: per point
++ g +>+< :: game
++ k !|(x o) :: ok move
++ m ?.(k [| g] [& g:t:?:(who y p)]) :: move
++ o (~(get bo boo) +<) :: old at o
++ p .(boo (~(set bo boo) +<)) :: play at o
++ t .(who !who) :: take turn
++ v ?:(x (icon &) ?:(o (icon |) '.')) :: view
++ x (~(get bo box) +<) :: old at x
++ y .(box (~(set bo box) +<)) :: play at x
-- ::
++ res ?: ~(win bo box) `"{~[(icon &)]} wins" :: result
?: ~(win bo boo) `"{~[(icon |)]} wins" ::
?: =(511 (con boo box)) `"tie :-(" ~ ::
++ row |= y=@ :~ (add y '1') :: print row
' ' ~(v at y 0) ::
' ' ~(v at y 1) ::
' ' ~(v at y 2) ::
== ::
++ tab ~["+ 1 2 3" (row 0) (row 1) (row 2)] :: print table
-- ::
-- ::
:: :: ::
:::: :: :: server
:: :: ::
=> |% :: arvo structures
++ axle ,[%1 eye=face but=tube gam=game] :: agent state
++ axon $?(axle [%0 eye=face gam=game]) :: historical state
++ card $% [%diff lime] :: update
[%quit ~] :: cancel
[%peer wire dock path] :: subscribe
[%pull wire dock ~]
== ::
++ face (pair (list ,@c) (map bone sole-share)) :: interface
++ lime $% [%sole-effect sole-effect] :: :sole update
[%octo-game game] :: :octo update
== ::
++ move (pair bone card) :: cause and action
++ mote (pair ship ,?) :: remote binding
++ tube (unit (pair ,? mote)) :: alive, remote
-- ::
=> |% :: parsers
++ colm (cook |=(a=@ (sub a '1')) (shim '1' '3')) :: row or column
++ come ;~(plug colm ;~(pfix fas colm)) :: coordinate
++ comb (pick come ;~(pfix sig (punt comp))) :: all command input
++ comp ;~(plug fed:ag ;~(pfix ace (flag %x %o))) :: login command
++ cope |=(? ?:(+< (stag %| (cold ~ sig)) comb)) :: with wait mode
-- ::
|_ [hid=hide moz=(list move) axle] :: per agent
++ et ::
|_ [from say=sole-share] :: per console client
++ abet +>(q.eye (~(put by q.eye) ost say)) :: continue
++ amok +>(q.eye (~(del by q.eye) ost)) :: discontinue
++ beep (emit %bel ~) :: bad user
++ cusp (cope wait) :: parsing rule
++ delt |= cal=sole-change :: input line change
=^ cul say (remit:sole cal good) ::
?~ cul (park:abet(p.eye buf.say) | ~) ::
abet:beep:(emit det/u.cul) ::
++ emit |= fec=sole-effect ^+ +> :: send effect
+>(moz [[ost %diff %sole-effect fec] moz]) ::
++ emil |= fex=(list sole-effect) :: send effects
?~(fex +> $(fex t.fex, +> (emit i.fex))) ::
++ good |=((list ,@c) -:(rose (tufa +<) cusp)) :: valid input
++ kick |= point :: move command
=^ dud gam ~(m ~(at go gam) +<) ::
?. dud abet:beep =+ mus=~(res go gam) ::
(park:abet(gam ?^(mus *game gam)) %2 mus) ::
++ line =^ cal say (transmit:sole set/p.eye) :: update command
(emit %det cal) ::
++ make =+ dur=(rust (tufa p.eye) comb) ::
?~ dur abet:beep ::
=. + line(p.eye ~) ::
?-(+<.dur & (kick +>.dur), | (plan +>.dur)) ::
++ mean |=((unit tape) ?~(+< +> (emit txt/+<+))) :: optional message
++ play |= lev=?(%0 %1 %2) :: update by level
?-(lev %0 +>, %1 line, %2 line:show:prom) ::
++ plow |= [lev=?(%0 %1 %2) mus=(unit tape)] :: complete print
abet:(mean:(play lev) mus) ::
++ prom %^ emit %pro %& :- %octo :: update prompt
?: wait "(their turn) " ::
": {~[(icon who.gam)]} to move (row/col): " ::
++ plan |= mut=(unit mote) :: peer command
?~ mut ?~(but abet:beep stop:abet) ::
?^(but abet:beep (link:abet u.mut)) ::
++ rend (turn `wall`~(tab go gam) |=(tape txt/+<)) :: table print
++ show (emit %mor rend) :: update board
++ sole ~(. cs say) :: console library
++ wait &(?=(^ but) !=(q.q.u.but who.gam)) :: waiting turn
++ work |= act=sole-action :: console input
?:(?=(%det -.act) (delt +.act) make) ::
-- ::
++ abet [(flop moz) .(moz ~)] :: resolve core
++ dump |=(mov=move %_(+> moz [mov moz])) :: send move
++ dish |=(cad=card (dump 0 cad)) :: forward move
++ flet |=(from ~(. et +< (~(got by q.eye) ost))) :: in old client
++ fret |=(from ~(. et +< *sole-share)) :: in new client
++ like |=(a=ship |*(* [/octo [a %tictactoe] +<])) :: to friend
++ link |= mot=mote %+ dish(but `[| mot]) %peer :: subscribe to friend
((like p.mot) /octo/net/[?:(q.mot %x %o)]) ::
++ pals %+ turn (pale hid (prix /sole)) |= sink :: per console
[[p=p.+< q=q.+<] r=(~(got by q.eye) p.+<)] ::
++ park |= [lev=?(%0 %1 %2) mus=(unit tape)] :: update all
=. +> ?:(=(%2 lev) push +>) ::
=+ pals ::
|- ^+ +>.^$ ?~ +< +>.^$ ::
$(+< t.+<, +>.^$ (~(plow et i.+<) lev mus)) ::
++ push =+ pey=(pale hid (prix /octo)) |- ^+ +> :: update friends
?~(pey +> $(pey t.pey, +> (sell p.i.pey))) ::
++ sell |=(ost=bone (dump ost %diff %octo-game gam)) :: update friend
++ stop (dish(but ~) pull/((like +>-.but) ~)) :: cancel subscribe
:: :::::::::::::::
:::: :: :: :: hooks
:: :::::::::::::::
++ diff-octo-game :: friend update
|= [then gam=game] =< abet ::
?. &(?=([~ %& *] but) =(src p.q.u.but)) +> ::
?: =(^gam gam) +> ::
(park(gam gam) %2 ~) ::
++ peer-octo-net :: urbit peer
|= [from pax=path] =< abet ::
=+ who==(%x -.pax) ::
?^ but (park %2 ~) ::
(park:(link src !who) %2 `"net from {<src>}") ::
++ peer-sole :: console subscribe
|= [from pax=path] =< abet ::
(plow:(fret +<-) %2 ~) ::
++ poke-sole-action :: console input
|= [from act=sole-action] =< abet ::
(work:(flet +<-) act) ::
++ prep |= [from old=(unit ,[(list move) axon])] :: initialize
=< abet ?~ old +> ::
=< (park %2 ~) ::
?- -.+>.old ::
%1 +>(+<+ u.old) ::
%0 +>(eye.+< eye.+>.old, gam.+< gam.+>.old)::
== ::
++ pull-octo ::
|= [from *] =< abet ::
(park(but ~) %2 `"dropped") ::
++ pull-sole :: disconnect console
|= [from *] =< abet ::
amok:(flet +<-) ::
++ quit-octo :: unlinked by friend
|=([then ~] abet:(park(but ~) %0 `"removed")) ::
++ reap-octo :: linked to friend
|= [then saw=(unit tang)] =< abet ::
?> ?=([~ %| *] but) ::
?^ saw (park:stop %0 `"fail to {<src>}") ::
(park(p.u.but %&) %0 `"link to {<src>}") ::
--

View File

@ -0,0 +1,185 @@
:: :: ::
:::: /hook/core/acto/ape :: :: dependencies
:: :: ::
/- *sole :: structures
/+ sole :: libraries
:: :: ::
:::: :: :: structures
!: :: ::
=> |% :: board logic
++ board ,@ :: one-player bitfield
++ point ,[x=@ y=@] :: coordinate
++ game ,[who=? box=board boo=board] :: game state
++ icon |=(? ?:(+< 'X' 'O')) :: display at
++ bo :: per board
|_ bud=board ::
++ get |=(point =(1 (cut 0 [(off +<) 1] bud))) :: get point
++ off |=(point (add x (mul 3 y))) :: bitfield address
++ set |=(point (con bud (bex (off +<)))) :: set point
++ win %- lien :_ |=(a=@ =(a (dis a bud))) :: test for win
(rip 4 0wl04h0.4A0Aw.4A00s.0e070) :: with bitmasks
-- ::
++ go :: per game
|_ game ::
++ at |_ point :: per point
++ g +>+< :: game
++ k !|(x o) :: ok move
++ m ?.(k [| g] [& g:t:?:(who y p)]) :: move
++ o (~(get bo boo) +<) :: old at o
++ p .(boo (~(set bo boo) +<)) :: play at o
++ t .(who !who) :: take turn
++ v ?:(x (icon &) ?:(o (icon |) '.')) :: view
++ x (~(get bo box) +<) :: old at x
++ y .(box (~(set bo box) +<)) :: play at x
-- ::
++ res ?: ~(win bo box) `"{~[(icon &)]} wins" :: result
?: ~(win bo boo) `"{~[(icon |)]} wins" ::
?: =(511 (con boo box)) `"tie :-(" ~ ::
++ row |= y=@ :~ (add y '1') :: print row
' ' ~(v at y 0) ::
' ' ~(v at y 1) ::
' ' ~(v at y 2) ::
== ::
++ tab ~["+ 1 2 3" (row 0) (row 1) (row 2)] :: print table
-- ::
-- ::
:: :: ::
:::: :: :: server
:: :: ::
=> |% :: arvo structures
++ axle ,[%1 eye=face but=tube gam=game] :: agent state
++ axon $?(axle [%0 eye=face gam=game]) :: historical state
++ card $% [%diff lime] :: update
[%quit ~] :: cancel
[%peer wire dock path] :: subscribe
[%pull wire dock ~]
== ::
++ face (pair (list ,@c) (map bone sole-share)) :: interface
++ lime $% [%sole-effect sole-effect] :: :sole update
[%octo-game game] :: :octo update
== ::
++ move (pair bone card) :: cause and action
++ mote (pair ship ,?) :: remote binding
++ tube (unit (pair ,? mote)) :: alive, remote
-- ::
=> |% :: parsers
++ colm (cook |=(a=@ (sub a '1')) (shim '1' '3')) :: row or column
++ come ;~(plug colm ;~(pfix fas colm)) :: coordinate
++ comb (pick come ;~(pfix sig (punt comp))) :: all command input
++ comp ;~(plug fed:ag ;~(pfix ace (flag %x %o))) :: login command
++ cope |=(? ?:(+< (stag %| (cold ~ sig)) comb)) :: with wait mode
-- ::
|_ [hid=hide moz=(list move) axle] :: per agent
++ et ::
|_ [from say=sole-share] :: per console client
++ abet +>(q.eye (~(put by q.eye) ost say)) :: continue
++ amok +>(q.eye (~(del by q.eye) ost)) :: discontinue
++ beep (emit %bel ~) :: bad user
++ cusp (cope wait) :: parsing rule
++ delt |= cal=sole-change :: input line change
=^ cul say (remit:sole cal good) ::
?~ cul (park:abet(p.eye buf.say) | ~) ::
abet:beep:(emit det/u.cul) ::
++ emit |= fec=sole-effect ^+ +> :: send effect
+>(moz [[ost %diff %sole-effect fec] moz]) ::
++ emil |= fex=(list sole-effect) :: send effects
?~(fex +> $(fex t.fex, +> (emit i.fex))) ::
++ good |=((list ,@c) -:(rose (tufa +<) cusp)) :: valid input
++ kick |= point :: move command
=^ dud gam ~(m ~(at go gam) +<) ::
?. dud abet:beep =+ mus=~(res go gam) ::
(park:abet(gam ?^(mus *game gam)) %2 mus) ::
++ line =^ cal say (transmit:sole set/p.eye) :: update command
(emit %det cal) ::
++ make =+ dur=(rust (tufa p.eye) comb) ::
?~ dur abet:beep ::
=. + line(p.eye ~) ::
?-(+<.dur & (kick +>.dur), | (plan +>.dur)) ::
++ mean |=((unit tape) ?~(+< +> (emit txt/+<+))) :: optional message
++ play |= lev=?(%0 %1 %2) :: update by level
?-(lev %0 +>, %1 line, %2 line:show:prom) ::
++ plow |= [lev=?(%0 %1 %2) mus=(unit tape)] :: complete print
abet:(mean:(play lev) mus) ::
++ prom %^ emit %pro %& :- %octo :: update prompt
?: wait "(their turn) " ::
": {~[(icon who.gam)]} to move (row/col): " ::
++ plan |= mut=(unit mote) :: peer command
?~ mut ?~(but abet:beep stop:abet) ::
?^(but abet:beep (link:abet u.mut)) ::
++ rend (turn `wall`~(tab go gam) |=(tape txt/+<)) :: table print
++ show (emit %mor rend) :: update board
++ sole ~(. cs say) :: console library
++ wait &(?=(^ but) !=(q.q.u.but who.gam)) :: waiting turn
++ work |= act=sole-action :: console input
?:(?=(%det -.act) (delt +.act) make) ::
-- ::
++ abet [(flop moz) .(moz ~)] :: resolve core
++ dump |=(mov=move %_(+> moz [mov moz])) :: send move
++ dish |=(cad=card (dump 0 cad)) :: forward move
++ flet |=(from ~(. et +< (~(got by q.eye) ost))) :: in old client
++ fret |=(from ~(. et +< *sole-share)) :: in new client
++ like |=(a=ship |*(* [/octo [a %tictactoe] +<])) :: to friend
++ link |= mot=mote %+ dish(but `[| mot]) %peer :: subscribe to friend
((like p.mot) /octo/net/[?:(q.mot %x %o)]) ::
++ pals %+ turn (pale hid (prix /sole)) |= sink :: per console
[[p=p.+< q=q.+<] r=(~(got by q.eye) p.+<)] ::
++ park |= [lev=?(%0 %1 %2) mus=(unit tape)] :: update all
=. +> ?:(=(%2 lev) push +>) ::
=+ pals ::
|- ^+ +>.^$ ?~ +< +>.^$ ::
$(+< t.+<, +>.^$ (~(plow et i.+<) lev mus)) ::
++ push =+ pey=(pale hid (prix /octo)) |- ^+ +> :: update friends
?~(pey +> $(pey t.pey, +> (sell p.i.pey))) ::
++ sell |=(ost=bone (dump ost %diff %octo-game gam)) :: update friend
++ stop (dish(but ~) pull/((like +>-.but) ~)) :: cancel subscribe
:: :::::::::::::::
:::: :: :: :: hooks
:: :::::::::::::::
++ diff-octo-game :: friend update
|= [then gam=game] =< abet ::
?. &(?=([~ %& *] but) =(src p.q.u.but)) +> ::
?: =(^gam gam) +> ::
(park(gam gam) %2 ~) ::
++ peer-octo-net :: urbit peer
|= [from pax=path] =< abet ::
=+ who==(%x -.pax) ::
?^ but (park %2 ~) ::
(park:(link src !who) %2 `"net from {<src>}") ::
++ peer-octo-web :: web peer
|= [from pax=path] =< abet ::
~& [%peer-web +<] ::
?^ but (park %2 ~) ::
%+ park(but `[%& src !who.gam]) %2 ::
`"web from {<src>}" ::
++ peer-sole :: console subscribe
|= [from pax=path] =< abet ::
(plow:(fret +<-) %2 ~) ::
++ poke-sole-action :: console input
|= [from act=sole-action] =< abet ::
(work:(flet +<-) act) ::
++ poke-octo-move ::
|= [from wha=point] =< abet ::
=^ dud gam ~(m ~(at go gam) wha) ::
?> dud =+ mus=~(res go gam) ::
(park(gam ?^(mus *game gam)) %2 mus) ::
++ prep |= [from old=(unit ,[(list move) axon])] :: initialize
=< abet ?~ old +> ::
=< (park %2 ~) ::
?- -.+>.old ::
%1 +>(+<+ u.old) ::
%0 +>(eye.+< eye.+>.old, gam.+< gam.+>.old)::
== ::
++ pull-octo ::
|= [from *] =< abet ::
(park(but ~) %2 `"dropped") ::
++ pull-sole :: disconnect console
|= [from *] =< abet ::
amok:(flet +<-) ::
++ quit-octo :: unlinked by friend
|=([then ~] abet:(park(but ~) %0 `"removed")) ::
++ reap-octo :: linked to friend
|= [then saw=(unit tang)] =< abet ::
?> ?=([~ %| *] but) ::
?^ saw (park:stop %0 `"fail to {<src>}") ::
(park(p.u.but %&) %0 `"link to {<src>}") ::
--

View File

@ -0,0 +1,26 @@
::
:::: /hook/door/octo-game/mar
::
/? 310
!:
|%
++ rip9
=+ b=0
|= a=@ ^- (list ,@A)
?: =(b 9) ~
[(cut 0 [b 1] a) $(b +(b))]
--
!:
|_ cod=[who=? box=@ boo=@] :: game state
::
++ grab :: convert from
|%
++ noun ,[who=? box=@ boo=@] :: clam from %noun
--
++ grow
|%
++ json ^- ^json
=> |=(bor=@ `^json`a/(turn (rip9 bor) |=(a=@A [%b =(1 a)])))
(jobe who/s/?:(who.cod %x %o) box/(. box.cod) boo/(. boo.cod) ~)
--
--

View File

@ -0,0 +1,16 @@
::
:::: /hook/door/octo-move/mar
::
/? 314
!:
::::
::
=+ point=,[x=@ y=@]
|_ point
::
++ grab :: convert from
|%
++ json (corl need (at ni ni ~):jo) :: reparse from %json
++ noun point :: clam from %noun
--
--

View File

@ -0,0 +1,32 @@
::
::
:::: /hook/hymn/fab/octo/pub/
::
^- manx
;html
;head
;meta(charset "utf-8");
;script(type "text/javascript", src "//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.js");
;script(type "text/javascript", src "/~/at/base/lib/urb.js");
;link(type "text/css", rel "stylesheet", href "/home/lib/base.css");
;link(type "text/css", rel "stylesheet", href "/home/pub/octo/src/main.css");
;title: :octo
==
;body
;div#what
;div#ship
;div.sig: ~
;div.ship;
;div.as;
==
;div#vs: vs
;div#user
;div.sig: ~
;div.ship;
;div.as;
==
==
;div#bord;
;script(type "text/javascript", src "/home/pub/octo/src/main.js");
==
==

View File

@ -0,0 +1,102 @@
#what,
#bord {
width: 600px;
text-align: center;
position: absolute;
left: 50%;
margin-left: -300px;
}
#what {
height: 36px;
top: 18px;
}
#bord {
height: 600px;
position: absolute;
top: 111px;
opacity: .6;
}
.turn #bord {
opacity: 1;
}
#what {
font-family: "bau";
}
#what div {
display: inline-block;
}
#what .ship {
font-weight: 400;
letter-spacing: 1px;
text-transform: uppercase;
}
.turn #what #ship,
#what #user {
border: 2px solid #fff;
}
#what #ship,
.turn #what #user {
border: 2px solid red;
}
#what #ship,
#what #user {
padding: .6rem;
}
#what .as {
width: 1.6rem;
}
#vs {
margin: 0 1rem;
padding: .3rem;
color: #fff;
background-color: #000;
}
.spac {
font-size: 100px;
line-height: 200px;
}
.spac {
width: 198px;
height: 198px;
border: 1px solid #000;
text-align: center;
float: left;
cursor: pointer;
}
.spac[data-index="0-0"],
.spac[data-index="1-0"],
.spac[data-index="2-0"] {
border-left: 0;
}
.spac[data-index="0-0"],
.spac[data-index="0-1"],
.spac[data-index="0-2"] {
border-top: 0;
}
.spac[data-index="2-0"],
.spac[data-index="2-1"],
.spac[data-index="2-2"] {
border-bottom: 0;
}
.spac[data-index="0-2"],
.spac[data-index="1-2"],
.spac[data-index="2-2"] {
border-right: 0;
}

View File

@ -0,0 +1,62 @@
$(function() {
$bord = $('#bord')
$whom = $('#whom')
lett = ["x","o"]
symb = [" ","✕","◯"]
draw = function(state) {
space = function(_state,y,x) {
return "<div class='spac' data-index='"+y+"-"+x+
"'>"+symb[_state]+"</div>"
}
s = ""
x = 0
y = 0
for(i=0;i<9;i++) {
j = [0,3,6,1,4,7,2,5,8][i] // XX math
s += space((state.box[j] ? 1 : 0)+(state.boo[j] ? 2 : 0),y,x)
x++
if((i+1)%3 == 0) {
y++
x=0
}
}
$bord.html(s)
turn(state.who)
}
which = null
turn = function(who) {
$('body').toggleClass('turn',(who == which))
}
assign = function(who) {
which = who
turn(who)
$('#ship .as').text(symb[Number(!lett.indexOf(who))+1])
$('#user .as').text(symb[lett.indexOf(who)+1])
}
urb.appl = 'octo'
urb.bind('/octo/web', function(err,res) {
if(which == null) { assign(res.data.who) }
draw(res.data)
})
// draw({
// box:[false,false,false,false,false,false,false,false,false],
// boo:[false,false,false,false,false,false,false,false,false]
// })
$bord.on('click', function(e) {
if(!$('body').hasClass('turn')) { return false }
$t = $(e.target).closest('.spac')
data = $.map(
$t.attr('data-index').split('-'),
function(i) { return Number(i); })
urb.send({mark:'octo-move',data:data})
})
$('#ship .ship').text(window.urb.ship)
$('#user .ship').text(window.urb.user)
})

9
demo/install1.sh Executable file
View File

@ -0,0 +1,9 @@
#!/bin/sh
#
X=$1
DEMO=demo
COLD=$DEMO/files
DESK=urbit/$X/$X/in/$DEMO
echo "cp -f $COLD/1-ape-tictactoe.hoon $DESK/ape/tictactoe/core/hook"
cp -f $COLD/1-ape-tictactoe.hoon $DESK/ape/tictactoe/core/hook

12
demo/install2.sh Executable file
View File

@ -0,0 +1,12 @@
#!/bin/sh
#
X=$1
DEMO=demo
COLD=$DEMO/files
DESK=urbit/$X/$X/in/$DEMO
echo "cp -f $COLD/2-ape-tictactoe.hoon $DESK/ape/tictactoe/core/hook"
cp -f $COLD/1-ape-tictactoe.hoon $DESK/ape/tictactoe/core/hook
echo "cp -f $COLD/mar-octo-game.hoon $DESK/mar/octo-game/door.hook"
cp -f $COLD/mar-octo-game.hoon $DESK/mar/octo-game/door.hook

21
demo/install3.sh Executable file
View File

@ -0,0 +1,21 @@
#!/bin/sh
#
X=$1
DEMO=demo
COLD=$DEMO/files
DESK=urbit/$X/$X/in/$DEMO
echo "cp -f $COLD/3-ape-tictactoe.hoon $DESK/ape/tictactoe/core/hook"
cp -f $COLD/3-ape-tictactoe.hoon $DESK/ape/tictactoe/core/hook
echo "cp -f $COLD/mar-octo-game.hoon $DESK/mar/octo-game/door.hook"
cp -f $COLD/mar-octo-game.hoon $DESK/mar/octo-game/door.hook
echo "cp -f $COLD/pub-octo-hymn.hoon $DESK/pub/octo/fab/hymn.hook"
cp -f $COLD/pub-octo-hymn.hoon $DESK/pub/octo/fab/hymn.hook
echo "cp -f $COLD/pub-octo-main.css $DESK/pub/octo/src/main.css"
cp -f $COLD/pub-octo-main.css $DESK/pub/octo/src/main.css
echo "cp -f $COLD/pub-octo-main.js $DESK/pub/octo/src/main.js"
cp -f $COLD/pub-octo-main.js $DESK/pub/octo/src/main.js

27
demo/script-1.txt Normal file
View File

@ -0,0 +1,27 @@
script:
~tasfyn-partyv and ~talsur-todres decide to build a tic-tac-toe game
tasfyn-partyv: would you like to play a game of thermonuclear war?
talsur-todres: no. how about some tic-tac-toe?
tasfyn-partyv: sure. but wait, do we have a server?
talsur-todres:
features of the game:
(0) we build one-computer two-player TTT
(1) we build console tic-tac-toe
(2) we install it over the network
+ 1 2 3
1 X X
2 O O
3 X O X
? 1/3
(3) we update it to change the characters
(4) maybe cheating with some pretyped assets, we make a web view
(5)

147
demo/script-2.txt Normal file
View File

@ -0,0 +1,147 @@
A == ~tasfyn-partyv
B == ~talsur-todres
A and B, on unix terminals on different machines, clone and
build urbit from scratch, cutting over the build.
Each screen is divided into two logical columns. A's
screen is filled with two shells. B's screen has a shell
on the left and is empty on the right.
At the unix prompt, both run
urbit -c myship
type in an invisible ticket, and begin their ships. All
diagnostic messages are suppressed. Both users land
initially in :talk.
A: is this thing on?
B: who am i? why am i here?
A: would you like to play a game of global thermonuclear war?
B: wouldn't you prefer tic-tac-toe?
A: sure, but i'll have to write it. hang on...
A switches to :dojo and runs
:+merge %tic-tac-a ~tasfyn-partyv %home
In the other window, A runs vim and edits, occasionally
hitting :w to save the file:
demo/file1.txt -> A/in/base/ape/tictactoe/core.hook
After ++bo,
A: the board state is a bitfield
A: btw, you can watch me code at <URL>.
B opens a browser and points it at <URL>, showing the
tree with live update every time A saves.
After ++go:
A: game semantics are not that complex...
After ++move:
A: basic console io, kinda boilerplaty
After ++come:
A: if you can infer the type of the product
A: of a combinator parser, you are probably
A: a typed functional language even if you
A: leave category theory to the real math nerds...
After ++park:
A: a fairly vanilla console server. probably some
A: of this should be sucked out into a library -
A: you can never completely beat the boilerplate.
A: also note that this is a two-way console with
A: operational transformation that cancels syntax
A: errors as you type, just like how :talk violates
A: your human rights by lowercasing your capitals.
A: finally, while the style is perfectly readable
A: for a hoon programmer, we don't normally go in
A: for this kind of mildly contrived topiary.
After ++pull-sole:
A: those were the event hooks where arvo calls us,
A: expecting a new state and a list of actions.
A: anyway, this should work - let's try it.
A: do this:
:+sync %tic-tac-a ~tasfyn-partyv %tic-tac-a
:+start %tic-tac-a %tictactoe
B does this. it puts him straight into TTT.
A: now hang on, I'll join you.
A uses ^V to pop the hood and types +~B/
A: bear in mind, this is a very crude shared space.
A: your server is just exporting a console interface
A: which we both can access. so essentially i'm
A: ssh-ed into your game world.
They play a couple of moves.
A: it's important to note that your urbit is also
A: in a sense, a database. try this from unix:
killall -9 urbit
urbit myship
B does this, comes back and plays a move.
B: we don't seem to have lost any data.
A: we didn't even come close to losing data,
A: so let's come a little closer:
killall -9 vere
rm -rf $checkpoint
urbit myship
B does this, comes back and plays a move.
B: whoa, that was heavy.
A: yeah, your life flashed before your eyes. or at least,
A: your event history. this system of checkpoint
A: and transaction log is actually how normal dbs work,
A: though urbit is designed as a personal computer and
A: hardly up for a normal db workload.
B: it's a little odd that either of us could play X or O.
A: or even have an edit war in the command line.
They have an edit war in the command line.
B: it might be right for some things. not tictactoe.
A: then we'll have to change it! often when someone
A: installs your software, later you find out it's not
A: perfect and sometimes actually needs to be changed.
B: i've had that experience a number of times.
A: but it's always tricky to operate on a beating heart,
A: so let's try it in a small way first...
A edits the source file and changes X to Z, or
maybe to a Unicode symbol. When he saves, the
change propagates to both consoles and also the
tree view on B's screen, even to the prompt UI.
B: i've seen that sort of thing before.
A: really? in any case, let's do it for real. the next
A: version is a genuine distributed tictactoe with
A: its own peer-to-peer move protocol. surely this
A: is some fancy technology...
A edits the source file into

162
demo/script-3.txt Normal file
View File

@ -0,0 +1,162 @@
For dialogue: start with dialogue ad-libbed by whoever is
doing the production. Later, copy it into a script and
edit that script.
For operation details, see commands.txt. Fill in the script
with literal operations *only once you have tested them
yourself*.
A: build and boot A
...
""
A: private-message B
...
""
B: create demo desk
...
""
B: vim in application version 1, just typing, very fast
...
""
A: sync A's demo desk to B
...
""
B: log in to A's tictactoe (intentionally reversed)
...
""
A: start tictactoe on A
A/B: play ONE full game of tictactoe, moves interleaved with
these subdemos:
B changes X to Z in the source, then changes it back
...
""
A or B enters an invalid move, beep sound is heard
...
""
A kills and restarts the vere process:
...
""
A kills the vere process, deletes the checkpoint, restarts:
...
""
A or B enters an invalid move, beep sound is heard:
...
""
A and B tussle humorously over weird shared command line
...
""
B edits version 1 into version 2, automagically upgrading A
...
""
B logs out of A's tictactoe
...
""
B starts local tictactoe
...
""
B connects local tictactoe to A's server
...
""
B edits in version 3 ape, with web support
...
""
A: watch editing of application
...
""
B edits in mar, pub (very fast)
...
""
A: logs in to game url
...
""
A: brings up web talk
...
""
B: creates a local channel to talk about TTT
...
""
A: subscribes from the web UI to B's channel
...
""
C, D, and E: join the channel and give humorous advice
...
""
A: loses the game
...
""
B: sends bitcoin payment to A
...
""
A: points browser at blockchain.info, shows real payment
...
""
close:
credit screen 1:
*everyone who has ever worked/for at Tlon, in alphabetical
order*,
credit screen 2:
*every non Tlon github uid that has contributed to our repository*
credit screen 3:
~, huge

View File

@ -1121,6 +1121,7 @@
# define c3__veer c3_s4('v','e','e','r') # define c3__veer c3_s4('v','e','e','r')
# define c3__vega c3_s4('v','e','g','a') # define c3__vega c3_s4('v','e','g','a')
# define c3__velt c3_s4('v','e','l','t') # define c3__velt c3_s4('v','e','l','t')
# define c3__verb c3_s4('v','e','r','b')
# define c3__vern c3_s4('v','e','r','n') # define c3__vern c3_s4('v','e','r','n')
# define c3__very c3_s4('v','e','r','y') # define c3__very c3_s4('v','e','r','y')
# define c3__view c3_s4('v','i','e','w') # define c3__view c3_s4('v','i','e','w')

View File

@ -104,11 +104,9 @@
/* u3a_road: contiguous allocation and execution context. /* u3a_road: contiguous allocation and execution context.
*/ */
typedef struct _u3a_road { typedef struct _u3a_road {
struct _u3a_road* par_u; // parent road u3p(struct _u3a_road) par_p; // parent road
u3p(struct _u3a_road) kid_p; // child road list
struct _u3a_road* kid_u; // child road list u3p(struct _u3a_road) nex_p; // sibling road
struct _u3a_road* nex_u; // sibling road
struct _u3a_road* now_u; // current road pointer
u3p(c3_w) cap_p; // top of transient region u3p(c3_w) cap_p; // top of transient region
u3p(c3_w) hat_p; // top of durable region u3p(c3_w) hat_p; // top of durable region

View File

@ -23,7 +23,8 @@
u3o_check_corrupt = 0x4, // check: gc memory u3o_check_corrupt = 0x4, // check: gc memory
u3o_check_fatal = 0x8, // check: unrecoverable u3o_check_fatal = 0x8, // check: unrecoverable
u3o_verbose = 0x10, // be remarkably wordy u3o_verbose = 0x10, // be remarkably wordy
u3o_dryrun = 0x20 // don't touch checkpoint u3o_dryrun = 0x20, // don't touch checkpoint
u3o_quiet = 0x40 // disable ~&
}; };
/** Globals. /** Globals.

View File

@ -104,5 +104,6 @@
/* u3to(), u3of(): offset/pointer conversion. /* u3to(), u3of(): offset/pointer conversion.
*/ */
# define u3to(type, x) ((type *) u3a_into(x)) # define u3to(type, x) ((type *) u3a_into(x))
# define u3tn(type, x) (x == 0) ? (void *)0 : ((type *) u3a_into(x))
# define u3of(type, x) (u3a_outa((type *)x)) # define u3of(type, x) (u3a_outa((type *)x))

View File

@ -521,6 +521,8 @@
c3_c* imp_c; // -I, czar name c3_c* imp_c; // -I, czar name
c3_c* nam_c; // -n, unix hostname c3_c* nam_c; // -n, unix hostname
c3_c* raf_c; // -r, raft flotilla c3_c* raf_c; // -r, raft flotilla
c3_c* who_c; // -T, begin with ticket
c3_c* tic_c; // -T, ticket value
c3_w kno_w; // -k, kernel version c3_w kno_w; // -k, kernel version
c3_w fuz_w; // -f, fuzz testing c3_w fuz_w; // -f, fuzz testing
c3_s por_s; // -p, ames port c3_s por_s; // -p, ames port
@ -536,7 +538,8 @@
c3_o pro; // -P, profile c3_o pro; // -P, profile
c3_o veb; // -v, verbose (inverse of -q) c3_o veb; // -v, verbose (inverse of -q)
c3_o nuu; // -c, new pier c3_o nuu; // -c, new pier
c3_o vno; // -V c3_o qui; // -q, quiet
c3_o vno; // -V, turn on +verb
c3_o mem; // -M, memory madness c3_o mem; // -M, memory madness
} u3_opts; } u3_opts;
@ -791,6 +794,16 @@
void void
u3_term_ef_boil(); u3_term_ef_boil();
/* u3_term_ef_ticket(): initial effects for new ticket.
*/
void
u3_term_ef_ticket(c3_c* who_c, c3_c* tic_c);
/* u3_term_ef_verb(): initial effects for verbose events.
*/
void
u3_term_ef_verb(void);
/* u3_term_ef_winc(): window change. /* u3_term_ef_winc(): window change.
*/ */
void void

4
n/a.c
View File

@ -967,11 +967,11 @@ _me_copy_south(u3_noun dog)
u3a_cell* new_u = (u3a_cell*)(void *)new_w; u3a_cell* new_u = (u3a_cell*)(void *)new_w;
// printf("south: cell %p to %p\r\n", old_u, new_u); // printf("south: cell %p to %p\r\n", old_u, new_u);
#if 0
if ( old_u->mug_w == 0x730e66cc ) { if ( old_u->mug_w == 0x730e66cc ) {
fprintf(stderr, "BAD: take %p\r\n", new_u); fprintf(stderr, "BAD: take %p\r\n", new_u);
} }
#endif
new_u->mug_w = old_u->mug_w; new_u->mug_w = old_u->mug_w;
// new_u->mug_w = 0; // new_u->mug_w = 0;
new_u->hed = _me_copy_south_in(old_u->hed); new_u->hed = _me_copy_south_in(old_u->hed);

4
n/j.c
View File

@ -209,8 +209,8 @@ u3j_find(u3_noun bat)
return jaw; return jaw;
} }
if ( rod_u->par_u ) { if ( rod_u->par_p ) {
rod_u = rod_u->par_u; rod_u = u3to(u3_road, rod_u->par_p);
} }
else return u3_none; else return u3_none;
} }

36
n/m.c
View File

@ -144,7 +144,7 @@ _cm_signal_handle_term(int x)
{ {
// Ignore if we are using base memory from work memory, very rare. // Ignore if we are using base memory from work memory, very rare.
// //
if ( (0 != u3H->rod_u.kid_u) && (&(u3H->rod_u) == u3R) ) { if ( (0 != u3H->rod_u.kid_p) && (&(u3H->rod_u) == u3R) ) {
_cm_emergency("ignored", c3__term); _cm_emergency("ignored", c3__term);
} }
else { else {
@ -179,7 +179,7 @@ _cm_signal_reset(void)
u3R = &u3H->rod_u; u3R = &u3H->rod_u;
u3R->cap_p = u3R->mat_p; u3R->cap_p = u3R->mat_p;
u3R->ear_p = 0; u3R->ear_p = 0;
u3R->kid_u = 0; u3R->kid_p = 0;
} }
/* _cm_stack_recover(): recover stack trace, with lacunae. /* _cm_stack_recover(): recover stack trace, with lacunae.
@ -271,13 +271,13 @@ _cm_signal_recover(c3_l sig_l, u3_noun arg)
u3R = &(u3H->rod_u); u3R = &(u3H->rod_u);
rod_u = u3R; rod_u = u3R;
while ( rod_u->kid_u ) { while ( rod_u->kid_p ) {
#if 0 #if 0
fprintf(stderr, "collecting %d frames\r\n", fprintf(stderr, "collecting %d frames\r\n",
u3kb_lent(rod_u->kid_u->bug.tax)); u3kb_lent((u3to(u3_road, rod_u->kid_p)->bug.tax));
#endif #endif
tax = u3kb_weld(_cm_stack_recover(rod_u->kid_u), tax); tax = u3kb_weld(_cm_stack_recover(u3to(u3_road, rod_u->kid_p)), tax);
rod_u = rod_u->kid_u; rod_u = u3to(u3_road, rod_u->kid_p);
} }
} }
@ -709,9 +709,9 @@ u3m_leap(c3_w pad_w)
/* Attach the new road to its parents. /* Attach the new road to its parents.
*/ */
{ {
c3_assert(0 == u3R->kid_u); c3_assert(0 == u3R->kid_p);
rod_u->par_u = u3R; rod_u->par_p = u3of(u3_road, u3R);
u3R->kid_u = rod_u; u3R->kid_p = u3of(u3_road, rod_u);
} }
/* Set up the new road. /* Set up the new road.
@ -727,26 +727,26 @@ u3m_leap(c3_w pad_w)
void void
u3m_fall() u3m_fall()
{ {
c3_assert(0 != u3R->par_u); c3_assert(0 != u3R->par_p);
#if 0 #if 0
fprintf(stderr, "fall: from %s %p, to %s %p (cap %p, was %p)\r\n", fprintf(stderr, "fall: from %s %p, to %s %p (cap %p, was %p)\r\n",
_(u3a_is_north(u3R)) ? "north" : "south", _(u3a_is_north(u3R)) ? "north" : "south",
u3R, u3R,
_(u3a_is_north(u3R)) ? "north" : "south", _(u3a_is_north(u3R)) ? "north" : "south",
u3R->par_u, u3to(u3_road, u3R->par_p),
u3R->hat_w, u3R->hat_w,
u3R->rut_w); u3R->rut_w);
#endif #endif
/* The new cap is the old hat - it's as simple as that. /* The new cap is the old hat - it's as simple as that.
*/ */
u3R->par_u->cap_p = u3R->hat_p; u3to(u3_road, u3R->par_p)->cap_p = u3R->hat_p;
/* And, we're back home. /* And, we're back home.
*/ */
u3R = u3R->par_u; u3R = u3to(u3_road, u3R->par_p);
u3R->kid_u = 0; u3R->kid_p = 0;
} }
/* u3m_hate(): new, integrated leap mechanism (enter). /* u3m_hate(): new, integrated leap mechanism (enter).
@ -948,8 +948,8 @@ u3m_soft_run(u3_noun fly,
/* Configure the new road. /* Configure the new road.
*/ */
{ {
u3R->ski.flu = u3nc(fly, u3R->par_u->ski.flu); u3R->ski.flu = u3nc(fly, u3to(u3_road, u3R->par_p)->ski.flu);
u3R->pro.don = u3R->par_u->pro.don; u3R->pro.don = u3to(u3_road, u3R->par_p)->pro.don;
u3R->bug.tax = 0; u3R->bug.tax = 0;
} }
u3t_on(coy_o); u3t_on(coy_o);
@ -1036,8 +1036,8 @@ u3m_soft_esc(u3_noun sam)
/* Configure the new road. /* Configure the new road.
*/ */
{ {
u3R->ski.flu = u3t(u3R->par_u->ski.flu); u3R->ski.flu = u3t(u3to(u3_road, u3R->par_p)->ski.flu);
u3R->pro.don = u3R->par_u->pro.don; u3R->pro.don = u3to(u3_road, u3R->par_p)->pro.don;
u3R->bug.tax = 0; u3R->bug.tax = 0;
} }

2
n/n.c
View File

@ -46,9 +46,11 @@ _n_hint(u3_noun zep,
} }
case c3__slog: { case c3__slog: {
if ( !(u3C.wag_w & u3o_quiet) ) {
u3t_off(noc_o); u3t_off(noc_o);
u3t_slog(hod); u3t_slog(hod);
u3t_on(noc_o); u3t_on(noc_o);
}
return _n_nock_on(bus, nex); return _n_nock_on(bus, nex);
} }

6
n/t.c
View File

@ -113,8 +113,8 @@ _t_jet_label(u3a_road* rod_u, u3_noun bat)
return u3h(u3t(u3t(u3h(cax)))); return u3h(u3t(u3t(u3h(cax))));
} }
if ( rod_u->par_u ) { if ( rod_u->par_p ) {
rod_u = rod_u->par_u; rod_u = u3to(u3_road, rod_u->par_p);
} }
else return u3_none; else return u3_none;
} }
@ -175,7 +175,7 @@ _t_samp_process(u3_road* rod_u)
} }
don = u3t(don); don = u3t(don);
} }
rod_u = rod_u->par_u; rod_u = u3tn(u3_road, rod_u->par_p);
} }
u3z(muf); u3z(muf);

View File

@ -67,6 +67,7 @@ _ames_czar(c3_y imp_y, c3_s* por_s)
snprintf(dns_c, 64, "%s.urbit.org", nam_c + 1); snprintf(dns_c, 64, "%s.urbit.org", nam_c + 1);
// uL(fprintf(uH, "czar %s, dns %s\n", nam_c, dns_c)); // uL(fprintf(uH, "czar %s, dns %s\n", nam_c, dns_c));
free(nam_c); free(nam_c);
u3z(nam); u3z(nam);

View File

@ -691,9 +691,16 @@ u3_lo_lead(void)
#endif #endif
if ( c3y == u3_Host.ops_u.nuu ) { if ( c3y == u3_Host.ops_u.nuu ) {
if ( u3_Host.ops_u.who_c ) {
u3_term_ef_ticket(u3_Host.ops_u.who_c, u3_Host.ops_u.tic_c);
}
u3_term_ef_boil(1); u3_term_ef_boil(1);
} }
if ( c3y == u3_Host.ops_u.veb ) {
u3_term_ef_verb();
}
#if 1 #if 1
_lo_slow(); _lo_slow();
#endif #endif

View File

@ -40,6 +40,22 @@ _main_readw(const c3_c* str_c, c3_w max_w, c3_w* out_w)
static c3_c hostbuf[2048]; // kill me static c3_c hostbuf[2048]; // kill me
/* _main_presig(): prefix optional sig.
*/
c3_c*
_main_presig(c3_c* txt_c)
{
c3_c* new_c = malloc(2 + strlen(txt_c));
if ( '~' == *txt_c ) {
strcpy(new_c, txt_c);
} else {
new_c[0] = '~';
strcpy(new_c + 1, txt_c);
}
return new_c;
}
/* _main_getopt(): extract option map from command line. /* _main_getopt(): extract option map from command line.
*/ */
static u3_noun static u3_noun
@ -57,12 +73,13 @@ _main_getopt(c3_i argc, c3_c** argv)
u3_Host.ops_u.fak = c3n; u3_Host.ops_u.fak = c3n;
u3_Host.ops_u.pro = c3n; u3_Host.ops_u.pro = c3n;
u3_Host.ops_u.dry = c3n; u3_Host.ops_u.dry = c3n;
u3_Host.ops_u.veb = c3y; u3_Host.ops_u.veb = c3n;
u3_Host.ops_u.qui = c3n;
u3_Host.ops_u.nuu = c3n; u3_Host.ops_u.nuu = c3n;
u3_Host.ops_u.mem = c3n; u3_Host.ops_u.mem = c3n;
u3_Host.ops_u.kno_w = DefaultKernel; u3_Host.ops_u.kno_w = DefaultKernel;
while ( (ch_i = getopt(argc, argv, "I:X:f:k:l:n:p:r:LabcdgqvFMPD")) != -1 ) { while ( (ch_i = getopt(argc, argv, "I:T:X:f:k:l:n:p:r:LabcdgqvFMPD")) != -1 ) {
switch ( ch_i ) { switch ( ch_i ) {
case 'M': { case 'M': {
u3_Host.ops_u.mem = c3y; u3_Host.ops_u.mem = c3y;
@ -72,6 +89,11 @@ _main_getopt(c3_i argc, c3_c** argv)
u3_Host.ops_u.imp_c = strdup(optarg); u3_Host.ops_u.imp_c = strdup(optarg);
break; break;
} }
case 'T': {
u3_Host.ops_u.who_c = _main_presig(optarg);
u3_Host.ops_u.tic_c = _main_presig(getpass("your ticket: ~"));
break;
}
case 'X': { case 'X': {
if ( 0 != strcmp("wtf", optarg) ) { if ( 0 != strcmp("wtf", optarg) ) {
return c3n; return c3n;
@ -123,7 +145,7 @@ _main_getopt(c3_i argc, c3_c** argv)
case 'g': { u3_Host.ops_u.gab = c3y; break; } case 'g': { u3_Host.ops_u.gab = c3y; break; }
case 'P': { u3_Host.ops_u.pro = c3y; break; } case 'P': { u3_Host.ops_u.pro = c3y; break; }
case 'D': { u3_Host.ops_u.dry = c3y; break; } case 'D': { u3_Host.ops_u.dry = c3y; break; }
case 'q': { u3_Host.ops_u.veb = c3n; break; } case 'q': { u3_Host.ops_u.qui = c3y; break; }
case 'v': { u3_Host.ops_u.veb = c3y; break; } case 'v': { u3_Host.ops_u.veb = c3y; break; }
case '?': default: { case '?': default: {
return c3n; return c3n;
@ -330,6 +352,12 @@ main(c3_i argc,
u3C.wag_w |= u3o_verbose; u3C.wag_w |= u3o_verbose;
} }
/* Set quiet flag.
*/
if ( _(u3_Host.ops_u.qui) ) {
u3C.wag_w |= u3o_quiet;
}
/* Set dry-run flag. /* Set dry-run flag.
*/ */
if ( _(u3_Host.ops_u.dry) ) { if ( _(u3_Host.ops_u.dry) ) {
@ -363,6 +391,7 @@ main(c3_i argc,
} }
// u3e_grab("main", u3_none); // u3e_grab("main", u3_none);
//
u3_lo_loop(); u3_lo_loop();
return 0; return 0;

View File

@ -365,8 +365,6 @@ u3_reck_kick(u3_noun ovo)
if ( (c3n == _reck_kick_spec(u3k(u3h(ovo)), u3k(u3t(ovo)))) && if ( (c3n == _reck_kick_spec(u3k(u3h(ovo)), u3k(u3t(ovo)))) &&
(c3n == _reck_kick_norm(u3k(u3h(ovo)), u3k(u3t(ovo)))) ) (c3n == _reck_kick_norm(u3k(u3h(ovo)), u3k(u3t(ovo)))) )
{ {
u3_noun tox = u3do("spat", u3k(u3h(ovo)));
#if 0 #if 0
if ( (c3__warn != u3h(u3t(ovo))) && if ( (c3__warn != u3h(u3t(ovo))) &&
(c3__text != u3h(u3t(ovo))) && (c3__text != u3h(u3t(ovo))) &&
@ -384,9 +382,11 @@ u3_reck_kick(u3_noun ovo)
u3nc(c3__flog, u3k(u3t(ovo)))); u3nc(c3__flog, u3k(u3t(ovo))));
} }
else { else {
u3_noun tox = u3do("spat", u3k(u3h(ovo)));
uL(fprintf(uH, "kick: lost %%%s on %s\n", uL(fprintf(uH, "kick: lost %%%s on %s\n",
u3r_string(u3h(u3t(ovo))), u3r_string(u3h(u3t(ovo))),
u3r_string(tox))); u3r_string(tox)));
u3z(tox);
#if 0 #if 0
if ( c3__hear == u3h(u3t(ovo)) ) { if ( c3__hear == u3h(u3t(ovo)) ) {
c3_assert(0); c3_assert(0);
@ -394,7 +394,6 @@ u3_reck_kick(u3_noun ovo)
#endif #endif
} }
#endif #endif
u3z(tox);
} }
u3z(ovo); u3z(ovo);
} }

View File

@ -222,9 +222,13 @@ _sist_suck(u3_noun ovo, u3_noun gon)
u3_lo_punt(2, u3kb_flop(u3k(u3t(gon)))); u3_lo_punt(2, u3kb_flop(u3k(u3t(gon))));
// u3_loom_exit(); // u3_loom_exit();
#if 1
u3_lo_exit(); u3_lo_exit();
exit(1); exit(1);
#else
u3z(ovo); u3z(gon);
#endif
} }
/* _sist_sing(): replay ovum from the past, time already set. /* _sist_sing(): replay ovum from the past, time already set.

View File

@ -1012,6 +1012,42 @@ u3_term_ef_boil(void)
} }
} }
/* u3_term_ef_verb(): initial effects for verbose events
*/
void
u3_term_ef_verb(void)
{
u3_noun pax = u3nq(u3_blip, c3__term, '1', u3_nul);
u3v_plan(pax, u3nc(c3__verb, u3_nul));
}
/* u3_term_ef_ticket(): initial effects for new ticket.
*/
void
u3_term_ef_ticket(c3_c* who_c, c3_c* tic_c)
{
u3_noun pax = u3nq(u3_blip, c3__term, '1', u3_nul);
u3_noun who, tic;
u3_noun whu, tuc;
whu = u3dc("slaw", 'p', u3i_string(who_c));
if ( u3_nul == whu ) {
fprintf(stderr, "ticket: invalid planet '%s'\r\n", who_c);
exit(1);
}
else { who = u3k(u3t(whu)); u3z(whu); }
tuc = u3dc("slaw", 'p', u3i_string(tic_c));
if ( u3_nul == tuc ) {
fprintf(stderr, "ticket: invalid secret '%s'\r\n", tic_c);
exit(1);
}
else { tic = u3k(u3t(tuc)); u3z(tuc); }
u3v_plan(pax, u3nt(c3__tick, who, tic));
}
/* u3_term_ef_bake(): initial effects for new terminal. /* u3_term_ef_bake(): initial effects for new terminal.
*/ */
void void

331
v/unix.c
View File

@ -21,6 +21,9 @@
#include "all.h" #include "all.h"
#include "v/vere.h" #include "v/vere.h"
/* undef this to turn off syncing out to unix */
#define ERGO_SYNC
/* _unix_ship_in(): c3_w[4] to ship. /* _unix_ship_in(): c3_w[4] to ship.
*/ */
static u3_noun static u3_noun
@ -82,42 +85,6 @@ _unix_mkdir(c3_c* pax_c)
} }
} }
/* _unix_mkpath(): mkdir -p, asserting
*
* adapted from
* http://niallohiggins.com/2009/01/08/mkpath-mkdir-p-alike-in-c-for-unix/
*/
static void
_unix_mkpath(const char *s)
{
char *q, *r = NULL, *path = NULL, *up = NULL;
if (strcmp(s, ".") == 0 || strcmp(s, "/") == 0)
return;
if ((path = strdup(s)) == NULL)
c3_assert(0);
if ((q = strdup(s)) == NULL)
c3_assert(0);
if ((r = dirname(q)) == NULL)
goto out;
if ((up = strdup(r)) == NULL)
exit(1);
_unix_mkpath(up);
_unix_mkdir(path);
out:
if (up != NULL)
free(up);
free(q);
free(path);
}
/* _unix_opendir(): opendir, recreating if nonexistent. /* _unix_opendir(): opendir, recreating if nonexistent.
*/ */
static DIR* static DIR*
@ -137,17 +104,6 @@ _unix_opendir(c3_c* pax_c)
return rid_u; return rid_u;
} }
/* _unix_unlink(): unlink, asserting.
*/
static void
_unix_unlink(c3_c* pax_c)
{
if ( 0 != unlink(pax_c) && ENOENT != errno ) {
uL(fprintf(uH, "error unlinking %s: %s\n", pax_c, strerror(errno)));
c3_assert(0);
}
}
/* u3_unix_acquire(): acquire a lockfile, killing anything that holds it. /* u3_unix_acquire(): acquire a lockfile, killing anything that holds it.
*/ */
void void
@ -332,38 +288,6 @@ _unix_file_watch(u3_ufil* fil_u,
} }
/* _unix_file_form(): form a filename path downward.
*/
static c3_c*
_unix_file_form(c3_c* pax_c,
u3_noun pre,
u3_noun ket,
u3_noun ext)
{
c3_c* pre_c = u3r_string(pre);
c3_c* ext_c = u3r_string(ext);
c3_w pax_w = strlen(pax_c);
c3_w pre_w = strlen(pre_c);
c3_w ext_w = strlen(ext_c);
c3_w ket_w = (c3y == ket) ? 1 : 0;
c3_c* pox_c = c3_malloc(pax_w + 1 + pre_w + 1 + ket_w + ext_w + 1);
strncpy(pox_c, pax_c, pax_w);
pox_c[pax_w] = '/';
strncpy(pox_c + pax_w + 1, pre_c, pre_w);
pox_c[pax_w + 1 + pre_w] = '.';
if ( c3y == ket ) {
pox_c[pax_w + 1 + pre_w + 1] = '^';
}
strncpy(pox_c + pax_w + 1 + pre_w + 1 + ket_w, ext_c, ext_w);
pox_c[pax_w + 1 + pre_w + 1 + ket_w + ext_w] = '\0';
free(pre_c); free(ext_c);
u3z(pre); u3z(ext);
return pox_c;
}
/* _unix_dir_watch(): instantiate directory tracker. /* _unix_dir_watch(): instantiate directory tracker.
*/ */
static void static void
@ -402,35 +326,6 @@ _unix_dir_watch(u3_udir* dir_u, u3_udir* par_u, c3_c* pax_c, c3_c* pot_c)
} }
/* _unix_dir_forge: instantiate directory tracker (and make directory).
*/
static void
_unix_dir_forge(u3_udir* dir_u, u3_udir* par_u, u3_noun tet)
{
c3_c* tet_c = u3r_string(tet);
c3_w pax_w = strlen(par_u->pax_c);
c3_w tet_w = strlen(tet_c);
c3_c* pax_c = c3_malloc(pax_w + 1 + tet_w + 1);
c3_c* pot_c = c3_malloc(pax_w + 1 + 1 + tet_w + 1);
strncpy(pax_c, par_u->pax_c, pax_w + 1);
pax_c[pax_w] = '/';
strncpy(pax_c + pax_w + 1, tet_c, tet_w + 1);
pax_c[pax_w + tet_w + 1] = '\0';
strncpy(pot_c, par_u->pot_c, pax_w + 1 + 1);
pot_c[pax_w + 1] = '/';
strncpy(pot_c + pax_w + 1 + 1, tet_c, tet_w + 1);
pot_c[pax_w + 1 + tet_w + 1] = '\0';
free(tet_c);
u3z(tet);
_unix_mkdir(pax_c);
_unix_mkdir(pot_c);
_unix_dir_watch(dir_u, par_u, pax_c, pot_c);
}
/* _unix_file_done(): finish freeing file. /* _unix_file_done(): finish freeing file.
*/ */
static void static void
@ -741,42 +636,6 @@ _unix_load(u3_ufil* fil_u)
} }
} }
/* unix_save(): save a file.
*/
static void
_unix_save(c3_c* pax_c, u3_atom oat)
{
c3_c* dir = strdup(pax_c);
_unix_mkpath(dirname(dir));
free(dir);
c3_i fid_i = open(pax_c, O_WRONLY | O_CREAT | O_TRUNC, 0666);
c3_w fln_w, rit_w, siz_w;
c3_y* oat_y;
if ( fid_i < 0 ) {
uL(fprintf(uH, "error opening %s: %s\n", pax_c, strerror(errno)));
u3m_bail(c3__fail);
}
siz_w = u3h(u3t(oat));
fln_w = u3r_met(3, u3t(u3t(oat)));
oat_y = c3_malloc(siz_w);
memset(oat_y, 0, siz_w);
u3r_bytes(0, fln_w, oat_y, u3t(u3t(oat)));
u3z(oat);
rit_w = write(fid_i, oat_y, siz_w);
if ( rit_w != siz_w ) {
uL(fprintf(uH, "error writing %s: %s\n", pax_c, strerror(errno)));
c3_assert(0);
}
close(fid_i);
free(oat_y);
}
/* _unix_file_load(): load a file by watcher. /* _unix_file_load(): load a file by watcher.
*/ */
static u3_weak static u3_weak
@ -1201,6 +1060,134 @@ _unix_hot_lose(u3_uhot* hot_u)
_unix_dir_free(&(hot_u->dir_u)); _unix_dir_free(&(hot_u->dir_u));
} }
/* _unix_home(): find home directory from identity.
*/
static u3_uhot*
_unix_home(u3_noun who)
{
u3_unix* unx_u = &u3_Host.unx_u;
u3_uhot* hot_u;
c3_w who_w[4];
_unix_ship_out(who, who_w);
for ( hot_u = unx_u->hot_u;
hot_u && !_(_unix_ship_sing(who_w, hot_u->who_w));
hot_u = hot_u->nex_u )
{
// uL(fprintf(uH, "uh: %p, %s\n", hot_u, hot_u->dir_u.pax_c));
}
return hot_u;
}
#ifdef ERGO_SYNC
/* _unix_mkpath(): mkdir -p, asserting
*
* adapted from
* http://niallohiggins.com/2009/01/08/mkpath-mkdir-p-alike-in-c-for-unix/
*/
static void
_unix_mkpath(const char *s)
{
char *q, *r = NULL, *path = NULL, *up = NULL;
if (strcmp(s, ".") == 0 || strcmp(s, "/") == 0)
return;
if ((path = strdup(s)) == NULL)
c3_assert(0);
if ((q = strdup(s)) == NULL)
c3_assert(0);
if ((r = dirname(q)) == NULL)
goto out;
if ((up = strdup(r)) == NULL)
exit(1);
_unix_mkpath(up);
_unix_mkdir(path);
out:
if (up != NULL)
free(up);
free(q);
free(path);
}
/* _unix_dir_forge: instantiate directory tracker (and make directory).
*/
static void
_unix_dir_forge(u3_udir* dir_u, u3_udir* par_u, u3_noun tet)
{
c3_c* tet_c = u3r_string(tet);
c3_w pax_w = strlen(par_u->pax_c);
c3_w tet_w = strlen(tet_c);
c3_c* pax_c = c3_malloc(pax_w + 1 + tet_w + 1);
c3_c* pot_c = c3_malloc(pax_w + 1 + 1 + tet_w + 1);
strncpy(pax_c, par_u->pax_c, pax_w + 1);
pax_c[pax_w] = '/';
strncpy(pax_c + pax_w + 1, tet_c, tet_w + 1);
pax_c[pax_w + tet_w + 1] = '\0';
strncpy(pot_c, par_u->pot_c, pax_w + 1 + 1);
pot_c[pax_w + 1] = '/';
strncpy(pot_c + pax_w + 1 + 1, tet_c, tet_w + 1);
pot_c[pax_w + 1 + tet_w + 1] = '\0';
free(tet_c);
u3z(tet);
_unix_mkdir(pax_c);
_unix_mkdir(pot_c);
_unix_dir_watch(dir_u, par_u, pax_c, pot_c);
}
/* _unix_file_form(): form a filename path downward.
*/
static c3_c*
_unix_file_form(c3_c* pax_c,
u3_noun pre,
u3_noun ket,
u3_noun ext)
{
c3_c* pre_c = u3r_string(pre);
c3_c* ext_c = u3r_string(ext);
c3_w pax_w = strlen(pax_c);
c3_w pre_w = strlen(pre_c);
c3_w ext_w = strlen(ext_c);
c3_w ket_w = (c3y == ket) ? 1 : 0;
c3_c* pox_c = c3_malloc(pax_w + 1 + pre_w + 1 + ket_w + ext_w + 1);
strncpy(pox_c, pax_c, pax_w);
pox_c[pax_w] = '/';
strncpy(pox_c + pax_w + 1, pre_c, pre_w);
pox_c[pax_w + 1 + pre_w] = '.';
if ( c3y == ket ) {
pox_c[pax_w + 1 + pre_w + 1] = '^';
}
strncpy(pox_c + pax_w + 1 + pre_w + 1 + ket_w, ext_c, ext_w);
pox_c[pax_w + 1 + pre_w + 1 + ket_w + ext_w] = '\0';
free(pre_c); free(ext_c);
u3z(pre); u3z(ext);
return pox_c;
}
/* _unix_unlink(): unlink, asserting.
*/
static void
_unix_unlink(c3_c* pax_c)
{
if ( 0 != unlink(pax_c) && ENOENT != errno ) {
uL(fprintf(uH, "error unlinking %s: %s\n", pax_c, strerror(errno)));
c3_assert(0);
}
}
/* _unix_pdir(): find directory reference from text. /* _unix_pdir(): find directory reference from text.
*/ */
static u3_udir** static u3_udir**
@ -1221,34 +1208,41 @@ _unix_pdir(u3_udir* par_u, u3_noun tet)
} }
} }
/* _unix_home(): find home directory from identity. /* unix_save(): save a file.
*/ */
static u3_uhot* static void
_unix_home(u3_noun who) _unix_save(c3_c* pax_c, u3_atom oat)
{ {
u3_unix* unx_u = &u3_Host.unx_u; c3_c* dir = strdup(pax_c);
u3_uhot* hot_u; _unix_mkpath(dirname(dir));
c3_w who_w[4]; free(dir);
_unix_ship_out(who, who_w); c3_i fid_i = open(pax_c, O_WRONLY | O_CREAT | O_TRUNC, 0666);
for ( hot_u = unx_u->hot_u; c3_w fln_w, rit_w, siz_w;
hot_u && !_(_unix_ship_sing(who_w, hot_u->who_w)); c3_y* oat_y;
hot_u = hot_u->nex_u )
{ if ( fid_i < 0 ) {
// uL(fprintf(uH, "uh: %p, %s\n", hot_u, hot_u->dir_u.pax_c)); uL(fprintf(uH, "error opening %s: %s\n", pax_c, strerror(errno)));
u3m_bail(c3__fail);
} }
return hot_u;
}
#if 0 siz_w = u3h(u3t(oat));
/* _unix_desk_sync_udon(): apply udon to existing value. fln_w = u3r_met(3, u3t(u3t(oat)));
*/ oat_y = c3_malloc(siz_w);
static u3_noun memset(oat_y, 0, siz_w);
_unix_desk_sync_udon(u3_noun don, u3_noun old)
{ u3r_bytes(0, fln_w, oat_y, u3t(u3t(oat)));
return u3dc("lump", don, old); u3z(oat);
rit_w = write(fid_i, oat_y, siz_w);
if ( rit_w != siz_w ) {
uL(fprintf(uH, "error writing %s: %s\n", pax_c, strerror(errno)));
c3_assert(0);
}
close(fid_i);
free(oat_y);
} }
#endif
/* _unix_desk_sync_tofu(): sync out file install. /* _unix_desk_sync_tofu(): sync out file install.
*/ */
@ -1420,6 +1414,7 @@ _unix_desk_sync_list(u3_udir* dir_u, u3_noun can)
u3z(can); u3z(can);
} }
#endif
/* _unix_desk_sync_ergo(): sync desk changes to unix. /* _unix_desk_sync_ergo(): sync desk changes to unix.
*/ */
@ -1430,11 +1425,11 @@ _unix_desk_sync_ergo(u3_noun hox,
u3_noun can, u3_noun can,
u3_uhot* hot_u) u3_uhot* hot_u)
{ {
#if 0 #ifndef ERGO_SYNC
u3z(hox); u3z(syd); u3z(lok); u3z(can); u3z(hox); u3z(syd); u3z(lok); u3z(can);
#else #else
u3_udir** dir_u = _unix_pdir(&(hot_u->dir_u), syd); u3_udir** dir_u = _unix_pdir(&(hot_u->dir_u), u3k(syd));
#if 0 #if 0
uL(fprintf(uH, "ergo %s %s %s\n", u3r_string(hox), uL(fprintf(uH, "ergo %s %s %s\n", u3r_string(hox),