3.2 Files as IO Spaces

Now that we have a binary file (foo.o) it is time to open it with poke. There are two ways to do that.

One way is to pass the name of the file in the poke invocation. The program will start, open the file, and present you with the REPL, like in:

$ poke foo.o
[…]
(poke)

The other way is to fire up poke without arguments, and then use the .file dot-command to open the file:

$ poke
[…]
(poke) .file foo.o
The current IOS is now `./foo.o'.
(poke)

Note how poke replies to the dot-command, stating that the current IOS is now the file we opened.

You may be wondering, what is this IOS thing? It is an acronym for Input/Output Space, often written IO Space. This is the denomination used to refer to the entities being edited with poke. In this case the IO space being edited is a file, but we will see that is not always the case: poke can also edit other entities such as memory buffers and remote block-oriented devices over the network. For now, let’s keep in mind that IOS, or IO space, refers to the file being edited.

And why “current”? GNU poke is capable of editing several files (more generally, several IO spaces) simultaneously. At any time, one of these files is the “current one”. In our case, the current IO space is the file foo.o, since it is the only file poke knows about:

(poke) .info ios
  Id	Type	Mode	Bias		Size		Name
* 0	FILE	rw	0x00000000#B	0x00000398#B	./foo.o

The command .info ios gives us information about all the IO spaces that are currently open. The first column tells us a positive integer that identifies the IOS. This IO space identifier is unique at any given time. In this example, the id corresponding to foo.o is 0. The second column tells us the type of IO space. The third column tells us that foo.o allows both reading and writing. The fourth column tells us the size of the file, in hexadecimal. The fifth column is the name of the IO space; in this case, it is the path to the file being edited.

You may wonder what is that weird suffix #B. It is a unit, and tells us that the size 0x398 is measured in bytes, i.e. the size of foo.o is 0x398 bytes (or, in decimal, 920 bytes.)

Finally, the asterisk character at the left of the entry for foo.o identifies it as the current IO space. To see this more clearly, let’s open another file:

(poke) .file bar.o
The current IOS is now `./bar.o'.
(poke) .info ios
  Id	Type	Mode	Bias		Size		Name
* 1	FILE	rw	0x00000000#B	0x00000398#B	./bar.o
  0	FILE	rw	0x00000000#B	0x00000398#B	./foo.o

Ah, there we have both foo.o and bar.o. Now the current IO space (the entry featuring the asterisk at the left) is the file that we just opened, bar.o. This is because poke always sets the most recently open file as the current one. We can switch back to foo.o using yet another dot-command, .ios, which gets an IO space as an argument:

(poke) .ios 0
The current IOS is now `./foo.o'.
(poke) .info ios
  Id	Type	Mode	Bias		Size		Name
  1	FILE	rw	0x00000000#B	0x00000398#B	./bar.o
* 0	FILE	rw	0x00000000#B	0x00000398#B	./foo.o

We are back to foo.o. Since we are not really interested in bar.o, let’s close it:

(poke) .close 1
(poke) .info ios
  Id	Type	Mode	Bias		Size		Name
* 0	FILE	rw	0x00000000#B	0x00000398#B	./foo.o

Note how in the examples above we used the IO space identifiers (0 and 1) in order to refer to them. This can be inconvenient, as these ids are not memorable at all. Fortunately it is also possible to refer to an IO space by name using the $<name> construct, like this:

(poke) .ios $<./foo.o>
The current IOS is now `./foo.o'.
(poke) .close $<./bar.o>

Note that the $<name> construct in lenient in the sense that it will accept any non-empty sub string that identifies an existing IO space in an unambiguous way. This is useful in order to avoid having to write annoying paths. For example:

(poke) .file /bin/ls
(poke) .file /bin/cat
(poke) .ios $<ls>
The current IOS is now `/bin/ls'.

Auto completion also works. Try it!