BaCon 3.9.2 documentation

Introduction

BaCon is an acronym for BAsic
CONverter. The BaCon BASIC converter is a tool to convert programs
written in BASIC syntax to C. The resulting C code can be compiled
using generic C compilers like GCC or CC. It can be compiled using a
C++ compiler as well.

BaCon intends to be a programming aid
in creating small tools which can be compiled on different Unix-based
platforms. It tries to revive the days of the good old BASIC.

The BaCon converter passes expressions
and numeric assignments to the C compiler without verification or
modification. Therefore BaCon can be considered a lazy converter:
it relies on the expression parser of the C compiler.

BaCon usage and parameters

To use BaCon, download the converter
and make sure the program has executable rights. The converter can be
used as follows:

bash ./bacon.sh myprog.bac

By default the converter will refer to
'/bin/bash' by itself. It uses a so-called 'shebang'
which allows the program to run standalone provided the executable
rights are set correctly. This way there is no need to execute BaCon
with an explicit use of BASH. So this is valid:

./bacon.sh myprog.bac

Alternatively, different versions of
Kornshell and Zshell can be used also:

mksh ./bacon.sh myprog.bac

zsh ./bacon.sh myprog.bac

All BaCon programs should use the
'.bac' extension. But it is not necessary to provide this extension
for conversion. So BaCon also understands the following syntax:

./bacon.sh myprog

Another possibility is to point to the
URL of a BaCon program hosted by a website. The program will then be
downloaded automatically, after which it is converted:

./bacon.sh
http://www.basic-converter.org/fetch.bac

The BaCon Basic Converter can be
started with the following parameters.

-c: determine which C compiler
should create the binary (defaults to 'gcc')

-l: pass a library to the C linker

-o: pass a compiler option to the
C compiler

-i: the compilation will use an
additional external C include file

-d: determine the directory where
BaCon should store the generated C files (defaults to the current
directory)

-x: extract gettext strings from
generated c sources

-z: allow the usage of lowercase
statements and functions

-a: recreate the BaCon static
archive

-b: defines which archiver program
to use for creating the BaCon archive (defaults to 'ar')

-r: defines the program to index
the objects in the BaCon archive (defaults to 'ranlib')

-p: do not cleanup the generated C
files (default behavior is to delete all generated C files
automatically)

-q: suppress line counting during
conversion and only show summary after conversion

-s: suppress warnings about
semantic errors

-w: store commandline settings in
a configuration file. This file will be used in subsequent
invocations of BaCon (not applicable for the GUI version)

-v: shows the current version of
BaCon

-h: shows an overview of all
possible options on the prompt. Same as the '-?' parameter

The shell script implementation can
convert and compile the BaCon version of BaCon. This will deliver the
binary version of BaCon which has an extremely high conversion
performance. On newer systems, the average conversion rate usually
lies above 10.000 lines per second.

This documentation refers both to the
shell script and binary implementation of BaCon.

Most of the aforementioned options also
can be used programmatically by use of the PRAGMA
keyword.

General syntax

BaCon consists of statements, functions
and expressions. Each line should begin with a statement. A line may
continue onto the next line by using a space and the '\' symbol at
the end of the line. The LET statement may be
omitted, so a line may contain an assignment only. Expressions are
not converted, but are passed unchanged to the C compiler (lazy
conversion).

BaCon does not require line numbers.
More statements per line are accepted. These should be separated by
the colon symbol ':'.

All keywords must be written in
capitals to avoid name clashes with existing C keywords or functions
from libc. Keywords in small letters are considered to be variables
unless the '-z' command line option is specified, in which case BaCon
tries to parse lowercase keywords as if they were written in
capitals. Note that this may lead to unexpected results, for example
if the program uses variable names which happen to be BaCon keywords.

Statements are always written without
using brackets. Functions however must use brackets to enclose their
arguments. Functions always return a value or string, contrary to
subs. Functions created in the BaCon program can be invoked
standalone, meaning that they do not need to appear in an assignment.

Subroutines may be defined using
SUB/ENDSUB and do not return a value. With the
FUNCTON/ENDFUNCTION statements a function can
be defined which does return a value. The return value must be
explicitly stated with the statement RETURN.

The three main variable types in BaCon
are defined as STRING, NUMBER and FLOATING. These are translated to
char*, long and double.

A variable will be declared implicitly
when the variable is used in an assignment (e.g. LET)
or in a statement which assigns a value to a variable. By default,
implicitly declared variables are of 'long' type. This default can be
changed by using the OPTION VARTYPE statement.
Note that implicitly declared variables always have a global scope,
meaning that they are visible to all functions and routines in the
whole program. Variables which are used and implicitly declared
within a SUB or FUNCTION also by default have a global scope. When
declared with the LOCAL statement variables will
have a scope local to the FUNCTION or SUB.

In case of implicit assignments, BaCon
assumes numeric variables to be of long type, unless specified
otherwise with OPTION VARTYPE. Also, it is possible to define a
variable to any other C-type explicitly using the DECLARE
and LOCAL statements.

Next to this, BaCon accepts type
suffixes as well. For example, if a variable name ends with the '$'
symbol, a string variable is assumed. If a variable name ends with
the '#' symbol, a float variable is assumed. If a variable name ends
with the '%' symbol, it is considered to be an integer variable. The
type suffixes also can be used when defining a function name.

Mathematics, variables

The standard C operators for
mathematics can be used, like '+' for addition, '-' for subtraction,
'/' for division and '*' for multiplication. For the binary 'and',
the '&' symbol must be used, and for the binary 'or' use the pipe
symbol '|'. Binary shifts are possible with '>>' and '<<'.

C operator

Meaning

C Operator

Meaning

+

Addition

|

Inclusive or

-

Subtraction

^

Exclusive or

*

Multiplication

>>

Binary shift right

/

Division

<<

Binary shift left

&

Binary and

+=, -=, *=, /=

Invalid in BaCon

The C operators '+=', '-=' and the like
are not valid in BaCon. Use INCR or DECR
instead.

Variable names may be of any length but
may not start with a number or an underscore symbol.

The BETWEEN keyword

When using
equations, it often occurs that a check needs to be performed to see
if a certain value lies within a range. For this purpose, BaCon
accepts the BETWEEN comparison keyword. For example:

IF
5 BETWEEN 0;10 THEN
PRINT "Found"

This
comparison will return TRUE in case the value 5 lies within 0 and 10.
The comparison will include the lower and upper boundary value during
evaluation. Note that the lower and upper values are being separated
by a semicolon. Alternatively, the keyword AND may be used here as
well, though this may lead to confusing constructs when adding more
logical requirements to the same equation.

The BETWEEN
comparison also accepts strings:

IF
"C" BETWEEN "Basic"
AND "Pascal" THEN
PRINT "This is C"

The order
of the mentioned range does not matter, the following code will
deliver the exact same result:

IF
"C" BETWEEN "Pascal"
AND "Basic" THEN
PRINT "This is C"

In case the
boundary values should be excluded, BaCon accepts the optional EXCL
keyword:

IF
variable BETWEEN 7 AND
3 EXCLTHEN PRINT
"Found"

The last
example will print "Found" in case the variable lies within
3 and 7 which are considered to be outside the valid range.

Indexed arrays

Declaration of static arrays

An array will never be declared
implicitly by BaCon, so arrays must be declared explicitly. This can
be done by using the keyword GLOBAL or DECLARE
for arrays which should be globally visible, or LOCAL
for local array variables.

Arrays must be declared in the C
syntax, using square brackets for each dimension. For example, a
local string array must be declared like this: 'LOCAL array$[5]'.
Two-dimensional arrays are written like 'array[5][5]',
three-dimensional arrays like 'array[5][5][5]' and so on.

In BaCon, static numeric arrays can
have all dimensions, but static string arrays cannot have more than
one dimension.

Declaration of dynamic arrays

Also dynamic arrays must be declared
explicitly. To declare a dynamic array, the statements GLOBAL
or LOCAL must be used together with the ARRAY
keyword, which determines the amount of elements. For example, to
declare a dynamic array of 5 integer elements: 'LOCAL array TYPE int
ARRAY 5'.

The difference with a static array is
that the size of a dynamic array can declared using variables, and
that their size can be redimensioned during runtime. The latter can
be achieved with the REDIM statement. This is
only possible for arrays with one dimension.

As with static numeric arrays, also
dynamic numeric arrays can have all dimensions, and dynamic string
arrays cannot have more than one dimension. The syntax to refer to
elements in a dynamic array is the same as the syntax for elements in
a static array.

Dimensions

Static arrays must be declared with
fixed dimensions, meaning that it is not possible to determine the
dimensions of an array using variables or functions, so during
program runtime. The reason for this is that the C compiler needs to
know the array dimensions during compile time. Therefore the
dimensions of an array must be defined with fixed numbers or with
CONST definitions. Also, the size of a static
array cannot be changed afterwards.

Dynamic arrays however can be declared
with variable dimensions, meaning that the size of such an array also
can be expressed by a variable. Furthermore, the size of a one
dimensional dynamic array can be changed afterwards with the REDIM
statement. This statement also works for implicitly created dynamic
arrays in the SPLIT and LOOKUP
statements.

By default, if an array is declared
with 5 elements, then it means that the array elements range from 0
to 4. Element 5 is not part of the array. This behavior can be
changed using the OPTION BASE statement. If
OPTION BASE is set to 1, an array declared with 5 elements will have
a range from 1 to 5.

Passing arrays to functions or subs

In BaCon it is possible to pass
one-dimensional arrays to a function or sub. The caller should simply
use the basename of the array (so without mentioning the dimension of
the array).

When the function or sub argument
mentions the dimension, a local copy of the array is created.

This will modify the original array and
prints the values assigned in the sub.

Returning arrays from functions

In BaCon, it is also possible to return
a one dimensional array from a function. This only works for dynamic
arrays, as the static arrays always use the stack memory assigned to
a function. This means, that when a function is finished, also the
memory for that function is destroyed, together with the variables
and static arrays in that function. Therefore only dynamic arrays can
be returned.

The syntax to return a one dimensional
dynamic array involves two steps: the declaration of the array must
contain the STATIC keyword, and the RETURN argument should only
contain the basename of the array without mentioning the dimensions.
For example:

This example will create a dynamic
array and assign some initial values, after which it is returned from
the function. The target 'my_array' now will contain the values
assigned in the function.

The statements SPLIT,
LOOKUP and MAP also accept
the STATIC keyword, which allows the implicitly created dynamic array
containing results to be returned from a function.

Note that when returning arrays, the
assigned array should have the same dimensions in order to prevent
memory errors.

Associative arrays

Declaration

An associative array is an array of
which the index is determined by a string, instead of a number.
Associative arrays use round brackets '(...)' instead of the square
brackets '[...]' used by normal arrays.

An associative array can use any kind
of string for the index, and it can have an unlimited amount of
elements. The declaration of associative arrays therefore never
mentions the range.

To declare an associative array, the
following syntax applies:

DECLARE
info
ASSOCint

This declares an array containing
integer values. To assign a value, using a random string "abcd"
as example:

info("abcd")
= 1

Similarly, an associative array
containing other types can be declared, for example strings:

DECLARE
txt$ASSOC
STRING

As with other variables, declaring
associative arrays within a function using LOCAL
will ensure a local scope of the array.

An associative array can have any amount of dimension. The indexes in
an associative array should be separated by a comma. For example:

Alternatively, the indexes also can be
specified in a delimited string format, using a single space as
delimiter:

demo$("one
two") = "world"

Note that the OPTION
BASE statement has no impact on associatve arrays.

For the index, it is also possible to
use the STR$ function to convert numbers or
numerical variables to strings:

PRINT
txt$(STR$(123))

Relations,
lookups, keys

In BaCon, it is possible to setup
relations between associative arrays of the same type. This may be
convenient when multiple arrays with the same index need to be set at
once. To setup a relation the RELATE keyword
can be used, e.g:

RELATE
assoc TO other

Now for each index in the array
'assoc', the same index in the array 'other' is set. It also is
possible to copy the contents of one associative array to another.
This can simply be done by using the assignment operator, as follows:

array$()
= other$()

Next to this, the actual index names in
an associative array can be looked up using the LOOKUP
statement. This statement returns a dynamically created array
containing all string indexes. The size of the resulting array is
dynamically declared as it depends on the amount of available
elements. Instead of creating a dynamic array, it is also possible to
return the indexes of an associative array into a delimited string by
using the function OBTAIN$.

To find out if a key already was
defined in the associative array, the function ISKEY
can be used. This function needs the array name and the string
containing the index name, and will return either TRUE or FALSE,
depending on whether the index is defined (TRUE) or not (FALSE).

The function NRKEYS
will return the amount of members in an associative array.

Deleting individual associative array
members can be done by using the FREE statement.
This will leave the associative array insertion order intact. The
FREE statement also can be used to delete a full associative array in
one step.

Lastly, the values of an associative
array can be sorted using the SORT statement. The
actual keys of the array will then be sorted as well, so the array
remains intact. A sort action will actually order the elements of the
associative array in memory. When using LOOKUP or OBTAIN$, the keys
will then appear in a sorted order based on the values of the
associative array.

Basic logic programming

With the current associative array
commands it is possible to perform basic logic programming. Consider
the following Logic program which can be executed with any Prolog
implementation:

Records

Declaration

Records are collections of variables
which belong together. A RECORD has a name by
itself and members of the record can be accessed by using the
<name>.<member> notation. The members should be declared
using the LOCAL statement. For example:

RECORD
recLOCAL valueLOCAL
nr[5]END RECORDrec.value =
99

As soon a record is created, it also
exists as a type. The name of the type always consists of the record
name followed by the '_type' suffix. From then on, it is possible to
declare other variables as being of the same type. To continue with
the same example:

DECLARE
var TYPE rec_type
var.value = 123

Arrays of records

Record definitions also can be created
as static arrays or as dynamic arrays. The size of the static array
is determined during compile time and the data will be stored in the
stack frame of a SUB or FUNCTION. This means that the array data is
lost when the SUB or FUNCTION is ended. Example of a static array
definition:

RECORD
data[10]LOCAL info$END
RECORD

To declare a dynamic array of records,
the keyword ARRAY must be used. The size of a dynamic record array is
determined during runtime, and therefore, can be set with variables
and functions. The data is stored in the heap. The BaCon memory
management will clean up the data when leaving a FUNCTION or SUB.
Example:

RECORD
data ARRAY 10LOCAL
name$[5]LOCAL age[5]END
RECORD

Note that dynamic arrays of records do
not allow members which are dynamic arrays themselves.

Passing records to
functions or subs

To pass a record, simply declare the
variable name with the appropriate record type in the header of the
function or sub. Example code:

Returning records
from functions

In order to return a record from a
function, the record type must be visible to the caller. The below
example declares the record in the main program. The function
declares a variable of the same type and initializes the record to 0.
This initialization is obligatory for string members to work
properly. Then some values are assigned. Lastly, the complete record
is returned to the caller:

Strings by value or by
reference

Strings can be stored by value
or by reference. By value means that a copy of the original
string is stored in a variable. This
happens automatically when when a string variable name
ends with the '$' symbol.

Sometimes it may be necessary to refer
to a string by reference. In such a case, simply declare a variable
name as STRING but omit the '$' at the end. Such a variable will
point to the same memory location as the original string. The
following examples should show the difference between by value and by
reference.

When using string variables by
value:

a$
= "I am here"
b$ = a$
a$ = "Hello
world..."PRINT a$, b$

This will print "Hello
world...I am here".
The variables point to their individual memory areas so they contain
different strings. Now consider the following code:

This will print "Goodbye...Goodbye..."
because the variable 'b' points to the same memory area as 'a$'. (The
optional FORMAT forces the variable 'b' to be printed as a string,
otherwise BaCon assumes that the variable 'b' contains a value.)

Note that as soon an existing string
variable is referred to by a reference variable, the string will not
profit from the optimized high performance string engine anymore.

ASCII, Unicode, UTF8

BaCon is a byte oriented converter.
This means it always will assume that a string consists of a sequence
of ASCII bytes. Though this works fine for plain ASCII strings, it
will cause unexpected results in case of non-Latin languages, like
Chinese or Cyrillic. However, BaCon supports UTF8 encoded strings
also.

In order to work with UTF8 strings,
OPTION UTF8 needs to be enabled. It will put
all string related functions in UTF8 mode at the cost of some
performance loss in string processing.

Next to this option, BaCon also
provides a few functions which relate to UTF8 encoding. The following
functions work independently from OPTION UTF8:

ULEN will
correctly calculate the actual characters based on the binary UTF8
sequence.

ISASCII can
be used to verify if a string only consists of ASCII data.

UTF8$ needs
the Unicode value as argument and returns the corresponding
character depending on environment settings and the current font
type.

UCS needs a
UTF8 character as an argument and returns the corresponding Unicode
value.

Creating and linking to libraries created with BaCon

With Bacon, it is possible to create
libraries. In the world of Unix these are known as shared objects.
The following steps should explain how to create and link to BaCon
libraries.

Step
1: create a library

The below program only contains a
function, which accepts one argument and returns a value.

FUNCTION
bla (NUMBER n)LOCAL
i
i = 5 * nRETURN
iENDFUNCTION

In this example, the program will be
saved as 'libdemo.bac'. Note that the name must begin with the
prefix 'lib'. This is a Unix convention. The linker will search for
library names starting with these three letters.

Step
2: compile the library

The program must be compiled using the
'-f' flag: bacon -f libdemo.bac

This will create a file called
'libdemo.so'.

Step 3: copy library to a
system path

To use the library, it must be located
in a place which is known to the linker. There are several ways to
achieve this. For sake of simplicity, in this example the library
will be copied to a system location. It is common usage to copy
additional libraries to '/usr/local/lib': sudo cp libdemo.so
/usr/local/lib

Step
4: update linker cache

The linker now must become aware that
there is a new library. Update the linker cache with the following
command: sudo ldconfig

Step
5: demonstration program

The following program uses the function
from the new library:

PROTO
bla
x = 5
result =
bla(x)PRINT result

This program first declares the
function 'bla' as prototype, so the BaCon parser will not choke on
this external function. Then the external function is invoked and the
result is printed on the screen.

Step
6: compile and link

Now the program must be compiled with
reference to the library created before. This can be done as follows:
./bacon -l demo program.bac

With the Unix command 'ldd' it will be
visible that the resulting binary indeed has a dependency with the
new library.

When executed, the result of this
program should show 25.

Remarks

In case global dynamic string arrays
are used by the BaCon shared object, then these need to be
initialized prior to using the arrays. This can be done by calling a
special function available in each shared object created in BaCon:
the 'BaCon_init()' function. In case the shared object is compiled by
a GNU C compatible compiler, then this function is executed
automatically.

Creating internationalization files

It is possible to create
internationalized strings for a BaCon program. In order to do so,
OPTION INTERNATIONAL should be enabled in the
beginning of the program. After this, make sure that each
translatable string is surrounded by the INTL$
or NNTL$ function.

Now start BaCon and use the '-x'
option. This will generate a template for the catalog file, provided
that the 'xgettext' utility is available on your platform. The
generated template by default has the same name as your BaCon
program, but with a '.pot' extension.

Then proceed with the template file and
fill in the needed translations, create the PO file as usual and copy
the binary formatted catalog to the base directory of the catalog
files (default: "/usr/share/locale").

The default textdomain and base
directory can be changed with the TEXTDOMAIN
statement.

Step 4: add translations

Step 5: create object file

Again at the command line prompt, run
the 'msgfmt' utility to convert the catalog file to a binary machine
object file. The result will have the same name but with an '.mo'
extension:

#
msgfmt -c -v -o hello.mo hello.po

Step 6: install

Copy the resulting binary formatted
catalog file 'hello.mo' into the correct locale directory. In this
example, the locale used was 'nl_NL'. Therefore, it needs to be
copied to the default textdomain directory '/usr/share/locale'
appended with the locale name, thus: /usr/share/locale/nl_NL. In
there, the subdirectory LC_MESSAGES should contain the binary catalog
file.

#
cp hello.mo /usr/share/locale/nl_NL/LC_MESSAGES/

The TEXTDOMAIN
statement can be used to change the default directory for the catalog
files.

Step 7: setup Unix environment

Finally, the Unix environment needs to
understand that the correct locale must be used. To do so, simply set
the LANG environment variable to the desired locale.

#
export LANG=nl_NL

After this, the BaCon program will show
the translated strings.

Networking

TCP

Using BaCon, it is possible to create
programs which have access to TCP networking. The following small
demonstration shows a client program which fetches a website over
HTTP:

The next program shows how to setup a
TCP server which accepts multiple connections. The main program uses
OPEN FOR SERVER multiple times. At each new
connection the program forks itself and handles the incoming data:

TLS secured network connections

The
previous chapter demonstrated network connections where the data is
transferred over the wire in plain text. However, with the increasing
vulnerabilities in current network traffic, it usually is a good idea
to apply Transport Layer Security (TLS).

BaCon does
not implement a propriety TLS standard by its own. However, it can
make use of existing libraries like OpenSSL. Alternatively, BaCon
also allows other TLS implementations, in case these provide an
OpenSSL compatible API. Examples are the GnuTLS and WolfSSL libraries
but also projects forking from OpenSSL, like BoringSSL and LibreSSL.
Note that currently BaCon supports client side TLS only.

To enable
TLS, simply add OPTION TLS to the program. From then on, new network
connections are considered to be TLS encapsulated:

OPTION
TLSTRUE

This option enables the usage of OpenSSL by default. The presence
of the OpenSSL libraries and header files on the system is required.
BaCon will try to convert the source program and assumes the default
locations of the OpenSSL development files. However, if these reside
at a different location, it is possible to specify their location as
follows:

PRAGMA
TLS openssl INCLUDE
<openssl/ssl.h> LDFLAGS
-lssl -lcrypto

The OPTION TLS statement is always required, but instead of
OpenSSL, it is possible to specify a different library:

PRAGMA
TLSgnutls

This will provide an indication that BaCon should make use of the
development files from the GnuTLS implementation. If these files
should be taken from a special location:

BaCon can use the function CA$ to discover the
certificate authority of the connection, and CN$
to discover the common name. The CIPHER$
function can be used to obtain details on the encryption and the
VERIFY function to verify the validity of the
certificate.

The following small program queries a Mac address API over TLS
using default OpenSSL:

Ramdisks and memory streams

When creating programs which need heavy
I/O towards the hard drive, it may come handy to create a ramdisk for
performance reasons. Basically, a ramdisk is a storage in memory.
While on Unix level administrator rights are required to create such
a disk, BaCon can create an elementary ramdisk during runtime which
is accessible within the program.

First, some amount of memory needs to
be claimed which has to be opened in streaming mode. This returns a
memory pointer which indicates the current position in memory,
similar to a file pointer for files.

Then, the statements GETLINE
and PUTLINE can be used to read and write
lines of data towards the memory storage. For example:

If the ramdisk needs to be read from
the beginning, use MEMREWIND to reposition
the memory pointer. In the next example, a GETLINE retrieves the line
which was stored there:

MEMREWIND
ramdiskGETLINE
text$ FROM
ramdisk

If the option MEMSTREAM was set to
TRUE, BaCon can treat the created ramdisk also as a string variable,
which allows manipulations by using the standard string functions.
The variable used for the memory pointer must be a string variable:

Always make sure that there is enough
memory to perform string changes to the ramdisk. The RESIZE
statement safely can be used to enlarge the claimed memory during
runtime, as this will preserve the data.

The contents of the ramdisk can be
written to disk using PUTBYTE. However, it
must be clear how many bytes need to be written, as the total amount
of memory reserved to the ramdisk may be bigger than the actual
amount of data. The function MEMTELL can be
used in case the memory pointer is positioned at the end of the
ramdisk:

Alternatively, if the ramdisk was
opened with OPTION MEMSTREAM set to TRUE, the string function LEN
also will return the length of the data.

Delimited strings

A delimited string is a string which
can be cut into parts, based on a character or on a set of
characters. An example of such a string is a plain space delimited
line in a textbook, where the words are separated by a whitespace.
Another example is an ASCII file, in which the lines are separated by
a newline. A very famous example of a delimited string is the Comma
Separated Value (CSV) string. From another point of view, a delimited
string also can be looked at as a list of items, which is the basis
of LISP like languages.

The SPLIT
statement can be used to split a string into elements of an array,
based on a delimiter. As with all statements and functions handling
delimited strings, the SPLIT statement will ignore a delimiter when
it occurs between double quotes. Such delimiter is considered to be
part of the string. For example:

One of the resulting members of the
array will contain "with,an"
because the comma is enclosed within double quotes. BaCon will
consider this a piece of text where the characters should be kept
together. The behavior of skipping delimiters within double quotes
can be changed by setting or unsetting OPTION
QUOTED. The JOIN statement can be used to
merge array elements back into one (delimited) string.

Instead of SPLIT, it is possible to use
FOR..IN as well. This statement will subsequently
return the parts of the delimited text into a variable. Example:

FOR
i$ IN "aa bb cc"

In this example, the variable 'i$' will
subsequently have the value 'aa', 'bb' and 'cc' assigned. Also the
FOR statement will skip a delimiter occurring within double quotes.
Note that the OPTION COLLAPSE will prevent
empty results, both for SPLIT and FOR.

It is also possible to return a single
member in a delimited string. This can be achieved with the TOKEN$
function. Note that all element counting is 1-based. The following
returns the 5th member of a space delimited string, being
"e
f". It does not use an optional third parameter,
because for all delimited string processing, BaCon defines the
default delimiter as a single space:

PRINTTOKEN$("a b c d \"e f\" g
h i j", 5)

But this function also works in case
some other delimiter is used. The delimiter must then be specified in
the third optional argument.

PRINTTOKEN$("1,2,3,4,5", 3, ",")

All the functions handling delimited
strings accept such an optional argument. Alternatively, OPTION
DELIM can define the delimiter string which should be used in
subsequent functions. As mentioned, the default value is a single
space.

The function EXPLODE$
will return a delimited string based on a specified amount of
characters:

PRINTEXPLODE$("aabbcc", 1)

The MERGE$
function will do the opposite: merging the elements of a delimited
string to one regular string, again optionally specifying a
delimiter, for example:

PRINTMERGE$("aa,bb,cc", ",")

The ISTOKEN
function can verify if a text occurs as a token in a delimited
string. If so, this function returns the actual position of the
token:

There are also functions to sort the
members in a delimited string (SORT$) and to put
them in reversed order (REV$). With PROPER$
it is possible to capitalize the first letter of each individual
element in a delimited string. The ROTATE$
function rotates the items in a delimited string.

To determine if a string contains a
delimiter at all, the HASDELIM function can
be used, while the DELIM$ function can change
the actual delimiter in a string to some other definition.

If a member still contains double
quotes and escaped double quotes, then this can be flattened out by
using the FLATTEN$ function. This function
will remove double quotes and put escaping one level lower:

PRINTFLATTEN$("\"Hello \\\"
world\"")

Lastly, the function AMOUNT
will count the number of members in a delimited string:

BaCon also has string functions
available to handle delimited strings which use unbalanced
delimiters. These are delimiters which consist of different
characters, or different sets of characters. Examples of such strings
are HTML or XML strings. They can be handled by functions like
INBETWEEN$ and OUTBETWEEN$
very easily. For example, to obtain the title of a website from an
HTML definition:

By default, INBETWEEN$ will perform a
non-greedy match, but the fourth optional argument can be set to
specify a greedy match.

Similarly, the OUTBETWEEN$ function
will return everything but the matched substring, effectively cutting
out a substring based on unbalanced delimiters.

Regular expressions

BaCon can digest POSIX compliant
regular expressions when using the REGEX
function or the string functions EXTRACT$,
REPLACE$ and WALK$. For
this, BaCon relies on the standard libc implementation. However, it
is possible to define a different regular expression engine with the
PRAGMA statement.

For example, to specify the very fast
NFA based regular expression library TRE, the following line must be
added at the top of the program:

PRAGMA
RE tre

This will include the header file from
the TRE library and will link against its shared object. Of course,
the system needs to have the required development files from the TRE
library installed.

BaCon will add the default locations of
all necessary files to the compile flags. In case these files are
kept at a different location, it is possible to define this
explicitly as well:

PRAGMA
RE tre INCLUDE <tre/regex.h>
LDFLAGS -ltre

Next to the TRE library, also the
Oniguruma library can be specified:

PRAGMA
RE onig

When specifying the required
development files:

PRAGMA
RE onig INCLUDE <onigposix.h>
LDFLAGS -lonig

Also the famous PCRE library is
supported:

PRAGMA
RE pcre

The full definition looks like:

PRAGMA
RE pcre INCLUDE <pcreposix.h>
LDFLAGS -lpcreposix

Basically, any regular expression
library with a functional POSIX interface can be specified. This
allows a lot of flexibility when certain features for regular
expression parsing are required. The libraries TRE, Oniguruma and
PCRE do not need a further INCLUDE or LDFLAGS specification if their
development files have their default names and reside at their
default location.

Error trapping, error catching and debugging

BaCon can distinguish between 4 types
of errors.

System errors. These relate to the
environment in which BaCon runs.

Syntax errors. These are detected
during the conversion process.

Compiler errors. These are
generated by the C compiler and passed on to BaCon.

Runtime errors. These can occur
during execution of the program.

When an error occurs, the default
behavior of a BaCon program is to stop. Only in case of runtime
errors, it is possible to let the program handle the error.

In case of statements, the
CATCH GOTO command can jump to a self-defined
error handling function. This is especially convenient when creating
GUI applications, as runtime errors by default appear on the Unix
command prompt.

In case of functions, the
OPTION ERROR must be set to FALSE to prevent
the program from stopping. The program then needs to check the
reserved ERROR variable to handle any
unexpected situation.

Alternatively, it is possible to set a
callback function for both statements and functions. This callback
function can be defined by the CATCH ERROR
statement. It should point to a function with three arguments: the
first argument capturing the statement or function causing the error,
the second the name of the file and the last the line number.

The reserved ERROR
variable contains the number of the last error occurred. A full list
of error numbers can be found in appendix
A. With the ERR$ function a human readable
text for the error number can be retrieved programmatically.

Next to these options, the statement
TRACE ON can set the program in such a way that
it is executed at each keystroke, step-by-step. This way it is
possible to spot the location where the problem occurs. The ESC-key
will then exit the program. To switch of trace mode within a program,
use TRACE OFF.

Also the STOP
statement can be useful in debugging. This will interrupt the
execution of the program and return to the Unix command prompt,
allowing intermediate checks. By using the Unix 'fg' command, or by
sending the CONT signal to the PID of the program, execution can be
resumed.

Using the ASCII editor

BaCon comes with its own built in
editor which will display code using syntax highlighting. The editor
requires an ANSI compliant terminal. To start the editor, simply use
the '-e'
argument and a filename:

#
bacon-eprog.bac

If the file does not exist, then an
empty screen occurs. Pressing the <ESC> button will pop up a
menu down below the screen.

The usual functionality for editing a
text applies. The following special actions are supported:

- To remove a line at once, the key
combination <CTRL>+<DEL> can be used.

- To copy a line of text, the INSERT
key will put the current line of text on the clipboard, and pressing
the INSERT key again will paste it.

Notes on transcompiling

The process of translating a
programming language into another language, and then compiling it, is
also known as transcompiling. BaCon is a Basic to C
translator, or a transcompiler, or transpiler.

When using BaCon, three stages can be
distinguished:

conversion time

compilation time

runtime

It is important to realize that BaCon
commands can function in all these stages. Examples of statements
which have impact the on conversion stage are INCLUDE,
RELATE, USEC, USEH,
WITH and some of the OPTION
arguments. These statements instruct BaCon about the way the Basic
code should be converted.

A statement impacting the compilation
stage is PRAGMA. With this statement it is
possible to influence the behavior of the compiler.

Most other BaCon statements are
effective during runtime. These form the actual program being
executed.

It should be clear that the
aforementioned stages cannot be mixed. For example, it does not make
sense to define the argument for the INCLUDE statement in a string
variable, as the INCLUDE statement is effective during conversion
time, while variables are used during runtime.

Note that except for system errors, the
logic of the error messages basically follows the same structure:
there are syntax errors (conversion time), compiler errors and
runtime errors. The system errors relate to the possibility of using
BaCon itself.

Overview of
BaCon statements and functions

ABS

ABS(x)

Type:
function

Returns the
absolute value of x. This is the value of x without sign. Example
without and with ABS, where the latter always will produce a positive
output:

PRINT
x-y
PRINT ABS(x-y)

ACOS

ACOS(x)

Type:
function

Returns the
calculated arc cosine of x, where x is a value in radians.

ADDRESS

ADDRESS(x)

Type:
function

Returns the
memory address of a variable or function. The ADDRESS function can be
used when passing pointers to imported C functions (see IMPORT).

ALARM

ALARM<sub>, <time>

Type:
statement

Sets a SUB
to be executed in <time> milliseconds. The value '0' will
cancel an alarm. The alarm will interrupt any action the BaCon
program currently is performing; an alarm always has priority.

After the
sub is executed, the program will continue the operation it was doing
when the alarm occurred. Example:

SUB
dinner
PRINT "Dinner time!"
END SUB
ALARM
dinner, 5000

ALIAS

ALIAS<function> TO
<alias>

Type:
statement

Defines an
alias to an existing function or an imported function. Aliases cannot
be created for statements or operators. Example:

ALIAS
"DEC" TO "ConvertToDecimal"
PRINT
ConvertToDecimal("AB1E")

ALIGN$

ALIGN$(string$,
width, type [,indent])

Type:
function

Aligns a
multi-line <string$> over a maximum of <width>
characters. The <type> indicates the kind of alignment to
apply: 0 = left alignment, 1 = right alignment, 2 means center
alignment, and 3 means fill or justify.

The
alignment takes place in three stages. First, if the original text
contains newline characters (0x0a), then these are replaced with a
single space. However, empty lines (double new lines) are preserved,
as well as all other special characters, like a space, tab, carriage
return, non breaking space or a form feed. Therefore, in some cases,
it may be necessary to remove such special characters before using
ALIGN$.

The second
stage will try to find the best spot where to replace the space
character for a new line character (0x0a). This should be done within
the given <width>. If there are multiple spaces then these are
preserved. If OPTION COLLAPSE was set to 'TRUE' then ALIGN$ will
automatically delete redundant spaces.

The third
stage will apply the chosen type of alignment. In case type is 0, 1
or 2, the lines in the final result are padded with a single space
character. In case type is 3, additional spaces are added equally in
between the words of a line. Note that the ALIGN$ function will not
hyphenate words. Lines are being cut at a white space as much as
possible. If a word does not fit in the provided width by itself,
then it will be wrapped around.

The
optional argument <indent> will prepend additional space
characters to each line. Example:

data$
= LOAD$("ascii_data.txt")
PRINT ALIGN$(data$, 40, 0)

When OPTION
UTF8 is enabled, ALIGN$ can handle UTF8 strings correctly as well.
The following example aligns a UTF8 text from the Gutenberg project
at two sides, each line not containing more than 50 characters,
starting 10 positions from the left:

AMOUNT

AMOUNT(string$
[,delimiter$])

Type:
function

Returns the
amount of tokens in a string split by delimiter$. The delimiter$ is
optional. If it is omitted, then the definition from OPTION
DELIM is assumed. When specified, it may consist of multiple
characters. If delimiter$ occurs between double quotes in string$
then it is ignored. Example:

AND

Performs a
logical 'and' between two expressions. For the binary 'and', use the
'&' symbol. Example:

IF
x = 0 AND y = 1 THEN PRINT "Hello"

APPEND

APPENDstring$ TO filename$

Type:
statement

Saves a
string to disk in one step. If the file already exists, the data will
be appended. See BAPPEND for appending binary
files in one step, and OPEN/WRITELN/READLN/CLOSE
to read and write to a file using a filehandle in append mode.
Example:

APPEND
result$ TO "/tmp/more_data.txt"

APPEND$

APPEND$(string$,
pos, token$ [, delimiter$])

Type:
function

Inserts
<token$> into a delimited string$ split by delimiter$, at
position <pos>. The delimiter$ is optional. If it is omitted,
then the definition from OPTION DELIM is
assumed. When specified, it may consist of multiple characters.

If the
<pos> parameter is 0, or is bigger than the amount of members
in <string$>, then <token$> is appended. If the <pos>
parameter is negative, then <string$> will be returned
unmodified.

If
delimiter$ occurs between double quotes in string$, then it is
ignored. This behavior can be changed by setting OPTION
QUOTED to FALSE. See DEL$ to delete members,
and the chapter on delimited string functions
for more information about delimited strings. Example:

PRINT
APPEND$("Rome Amsterdam Kiev Bern Paris London", 2,
"Vienna")

ARGUMENT$

ARGUMENT$

Type:
variable

Reserved
variable containing name of the program and the arguments to the
program. These are all separated by spaces.

If the
CMDLINE function is used then this variable
will contain optional arguments to command line functions.

ASC

ASC(char)

Type:
function

Calculates
the ASCII value of char (opposite of CHR$). See
also UCS for UTF8 characters. Example:

PRINT
ASC("x")

ASIN

ASIN(x)

Type:
function

Returns the
calculated arcsine of x, where x is a value in radians.

ATN

ATN(x)

Type:
function

Returns the
calculated arctangent of x, where x is a value in radians.

PRINT
ATN(RAD(90))

ATN2

ATN2(y,
x)

Type:
function

Returns the
calculated arctangent of y/x. The sign of the arguments is used to
determine the quadrant.

PRINT
ATN2(30, -35)

B64DEC$

B64DEC$(x$)

Type:
function

Returns the
decoded string or data from a BASE64 string. In case of binary data,
the LEN function will correctly provide the amount
of bytes available in the string. Example:

PRINT
B64DEC$("QmFDb24gaXMgZnVu")

Example
where binary PNG data is recovered into a string variable and saved:

B64ENC$

B64ENC$(x$[,
length])

Type:
function

Returns the
encoded string from a regular string or memory area. In case of a
string, the length of the string is the default. In case of a memory
area, the additional <length> argument must specify the amount
of bytes to encode. Examples:

PRINT
B64ENC$("Encode me")
PRINT B64ENC$(mem, 1024)

BAPPEND

BAPPENDdataTO filename$
SIZE amount

Type:
statement

Saves a
memory area with binary data to disk in one step. If the file already
exists, the data will be appended. See APPEND
for appending text files in one step, and OPEN/PUTBYTE/GETBYTE/CLOSE
to read and write to a file using a filehandle. Example:

BAPPEND
mem TO "/home/me/data" SIZE 10

BASENAME$

BASENAME$(filename$
[, flag])

Type:
function

Returns the
filename part of a given full filename. The optional [flag] indicates
the part of the filename to be returned. The values are: 0 = full
filename (default), 1 = filename without extension and 2 = extension
without filename. See also DIRNAME$.

BIN$

BIN$(x)

Type:
function

Calculates
the binary value of x and returns a string with the result. The type
size depends on the setting of OPTION MEMTYPE. If MEMTYPE is set to
char (default), then 8 bits are returned, if it is set to short then
16 bits are returned, etc. See also DEC to convert
back to decimal.

BIT

BIT(x)

Type:
function

This
function returns the value for a bit on position <x>. If x = 0
then it returns 1, if x = 1 then it returns 2, if x = 2 then it
returns 4 and so on.

PRINT
BIT(x)

BLOAD

BLOAD(filename$)

Type:
function

Performs a
load into a memory address of a binary file. The memory address is
returned when the loading was successful. When done with the data,
the memory should be freed with the FREE
statement. See LOAD$ for loading text files in
one step, and OPEN/PUTBYTE/GETBYTE/CLOSE
to read and write to a file using a file handle. Example:

BREAK

The
optional parameter can define to which level the break should take
place in case of nested loops. This parameter should be an integer
value higher than 0. See also CONTINUE to
resume a loop.

BSAVE

BSAVEdataTO filename$
SIZE amount

Type:
statement

Saves a
memory area with binary data to disk in one step. If the file already
exists it is overwritten. The amount must be specified in bytes. See
SAVE for saving text files in one step, and
OPEN/PUTBYTE/GETBYTE/CLOSE
to read and write to a file using a filehandle. Example:

BSAVE
mem TO "/home/me/picture.png" SIZE 12123

BYTELEN

BYTELEN(x$,
y [, z])

Type:
function

Returns the
actual byte length of UTF8 string x$ in case of y characters. This is
a wrapper function which can be used in combination with regular
string functions, allowing correct processing of UTF8 string
sequences. If the optional argument z is set then start counting the
byte length from the right size of string x$. Example:

CA$

CA$(connection)

Type:
function

Returns the
Certificate Authority from the certificate used in the current
network connection. Assumes that TLS has been enabled. See the
chapter on secure network connections for more
details. See also CN$.

CALL

CALL
<sub name> [TO <var>]

Type:
statement

Calls a
subroutine if the sub is defined at the end of the program. With the
optional TO also a function can be invoked which stores the result
value in <var>.

Example:

CALL
fh2celsius(72) TO celsius
PRINT celsius

CATCH

CATCHGOTO <label> | RESET|
ERROR<function>

Type:
statement

The GOTO
keyword sets the error function where the program should jump to if
runtime error checking is enabled with TRAP. This
only is applicable for statements. For an example, see the RESUME
statement.

The ERROR
keyword allows setting a callback function where the program will
jump to in case an error occurs. This works both for statements and
functions provided that OPTION ERROR is set to FALSE. This is to
prevent that erroneous functions will stop the program. The callback
function should have three arguments which will hold the name of the
statement or function, the name of the file and the line number where
the error occurred. Example:

CEIL

Rounds x up
to the nearest integral (integer) number. This function always
returns a float value. See also FLOOR and ROUND.

CHANGE$

CHANGE$(string$,
position, new$ [, delimiter$])

Type:
function

Changes the
token in string$, which is split by delimiter$, at position with
new$. The delimiter$ is optional. If it is omitted, then the
definition from OPTION DELIM is assumed. When
specified, it may consist of multiple characters. If delimiter$
occurs between double quotes in string$ then it is ignored. This
behavior can be changed by setting OPTION QUOTED
to FALSE.

If the
indicated position is outside a valid range, the original string is
returned. Use the FLATTEN$ function to
flatten out the returned token. See also EXCHANGE$,
TOKEN$ and SPLIT.

CHANGEDIR

CHANGEDIR
<directory>

Type:
statement

Changes the
current working directory. Example:

CHANGEDIR
"/tmp/mydir"

CHOP$

CHOP$(x$[,
y$[, z]])

Type:
function

Returns a
string defined in x$ where on both sides <CR>, <NL>,
<TAB> and <SPACE> have been removed. If other characters
need to be chopped then these can be specified in the optional y$.
The optional parameter z defines where the chopping must take place:
0 means on both sides, 1 means chop at the left and 2 means chop at
the right. Examples:

PRINT
CHOP$("bacon", "bn")
PRINT CHOP$("
hello world ", " c, 2)

PRINT
CHOP$("print \"end\"", "\n\r\t " &
CHR$(34))

CHR$

CHR$(x)

Type:
function

Returns the
character belonging to ASCII number x. This function does the
opposite of ASC. The value for x must lie between
0 and 255. See UTF8$ for Unicode values.
Example:

LET
a$ = CHR$(0x23)
PRINT a$

CIPHER$

CIPHER$(connection)

Type:
function

Returns the
description of the encryption methods in use by the current network
connection. Assumes that TLS has been enabled. See the chapter on
secure network connections for more details. See
also CA$ and CN$.

CL$

CL$

Type:
variable

The Clear
Line variable clears the line indicated by the current cursor
position. See also EL$.

CLASS

CLASS <body>ENDCLASS
| END CLASS

Type:
statement

Defines a
class in original C++ code. This code is put unmodified into the
generated global header source file. It is particularly useful when
embedding C++ code into BaCon. See also USEC and
USEH. Example:

CMDLINE

CMDLINE(options$)

Type:
function

Defines the
possible command line options to the current program. The CMDLINE
function returns the ASCII value of each option until all provided
options are parsed, in which case a '-1' is returned. In case an
unknown option is encountered, question mark is returned.

If
<options$> contains a colon, then an extra argument to the
option is required. Such argument will appear in the reserved
variable ARGUMENT$. Example where a program
recognizes the options '-n' and '-f <arg>':

The CONCAT$
function is deprecated but it still is available for compatibility
reasons. It can be used for high performance string concatenation but
care should be taken when using non-BaCon functions as arguments.

Instead,
BaCon uses the '&' symbol as infix string concatenation operator.
This operator is more versatile and allows any kind of concatenation.
The following is the same example using '&':

txt$
= "Help this is " & name$ & " carrying a
strange " & thing$

CONST

CONST
<var> = <value> | <expr>

Type:
statement

Assigns a
value a to a label which cannot be changed during execution of the
program. Consts are globally visible from the point where they are
defined. Example:

CR$

CURDIR$

CURDIR$

Type:
function

Returns the
full path of the current working directory. See also ME$
or REALPATH$.

CURSOR

CURSOR
<ON|OFF>
| <FORWARD|BACK|UP|DOWN>
[x]

Type:
statement

Shows
("on")
or hides ("off")
the cursor in the current ANSI compliant terminal. Also, the cursor
can be moved one position in one of the four directions. Optionally,
the amount of steps to move can be specified. Example:

PRINT
"I am here"
CURSOR DOWN 2
PRINT "...now I am
here"

CUT$

CUT$(string$,
start, end [, delimiter$])

Type:
function

Retrieves
elements from a delimited string$ split by delimiter$, starting at
<start> until <end> inclusive. The delimiter$ is
optional. If it is omitted, then the definition from OPTION
DELIM is assumed. When specified, it may consist of multiple
characters.

If the
<start> parameter is higher than <end>, the result will
be the same as when the parameters were reversed.

If
delimiter$ occurs between double quotes in string$, then it is
ignored. This behavior can be changed by setting OPTION
QUOTED to FALSE. See also HEAD$ and TAIL$,
and the chapter on delimited string functions
for more information about delimited strings. Example:

DATA

DATA
<x, y, z, ...>

Type:
statement

Defines
data. The DATA statement always contains data which is globally
visible. The data can be read with the READ
statement. If more data is read than available, then in case of
numeric data a '0' will be retrieved, and in case of string data an
empty string. To start reading from the beginning again use RESTORE.
Example:

DAY

DAY(x)

Type:
function

Returns the
day of the month (1-31) where x is amount of seconds since January 1,
1970. Example:

PRINT
DAY(NOW)

DEC

DEC(x
[,flag])

Type:
function

Calculates
the decimal value of x, where x should be passed as a string. The
optional flag parameter determines the base to convert from. If flag
= 0 (default) then base is hexadecimal, and if flag = 1 then binary
base is assumed. See also HEX$ and BIN$
for hexadecimal and binary conversions. Example:

PRINT
DEC("AB1E")
PRINT DEC("00010101", 1)

DECLARE

DECLARE
<var>[,var2,var3,...] TYPE|ASSOC
<c-type> | [ARRAY <size>]

Type:
statement

This
statement is similar to the GLOBAL statement
and is available for compatibility reasons.

DECR

DECR<x>[, y]

Type:
statement

Decreases
variable <x> with 1. Optionally, the variable <x> can be
decreased with <y>. Example:

DEG

DEG(x)

Type:
function

Returns the
degree value of x radians. Example:

PRINT
DEG(PI)

DEL$

DEL$(string$,
pos [, delimiter$])

Type:
function

Deletes a
member at position <pos> from a delimited string$ split by
delimiter$. The delimiter$ is optional. If it is omitted, then the
definition from OPTION DELIM is assumed. When
specified, it may consist of multiple characters.

If the
<pos> parameter is smaller than 1 or bigger than the amount of
members in <string$>, then the original string$ is returned.

If
delimiter$ occurs between double quotes in string$, then it is
ignored. This behavior can be changed by setting OPTION
QUOTED to FALSE. See APPEND$ for adding
members, and the chapter on delimited string
functions for more information about delimited strings. Example:

PRINT
DEL$("Rome Amsterdam Kiev Bern Paris London", 2)

DELETE

DELETE
<FILE|DIRECTORY|RECURSIVE>
<x$>

Type:
statement

Deletes a
file with the FILE argument, or an empty directory when using the
DIRECTORY argument. The RECURSIVE argument can delete a directory
containing files. It can also delete a complete directory tree. If an
error occurs then this can be captured by using the CATCH
statement. Example:

DELETE
FILE "/tmp/data.txt"
DELETE RECURSIVE
"/usr/data/stuff"

DELIM$

DELIM$(string$,
old$, new$)

Type:
function

Changes the
delimiter in string$ from old$ to new$. The new delimiter can be of
different size compared to the old delimiter.

If the old
delimiter occurs between double quotes in string$, then it is
ignored. This behavior can be changed by setting OPTION
QUOTED to FALSE. See also the chapter on delimited
string functions for more information about delimited strings.
Example:

DIRNAME$

DO

With
DO/DONE a body of statements can be grouped together. This is useful
in case of special compiler constructs like pragmas. Example:

PRAGMA
omp parallel sections
DO
<...code...>
DONE

DOTIMES

DOTIMES
x
<body>
[BREAK]|[CONTINUE]DONE

Type:
statement

With
DOTIMES/DONE a body of statements can be repeated for a fixed amount
of times without the need for a variable. This is known as an
anonymous loop. As with other loops, it can be prematurely exited by
using BREAK. Also, part of the body can be
skipped by the use of the CONTINUE statement.
See FOR/NEXT, WHILE/WEND and
REPEAT/UNTIL for setting up other types of
loops. Example:

DOTIMES
10
PRINT "Hello world"
DONE

EL$

EL$

Type:
variable

The Erase
Line variable clears the line from the current cursor position
towards the end of the line. See also CL$.

END

END
[value]

Type:
statement

Exits a
program. Optionally, a value can be provided which the program can
return to the shell.

ENDFILE

ENDFILE(filehandle)

Type:
function

Function to
check if EOF on a file opened with <handle> is reached. If the
end of a file is reached, the value '1' is returned, else this
function returns '0'. For an example, see the OPEN
statement.

ENUM

ENUM item1,
item2, item3ENDENUM |END ENUM

Type:
statement

Enumerates
variables automatically. If no value is provided, the enumeration
starts at 0 and will increase with integer numbers. Example:

EPRINT

EQ

Verifies if
x is equal to y. To improve readability it is also possible to use IS
instead. Both the EQ and IS operators only can be used in case of
numerical comparisons. Examples:

IF
q EQ 5 THEN
PRINT "q equals 5"
END IF

BaCon also
accepts a single '=' symbol for comparison. Next to the single '='
also the double '==' can be used. These work both for numerical
comparisons and for string comparisons. See also NE.

IF
b$ = "Hello" THEN
PRINT "world"
END
IF

EQUAL

EQUAL(x$,
y$)

Type:
function

Compares
two strings, and returns 1 if x$ and y$ are equal, or 0 if x$ and y$
are not equal. Use OPTION COMPARE to establish
case insensitive comparison. Example:

IF
EQUAL(a$, "Hello") THEN
PRINT "world"
END
IF

The EQUAL
function is in place for compatibility reasons. The following code
also works:

IF
a$ = "Hello" THEN
PRINT "world"
END
IF

ERR$

ERR$(x)

Type:
function

Returns the
runtime error as a human readable string, identified by x. Example:

PRINT
ERR$(ERROR)

ERROR

ERROR

Type:
variable

This is a
reserved variable, which contains the last error
number. This variable may be reset during runtime.

EVAL

EVAL(x$)

Type:
function

Returns the
evaluated result of a mathematical function in a string. The syntax
for the mathematical function follows the regular C syntax. This
means that the operators + (add), - (subtract), * (multiply), /
(divide), ^ (exponent) and % (modulus) work as usual. More over, the
following C functions from libm are supported: abs, acos, asin, atan,
atan2, ceil, cos, cosh, exp, floor, ln (log), log (log10), log10,
pow, sin, sinh, sqrt, tan and tanh. There are three additional
functions for faculty (fac), combination (ncr) and permutation (npr)
which are supported as well. The constants 'pi' and 'e' can be used
also.

The string
may contain real variables from the BaCon program. These will be
evaluated automatically. Example:

x
= 3
y = 4
PRINT EVAL("x*x
+ y + 5")

EVEN

EVEN(x)

Type:
function

Returns 1
if x is even, else returns 0.

EXCHANGE$

EXCHANGE$(haystack$,
pos1, pos2 [, delimiter$])

Type:
function

Exchanges
the token at pos1 with the token at pos2 in haystack$ split by
delimiter$. The delimiter$ is optional. If it is omitted, then the
definition from OPTION DELIM is assumed. When
specified, it may consist of multiple characters. If delimiter$
occurs between double quotes in haystack$ then it is ignored. This
behavior can be changed by setting OPTION QUOTED
to FALSE.

If one of
the indicated positions is outside a valid range, the original string
is returned. Use the FLATTEN$ function to
flatten out the returned token. See also CHANGE$,
TOKEN$ and SPLIT.
Examples:

Note that
this is just an example to demonstrate the EXCHANGE$ function.
Delimited strings can be sorted using the native SORT$
function.

EXEC$

EXEC$(command$
[, stdin$[, out]])

Type:
function

Executes an
operating system command and returns the result to the BaCon program.
The exit status of the executed command itself is stored in the
reserved variable RETVAL. Optionally, a second
argument may be used to feed to STDIN. Also optionally, a third
argument can be specified to determine whether all output needs to be
captured (0 = default), only stdout (1) or only stderr (2). See
SYSTEM to plainly execute a system command.
Example:

EXIT

Exits a SUB
or FUNCTION prematurely. Note that functions
which are supposed to return a value will return a 0. String
functions will return an empty string.

Also note
that it is allowed to write EXIT SUB or EXIT FUNCTION to improve code
readability.

EXP

EXP(x)

Type:
function

Returns e
(base of natural logarithms) raised to the power of x.

EXPLODE$

EXPLODE$(string$,
length [, delimiter$])

Type:
function

Splits a
string based on <length> characters and returns the result in a
delimited string using the default delimiter. The delimiter$ is
optional. If it is omitted, then the definition from OPTION
DELIM is assumed. When specified, it may consist of multiple
characters.

See also
SPLIT to create an array based on a delimiter,
MERGE$ to join the components of a delimited
string back to a regular string, and the chapter on delimited
string functions for more information about delimited strings.
Example:

PRINT
EXPLODE$("Amsterdam", 1)

EXTRACT$

EXTRACT$(x$,
y$[, flag])

Type:
function

Returns the
string defined in <x$> from which the string mentioned in <y$>
has been removed. The optional flag determines if the <y$>
should be taken as a regular expression where OPTION
COMPARE establishes case insensitive expression matching. See
also REPLACE$.

FALSE

FALSE

Type:
variable

Represents
and returns the value of '0'.

FILEEXISTS

FILEEXISTS(filename)

Type:
function

Verifies if
<filename> exists. If the file exists, this function returns 1.
Else it returns 0. This function also can be used to verify if a
directory exists. If <filename> is a symbolic link, it is
dereferenced.

FILELEN

FILELEN(filename)

Type:
function

Returns the
size of a file identified by <filename>. If an error occurs
this function returns '-1'. The ERR$ statement
can be used to find out the error if TRAP is set
to LOCAL. Example:

length
= FILELEN("/etc/passwd")

FILETIME

FILETIME(filename,
type)

Type:
function

Returns the
timestamp of a file identified by <filename>, depending on the
type of timestamp indicated in <type>. The type can be one of
the following: 0 = access time, 1 = modification time and 2 = status
change time. Example:

FILETYPE

FILETYPE(filename)

Type:
function

Returns the
type of a file identified by <filename>. If an error occurs
this function returns '0'. The ERR$ statement can
be used find out which error if TRAP is set to
LOCAL. The following values may be returned:

Value

Meaning

0

Error or undetermined

1

Regular file

2

Directory

3

Character device

4

Block device

5

Named pipe (FIFO)

6

Symbolic link

7

Socket

FILL$

FILL$(x,
y)

Type:
function

Returns an
<x> amount of character <y>. The value for y must lie
between 0 and 127 in ASCII mode, or between 0 and 1114111 (0x10FFFF)
in case OPTION UTF8 is enabled. Example printing 10 times the
character '@':

PRINT
FILL$(10, ASC("@"))

Example
printing 5 times a smiley character using unicode:

OPTION
UTF8 TRUE
PRINT FILL$(5, 0x1F600)

See also
COUNT to count the amount of times a character
occurs in a string.

FIRST$

FIRST$(string$,
amount [, delimiter$])

Type:
function

Retrieves
the remaining elements except the last <amount> from a
delimited <string$> split by delimiter$. The delimiter$ is
optional. If it is omitted, then the definition from OPTION
DELIM is assumed. When specified, it may consist of multiple
characters.

If no
delimiter is present in the string, this function will return the
full <string$>.

If
delimiter$ occurs between double quotes in string$, then it is
ignored. This behavior can be changed by setting OPTION
QUOTED to FALSE.

See also
TAIL$ to obtain elements counting from the end
from the delimited string, and HEAD$ to obtain
elements counting from the start. Refer to the chapter on delimited
string functions for more information about delimited strings.
Example:

FLATTEN$

FLATTEN$(txt$
[, groupingchar$])

Type:
function

Flattens
out a string where the double quote symbol is used to group parts of
the string together. Instead of the double quote symbol a different
character can be specified (optional). See also UNFLATTEN$
for the reverse operation. Examples:

FOR

With
FOR/NEXT a body of statements can be repeated a fixed amount of
times.

In the
first usage the variable x will be increased (to) or decreased
(downto) until y with 1, unless a STEP is specified. Example:

FOR
x = 1 TO 10 STEP 0.5
PRINT x
NEXT

In the
second usage of FOR, the variable <var$> will be assigned the
space delimited strings mentioned in source$. Instead of a space
delimiter, some other delimiter can be specified after the STEP
keyword. The delimiter can consist of multiple characters. If the
<delimiter$> occurs in between double quotes, then it is
skipped until FOR finds the next one. This behavior can be changed by
setting OPTION QUOTED to FALSE.

To prevent
empty results, OPTION COLLAPSE can be set to
TRUE (or 1). See also SPLIT to create an array
of delimited strings.

Example:

OPTION
COLLAPSE TRUE
FOR x$ IN "Hello cruel world"
PRINT
x$
NEXT

FOR
y$ IN "1,2,\"3,4\",5" STEP ","
PRINT
y$
NEXT

FORK

FORK<child>
[ENDFORK[x]] | [END FORK [x]]

Type:
function

Duplicate
the current running program in memory. If the return value is 0, then
we're in the child process. If the child process needs an explicit
exit then ENDFORK can be used.

If the
return value > 0, then we are in the parent process; the actual
value is the process ID of the spawned child.

If the
return value < 0, then an error has occurred. See also REAP
to detect and cleanup child processes which have ended, or SIGNAL
to prevent occurring zombie processes altogether. Example:

FUNCTION

Defines a
function. The variables within a function are visible globally,
unless declared with the LOCAL statement.
Instead of the Bacon types STRING, NUMBER and FLOATING for the
incoming arguments, also regular C-types can be used. If no type is
specified, then BaCon will recognize the argument type from the
variable suffix. In case no suffix is available, plain NUMBER type is
assumed. With VAR a variable amount of arguments
can be defined.

A FUNCTION
always returns a value or a string, this should explicitly be
specified with the RETURN statement. If the
FUNCTION returns a string, then the function name should end with a
'$' to indicate a string by value. Function names also may end with
the '#' or '%' type suffix, to force a float or integer return type.

Furthermore,
it is also possible to explicitly define the type of the return value
using the TYPE keyword.

GETBYTE

GETBYTE
<memory> FROM <handle> [CHUNK x] [SIZE
y]

Type:
statement

Retrieves
binary data into a memory area from a either a file or a device
identified by handle, with optional amount of <x> bytes
depending on OPTION MEMTYPE (default amount of
bytes = 1). Also optionally, the actual amount retrieved can be
stored in variable <y>. Use PUTBYTE to
write binary data.

GETENVIRON$

Returns the
value of the environment variable 'var$'. If the environment variable
does not exist, this function returns an empty string. See SETENVIRON
to set an environment variable.

GETFILE

GETFILE
<var> FROM <dirhandle>

Type:
statement

Reads a
file from an opened directory. Subsequent reads return the files in
the directory. If there are no more files then an empty string is
returned. Refer to the OPEN statement for an
example on usage.

GETKEY

GETKEY

Type:
function

Returns a
key from the keyboard without waiting for <RETURN>-key. See
also INPUT and WAIT.
Example:

PRINT
"Press <escape> to exit now..."
key = GETKEY
IF
key = 27 THEN
END
END IF

GETLINE

GETLINE
<variable$> FROM <handle>

Type:
statement

Reads a
line of data from a memory area identified by <handle> into a
string variable. The memory area can be opened in streaming mode
using the the OPEN statement (see also the
chapter on ramdisks and memory streams). A
line of text is read until the next newline character. Example:

GETX / GETY

Returns the
current x and y position of the cursor. An ANSI compliant terminal is
required. See GOTOXY to set the cursor
position.

GLOBAL

GLOBAL
<var>[,var2,var3,...] [TYPE]|ASSOC
<c-type> | [ARRAY <size>]

Type:
statement

Explicitly
declares a variable to a C-type. The ASSOC keyword is used to declare
associative arrays. This is always a global declaration, meaning that
variables declared with the GLOBAL keyword are visible in each part
of the program. Use LOCAL for local
declarations.

The ARRAY
keyword is used to define a dynamic array,
which can be resized with REDIM at a later stage
in the program.

Optionally,
within a SUB or FUNCTION
it is possible to use GLOBAL in combination with RECORD
to define a record variable which is visible globally.

Multiple
variables of the same type can be declared at once, using a comma
separated list. In case of pointer variables the asterisk should be
attached to the variable name:

GLOBAL
x, y, z TYPE int
GLOBAL *s, *t TYPE long

GOSUB

GOSUB
<label>

Type:
statement

Jumps to a
label defined elsewhere in the program (see also the LABEL
statement). When a RETURN is encountered, the
program will return to the last invoked GOSUB and continue from
there. Note that a SUB or FUNCTION
also limits the scope of the GOSUB; it cannot jump outside. Example:

PRINT
"Where are you?"
GOSUB there
PRINT
"Finished."
END
LABEL there
PRINT "In
a submarine!"
RETURN

GOTO

GOTO
<label>

Type:
statement

Jumps to a
label defined elsewhere in the program. Note that a SUB
or FUNCTION limits the scope of the GOTO; it
cannot jump outside. See also the LABEL
statement.

GOTOXY

GOTOXY
x, y

Type:
statement

Puts cursor
to position x,y where 1,1 is the upper left of the terminal screen.
An ANSI compliant terminal is required. Example:

HASDELIM

Determines
whether the string contains a delimiter or not. If the delimiter is
not present, FALSE (0) is returned. Otherwise this function returns
the position of the first delimiter in the string.

The
delimiter$ is optional. If it is omitted, then the definition from
OPTION DELIM is assumed. When specified, it may
consist of multiple characters. If delimiter$ occurs between double
quotes in string$ then it is ignored. Refer to the chapter on
delimited string functions for more
information about delimited strings.

HASH

Returns a
64bit hash from a string$. The hash algorithm used is based on the
Fowler-Noll-Vo algorithm (FNV1a). Example:

PRINT
HASH("Hello world") FORMAT "%lud\n"

HEAD$

HEAD$(string$,
amount [, delimiter$])

Type:
function

Retrieves
the first <amount> elements from a delimited string$ split by
delimiter$. The delimiter$ is optional. If it is omitted, then the
definition from OPTION DELIM is assumed. When
specified, it may consist of multiple characters.

If
delimiter$ occurs between double quotes in string$, then it is
ignored. This behavior can be changed by setting OPTION
QUOTED to FALSE.

See also
LAST$ to obtain the remaining elements, and
TAIL$ to obtain elements counting from the end
of the delimited string. Refer to the chapter on delimited
string functions for more information about delimited strings.
Example:

HEX$

HEX$(x)

Type:
function

Calculates
the hexadecimal value of x. Returns a string with the result. See
also DEC to convert back to decimal.

HOST$

HOST$(name$)

Type:
function

When name$
contains a hostname this function returns the corresponding IP
address. If name$ contains an IP address the corresponding hostname
is returned. If the name or IP address cannot be resolved an error is
generated. Examples:

PRINT
HOST$("www.google.com")
PRINT HOST$("127.0.0.1")

HOSTNAME$

HOSTNAME$()

Type:
function

Retrieves
the actual hostname of the current system where the program is
running. Example:

PRINT
"My hostname is: ", HOSTNAME$

HOUR

HOUR(x)

Type:
function

Returns the
hour (0-23) where x is the amount of seconds since January 1, 1970.

IF

Execute
<body> if <expression> is true. If <expression> is
not true then run the optional ELSE body. Multiple IF's can be
written with ELIF. The IF construction should end with ENDIF or END
IF or FI. Example:

a
= 0
IF a > 10 THEN
PRINT "This is
strange:"
PRINT "a is bigger than
10"
ELSE
PRINT "a is smaller than 10"
END
IF

The IF
statement also allows comparing strings. The textual order is
determined by the standard ASCII table. As a result, capital letters,
which occur in the ASCII table before the small letters, are
considered to be 'smaller' than regular letters.

If only one
function or statement has to be executed, then the if-statement also
can be used without a body. For example:

IF
age > 18 THEN PRINT "You are an adult"
ELSE INPUT
"Your age: ", age

It is not
allowed to mix an IF without a body and an ELSE which contains a
body, or v.v. For example, the following is not allowed:

IF
year > 1969 THEN PRINT "You are younger"
ELSE
PRINT
"You are older"
ENDIF

IIF / IIF$

IIF(expression,
true, false)
IIF$(expression,
true, false)

Type:
function

The inline
IF behaves similar to a regular IF, except that it is used as a
function. The first argument contains the expression to be evaluated,
the second argument will be returned when the expression is true, and
the last will be returned when the expression is false.

The inline
IF function also allows comparing strings. The textual order is
determined by the standard ASCII table. As a result, capital letters,
which occur in the ASCII table before the small letters, are
considered to be 'smaller' than regular letters.

If the
returned values are numeric, a plain IIF must be used. If strings are
returned, then IIF$ should be used. Examples:

IMPORT

Imports a
function from a C library defining the type of return value.
Optionally, the type of arguments can be specified. Also optionally
it is possible to define an alias under which the imported function
will be known to BaCon.

When the
library name is 'NULL', a function will be imported from the program
itself. In such situation, the ALIAS keyword is obligatory. Note that
the program must be compiled with a linker flag like
'-export-dynamic' (GCC) or '-rdynamic' (TCC) to make the target
function visible for IMPORT.

An imported
library can also be closed afterwards by using CLOSE
LIBRARY. This will unload any symbols from the current program
and release the library.

INBETWEEN$

INBETWEEN$(haystack$,
lm$, rm$ [,greedy])

Type:
function

This
function returns a substring from haystack$, delimited by lm$ on the
left and rm$ on the right. The delimiters may contain multiple
characters. They are not part of the returned result. The greedy
parameter is optional and specifies if rm$ should indicate the most
right match. See also OUTBETWEEN$. Example
usage:

INCLUDE

INCLUDE
<filename>[, func1, func2, ...]

Type:
statement

Adds a
external BaCon file to current program. Includes may be nested. The
file name extension may be omitted. Optionally, it is possible to
specify which particular functions in the included file need to be
added. Examples:

INCLUDE
"beep.bac"
INCLUDE "canvas"
INCLUDE
"hug", INIT, WINDOW, DISPLAY

INCR

INCR<x>[, y]

Type:
statement

Increases
variable <x> with 1. Optionally, the variable <x> can be
increased with <y>.

INPUT

INPUT
[text[, ... ,]<variable[$]>

Type:
statement

Interactive
input from the user. If the variable ends with a '$' then the input
is considered to be a string. Otherwise it will be treated as
numeric. Example:

INPUT
a$
PRINT "You entered the following: ", a$

The
input-statement also can print text. The input variable always must
be present at the end of the line. Example:

INPUT
"What is your age? ", age
PRINT "You probably
were born in ", YEAR(NOW) - age

The INPUT
statement by nature is a blocking statement. However, it can be used
for capturing data from STDIN as well. The INPUT statement will
return immediately if STDIN has no data. In such situation, a string
variable will be empty and a numeric variable will be 0.

Note that
INPUT always will chop off a trailing newline from text captured into
a string variable, if there is any.

The OPTION
INPUT parameter can be used to define where INPUT should cut off the
incoming stream from STDIN. This is especially useful in CGI
programs, for example:

OPTION
INPUT CHR$(4)
INPUT data$

INSERT$

INSERT$(source$,
x, string$)

Type:
function

Inserts the
string$ into source$ at position <x>. The letters in source$
starting from position <x> are pushed forward. If x <= 1
then string$ is prepended to source$. If position > length of
source$ then string$ is appended to source$. Example:

PRINT
INSERT$("Hello world", 7, "cruel ")

INSTR

INSTR(haystack$,
needle$ [,z])

Type:
function

Returns the
position where needle$ begins in haystack$, optionally starting at
position z. If not found then this function returns the value '0'.
See also TALLY to count the occurrences of
needle$.

INSTRREV

INSTRREV(haystack$,
needle$ [,z])

Type:
function

Returns the
position where needle$ begins in haystack$, but start searching from
the end of haystack$, optionally at position z also counting from the
end. The result is counted from the beginning of haystack$. If not
found then this function returns the value '0'.

INTL$

INTL$(x$)

Type:
function

Specifies
that <x$> should be taken into account for
internationalization. All strings which are surrounded by INTL$ will
be candidate for the template catalog file. This file is created when
BaCon is executed with the '-x' switch. See also the chapter about
internationalization and
the TEXTDOMAIN statement.

ISASCII

ISASCII(string$)

Type:
function

Returns
TRUE (1) if <string$> only contains ASCII data. If not, FALSE
(0) is returned. See also TOASCII$. Example:

PRINT
ISASCII("hello world")

ISFALSE

ISFALSE(x)

Type:
function

Verifies if
x is equal to 0.

ISKEY

ISKEY(array,
string$)

Type:
function

Returns
TRUE (1) if <string$> is defined as a key in the associative
<array>. If not, FALSE (0) is returned. See also NRKEYS.
Example:

ISTOKEN

ISTOKEN(string$,
token$ [, delimiter$])

Type:
function

Verifies if
the <token$> occurs in a delimited <string$>. The
delimiter$ is optional. If it is omitted, then the definition from
OPTION DELIM is assumed. When specified, it may
consist of multiple characters.

If
delimiter$ occurs between double quotes in string$, then it is
ignored. This behavior can be changed by setting OPTION
QUOTED to FALSE.

If token$
was found in string$, then this function returns the actual position
of the token in the delimited string, counting from the left.
Otherwise it returns '0'. See also TOKEN$.
Example:

ISTRUE

ISTRUE(x)

Type:
function

Verifies if
x is not equal to 0.

ISUTF8

ISUTF8(string$)

Type:
function

Returns
TRUE (1) if <string$> is compliant with UTF8 encoding. If not,
FALSE (0) is returned. Note that also random binary data can
accidentally be compliant to UTF8 and that ASCII data always is
compliant to UTF8. See also ISASCII. Example:

PRINT
ISUTF8("Después mañana voy para mi casa")

JOIN

JOIN
<array> [BY <sub>] TO <string> SIZE
<variable>

Type:
statement

This
statement can join elements of a one dimensional string array into a
single string. The optional argument in BY defines the delimiter
string in between the array elements. If BY is omitted, then no
delimiter is put in between the concatenated array elements. The
result is stored in the <string> argument mentioned by the TO
keyword. The total amount of array elements to be joined must be
defined in SIZE. See also SPLIT to do the
opposite. Example:

LABEL

Defines a
label which can be jumped to by using a GOTO,
GOSUB or CATCH GOTO
statement. Also RESTORE may refer to a label.
A label may not contain spaces.

LAST$

LAST$(string$,
amount [, delimiter$])

Type:
function

Retrieves
the remaining elements except the first <amount> from a
delimited string$ split by delimiter$. The delimiter$ is optional. If
it is omitted, then the definition from OPTION
DELIM is assumed. When specified, it may consist of multiple
characters.

If no
delimiter is present in the string, this function will return the
full <string$>.

If
delimiter$ occurs between double quotes in string$, then it is
ignored. This behavior can be changed by setting OPTION
QUOTED to FALSE. See also HEAD$ to get the
first element(s), and the chapter on delimited
string functions for more information about delimited strings.
Example:

LEFT$

LEN

Returns the
length of ASCII string x$. If OPTION UTF8 is enabled, then the LEN
function will return the length of UTF8 formatted strings correctly
as well. See also ULEN.

LET

LET
<var> = <value> | <expr>

Type:
statement

Assigns a
value or result from an expression to a variable. The LET statement
may be omitted. Example:

LET
a = 10

LINENO

LINENO

Type:
variable

Contains
the current line number of the program. This variable mainly is used
for debugging purposes.

LOAD$

LOAD$(filename$)

Type:
function

Returns a
string with the content of the specified text file in one step. See
BLOAD for loading binary files in one step, and
OPEN/WRITELN/READLN/CLOSE
to read and write to a file using a filehandle. Example:

LOCAL

This
statement only has sense within functions, subroutines or records. It
defines a local variable <var> with C type <type> which
will not be visible to other functions, subroutines or records, nor
to the main program.

If the TYPE
keyword is omitted then variables are assumed to be of 'long' type.
If TYPE is omitted and the variablename ends with a '$' then the
variable will be a string.

The ARRAY
keyword is used to define a dynamic array,
which can be resized with REDIM at a later stage
in the program.

Multiple
variables of the same type can be declared at once, using a comma
separated list. In case of pointer variables the asterisk should be
attached to the variable name:

LOCAL
x, y, z TYPE int
LOCAL *s, *t TYPE long

LOG

LOG(x)

Type:
function

Returns the
natural logarithm of x.

LOOKUP

LOOKUP
<assoc> TO <array> SIZE <variable>
[STATIC]

Type:
statement

Retrieves
all index names created in an associative array. The results are
stored in <array>. As it sometimes is unknown how many elements
this resulting array will contain, the array should not be declared
explicitly. Instead, LOOKUP will declare the result array
dynamically.

If LOOKUP
is being used in a function or sub, then <array> will have a
local scope. Else <array> will be visible globally, and can be
accessed within all functions and subs.

The total
amount of elements created in this array is stored in <variable>.
This variable can be declared explicitly using LOCAL
or GLOBAL. See also OBTAIN$
to store index names into a delimited string. Example:

The
optional STATIC keyword allows the created <array> to be
returned from a function.

MAKEDIR

MAKEDIR
<directory>

Type:
statement

Creates an
empty directory. Parent directories are created implicitly. If the
directory already exists then it is recreated. Errors like write
permissions, disk quota issues and so on can be captured with CATCH.
Example:

MAKEDIR
"/tmp/mydir/is/here"

MAP

Performs a
mapping of a function towards one or more arrays, storing the results
in another array. All arrays shall have one dimension. The target
array can be declared previously with the DECLARE
or LOCAL statement. Using LOCAL in combination
with the optional STATIC keyword, the array is created so it can be
returned from a function. However, if there is no explicit previous
declaration, then the MAP statement will declare the target array
implicitly. The STATIC keyword can be used here as well.

When the
target array is declared implicitly, the following logic applies: if
MAP is being used in a function or sub, then the target <array>
will have a local scope. Else <array> will be visible globally,
and can be accessed within all functions and subs.

The
<function> can either be defined by DEF FN,
or it can point to a regular function. Only the function name should
be provided, not the arguments. Note that the amount of arguments
must be the same as the amount of arrays to which the <function>
is mapped. Example:

In this
example, the first 5 elements of array1 and array2 are used for the
'addition' function. The results are stored in the array 'result'.
See also SUM for adding members within the same
array.

String
arrays are supported as well:

word$
= "Hello world this is a program"
DEF FN func(x$) =
LEN(x$)
SPLIT word$ TO letter$ SIZE total
MAP letter$ BY
func TO new SIZE total

Here, each
word is put into an array, after which the length of the individual
words is being calculated. The results are then stored in another
array.

MAX / MAX$

MAX(x,
y)
MAX$(x$, y$)

Type:
function

Returns the
maximum value of two numbers or two strings. In case of strings, this
function will follow the ASCII table to determine the 'maximum'
string. This means that small letters, which occur in the ASCII table
after capital letters, will have priority. Example:

PRINT
MAX(3, PI)
PRINT MAX$("hello", "HELLO")

MAXNUM

MAXNUM(type)

Type:
function

This
function returns the maximum value possible for a certain type.
Example:

PRINT
MAXNUM(short)
PRINT MAXNUM(long) FORMAT "%ld\n"

MAXRANDOM

MAXRANDOM

Type:
variable

Reserved
variable which contains the maximum value RND can
generate. The actual value may vary on different operating systems.

ME$

ME$

Type:
function

Returns the
full path of the current active program. See also CURDIR$
and REALPATH$.

MEMCHECK

MEMCHECK(memory
address)

Type:
function

Verifies if
<memory address> is accessible, in which case a '1' is
returned. If not, this function returns a '0'. Example:

IF
MEMCHECK(mem) THEN POKE mem, 1234

MEMORY

MEMORY(x)

Type:
function

Claims
memory of x size, returning a handle to the address where the memory
block resides. Use FREE to release the memory.
Note that OPTION MEMTYPE can influence the type
of memory created. The following example creates a memory area to
store integers:

OPTION
MEMTYPE int
area = MEMORY(100)

Effectively,
this will provide a memory area of 100 times the length of an
integer.

MEMREWIND

MEMREWIND
<handle>

Type:
statement

Returns to
the beginning of a memory area opened with <handle>.

MEMTELL

MEMTELL(handle)

Type:
function

Returns the
current position in the memory area opened with <handle>.

MERGE$

MERGE$(string$
[, delimiter$])

Type:
function

Merges the
components of a delimited string to a regular string. The delimiter$
is optional. If it is omitted, then the definition from OPTION
DELIM is assumed. When specified, it may consist of multiple
characters.

MID$

MID$(x$,
y, [z])

Type:
function

Returns z
characters starting at position y in x$. If y is a negative number,
then start counting the position from the end of x$. The parameter
'z' is optional. When this parameter is 0, negative or omitted, then
everything from position 'y' until the end of the string is returned.
Example:

MIN / MIN$

MIN(x,
y)
MIN$(x$, y$)

Type:
function

Returns the
minimum value of two numbers or two strings. In case of strings, this
function will follow the ASCII table to determine the 'minimum'
string. This means that capital letters, which occur in the ASCII
table before the small letters, will have priority. Example:

PRINT
MIN(3, PI)
PRINT MIN$("hello", "HELLO")

MINUTE

MINUTE(x)

Type:
function

Returns the
minute (0-59) where x is amount of seconds since January 1, 1970.

MOD

MOD(x,
y)

Type:
function

Returns the
modulo of x divided by y.

MONTH

MONTH(x)

Type:
function

Returns the
month (1-12) in a year, where x is the amount of seconds since
January 1, 1970.

MONTH$

MONTH$(x)

Type:
function

Returns the
month of the year as string in the system's locale ("January",
"February", etc), where x is the amount of seconds since
January 1, 1970.

MYPID

MYPID

Type:
function

Returns the
process ID of the current running program.

NE

x NE
y

Type:
operator

Checks if x
and y are not equal. Instead, ISNOT can be used as well to improve
code readability. The NE and ISNOT operators only work for numerical
comparisons.

Next to
these, BaCon also accepts the '!=' and '<>' constructs for
comparison. These work both for numerical and string comparisons. See
also EQ.

NL$

NL$

Type:
variable

Represents
the New Line as a string.

NNTL$

NNTL$(x$,
y$, value)

Type:
function

Specifies
that <x$> should be taken into account for
internationalization. This is a variation to INTL$.
With NNTL$ singularities and multitudes can be specified, which are
candidate for the template catalog file. This file is created when
BaCon is executed with the '-x' switch. See also TEXTDOMAIN
and INTL$ and the chapter on internationalization.
Example:

OBTAIN$

OBTAIN$(assoc$
[,delimiter$])

Type:
function

Retrieves
all index names from an associative array and returns a delimited
string split by delimiter$. Multiple indexes in the same element are
returned space separated. The delimiter$ is optional. If it is
omitted, then the definition from OPTION DELIM
is assumed. When specified, it may consist of multiple characters.

See the
chapter on delimited string functions for
more information about delimited strings. See also LOOKUP
to store index names from an associative array into a regular array.
Example:

PRINT
OBTAIN$(AssocArray)

ODD

ODD(x)

Type:
Function

Returns 1
if x is odd, else returns 0.

ON

ON x
GOTOlabel1
[,label2[, label<x>]]

Type:
statement

Jump to a
label based on the value of x. When x is 1 then the first label is
chosen, when x is 2 the second label and so on. When x has a higher
value than the available labels this statement is ignored. Example:

OPEN

When used
with READING, WRITING, APPENDING or READWRITE, this statement opens a
file assigning a handle to it. The READING keyword opens a file for
read-only, the WRITING for writing, APPENDING to append data and
READWRITE opens a file both for reading and writing. Example:

OPEN
"data.txt" FOR READING AS myfile
WHILE
NOT(ENDFILE(myfile)) DO
READLN txt$ FROM myfile
IF
NOT(ENDFILE(myfile)) THEN
PRINT
txt$
ENDIF
WEND
CLOSE FILE myfile

When used
with DIRECTORY a directory is opened as a stream. Subsequent reads
will return the files in the directory. Example:

When used
with SERVER the program starts as a server to accept incoming network
connections. When invoked multiple times in TCP mode using the same
host and port, OPEN SERVER will not create a new socket, but accept
another incoming connection. Instead of specifying an IP address,
also the Unix wildcard '*' can be used to listen to all interfaces.
See also OPTION NETWORK to set the network
protocol.

OPEN
"*:51000" FOR SERVER AS myserver
WHILE
NOT(EQUAL(LEFT$(dat$, 4), "quit")) DO
RECEIVE dat$
FROM myserver
PRINT "Found: ", dat$
WEND
CLOSE
SERVER myserver

Sets an
option to define the behavior of the compiled BaCon program. It is
recommended to use this statement in the beginning of the program, to
avoid unexpected results.

The
BASE argument determines the lower bound of arrays. By default the
lower bound is set to 0. Note that this setting also has impact on
the array returned by the SPLIT and LOOKUP
statements. It has no impact on arrays which assign their values
statically at the moment of declaration.

The COMPARE argument defines if string comparisons in the IF
and IIF/IIF$ statements and in the BETWEEN
operator and also in regular expressions with REPLACE$,
EXTRACT$ and REGEX
should be case sensitive (0) or not (1). The default is case
sensitive (0).

The
SOCKET argument defines the timeout for setting up a socket to an IP
address. Default value is 5 seconds.

The
NETWORK argument defines the type of protocol: TCP, UDP, BROADCAST,
MULTICAST or SCTP. When MULTICAST is selected also an optional value
for TTL can be specified. When SCTP is selected an optional value
for the amount of streams can be specified. Default setting for this
option is: TCP. Default value for TTL is 1. Default amount of SCTP
streams is 1.

The
MEMSTREAM argument allows the handle created by the OPEN
FOR MEMORY statement to be used as a string variable (1).
Default value is 0.

The
MEMTYPE argument defines the type of memory to be used by POKE,
PEEK, MEMORY, RESIZE,
PUTBYTE, GETBYTE,
COPY, ROL and ROR.
Default value is 'char' (1 byte). Any valid C type can be used here,
for example 'float', 'unsigned int', 'long' etc.

The
COLLAPSE argument specifies if the results of the SPLIT
and FOR..IN statements and of the delimited
string functions may contain empty results (0) in case the
separator occurs as a sequence in the target string, or not (1).
Default value is 0.

The
STARTPOINT argument has impact on the way the INSTRREV
function returns its results. When set to 1, the result of the
INSTRREV function is counted from the end of the string. Default
value is 0 (counting from the beginning of the string).

The
DEVICE argument determines the way a device or file is opened in the
OPEN FOR DEVICE statement. By default BaCon uses
the following open mode: O_RDWR|O_NOCTTY|O_SYNC. Other common Unix
open modes are O_APPEND, O_ASYNC, O_CREAT, O_EXCL, O_NONBLOCK and
O_TRUNC. Please refer to the open manpage for more details on the
open modes.

The
PARSE argument defines if BaCon should allow non-BaCon code. It can
be used to embed foreign functions from external C libraries. Use
with care, as this option accepts any random piece of text. Errors
only will popup during compile time, which may be hard to
troubleshoot. The default value is 1.

The
FRAMEWORK option is used in case of linking to MacOSX frameworks
like Cocoa. This option allows multiple frameworks separated by a
comma. For example: PRAGMA FRAMEWORK COCOA.

The
VARTYPE option defines the default variable type in case of implicit
declarations. The default value for this option is: long.

The
QUOTED argument defines whether text delimiters appearing between
double quotes should be skipped (1) or not (0). The default is to
skip delimiters between double quotes (1).

The DQ
argument defines the symbol for OPTION QUOTED. This is a numeric
ASCII value. Default value is 34 (double quotes).

The UTF8 argument enables all BaCon string functions to process text
in UTF8 format correctly. The default is to process text as ASCII
(0).

The DELIM argument defines the delimiter string when processing
delimited strings. It always should be provided as a static string
literal. The default value is a single space "
".

The
BREAK argument prevents and disables the use of BREAK statements in
generated C code. The default is to allow BREAK statement (TRUE).

The
EXPLICIT argument enforces the declaration of all variables used in
a program. The default value is 0 (FALSE), so no variable
declaration is enforced.

The
INPUT argument defines where the stream of input characters from
STDIN should be cut off. By default, INPUT returns when a newline is
encountered. The default value is "\n".

The
ERROR argument sets whether or not a program will exit as soon a
runtime error occurs. The default is TRUE (exit upon error). If set
to FALSE, the program must take care of error handling by itself,
and setting an error callback will be possible. See also the chapter
on error catching for more
information.

The
PROPER argument sets whether or not the PROPER$
function should leave the items in a delimited string intact or not.
The default value is FALSE, causing the PROPER$ function to
lowercase the remainder of each item.

The
TLS argument enables network connections to be TLS encapsulated. See
the chapter on secure network connections for
more details. The default value is FALSE.

OR

x OR
y

Type:
operator

Performs a
logical or between x and y. For the binary or, use the '|' symbol.

OS$

OS$

Type:
function

Function
which returns the name and machine of the current Operating System.

OUTBETWEEN$

OUTBETWEEN$(haystack$,
lm$, rm$ [,greedy])

Type:
function

This
function returns haystack$ where the substring delimited by lm$ on
the left and rm$ on the right is cut out. The delimiters may contain
multiple characters. They are not part of the returned result. The
greedy parameter is optional and specifies if rm$ should indicate the
most right match. See also INSERT$ to insert a
string and INBETWEEN$ to return the
delimited substring. Example usage:

PEEK

Returns a
value stored at memory address x. The type of the returned value can
be determined with OPTION MEMTYPE.

PI

PI

Type:
variable

Reserved
variable containing the number for PI: 3.14159265358979323846.

POKE

POKE
<x>, <y> [SIZE range]

Type:
statement

Stores a
value <y> at memory address <x>. The optional SIZE
keyword can be used to store the value <y> in a complete range
of addresses starting from address <x>. Use PEEK
to retrieve a value from a memory address. Use OPTION
MEMTYPE to determine the actual size of the type to store.
Examples:

POW

PRAGMA

Instead of
passing command line arguments to influence the behavior of the
compiler, it is also possible to define these arguments
programmatically. Mostly these arguments are used when embedding
variables or library dependent structures into BaCon code. When no
valid option to PRAGMA is provided, BaCon will translate to the plain
compiler directive '#pragma'. Example when SDL code is included in
the BaCon program:

PRINT

Prints a
numeric value, text, variable or result from expression to standard
output. As with most BASICs, the PRINT statement may be abbreviated
using the '?' symbol. A semicolon at the end of the line prevents
printing a newline. For printing to stderr, see EPRINT.
Examples:

PRINT
"This line does ";
PRINT "end here: ";
PRINT
linenr + 2

Multiple
arguments maybe used but they must be separated with a comma.
Examples:

The FORMAT
argument is optional and can be used to specify different types in
the PRINT argument. The syntax of FORMAT is similar to the printf
argument in C. Example:

PRINT
"My age is ", 42, " years which is ", 12 + 30
FORMAT "%s%d%s%d\n"

The result
also can be printed to a string variable. This can also be done in
combination with FORMAT. To achieve this, use the keyword TO.
Optionally, the total amount of resulting characters can be provided
with the SIZE keyword. If no size is given, BaCon will use its
default internal buffer size (512 characters).

PROPER$

Capitalizes
the first letter of all elements in a delimited string split by
delimiter$. By default, other letters are put to lowercase. This
behavior can be altered by setting OPTION PROPER.

The
delimiter$ is optional. If it is omitted, then the definition from
OPTION DELIM is assumed. When specified, it may
consist of multiple characters.

If
delimiter$ occurs between double quotes in string$, then it is
ignored. This behavior can be changed by setting OPTION
QUOTED to FALSE. See the chapter on delimited
string functions for more information about delimited strings.
Example:

PRINT
PROPER$("hEllO crUEl wOrLd")

PROTO

Defines a
foreign function so it is accepted by the BaCon parser. Multiple
function names may be mentioned, but these should be separated by a
comma. Optionally, PROTO accepts an alias which can be used instead
of the original function name. Also, PROTO can define a c-type to
define the type of return value for a foreign function.

During
compilation the BaCon program must explicitly be linked with an
external library to resolve the function name. See also OPTION
PARSE to allow foreign functions unconditionally. Examples:

PULL

PULL
x

Type:
statement

Puts a
value from the internal stack into variable <x>. The argument
must be a variable. The stack will decrease to the next available
value.

If the
internal stack has reached its last value, subsequent PULL's will
retrieve this last value. If no value has been pushed before, a PULL
will deliver 0 for numeric values and an empty string for string
values. See PUSH to push values to the stack.

PUSH

PUSH
<x>|<expression>

Type:
statement

Pushes a
value <x> or expression to the internal stack. There is no
limit to the amount of values which can be put onto the stack other
than the available memory. The principle of the stack is Last In,
First Out.

PUTBYTE

PUTBYTE
<memory> TO <handle> [CHUNK x] [SIZE
y]

Type:
statement

Store
binary data from a memory area to either a file or a device
identified by handle, with an optional amount of <x> bytes,
depending on OPTION MEMTYPE (default amount of
bytes = 1). Also optionally, the actual amount stored can be captured
in variable <y>.

This
statement is the inverse of GETBYTE, refer to
this command for an example.

PUTLINE

PUTLINE
"text"|<variable$> TO <handle>

Type:
statement

Write a
line of string data to a memory area identified by handle. The line
will be terminated by a newline character. The memory area must be
set in streaming mode first using OPEN (see also
the chapter on ramdisks and memory streams).
Example:

RAD

RAD(x)

Type:
function

Returns the
radian value of x degrees. Example:

PRINT
RAD(45)

RANDOM

RANDOM
(x)

Type:
function

This is a
convenience function to generate a random integer number between 0
and x - 1. See also RND for more flexibility in
creating random numbers. Example creating a random number between 1
and 100:

READLN

Reads a
line of ASCII data from a file identified by <handle> into
variable <var>. See the GETBYTE
statement to read binary data. Example:

READLN
txt$ FROM myfile

REALPATH$

REALPATH$(filename$)

Type:
function

Returns the
absolute full path and name of a given filename. Symbolic links are
resolved as well as relative references like '../'. See also CURDIR$.

REAP

REAP(pid)

Type:
function

After a
forked process has ended, it can turn into a so-called 'zombie'
process. This function can remove such process from the process list,
using the process ID as an argument. When the value -1 is used as
argument, REAP will remove any zombie child process.

The return
value of REAP indicates the process ID of the process which was
removed from the process list successfully. If the return value is 0,
then no child process has finished yet, and no process ID has been
removed. When the return value is -1, an error has occurred (a common
mistake is providing a wrong process ID value).

This
function does not pause and returns immediately. For an example,
refer to FORK.

RECEIVE

RECEIVE
<var> FROM <handle> [CHUNK <chunksize>]
[SIZE <amount>]

Type:
statement

Reads data
from a network location identified by handle into a string variable
or memory area. Subsequent reads return more data until the network
buffer is empty. The chunk size can be determined with the optional
CHUNK keyword. In case of TLS connections, it is recommended to use a
multitude of 16k for the chunk size.

The amount
of bytes actually received can be retrieved by using the optional
SIZE keyword. If the amount of bytes received is 0, then the other
side has closed the connection in an orderly fashion. In such a
situation the network connection needs to be reopened. Example:

RECORD

Defines a
record <var> with members. If the record is defined in the main
program, it automatically will be visible globally. If the record is
defined within a function, the record will have a local scope,
meaning that it is only visible within that function. To declare a
global record in a function, use the DECLARE
or GLOBAL keyword.

The members
of a record should be defined using the LOCAL
statement and can be accessed with the 'var.member' notation. See the
chapter on records for more details on the
usage of records. Also refer to WITH for
assigning values to multiple members at the same time. Example:

REDIM

REDIM
<var> TO <size>

Type:
statement

Redimensions
a one dimensional dynamic array to a new size. The contents of the
array will be preserved. If the array becomes smaller then the
elements at the end of the array will be cleared. The dynamic array
has to be declared previously using DECLARE or
LOCAL. Example:

REDIM
a$ TO 20

REGEX

REGEX
(txt$, expr$)

Type:
function

Applies a
POSIX Extended Regular
Expression expr$ to the string txt$. If the expression matches,
the position of the first match is returned. If not, this function
returns '0'. The length of the last match is returned in the reserved
variable REGLEN.

Use OPTION
COMPARE to set case sensitive matching. Note that this function
does not support non-greedy matching. See the chapter on regular
expressions to specify different regular expression engines for
more flexibility. Examples:

REGLEN

RELATE

RELATE
<assocA> TO <assocB>[, assocC, ...]

Type:
statement

This
statement creates a relation between associative arrays. Effectively
this will result into duplication of settings; an index in array
<assocA> also will be set in array <assocB>. A previous
declaration of the associative arrays involved is required. Example:

REM

Adds a
comment to your code. Any type of string may follow the REM
statement. Instead of REM also the single quote symbol ' maybe used
to insert comments in the code.

BaCon also
accepts C-style block comments: this can be done by surrounding
multiple lines using /* and */.

RENAME

RENAME
<filename> TO <new filename>

Type:
statement

Renames a
file. If different paths are included the file is moved from one path
to the other. Note that an error occurs when the target directory is
on a different partition. Example:

RENAME
"tmp.txt" TO "real.txt"

REPEAT

REPEAT
<body>
[BREAK]|[CONTINUE]UNTIL
<equation>

Type:
statement

The
REPEAT/UNTIL construction repeats a body of statements. The
difference with WHILE/WEND is that the body will
be executed at least once. The optional BREAK
statement can be used to break out the loop. With CONTINUE
part of the body can be skipped. The BETWEEN operator is allowed in
the equation. Example:

REPEAT
C
= GETKEY
UNTIL C = 27

REPLACE$

REPLACE$(haystack$,
needle$, replacement$ [, flag])

Type:
function

Substitutes
a substring <needle$> in <haystack$> with <replacement$>
and returns the result. The replacement does not necessarily need to
be of the same size as the substring. With the optional flag set to 1
the <needle$> should be taken as a regular expression, and
OPTION COMPARE impacts case insensitive
matching. With the optional flag set to 2, REPLACE$ will behave as a
translate, meaning that the characters in <needle$> will be
replaced by the successive characters in <replacement$>. See
also EXTRACT$.

RETURN

If RETURN
has no argument it will return to the last invoked GOSUB.
If no GOSUB was invoked previously then RETURN has no effect.

Only in
case of functions the RETURN statement must contain a value. This is
the value which is returned when the FUNCTION
is finished.

RETVAL

RETVAL

Type:
variable

Reserved
variable containing the return status of the operating system
commands executed by SYSTEM or EXEC$.

REV$

REV$(string$
[,delimiter$])

Type:
function

Puts all
elements in a delimited string split by delimiter$ in reverse order.
The delimiter$ is optional. If it is omitted, then the definition
from OPTION DELIM is assumed. When specified,
it may consist of multiple characters.

If
delimiter$ occurs between double quotes in string$, then it is
ignored. This behavior can be changed by setting OPTION
QUOTED to FALSE. See also the chapter on delimited
string functions for more information about delimited strings.
Example:

REVERSE$

REWIND

REWIND
<handle>

Type:
statement

Returns to
the beginning of a file opened with <handle>.

RIGHT$

RIGHT$(x$,
y)

Type:
function

Returns y
characters from the right of x$.

RND

RND

Type:
function

Returns a
random number between 0 and the reserved variable MAXRANDOM.
The generation of random numbers can be seeded with the statement
SEED. See also the function RANDOM
for a more convenient way of generating random numbers. Example:

SEED
NOW
x = RND

ROL

ROL

Type:
function

This
function performs a binary shift to the left. The highest bit will be
recycled into bit 0. The total amount of bits in a value is
determined by the MEMTYPE option.

OPTION
MEMTYPE short
PRINT ROL(32768)

ROR

ROR

Type:
function

This
function performs a binary shift to the right. The lowest bit will be
recycled into the highest, depending on the setting of the MEMTYPE
option.

OPTION
MEMTYPE int
PRINT ROR(1)

ROTATE$

ROTATE$(string$,
step [,delimiter$])

Type:
function

Rotates all
elements in a delimited string split by delimiter$ <step>
positions forward. In case the <step> parameter is a negative
number, the rotation will be backwards. The delimiter$ is optional.
If it is omitted, then the definition from OPTION
DELIM is assumed. When specified, it may consist of multiple
characters.

If
delimiter$ occurs between double quotes in string$, then it is
ignored. This behavior can be changed by setting OPTION
QUOTED to FALSE. See also the chapter on delimited
string functions for more information about delimited strings.
Example:

PRINT
ROTATE$("Rome Amsterdam Kiev Bern Paris London", 2)

ROUND

ROUND(x)

Type:
function

Rounds x to
the nearest integer number. For compatibility reasons, the keyword
INT may be used instead. Note that this function always returns an
integer value.

See also
FLOOR to round down to the nearest the integer
and MOD to get the fraction from a fractional
number.

ROWS

ROWS

Type:
function

Returns the
amount of rows in the current ANSI compliant terminal. Use COLUMNS
to get the amount of columns.

RUN

RUN
<command$>

Type:
statement

Executes an
operating system command thereby transferring control. This
effectively means that the current program is left permanently, the
process ID is preserved and that this statement does not return to
the BaCon program. Typically, the RUN statement is used at the end of
a BaCon program. It can only execute one system command at a time.

The
behavior of RUN differs from the SYSTEM
statement, which can execute a set of compound commands in a shell
and can query the exit status. See also EXEC$
and RUN$.

Example:

RUN
"ls -l"

RUN$

RUN$(command$
[, stdin$[, out]])

Type:
function

Executes an
operating system command in a coprocess and returns the resulting
output to the BaCon program. Because the coprocess PID is not a
shell, but the PID of the executed command itself, this function
cannot return a system command exit status, and can only execute one
system command at a time. Optionally, a second argument may be used
to feed to STDIN. Also optionally, a third argument can be specified
to determine whether all output needs to be captured (0 = default),
only stdout (1) or only stderr (2). See RUN and
SYSTEM to plainly execute a system command.
Example:

SAVE

SAVEstring$ TO filename$

Type:
statement

Saves a
string to disk in one step. If the file already exists it is
overwritten. See BSAVE for saving binary files
in one step, and OPEN/WRITELN/READLN/CLOSE
to read and write to a file using a filehandle. Example:

SAVE
result$ TO "/tmp/data.txt"

SCROLL

SCROLL<UP [x]|DOWN[x]>

Type:
statement

Scrolls the
current ANSI compliant terminal up or down one line. Optionally, the
amount of lines to scroll can be provided.

SEARCH

SEARCH(handle,
string [,flag])

Type:
function

Searches
for <string> in file opened with <handle>. The search
returns the byte offset in the file where the first occurrence of
<string> is located. Use SEEK to
effectively put the filepointer at this position. If the string data
is not found, then the value '-1' is returned.

Optionally,
a third argument can be used to determine where to start the search
and in which direction the search should take place. The following
values are accepted:

0: start at
the beginning of the file, search forward (default)
1: start at
the current position of the filepointer, search forward
2: start
at the current position of the filepointer, search backward
3:
start at the end of the file, search backward.

Note that
when searching backwards, the actual search begins at the start
position minus the length of the searched string.

SECOND

SECOND(x)

Type:
function

Returns the
second (0-59) where x is the amount of seconds since January 1, 1970.

SEED

SEED
x

Type:
statement

Seeds the
random number generator with some value. After that, subsequent
usages of RND and RANDOM
will return numbers in a random order. Note that seeding the random
number generator with the same number also will result in the same
sequence of random numbers.

By default,
a BaCon program will automatically seed the random number generator
as soon as it is executed, so it may not be needed to use this
function explicitly. Example:

SEED
NOW

SEEK

SEEK
<handle> OFFSET <offset> [WHENCESTART|CURRENT|END]

Type:
statement

Puts the
filepointer to new position at <offset>, optionally starting
from <whence>.

SELECT

SELECT
<variable> CASE <body>[;] [DEFAULT <body>]
ENDSELECT

Type:
statement

With this
statement a variable can be examined on multiple values. Optionally,
if none of the values match the SELECT statement may fall back to the
DEFAULT clause. Example:

Contrary to
most implementations, in BaCon the CASE keyword also may refer to
expressions and variables. Note that in such situation, each CASE
keyword will re-evaluate the expression at each occurrence.

Also, BaCon
knows how to 'fall through' by either using a semicolon or a comma
separated list, in case multiple values lead to the same result:

SEND

SEND
<var> TO <handle> [CHUNK <chunk>]
[SIZE <size>]

Type:
statement

Sends data
in <var> to a network location identified by <handle>.
Optionally, the amount of bytes to send can be specified with the
CHUNK keyword. As by default SEND will consider the <var> to be
a string, the default amount of data is the string length of <var>.
However, instead of a string, also binary data can be sent by using a
memory area created by the MEMORY function. In
such a situation it is obligatory to also specify the chunk size.

The amount
of bytes actually sent can be retrieved by using the optional SIZE
keyword. For an example of SEND, see the RECEIVE
statement.

SETENVIRON

SETENVIRON
var$, value$

Type:
statement

Sets the
environment variable 'var$' to 'value$'. If the environment variable
already exists, this statement will overwrite a previous value. See
GETENVIRON$ to retrieve the value of an
environment variable. Example:

SETENVIRON
"LANG", "C"

SETSERIAL

SETSERIAL<device>
IMODE|OMODE|CMODE|LMODE|SPEED|OTHER<value>

Type:
statement

This
statement can set the properties of a serial device. The Input Mode
(IMODE), Output Mode (OMODE), Control Mode (CMODE) and Local Mode
(LMODE) can be set, as well as the speed and the special properties
on the serial device. A discussion on the details of all these
options is outside the scope of this manual. Please refer to the
TermIOS documentation of your C compiler instead.

Example
usage opening a serial port in 8N1, ignoring 0-byte as a break,
canonical, and non-blocking with a timeout of 0.5 seconds:

SGN

Returns the
sign of x. If x is a negative value, this function returns -1. If x
is a positive value, this function returns 1. If x is 0 then a 0 is
returned.

SIGNAL

SIGNAL
<sub>, <signal>

Type:
statement

This
statement connects a callback function to a Unix signal. Plain POSIX
signal names can be used, for example SIGINT, SIGTERM, SIGCHLD and so
on. Next to that, this statement accepts the SIG_DFL (default action)
and SIG_IGN (ignore signal) symbols for a callback also.

SIN

SIZEOF

SIZEOF(type)

Type:
function

Returns the
bytesize of a C type.

SLEEP

SLEEP
<x>

Type:
statement

Sleeps <x>
milliseconds (sleep 1000 is 1 second).

SORT

SORT
<x> [SIZE <x>] [DOWN]

Type:
statement

Sorts the
one-dimensional array <x> in ascending order. Only the basename
of the array should be mentioned, not the dimension. The array may be
a numeric, string or associative array. The amount of elements
involved can be specified with SIZE. This keyword is optional for
static arrays, but should always be used in case of dynamic arrays.
It has no meaning with associative arrays. Also optionally, the
keyword DOWN can be used to sort in descending order. Example:

SORT$

SORT$(string$
[,delimiter$])

Type:
function

Sorts all
elements in a delimited string split by delimiter$. The delimiter$ is
optional. If it is omitted, then the definition from OPTION
DELIM is assumed. When specified, it may consist of multiple
characters.

If
delimiter$ occurs between double quotes in string$, then it is
ignored. This behavior can be changed by setting OPTION
QUOTED to FALSE. See also the chapter on delimited
string functions for more information about delimited strings.
Example:

PRINT
"Sorted members: ", SORT$("f,q,a,c,i,b,r,t,e,d,z,",
",")

SOURCE$

SOURCE$

Type:
variable

Reserved
variable which contains the BaCon source code of the current running
program. Note that for commercial programs this variable should not
be used, because it stores the source code as plain text in the
resulting binary.

SPC$

SPC$(x)

Type:
function

Returns an
x amount of spaces.

SPLIT

This
statement can split a string into smaller pieces. The optional BY
argument determines where the string is being split. If the BY
keyword is omitted then the definition from OPTION
DELIM is used to split string$. The results are stored in the
argument <array$> mentioned by the TO keyword. As sometimes it
cannot be known in advance how many elements this resulting array
will contain, the array may not be declared before with LOCAL
or GLOBAL.

If SPLIT is
being used in a function or sub, then <array$> will have a
local scope. Else <array$> will be visible globally, and can be
accessed within all functions and subs.

The total
amount of elements created in this array is stored in <variable>.
This variable can be declared explicitly using LOCAL
or GLOBAL.

If the
<substr$> delimiter occurs in between double quotes, then it is
skipped. This behavior can be changed by setting OPTION
QUOTED to FALSE. If a double quote needs to be present in the
<string$>, it must be escaped properly.

If the
value for BY is numeric, then string$ will be cut in pieces each
containing <nr> characters. If <nr> is 0 then there are
no results. If <nr> is equal to or bigger than the length of
the string, then the original string will be returned as an array
with one element.

Example
usage:

OPTION
BASE 1
LOCAL dimension
SPLIT "one,two,,three" BY
"," TO array$ SIZE dimension
FOR i = 1 TO
dimension
PRINT array$[i]
NEXT

The above
example will return four elements, of which the third element is
empty. If OPTION COLLAPSE is put to 1, the
above example will return three elements, ignoring empty entries.

SPLIT
"one,two,\"three,four\",five" BY "," TO
array$ SIZE dim

This will
return 4 elements, because one separator (the comma) lies in between
double quotes.

The
optional STATIC keyword allows the created <array> to be
returned from a function. See also EXPLODE$
to split text returning a delimited string, TOKEN$
to retrieve one single element from a delimited string, and JOIN
to join array elements into a string.

SQR

SQR(x)

Type:
function

Calculates
the square root from a number.

STOP

STOP
[signal]

Type:
statement

Halts the
current program and returns to the Unix prompt. The program can be
resumed by performing the Unix command 'fg', or by sending the CONT
signal to its pid: kill -CONT <pid>.

The STOP
statement actually sends the 'STOP' signal to the current program.
Optionally, a different signal can be defined. The signal can be a
number or a predefined name from libc, like SIGQUIT, SIGKILL, SIGTERM
and so on. Example sending the <CTRL>+<C> signal:

STR$

SUB

Defines a
subprocedure. A subprocedure never returns a value (use FUNCTION
instead).

Variables
used in a sub are visible globally, unless declared with LOCAL.
The incoming arguments are always local. Instead of the BaCon types
STRING, NUMBER and FLOATING for the incoming arguments, also regular
C-types also can be used. If no type is specified, then BaCon will
recognize the argument type from the variable suffix. In case no
suffix is available, plain NUMBER type is assumed. With VAR
a variable amount of arguments can be defined. Example:

SUB
add(NUMBER x, NUMBER y)
LOCAL result
PRINT "The
sum of x and y is: ";
result = x + y
PRINT
result
END SUB

SUM / SUMF

SUM(array,
amount [,minimum])
SUMF(array,
amount [,minimum])

Type:
function

Returns the
sum of <amount> elements in <array>. Optionally, a check
can be added which specifies the minimum value for each element to be
added. If an array element falls below the specified value then it is
excluded from the sum calculation.

The SUM and
SUMF functions perform the same task, but SUM requires an array with
integers and SUMF an array with floating values. See also MAP.
Example:

PRINT
SUM(ages, 10)
PRINT SUMF(temperatures, 100, 25.5)

SWAP

SWAPx, y

Type:
statement

Swaps the
contents of the variables x and y. The types of the variables can be
mixed. Note that when swapping an integer with a float precision may
be lost.

SYSTEM

SYSTEM
<command$>

Type:
statement

Executes an
operating system command. It causes the BaCon program to hold until
the command has been completed. The exit status of the executed
command itself is stored in the reserved variable RETVAL.
Use EXEC$ to catch the result of an operating
system command. Example:

SYSTEM
"ls -l"

TAB$

TAB$(x)

Type:
function

Returns an
x amount of tabs.

TAIL$

TAIL$(string$,
amount [, delimiter$])

Type:
function

Retrieves
the last <amount> elements from a delimited string$ split by
delimiter$. The delimiter$ is optional. If it is omitted, then the
definition from OPTION DELIM is assumed. When
specified, it may consist of multiple characters.

If
delimiter$ occurs between double quotes in string$, then it is
ignored. This behavior can be changed by setting OPTION
QUOTED to FALSE.

See also
FIRST$ to obtain the remaining elements from
the delimited string, and HEAD$ to obtain
elements counting from the start. Refer to the chapter on delimited
string functions for more information about delimited strings.
Example:

TALLY

TALLY(haystack$,
needle$ [,z])

Type:
function

Returns the
amount of times needle$ occurs in haystack$, optionally starting at
position z. If the needle$ is not found, then this function returns
the value '0'. See INSTR to find the position of
a string. Example:

amount
= TALLY("Hello world are we all happy?", "ll")
PRINT
TALLY("Don't take my ticket", "t", 10)

TAN

TAN(x)

Type:
function

Returns the
calculated tangent of x, where x is a value in radians.

TELL

TELL(handle)

Type:
function

Returns
current position in file opened with <handle>.

TEXTDOMAIN

TEXTDOMAIN<domain$>, <directory$>

Type:
statement

When OPTION
INTERNATIONAL is enabled, BaCon by default configures a
textdomain with the current filename and a base directory
"/usr/share/locale" for the message catalogs. With this
statement it is possible to explicitly specify a different textdomain
and base directory.

TIMER

TIMER

Type:
function

Keeps track
of the amount of milliseconds the current program is running.
Example:

TIMEVALUE

Returns the
amount of seconds since January 1 1970, from year (a), month (b), day
(c), hour (d), minute (e), and seconds (f). Example:

PRINT
TIMEVALUE(2009, 11, 29, 12, 0, 0)

TOASCII$

TOASCII$(string$)

Type:
function

Returns the
same string of which each byte has bit 7 set to 0. Note that this can
lead to unpredictable results. See also ISASCII
or ISUTF8. Example:

PRINT
TOASCII$("Hello world")

TOKEN$

TOKEN$(haystack$,
n [, delimiter$])

Type:
function

Returns the
nth token in haystack$ split by delimiter$. The delimiter$
is optional. If it is omitted, then the definition from OPTION
DELIM is assumed. When specified, it may consist of multiple
characters.

If
delimiter$ occurs between double quotes in haystack$, then it is
ignored. This behavior can be changed by setting OPTION
QUOTED to FALSE.

If the
indicated position is outside a valid range, the result will be an
empty string. Use the FLATTEN$ function to
flatten out the returned token. See also ISTOKEN,
AMOUNT and SPLIT.

TRACE

TRACE<ON|MONITOR<var1, var2, ...>|OFF>

Type:
statement

The ON
keyword starts trace mode. The program will wait for a key to
continue. After each keypress, the next line of source code is
displayed on the screen, and then executed. Pressing the ESCAPE key
will exit the program.

The MONITOR
keyword also starts trace mode, but allows monitoring values of
variables. After each line of source code the content of the
specified variables is displayed.

If TRACE is
used within a function, make sure to also add TRACE OFF at the end of
the function.

Example:

LOCAL
var
TRACE MONITOR var
FOR var = 1 TO 10
INCR
var
NEXT

TRAP

TRAP
<LOCAL|SYSTEM>

Type:
statement

Sets the
runtime error trapping. By default, BaCon performs error trapping
(LOCAL). BaCon tries to examine statements and functions where
possible, and will display an error message based on the operating
system internals, indicating which statement or function causes a
problem. Optionally, when a CATCH is set, BaCon
can jump to a LABEL instead, where a
self-defined error function can be executed, and from where a RESUME
is possible.

When set to
SYSTEM, error trapping is performed by the operating system. This
means that if an error occurs, a signal will be caught by the program
and a generic error message is displayed on the prompt. The program
will then exit gracefully

The setting
LOCAL decreases the performance of the program, because additional
runtime checks are carried out when the program is executed.

TRUE

TRUE

Type:
variable

Represents
and returns the value of '1'. This is the opposite of the FALSE
variable.

TYPEOF$

TYPEOF$(x)

Type:
function

Returns the
type of a variable.

UCASE$

UCASE$(x$)

Type:
function

Converts x$
to uppercase characters and returns the result. See LCASE$
to do the opposite.

UCS

UCS(char)

Type:
function

Calculates
the Unicode value of the given UTF8 character (opposite of UTF8$).
See also ASC for plain ASCII characters. Example:

ULEN

Returns the
length of the UTF8 string x$. Optionally, the position at y can be
specified. See LEN for plain ASCII strings.

UNFLATTEN$

UNFLATTEN$(txt$
[, groupingchar$])

Type:
function

Unflattens
a string where the double quote symbol is used to group parts of the
string together. The string will be surrounded with double quotes and
any existing escapes will be escaped. Instead of the double quote
symbol a different character can be specified (optional). See also
FLATTEN$ for the reverse operation. Examples:

UNIQ$

UNIQ$(string$
[,delimiter$])

Type:
function

Unifies all
elements in a delimited string split by delimiter$. The delimiter$ is
optional. If it is omitted, then the definition from OPTION
DELIM is assumed. When specified, it may consist of multiple
characters.

If
delimiter$ occurs between double quotes in string$, then it is
ignored. This behavior can be changed by setting OPTION
QUOTED to FALSE. See also the chapter on delimited
string functions for more information about delimited strings.
Example:

USEC

Defines a
body with C code. This code is put unmodified into the generated C
source file. Example:

USEC
char
*str;
str = strdup("Hello");
printf("%s\n",
str);
END USEC

USEH

USEH <body>ENDUSEH
| END USEH

Type:
statement

Defines a
body with C declarations and/or definitions. This code is put
unmodified into the generated global header source file. This can
particularly be useful in case of using variables from external
libraries. See also USEC to pass C source code.
Example:

USEH
char
*str;
extern int pbl_errno;
END USEH

UTF8$

UTF8$(x)

Type:
function

Returns the
character belonging to Unicode number x. This function does the
opposite of UCS. The value for x can lie between 0
and 0x10FFFF. Note that the result only will be visible in a valid
UTF8 environment, and also that the installed character set should
support the character. See also CHR$ for plain
ASCII characters. The following should print a smiley emoticon:

LET
a$ = UTF8$(0x1F600)
PRINT a$

VAL

VAL(x$)

Type:
function

Returns the
actual value of x$. This is the opposite of STR$.
Example:

nr$
= "456"
q = VAL(nr$)

VAR

VAR<array$> SIZE<x>

Type:
statement

Declares a
variable argument list in a FUNCTION or SUB.
There may not be other variable declarations in the function header.
The arguments to the function are put into an array of strings, and
the resulting amount of elements is stored in <x>. Example:

VERIFY

VERIFY(connection,
file$)

Type:
function

Verifies
the certificates of the current TLS connection against file$. The
file$ should be in PEM format and should contain all root CA
certificates. Usually this information can be extracted from a web
browser. See also the chapter on secure network
connections.

In case of
an invalid certificate, OpenSSL and GnuTLS will not drop the active
TLS connection, and the VERIFY function will return the TLS error
code.

For
WolfSSL, the connection will be dropped immediately, and the reserved
ERROR variable will contain the actual TLS error code. Use CATCH
GOTO to prevent the program from stopping and workaround the TLS
problem.

VERSION$

VERSION$

Type:
variable

Reserved
variable which contains the BaCon version text.

WAIT

WAIT(handle,
milliseconds)

Type:
function

Suspends
the program for a maximum of <milliseconds> until data becomes
available on <handle>.

This is
especially useful in network programs where a RECEIVE
will block if there is no data available. The WAIT function checks
the handle and if there is data in the queue, it returns with value
'1'. If there is no data then it waits for at most <milliseconds>
before it returns. If there is no data available, WAIT returns '0'.
Refer to the RECEIVE statement for an example.

This
statement also can be used to find out if a key is pressed without
actually waiting for a key, so without interrupting the current
program. In this case, use the STDIN filedescriptor (0) as the
handle. Example:

As can be
observed in this code, instead of '0' the reserved POSIX variable
STDIN_FILENO can be used also. See also appendix
B for more standard POSIX variables.

WALK$

WALK$(directory$,
filetype, regex, recursive [,delimiter$])

Type:
function

This
function returns a delimited string with all the file names located
in <directory$>. The <filetype> argument can contain a
number from 1 to 7 and determines the kind of file to look for:

Value

Meaning

1

Regular file

2

Directory

3

Character device

4

Block device

5

Named pipe (FIFO)

6

Symbolic link

7

Socket

The <regex>
argument defines a regular expression and acts as an additional
filter to narrow down the resulting list further. The <recursive>
argument can either be TRUE or FALSE to define whether or not
underlying directories should be searched as well.

The
delimiter$ argument is optional. If it is omitted, then the
definition from OPTION DELIM is assumed. When
specified, it may consist of multiple characters. Note that the
default delimiter used by BaCon is a single whitespace, while file
names can contain whitespaces as well. It is therefore recommended to
specify a delimiter like NL$ which usually does
not occur in file names.

If
delimiter$ occurs between double quotes in string$, then it is
ignored. This behavior can be changed by setting OPTION
QUOTED to FALSE. See also the chapter on delimited
string functions for more information about delimited strings.

Example to
list files in the current directory:

PRINT
WALK$(".", 1, ".+", FALSE, NL$)

Example to
list all directories in /tmp containing an underscore symbol:

PRINT
WALK$("/tmp", 2, "[_]+", FALSE, NL$)

Example to
recursively list all files ending in ".jpg" and also start
with a number:

PRINT
WALK$(".", 1, "^[[:digit:]]+.*.jpg$", TRUE, NL$)

WEEK

WEEK(x)

Type:
function

Returns the
week number (1-53) in a year, where x is the amount of seconds since
January 1, 1970. Example:

PRINT
WEEK(NOW)

WEEKDAY$

WEEKDAY$(x)

Type:
function

Returns the
day of the week as a string in the system's locale ("Monday",
"Tuesday", etc), where x is the amount of seconds since
January 1, 1970.

WHILE

WHILE <equation>
[DO]
<body>
[BREAK]|[CONTINUE]WEND

Type:
statement

The WHILE/WEND is used to repeat a body
of statements and functions. The DO keyword is optional. The optional
BREAK statement can be used to break out the
loop. With the optional CONTINUE part of the
body can be skipped. Example:

LET
a = 5
WHILE a > 0 DO
PRINT a
a = a - 1
WEND

As the
WHILE statement uses an equation to evaluate, it also allows the
BETWEEN operator: