diff --git a/Makefile b/Makefile index c94d85fdc..c0ea4e07d 100644 --- a/Makefile +++ b/Makefile @@ -354,7 +354,7 @@ LIBCOMMONMARK=outside/commonmark/build/src/libcmark.a LIBSCRYPT=outside/scrypt/scrypt.a -all: vere +all: urbit .MAKEFILE-VERSION: Makefile .make.conf @echo "Makefile update." @@ -363,7 +363,7 @@ all: vere .make.conf: @echo "# Set custom configuration here, please!" > ".make.conf" -vere: $(BIN)/vere +urbit: $(BIN)/urbit meme: $(BIN)/meme $(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 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) - $(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 -$(BIN)/vere: $(LIBCRE) $(LIBCOMMONMARK) $(VERE_OFILES) $(LIBUV) $(LIBRE2) $(LIBED25519) $(LIBANACHRONISM) $(LIBSCRYPT) - @echo " CCLD $(BIN)/vere" +$(BIN)/urbit: $(LIBCRE) $(LIBCOMMONMARK) $(VERE_OFILES) $(LIBUV) $(LIBRE2) $(LIBED25519) $(LIBANACHRONISM) $(LIBSCRYPT) + @echo " CCLD $(BIN)/urbit" @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 $(BIN)/meme: $(LIBCRE) $(LIBCOMMONMARK) $(MEME_OFILES) $(LIBUV) $(LIBRE2) $(LIBED25519) $(LIBANACHRONISM) $(LIBSCRYPT) @@ -416,24 +416,24 @@ etags: osxpackage: $(RM) -r inst $(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 - cp $(BIN)/vere inst/usr/local/bin + cp $(BIN)/urbit inst/usr/local/bin cp urb/urbit.pill 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: - $(MAKE) $(BIN)/vere LIB=/usr/share/urb + $(MAKE) $(BIN)/urbit LIB=/usr/share/urb debinstall: 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 -R urb/zod $(DESTDIR)/usr/share/urb clean: - $(RM) $(VERE_OFILES) $(BIN)/vere vere.pkg $(VERE_DFILES) + $(RM) $(VERE_OFILES) $(BIN)/urbit urbit.pkg $(VERE_DFILES) distclean: clean $(LIBUV_MAKEFILE) $(MAKE) -C outside/libuv_0.11 distclean diff --git a/demo/commands.txt b/demo/commands.txt new file mode 100644 index 000000000..b3097af41 --- /dev/null +++ b/demo/commands.txt @@ -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 + diff --git a/demo/files/1-ape-tictactoe.hoon b/demo/files/1-ape-tictactoe.hoon new file mode 100644 index 000000000..e418af857 --- /dev/null +++ b/demo/files/1-ape-tictactoe.hoon @@ -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 +<-) :: +-- diff --git a/demo/files/2-ape-tictactoe.hoon b/demo/files/2-ape-tictactoe.hoon new file mode 100644 index 000000000..a3934572e --- /dev/null +++ b/demo/files/2-ape-tictactoe.hoon @@ -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 {}") :: +++ 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 {}") :: + (park(p.u.but %&) %0 `"link to {}") :: +-- diff --git a/demo/files/3-ape-tictactoe.hoon b/demo/files/3-ape-tictactoe.hoon new file mode 100644 index 000000000..42365e72d --- /dev/null +++ b/demo/files/3-ape-tictactoe.hoon @@ -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 {}") :: +++ peer-octo-web :: web peer + |= [from pax=path] =< abet :: + ~& [%peer-web +<] :: + ?^ but (park %2 ~) :: + %+ park(but `[%& src !who.gam]) %2 :: + `"web from {}" :: +++ 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 {}") :: + (park(p.u.but %&) %0 `"link to {}") :: +-- diff --git a/demo/files/mar-octo-game.hoon b/demo/files/mar-octo-game.hoon new file mode 100644 index 000000000..d776a3c4b --- /dev/null +++ b/demo/files/mar-octo-game.hoon @@ -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) ~) + -- +-- diff --git a/demo/files/mar-octo-move.hoon b/demo/files/mar-octo-move.hoon new file mode 100644 index 000000000..ab13eee6b --- /dev/null +++ b/demo/files/mar-octo-move.hoon @@ -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 + -- +-- diff --git a/demo/files/pub-octo-hymn.hoon b/demo/files/pub-octo-hymn.hoon new file mode 100644 index 000000000..526b5f796 --- /dev/null +++ b/demo/files/pub-octo-hymn.hoon @@ -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"); + == +== diff --git a/demo/files/pub-octo-main.css b/demo/files/pub-octo-main.css new file mode 100644 index 000000000..5ea0da7bc --- /dev/null +++ b/demo/files/pub-octo-main.css @@ -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; +} diff --git a/demo/files/pub-octo-main.js b/demo/files/pub-octo-main.js new file mode 100644 index 000000000..b3cc5d121 --- /dev/null +++ b/demo/files/pub-octo-main.js @@ -0,0 +1,62 @@ +$(function() { + $bord = $('#bord') + $whom = $('#whom') + + lett = ["x","o"] + symb = [" ","✕","◯"] + draw = function(state) { + space = function(_state,y,x) { + return "
"+symb[_state]+"
" + } + 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) +}) diff --git a/demo/install1.sh b/demo/install1.sh new file mode 100755 index 000000000..41b08a1d5 --- /dev/null +++ b/demo/install1.sh @@ -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 diff --git a/demo/install2.sh b/demo/install2.sh new file mode 100755 index 000000000..f818c04da --- /dev/null +++ b/demo/install2.sh @@ -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 diff --git a/demo/install3.sh b/demo/install3.sh new file mode 100755 index 000000000..734144344 --- /dev/null +++ b/demo/install3.sh @@ -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 diff --git a/demo/script-1.txt b/demo/script-1.txt new file mode 100644 index 000000000..fdd6cb633 --- /dev/null +++ b/demo/script-1.txt @@ -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) diff --git a/demo/script-2.txt b/demo/script-2.txt new file mode 100644 index 000000000..c6a1d5c38 --- /dev/null +++ b/demo/script-2.txt @@ -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 . + + B opens a browser and points it at , 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 diff --git a/demo/script-3.txt b/demo/script-3.txt new file mode 100644 index 000000000..45e1e88c8 --- /dev/null +++ b/demo/script-3.txt @@ -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 + diff --git a/i/c/motes.h b/i/c/motes.h index e67ce0b21..ff56945fa 100644 --- a/i/c/motes.h +++ b/i/c/motes.h @@ -1121,6 +1121,7 @@ # define c3__veer c3_s4('v','e','e','r') # define c3__vega c3_s4('v','e','g','a') # 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__very c3_s4('v','e','r','y') # define c3__view c3_s4('v','i','e','w') diff --git a/i/n/a.h b/i/n/a.h index d92e28ad4..c29a1cd87 100644 --- a/i/n/a.h +++ b/i/n/a.h @@ -104,11 +104,9 @@ /* u3a_road: contiguous allocation and execution context. */ typedef struct _u3a_road { - struct _u3a_road* par_u; // parent road - - struct _u3a_road* kid_u; // child road list - struct _u3a_road* nex_u; // sibling road - struct _u3a_road* now_u; // current road pointer + u3p(struct _u3a_road) par_p; // parent road + u3p(struct _u3a_road) kid_p; // child road list + u3p(struct _u3a_road) nex_p; // sibling road u3p(c3_w) cap_p; // top of transient region u3p(c3_w) hat_p; // top of durable region diff --git a/i/n/o.h b/i/n/o.h index 7b90e9b27..8591dfee3 100644 --- a/i/n/o.h +++ b/i/n/o.h @@ -23,7 +23,8 @@ u3o_check_corrupt = 0x4, // check: gc memory u3o_check_fatal = 0x8, // check: unrecoverable 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. diff --git a/i/n/u.h b/i/n/u.h index 9eb033ea3..46c9553af 100644 --- a/i/n/u.h +++ b/i/n/u.h @@ -104,5 +104,6 @@ /* u3to(), u3of(): offset/pointer conversion. */ # 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)) diff --git a/i/v/vere.h b/i/v/vere.h index 9acf5ad7c..05f89d2c4 100644 --- a/i/v/vere.h +++ b/i/v/vere.h @@ -521,6 +521,8 @@ c3_c* imp_c; // -I, czar name c3_c* nam_c; // -n, unix hostname 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 fuz_w; // -f, fuzz testing c3_s por_s; // -p, ames port @@ -536,7 +538,8 @@ c3_o pro; // -P, profile c3_o veb; // -v, verbose (inverse of -q) 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 } u3_opts; @@ -791,6 +794,16 @@ void 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. */ void diff --git a/n/a.c b/n/a.c index 9d248b81a..56696c27b 100644 --- a/n/a.c +++ b/n/a.c @@ -967,11 +967,11 @@ _me_copy_south(u3_noun dog) u3a_cell* new_u = (u3a_cell*)(void *)new_w; // printf("south: cell %p to %p\r\n", old_u, new_u); - +#if 0 if ( old_u->mug_w == 0x730e66cc ) { fprintf(stderr, "BAD: take %p\r\n", new_u); } - +#endif new_u->mug_w = old_u->mug_w; // new_u->mug_w = 0; new_u->hed = _me_copy_south_in(old_u->hed); diff --git a/n/j.c b/n/j.c index 0e6db22b2..acc70703a 100644 --- a/n/j.c +++ b/n/j.c @@ -209,8 +209,8 @@ u3j_find(u3_noun bat) return jaw; } - if ( rod_u->par_u ) { - rod_u = rod_u->par_u; + if ( rod_u->par_p ) { + rod_u = u3to(u3_road, rod_u->par_p); } else return u3_none; } diff --git a/n/m.c b/n/m.c index d9db52f6d..f4cbbd922 100644 --- a/n/m.c +++ b/n/m.c @@ -144,7 +144,7 @@ _cm_signal_handle_term(int x) { // 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); } else { @@ -179,7 +179,7 @@ _cm_signal_reset(void) u3R = &u3H->rod_u; u3R->cap_p = u3R->mat_p; u3R->ear_p = 0; - u3R->kid_u = 0; + u3R->kid_p = 0; } /* _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); rod_u = u3R; - while ( rod_u->kid_u ) { + while ( rod_u->kid_p ) { #if 0 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 - tax = u3kb_weld(_cm_stack_recover(rod_u->kid_u), tax); - rod_u = rod_u->kid_u; + tax = u3kb_weld(_cm_stack_recover(u3to(u3_road, rod_u->kid_p)), tax); + 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. */ { - c3_assert(0 == u3R->kid_u); - rod_u->par_u = u3R; - u3R->kid_u = rod_u; + c3_assert(0 == u3R->kid_p); + rod_u->par_p = u3of(u3_road, u3R); + u3R->kid_p = u3of(u3_road, rod_u); } /* Set up the new road. @@ -727,26 +727,26 @@ u3m_leap(c3_w pad_w) void u3m_fall() { - c3_assert(0 != u3R->par_u); + c3_assert(0 != u3R->par_p); #if 0 fprintf(stderr, "fall: from %s %p, to %s %p (cap %p, was %p)\r\n", _(u3a_is_north(u3R)) ? "north" : "south", u3R, _(u3a_is_north(u3R)) ? "north" : "south", - u3R->par_u, + u3to(u3_road, u3R->par_p), u3R->hat_w, u3R->rut_w); #endif /* 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. */ - u3R = u3R->par_u; - u3R->kid_u = 0; + u3R = u3to(u3_road, u3R->par_p); + u3R->kid_p = 0; } /* u3m_hate(): new, integrated leap mechanism (enter). @@ -948,8 +948,8 @@ u3m_soft_run(u3_noun fly, /* Configure the new road. */ { - u3R->ski.flu = u3nc(fly, u3R->par_u->ski.flu); - u3R->pro.don = u3R->par_u->pro.don; + u3R->ski.flu = u3nc(fly, u3to(u3_road, u3R->par_p)->ski.flu); + u3R->pro.don = u3to(u3_road, u3R->par_p)->pro.don; u3R->bug.tax = 0; } u3t_on(coy_o); @@ -1036,8 +1036,8 @@ u3m_soft_esc(u3_noun sam) /* Configure the new road. */ { - u3R->ski.flu = u3t(u3R->par_u->ski.flu); - u3R->pro.don = u3R->par_u->pro.don; + u3R->ski.flu = u3t(u3to(u3_road, u3R->par_p)->ski.flu); + u3R->pro.don = u3to(u3_road, u3R->par_p)->pro.don; u3R->bug.tax = 0; } diff --git a/n/n.c b/n/n.c index 61af0fd41..a41c7634e 100644 --- a/n/n.c +++ b/n/n.c @@ -46,9 +46,11 @@ _n_hint(u3_noun zep, } case c3__slog: { - u3t_off(noc_o); - u3t_slog(hod); - u3t_on(noc_o); + if ( !(u3C.wag_w & u3o_quiet) ) { + u3t_off(noc_o); + u3t_slog(hod); + u3t_on(noc_o); + } return _n_nock_on(bus, nex); } diff --git a/n/t.c b/n/t.c index eeefb0ca3..ff937334b 100644 --- a/n/t.c +++ b/n/t.c @@ -113,8 +113,8 @@ _t_jet_label(u3a_road* rod_u, u3_noun bat) return u3h(u3t(u3t(u3h(cax)))); } - if ( rod_u->par_u ) { - rod_u = rod_u->par_u; + if ( rod_u->par_p ) { + rod_u = u3to(u3_road, rod_u->par_p); } else return u3_none; } @@ -175,7 +175,7 @@ _t_samp_process(u3_road* rod_u) } don = u3t(don); } - rod_u = rod_u->par_u; + rod_u = u3tn(u3_road, rod_u->par_p); } u3z(muf); diff --git a/v/ames.c b/v/ames.c index 391032fcb..b48c1d5d2 100644 --- a/v/ames.c +++ b/v/ames.c @@ -67,6 +67,7 @@ _ames_czar(c3_y imp_y, c3_s* por_s) snprintf(dns_c, 64, "%s.urbit.org", nam_c + 1); // uL(fprintf(uH, "czar %s, dns %s\n", nam_c, dns_c)); + free(nam_c); u3z(nam); diff --git a/v/loop.c b/v/loop.c index 8103518f8..8f4788a58 100644 --- a/v/loop.c +++ b/v/loop.c @@ -691,9 +691,16 @@ u3_lo_lead(void) #endif 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); } + if ( c3y == u3_Host.ops_u.veb ) { + u3_term_ef_verb(); + } + #if 1 _lo_slow(); #endif diff --git a/v/main.c b/v/main.c index 37bafcb34..15fea5f82 100644 --- a/v/main.c +++ b/v/main.c @@ -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 +/* _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. */ 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.pro = 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.mem = c3n; 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 ) { case 'M': { 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); 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': { if ( 0 != strcmp("wtf", optarg) ) { return c3n; @@ -123,7 +145,7 @@ _main_getopt(c3_i argc, c3_c** argv) case 'g': { u3_Host.ops_u.gab = c3y; break; } case 'P': { u3_Host.ops_u.pro = 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 '?': default: { return c3n; @@ -329,6 +351,12 @@ main(c3_i argc, if ( _(u3_Host.ops_u.veb) ) { u3C.wag_w |= u3o_verbose; } + + /* Set quiet flag. + */ + if ( _(u3_Host.ops_u.qui) ) { + u3C.wag_w |= u3o_quiet; + } /* Set dry-run flag. */ @@ -363,6 +391,7 @@ main(c3_i argc, } // u3e_grab("main", u3_none); + // u3_lo_loop(); return 0; diff --git a/v/reck.c b/v/reck.c index 30a21d50a..568c8978d 100644 --- a/v/reck.c +++ b/v/reck.c @@ -365,8 +365,6 @@ u3_reck_kick(u3_noun ovo) if ( (c3n == _reck_kick_spec(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 ( (c3__warn != u3h(u3t(ovo))) && (c3__text != u3h(u3t(ovo))) && @@ -384,9 +382,11 @@ u3_reck_kick(u3_noun ovo) u3nc(c3__flog, u3k(u3t(ovo)))); } else { + u3_noun tox = u3do("spat", u3k(u3h(ovo))); uL(fprintf(uH, "kick: lost %%%s on %s\n", u3r_string(u3h(u3t(ovo))), u3r_string(tox))); + u3z(tox); #if 0 if ( c3__hear == u3h(u3t(ovo)) ) { c3_assert(0); @@ -394,7 +394,6 @@ u3_reck_kick(u3_noun ovo) #endif } #endif - u3z(tox); } u3z(ovo); } diff --git a/v/sist.c b/v/sist.c index b2c29ea83..ff42b650b 100644 --- a/v/sist.c +++ b/v/sist.c @@ -222,9 +222,13 @@ _sist_suck(u3_noun ovo, u3_noun gon) u3_lo_punt(2, u3kb_flop(u3k(u3t(gon)))); // u3_loom_exit(); +#if 1 u3_lo_exit(); exit(1); +#else + u3z(ovo); u3z(gon); +#endif } /* _sist_sing(): replay ovum from the past, time already set. diff --git a/v/term.c b/v/term.c index 7934df5b4..0c2089d9c 100644 --- a/v/term.c +++ b/v/term.c @@ -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. */ void diff --git a/v/unix.c b/v/unix.c index f411838d1..cbf98e58d 100644 --- a/v/unix.c +++ b/v/unix.c @@ -21,6 +21,9 @@ #include "all.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. */ 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. */ static DIR* @@ -137,17 +104,6 @@ _unix_opendir(c3_c* pax_c) 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. */ 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. */ 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. */ 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. */ static u3_weak @@ -1201,6 +1060,134 @@ _unix_hot_lose(u3_uhot* hot_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. */ 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* -_unix_home(u3_noun who) +static void +_unix_save(c3_c* pax_c, u3_atom oat) { - u3_unix* unx_u = &u3_Host.unx_u; - u3_uhot* hot_u; - c3_w who_w[4]; + c3_c* dir = strdup(pax_c); + _unix_mkpath(dirname(dir)); + free(dir); - _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)); + 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); } - return hot_u; -} -#if 0 -/* _unix_desk_sync_udon(): apply udon to existing value. -*/ -static u3_noun -_unix_desk_sync_udon(u3_noun don, u3_noun old) -{ - return u3dc("lump", don, old); + 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); } -#endif /* _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); } +#endif /* _unix_desk_sync_ergo(): sync desk changes to unix. */ @@ -1430,11 +1425,11 @@ _unix_desk_sync_ergo(u3_noun hox, u3_noun can, u3_uhot* hot_u) { -#if 0 +#ifndef ERGO_SYNC u3z(hox); u3z(syd); u3z(lok); u3z(can); #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 uL(fprintf(uH, "ergo %s %s %s\n", u3r_string(hox),