Skip to content

Fundamental specification and an open standard whitepaper for our innovative brainfuck OS and programming environment

License

Notifications You must be signed in to change notification settings

bf-enterprise-solutions/bfosix

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 

Repository files navigation

BFOSIX v2 – (Mostly Informal) Brainfuck Operating System Specification

BFOSIX is a single-(user|process|thread) Brainfuck-based operating system specification. Akin to POSIX, it defines a basic set of primitives (syscalls) for things that a programming language such as Brainfuck needs to rely on the Operating System in.

Syscalls and $

$ is the only command that BFOSIX adds to Brainfuck command set. This is to ensure a clean separation between the programming language and Operating System. Brainfuck should stay minimal, even if used as a full-fledged OS-aware language. $ has two uses:

  • As a syscall-invoking command.
  • As exec-like command to run the code from some file.

Boring things first.

$ as a script execution

If you lay out a file name in memory and invoke $ at the first cell of the name, then $ will

  • Leave the memory and program pointer the same.
  • Immediately execute the Brainfuck code (script thereof) in the chosen file.
  • The memory that the script have altered is left as the script left it after terminating (either with exit or simply reaching the end of the script).
  • Once script finishes running, return to the code that invoked $ and continue running it.

Example of the code: file called “hello”:

++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.

main program:

+[>>++++++++++[>++++++++++<-]>[>+>+>+>+>+<<<<<-]>++++>+>++++++++>++++++++>+++++++++++<<<<$[-]++++++++++.[-]<<<<]

In this example, the main program invokes the script from the file named “hello” (essentially a “Hello World!”-printing program from Wikipedia), outputs a newline and loops. While not immediately useful (unless you want to clutter your terminal), it shows the point – you can now modularize your programs and invoke the code from other files, sharing the memory between them.

Because of this memory sharing, the exec-like usage of $ is significantly different from the POSIX exec: it has no arguments. Thus, scripts invoked by $ should rely of what is in the memory at the moment they are ran. More so: scripts can freely access the memory of the processes that called them. While not exactly a good thing security-wise, this is a feature that allows scripts to look up the “environment” they are running in.

$ as a syscall invokation

In case the cell that $ is invoked on is a cell with the value of less than 32, the $ call is considered to be a syscall. The number of syscalls to have is implementation-dependent. but all the BFOSIX-compliant systems should have at least the syscalls listed below.

Note on the notation

For all the syscalls, a certain notation is used to show memory contents that they require. The rules of this notation are:

  • |0| is a cell. In this case, a cell with a value of zero.
  • |...| is a sequence of cells that I was too lazy to write in full. Imply ranges or whatever makes sense here.
  • |value| is one value in the cell.
  • |0|1|2| is a sequence of cells. In this case, these cells have 0, 1, and 2 in them.
  • |...values| is a sequence of values in a null-terminated sequence of cells.
  • |?value| is an optional value cell. “Optional” means that syscall will work even without it, so one can omit setting such a cell from the syscall setup. If there are several optional cells one after the other, it means that they all can be omitted. Some of them can be omitted too, starting from the rightmost one.
  • |...?values| is an optional null-terminated sequence of cells with certain values in them.
  • |?value(x)| is an optional value that has a default in case it wasn’t provided.
    • |...?filename("a.out")| means that filename is an optional string defaulting to “a.out”.

Examples: |a|0|b|?c|...?d| means “a one-cell value a followed by the zero cell and cell with value b. After those, there can be a cell with value c, and, after it, there can be a null-terminated sequence d.”

Now to syscalls.

Syscalls

exit (code 0)

Action

Stops executing current Brainfuck script/process. Returns to the parent script/process. If there’s no parent process, shuts BFOSIX system down.

Arguments
|0|...?args|

No arguments. Implementations are welcome to add errno and other UNIX-y exit niceties as implementation-dependent args.

Returns
|0|

Nothing, leaves zero (syscall code) intact.

read/recv/write/sendto (code 1)

Arguments
|1|...filename|0|...?flags|

where filename is either a string of text naming the file, an IPv4 address like

|ipv4one(0)|ipv4two(0)|ipv4three(0)|ipv4four(0)|

or IPv6 address like

|ipv6one(0)|ipv6two(0)|ipv6three(0)|ipv6four(0)|ipv6five(0)|ipv6six(0)|ipv6seven(0)|...|ipv6sixteen(0)|

or something else that the implementation could allow, including non-TCP/IP addresses.

Action

Sets the input/output streams of Brainfuck program (the one used by ~,~ and .) to the file/socket named filename. Behavior differs between the cases of file and socket:

  • If filename if a null byte, set input/output streams to the default (stdin / stdout) value.
  • If filename is a name of the file, set the stream to the stream of its contents. When the file end, ~,~ will store the null byte into the memory.
  • If filename is an IP address, connect and listen on it and fetch characters with ~,~ one by one. If the message is over, ~,~ reads a null byte. After this, ~,~ can be invoked again to start listening and reading the next message.
    • Using . on an IP address or other network address should stark a new packet terminated by the null byte.

The flags are implementation-dependent, and may be set to (non-exhaustive list):

  • Set input and output separately.
  • Allow overwriting/appending to the file.
  • Setting the offset into the file.
Returns
|0|

Leaves memory empty.

time (code 2)

Arguments
|2|?year(0 i.e. 1900)|?month(1 i.e. Jan)|?day(1)|?hour(0 i.e. midnight)|?minute(0)|?second(0)|
Action

If at least some of the year, month, day, hour, minute, second are present, set the system time to the respective values and defaults. The year starts counting from 1900, so 173 in the year cell would be 2073, while 255 (the maximum possible cell value for 8-bit implementations) caps the existence of BFOSIX to 2155. Hopefully we’ll get a new specification by then :)

If none of the time cells are set, time fills all of those with the current date and time. In case of the time of writing (Thu, 02 December of 2021, 01:55:49 AM), it would write 121, 12, 2, 1, 55, and 49 to the six cells after the syscall code.

In both cases (no time cells and any of those), syscall cell is erased. In case of some cells being set at the time of the call, they are erased too.

Returns

If called with non-empty arguments, erases all the arguments

|0|

otherwise, returns current date in the format

|2|year|month|day|hour|minute|second|

rand (code 3)

Arguments
|3|...?seed|

No arguments. Implementations are welcome to have an additional seed argument to generate the random value from it.

Action

Put the random value into the cell with the syscall code. It is implementation-dependent whether the random value generation is potato random, pseudo-random, almost random, or absolutely random.

Returns
|rand|

Random number.

Other possible syscalls

Implementations are welcome to introduce new syscalls in case those are considered useful. However, the maximum syscall number should never exceed 32, so that it never interlaces with the area of printable characters and files. Other than that, there are no restrictions on what those syscalls should look like and how they should behave. One can even make their Brainfuck-based OS to be a multi-(user|process|threaded) one, all with the help of additional syscalls.

Implementations can add special files (akin to UNIX /dev/null and /dev/random) that will behave in special ways when read/written to. Those, however, should not replace syscalls like time and rand, they can only add to those.

About

Fundamental specification and an open standard whitepaper for our innovative brainfuck OS and programming environment

Topics

Resources

License

Stars

Watchers

Forks