bf manual version 0.8.4
_-_-_-_-_-_-_-_-_-_-_-_

This is BogusForth, an obfuscated language based mainly upon forth 
(widely known), created by Charles Moore, and false, another obfuscated 
language by Wouter van Oortmerssen. Many ideas were also taken from TRUE, 
by Dewi. Therefore, thanks to Moore, Wouter and Dewi.

It's GPL! Enjoy!

Antonio Maschio <tbin@libero.it>

Language specs
-_-_-_-_-_-_-_-


1. Notation
-----------

The following stack values are used in commands notation:
 n		a number
[f]		a function
"s"		a string
 d		a number, string or a function
 f		a flag (true/false)
 v		a variable
x*d		a non definite number of data


2. Input strings
----------------

Input strings are evaluated from left to right, just like in forth. 
Any line is 255 characters long; this is not a limitation, since any
command, using the stack, may reside on a single line, and the result 
would be same as multiple commands in a line; 
besides, input is buffered, so if your line is, say, 356 chars long, 
the first 255 will be evaluated as the first command line, and the rest 
as the second.
BEWARE! commands are single chars, and may be divided, but numbers, strings 
comments and functions are not, so they may get split. For practical and
secure input, limit input lines to be not longer than screen monitor 
(80 chars).


3. Entities
-----------

In the following, the bricks of the whole language. 

3.1 
numbers (0-9)

Numbers are only integers (ranging from -2^31 to 2^31-1);
negative numbers must be input with '\' (negate) after them, as in 345\
(see 5.1.3 for the removed H, O and B features, present in the previous
version).
	
3.2 
variables (a-z; A-Z)

they can host numbers, strings and functions; variables names are 
constituted by single letters, but 'a' and 'A' are distinct variables, 
so the programmer may use 26 x 2 = 52 variables. Not much, but a wise 
use of the stack may help. See 4.1.
Variables are initialized to number 0 at start. Anyway, initialize them
by yourself (it may happen that a variable should contain a string,
e.g. for file treatment; in this case a number won't fit).
	
3.3 
strings

they are input enclosing them into double quotes ".." - ( - "s" ).
If you omit the closing ", everything from the first " up to the end of line
will be a string.
Strings are 256 chars long. If you unify two of them (through u, see), 
only the first 256 of the union will be given. The rest will be lost.
Don't despair! I have NEVER used such long strings... have you?

3.4 
comments

they are input enclosing them into curly brackets { }.
If you omit the last }, everything from the first { up to the end of line
will be a string (similar to the // comment of C++). 
But beware: any opening { after the first will be ignored, since the first } 
found will close the first given {.

3.5 
functions
	
they can host a complete command line, or a simple amount of data.
They are input enclosing them into square brackets [..] - ( - [f] ).
Functions may be nested, but they must be on a single line.

3.6 
tests

0	zero - false value (left by tests).
1	one - true value (left by tests). Anyway, any non-zero value is true,
	like in C.

3.7 
conclusions

any other char than those compounding the language is discarded, so
you may over-obfuscate your code by inserting here and there any char,
which will confound the reader (but not the compiler, I hope!).

	
4. Commands
-----------

4.1 
variable treatment

the following commands must be put *JUST* after the variable name.
If a blank or any other char is interposed, they will be treated 
as different commands (see '!' - root and ':' - show stack content).

!	exclamation mark ( d v - ) 
	store a value into a variable, as in 23f! (will store 23 into f).
	TOS will be removed after  that.
	
:	colon ( v - d ) 
	fetch variable content, as in f: (with reference to the previous
	example, will leave 23 on TOS).


4.2 
function command

@ 	at ( [f] - x*d ) 
	execute [f], which may be left on TOS by a direct command, 
	as in ["executed"i.]@ or, more useful after a variable fetching, 
	as in d:@.

4.3 
control flow commands

? 	question mark ( f [f] | f [f1] [f2] - x*d ) 
	if-then-else; in the first form ( f[f]? ) execute [f] if f, 
	in the second ( f[f1][f2]? ) execute [f1] if f, otherwise [f2].

# 	number ( [f1] [f2] - x*d ) 
	while cycle; while [f1] execute [f2]. It's the only cycle admitted, 
	as in false and in TRUE. It would have been easy to implement a 
	form of for..next, but I don't like it much. Maybe in the future...
	
t	letter t ( - ) 
	tear away remaining input line, without parsing it.

4.4 
stack commands

% 	percent ( n - n n ) 
	dup.
	
; 	semi-colon ( n - ) 
	drop.
	
$	dollar ( n1 n2 - n2 n1 ) 
	swap.
	
_	underscore ( n3 n2 n1 - n2 n1 n3 ) 
	rot.
	
r 	letter r ( n1 - n2 ) 
	roll, with control over limits. 0r does nothing; 1r does nothing; 
	2r = $; 3r = _. If n1 is beyond stack depth, does nothing.
	
p	letter p ( n1 - n2 ) 
	pick, with control over limits. 0p does nothing; 1p = %; 2p = over 
	(like in forth, but this specific command is not part of bf).
	
:	colon ( - ) 
	show stack content, leaving it untouched.
	
)	right parenthesis ( x*d - ) 
	empty stack (but maintain variables). In my opinion, good programming 
	should always end with an empty stack, after all calculations are done 
	and results shown, and this command helps in doing this.
	But BEWARE! You should get to a clear stack by program flow, not with it.
	I don't plan to remove it as a command, but it may be.
	
}	right curly bracket ( - ) 
	If used outside a comment, leave on TOS current stack depth, 
	a value between 0 and 255. If you need more stack space, change 
	the value of STACKMAX in bf.h and recompile.
	
4.5 
math commands	

* 	asterisk ( n1 n2 - n1*n2 ) 
	multiplication.
	
+ 	plus ( n1 n2 - n1+n2 ) 
	addition. For string addition see u.
	
- 	hyphen ( n1 n2 - n1-n2 ) 
	subtraction. For substrings, see u.
	
/ 	slash ( n1 n2 - n1/n2 ) 
	integer division.
	
m	letter m ( n1 n2 - n3 ) 
	modulo function. Return remainder of n1/n2; the result is always between
	0 and n2, and so it conforms to math rules, not to the C version of
	the mod() function.
	
^	circumflex accent ( n1 n2 - n3 ) 
	n2th power of n1. Controls are taken over zero base and negative exponent, 
	which would lead to a 1/0 fraction.
	
!	exclamation mark ( n1 n2 - n3 )
	if used not just after a letter, gives the integer n2th root of n1, 
	with control over zero root (which would lead to a 1/0 exponent) 
	and over negative base and even exponent (which would lead to a complex 
	mathematics). 
	It treats odd roots of negative numbers, which exist, but strangely 
	calculators seem not to take care of this option, refusing to calculate 
	e.g. -27^(1/3). Try.
	
\	backslash ( n - -n ) 
	negate number on TOS.
	
g	letter g ( f - ) 
	generate random number between 0 and 32768 if f is True, otherwise 
	set random seed.
	
4.6 
logical commands
These commands work with numbers and strings. logical and, or, not and
xor work with truth values, so if you use them with numbers, 0 will mean
False and any other number will be True.

= 	equal ( d1 d2 - f ) 
	true if d1 = d2 (for strings and function, usual conventions apply).
	
>	greater than ( d1 d2 - f ) 
	true if d1 > d2 (for strings and functions, usual conventions apply).
	
& 	ampersand ( n1 n2 - f ) 
	logical and.
	
| 	vertical bar ( n1 n2 - f ) 
	logical or
	
~ 	tilde ( n - f ) 
	logical not.
	
l	letter l ( n1 n2 - f ) 
	logical xor.
	
4.7 
bitwise commands

a	letter a ( n1 n2 - n3 ) 
	bitwise and.
	
o	letter o ( n1 n2 - n3 ) 
	bitwise or.
	
n	letter n ( n1 - n2 ) 
	bitwise not (1 complement).
	
x	letter x ( n1 n2 - n3 ) 
	bitwise xor.
	
4.8 
input/output commands

i	letter i ( n - ) 
	print TOS (number, string or function).
	
j	letter j ( n1 n2 - ) 
	print number n1 in a field of n2 chars (filled with spaces if number is 
	smaller). If number is longer than n2, n1 is printed with no field.
	
k	letter k ( n1 n2 - ) 
	print number n1 with n2 decimal digits after the dot (useful for 
	printing fixed sized decimal numbers calculated as integers).
	
< 	lesser than ( - "s" ) 
	read input string from keyboard.
	
( 	left parenthesis ( "s" - x*d ) 
	read input stream from file whose name is on TOS. File lines are read 
	sequentially until EOF or an error is met. Stack may result changed, 
	after this operation, so you may ) before launching a file, if you need 
	stack checking. Use the form f( to read and execute buffer file (see f).
			
4.9 
string and char commands

`	grave ( - n ) 
	put on TOS ASCII code of the following char on stream; it's the only 
	command which must be put before its input. If followed by a blank space, 
	puts 32; if followed by a tab, puts 9; if last on stream, assumes next 
	command is a return, so leaves 13. This command always succeeds 
	(and never return '\0').
	- NOTE for Windows users - hit Alt+096 to get this sign if it
	doesn't appear in your keyboard -
	- NOTE for Unix users -  hit <> to get this sign if it 
	doesn't appear in your keyboard -
	
'	single quote ( n - ) 
	emit char whose ASCII code is on TOS. 13' is a CR, 9' is a HT 
	(horizontal tab), 7' is the bell (on some systems, 7' may not work).
	
,	comma ( "s" - n ) 
	convert string on TOS to number, leaving it on TOS. Input numbers 
	with <, (see <).
	
.	period ( - ) 
	emit a Carriage Return (more elegant than 13').
	
e	letter e ( "s1" n - "s2" | n ) 
	extract nth char of string "s" and leave it on TOS. Values of n 
	range from 0 to strlen("s") - 1. If n is >= strlen("s"), return a 
	null string. If negative, return string length.
	
u	letter u ( "s" - n | "s1" "s2" 0 - "s1+s2" | "s1" n1 n2 - "s2" ) 
	it's a multipurpose command. 
	* In its first form, unveils ASCII code of first char of string "s" 
	and leave it on TOS as an integer.
	* If a 0 is left on TOS before u, it tries to join the topmost 
	strings under TOS "s1" and "s2", and will leave them on TOS 
	as a single string. Since strings may not exceed 255, if you try 
	to join two strings whose total length is greater than 255, 
	the resulting string will be truncated.
	* In its third form, if two numbers are left on TOS (the topmost one must
	not be 0), u will leave on TOS the substring s2 whose count starts
	at n1 in s1 and ends at n2 (counting from 0).
	Notice that it's not a limitation having n2 not equal to 0, since
	it has no sense extracting a string from 0 to 0 (being TOS first
	char, simply), or extracting a string from 6 to 0 (backwardly; use
	from 0 to 6 instead, and so n2 is not 0).

4.10
system commands

Some of the following commands are #def driven.
In UNIX systems, commands such pwd and cat are very common and useful.
In Windows they are available only through external software
such as djgpp and mynsys. If you happen to have a working gcc and some
Unix software (ls.exe, pwd.exe, cat.exe and less.exe are needed)
uncomment the #undef WIN32 line in bf.h and recompile. You will
gain the full bf capabilities. See bf.h.
	
h	letter h ( - ) 
	help on system command list.
	
v	letter v ( - ) 
	print vocabulary (with short explanations) by screens.
	
d	letter d ( - ) 
	list directory. Executes "dir" on windows/dos systems, and "ls" on Unix 
	systems. You can change commands (adding options, for example) modifying 
	COMDIR in bf.h for UNIX environments and recompiling.
	
w	letter w ( - ) ONLY FOR UNIX
	print working directory. If you have similar system commands for 
	windows/dos, you may redefine COMDIR for WIN32 environments in bf.h 
	and recompile, uncommenting #undef WIN32. See bf.h.
	
c	letter c ( "s" - ) 
	change working directory to "s". Absolute, relative and mnemonics 
	strings (like ..) may be used.
	This command is inspired to the Unix philosophy, in which every
	attached device is thought as a file. This won't work under Win32.
	This means that you will not be able to change drive (a non-existent
	concept under Unix), and bf will run into its own drive. C'est la vie.
		
b	letter b ( "s" - ) 
	reset buffer file name to "s".
	
f	letter f ( - "s" ) 
	leave on TOS current buffer file name.
	
y	letter y ( "s" - ) 
	yield stack content to file "s". Use fy to yield stack content to
	buffer file.
	
]	right square bracket ( - ) 
	if used outside a function, toggle on/off appending current input line 
	into file ./bf.bf. Use b to change buffer file name (see). If ] is 
	contained in the input line, the char itself won't be written to file.
	
s	letter s ( "s" - ) ONLY FOR UNIX
	show contents of file identified by "s". Execute cat | less.

z	letter z
	toggle on/off debugging option. Debugging option active causes 
	debugging line to be printed. A debugging line is printed
	after each instruction in the form:
	
			[ TOS-2 TOS-1 TOS ] --> next-instr. <--
	
	that is: last 3 top stack elements and next instruction of the input.
	* If next-instr. shows a number, it is the first digit of the number,
	but being a number you know that next step is to recover a number,
	and it doesn't matter if it is long or one-char.
	* If next-instr. shows a " or a [, it means that the next instruction
	is a string- or a function-recovering.
	* In the normal flow, next-instruction shows a char, which is a plain
	bf instruction.
	* If no instruction is contained between the --> <-- markers, it is a
	blank line. 
	* If no markers appear, you have reached the end of line.
	Further work may insert the possibility to write debugging line on
	a file. I'm thinking about it.
	
q	letter q ( n - ) 
	quit interpreter immediately with status n. Of course, commands 
	following q will never be executed, and stack content will be lost. 
	Normal program termination is 0q, abnormal is nq, where n is a 
	programmer's defined error code (the same code is returned to the 
	operating system, for the appropriate measures, if it can manage it).


5. some remarks
---------------

5.1 
missing commands

5.1.1 
You may have noticed that 'lesser than' is missing. But a wise use of 
the stack may replace any test command, with only >, ~ and $. See this:

greater than is				>
lesser than is 				$>  (swap and test again)
lesser than or equal is		>~  (greater not)
greater than or equal is 	$>~ (lesser not)
equal is 					=
not equal is 				=~  (equal not)

Fancy, huh?

5.1.2 

Also, you may have noticed that at present it's impossible to assure 
writing specific string to stdout, if a program is redirected to a file. 
Try the following: write

"Enter your name:"i.<"Hello, "ii.0q

into a file called, say, "greetings.bf", then type:

./bf -q greeting.bf > greetings.out

You will see that the program is waiting for your string, but that the message
has been written to file, not to stdout. If you digit, say

Hugo

the program will end. Look at greetings.out; you will see:

Enter your name:
Hello, Hugo

Of course what preceeds is a false problem. 
In Unix, when you redirect the output, you may redirect the input too. 
Create a file, named Hugo, containing the string Hugo. Then digit

./bf -q greeting.bf < Hugo > greeting.out

and that's all. The program behaves as usual, getting the input from the file
Hugo (which should contain the exact sequence of needed data) and redirecting
the output to greeting.out, in a pure and standard way, from the Unix 
point of view.

5.1.3
Getting back to the comment section (see 3.4), in a certain sense, 
even all capitalized text is considered a comment, since capital letters 
are discarded, unless they are variables. I consider this feature a nice one. 
That's because from version 0.8.4 it's no more possible to input Hex, 
Octal or Binary numbers. Apart from the fact the routine was full of bugs,
(try to input 7FFFH in 0.8.2), it would have retained letters from A to F, 
H and O for this purpose. These letters could have been used neither 
as variables nor as comments. So I deleted this feature.

Never mind! Only Forth and C have a strong need to use other-than-decimal 
numbers, and only if they use memory location or are connected to some
pin (often identified by an hex). bf doesn't. 

Be happy, integer and decimal!

5.1.4
For what about floating point math... well, do we really need it? For such a
funny language? If you want absolutely this feature, well, consider that:
- I could alter getNumber() to get floating point number. It's easy (I've
  done it actually).
- I should use the dot for both CR and floating point. This would led to
  input 0.2 just as 0.2; of course .2 wouldn't work. Is this a mess?
- Really, the whole thing would lead to big math, that would involve 
  at least sin, cos, ln, arcsin, arccos, arctan and so on. 
  I don't really see any usefulness in this, at this point (and, above all,
  I'm over with ASCII chars!!!).

Maybe in the future (actually, floating math is programmed for
version 0.9. This may signify a whole rewriting of a big part of the code,
and maybe of the language).

