ScriptBasic Users Guide

by Peter Verhas

Table of Contents

[Contents]

1. Introduction

ScriptBasic is a BASIC language interpreter with several features that makes it unique. First of all ScriptBasic itself is free and is supported by the GNU LGPL licence. Note that the GNU LGPL licence applies only to ScriptBasic itself, while the modules interfacing 3rd party software may apply different licenses. For example the module interface code for the module T<bdb> is under LGPL, but the library it uses, namely the Berkeley DB is NOT LGPL!

ScriptBasic runs on Windows NT, Windows95, Linux, Tru64 UNIX and probably on many other platforms. ScriptBasic the ideal tool to write small scripts that gurus write in Perl. However you need not be a guru to powerfully program in ScriptBasic.

This is not the only situation to consider ScriptBasic. ScriptBasic can be a valuable tool for experts as well as a language interpreter ready to be built into their application. Read the list of ScriptBasic features and decide how you can use it.

This documentation is the User's Guide for the so-called STANDARD variation of the interpreter. This code runs on the command line, accepts command line arguments and runs a single program in a single process. Other variations exist, which are based on the same code but exhibit different interfaces to the system. Some features for those variations may be different, but most language features probably remain the same. The variation Eszter SB Application Engine is shipped with the ScriptBasic package and is embedding the interpreter into a multi-thread, single process web server. Other embedded variations are available from independent developers.

This document describes how to use the interpreter and the programming language.

[Contents]

2. Using ScriptBasic

This chapter is about the STANDARD variation of the interpreter. Starting and using other variations may probably be different.

[Contents]

2.1. Running from command line

There are several ways to start a ScriptBasic program. The different ways also depend on the installation. Windows NT may associate the extension T<.sb> with the ScriptBasic interpreter. In this case you can start a ScriptBasic program double clicking on its name in the explorer. You can type the name of the text file containing your basic program and UNIX will start it for you automatically if the first line of the program contains the starting information like

#! /usr/bin/scriba

and the file itself is executable. The simplest way among all is to type the name of the executable. First try to start it without any command line argument:

$ scriba
Usage: basic [options] program.bas

options: -o file_name specify output file, save binary format to file but don't execute -b file_name load binary format from file and execute -n do not use cache (no save, no load) -e execute after binary format was saved -v print version info and stop -c inform scriba that this is a CGI script. -C save C program output. -E save executable output. (may not work under some OS) -p preprocessor specify external preprocessor. -i preprocessor specify internal preprocessor. -f configurationfile specify configuration file -d debug module error (UNIX only) -k text_config_file compile the configuration file to binary -D dump the configuration file in text format

The program does not insist on its name, the person installing can name it basic, scriba or any other name. However scriba is the preferred name for the executable. When you start the program without arguments it tells you the different options. If the program does not start check that the executable is in the path or specify the full path to the executable. Under UNIX you may need to start ScriptBasic after you have compiled as ./scriba

The compilation and execution of the code can be altered and driven by command line options. There are not too many and usually you do not need any. If you want to start a basic program you can type:

$ scriba hello.bas
Hello world!
$ _

The program will execute the basic code and after executing the final statement it exists the process.

OPTION -o

ScriptBasic STANDARD variation is able to dump the compiled code to a file and later use this image to execute the basic program. To do this you can type

$ scriba -o hello.bbf hello.bas

This command will compile the program hello.bas into the file hello.bbf. The code itself will not be executed. The extension bbf stands for basic binary format, but you can use any extension. ScriptBasic does not assume any default extensions.

OPTION -b

The saved binary format can be executed by the interpreter issuing the command

$ scriba -b hello.bbf

The switch `-b' tells the interpreter that the file is already a compiled format and it needs only execution. However ScriptBasic STANDARD variation is intelligent enough to recognize the binary format and it will not try to interpret it as basic text even if you miss the switch `-b'. The command line

$ scriba hello.bbf

should also work. The switch `-b' is available because recognizing the binary format applies some heuristics and using the `-b' switch to execute a compiled basic program is the safe way.

Note that the compiled format is not compiled in the sense of usual compilers. The compiled format is NOT machine executable. This is the internal format that the interpreter interprets and executes. This format is created and stored in memory each time a basic program is executed. When the `-o' switch is used this internal format is saved and can be reloaded later to execute again the basic program.

This binary format is proprietary and is NOT portable. This binary format was designed to load the programs fast and allow the interpreter speedy startup for codes executed many times. You have to "compile" your basic code on the architecture you want to run it. It needs not be physically the same machine, but it should be the same type of operating system, the same compiler used to compile ScriptBasic executable and the same ScriptBasic version and build number. The different variations may accept each others binary format. For example the Eszter SB Application Engine variation accepts the binary format created by the STANDARD variation. We recognized that the STANDARD variation running on Linux compiled with gcc can execute the binary format generated by the Windows NT version of ScriptBasic, but this is only the fact of life and it is not a guaranteed feature.

OPTION -e

In certain situations you may want to save the binary format and execute the code the same time. In this situation you can issue the command line:

$ scriba -o hello.bbf -e hello.bas

The switch `-e' tells ScriptBasic to execute the code. This is not the normal behavior when binary format is saved to file. Note that you need the switch `-e' only when the switch `-o' is also on the command line. To execute a program without saving the binary format to a file you need no switches at all.

OPTION -n

The binary format of the code is usually saved into a directory without user intervention. The cache directory is defined in the configuration file using the configuration key cache. In certain situation you want to avoid caching of the code. If you use the command line option `-n' neither cache checking for newer version nor cache writing will be performed.

OPTION -c

You should use the `-c' option in programs that are executed as CGI scripts. This helps the error reporting system to cooperate with the web server and send properly formatted HTML formatted errors whenever and error occurs.

OPTION -C

The option `-C' asks the interpreter to generate C language compiled code. For more about this option read in Compiling BASIC programs to C.

OPTION -E

The option `-E' asks the interpreter to create a stand alone executable from the BASIC program. This is an option that works only on some platform, but not on all. It does work on Windows and under Linux and some users reported success using it under FreeBSD and Solaris. When using this option the interpreter creates a file that can be started and contains the compiled BASIC program in itself. This is not a compilation just as well as compiling into binary format is not a real compilation. It copies the binary executable code of the interpreter and the binary format of the BASIC program into one file and sets it so that executes the BASIC program embedded into the executable file.

When you use this option under Linux, you have to specify the full path to the interpreter. Thus you may not successfully execute

scriba –Eo test test.sb

but rather you have to type:

/usr/bin/scriba –Eo test test.sb

This is because ScriptBasic relies on the command line to find the executable file it has to copy into the created output executable. If you do not know where the ScriptBasic interpreter is installed you can type the command:

which scriba

to find out the exact location.

Also note that the generated file can not be executed immediately after it has been generated. You have to set the execute permission on the generated file, for example:

chmod u+x test

before you can issue the command

./test

OPTION -p

The option `-p' should be used to specify an external preprocessor. This preprocessor has to be configured in the configuration file of ScriptBasic. Ask the system manager responsible for your installation about the available preprocessors. If this person is you read the section Using external preprocessor. You can specify more than one preprocessors on the line. These are executed one after the other in the order they are specified on the command line. If no preprocessor is defined on the command line the interpreter will execute the preprocessor or preprocessors that are assigned to the extensions of the source file name. The assignments should be configured in the ScriptBasic configuration file.

OPTION -i

The option `-i' specifies an internal preprocessor. Internal pre-processors are implemented as DLL or SO file. These programs are loaded by the ScriptBasic interpreter when the command line option `-i' is used, or when the program contains the command USE. The internal pre-processor can alter the source code after the interpreter read the code into memory, but also can do a lot of other things while ScriptBasic compiles the code, and some of them even during run time. For more information on internal pre-processors read the guide of the actual pre-processor, or read the developers guide that details how internal pre-processors should be developed.

The argument to this option has to be the name of the internal preprocessor as configured in the configuration file. For example, to start the program in command line debugger mode the user has to type:

scriba -i dbg hello.bas

The program will load the preprocessors in the order they are specified.

OPTION -f

When ScriptBasic starts it reads its configuration file. Some programs can run without any configuration information, however more complex programs will need external modules and this most probably will require configuration. The configuration file is located usually at `/etc/scriba/basic.conf' under UNIX or in the same directory where the executable is under Windows NT. However in some situation you may want to run ScriptBasic using some special configuration file. In this case you can specify the configuration file using the option `-f'. The argument to this option is the name of the file that is the compiled configuration information. The only exception is when you are using this option along with the option `-k' to compile the configuration information. In this case the argument to the option `-f' has to be the name of the configuration file that is to be created.

OPTION -d

The option `-d' is a special one and you need it only when you try to find out configuration errors you made. The option can be used under UNIX as well as under Windows. However ScriptBasic will print out different errors under the different operating systems.

You can also use this option when a configuration file can not be compiled and ScriptBasic reports that there are errors in the configuration file. Be prepared that ScriptBasic may print out quite a huge portion of the configuration file following the error to specify the location of the error.

On UNIX the option `-d' prints out the system error message when an external module fails to load. Without this option the interpreter says: 'module can not be loaded', but you, the installer of the module do not know why. Here is the reason why it is needed in some cases on UNIX and why not under Windows.

On Windows when you compile source code to DLL all symbolic references have to be resolved. If a module uses the zlib.lib for example, you have to link it against the DLL during link time. UNIX is more allowing. If you miss the `-lz' (to stay with the example of needing zlib) when you link the shared object the linker does not complain, because UNIX dynamic loading system allows symbolic reference resolution during run time. However when you run ScriptBasic and want to load the module this missing function appears immediately.

A real word example is the MySQL module. The first version of ScriptBasic MySQL module supported MySQL v3.22. The version v3.23 already required the zlib library. The v2.23 was tested only on Windows NT and when it was first compiled by a FreeBSD user, the module was not loadable. He needed the `-d' to see the error, which said 'unresolved reference: uncompress' making immediately clear that the option `-lz' had to be added to the UXLIBS: line in the file interface.c.

Using the option `-d' ScriptBasic will print out the directories where it seeks include files and modules.

OPTION -k

The option `-k' can and should be used to compile a text configuration file to binary format. In this case the input file name should specify a text format configuration file and not a BASIC program. The output file can be specified by the option `-f', but it is not a must. If the option `-f' is not used along with the option `-k' the output file will be the default configuration file.

Note that ScriptBasic command line parsing is the same when you use the option `-k' as it is when executing a program. Therefore all options, typically the option `-f' should precede the input file name. If the option `-f' is placed after the input file name, the command line parsing program believes that it will be some command line argument for the BASIC program and ignores it.

OPTION -D

The option `-D' can be used to display the content of the current compiled configuration file. ScriptBasic will read the configuration file and dump the content formatted according to the text configuration syntax to the standard output. You can use the option `-f' to specify an alternate compiled configuration file if not the default is to be debugged. If an output file is specified using the option `-o' along with the option `-D' the text content of the configuration file is printed into the output file. The output can be sent to the standard output explicitly specifying -o STDOUT as output or to the standard error specifying -o STDERR.

OPTION -v

The last switch is `-v', which can be used to print version information.

$ scriba -v

ScriptBasic v2.0 Variation >>STANDARD<< build 0 Magic value 859010868

Node size is 16 Extension interface version is 11 Compilation: Jul 23 2002 22:24:56 Executable: T:\ScriptBasic\bin\scriba.exe

When you use this switch ScriptBasic does not execute any program. Instead it prints out information on itself and stops. The information lines printed are:

The actual magic value and the compilation date will be different when you try the option `-v' on the released version of ScriptBasic, because this documentation was created using a pre-release version of ScriptBasic v2.0b0.

Note that any command line option should be specified before the name of the BASIC program. Any command line option or argument specified following the name of the file containing the basic program in text or binary format will be passed to the basic program itself. The basic program can use the function COMMAND() to access this part of the command line.

[Contents]

2.2. Running CGI programs

Although this topic should have been out of the scope of this documentation it is described here in detail because of its importance. Several users want to run ScriptBasic programs as CGI scripts.

Running CGI programs is just the same as running command line programs if you are experienced configuring your web server. The major difference is that it is the web server that starts the command line program and not the shell (or command.exe).

Under UNIX you can start a ScriptBasic program the same way as any other CGI scripts. The very first line of BASIC program should be

#! /usr/bin/scriba

assuming that the executable code is called scriba and it is placed in the directory /usr/bin. The text file containing the code should also be executable for the user who runs the CGI scripts. This user is usually called nobody. You may say

$ chmod a+x hello.bas

to give all users execute permission. This may impose security questions that we do not discuss here. You should really know what you are doing.

On Windows NT using Internet Information Server the situation is different. Here you have to associate the extension with the executable of ScriptBasic. Note that this is not the same association as the one that allows the explorer to run the program when you double click on it. You have to configure the association in the Internet Service Manager configuration program.

You can also execute BASIC programs in the Eszter SB Application Engine to generate web applications. In this case the Eszter SB Application Engine has to be started from the command line or as a daemon under UNIX or installed as a service under Windows NT. The BASIC programs are executed inside the engine without starting a new process unlike in CGI and thus execution is faster. Nevertheless the programs on the BASIC programming level feel as if they were CGI programs, thus CGI programs can be executed this way without any modification.

[Contents]

2.3. Writing CGI programs

There are two ways to write CGI programs in ScriptBasic. The old way is just like in any other language: the basic program can access the environment, the standard input and standard output. This is all needed to write a CGI program, decode the CGI parameters and create the http response.

The better way is to use the CGI module delivered with ScriptBasic that automatically handles CGI input, CGI environment variables, creates the uploaded files and even supports some security settings. For more details on the CGI module read the separate documentation of the module named CGI.

[Contents]

3. Installation Instructions

Installation of ScriptBasic is easy. Although there is no SETUP.EXE to install the program, it does not require you to be rocket scientists to install under Windows NT. Under Linux you can use the Debian or the RedHat packages to install the program. Under other unices you should build the and install the program from source that should be as complex and sophisticated as typing make install.

[Contents]

3.1. Installation under Windows

To install the software on Windows is quite easy. Extract the ZIP file into a temporary directory and start the executable `SETUP.EXE'.

Note that another file named `SBCAB.BIN' should be in the same directory where the program `SETUP.EXE' is. This file `SBCAB.BIN' contains the files in a compressed archive that the program `SETUP.EXE' reads and uses to install ScriptBasic.

After starting `SETUP.EXE' all you have to do is to specify the directory where you want to install ScriptBasic, and `SETUP.EXE' does the rest for you.

After you have installed ScritpBasic you can safely delete the files `SETUP.EXE' and `SBCAB.BIN' from the temporary directory. Do not delete `SETUP.EXE' that was copied into the installation directory. This is needed to uninstall ScriptBasic in case you want to uninstall it ever.

[Contents]

3.1.1. Installation under Windows from source

To install from sources you have to compile ScriptBasic first. The process of compilation under Windows operating system is defined in the Developers’ Guide. Note that the Developers’ Guide may not be up to date lacking this chapter.

ScriptBasic does not require installation to use the basic features. Installation and configuration is required to enable ScriptBasic to use advanced features like, loading external modules.

After compilation you can run the BASIC program `install.sb' using the freshly compiled executable `scriba.exe'. This program will partially install ScriptBasic into a directory. To start the program use the command file `install.cmd'.

After you have done this you may want to alter the system PATH to include the directory where the executable is. In case you use the default installation directory this is

C:\ScriptBasic\bin

On Windows 2000 to do it click on the start button, control panel, system. Choose the tab Advanced and then the middle button with the text Environment Variables...

Select the variable Path either from User variables of from System variables. Press the button Edit..., press "Home" to get to the start of the line and type the directory of the ScriptBasic binaries, like C:\ScriptBasic\bin;. Do not delete any of the characters already in the edit box, and do not forget the separating semicolon.

You can find a file `scriba.conf' in this directory. This is the configuration file of ScriptBasic. Do NOT try to edit this file using notepad. This is a binary format file created using the ScriptBasic command line option `-k'. If you want to change any configuration options edit the file `scriba.conf.lsp' and generate the new `scriba.conf' file typing the command line:

C:\ScriptBasic\bin> scriba -k scriba.conf.lsp 

When ScriptBasic starts it searches for the configuration file in the same directory where the executable is (this is a Windows only feature). If you want to store the configuration file in a different directory then use the registry editor and set the key

HKEY_LOCAL_MACHINE\Software\ScriptBasic\config

to hold the full path file name of the configuration file (not the text version but the converted binary).

After the successful installation run some test programs.

[Contents]

3.2. Installation under Linux

To install ScriptBasic under Debian Linux is as simple as typing

dpkg --install scriba-v2.0b0-1_i386.deb

If you happen to install ScriptBasic on a RedHat Linux then you can download the RPM version of the program and say

rpm -i scriba-2.0b0-1.i386.rpm
This will install and configure ScriptBasic form most of the systems. In case the directory structure of the standard installation does not fit your needs then you can edit the configuration file scriba.conf.unix.lsp and convert it to binary version using the command line:

#/usr/bin/scriba -k scriba.conf.unix.lsp 

This is the default configuration file that ScriptBasic reads and all other directories and locations are taken from this file.

In case you want to create a version of ScriptBasic that links some external modules statically or want to play around with the source then you have to recompile the source. Because this is the standard installation mode for any operating system that is not Windows nor Linux, read on in the next section how to do it.

[Contents]

3.3. Installation under other Unices

On Windows NT and Linux (Debian or RedHat) the installation is simple. On other operating system the installation is a bit more sophisticated. You have to extract the tar.gz source file into a directory get super-user privileges issuing the command su and have to type:

./setup

If you happen to need it try it now. If you face issues, then please consult the developers guide that details how to compile ScriptBasic sources.

[Contents]

3.4. Configuration

To reach advanced features, like using system include files from predefined directories or using dynamic modules you have to create a configuration file. This configuration file is probably different for most installation and reflects the directory structure, networking environment and other specialties of your setup.

The format of the configuration file is binary. This is to speed up configuration information reading. To create this binary format, you have to edit the text format of the configuration file usually named `scriba.conf.lsp' and have to convert it to binary format using the command line

scriba -k scriba.conf.lsp

The ScriptBasic executable using the option `-D' dumps binary configuration files into text format. Note that this dump program will not restore the comments of the original configuration file nor the line breaks or spaces (except those in strings).

The format of the text file version of the configuration information is simple. It contains the keys and the corresponding values separated by one or more spaces and new lines. Usually a key and the assigned value are written on a line. Lines starting with the character ; are comment.

The values can be integer numbers, real numbers, strings and sub-configurations. Strings can either be single line started and terminated by a single " character or multi-line strings starting and ending with three """ characters, just like in the language ScriptBasic.

Sub-configurations start with the character ( and are closed with the character ). The lists between the parentheses are keys and corresponding values.

[Former versions of ScriptBasic preceding version 2.0.0 did not allow a configuration to have empty sub configuration. Version 2.0.0 and later allow such a configuration part. This may happen in case the configuration file is edited and all the keys in a subconfiguration is commented out. This was a bug that was hard to spot. The later version executed a clean up procedure when reading the text version of the configuration file during configuration compilation and removes the sub tree.]

The keywords of the current version are:

ScriptBasic ignores all lines containing a key that it does not understand. This is dangerous on one hand because it makes typing errors less recognizable. On the other hand it allows different variations share common configuration file. The external modules implemented as dynamic load library functions can also access any configuration data.

An example configuration file from a Windows NT installation:

; scriba.conf
; ScriptBasic sample configuration file
;
; Note that this configuration file format is from v2.0b0 or later and has to be compiled
; to internal binary format before starting ScriptBasic

; this is the extension of the dynamic load libraries on this system dll ".dll"

; where the modules are to be loaded from module "d:\\MyProjects\\sb\\modules\\" module "d:\\MyProjects\\sb\\sysmodules\\" module "c:\\ScriptBasic\\modules\\"

; where to search system and module include files ; trailing / or \\ is needed include "d:\\MyProjects\\sb\\source\\include\\" include "c:\\ScriptBasic\\source\\include\\"

; ; define external preprocessors ; preproc ( ; extensions that preprocessors are to be applied on extensions ( ; here the key is the extension and the value is the symbolic name of the external ; preprocessor heb "heb" ) ; the external preprocessors external ( heb ( executable "D:\\MyProjects\\sb\\Release\\scriba.exe d:\\MyProjects\\sb\\source\\heber.bas" directory "d:\\MyProjects\\sb\\hebtemp\\"

) ) )

; ; LIMIT VALUES TO STOP INIFINITE LOOP ;

; the maximal number of steps allowed for a program to run ; comment it out or set to zero to have no limit maxstep 30000

; the maximal number of steps allowed for a program to run ; inside a function. ; comment it out or set to zero to have no limit maxlocalstep 0

; the maximal number of recursive function call deepness ; essentially this is the "stack" size maxlevel 300

; the maximal memory in bytes that a basic program is allowed to use ; for its variables maxmem 1000000

;

; ScriptBasic loads the modules before starting the code ; in the order they are specified here ; ;preload "ext_trial"

; ; This is the directory where we store the compiled code ; to automatically avoid recompilation ; cache "d:\\MyProjects\\sb\\cache\\"

cgi ( ;

; These are the keys used by the CGI module ; debugfile "d:\\MyProjects\\sb\\cgidebug.txt" )

Although Windows NT programs are usually configured using the registry or active directory services ScriptBasic uses a text file to ease and maintain compatibility with UNIX versions.

To ease the compatibility even more the file names are allowed to use the UNIX style forward slash / as directory separator character.

When the program starts one of its first action is to search the configuration file. The search for the configuration file is different on Windows NT and under UNIX operating system.

[Contents]

3.5. Configuration file location under Windows NT

Win32 installation first tries to open the file `scriba.conf' if it exists in the same directory as the executable file. This is a convenient place to store the configuration file and does not require registry editing to install ScriptBasic. This is also the ultimate place for CD ROM products utilizing ScriptBasic that need running instantaneously without any installation.

If the file `scriba.conf' does not exist in the directory of the executable the configuration manager tries to open the file, which is specified in the string value, named config under the registry key HKEY_LOCAL_MACHINE\Software\ScriptBasic. If there is no name specified in this registry value ScriptBasic tries to locate the configuration file `scriba.ini' in the system directory. The system directory is determined reading the environment variable windir. If this environment variable does not exits ScriptBasic tries systemroot. It should usually exist on normal Windows installation. If ScriptBasic can not find even this environment variable it tries `C:\WINDOWS' as final try. If no configuration file can be found ScriptBasic tries to execute the program without configuration information.

Note that if for example `C:\WINNT\scriba.ini' exists and is valid, but the registry defines a different and a non-existent or invalid file ScriptBasic will fail to load the configuration file. It will try to read the file specified in the registry. The other file options are searched when the registry key does not exist or is empty.

If the command line uses the option `-f' then the argument of the option is used as configuration file and this overrides all configuration search algorithm. If the file specified in the option `-f' does not exists then ScriptBasic runs without configuration.

[Contents]

3.6. Configuration file location under UNIX

UNIX installations try to locate the configuration file from the environment variable SCRIBACONF. This environment variable should contain the configuration file name. If this environment variable does not exist ScriptBasic tries to load the configuration data from the file `/etc/scriba/basic.conf'.

Note that if the file defined in the environment variable SCRIBACONF is non-existent or is invalid ScriptBasic does not try to load the configuration from the default configuration file.

If you can not configure ScriptBasic configuration file name using environment variables or the system registry under Windows NT you can modify the source file `scriba.c'. You have to alter the function scriba_LoadConfiguration.

If the command line uses the option `-f' then the argument of the option is used as configuration file and this overrides all configuration search algorithm. If the file specified in the option `-f' does not exists then ScriptBasic runs without configuration.

[Contents]

3.7. Overriding the default configuration file

On both UNIX and Windows NT you can specify a configuration file on the command line. If you specify the file name of the configuration file on the command line following the option `-f' then the specified configuration file is going to be used instead of the default.

[Contents]

3.8. Trouble shooting installation

Although installation is quite simple there can be some pitfalls that we and our users have experienced during installing ScriptBasic. To help you we list the possible error.

[Contents]

4. Code caching

The interpreter has to do several things before actually starting the BASIC code. It has to read the file, split it into tokens, analyze the program and build the internal executable format. This takes a lot of time especially for programs longer than a few lines. This can be skipped if the code built up is saved into a file and the file is loaded and run without the recompilation.

To save the binary format file after the BASIC program was analyzed and build the `-o' option can be used. To load and run the code the binary file can be used instead of the text file containing the BASIC code. The interpreter automatically recognizes the binary format and does not try to interpret it as BASIC program source. To help the interpreter you can also supply the option `-b' on the command-line that tells the interpreter to believe without checking that the file is binary format of the basic program. This is one solution to speed up execution of the ScriptBasic programs and to avoid recompilation of the code several times. The other method is caching.

The configuration file (see section Installation Instructions) may contain a value for the key cache. The value for this key should specify a readily existing directory (do not forget the trailing / or \) where the BASIC interpreter can store the binary format of the code. If there is a valid value specified as cache directory the interpreter checks the cache for an already existing binary format file and if that is newer than the BASIC source it neglects the BASIC source and loads the binary format from the cache.

On the other hand whenever a BASIC source code was analyzed and built the resulting binary code is saved into the cache. This method is transparent for the user and significantly speeds up program execution especially for CGI programs that run many times.

To avoid cache using you can use the command-line option -n.

Caching has some limitation that can result unwanted behavior. Before switching on program code cache, please read the following sections that describe the shortages and the security issues that should be considered.

[Contents]

4.1. How cache file name is calculated

The cache file name is calculated from the source file name. The applied algorithm calculated the MD5 digest of the source file name and converts it to a 32-character string. The digest itself is 16 bytes long. The conversion to ASCII takes the 32 half-bytes. Each half byte can have a value from zero to 15. Zero is converted to A, 1 to B and so on. This method was introduced in ScriptBasic v1.0build18 and eliminates some shortages of the algorithm of former versions.

[Contents]

4.2. Cache handling shortages

The cache directory contains the cached binary format program codes for the BASIC programs executed. For each BASIC program a new file is generated when the BASIC source code is analyzed and built.

The file name for the cache file is calculated using the file name. This file name includes the full path to the file under Windows NT but is the bare file name as supplied on the command line under UNIX.

This means that if you have two different programs named `hello.bas' in two different directories and you run one after the other from their directory issuing the command line under UNIX

scriba hello.bas

the second execution will erroneously think that the cache file created when the first one was running belong to this program and will execute the binary code.

On the other hand if you execute the program `hello.bas' from two different directories and the supplied paths are different the caching mechanism will not realize that the two execution refer to the same file.

Also note that cache handling does not compare the modification time of the files that basic program includes. If the program itself does not change, but an included file did the caching it will still run the older version.

Caching usually works and in case you experience mysterious problems you can try to avoid caching using the option `-n' or commenting out the configuration line cache. Web servers usually specify full path to the executed code and in that case cache file name conversion is correct. Especially Apache does start CGI programs passing the full path to ScriptBasic as argument and thus caching works well with this web server.

It is recommended to switch the caching totally off during development and switch on at the start of the test phase. On test environment delete the cache frequently whenever you experience mysterious errors that you think you have already corrected.

[Contents]

4.3. Cache security

Caching is great, but there are some security issues that you have to understand before allowing caching. The ScriptBasic interpreter is usually available to all users in an installation. The cache directory should be created for the interpreter and the security of the directory should be set so that each user can read and write the directory. This may impose security risks in a shared environment.

[Contents]

5. Compiling BASIC programs

BASIC programs can be compiled to a tokenized form, to C code or to an executable file.

The tokenized format is the internal format of ScriptBasic and this is always generated before executing a BASIC program. To speed up execution ScriptBasic is capable saving this code into cache files automatically. However in some situation you may want to save this format into a separate file. To do this you have to issue the command

scriba -no myprogram.bbf myprogram.bas

This will save the code into the file `myprogram.bbf'. After having this file you can execute the BASIC program issuing the command

$ scriba -b myprogram.bbf

or

$ scriba myprogram.bbf

On UNIX you can make the compiled file to be executable setting the permissions

$ chmod u+x myprogram.bbf

and after that you can just write:

$ ./myprogram.bbf

Please note that binary format files may not be executed on different versions or builds of ScriptBasic and are not movable from one platform to another. You may be lucky to execute Windows NT and Linux version bbf files on the other platform, but this is not a guaranteed feature. You surely can not run the binary format generated on a DEC OSF/1 (ooops, sorry Tru64 UNIX) on a 32 bit system.

[Contents]

5.1. Binary format of the BASIC code

In this section we describe some features of the binary format of the BASIC programs saved by ScriptBasic automatically into the cache directory or to a file using the option `-o'. There is absolutely no need to know or understand the binary format of ScriptBasic for those who want to program in ScriptBasic. However advanced users may want to perform some modification on binary format BASIC programs, like changing the interpreter location in the start line. For those this section describes the details.

The binary format is binary. It starts with some constant leading code to ensure that no erroneous execution starts and to avoid memory corruption. This leading code helps ScriptBasic to recognize the binary format even if the interpreter was started without specifying the option `-b'.

The binary format may, however start with a textual line specifying the interpreter. This is needed to make the binary format file executable on UNIX, for example to run a CGI program. This line is interpreted by the UNIX operating system and is ignored by the interpreter. Because this line has no meaning on Windows NT the line HAS TO be terminated by a line feed and not CR/LF. You need not worry about it, because this is created this way on Windows NT as well as on UNIX. This first line is copied from the source BAS file when the binary format is created.

You may want to change this line when you want to run the code on a machine having the interpreter located at a different location. To do this you can use the following sample ScriptBasic code:

cmdlin = command()
split cmdlin by " " to FileName,Interpreter
open FileName for input as 1

binmode 1 File$ = input(lof(1),1) close 1 if left(File$,1) = "#" then i = 1 while i < len(File$) and mid(File$,i,1) <> "\n" i = i+1 wend if mid(File$,i,1) = "\n" then File$ = "#!" & Interpreter & mid(File$,i,len(File$)) end if

open FileName for output as 1 binmode 1

print#1,File$ close 1 end if

This leading line is optional.

The first byte of the binary code (following the optional command line) is the ASCII number of the size of a long on the actual platform. This is currently 4 on Linux and Windows NT, Windows 95/8 and it is 8 for Tru64 UNIX.

This is followed a magic code. This is 0x1A534142. On DOS platforms this is printed as BAS^Z and prevents dumping the code to the screen if one attempts. This magic code is saved as a long. This means that the order of the bytes follows the order of the bytes in a long in memory on the machine the code was saved. This is followed by six long values. These are

The following eight bytes contain the name of the variation that created the binary code. Because some variations do not differ in binary format from the STANDARD variation they create binary file saying it being STANDARD.

To successfully load a binary format file to run in ScriptBasic the long size, the magic code, version information including the build and the variation string should match. Date may be different.

Following this header the real information of the executable code is placed. The following four long numbers present in order the

Following this the nodes come one after the other. ScriptBasic prints the size of a single node in bytes when the option `-v' is used. This is usually 16bytes on 32bit systems and 24bytes on 64bit systems. If you get smaller node size printed then you will face alignment problems. If you get bigger node check your compiler options. ScriptBasic was not tested on 128bit systems up to now.

The string table follows the nodes. This contains all the strings zero character terminated that present in the code. There is at least a zero valued byte in the string table even if the program does not contain any string constant.

There can be arbitrary data following the string table, they are ignored.

[Contents]

6. Compiling BASIC program to EXE

ScriptBasic program can be "compiled" to executable directly under Windows and Linux. To do this you should use the option `-E' and you should also specify an output file using the option `-o'. For example:

scriba -Eo queens.exe queens.bas

will generate an executable file `queens.exe' that will run the BASIC program `queens.bas'. When using this option the ScriptBasic interpreter will ignore any cached precompiled code and will compile the BASIC program from source code fresh.

Note that this kind of compilation works only on Linux and Windows and the generated file is operating system specific, and can not run on any other operating system. Beta test users reported that the feature works on FreeBSD and on Solaris, but the developers lacking test resources can not guarantee this.

Although the ScriptBasic interpreter compiled and installed on other operating system (above Windows and Linux) will accept these options and will generate a file it may not be usable. This feature uses the specialties of the executable format of Windows and Linux.

The compilation to executable is not a real compilation, in the sense that the program is not compiled into real machine code, and thus do not expect it running faster or using less memory. This methodology only creates the intermediary code that the ScriptBasic execution module uses and puts it into an executable file that also contains the interpreter. The final executable will contain the binary code of the BASIC program and will execute the same way as it would execute running the original file.

In the rest of this chapter we detail how the BASIC to EXE direct compilation works.

[Contents]

6.1. BASIC to EXE compilation technical details

Under Windows and Linux an executable file is loaded into the system without caring too much the length of the file. This is the feature that let viruses attach themselves to executable file under Windows. When ScriptBasic is started with the option `-E' the interpreter makes a copy of the executable of itself and appends the compiled intermediate code after the executable code. Finally it prints the eleven characters string SCRIPTBASIC and a four byte file byte offset pointing after the end of the executable part of the file.

When the interpreter starts first it check if the last 15 bytes start with the string SCRIPTBASIC. If it does not then the interpreter continues in normal operation processing the command line parameters. However if the last 15 bytes start with the string SCRIPTBASIC then the executable is a ScriptBasic generated executable and it loads the code from the executable starting at the byte offset specified by the last four bytes of the file.

[Contents]

7. Compiling BASIC programs to C

Although ScriptBasic is an interpreted language it is possible to create stand-alone executables from BASIC programs on any platform where ScriptBasic can run. To get an executable standalone program first you have to compile your BASIC program to C and the C code has to be compiled to get the executable. (Unless you use the option `-E' that can generate executable directly.)

To get the C version of the BASIC program you should use the command line option C, for example:

scriba -nCo myprogram.c myprogram.bas

This command will compile the BASIC program `myprogram.bas' and save the code in C language format into the text file `myprogram.c'. You have to compile this file using a C compiler and link it with the library files.

When using this option the ScriptBasic interpreter will ignore any cached precompiled code and will compile the BASIC program from source code fresh. When compiling BASIC to C do not forget to specify the output file using the option `-o'. Without this option ScriptBasic does not perform the compilation, there is no default file name for the output.

Note that this is not a real compilation. This methodology only creates the intermediary code that the ScriptBasic execution module uses and puts it into a C program. The final executable will contain the binary code of the BASIC program and will execute the same way as it would execute running the original file.

The achievements you can get compiling the code and generating standalone executable file are:

Also note that you have to have a properly created configuration file and the dll or so modules on the system your executable is going to run in case you need some features that rely on configuration settings.

You may also consider recompiling the ScriptBasic interpreter to statically link some of the external modules that your BASIC program uses.

[Contents]

7.1. Compilation under Windows NT

Currently Visual C command line cl and Borland command line bcc32 compilers are supported.

There are two command files that you can find in the bin directory under the installation directory. These are `bascl.cmd' to automate the compilation using the Microsoft compiler and `basbcc32' to automate the compilation using the Borland compiler.

The `bin' directory also contains the files `libscriba.lib' and `libscriba.obj' to be used by the Microsoft compiler and linker, as well as `libscriba_omg.lib' and `libscriba_omg.obj' to be used by the Borland compiler and linker.

The content of the file `bascl.cmd':

scriba -n -Co %1.c %1.bas
cl /Ox /GA6s /DWIN32 /MT /nologo /W0 /c /Fo%1.obj %1.c
cl /Ox /GA6s /DWIN32 /MT /nologo /W0 /Fe%1.exe %1.obj \ScriptBasic\bin\libscriba.obj \ScriptBasic\bin\libscriba.lib ws2_32.lib advapi32.lib

The content of the file `bascbcc32.cmd':

scriba -n -Co %1.c %1.bas
bcc32 -5 -c -o%1.obj %1.c
bcc32 %1.obj \ScriptBasic\bin\libscriba_omg.obj \ScriptBasic\bin\libscriba_omg.lib

This is the content as the files are installed. In case you have more than one disk, or the installation directory is not `\ScriptBasic' you may need to edit the file you intend to use replacing the \ScriptBasic\bin\ with the actual directory where the object and library files are. It is recommended that you also edit the disk drive letter into the full path so that the command script works in case the actual working directory is on a different disk than the one where ScriptBasic is installed.

The reason that there are two different object and library files for the two different compilers is that these compilers support different object and library format. Microsoft supports the COFF format, while the free compiler available from Borland supports only OMG format. Although there is a coff2omg converter available from Borland that works only for library files that are DLL wrapper libraries and not for object files or for library files containing actual code.

These object and the library files contain the same code with the exception that they were created using different compilers.

[Contents]

7.2. Compilation under UNIX

The UNIX installation puts `libscriba.a' in the directory `/usr/local/lib'. This means that you can use the gcc option `-l' to specify this library. Therefore the command line to compile the generated C file is:

$ gcc -o myprogram myprogram.c -lm -ldl -lpthread -lscriba

This will compile the ScriptBasic generated `myprogram.c' to the executable `myprogram'.

[Contents]

8. Compiling ScriptBasic with modules

This section is rather technical and not for the BASIC programmer. This section details how to compile the ScriptBasic interpreter so that it already includes some of the external modules. This requires knowledge how to compile C programs and some programming practice of C is also helpful. If you just want to program in BASIC do not read this section and get distracted by this, skip to the next section.

ScriptBasic supports external modules that are usually delivered as DLL or SO files and using them do not require the recompilation of the interpreter. However in some cases there is a need to compile the ScriptBasic interpreter and some of the external modules into a single executable image. This may be the case when you deliver a solution to a customer and want to build a special version of the interpreter lessening the possibility of misconfiguration or you just simply want to protect your intellectual property implemented in the external module and do not want to deliver it as DLL or SO file. Linking some modules static into the interpreter also provides some speed improvement.

To link some modules into the interpreter you have to create a file named `lmt_XXX.def'. This file should list the names of the modules that you want to statically link. There can be empty lines and lines starting with the character # as comment. You can use the characters XXX (not necessarily three character, but try to avoid the word httpd and none as we have already have those) to distinguish your compilation.

After the file is created issue the command:

perl lmt_make.pl lmt_XXX.def

This will create the file lmt_XXX.c.

THIS IS CHANGED TOTALLY FOR v1.0BUILD30 and ABOVE. TO BE REWRITTEN ALTER. ACTUALLY ALL THESE THINGS SHOULD GO INTO THE DEVELOPERS GUIDE!!

If you look into the file `lmt_XXX.c' you will see that the module tables are referenced by the global table StaticallyLinkedModules. You have to give the name of the function as a string as well as the function as well. This table will be searched by ScriptBasic when the module is "loaded". When a module is loaded from a DLL or SO file such a table is provided by the operating system and is searched by operating system functions.

The next step is to compile the modules for the static linking. This is a bit different from compiling for DLL or SO file as result. When the module is compiled to be linked into a DLL or SO file all interface functions should be exported so that the operating system can access their name and entry point. When the module is compiled to be linked together with the interpreter all functions should be static. If we compiled the module the same way as for targeting DLL or SO file we were not able to link more than one module into the interpreter because the linker would complain about multiple defined versmodu and other functions that are defined in each module.

To compile a module for static linking you should use the compilation option `-DSTATIC_LINK=1' that tells the C preprocessor to define some macros differently than normal. If you look into the `Makefile' or `Makefile.nt' you will see that these compilation options are already there and all module interface files can be compiled using the tool make to its static version which is named `s_module.o[bj]'. The prefix s_ is used to denote that this version of the object file was compiled from the same C source using the options that are required for static linking of the interpreter.

Choose an appropriate executable name XXX for your version and edit the Makefile. Create the rule that compiles your version. Your version will eventually use `lmt_XXX.c' and `lmt_XXX.o[bj]' instead of `lmt_none.*' and the executable will depend on the source and should be linked with the compiled object files and libraries of the modules. As an example you can look at the variation sbhttpd that includes the CGI and the MT module linked into it.

Type

make XXX

And you should get your executable.

[Contents]

9. General Language Format

This chapter defines the language format, how to program in BASIC. The later chapters define in detail the functions available in the interpreter.

[Contents]

9.1. Hello World

ScriptBasic is a BASIC language. As such it is line oriented. The commands follow each other in the source file lines. The simplest example, the usual "hello word" example is a one-liner in basic:

print "HELLO WORLD"

You can write the commands upper or lower case or even mixed case. Therefore the following lines are equivalent:

Print "HELLO WORLD"
print "HELLO WORLD"
PRINT "HELLO WORLD"
PrInt "HELLO WORLD"

[Contents]

9.2. Strings

Strings are most frequently used entities in a BASIC program. As you could already see in the very first example strings are quoted with double quote. But they can be more than just characters between double quotes. String as a type is a basic data type of ScriptBasic. A variable having string value contains several bytes. There is no length limit for a string other than the virtual memory of the machine. A string may contain character of any code even characters that have the ASCII code zero. In other words a string is a collection of bytes of certain length. You can treat strings as arbitrary length of binary data if you need.

Strings can be concatenated, you can cut off a part of a string and several other functions and operators can handle strings. ScriptBasic automatically allocates the space required to store the string and releases the unused space when the string is not needed anymore. For more information on string handling operators and functions see the chapter Command reference.

The simplest form of a string is a strings constant appearing in the source file. This is the form like in the example

print "Hello Word\n"

Here you can note that there is a special character at the end of the string denoted by two characters. This may be familiar from other languages. The characters \n mean a new line character in a readable form. The \ (backslash) character is the escape character in a string altering the meaning of the character that follows it. The special characters that ScriptBasic handles are:

All other characters remain the same after a backslash. This means that you can write \\ to have a string containing a backslash character, or \" to have a string containing a double quote character, but \a means nothing else than the letter a.

There is another way to include special characters into string constants. The usual way in BASIC is to split the string into sub strings and concatenate the parts during run time, like in the code fragment:

St = "This is a special string, containing a bell character at the end" & chr(7)

You can do this in ScriptBasic, but you can do it easier and more effective:

St = "This is a special string, containing a bell character at the end\7" 

The last character is a number preceded by a backslash. Whenever numbers follow a backslash character in a string ScriptBasic calculates the value of the numbers and uses the character of the code. If the first character after the backslash is zero then the number is treated as octal number, otherwise it is treated as a decimal number.

Strings should not contain the new line character. In other words

St = "this is
a multi line
string of three lines."

is not legal in ScriptBasic. It was legal in former versions before v1.0build15 to write multi-line strings, but it caused problem to programmers forgetting the closing double quote character on a line. Instead a new string constant format was introduced that starts and ends with three double quote characters. For example:

St = """this is
a multi line
string of three lines."""

is perfectly correct. Strings starting and ending with three " characters can, but need not span multiple lines. There is another difference between single-line and multi-line strings. A multi-line string may contain a double quote character without escaping with backslash. You can write:

St = """this is " a double quote character """

or you can write

St = """this is \" a double quote character """

which is also correct. The only situation where you should escape a double quote character in a multi-line string is when you want to have three or more " characters following each other in a string. For example

St = """this is """ three double quote characters """ THIS IS WRONG

is wrong. You have to type instead:

St = """this is \""" three double quote characters """

or

St = """this is "\"" three double quote characters """

or

St = """this is ""\" three double quote characters """

or

St = """this is \""\" three double quote characters """

or some other variation of escaping one or more of the consecutive " characters. The rule is that there can not be three consecutive un-escaped " characters inside a multi-line string.

There is another constrain regarding multi-line strings. The very first character of a multi-line string should not be the character & or it has to be escaped with the backslash character. Thus:

St = """\& is a 
multi-line string starting with an & character """

is the correct format. If you use the & character without escaping it as the very first character of a multi-line string it will be treated as a binary multi-line string.

A binary multi-line string is a very special beast that only hard code users need to specify binary data inside a BASIC program. In such strings all new-line characters are ignored unless escaped with the back-slash character. Thus the following two strings

"""&is a 
binary multi-line\n string starting with an & character """

"is a binary multi-line\n string starting with an & character "

are equivalent with the exception that the second string is a liar, because that is not a binary multi-line string. Single-line strings can not be binary, and in case the first character of a single-line string is the & character that is just treated as a normal character.

[Contents]

9.3. Numbers

There are two types of numbers in ScriptBasic:

The integer numbers can be used to represent integral values, while real numbers can be used to represent number that have fractional part or are too large to store as integer. The integer numbers are stored in a memory location of size equivalent to a long of the programming language C. The real numbers are stored internally as C double.

Number constants can be used in the basic program in the usual format. Integer numbers are represented in either decimal or hexadecimal format. Decimal numbers contain only digits. Hexadecimal numbers start with the characters 0x or 0X and are followed by hexadecimal digits. The format that many basic implementation follows using the &H characters to start a hexadecimal number is also allowed. When a number contains a # character inside, like 2#110111 then the number preceding the # is the RADIX of the number and the characters following the # is the number in the given radix. Because the limited number of characters in the ABC the RADIX can go from 2 to 36 only. The following numbers are valid integer constants in ScriptBasic:

There is no internal difference between decimal and hexadecimal numbers for ScriptBasic. The lexical analyzer converts both format to internal representation and stores the value of the number. In other words wherever you are allowed to use a decimal number you are allowed to use a hexadecimal number or any radix number as well. You should decide whether to use decimal or hexadecimal or any other radix number for your convenience taking care of BASIC source code readability.

Real number constants can only be decimal and may contain fractional and exponential part. The followings are valid real number constants:

3.14
1.0
1.
2.3E-7

2.3e7 2.3E+7

Note that the exponent part is preceded by the character e or E and is followed optionally be a sign. The number 1. is a real number and is stored in a C double internally although it could be integer. ScriptBasic will store this number as a real number. However real numbers are automatically converted to integer values whenever ScriptBasic needs an integer value.

[Contents]

9.4. Variables

Variables are core entities of ScriptBasic. Variables are used to store string, real or integer values. Variable names start with alpha characters, underscore, dollar sign or colon, and from the second character they may contain digit characters in addition to all these characters. The last character of a variable name should not be colon.

Whenever you need a variable choose a meaningful name. If you are a real old BASIC programmer use trailing $ to denote string variables. However ScriptBasic can store any value in any variable, one at a time of course.

The colon as a name character is allowed to help name space management, and you should use it only for the purpose.

The following are valid and invalid variable name examples:

myvariable   This is a perfectly legal variable name.
main::var    This is OK. This variable is in the name space main.
chr$         This is invalid. Chr$ is a reserved word,
             this is a built-in function
apple$       This is OK. You will use it probably to store strings.
b:2          This is valid, but it is recommended not to use : inside
             variable names, because it is unreadable.
             Use colon only to separate hierarchical name space and
             variable name.

_mother If it is your taste to start a variable with underscore you can. Beee$bop Valid, but it is not recommended. The dollar sign is allowed in variable names to allow the usual BASIC string variable notation. System or application specific extensions may use predefined global variable names that contain a $ sign inside. Using such variable names you may get into conflict. ::boo This is valid. This variable is explicitly noted to be in the current name space.

_::baa This is valid. The variable is in the parent name space. ::chr$ This is valid, even though chr$ is a predefined function.

For more information on name spaces read the chapter Name spaces.

Variables can contain any data in ScriptBasic. There is nothing like integer or string variable. A variable may contain integer value at a time a real value another time and string value later. You can use a variable name to use real, integer or string value at a time; later you may use the variable as an array; later as a real again. You can change it any time.

Variables can be local or global. Global variables are those that are not declared but used (unless declare option DeclareVars is specified in the code, or declare option DefaultLocal declaration is in effect). Any variable by default is global unless it is declared to be local. Local variables are local to the function or subroutine in which they are declared to be local. To declare local variables you should use the command local. (Note that it is possible to use the directive declare option DeclareVars to require explicit variable declarations. This directive is detailed later.)

REM This is a sample program to demonstrate local variables

'A is a global variable A=13 Call MySUB Print A,"\n",B

Sub MySUB Local A A=9 B=55 End Sub

The output of the program is

13
55

This is because the variable B inside the sub is global, but the variable A is local and as such it does not alter the value of the global variable A. You can define one or more variables to be local in a local statement. If you declare more than one variable to be local then you have to separate the variable names with commas.

[Contents]

9.5. Constants

Constants are values that the program can not alter. Unlike variables constants have a single value and this value does not change during program execution. The strings and numbers that are used in a program are naturally constants. They are the simplest forms of constants without a name. However you may want to name constant values. You could store the value in a named location, in a variable but that consumes an extra variable and slows down execution.

ScriptBasic allows you to define constants using the format:

const name=value

or

global const name=value

where name is an identifier and value is a string or a number. You can not specify an expression as a value, only constant string or number. Later you can use the name of the constant in any expression where you could use the value of the constant. If you have the constant declaration:

Const nl = "\n"

then the following two lines are identical, they create the same executed code and therefore execute the same speed and need the same size of memory:

print 6+6,nl
print 6+6,"\n"

ScriptBasic evaluates named constants during syntax analysis and the name of the constant is replaced by their defined value in the expression where the constant is used.

Named constants are local to the subroutine or function they are defined in unless you use the keyword global. If you declare a constant in a module (see chapter Name spaces for more on modules and name spaces) the named constant becomes part of the name space and you can refer to the constant only with full name space specification from outside of the module. If you declare a named constant inside a function or a subroutine without the keyword global the constant becomes local, and can not be used outside of the subroutine or function.

If you use the keyword global the constant is declared global. This means that the constant is not part of any name space and can be used anywhere in the program after the line it was declared.

When ScriptBasic finds an identifier in an expression, which is not a built-in function or reserved word it checks the followings until a check succeeds:

Constants can be redefined. When a named constant is defined in a const statement ScriptBasic does not check if the constant has already be defined. It is legal to change the actual value of a constant during compile time. Note however, that this does not make a constant to be a variable. The change of the value is performed during syntax analysis and not during execution. Const statements do not generate any executable code and therefore are never executed.

When an identifier is declared as a constant the identifier can not be used as variable in an expressions following the program line that defines the constant. Sometimes you want to delete a defined constant and use the identifier as variable again. To use an identifier as a variable that was already defined as constant you can use the command

var name

where the name is the identifier. This declaration tells ScriptBasic that the identifier is not a constant anymore. This declaration is similar to the normal, non-global const declaration. If you write a var statement inside a function or subroutine the identifier becomes a local or module specific global variable in the function or subroutine only. If you write a var statement outside any function or subroutine the identifier becomes a variable in the module only.

To explain the behavior let us see an example:

module TEST
a = "GLOBAL VARIABLE"
Global Const a = "a "

Const b = "b "

sub TestSub const c = "c " ' all three identifiers are constants here print " values in TestSub=",a,b,c,"\n" ' from now on until end of the sub ' 'a' is a variable (global or local) var a

' here 'a' is a global variable print "a in sub as a global variable holds the value=",a,"\n"

' now a is defined to be a local variable from now on ' until the end of the subroutine local a a = "LOCAL VARIABLE" print "a in sub=",a,"\n" end sub

' 'a' and 'b' are constants here again as ' 'var' declaration was inside the sub print "values in the module=",a,b,c,"\n"

print "values called from within the module:\n" TestSub

' 'a' is a variable from now on (global only ' as we are global here) var a

' here a is a global variable again print "a in module=",a,"\n"

end module

' here 'a' is a global const (var a was inside the module) ' -- ' 'b' was const but not 'global const', so here it is ' a global variable again ' -- ' 'c' was inside the module, inside the sub. Here it is ' totally undef print "values outside the module=",a,b,c,"\n"

print "values called from outside the module:\n" TEST::TestSub var a print "a in global=",a,"\n"

The output is:

values in the module=a b undef
values called from within the module:
  values in TestSub=a b c
a in sub as a global variable holds the value=GLOBAL VARIABLE
a in sub=LOCAL VARIABLE
a in module=GLOBAL VARIABLE
values outside the module=a undefundef
values called from outside the module:
  values in TestSub=a b c
a in sub as a global variable holds the value=GLOBAL VARIABLE
a in sub=LOCAL VARIABLE
a in global=undef

To help understand even deeper the behavior of local, global, module specific constants and variables here we present a short description how the syntax analyzer handles the constants. You need read this only if you are curious.

There are several symbol tables during syntax analysis. ScriptBasic maintains a symbol table

When a constant is defined the name and the corresponding value gets into this symbol table. If the const statement is global the name is not altered. If the const statement is not global the name is modified to include the name space. This modification is the same as the modification for variables. After this modification an apostrophe character is appended to the constant name and the name of the actual function or subroutine if the constant is defined inside one. This is the same name decoration mechanism, which is performed for the labels.

When an identifier is found in an expression the syntax analyzer searches for the name module::constname'function in the symbol table if the expression is inside a function or subroutine. If the expression is in a global area - out of any subroutine or function - this search is not performed. If there is no such entry in the symbol table the analyzer searches for the symbol module::constname'. If this symbol is still not defined in the symbol table the analyzer searches constname.

If any of the names can be found in the symbol table the identifier constaname is replaced in the token list with the value of the constant.

When a var statement declares an identifier to be constant it actually does a weird action inside the interpreter. It redefines the constant name module::constname' or module::constname'function to be associated with the value NULL. In other words, when the syntax analyzer finds the constant name in the symbol table and retrieves the pointer that is supposed to point to the constant replacement lexical element it gets a pointer with NULL value. But it does find the constant name in the symbol table and the search finishes successfully. On the other hand the next step in the syntax analysis sees only the NULL value in the constant replacement pointer and thinks that no constant was found.

This means that if the basic program has a global constant and we declare the identifier to be a variable using a var statement the constant search stops when it finds it to be a local (either function or subroutine local or module local) constant. A local constant that happens to have a replacement pointer pointing to NULL. And it does not search for the global constant, because it did find a symbol table entry.

The same situation happens if a module constant is redefined using the var statement inside a subroutine or function.

ScriptBasic defines some named constants before it starts analyzing the program. These named constants always start with the letters sb, and their purpose is to help the programmer to set various options in option statements.

The global constants defined by the ScriptBasic interpreter are:

These constants are defined by the interpreter and there is no need to include any file to use these constants. Other constants are defined in various header files.

[Contents]

9.6. Forcing Variable Declaration

BASIC languages generally do not require variable declaration to be programmer friendly. ScriptBasic is no exception for compatibility reasons: you can write huge programs without declaring any variable. Although this is possible this is not a good practice. Programmers can easily mistype a variable name and end up getting a new variable with undef value instead of getting compilation error. This may cost a lot of debugging time.

To help programmers avoid such a situation ScriptBasic can be asked to report any such variable as compilation error. However this also means that the programmer has to declare the global variables. To tell ScriptBasic that a certain part of the program or the whole program requires variable declaration the programmer has to issue the declaration

declare option DeclareVars

This is a directive that does not generate any code, but tells the compiler to require variable declaration. To declare global variables the program should use the command global. For example

declare option DeclareVars
global a,b,c

declares three global variables a, b and c. The directive declare option DeclareVars is effective from the line where the directive is. Any undeclared variable used before the directive can also be used without declaration after the directive as well. For example:

a = 2
declare option DeclareVars
global b,c
b = 3
c = 4
print a,b,c
print

The variable a is implicitly declared before the directive and thus it can be used even after the directive. Before the directive the global variables are implicitly declared. As no global variable is allowed to be declared more than once such an implicitly declared variable should NOT be declared in a global declaration. For example

a = 2
declare option DeclareVars
global a

generates compilation time error. Once you switched on the variable declaration requirement, you should declare each new global variable until the end of the program. This means that all included or imported files should declare all global variables if you use the directive before including or importing a file. Because this may pose some incompatibility with older code you can use the directive

declare option AutoVars

Following this line the declaration is implicit again until the end of the program or until the next declare option DeclareVars. You can switch on and off global variable declaration forcing as many times as you like. It is also not an error to switch it on if this is already on, or off it is already off. The compiler does not count however the number of on and off directives. Thus

declare option DeclareVars
declare option DeclareVars
declare option AutoVars

is just the same as

declare option DeclareVars
declare option AutoVars

or just the same as

declare option AutoVars

It is always the last declare option directive, which is in charge.

Although you can mix program segments that require and do not require global variable declaration it is recommended to issue declare option DeclareVars at the start of the program and declare all global variables.

[Contents]

9.7. Arrays

Arrays are memory locations that store many values at the same time. While normal variables store a single value at a time, an array variable can store many values. The values are accessed via the name of the variable and the appropriate indices. The index or indices follow the name of the variable between [ and ]. This is the usual notation for most programming languages, like C, Perl, PASCAL, Python. Some BASIC implementations use ( and ) instead, but that confuses array access and function call.

In the following subsections we describe how to use arrays.

[Contents]

9.7.1. Creating arrays

Any variable can become an array. In ScriptBasic arrays are automatically created. There is no statement like DIM. All you have to do is to use the variable like an array. Array subscripts are written using square brackets. This is usually the convention in PASCAL and in C. Other BASIC languages use normal parentheses to index arrays. That confuses the reader as well as the parser, because function call looks the same as array access. Therefore ScriptBasic uses the square brackets.

There is no limit on the number of indices. You can use as many as you like. Also there is no limit on the index values other than the index values have to be integer and that memory may limit the array sizes. Positive, negative or zero integers can play the role of an index. Whenever you access an array element or assign a value to that ScriptBasic automatically checks if the referenced array element exists or not and adjusts the array if necessary. For example:

a[1] = 3
a[5]=4
for i=1 to 5
print a[i]
print
next

is perfectly legal and prints:

3
undef
undef
undef
4

Arrays are handled quite liberal. You are not required to declare the index bounds, you need not declare the number of indices. As a matter of fact you can have different number of indices at different points in the array. For example the following code is also legal:

a[1] = 3
a[5,3]=4
print a[1],"\n",a[5,3]

You can even write:

a[1] = 3
a[5,3,1,6,5,4,3,6,4,3,2222]=4
print a[1],"\n",a[5,3,1,6,5,4,3,6,4,3,2222]

if you wish.

What happens if you write:

a[1] = 3
a[5,3]=4
print a[1],"\n",a[5]

ScriptBasic will print

3
ARRAY@#008C0BC8

or some similar message. What has happened? To understand we have to explain how ScriptBasic stores the arrays.

An array in ScriptBasic is stored as a list of C pointers. When a ScriptBasic variable first time used as an array a new array of a single element is created. It has one element assigned to the index that was referenced.

VARIABLE[6] = 555

Later, when other elements are referenced the array is automatically extended. For example if the array was first time referenced using the index 6 and it was accessed second time using the index 11 ScriptBasic automatically extends the array to contain six elements.

VARIABLE[11] = "a string"

This means that an array can consume signifi