Software Tools

Do one thing well, and work together.

Archive for the ‘Uncategorized’ Category

How to compile and run Inferno on Ubuntu 14.04

with one comment

Download Inferno from Vita Nuova’s web site.

Create /usr/inferno and make it writable by other.

Expand the inferno tgz file with tar xzf while the current directory is /usr.

Update the file mkconfig to set SYSHOST to Linux, uncomment OBJTYPE=386, and comment out OBJTYPE=$objtype.  Run ./

export PATH=/usr/inferno/Linux/386/bin:$PATH
mk nuke

mk install will fail to find sys/cdefs.h, so add -I/usr/include/x86_64-linux-gnu\ to CFLAGS in mkfiles/mkfile-Linux-386.

mk install will fail to find gnu/stubs-32.h, so run sudo apt-get install libc6-dev-i386 to install 32-bit libraries.

mk install will produce a floating point exception when limbo tries to compile runt.m.  Commenting out the line that sets NaN will avoid the exception.  Instead of trying to find a solution to this problem in the code from 2010, update it with hg pull -uv and hg update to see whether the problem was resolved. (Install mercurial with the command sudo apt-get install mercurial.)  Accept the changed *.dis files.  Resolve conflicts in mkfiles/mkfile-Linux-386, by allowing the new -I option, and deleting the X11R6 include.

hg resolve –mark
hg resolve –all
hg pull -uv # gives no more output

mk install will fail to find X11/Xlib.h, so run sudo apt-get install libx11-dev and libxext-dev to install X11 headers.

mk install will fail to find X11 and Xext, so run sudo apt-get install libx11-6:i386, libxext-dev:i386 to install 32-bit versions of the same.

So we now get far enough to see some code that needs the NaN we earlier removed.

calc.b:135: ‘NaN’ is not a member of ‘Math’ of type Math
calc.b:352: Nan’s value cannot be determined
calc.b:62: cannot index ‘conw’
calc.b:63: cannot index ‘conw’
calc.b:63: cannot index ‘conw’
mk: limbo -I/usr/inferno/module -gw calc.b : exit status=exit(1)

Let’s put it back in and see what happens: we’re back to a floating-point exception, so updating to the most recent version of code didn’t fix it.

Added the keyword volatile and the “=a” output constraint to fpuctl.h:setfcr, per this discussion.

mk nuke, and then mk install appears to complete successfully.

emu wm/wm starts a window manager session within the emulator.



Written by catena

11 June 2014 at 0017

Posted in Uncategorized

Credo example: from lex and c source to cygwin executable, across directories

leave a comment »

This article walks through building a trivial example of lex source
code into C, and then compiling the generated C source code into
object files and an executable in a different directory. The point is
to demonstrate using dodep to generate and customize build scripts
and list dependencies, and credo to execute the build process.

Lines which start with ; are shell commands; lines without are output.
Key commands are displayed in red text.

Starting state

We start with the files lorem, src/dcr.l, src/header.c, src/lex.h,
and an empty obj directory. Each line of lorem ends with a
carriage return (not usually printed), which we want to strip.
header.c is an ordinary C source file to compile and link.
lex.h gives us a local header to look for.

Generate source code

; cd src
; echo flex > dcr.c.lex.env

We first go into the src directory, and set the lex shell variable to flex,
to specify which lexer to use. To demonstrate an unusual feature,
that would be valid across ports to different operating systems,¹
we’ll capture it with this command.
¹ Inferno and Plan 9 store variables by name in the directory /env,
different for each process. This gives it a definite advantage in
capturing dependencies on variables, since we can just list the name
of the shell-variable file as a dependency.

src/dcr.c.lex.env:1: flex

This setting applies (is transformed into a shell variable) when credo
processes the target dcr.c, if dcr.c depends on /env/lex.

; dodep (c lex l c) dcr.c
credo dcr.c

We ask dodep to generate a shell script and list of dependencies with
this command. The content of these files comes from a library,
indexed by the four parameters given before the name of the file we
want to build. In this case, we want to look in the “c” namespace,
at the command “lex”, to translate an “l” file to a “c” file.

The generated dependency list includes the name of the lex source file,
and references to the variables lex and lflags.

src/dcr.c.dep:1: 0 dcr.l
src/dcr.c.dep:2: 0 /env/lex
src/dcr.c.dep:3: 0 /env/lflags

Credo passes the name of its target, the C source file, to the shell script,
which prints the name of the C source file if it was able to create it.

src/ #!/dis/sh
src/ c = $1
src/ (sum l) = `{grep '\.l$' $c^.dep}
src/ if {no $lex} {lex = lex}
src/ if {
src/ flag x +
src/ os -T $lex $lflags $l
src/ mv lex.yy.c $c
src/ } {
src/ echo $c
src/ }

The hosted-Inferno command os calls host-OS commands. Under Cygwin,
it calls Cygwin or Windows commands.

Dodep finally prints a credo command to build the requested target.

; credo dcr.c
credo dcr.l
credo dcr.c
os -T flex dcr.l
mv lex.yy.c dcr.c

Credo builds all its non-/env dependencies in parallel. Once these
are complete, it determines whether the checksum of each file on which
it depends is different than the checksum stored for that file the
last time credo built this target.

This credo command creates a build-avoidance marker file dcr.l.redont,
which tells further runs of credo that the file dcr.l does not need
any processing, so exit early. It calls the host’s flex program,
on the path set when the Inferno environment started, to create the
target file dcr.c.

It updates the check sums in the file dcr.c.dep, to reflect content at
the time of compilation. This means that each target has its own view
of its dependencies, and any change to any file on which it depends,
or a change to the list of files on which it depends, prompts the
target to rebuild.

src/dcr.c.dep:1: 79f9925952d9cfb5a58270c0e2b67691 dcr.l
src/dcr.c.dep:2: 897a779351421523cadbafccdce22efe /env/lex
src/dcr.c.dep:3: 0 /env/lflags

It creates these checksum files to detect any changes to the target’s
dependencies or build script.

src/dcr.c.dep.sum:1: c33129421847b7d897d4e244caf1b8c0 dcr.c.dep

src/ 71d94d651922bd5ff5b543bba52f47d0

It also checksums the target file itself. If credo finds, the next
time it runs, that the current checksum of the target does not match,
then it assumes that the target was changed by hand, and will not
overwrite it.

src/dcr.c.sum:1: 2fed3667f390fd80993e090a7eb92c75 dcr.c

Compile objects and executable

We now have all the source, so we go to the object-file and executable
directory, and ask dodep to provide do and dep files to build dcr.exe.
From the “c”-language toolset, we use “cc” to compile an “o”bject file
into an “exe”cutable.

; cd ../obj
; dodep (c cc o exe) dcr.exe
credo dcr.exe

This time the dodep command created two *.do files, and, instead of a do and dep file for the target dcr.exe.

obj/ #!/dis/sh
obj/ dep = $1
obj/ exe = `{echo $dep | sed 's,\.dep,,'}
obj/ (stem ext o) = `{crext o $exe}
obj/ adddep $exe /env/ars /env/cc /env/cflags /env/ldflags /env/objs
obj/ adddep $exe $o
obj/ adddep $exe `{/lib/do/c/coneed $o} creates the dependency list dcr.exe.dep for the target
dcr.exe by adding a set of credo-specific (ars and objs) and standard
(cc, cflags, and ldflags) shell variables; the primary object file,
named for the executable; and any other object files which the primary
one needs. The tool coneed does this last bit of analysis by compiling
the primary object file, looking for unresolved symbols in available
source code, compiling the source code to make sure, and printing the
set of matching object files.

obj/ #!/dis/sh
obj/ exe = $1
obj/ if {no $cc} {cc = cc}
obj/ if {
obj/ flag x +
obj/ os -T $cc $cflags -o $exe $objs $ars $ldflags
obj/ } {
obj/ echo os -T ./$exe
obj/ }

To gather enough information to compile the executable, credo relays
information from dependencies back to calling targets through *.relay
files, which are shell scripts that set the environment for calling targets.

Finally, to start the build process, we locate the source code,
record which compilation tools to use, and again call credo.

; srcdir = ../src/
; echo cpp-3 > default.cpp.env
; echo -I../src/ > default.cppflags.env
; echo gcc-3 >
; credo dcr.exe
credo dcr.exe.dep
os -T gcc-3 -I../src/ -c ../src/dcr.c
os -T gcc-3 -I../src/ -c ../src/header.c
credo dcr.o.dep
credo dcr.o
credo header.o.dep
credo header.o
credo dcr.exe
os -T gcc-3 -o dcr.exe dcr.o header.o
os -T ./dcr.exe

Credo first runs to find and store the dependencies of
dcr.exe in dcr.exe.dep. dcr.exe.dep is an implicit dependency of dcr.exe,
so credo runs its *.do script automatically.

obj/dcr.exe.dep:1: 0 /env/ars
obj/dcr.exe.dep:2: 131eb9ab2f6a65b34e0158de1b321e3c /env/cc
obj/dcr.exe.dep:3: 0 /env/cflags
obj/dcr.exe.dep:4: 0 /env/ldflags
obj/dcr.exe.dep:5: 84a1a3c306e006dd723bebe9df29ee6c /env/objs
obj/dcr.exe.dep:6: 3f0d90c1c7483ad1805080cf9e48d050 dcr.o
obj/dcr.exe.dep:7: 1db618b791dc87ac0bd5504f69434273 header.o

Coneed uses $srcdir to find dcr.c, and the setting of cppflags in
default.cppflags.env to find lex.h. Once coneed compiles dcr.o,
it finds the unresolved symbol for the header function, finds a
definition of header() in header.c, and compiles header.o to verify
that it defines the symbol. Coneed finds no other unresolved symbols
supplied by other source code in $srcdir (c.f. printf), so it stops.
Coneed uses “dodep (c cc c o)” to compile the source code in $srcdir
into object files in the current directory (obj). This generates
* and * for each source file: those for dcr are shown,
the ones for header are identical.

obj/ #!/dis/sh
obj/ dep = $1
obj/ o = `{echo $dep | sed 's,\.dep,,'}
obj/ (stem ext c) = `{crext c $srcdir^$o}
obj/ adddep $o /env/cc /env/cflags /env/cppflags
obj/ adddep $o $c
obj/ adddep $o `{/lib/do/c/findh $c}

obj/ #!/dis/sh
obj/ o = $1
obj/ (sum c) = `{grep '\.c$' $o^.dep}
obj/ if {no $cc} {cc = cc}
obj/ if {
obj/ flag x +
obj/ os -T $cc $cflags $cppflags -c $c
obj/ } {
obj/ echo 'objs = $objs '^$o > $o^.relay
obj/ }

Before credo runs it runs to generate dcr.o.dep
(header.o likewise). To find the paths to C header files it calls findh,
which gathers header-file #includes from the C source files,
and searches for them in local and system directories using cppflags
and the search list printed by $cpp -v.

obj/dcr.o.dep:1: 131eb9ab2f6a65b34e0158de1b321e3c /env/cc
obj/dcr.o.dep:2: 0 /env/cflags
obj/dcr.o.dep:3: 9134215aef7b4657beb5c4bb7a20d4a1 /env/cppflags
obj/dcr.o.dep:4: 2fed3667f390fd80993e090a7eb92c75 ../src/dcr.c
obj/dcr.o.dep:5: feea1fa232f248baa7a7d07743ee86c4 ../src/lex.h
obj/dcr.o.dep:6: fb584676de41ee148c938983b2338f5b /n/C/cygwin/usr/include/stdio.h
obj/dcr.o.dep:7: f6409b1008743b1866d4ad8e53f925cc /n/C/cygwin/usr/include/string.h
obj/dcr.o.dep:8: 468b1dd86fef03b044dceea020579940 /n/C/cygwin/usr/include/errno.h
obj/dcr.o.dep:9: 4e6678324ba6b69666eba8376069c950 /n/C/cygwin/usr/include/stdlib.h
obj/dcr.o.dep:10: c7575313e03e7c18f8c84a5e13c01118 /n/C/cygwin/usr/include/inttypes.h
obj/dcr.o.dep:11: a8fd5fa102b8f74d1b96c6c345f0e22d /n/C/cygwin/usr/include/unistd.h

obj/header.o.dep:1: 131eb9ab2f6a65b34e0158de1b321e3c /env/cc
obj/header.o.dep:2: 0 /env/cflags
obj/header.o.dep:3: 9134215aef7b4657beb5c4bb7a20d4a1 /env/cppflags
obj/header.o.dep:4: ecd87752a211e69078e6bc37afbb561b ../src/header.c
obj/header.o.dep:5: feea1fa232f248baa7a7d07743ee86c4 ../src/lex.h
obj/header.o.dep:6: fb584676de41ee148c938983b2338f5b /n/C/cygwin/usr/include/stdio.h

At this point credo has the dependencies for dcr.exe, so it works
through them, calling the *.relay files—generated by the object files’
do scripts—to gather object names in $objs.

obj/dcr.o.relay:1: objs = $objs dcr.o

obj/header.o.relay:1: objs = $objs header.o

There’s not much to do since coneed already compiled the object files,
so it links them, and prints an os command to run the executable,
since Inferno can’t directly run a Cygwin executable.

Clean up

To clean up, we remove generated files in the src and obj directories.

; rm -f *.redoing *.redont *.renew *.reold *.sum

This removes all the temporary state files created by credo.
Once this is done credo will rebuild from scratch, and reconstruct
each target’s view of its dependencies.

; rm -f `{lsdo | sed 's,^c?redo ,,'}

This removes all the targets created by do scripts. The lsdo command
(called by credo with no targets) prints credo commands for all the
credo targets in the current directory. For example:

; cd src; credo
credo dcr.c

; cd obj; credo
credo dcr.exe
credo dcr.exe.dep
credo dcr.o
credo dcr.o.dep
credo header.o
credo header.o.dep

Once the targets are removed, credo will unconditionally generate them.

; rm -f *.do *.dep *.relay

This removes all the instructions credo uses to build files.
These may usually be regenerated by dodep, adddep (which adds
to the given target’s dependency list the given files), and
rmdep (which removes the given files).

A single library script is provided to remove the state, target,
and dodep files.

; rm -f *.env

This removes default and per-target environment settings.

Once we remove these sets of files, the directories contain only the
files present in their starting state.

Written by catena

3 July 2011 at 1451

Posted in Uncategorized

Age: absolutely minimal version control

leave a comment »

The timing of this post was inspired by a rant against git by Mike Taylor.

Here’s a version-control system in two rc (Plan 9 shell) scripts. Age copies files (without certain derived files such as objects and archives) to a backup directory under the current directory, and stores in that directory a tgz for distribution. Aged gives you a contextual difference of files changed since your last save. (There’s also little scripts called stardate and monnum that print YYYYMMDD.)

It’s got about none of git’s features, and is woefully inefficient, but it does one thing really well: have a backup when you make a bad change, if you use it regularly. I’ve used this for a few weeks, and it’s Good Enough.

Written by catena

10 May 2010 at 1651

Posted in Uncategorized

nb—search and index notes in files by keyword

leave a comment »

[Download a UTF-8 version of this file.]

nb name search index keyword
nb—search and index notes in files by keyword

nb keyword

nb description search keyword path file line acme
Nb searches for the given keyword in each nbindex file listed in
$HOME/nbindexes.  If it finds a match, nb prints the path, filename,
and line number of the indexed file in the format acme uses to refer to
lines in a file.

nb file format store index line path file line acme nbindexes
This file is an example.  Nb searches all files in the current directory
for lines which begin “^nb ”, and copies them into the file nbindex.
Each match is listed with its filename, and line number, e.g. for acme
to show the line on a right-click of the mouse.  It then adds the
path and filename of the current directory’s nbindex file to the file

By convention I use 1 blank line to separate paragraphs after an nb
line, and 2 blank lines to separate nb lines, but nb doesn’t care about

nb nbindex example search keyword
This is the nbindex file for this file.

	nb.1:1 name search index keyword
	nb.1:5 keyword
	nb.1:8 description search keyword path file line acme
	nb.1:15 file format store index line path file line acme nbindexes
	nb.1:28 nbindex example search keyword
	nb.1:50 source plan9port rc script
	nb.1:70 port plan9port rc shell script grëp
	nb.1:75 author
	nb.1:78 bugs

This is the output of the command “nb keyword”.  It lists the full
path since it may refer to files anywhere in the filesystem.

	/usr/local/plan9/bin/nb.1:1 name search index keyword
	/usr/local/plan9/bin/nb.1:5 keyword
	/usr/local/plan9/bin/nb.1:8 description search keyword path file line acme
	/usr/local/plan9/bin/nb.1:28 nbindex example search keyword

nb source plan9port rc script
flag e +

if(test -r $catalog && ! ~ $1 ''){
	list=`{cat $catalog}
	grëp $* $list | sed 's,nbindex:[0-9]+: ,,'

grep -n '^nb ' * >[2]/dev/null | sed 's,: ?nb +, ,' > nbindex
echo `{pwd}^'/nbindex' >> $catalog
if(~ $TMPDIR ''){
sort -u $catalog > $tmp
mv $tmp $catalog

nb port plan9port rc shell script grëp
Nb in written in plan9port’s rc, but should be straightforward to port
to any shell.  Use grep instead of grëp.

nb author

nb bugs
Nb generates the index after it searches, to present results immediately,
so it does not show changes since its last run.  If you want to see
the latest changes, then run nb with no parameters before you supply a
keyword (e.g. in acme, middle-click on nb after you edit an nb line or
following text).

Written by catena

5 March 2010 at 1434

Posted in Uncategorized

Update Go scanner to accept non-ASCII operators

with one comment

Read the discussion of this change on the golang-nuts mailing list. See this notice in UTF-8 format.

For each line, the scanner accepts, in place of the first operator, any of the remaining operators, and outputs a token whose string (set in $GOROOT/src/go/token/token.go) is the first operator.

! ¬




&= ∧=

&^ ∧¬

&^= ∧¬=




<<= ≪=


== =?



>>= ≫=


^= ⊻=


|= ∨=

|| ⋁

To install, copy $GOROOT/src/pkg/go/scanner/scanner.go to another file.

Replace scanner.go with scanner.go

Run $GOROOT/src/all.bash and check for 0 unexpected errors.

Changes to scanner.go update gofmt, which accepts UTF-8 operators and outputs their ASCII equivalents.  This mkfile production rule uses gofmt as a preprocessor to create a sharable and compilable file.

%.go: %.ℊℴ

cat $stem.ℊℴ | gofmt > $stem.go

See these files for an example of each new operator form in the context of a simple Go program.



Please mail me privately if something doesn’t work with this code, to avoid noise on the golang-nuts list, since we’re no longer discussing officially-released code.

Written by catena

10 February 2010 at 0116

Posted in Uncategorized