Copyright (C) 1998-2010 MKTMK Moscow, Russia

http://www.mktmk.narod.ru.

e-mail: mktmk<at>narod.ru

 

Interpreter Open Basic.

Users manual.

Version 1.90.

 

 

Table of contents

 

Program summary. 2

Vendor 3

Feedback. 3

Disclaimer 3

References 3

History of changes and bugs fixed. 3

List of files for distribution. 4

1. Task description and program purpose. 6

2. Terms of use. 6

3. Input and output data. 7

3.1. General information. Using of interpreter. Loading and running of *.bas programs. 7

3.2. Technical solutions review.. 8

3.3. Input-output system review.. 8

3.4. ob_obasic class methods and enumerations used for *.bas programs loading and running. 10

3.4.1. ob_obasic constructor 11

3.4.2. clear_project method. 11

3.4.3. load_project method. 11

3.4.4. run method. 11

3.4.5. set_current_input_stream method. 11

3.4.6. get_current_input_stream method. 12

3.4.7. typeend enumeration. 12

3.5. ob_obasic class methods and enumerations used for debugging process arrangement in Open Basic interpreter 12

3.5.1. step enumeration. 12

3.5.2. setstep method. 13

3.5.3. getstep method. 13

3.5.4. ob_modestream class 13

3.5.5. ob_loadbreakstr function. 13

3.6. Methods and enumerations of ob_obasic class used for conjunction of Open Basic I/O subsystem and OS I/O subsystem 14

3.6.1. General notes 14

3.6.2. setoperatorbreak and getoperatorbreak methods 14

3.6.3. setin and setout methods 14

3.6.4. ob_lex::typelex enumeration. 15

3.6.5. gettypenextlex and restoreinputpointer methods 15

3.7. Open Basic language syntax. General information. 15

3.8. Open Basic data types, names and labels 16

3.9. User defined functions in Open Basic. 18

3.9.1. Type of returned value for user-defined function. 19

3.9.2. Prototypes used for user-defined function. 19

3.9.3. User-defined functions arguments 20

3.9.4. Argument arrays structure. 20

3.9.5. Choosing of Basic-name for user-defined function. 23

3.9.6. Attaching of user-defined function to OB execution system.. 23

3.10. Methods and enumerations of ob_obasic class used for attaching and detaching of user-defined functions 25

3.10.1. ob_type_del enumeration. 25

3.10.2. setfun methods 25

3.10.3. delfun method. 25

3.11. Access to *.bas program data from user-defined function. 25

3.12. Methods and enumerations of ob_obasic class used for access to Open Basic data from user-defined functions 26

3.12.1. Methods and enumerations of ob_obasic class used for determining of Open Basic variables and arrays type 26

3.12.1.1. Enumeration ob_type_ident 26

3.12.1.2. typevar method. 26

3.12.1.3. typearray method. 26

3.12.2. Methods of ob_obasic class used for determining of length of Open Basic string variables and string arrays elements 27

3.12.3. Methods of ob_obasic class used for determining of Open Basic arrays sizes 28

3.12.4. Methods of ob_obasic class used for writing of Open Basic variables 29

3.12.5. Methods of ob_obasic class used for reading of Open Basic variables 29

3.12.6. Methods of ob_obasic class used for creating and deleting of Open Basic variables and arrays 30

3.12.6.1. Methods of ob_obasic class used for creating of Open Basic variables 30

3.12.6.2. Methods of ob_obasic class used for creating of Open Basic arrays 30

3.13. Description of other methods of ob_obasic class 31

3.14. Operators used in Open Basic. 31

3.14.1. PRINT operator 31

3.14.2. INPUT operator 32

3.14.3. FOR and NEXT operators 32

3.14.4. GOTO operator 34

3.14.5. GOSUB and RETURN operators 34

3.14.6. LET operator 35

3.14.7. DIM operator 36

3.14.8. STOP and END operators 36

3.14.9. REM operator 37

3.14.10. OPEN and CLOSE operators 38

3.14.11. KILL operator 38

3.14.12. READ, DATA and RESTORE operators 39

3.14.13. RANDOMIZE operator 40

3.14.14. IF operator 40

3.15. Built-in functions 41

3.15.1. SGN% function. 41

3.15.2. ABS function. 42

3.15.3. INT% function. 42

3.15.4. SIN, COS, ATN, SQR, EXP, LOG and LOG10 functions 42

3.15.5. RND function. 43

3.15.6. LEN% function. 43

3.15.7. DAT$ and CLK$ functions 43

3.15.8. D2STR$, D2HEXSTR$, STR2FLOAT and STR2INT% functions 43

3.16. Error handling. 44

3.17. Diagnostic messages table. 45

 

Program summary

 

Open Basic (OB) is an implementation of BASIC programming language interpreter. OB is developed for embedding into user application as scripting language.

 

OB is distributed as source code under GNU Lesser General Public License.

 

OB system commands can be expanded by attaching user-defined functions to Open Basic execution system.

 

User-defined functions can be written on C/C++ programming language and also on assembler or other languages. User-defined functions can be activated from Basic program, receive parameters of different types from Basic program and return their work results to Basic program.

 

The specially developed user-defined functions calling interface allows to determine type of parameters and their sequence during program execution.

 

OB inplements BASIC programming language subset of commands. OB is written entirely on C++ and is implemented as a class with ob_obasic class name.

 

OB supports data of three following types:

 

-        floating point data

-        signed integer data

-        string data

Also OB supports arrays of types listed above.

 

OB has multithread-safe code.

 

The following points are described in this document:

 

- using of Open Basic interpreter

- syntax of Open Basic operators

- user-defined functions interface for Open Basic data accessing

- rules for user-defined functions attaching

- Open Basic data types

- debugging options

 

OB does not use any graphical software libraries.

OB does not use any operational system calls.

 

Vendor

 

Copyright (C) 1998-2010 MKTMK Moscow, Russia

http://www.mktmk.narod.ru.

E-mail: mktmk<at>narod.ru

 

MKTMK software company, Moscow, Russia

 

Feedback

 

If you plan to use this interpreter and want to receive information about release of new versions or our E-mail/web address possible changes please contact us by E-mail.

 

MKTMK software company is interested in the interpreter application experience. The following optional information provided by you will be useful for our software product maintenance:

- tasks you use the interpreter for

- your compiler and its version number

- bugs found in the program

- documentation comprehension and mistakes found in it

- whether you have attached user-defined functions and your experience of this process

- your commentary on user-defined functions interface

- operating system that you use

- information source where you found information about our interpreter

 

 

Disclaimer

 

The interpreter and its documentation are provided on as is. MKTMK company is not responsible for possible damage or loss caused by usage of the interpreter.

We will appreciate any information provided by you about bugs and mistakes found in the program.

 

References

 

All trademarks mentioned in this document are property of their respective owners. 

 

History of changes and bugs fixed

 

03.jan.2010 version 1.90 for Windows

 

1.   Fixed bug with processing of REM operator during file loading. During commenting on string label with colon the bug caused program infinite looping during load_project method execution.

 

2.   Added option to create projects from multiple files. The option is possible due to two new added methods - clear_project and load_project which allow multiple *.bas files loading. GOTO operators can be used for jumping between the project files and GOSUB operators can be used for calling between the project files. All labels and variables of the project are avaiable to any module.

 

3.   Added option of GOTO and GOSUB usage for jumping to label placed in other file.

 

4.   Added restriction on maximum number of GOSUB nested calls. The maximum number of nested calls by default is 4096. The maximum number can be changed by using set_max_nested_gosub or get_max_nested_gosub functions.

 

5.   Added new mechanism of user code running before and after specified operator. Previously used mechanism of user code running was based on interrupt of run method execution. New mechanism is based on usage of functors and allows reducing of amount of code required for input-output process arrangement. Previously used mechanism of user code running is now considered out-of-date and is used for compatibility with already existing code. This mechanism will be removed from future versions of the interpreter and therefore is not recommended for use in new development projects. For further information please refer to setoperatorbreak and getoperatorbreak methods description in this document.

 

18.feb.2007 version 1.80 for Windows and Linux

 

1.   Fixed bug in array indexing by array element.

 

2.   Now file name in OPEN operator can be set not only as string constant but also as string variable.

 

3.   Starting from version 1.80 all *.bas programs, in addition to labels in the form of number (line numbers) support, also support string labels ending with colon.

 

4.   Getstarttime() and getstoptime() methods are excluded from ob_obasic class as not relating to primary function of the interpreter. User is able to easily control run time of any interpreter method by himself.

 

28.aug.2005 version 1.71 for Windows and Linux

 

Fixed bug in version number return function.

 

21.aug.2005 version 1.70 for Windows and Linux

 

Fixed bug in working with hexadecimal numbers.

Multithread libraries for MSVC7 are created.

 

23.feb.2005 version 1.50 for Windows and Linux

 

1998 first version for DOS

 

List of files for distribution

 

*.bas programs example files

 

.\bas

test_project1.bas

test_project2.bas

test1.bas

test2.bas

test3.bas

test4.bas

test5.bas

test6.bas

test7.bas

test8.bas

test9.bas

test10.bas

test11.bas

test12.bas

test13.bas

test14.bas

test15.bas

test16.bas

test17.bas

test18.bas

test19.bas

test20.bas

test21.bas

test22.bas

test23.bas

test24.bas

test25.bas

test26.bas

test27.bas

test28.bas

test29.bas - example files that can be executed by ob190_msvc.exe console application

 

Batch files for *.bas programs execution

 

.\bat

test1.bat

test2.bat

test3.bat

test4.bat

test5.bat

test6.bat

test7.bat

test8.bat

test9.bat

test10.bat

test11.bat

test12.bat

test13.bat

test14.bat

test15.bat

test16.bat

test17.bat

test18.bat

test19.bat

test20.bat

test21.bat

test22.bat

test23.bat

test24.bat

test25.bat

test26.bat

test27.bat

test28.bat

test29.bat - example files that run ob190_msvc.exe console application

 

Source text files

.\source

ob1.bas

ob2.bas

ob3.bas

ob4.bas

ob5.bas

ob6.bas

ob7.bas

ob8.bas

ob9.bas

ob10.bas

ob11.bas

ob11.bas - source text files

 

  Command line handler source texts files

 

.\comline

comline.cpp - functions for command line parsing

comline.h - functions for command line parsing

 

  Console application source text files

 

.\example

ob.cpp - main() of ob190_msvc.exe test example, user-defined functions and examples of attaching of user-defined functions.

 

Example of Open Basic use as a console application

 

.\exe

ob190_msvc.exe - Open Basic MSVS 2008 console application

It receives name of text file with *.bas program as a parameter and executes it. When run with -? switch, it prints list of its switches. Use for .NET platform only (WinXP and later).

 

Description files

 

.\htm

read_rus.htm - file containing Russian version of users manual file

read_eng.htm - file containing English version of users manual file

shortrus.htm - file containing Russian version of brief reference book about ob_obasic class methods and enumerations

shorteng.htm - file containing English version of brief reference book about ob_obasic class methods and enumerations 

 

Header files

 

.\include

mstore.h - data storage policies

mvect.h - vector

mlist.h - list

mstack.h - stack

mhash.h - hash table

ob.h - Open Basic main header file

 

1. Task description and program purpose

 

During work in user application it is often become necessary to use simple scripting language. Such task appears when application operates with some amount of primitives that should be called in different sequence according to different work modes.

 

Examples:

 

- database requests with various conditions of data sampling

- hardware and/or software testing

- communication with nonstandard hardware using different communication channels

- Graphical User Interface making and manipulations with GUI objects

- terminal input language for command line parsing

- input language for use by operator in automated industrial control system tasks

- complex configuration files input language

- etc

 

Graphical User Interface makes process of task automatization more difficult. Therefore it is often necessary to complement Graphical User Interface with features provided by the scripting language.

 

The Open Basic interpreter is developed for embedding into user applications as scripting language.

 

OB is distributed as source code under GNU LGPL (Lesser General Public License).

OB command system can be expanded by attaching user-defined functions to Open Basic execution system.

 

User-defined functions can be written on C/C++ programming languages, assembler or other languages. User-defined functions can be activated from Basic program, receive parameters of different types from Basic program and return their work results to Basic program.

 

User-defined functions have access to all variables and arrays of Basic program, and not only to those transferred by using of parameters. This access is based on names of variables and arrays. 

2. Terms of use

 

Open Basic is written entirely on C++ and does not use system calls of any operation system. Open Basic can be used along with any graphical software library.

 

3. Input and output data

 

3.1. General information. Using of interpreter. Loading and running of *.bas programs.

 

The Open Basic interpreter is implemented as a class with ob_obasic name. The interpreter work consists in execution of program written on BASIC programming language. In this users manual file such program is called a *.bas-program. The *.bas-program can be either a text file or a buffer in memory opened as istream data stream.

 

The following definitions are further used in users manual file:

 

1. "operator" operator of BASIC language(for example, PRINT, FOR etc)

2. "user-defined function" - user-defined function attached to Open Basic execution system

3. "function" - C++ function

4. "method" - method of ob_obasic class

5. "*.bas-program" program written on BASIC programming language

 

In order to use the interpreter one should:

 

1.   Download from http://www.mktmk.narod.ru archive containing:

-        interpreter source code

-        ob.h header file

-        header files with template containers implementation(mstore.h,mvect.h,mlist.h,mstack.h,mhash.h);

 

2.   Include interpreter source code into the project;

3.   Indicate path in the project for attaching of ob.h interpreter header file;

4.   Indicate path in the project for attaching of template containers header files (mstore.h,mvect.h,mlist.h,mstack.h,mhash.h);

5.   Include ob.h header file of interpreter into your C++ files using #include directive;

6.   Make declaration about usage of interpreter namespace using namespace ob_charspace;

7.   Create ob_obasic class instance in your C++ program;

8.   If streams used for input or output differ from standard cin or cout streams then intercept interpreters input and output using setoperatorbreak, setin and setout methods;

9.   Clear project using clear_project method;

10.Load program for execution using load_project method;

11.Run program for execution using run method.

 

Example:

 

//loading and running of test1.bas program

ifstream inp1("test1.bas",ios::binary);//input stream opening

ob_obasic basic_interpreter;//creation of interpreter instance

basic_interpreter.clear_project();//project clean-up

basic_interpreter.load_project(&inp1);//loading of test1.bas using load_project method

basic_interpreter.run();//test1.bas program running

 

ATTENTION! Input stream should be opened in ios::binary mode.

 

EXPLANATION:

 

Despite the fact that *.bas program itself is a text file, as a stream it should be opened in ios::binary mode. This should be done due to some features of carriage return characters and line feed processing in ios::text mode.

 

Example:

 

//loading and running of test2.bas and test3.bas programs after test1.bas program termination

ifstream inp2("test2.bas",ios::binary);//input stream opening

ifstream inp3("test3.bas",ios::binary);//input stream opening

basic_interpreter.clear_project();//project clean-up

basic_interpreter.load_project(&inp2);//*.bas program loading

basic_interpreter.load_project(&inp3);//*.bas program loading

basic_interpreter.set_current_input_stream(&inp2);//setting of inp2 stream as first in run queue

basic_interpreter.run();//test2.bas program running

 

ATTENTION! Input stream should be opened in ios::binary mode.

 

ATTENTION! If project consists of multiple files (streams), then last loaded file (stream) will be first to be run. In order to set a file (stream) that should be run first set_current_input_stream method should be used.

 

3.2. Technical solutions review

 

The following main problems were solved during development of the interpreter:

 

1.   Ability to store Basic program in file on disc or buffer in memory. To provide this ability the interpreter receives input program as istream* input stream pointer. The actual stream type (file on disc or buffer in memory) is determined by user. In the same way input stream for INPUT operator and output stream for PRINT operator can be either files or memory buffers.

 

2.   In order to provide more flexible usage OB has three stages of *.bas-programs execution process:

 

-        First stage is project clean-up using clear_project method. During project clean-up process internal tables of the interpreter are cleaned from previous project data (clean-up of jump labels tables, tables of variables and array etc).

 

-        Second stage is program loading using load_project method. During the process of loading jump labels table is created and internal variables are set up. Set of files (streams) that are simultaneously loaded in instance of the interpreter is called a project. All variables, arrays and labels in the project have common interaction space. Labels in all project files (streams) must not repeat. All variables created in one file of the project are available for all other files of the project.

 

-        Third stage is program execution using run method. During the execution process reading of program text and performing of different actions (variables and arrays creating, calculation and value assignment to variables, operators or functions execution) take place.

 

The termination of run method happens due to following reasons:

 

-        expire of input stream

-        syntax error in the program

-        breakpoint character

-        end of line character with flag of step-by-step work mode set on

 

On its termination run method returns exit code. By analyzing this code user is able to know the reason of method termination.

After its termination run method can be continued without new loading of the program.

 

3.   One instance of the interpreter is able to perform one project at the given moment of time. The program can contain several instances of the interpreter. The interpreter does not have static data members (except constants available for reading). Therefore several instances of the interpreter are able to work simultaneously in different threads.

 

4.   User-defined functions in Open Basic have identical interface. This interface allows to analyse types of parameters and sequence of parameters of user-defined functions during runtime. Such type of approach requires careful work of developer; on the other hand, such approach does not limit the ability of creating user-defined functions with various parameters.

 

5.   The ob_obasic class itself is not a template; therefore it can be taken out to static or dynamic library. This action allows reducing of translating time.

 

3.3. Input-output system review

 

There are two alternative ways of data input-output process arrangement from/to the interpreter:

 

  1. Using PRINT and INPUT operators along with auxiliary input-output classes (functors)
  2. Using user-defined functions of input-output

 

First way of input-output process arrangement.

 

During execution of *.bas program the interpreter works with internal variables and arrays and also with user-defined functions. All these objects are arranged in tables. All actions with these objects are performed without calling of operating system services and by means of the interpreter execution system only. But I/O operators (PRINT and INPUT) require calling of operating system services because specific type of input-output process and way of its realization may vary a lot depending on different operating systems and different applications. For conjunction of the interpreter I/O subsystem and OS I/O subsystem setoperatorbreak, setin and setout methods are used.

 

PRINT operator sends data to output data stream. This data stream is connected to the interpreter using setout method. Usually ostrstream class with static buffer is used as output stream. By default cout is used as output stream.

 

INPUT operator receives data from input data stream. This input stream is connected to the interpreter using setin method. Usually istrstream class with static buffer is used as input stream. By default cin is used as input stream.

 

For conjunction of the interpreter I/O subsystem and OS I/O subsystem user should create two functor classes that are derivatives from ob_functor_break_base class:

 

class ob_functor_break_base{

public:

ob_functor_break_base(){}

virtual ~ob_functor_break_base(){}

virtual void run_before(ob_obasic* basicptr)=0;

virtual void run_after(ob_obasic* basicptr)=0;

};

 

In these ob_functor_break_base class derivatives user redefines run_before and run_after methods. After this user creates reference to functors in the interpreter using setoperatorbreak method.

 

Run_before and run_after methods are run before and after input-output operators execution respectively. In run_before methods user prepares input-output streams for the interpreter. In run_after methods user processes input-output results.

 

Functor instances should be in the same scope with ob_obasic interpreter instance. If the program contains several ob_obasic interpreter instances then each of them should have its own input-output functor instances.

 

Example (from ob.cpp file)

 

-        creating of functor for output (for PRINT operator)

 

class ob_functor_break_print_def:public ob_functor_break_base{

char printbuffer[ob_maxlengthstring];

ostrstream pr;

public:

ob_functor_break_print_def():pr(printbuffer,ob_maxlengthstring){}

virtual ~ob_functor_break_print_def(){}

 

void run_before(ob_obasic* basicptr){

printbuffer[0]=0;

pr.clear();

pr.seekp(0);

basicptr->setout(&pr);

}

 

void run_after(ob_obasic* basicptr){

if(printbuffer[0]!=0){

pr<<ends;

 

//-------------------------------------------------

cout<<printbuffer;//your output code place here

//-------------------------------------------------

 

}//if

}

};

-        creating of functor for input (for INPUT operator)

 

class ob_functor_break_input_def:public ob_functor_break_base{

char inputbuffer[ob_maxlengthstring];

char inputbuffer1[ob_maxlengthstring];

strstream pr;

public:

ob_functor_break_input_def():pr(inputbuffer1,ob_maxlengthstring){}

virtual ~ob_functor_break_input_def(){}

 

void run_before(ob_obasic* basicptr){

 

ob_lex::typelex tll=basicptr->gettypenextlex();

basicptr->restoreinputpointer();

 

if(tll!=ob_lex::SHARP){

 

inputbuffer[0]=0;

 

//-------------------------------------------------

cin>>inputbuffer;//your input code place here

//-------------------------------------------------

 

pr.clear();

pr.seekp(0);

 

pr<<inputbuffer;

 

pr.seekg(0);

basicptr->setin(&pr);

}//if

}

 

void run_after(ob_obasic* basicptr){}

};

 

-        creating of functor instances

 

ob_functor_break_print_def ob_functor_break_print;

ob_functor_break_input_def ob_functor_break_input;

 

-        creating of references to functors in the interpreter instance

 

example_basic_interpreter.setoperatorbreak("PRINT",&ob_functor_break_print);

example_basic_interpreter.setoperatorbreak("INPUT",&ob_functor_break_input);

 

In example given input-output is performed from/to standard cin and cout streams. Given examples of functors can be used in GUI-using program by replacing the following lines

 

//-------------------------------------------------

cout<<printbuffer;//your output code place here

//-------------------------------------------------

 

//-------------------------------------------------

cin>>inputbuffer;//your input code place here

//-------------------------------------------------

 

by users code of input-output from/to corresponding Windows window.

 

Second way of input-output process arrangement.

 

Input-output process can be arranged without using of PRINT and INPUT operators by using of input-output user-defined functions. User writes his own input-output user-defined functions, and then registers them in the interpreter so that these input-output user-defined functions are used in *.bas program text instead of PRINT and INPUT operators.

 

3.4. ob_obasic class methods and enumerations used for *.bas programs loading and running

 

3.4.1. ob_obasic constructor

 

ob_obasic(ostream* o=&cout,istream* read=&cin);

 

creates an instance of Open Basic interpreter.

 

Constructor arguments:

 

1. o argument- pointer that points on output stream in which data is output by PRINT operator.

 

ATTENTION! The output stream must be opened in ios::text mode.

 

EXPLANATION:

 

The output stream itself is an ordinary text stream in which text data is output.

 

2. read argument - pointer that points on input stream from which data is read by INPUT operator.

 

ATTENTION! The input stream must be opened in ios::binary mode.

 

3.4.2. clear_project method

 

During its work the interpreter creates following tables:

 

1. table of variables

2. table of arrays

3. user-defined functions table

4. DATA operator data table (stream)

5. table of labels

6. table of FOR operators cycles

7. table of active files

8. GOSUB subprograms table (stack)

 

Clear_project method clears all tables except for user-defined functions table.

 

User-defined functions table can be erased only by void clrtablfun(); method calling.

 

3.4.3. load_project method

 

void load_project(istream* i) method; - this method loads *.bas program.

 

The argument of this method is a pointer which points on the stream where *.bas program is contained.

 

ATTENTION! This stream must be opened in ios::binary mode.

 

The internal pointer of stream data should point on program start.

After the interpreter finishes its work the internal pointer points on program end. In order to run the same program one more time one should transpose the internal pointer using seekg method and reload the program using load_project method.

 

Load_project method is able to load several streams simultaneously. A set of simultaneously loaded streams is called a project.

 

3.4.4.  run method

 

typeend run(); method - this method runs loaded program or continues program execution after program stop with returning of exit code. If the project consists of more than one stream then last loaded stream is run. In order to set stream to be run one should use set_current_input_stream method.

 

3.4.5. set_current_input_stream method

 

set_current_input_stream(ob_istreamcommon* i) method points on stream that should be executed first when run() method is called. The i stream should be loaded beforehand using load_project method.

 

3.4.6. get_current_input_stream method

 

ob_istreamcommon* get_current_input_stream() method returns current running stream.

 

3.4.7. typeend enumeration

Enumeration

enum typeend{

DUMMYEND,ENDFILEEND,ENDOPERATORDETECT,EOLEND,BREAKPOINTEND,NOLOADEND,

BREAKBEFOREOPERATOR,BREAKAFTEROPERATOR

};

 

defines run method exit code.

 

Exit codes are the following:

 

1. typeend=DUMMYEND this code is never returned by run method during normal work and is used for internal jumps.

 

2. typeend=ENDFILEEND this code means that run method has been terminated because of input stream expiration. This is normal termination of *.bas-program if END operator is not present in *.bas-program.

 

3. typeend=ENDOPERATORDETECT this code means that run method has been terminated because of detection of END operator. This is normal termination of *.bas-program.

 

4. typeend=EOLEND - this code means that run method has been terminated after current line execution because step=STEP flag was set using setstep method.

 

5. typeend=BREAKPOINTEND - this code means that run method has been terminated after reading of '@' character that is used as a breakpoint character in Open Basic

 

6. typeend=NOLOADEND - this code means that run method has terminated because load_project method had not been executed and input stream had not been opened.

 

7. typeend=BREAKBEFOREOPERATOR - this code means that run method has terminated before OB operator execution. This termination mode is left for compatibility with already existing code and is not recommended for use in new development projects. This mode will not be available in future versions of the interpreter.

 

8. typeend=BREAKAFTEROPERATOR - this code means that run method has terminated after OB operator execution. This termination mode is left for compatibility with already existing code and is not recommended for use in new development projects. This mode will not be available in future versions of the interpreter.

3.5. ob_obasic class methods and enumerations used for debugging process arrangement in Open Basic interpreter

 

OB has two debugging modes: first is step-by-step *.bas-programs execution, second is breakpoints assignment.

Step-by-step *.bas-programs execution is implemented by setstep method.

The '@' character placed in separate line of *.bas-program text implements a breakpoint.

There can be several breakpoints in *.bas-program. After all breakpoints are specified the *.bas-program should be reloaded using load_project method.

When control is transferred to line containing '@' character the program halts.

In this case exit code of run method is BREAKPOINTEND. In order to continue program execution run(); method should be run again.

 

3.5.1. step enumeration

 

enum step{NOSTEP,STEP}; enumeration - this enumeration determines step-by-step program execution mode. This enumeration is used in setstep and getstep methods. Default value is step=NOSTEP.

If step=NOSTEP the program is executed without interruptions.

If step=STEP the program is terminated with typeend=EOLEND code after each program line execution.

 

3.5.2. setstep method

 

void setstep(step ts) method - this method sets step-by-step program execution mode on or off. This method can be used at any moment of the interpreter work.

If step-by-step program execution mode is set on then run(); method will be terminated after execution of each *.bas-program line. In order to continue program execution run(); method should be run again.

 

3.5.3. getstep method

 

step getstep() method this method returns current mode of step-by-step program execution.

 

3.5.4. ob_modestream class

 

ob_modestream class will be used for processing of UNICODE and UTF-8 files. These modes are not supported in version 1.90 of the interpreter. The corresponding fields in functions callings are set equal to default constructor ob_modestream().

 

3.5.5. ob_loadbreakstr function

 

The function is:

 

bool ob_loadbreakstr(

ob_istreamcommon* in1,

ob_type_stringsize lengthbuffers,

ob_type_char* ptrbefore,

ob_type_char* ptrcurrent,

ob_type_char* ptrafter,

ob_modestream ms=ob_modestream()

);

 

where:

 

istream* in1 - current input executable *.bas-file

lengthbuffers - length of ptrbefore, ptrcurrent, ptrafter buffers

ptrbefore - buffer for line that goes before current executable line

ptrcurrent - buffer for current executable line

ptrafter - buffer for line that goes after current executable line

ob_modestream - input file format flag. In version 1.90 of the interpreter this flag is given by default.

 

Function ob_loadbreakstr loads corresponding lines of currently running program into selected buffers.

 

Function ob_loadbreakstr is not a method of ob_obasic class.

 

Example:

 

//Creating of the interpreter and running of program in step-by-step mode

//with printing of currently executable lines

ob_type_char strbefore[ob_maxlengthstring];//buffer

ob_type_char strcurrent[ob_maxlengthstring];//buffer

ob_type_char strafter[ob_maxlengthstring];//buffer

ob_obasic basic_interpreter;//creating of the interpreter

//loading and running of test1.bas program

//with step-by-step program execution

//and printing of currently executable lines

ifstream inp1("test1.bas",ios::binary);//input stream opening

basic_interpreter.clear_project();//project clean-up

basic_interpreter.load_project(&inp1);//loading of test1.bas program

basic_interpreter.setstep(ob_obasic::STEP);//setting of step-by-step mode

while(1){

if(basic_interpreter.run()!=ob_obasic::EOLEND) break;//running of *.bas-program

ob_loadbreakstr(&inp1,ob_maxlengthstring,strbefore,strcurrent,strafter);

cout<<endl<<"String current: "<<strcurrent;

}//while

3.6. Methods and enumerations of ob_obasic class used for conjunction of Open Basic I/O subsystem and OS I/O subsystem

 

3.6.1. General notes

 

During the execution of *.bas program the interpreter works with internal variables and arrays and user-defined functions. All these objects are arranged into tables. All actions with these objects are performed without caling of operating system services and by means of the interpreter execution system only. But I/O operators (PRINT and INPUT) require calling of operating system services because specific type of input-output process and way of its realization may vary a lot depending on different operating systems and different applications. For conjunction of the interpreter I/O subsystem and OS I/O subsystem setoperatorbreak, setin and setout methods are used.

 

3.6.2. setoperatorbreak and getoperatorbreak methods

 

For each of the operators in OB (PRINT, INPUT, FOR etc) it is possible to execute user code before and after execution of the operator. Usually this option is used for operators like PRINT, INPUT, i.e. for input and output process organizing during operator work in GUI-based application.

 

bool setoperatorbreak(ob_type_char* name,ob_functor_break_base* b);

 

Method arguments:

 

1. name operator name

2. ob_functor_break_base* b functor pointer

 

return value:

 

true - termination successful

false operator name is not found

 

To know more about use of setoperatorbreak method refer to p. 3.3 Input-output system review of this document.

 

Method

 

bool getoperatorbreak(ob_type_char* name,ob_functor_break_base** b);

 

allows to get functor pointer. If functor has not been set for specified operator then b=0. Returns false if operator name is not found. By default functors are not set for all operators.

 

3.6.3. setin and setout methods

 

These methods allow redefining input and output streams previously defined in the constructor.

 

void setin(ob_istreamcommon* i);

void setout(ob_ostreamcommon* o);

 

ATTENTION! Input stream must be opened in ios::binary mode.

ATTENTION! Output stream must be opened in ios::text mode.

 

setin method redefines rd stream of the constructor.

setout method redefines o stream of the constructor.

 

3.6.4. ob_lex::typelex enumeration

 

This enumeration defines current lexical token.

 

enum typelex{

PLUS,MINUS,MUL,DIV,POWER,ASSIGN,LP,RP,STRING,SEMICOLON,COMMA,ENDPROGRAMM,EOL,

LESS,GREAT,SHARP,BREAKPOINT,

DECINTNUMBER,HEXINTNUMBER,FLOATNUMBER,

FUNC,OPERATOR,

OLDVARIABLE,OLDARRAY,NEWNAME,

BAD

};

 

3.6.5. gettypenextlex and restoreinputpointer methods

 

These methods are used for simplification of input and output operators implementation.

 

- ob_lex::typelex gettypenextlex();

- void restoreinputpointer();

 

Method

ob_lex::typelex gettypenextlex();

 

This method returns next lexical token from input stream. Some operators (for example, INPUT operator) have the same syntax for input from file and console input. Current direction of input is determined by next # lexical token. Using gettypenextlex() method one can determine next lexical token type and thereby determine where input is expected from.

 

Method

void restoreinputpointer();

 

This method is used for recovering of input stream state after use of gettypenextlex().

 

In example given in p. 3.3 Input-output system review gettypenextlex and restoreinputpointer methods are used for input direction determination in INPUT operator. If SHARP lexical token is detected, console input will not be performed. PRINT operator does not need such code because output does not block the work process.

 

3.7. Open Basic language syntax. General information

 

ATTENTION! All objects of *.bas-program like variables, arrays, user-defined functions etc must have different names.

 

The Open Basic interpreter supports subset of Basic language operators. These operators are described below. It is possible to work with three types of data: floating-point, integer and string. Also it is possible to work with arrays consisting of these data types.

 

Variables in Open Basic do not need to be described before their first use. The first appearance of a variable in a program should be on the left of assignment operator.

 

Arrays in Open Basic should be described before their first use by DIM operator. Arrays can be multidimensional. Data for arrays and variables is arranged in free memory by new operator. The maximum size of array depends on new operator restrictions in each specific operating system.

 

In Open Basic first index of array is 1 (not 0).

 

Unlike DIM operator of standard Basic language DIM operator of Open Basic is executable. It is executed every time the control is transferred on it.

 

It is possible to repeat description of array with the same name in DIM operator. New array can have dimensions that differ from old array dimensions. During this process old data is lost. Such procedure can be used for memory release. After huge array is captured by DIM operator it is possible to release some memory by describing array with the same name and dimension of one element.

 

When describing array in DIM operator integer variables can be used as dimensions.

 

When created numerical variables and arrays are initialized by zero. String variables and arrays are initialized by empty string ("").

 

Range of floating-point and integer data depends on C++ compiler. Usually integer data is int and floating-point data is float. In file ob.h types of variables are determined using typedef:

 

typedef char ob_type_char;

typedef float ob_type_flo;

typedef int ob_type_int;

 

The maximal length of string variables is determined by ob_maxlengthstring constant in ob.h file. For OB v1.90 ob_maxlengthstring=4096.

A *.bas-program can contain empty strings.

The Open Basic interpreter supports the following operations with integer data and floating-point data:

 

+ - addition

- - substraction

* - multiplication

/ - division

^ - involution

- - unary minus

+ - unary plus

= - assignment

 

relational expressions

 

< - "less than"

> - "greater than"

= - "equal"

<> - "not equal"

<= - "less or equal"

>= - "equal or greater"

 

Relational expressions are used in IF operator.

String data supports only addition, comparison and line assignment operations.

 

3.8. Open Basic data types, names and labels

 

As with standard Basic language, type of a variable or an array in Open Basic

is determined by its name. For example:

- if variable or array name ends with '%' character then this variable or array is of integer type.

- if variable or array name ends with '$' character then this variable or array is of string type.

- if variable or array name ends with any other character then this variable or array is of floating-point type.

 

Many Open Basic types are described in ob.h using typedef.

ob_type_flo type is reflected to float type using typedef.

ob_type_int type is reflected to int type using typedef.

In user-defined functions it is recommended to use ob_type_flo and

ob_type_int types, so that if, for example,ob_type_flo is changed from float to double, types compatibility will be supported.

 

It is possible to use any combinations of letters and numbers for names of variables, arrays and user-defined functions. The first symbol of the name must be a letter.

Letters used in a name can be upper case or lower case. The underline symbol '_' and '$' and '%' symbols are also considered as letters.

Letters in names are not reduced to one register.For example, MASS, mass

and Mass are three different names.

The maximum length of a name is determined by ob_maxlengthstring constant in ob.h file. For OB v1.90 ob_maxlengthstring=4096.

 

Example:

 

Array declaration of and initialization of two variables of integer and floating-point type. The last dimension of the array is specified by a variable. Type of mass array elements is floating-point. The counter% variable is of integer type. The data variable is of floating-point type.

 

counter%=7

DIM mass(2,3,10,counter%)

data=counter%+37.77

 

Example:

 

Array declaration and using of it. Another declaration of array with same name but other dimension and using of it.

  

DIM mass(10)

 

FOR i%=1 TO 10 STEP 1

mass(i%)=i%+37.77

NEXT i%

 

counter%=7

 

DIM mass(counter%,3)

 

FOR i%=1 TO counter% STEP 1

mass(i%,2)=i%+37.77

NEXT i%

 

If the expression uses data of different types then types reduction is used.

If the expression uses data of integer type and data of floating-point type then the resultant type will be floating-point.

During assignment operation execution the type of expression on the right is reduced to the type of expression on the left of = assignment sign.

If a variable of integer type is on the left of the assignment sign and a variable of floating-point type is on the right of it then fractional part of floating-point type variable is truncated.

 

The Open Basic supports labels in the form of line numbers. These numbers do not have to be running is succession. It is not necessary to enumerate every line of the program. GOTO and GOSUB operators perform jump only to enumerated line. It is also possible to create label for empty line.

 

Example:

 

ii%=6

ik%=8

 

IF ii%<>6 THEN GOTO 10

 

PRINT "ii%=";ii%;

10 PRINT " ii%!=6"

 

IF ik%=7 THEN GOSUB 11

 

PRINT "ik%=";ik%;

GOTO 12

11

PRINT " ik%!=7"

RETURN

12

STOP

END

 

Starting from version 1.80 all *.bas programs, in addition to labels in the form of number (line numbers) support, also support string labels ending with colon. The colon is a part of label identifier and should follow label identifier without separation symbol. In GOTO and GOSUB operators string label identifier should be written without colon on its end. Labels in the form of number (line numbers) and string labels can be used in the program simultaneously. String label must start with a letter.

 

Example:

 

REM Test string label

 

PRINT

PRINT "Start--------------------------------"

 

loop_counter%=10

 

FOR i%=1 TO loop_counter%

 

PRINT "-------------------------------- ";"pass=";i%

 

GOSUB gosub_label_1

GOSUB gosub_label_2

GOSUB gosub_label_3

GOSUB gosub_label_4

 

NEXT i%

 

PRINT "End program OK"

 

10

STOP

END

 

gosub_label_1:

PRINT "gosub_label_1"

 

a%=i%/2*2

 

IF a%=i% THEN GOTO goto_label_1

PRINT "do not goto detect"

ENDIF

 

goto_label_1:

 

RETURN

 

gosub_label_2: PRINT "gosub_label_2"

 

a%=i%/2*2

 

IF a%=i% THEN GOTO goto_label_2

PRINT "do not goto detect"

ENDIF

 

 

goto_label_2:RETURN

 

gosub_label_3:

PRINT "gosub_label_3"

RETURN

 

gosub_label_4:

PRINT "gosub_label_4"

RETURN

 

3.9. User defined functions in Open Basic

 

OB system commands can be expanded by attaching user-defined functions to Open Basic execution system.

 

Arguments of user-defined functions allow determining of call arguments type and their sequence during the program execution.

 

User-defined functions are attached to Open Basic execution system under certain names (so-called Basic-names). Each user-defined function is attached under its own Basic-name. After functions are attached they can be called in *.bas-program text using their Basic-names. It is possible to pass parameters to user-defined functions and get results from user-defined functions. User-defined functions can be called without parameters. User-defined functions can be written on C/C++, assembler or other languages.

 

All user-defined functions have 2 names:

 

1. C++ function name included in project, which name allows function calling from C++ program.

2. Basic-name function name, which name allows function calling from *.bas-program.

 

The first name (C++ function name) is obtained by user-defined functions upon their creation (writing). The second name (Basic-name function name) is obtained by user-defined functions when they are attached to Open Basic execution system using setfun method.

 

User-defined function can be based on one of three following prototypes:

 

-        Function that returns floating-point value

-        Function that returns integer value

-        Function that returns string value

 

In order to create user-defined function and attach it to Open Basic execution system one should perform the following actions:

 

1. Choose type of returned value for user-defined function

2. Choose C++ function name for user-defined function

3. Create user-defined function using one of three prototypes listed above

4. Choose Basic-name function name for user-defined function

5. Attached user-defined function to Open Basic execution system using setfun method and using Basic-name function name and C++ function name as parameters

 

After these actions are done it is possible to use Basic-name function name in *.bas-program.

 

3.9.1. Type of returned value for user-defined function

 

User-defined function can return values of three following types:

 

- floating-point type ob_type_flo

- integer type ob_type_int

- string type ob_type_char*

 

 

3.9.2. Prototypes used for user-defined function

 

User-defined function can be based on one of three following prototypes:

 

1. Functions that return floating-point value

 

ob_type_flo name_flo(

ob_obasic* basic_ptr,

const ob_type_char* parstring,

const ob_type_parnum *descrf,

const ob_type_parnum *descri,

const ob_type_parnum *descrc,

const ob_type_flo* parf,

const ob_type_int* pari,

const ob_type_char* parc

);

 

2. Functions that return integer value

 

ob_type_int name_int(

ob_obasic* basic_ptr,

const ob_type_char* parstring,

const ob_type_parnum *descrf,

const ob_type_parnum *descri,

const ob_type_parnum *descrc,

const ob_type_flo* parf,

const ob_type_int* pari,

const ob_type_char* parc

);

 

3. Functions that return string value

 

ob_type_char* name_char(

ob_obasic* basic_ptr,

const ob_type_char* parstring,

const ob_type_parnum *descrf,

const ob_type_parnum *descri,

const ob_type_parnum *descrc,

const ob_type_flo* parf,

const ob_type_int* pari,

const ob_type_char* parc

);

 

All these prototypes differ only by type of value they return.

 

File ob.h contains OB_DECLARE_USER_FUNCTION(name,typeret)macro that can be used for user-defined functions declaration. The name parameter is C++ function name, typeret parameter is type of returned value.

 

Example:

 

Decraration of user-defined function using OB_DECLARE_USER_FUNCTION macro.

C++ function name is "myfun1".

Type of returned value is ob_type_flo.

 

OB_DECLARE_USER_FUNCTION(myfun1,ob_type_flo);

 

Example:

 

Determination of user-defined function using OB_DECLARE_USER_FUNCTION macro.

C++ function name is "myfun2".

Type of returned value is ob_type_int.

 

OB_DECLARE_USER_FUNCTION(myfun2,ob_type_int){

return 365;

}

 

Example:

 

Determination of user-defined function using OB_DECLARE_USER_FUNCTION macro.

C++ function name is "myfun3".

Type of returned value is ob_type_char*.

 

OB_DECLARE_USER_FUNCTION(myfun3,ob_type_char*){

return "Hello world";

}

3.9.3. User-defined functions arguments

 

User-defined functions interface in Open Basic is specially developed to provide ability to control actual arguments in calling during program execution.

 

To provide this ability the set of user-defined functions parameters contains two sets of arrays.

 

First set is set of arrays containing argument descriptions descrf, descri, descrc.

These arrays contain information about quantity and sequence order of actual arguments in user-defined function calling.

 

Second set is set of arrays containing argument values parf, pari, parc. These arrays contain values of actual arguments in user-defined function calling.

 

Purpose and structure of descr* and par* arrays are given detailed description in next part of this document.

 

3.9.4. Argument arrays structure

 

There are three types of user-defined functions. All these types have same arguments and different types of returned result.

 

Let us consider user-defined function arguments by example of function that returns floating-point type value.

 

ob_type_flo name_flo(

ob_obasic* basic_ptr,

const ob_type_char* parstring,

const ob_type_parnum *descrf,

const ob_type_parnum *descri,

const ob_type_parnum *descrc,

const ob_type_flo* parf,

const ob_type_int* pari,

const ob_type_char* parc

);

 

Function arguments:

 

1. ob_obasic* basic_ptr pointer on ob_obasic interpereter instance to which the function is attached. Used for accessing program variables by using ob_obasic methods.

 

2. const char* parstring string representations of arguments.

 

Example:

 

If USER_FUN1 function is called with arguments USER_FUN1(1.123,a_a%,1+2) then parstring array will contain following strings: "1.123","a_a%","1+2".

These strings will be stored sequentially and separated by zero.

 

3. argument descriptions arrays descr*:

 

const ob_type_parnum *descrf for floating-point type arguments

const ob_type_parnum *descri - for integer type arguments

const ob_type_parnum *descrc - for string type arguments

 

these arrays desctibe quantity, types and position of all arguments that were passed to user-defined function from *.bas-program. These arrays are used to control quantity, type and sequence order of arguments in calling of user-defined function.

 

Structure of descrf arrays (other arrays have same structure):

 

descrf[0] count of floating-point type arguments in current calling

Other elements of descrf array (their quantity is descrf[0]) are ordinal numbers of floating-point type parameters in current calling.

Ordinal numbers are counted starting from 1.

 

Example:

 

If USER_FUN1(1.123,a_a%,1+2) are set as USER_FUN1 function arguments in calling of this function then

 

descrf array will contain following numbers: 1,1

descri array will contain following numbers: 2,2,3

descrc array will contain following numbers: 0

 

Example:

 

If USER_FUN1("str1","srt2"+"str3",1.1,1.2,1.3,1.4) are set as USER_FUN1 function arguments

in calling of this function then

 

descrf array will contain following numbers: 4,3,4,5,6

descri array will contain following numbers: 0

descrc array will contain following numbers: 2,1,2

 

4. argument values arrays par*:

 

const ob_type_flo* parf - for floating-point type arguments

const ob_type_int* pari - for integer type arguments

const ob_type_char* parc - for string type arguments

 

these arrays describe values of all corresponding types arguments that were passed to user-defined function in current calling from *.bas-program.

 

The arguments will be in succession, strings in parc array, as well as in parstring array, are separated by trailing zero.

 

Example:

 

([a_a%] is value of variable with name of a_a%)

 

If USER_FUN1 function is called with arguments USER_FUN1(1.123,a_a%,1+2) then

 

parf array will contain following numbers: 1.123

pari array will contain following numbers: [a_a%],3

parc array will not contain any values

 

Example:

 

If USER_FUN1 function is called with arguments USER_FUN1("str1","srt2"+"str3",1.1,1.2,1.3,1.4) then

 

parf array will contain following numbers: 1.1,1.2,1.3,1.4

pari array will not contain any values

parc array will contain following strings: "str1","srt2str3"

 

ob.h file contains OB_DECLARE_USER_FUNCTION(name,typeret) macro that can be used for user-defined functions declaration. The name argument is C++ function name, typeret argument is the type of returned value.

 

Maximum number of arguments is determined by ob_maxnumpar constant in ob.h file.

For OB v1.90 ob_maxnumpar=64;.

 

By using descr* arguments sequence order description arrays and par* argument value arrays user can analyse types and sequence order of arguments in current user-defined function calling during program execution.

Analyzis of descr* arrays gives full information about types, quantity and sequence order of arguments in current user-defined function calling.

 

Example:

 

String variable is passed as argument into user-defined function that calculates sine. In this case descrf, descri and descrc arrays will contain following values:

 

descrf[0]=0

descri[0]=0

descrc[0]=1

 

By analyzing this information user is able to perform tasks he needs, for example:

 

1. generate users exception

2. substitute in default argument, for example 0.

3. perform program halt with printing of alert

4. try to transform string into number using atof

 

In order to facilitate access to string data Open Basic provides function

 

const ob_type_char*

ob_getstringparam(

const ob_type_parnum *descrc,

const ob_type_char* parc,

const ob_type_parnum i);

 

Function arguments:

 

1. descrc string arguments description array

2. parc - string arguments values array

3. i - number of line that was passed in arguments (numeration starts from zero)

 

By using this function user can gain access to i-numbered line that was written into string arguments or names of user-defined function.

If i is greater than descrc[0], the function returns 0.

If descrc[0] is equal to zero, the function returns 0.

Function ob_getstringparam is not ob_obasic class method.

 

3.9.5. Choosing of Basic-name for user-defined function

 

Basic-name for user-defined function should differ from names of operators, variables, arrays or other user-defined functions of *.bas-program.

 

3.9.6. Attaching of user-defined function to OB execution system

 

Attaching of user-defined function to OB execution system is performed by using setfun methods.

 

bool setfun(ob_type_char* name,ob_type_flofun f);

bool setfun(ob_type_char* name,ob_type_intfun f);

bool setfun(ob_type_char* name,ob_type_charfun f,ob_type_del dt);

 

Method arguments:

 

1. name - Basic-name of user-defined function

2. f - pointer on user-defined function

3. dt - type of returned value allocation in memory (only for functions that return string)

 

Example:

 

//attaching of userfun1 user-defined function

//this function returns floating-point type value

//this function types "hello world" message and returns value 3.1416

//during its attaching the function receives "TEST_FUN1" Basic-name

//which means that in *.bas-programs it is possible to call this function by name "TEST_FUN1"

 

OB_DECLARE_USER_FUNCTION(userfun1,ob_type_flo){

cout<<endl<<"hello world";

return (ob_type_flo)3.1416;

}

 

main(){

ob_obasic onebasic;//the interpreter instance is created

 

onebasic.setfun("TEST_FUN1",userfun1);//TEST_FUN1 user-defined function function is attached

 

ifstream inonebasicf("EXAMPLE.BAS",ios::binary);//EXAMPLE.BAS file is opened

 

onebasic.clear_project();

onebasic.load_project(&inonebasicf);//EXAMPLE.BAS file is loaded into the interpreter

 

onebasic.run();//running of *.bas-program

}

 

Sequence order of attaching of function returning string data type differs from described above.

Returned value has two types of memory allocation:

 

- in the heap (using new[] operator)

- in static memory

 

In the first case user-defined function is attached with dt=OB_DELETE argument.

After this function finishes its work Open Basic will free memory by using delete[] operator.

 

Example:

 

In example given the interpreter instance is created, then file with name

EXAMPLE.BAS is opened and is loaded into the interpreter. After this four functions TEST_FUN1-TEST_FUN4 are attached to OB execution system.

 

TEST_FUN1 function prints list of its floating-point type arguments and returns floating-point type value that is equal to sum of floating-point type arguments of the function.

 

TEST_FUN2 function prints list of its integer type arguments and returns integer type value that is equal to sum of integer type arguments of the function.

TEST_FUN3 and TEST_FUN4 functions print their first string type argument and return string "This is string".

During this TEST_FUN4 function allocates its returned value in static memory and TEST_FUN3 function allocates its returned value in free memory.

All these functions control whether types of their arguments are correct. If arguments of required type are missing then functions type appropriate messages.

 

#include <ob.h>

 

char* s="This is string";

 

OB_DECLARE_USER_FUNCTION(userfun1,ob_type_flo){

ob_type_flo summ=0;

ob_type_parnum i;

if(descrf[0]==0) cout<<endl<<"Not float parameters";

for(i=0;i!=descrf[0];i++){

summ+=parf[i];

cout<<endl<<"parameters["<<i<<"]="<<parf[i];

}

return summ;

}

 

OB_DECLARE_USER_FUNCTION(userfun2,ob_type_int){

ob_type_int summ=0;

ob_type_parnum i;

if(descri[0]==0) cout<<endl<<"Not int parameters";

for(i=0;i!=descri[0];i++){

summ+=pari[i];

cout<<endl<<"parameters["<<i<<"]="<<pari[i];

}

return summ;

}

 

OB_DECLARE_USER_FUNCTION(userfun3,char*){

if(descrc[0]==0) cout<<endl<<"Not string parameters";

cout<<endl<<parc;

char* p=new char[strlen(s)+1];

strcpy(p,s);

return p;

}

 

OB_DECLARE_USER_FUNCTION(userfun4,char*){

if(descrc[0]==0) cout<<endl<<"Not string parameters";

cout<<endl<<parc;

return s;

}

 

main(){

ob_obasic onebasic;//creating of the interpreter instance

 

onebasic.setfun("TEST_FUN1",userfun1);//attaching of TEST_FUN1 function

onebasic.setfun("TEST_FUN2",userfun2);//attaching of TEST_FUN2 function

onebasic.setfun("TEST_FUN3",userfun3,OB_DELETE);//attaching of TEST_FUN3 function

onebasic.setfun("TEST_FUN4",userfun4,OB_NODELETE);//attaching of TEST_FUN4 function

 

ifstream inonebasicf("EXAMPLE.BAS",ios::binary);//opening of EXAMPLE.BAS file

 

onebasic.clear_project();

onebasic.load_project(&inonebasicf);//loading of EXAMPLE.BAS into the interpreter

 

onebasic.run();//running of *.bas-program

}

 

The following actions are performed by Open Basic execution system when it detects the name of attached function in *.bas-program text:

 

1. it calculates all arguments in current calling of *.bas-program

2. it fills descr* arrays

3. it fills par* arrays

4. it fills ob_obasic* basic_ptr pointer with address of Open Basic current object

5. it fills parstring string

6. it transfers control to user-defined function

 

User-defined function should control types, quantity and sequence order of arguments in current calling.

 

3.10. Methods and enumerations of ob_obasic class used for attaching and detaching of user-defined functions

 

3.10.1. ob_type_del enumeration

 

Enumeration enum ob_type_del{OB_DELETE,OB_NODELETE}; - this enumeration determines type of allocation in memory of value returned by used-defined function. This enumeration is used in setfun method for attaching of user-defined functions that return ob_type_char*type.

 

If dt=OB_DELETE then returned value is put to free memory by new operator. After user-defined function is terminated, this value will be deleted by delete[] operator.

If dt=OB_NODELETE then returned value will not be deleted by delete[] operator.

 

3.10.2. setfun methods

 

Methods

 

bool setfun(ob_type_char* name,ob_type_flofun f);

bool setfun(ob_type_char* name,ob_type_intfun f);

bool setfun(ob_type_char* name,ob_type_charfun f,ob_type_del dt);

 

These methods attach user-defined function to Open Basic execution system.

 

Method arguments:

 

1. name - Basic-name of user-defined function

2. f - pointer on user-defined function

3. dt - type of returned value allocation in memory (only for functions that return string)

 

If function with name name has not been attached to Open Basic execution system yet, then method attaches this function and returns false.

 

If function with name name is already attached to Open Basic execution system, then method replaces this function with new one and returns true.

 

Types ob_type_flofun, ob_type_intfun and ob_type_charfun are pointers on functions described in ob.h. They differ by type of value they return.

 

3.10.3. delfun method

 

Method

 

bool delfun(ob_type_char* name);

 

This method detaches user-defined function from Open Basic execution system.

 

Method arguments:

 

1. name - Basic-name of user-defined function

 

Method delfun returns true if function has been successfully detached and false if function was not found.

 

3.11. Access to *.bas program data from user-defined function

 

User-defined function can receive arguments from *.bas-program.

User-defined function can send its output value to *.bas-program.

User-defined function can read and write variables of *.bas-program.

 

If a variable or an array is used in *.bas-program then user-defined function is able to read and write this variable and array elements.

 

User-defined function can check presence of a variable with specified name in the program. User-defined function can create variables with specified name in the variable table.

 

These features are implemented in Open Basic by methods described in next part of this document.

 

3.12. Methods and enumerations of ob_obasic class used for access to Open Basic data from user-defined functions

 

Methods described in this paragraph are usually run in user-defined functions so in given examples these methods are run using ob_obasic* basic_ptr pointer. First argument of user-defined function has such name in all user-defined functions if these functions are determined using OB_DECLARE_USER_FUNCTION macro.

Generally methods described in this paragraph can be run in any part of C++program in which the interpreter is used. For example, after halting *.bas-program by using breakpoint it is possible to print values of variables and arrays. Also it is possible to create and initialize certain variables before program start.

 

3.12.1. Methods and enumerations of ob_obasic class used for determining of Open Basic variables and arrays type

 

3.12.1.1. Enumeration ob_type_ident

 

Enumeration

 

enum ob_type_ident {OB_IDENTFLO,OB_IDENTINT,OB_IDENTSTR,OB_NOIDENT};

 

This enumeration determines type of a variable or an array. This enumeration is used in typevar and typearray methods for determining of variable or array type.

 

If ob_type_ident=OB_IDENTFLO then the variable is of floating-point type.

If ob_type_ident=OB_IDENTINT then the variable is of integer type.

If ob_type_ident=OB_IDENTSTR then the variable is of string type.

If ob_type_ident=OB_NOIDENT then the variable was not found.

 

3.12.1.2. typevar method

 

Method

 

ob_type_ident typevar(ob_type_char* name); - this method returns type of a variable with name name.

 

Method arguments:

 

1. name name of Basic-variable

 

3.12.1.3. typearray method

 

Method

 

ob_type_ident typearray(ob_type_char* name); - this method returns type of an array with name name.

 

Method arguments:

 

1. name name of Basic-array (without brackets or indexes)

 

Example: If there a *.bas-program containing the following code

 

DIM array1%(10,10), array2$(10,10), array3(10,10)

a%=10

b$="string example"

c=101.4

 

then, after this part of code is executed in user-defined functions attached to the interpreter, using of these methods will give the following results:

 

ob_type_ident ident;

ident=basic_ptr->typevar("a%");// ident has the value of OB_IDENTINT

ident=basic_ptr->typevar("b$");// ident has the value of OB_IDENTSTR

ident=basic_ptr->typevar("c"); // ident has the value of OB_IDENTFLO

 

ident=basic_ptr->typearray("array1%");// ident has the value of OB_IDENTINT

ident=basic_ptr->typearray("array2$");// ident has the value of OB_IDENTSTR

ident=basic_ptr->typearray("array3"); // ident has the value of OB_IDENTFLO

 

In given example basic_ptr is the first argument in user-defined functions, the pointer on the interpreter instance.

 

The given example of *.bas-does not contain a variable with VAR name and an array with ARR name, so using of these methods will give the following results:

 

ident=basic_ptr->typevar("VAR");// ident has the value of OB_NOIDENT

ident=basic_ptr->typearray("ARR");// ident has the value of OB_NOIDENT

 

3.12.2. Methods of ob_obasic class used for determining of length of Open Basic string variables and string arrays elements

 

Method

 

ob_type_ident

strlenvar(

ob_type_char* name,

ob_type_stringsize* len,

ob_type_arraysize* as=OB_NULL);

 

This method determines variable type and length of variable or array element with name name.

 

Method arguments:

 

1. name name of Basic-variable or Basic-array

2. *len for string type variables this argument contains string length without trailing zero. For floating-point type or integer type variables this argument contains sizeof(ob_type_float) or sizeof(ob_type_int) respectively.

3. *as - array indexes (if name is the name of an array)

 

Method strlenvar can be called for Basic-variables or elements of Basic-arrays.

There are two ways of strlenvar method calling for Basic-arrays:

 

1. With specifying of current indexes in the array name (as=OB_NULL argument)

2. With specifying of current indexes in *as argument (as!=OB_NULL argument)

 

This method returns OB_NOIDENT if there is name assignment error, for example if the name does not begin with a letter or is a name of array not described yet or there is no such variable. On normal termination this method returns type of the variable.

Argument *len for string type variables contains string length without trailing zero. For floating-point type or integer type variables *len argument contains

sizeof(ob_type_float) or sizeof(ob_type_int) respectively.

 

Example: Calling of strlenvar method for an array element with specifying of current indexes in the array name

 

If there a *.bas-program containing the following code:

 

DIM array2$(10,10)

array2$(5,5)="array string example"

 

then, after this part of code is executed in user-defined functions attached to the interpreter, using of strlenvar method will give the following results:

 

ob_type_stringsize len;

 

ob_type_ident ident;

ident=basic_ptr->strlenvar("array2$(5,5)",&len);// ident==OB_IDENTSTR len==20

 

Example: Calling of strlenvar method for an array element with specifying of current indexes in *as argument

 

If there a *.bas-program containing the following code:

 

DIM array2$(10,10)

array2$(5,5)="array string example"

 

then, after this part of code is executed in user-defined functions attached to the interpreter, using of strlenvar method will give the following results:

 

ob_type_stringsize len;

 

ob_type_ident ident;

ob_type_arraysize as[]={5,5};

ident=basic_ptr->strlenvar("array2$",&len,as);// ident==OB_IDENTSTR len==20

 

Example: Calling of strlenvar method for variables

 

If there a *.bas-program containing the following code:

 

DIM array1%(10,10), array3(10,10)

a%=10

b$="string example"

c=101.4

 

then, after this part of code is executed in user-defined functions attached to the interpreter, using of strlenvar method will give the following results:

 

ob_type_ident ident;

ob_type_stringsize len;

 

ident=basic_ptr->strlenvar("a%",&len);// ident==OB_IDENTINT len==4

ident=basic_ptr->strlenvar("b$",&len);// ident==OB_IDENTSTR len==14

ident=basic_ptr->strlenvar("c",&len); // ident==OB_IDENTFLO len==4

 

3.12.3. Methods of ob_obasic class used for determining of Open Basic arrays sizes

 

Method

 

const ob_type_arraysize* getarraysize(

ob_type_char* name,ob_type_arraydimension* kr); - this method returns number of array dimensions and size of each dimension.

 

Method arguments:

 

1. name array name.

2. *kr - number of array dimensions. This argument is filled using getarraysize method.

The returned argument is an array of each dimension sizes. It is created during array descripting by DIM operator. This argument is Open Basic internal buffer and should be read-only.

 

Example:

 

The array is described by DIM Array_1(10,11,12) operator.

 

Using of getarraysize method.

 

const ob_type_arraysize *sr;

ob_type_arraydimension kr;

sr=basic_ptr->getarraysize("Array_1",&kr);

 

After getarraysize is used kr=3 and sr pointer points on array {10,11,12}.

 

3.12.4. Methods of ob_obasic class used for writing of Open Basic variables

 

Methods

 

bool

writevar(ob_type_char* name,ob_type_flo val,ob_type_arraysize* as=OB_NULL);

 

bool

writevar(ob_type_char* name,ob_type_int val,ob_type_arraysize* as=OB_NULL);

 

bool

writevar(ob_type_char* name,ob_type_char* val,ob_type_arraysize* as=OB_NULL);

 

Method arguments:

 

1. name name of Basic-variable or Basic-array

2. val - values that are being written into variables or array elements

3. *as - arrays indexes (if name is the name of an array)

 

Methods writevar can be called for Basic-variables or Basic-arrays elements.

There are two ways of writevar methods calling for Basic-arrays.

 

1. With specifying of current indexes in the array name (as=OB_NULL argument)

2. With specifying of current indexes in *as argument (as!=OB_NULL argument)

 

Methods write a variable with name name into table of variables and assign val value to it.

 

If a variable does not exist it will be created.

 

The checking of name type takes place, i.e. a variable is created that corresponds to the name.

 

If type of assigned value does not correspond to name type (for example, when trying to create integer type variable with second argument of ob_type_char* val), then the method generates an exception.

 

Name name can be a name of array element. In this case this name should contain indexes of specific element in accordance with the Basic rules.

 

Methods return false if there is a name assignment error (for example, if the first simbol of the name is not a letter or if name is a name of an array but this array has not been described yet). Methods return true if all parameters are correct and no errors occured during execution.

 

Example: The following code should be written in user-defined function to assign value 10.4 to VAR variable:

 

if(basic_ptr->writevar("VAR",10.4)==false) cout<<endl<<"error in writevar";

 

Example: The following code should be written in user-defined function to assign value "Hello world" to the third element of array_string$(10) array:

 

if(basic_ptr->writevar("array_string$(3)","Hello world")==false)

cout<<endl<<"error in writevar";

 

3.12.5. Methods of ob_obasic class used for reading of Open Basic variables

 

Methods

 

bool

readvar(ob_type_char* name,ob_type_flo* val,ob_type_arraysize* as=OB_NULL);

 

bool

readvar(ob_type_char* name,ob_type_int* val,ob_type_arraysize* as=OB_NULL);

 

bool

readvar(ob_type_char* name,ob_type_char* val,ob_type_arraysize* as=OB_NULL);

 

Method arguments:

 

1. name name of Basic-variable or Basic-array

2. *val value that is read from a variable or an array element

3. *as - array indexes (if name is the name of an array)

 

Methods readvar can be called for Basic-variables or Basic-arrays elements.

There are two ways of readvar methods calling for Basic-arrays.

 

1. With specifying of current indexes in the array name (as=OB_NULL argument)

2. With specifying of current indexes in *as argument (as!=OB_NULL argument)

 

Methods read a variable with name name from table of variables into val pointer.

 

If a variable does not exist it will not be created.

 

Name name can be a name of array element. In this case this name should contain indexes of specific element in accordance with the Basic rules.

 

Methods return false if there is a name assignment error (for example, if the first simbol of the name is not a letter or if name is a name of an array but this array has not been described yet or there is no such variable). Methods return true if all parameters are correct and no errors occured during execution.

 

If type of variable and type of val argument do not match (for example, when trying to assign an integer type value to a string type variable) then the method generates an exception.

 

Example: The following code should be written in user-defined function to read the value of variable with name VAR1 to C++ variable with name val1:

 

ob_type_flo val1;

if(basic_ptr->readvar("VAR1",&val1)==false) cout<<endl<<"error name var in readvar";

 

Example: The following code should be written in user-defined function to read the value of the fourth element of array_string$(10) array:

 

ob_type_char buf[256];

ob_type_char* pchar=buf;

if(basic_ptr->readvar("array_string$(4)",pchar)==false)

cout<<endl<<"error name var in readvar";

 

3.12.6. Methods of ob_obasic class used for creating and deleting of Open Basic variables and arrays

 

3.12.6.1. Methods of ob_obasic class used for creating of Open Basic variables

 

Method

 

void createvar(ob_type_char* name);

 

Method arguments:

 

1. name name of Basic-variable or Basic-array

 

This method creates a variable with name name in table of variables of the interpreter.

The variable type is determined by presence of '%' and '$' characters in variables name.

3.12.6.2. Methods of ob_obasic class used for creating of Open Basic arrays

  Method

 

void createarray(

ob_type_char* name,ob_type_arraydimension kr,ob_type_arraysize* as);

 

Method arguments:

 

1. name name of Basic-variable or Basic-array

2. kr - number of array dimensions

3. *as - array of each dimension sizes

 

This method creates an array with name name in table of arrays of the interpreter. If the array with such name already exists then it is deleted and created again with specified arguments.

Type of elements of array that is created is determined by presence of '%' and '$' characters in arrays name. The method is equivalent to DIM operator.

 

Arguments of this method are similar to arguments of getarraysize method.

 

Example: The following code should be written in user-defined function to create an array of integers ARRAY1%(5,10,20):

 

ob_type_arraysize as[]={5,10,20};

basic_ptr->createarray("ARRAY1%",3,as);

 

3.13. Description of other methods of ob_obasic class

 

~ob_obasic(); - destructor.

 

Method static const ob_type_char* about()- this method returns a string of information about the program. The string can contain LF and CR characters.

 

Example:

 

cout<<ob_obasic::about();//printing of information about the program

 

Method static const ob_type_serialnum serial_number() this method returns serial number of the program.

 

Method static const ob_type_int version() this method returns number of current version of the program multiplied by 100. For version 1.90 this method returns 190.

 

Methods

 

void set_max_nested_gosub(ob_type_countlist m);

ob_type_countlist get_max_nested_gosub();

 

These methods determine the maximum number of nested calls for GOSUB operator. Default maximum number of nested calls for GOSUB operator is 4096. When specified number of nested calls is exceeded then exception is generated. If this value is set to 0 then check of nested calls for GOSUB operator is not performed.

 

3.14. Operators used in Open Basic

 

Operators can be placed in same line and be divided from each other by spaces.

Some operators like DATA or PRINT should be the only operators in the line, because list of arguments of these operators should be explicitly bounded.

In operators descriptions the characters in square brackets mean optional characters.

 

The following operators are supported in Open Basic:

 

3.14.1. PRINT operator

 

This operator sends list of variables to output stream that was specified during ob_obasic creating.

Operator format:

 

[N] PRINT [#EXP,][LIST]

 

where

N - the number of the line

LIST list of elements that are represented as constants, variables, string or

numerical expressions.

EXP - expression that determines number of output channel opened by OPEN

operator

 

Without list of elements PRINT operator sends LF/CR characters to output stream.

If some of the list elements are expressions then Open Basic calculates these expressions and prints the result.

 

Example:

 

10 TT%=40

TTT=101.3

20 PRINT "TT%=";TT,"TTT=";TTT+0.3

 

The result of operators work

 

TT%=40 TTT=101.6

 

List elements are separated from each other by commas or semicolons.

If list elements are separated by commas then tab character is sent to output stream between list elements.

If there is a comma or a semicolon on the end of the elements list then line feed is not performed after PRINT operator.

PRINT operator with elements list should be the only operator in the line.

 

3.14.2. INPUT operator

 

This operator inputs data from input stream that was specified during ob_obasic creating.

Operator format:

 

[N] INPUT [#EXP,]VAR1,[VAR2,VAR3,...]

 

where

N - the number of the line

VAR1,[VAR2,VAR3,...] list of variables

EXP expression that determines number of input channel opened by OPEN operator

 

When Open Basic meets INPUT operator it inputs data represented in numerical form from the stream and assigns this data to variables from the list. Strings in the stream should be quoted.

 

Example:

 

10 TT%=40

TTT=101.3

20 INPUT TT%,TTT

 

3.14.3. FOR and NEXT operators

 

These operators create cycle in such way that Open Basic checks condition automatically on each iteration.

 

FOR operator format:

 

[N] FOR VAR=EXP1 TO EXP2 [STEP EXP3]

 

where

N - the number of the line

VAR - control variable (cycle index)

EXP1 index initial value. Can be any numerical expression.

EXP2 index final value. Can be any numerical expression.

EXP3 index value increment. Can be any numerical expression. Can be positive or negative. Default is 1.

 

Control variable (cycle index) can be an array element.

 

FOR and NEXT operators should be used together only. FOR operator determines cycle start and NEXT operator determines cycle end.

 

NEXT operator format:

 

[N] NEXT VAR1

 

where

N - the number of the line

VAR1 - control variable used in FOR operator

 

If initial value of cycle variable is greater than its final value then cycle is not performed.

Transferring of control inside the cycle is not allowed.

To avoid truncation errors it is recommended to use integer variables as cycle variables.

Cycles can be nested into each other; in this case the inner cycle must end before the outer cycle.

FOR operator has some implementation features. They take place because Open Basic itself is an interpreter. During entrance into the cycle checking of cycle conditional is performed. If cycle conditional is not met the cycle will not be performed. In this case the searching of corresponding NEXT operator and control transferring to it is performed. During these actions any possible branching of the algorithm by GOTO operators are not taken into account.

 

Example:

 

GOTO 30

10

NEXT i%

GOTO 20

 

30 FOR i%=10 TO k% STEP 1

 

GOTO 10

 

 

20

STOP

END

 

This example will work if k% is greater than 10. If it is not then abnormal termination will happen.

 

Example:

 

FOR i%=1 TO 3

FOR ii%=4 TO 1 STEP -2

PRINT "Work FOR operator","ii%=";ii%,"i%=";i%

NEXT ii%

NEXT i%

 

Result of operators work

 

Work FOR operator ii%=4 i%=1

Work FOR operator ii%=2 i%=1

Work FOR operator ii%=4 i%=2

Work FOR operator ii%=2 i%=2

Work FOR operator ii%=4 i%=3

Work FOR operator ii%=2 i%=3

 

Example:

 

FOR i%=1 TO 3

FOR ii%=4 TO 1 STEP -2

PRINT "Work FOR operator","ii%=";ii%,"i%=";i%

NEXT ii%

NEXT i%

 

Result of operators work

 

Work FOR operator ii%=4 i%=1

Work FOR operator ii%=2 i%=1

Work FOR operator ii%=4 i%=2

Work FOR operator ii%=2 i%=2

Work FOR operator ii%=4 i%=3

Work FOR operator ii%=2 i%=3

 

3.14.4. GOTO operator

 

This operator calls direct jump to specified line.

 

Operator format:

 

[N] GOTO line_number

 

or

 

[N] GOTO label_string

 

where

N - the number of the line

line_number - number of the line to which the transition is performed

label_string string label

 

Example:

 

20 GOTO 50

PRINT "This operator do not work in example"

50 PRINT "Work GOTO operator"

 

Result of operators work

 

Work GOTO operator

 

Example:

 

20 GOTO label_1

PRINT "This operator do not work in example"

label_1: PRINT "Work GOTO operator"

 

Result of operators work

 

Work GOTO operator

 

3.14.5. GOSUB and RETURN operators

 

These operators call subroutine.

Operator format:

 

[N] GOSUB line_number

 

or

 

[N] GOSUB label_string

 

where

N - number of the line

line_number - number of line to which the transition is performed

label_string string label

 

When Open Basic meets GOSUB operator it transfers control to the line that is specified in GOSUB operator. The program then continues to run from this line. When Open Basic meets RETURN operator the control is transferred to line that goes after the line containing GOSUB operator.

 

GOSUB and RETURN operators should be used together only.

 

RETURN operator format:

 

[N] RETURN

 

where

N - the number of the line

 

Subroutines can be nested into each other.

 

Example:

 

GOSUB 10

GOTO 100

 

10

PRINT "Work GOSUB operator 1"

GOSUB 20

PRINT "Work GOSUB operator 2"

RETURN

20

PRINT "Work GOSUB operator 3"

PRINT "Work GOSUB operator 4"

RETURN

100

 

STOP

END

 

Result of operators work

 

Work GOSUB operator 1

Work GOSUB operator 3

Work GOSUB operator 4

Work GOSUB operator 2

 

Example:

 

GOSUB label_gosub_1

GOTO label_goto_1

 

label_gosub_1:

 

PRINT "Work GOSUB operator 1"

GOSUB label_gosub_2

PRINT "Work GOSUB operator 2"

RETURN

 

label_gosub_2:

PRINT "Work GOSUB operator 3"

PRINT "Work GOSUB operator 4"

RETURN

label_goto_1:

 

STOP

END

 

Result of operators work

 

Work GOSUB operator 1

Work GOSUB operator 3

Work GOSUB operator 4

Work GOSUB operator 2

 

3.14.6. LET operator

 

This operator assigns a value to a variable.

 

Operator format:

 

[N] [LET] VAR=EXP

 

where

N - the number of the line

LET - optional name of the operator

VAR - variable that receives a new value

EXP - expression that determines a new value

 

Example:

 

20 LET a=100.1

PRINT "Work LET operator","a=";a

 

Result of operators work

 

Work LET operator a=100.1

 

3.14.7. DIM operator

 

This operator reserves a place for numerical or string array.

 

Operator format:

 

[N] DIM LIST

 

where

N - the number of the line

LIST list of arrays names separated by commas

 

Open Basic supports arrays of any size and dimension. Due to the fact that place for these arrays is reserved by C++ 'new' operator the restrictions on array size or dimension are caused by 'new'operator implementation features on a specific platform. For example, in MS DOS 'new'operator does not receive more than 64K bytes of memory. Therefore, overall size of an array in MS DOS Open Basic cannot exceed 64K bytes and number of array dimensions also cannot exceed 64K bytes.

 

Dimensions of arrays in Open Basic can be changed. During descripting of already descripted array this array is deleted and is created again, possibly with new dimensions and size.

During their creating numerical arrays are initialized by zero. String arrays are initialized by empty string.

The type of the array being created is determined by variable type identification rules and by presence of % and $ characters in arrays name.

 

Example:

 

DIM a%(2,2,3),b(3,2,4)

DIM a$(2,2,3,2)

 

a$="variable string"

a$(1,1,3,2)="array string"

a%(2,2,3)=10

b(1,1,1)=101.1

 

 

PRINT a$(1,1,3,2)

PRINT a$

PRINT "a%=";a%

PRINT "b=";b

 

Result of operators work

 

array string

variable string

a%=10

b=101.1

 

3.14.8. STOP and END operators

 

These operators are used for program termination.

STOP operator invokes clean-up of all Open Basic tables -tables of variables, tables of arrays etc.

END operator also invokes clean-up of all Open Basic tables and also sets internal halt flag. Reset of this flag is performed in ob_obasic::load_project method.

 

These operators do not invoke clean-up of user-defined functions table.

 

Operators format:

 

[N] STOP

[N] END

 

where

N - the number of the line

 

Example:

 

PRINT "example STOP and REM operator"

10 STOP

20 END

 

3.14.9. REM operator

 

This operator sets comments to the program.

 

Operator format:

 

[N] REM COMMENT

 

where

N - the number of the line

COMMENT comments text

 

REM operators and empty lines increase program execution time and occupy some amount of memory.

 

Example:

 

a=1

 

10 REM this text is comment

 

PRINT "a=";a

 

STOP

END

 

If control is never transferred to REM operator then this operator does not increase program execution time.

 

Example:

 

a=1

b=2

c=3

 

GOSUB label1

GOSUB label2

 

STOP

END

 

label1:

a=b+c

RETURN

 

REM this text is comment

REM this text is comment

REM this text is comment

REM this text is comment

REM this text is comment

 

label2:

b=a+c

RETURN

 

3.14.10. OPEN and CLOSE operators

 

OPEN operator opens file. CLOSE operator closes file.

 

OPEN operator format:

 

[N] OPEN filename FOR INPUT AS FILE #EXP

[N] OPEN filename FOR OUTPUT AS FILE #EXP

 

where

N - the number of the line

filename name of the file

EXP expression that is calculated and reduced to integer type. Usually constants are used.

AS FILE key words

 

OPEN FOR INPUT operator opens a file for reading.

OPEN FOR OUTPUT operator opens a file for writing.

 

CLOSE operator format:

 

[N] CLOSE #EXP1,[#EXP1,#EXP2,...]

 

where

N - the number of the line

EXP - expression that is calculated and reduced to integer type. Usually constants are used.

 

Example:

 

k%=10

 

OPEN "F000.TXT" FOR OUTPUT AS FILE #k%+1

OPEN "F001.TXT" FOR OUTPUT AS FILE #k%+2

 

FOR i%=1 TO KOL% STEP 1

PRINT "i%=",i%

PRINT #k%+1,i%

f=i%+0.1

PRINT #k%+2,f

NEXT i%

 

CLOSE #k%+1

CLOSE #k%+2

 

OPEN "F000.TXT" FOR INPUT AS FILE #k%+2

OPEN "F001.TXT" FOR INPUT AS FILE #k%+3

 

FOR i%=1 TO KOL% STEP 1

INPUT #k%+2,ii%

INPUT #k%+3,ff

PRINT "ii%=",ii%

f=i%+0.1

IF ii%<>i% THEN PRINT " Error test OPEN-CLOSE command" GOTO 10

IF ff<>f THEN PRINT " Error test OPEN-CLOSE command" GOTO 10

NEXT i%

 

CLOSE #k%+2

CLOSE #k%+3

 

10 STOP

END

 

3.14.11. KILL operator

 

This operator deletes file\files.

 

Operator format:

 

[N] KILL STR1[,STR2,STR3,...]

 

where

N - the number of the line

STR1, STR2 ,STR3 - file names

 

Example:

 

10 KILL "F000.TXT","F001.TXT"

 

3.14.12. READ, DATA and RESTORE operators

 

READ and DATA operators are used for arrangement of data block that is read by Open Basic interpreter during the program execution.

 

READ operator format:

 

[N] READ VAR1[,VAR2,VAR3,...]

 

where

N - the number of the line

VAR1,VAR2,VAR3 variables that are assigned values from list of DATA operator

 

DATA operator format:

 

[N] DATA EXP1,[EXP1,EXP2,...]

 

where

N - the number of the line

EXP1,EXP2,EXP3 expression that is calculated and assigned to a variable from READ list. Can be numerical or string. Usually constants are used.

 

RESTORE operator format:

 

[N] RESTORE

 

where

N - the number of the line

 

Before executing program Open Basic browses all DATA operators in order of their appearance and creates a data block. Each time READ operator is encountered in the program the data block outputs sequentially matching value for variables of this operator in the same order in which they are specified in the data block.

After READ operator is performed the position of last read data is remembered. Next READ operator starts data read from position specified by previous READ operator.

Open Basic performs reload of the same data using RESTORE operator.

DATA operator should be the only one operator in the line.

 

Example:

 

DATA 1.1,2,3,4,"1 string for data"

DATA 5.1,6,7,4+4,"2 string for data"

 

DIM z%(3)

 

READ a2,z%(1),z%(2),z%(3),e2$

 

READ a,b%,c%,d%,e$

PRINT "a=";a;" b%=";b%;" c%=";c%;" d%=";d%;" e$=";e$

READ a1,b1%,c1%,d1%,e1$

PRINT "a1=";a1;" b1%=";b1%;" c1%=";c1%;" d1%=";d1%;" e1$=";e1$

RESTORE

READ a1,z%(1),z%(2),z%(3),e1$

PRINT "a1=";a1;" z%(1)=";z%(1);" z%(2)=";z%(2);" z%(3)=";z%(3);

PRINT " e1$=";e1$

 

Result of operators work

 

a=1.1 b%=2 c%=3 d%=4 e$=1 string for data

a1=5.1 b1%=6 c1%=7 d1%=8 e1$=2 string for data

a1=1.1 z%(1)=2 z%(2)=3 z%(3)=4 e1$=1 string for data

 

3.14.13. RANDOMIZE operator

 

This operator initializes random number generator with a new value. Current system time in seconds is used as a new value, therefore at least 1 second should pass before RANDOMIZE operator can be used again after its previous use.

 

Operator format:

 

[N] RANDOMIZE

 

where

N - the number of the line

 

RANDOMIZE operator is placed before first use of random number generation function(RND function). When RND function is performed RANDOMIZE operator changes initial value of random number in such way that RND function gives different numbers on its next pass.

 

Example:

 

10 RANDOMIZE

 

3.14.14. IF operator

 

This operator is used for conditional jumps performing. It has three formats: string format, block format and short block format.

 

String format of IF operator:

 

[N] IF REL-EXP THEN operators

 

where

N - the number of the line

THEN key word

REL-EXP test condition. The relational expression can be either arithmetic or string.

operators an operator or a group of operators

 

If REL-EXP condition is true then operator (operators) in string after THEN key word is (are) performed. If REL-EXP condition is false then operator in line going after line with IF operator is performed.

 

Example:

 

TT%=40

20 IF TT%=40 THEN GOTO 50

PRINT "This operator do not work in example"

50 PRINT "Work IF operator","TT%=";TT%

 

Result of operators work

 

Work IF operator TT%=40

 

Example:

 

TT%=40

IF TT%=40 THEN PRINT "Work IF operator","TT%=";TT% GOTO 10

PRINT "This operator do not work in example"

10 PRINT "Work IF operator","TT%=";TT%

 

Result of operators work

 

Work IF operator TT%=40

Work IF operator TT%=40

 

Example:

 

TT%=40

IF TT%=40 THEN a=101.1 b=102.1 c=103.1 GOTO 10

a=1101.1 b=1102.1 c=1103.1

PRINT "This operator do not work in example"

10 PRINT "a=";a,"b=";b,"c=";c

 

Result of operators work

 

a=101.1 b=102.1 c=103.1

 

Block format of IF operator:

 

[N] IF REL-EXP THEN

operators1

ELSE

operators2

ENDIF

 

where

N - the number of the line

THEN key word

REL-EXP test condition. The relational expression can be either arithmetic or string.

operators - an operator or a group of operators

 

If REL-EXP condition is true then operator (operators) in block between THEN and ELSE key words is (are) performed. If REL-EXP condition is false then operator (operators) in block between ELSE and ENDIF key words is (are) performed.

 

Short block format of IF operator:

 

[N] IF REL-EXP THEN

operators1

ENDIF

 

where

N - the number of the line

THEN key word

REL-EXP - test condition. The relational expression can be either arithmetic or string.

operators - an operator or a group of operators

 

If REL-EXP condition is true then operator (operators) in block between THEN and ENDIF key words is (are) performed. If REL-EXP condition is false then operator in line going after ENDIF key word is performed.

 

3.15. Built-in functions

 

3.15.1. SGN% function

 

SGN% function is a sign function.

 

Function format: SGN%(EXP)

 

where EXP is an integer or a floating-point expression.

 

This function returns +1 if EXP>0, -1 if EXP<0 and 0 if EXP=0.

If the argument is specified incorrectly (of a string type) then an error is generated.

 

Example:

 

PRINT "This is example SGN function"

PRINT "<0";SGN%(-1-2);" >0";SGN%(2*3);" =0";SGN%(9+1-10)

 

3.15.2. ABS function

 

ABS function determines absolute value of the argument.

 

Function format: ABS(EXP)

 

where EXP is an integer or a floating-point expression.

 

This function returns floating-point type result, even if the argument is of integer type.

If the argument is specified incorrectly (of a string type) then an error is generated.

 

Example:

 

PRINT "This is example ABS function"

PRINT "abs(-20.5)=";ABS(-20.5);" abs(20.5)=";ABS(20.5)

 

3.15.3. INT% function

 

INT% function determines integer part of the argument.

 

Function format: INT%(EXP)

 

where EXP is an floating-point expression.

 

This function returns integer type result.

If the argument is specified incorrectly (of a string type) then an error is generated.

 

Example:

 

PRINT "This is example INT% function"

PRINT "int(-20.3)=";INT%(-20.3);" int(20.3)=";INT%(20.3)

 

3.15.4. SIN, COS, ATN, SQR, EXP, LOG and LOG10 functions

 

These functions calculate sine, cosine, arc tangent, square root, exponent, logarithm and common logarithm respectively.

 

Functions formats:

SIN(EXP),

COS(EXP),

ATN(EXP),

SQR(EXP),

EXP(EXP),

LOG(EXP),

LOG10(EXP)

 

where EXP is an integer or a floating-point expression.

 

This functions return floating-point type result.

If the argument is specified incorrectly (of a string type) then an error is generated.

 

Example:

 

PRINT "This is example trigonometric function"

a=SIN(3.14/2)

b=COS(0)

c=ATN(1)

d=SQR(4.0)

e=EXP(1)

f=LOG(EXP(1))

g=LOG10(10)

PRINT "a=";a;" b=";b;" c=";c;" d=";d;" e=";e;" f=";f;" g=";g

 

3.15.5. RND function

 

RND function generates pseudorandom number in 0-1 interval.

Function format: RND()

 

This functions return floating-point type result.

The arguments are ignored.

 

Example:

 

PRINT "This is example RND function"

PRINT RND(),RND(),RND(),RND();

RANDOMIZE

PRINT RND(),RND(),RND(),RND();

 

3.15.6. LEN% function

 

LEN% function determines string length.

 

Function format: LEN%(EXP)

 

where EXP is a string expression.

 

This function returns integer type result.

If the argument is specified incorrectly (of an integer or a floating-point type) then an error is generated.

 

Example:

 

PRINT "This is example LEN function"

STRing_this$="aaa bbb ccc ddd"

PRINT "len=";LEN%(STRing_this$)

 

3.15.7. DAT$ and CLK$ functions

 

These functions return current date and time respectively.

 

Functions formats:

 

DAT$(),

CLK$()

 

These functions return string type result.

The arguments are ignored.

 

Date format: day-month-year

Time format: hour:min:sec

 

Example:

 

PRINT "This is example DAT$ & CLK$."

PRINT "data=";DAT$;" time=";CLK$

 

3.15.8. D2STR$, D2HEXSTR$, STR2FLOAT and STR2INT% functions

 

D2STR$ function converts a number to a string containing its decimal notation.

 

Function format: D2STR$(EXP)

 

where EXP is an integer number or a number with floating point.

 

This function returns string type result.

 

D2HEXSTR$ function converts an integer number to a string containing its hexadecimal notation.

 

Function format: D2HEXSTR$(EXP)

 

where EXP is an integer number.

 

This function returns string type result.

 

STR2FLOAT function converts a string to a number.

 

Function format: STR2FLOAT(EXP)

 

where EXP is a string.

 

This function returns a number with floating point. If a string cannot be converted to a number then zero is returned.

 

STR2INT% function converts a string to an integer number.

 

Function format: STR2INT%(EXP)

 

where EXP is a string.

 

This function returns an integer number. If a string cannot be converted to an integer number then zero is returned.

 

Example:

 

PRINT "converter from digit to string =";D2STR$(123)

PRINT "converter from string to float =";STR2FLOAT("1.234")

PRINT "converter from string to int =";STR2INT%("1234")

PRINT "converter from digit to hex string =";D2HEXSTR$(4660)

 

 

3.16. Error handling

 

When Open Basic encounters an error it generates an exception of ob_err type with the error code. User should intercept this exception and handle it. ob_err class has dedicated methods for such handling. Here is a typical scheme of working with ob_err exceptions:

 

int main(int argc, char * argv[]){

 

int ret=0;//main return code

 

ifstream fi;//input stream

 

try{

 

ob_obasic basic_interpreter(OB_NULL);//creating of the interpreter

 

fi.open("test1.bas",ios::binary);//opening of input stream in binary mode

 

basic_interpreter.clear_project();

basic_interpreter.load_project(&fi);//loading of *.bas-program

 

ob_obasic::typeend te=basic_interpreter.run();//running of *.bas-program

 

cout<<endl<<"Stop by stop code";//printing of stop code

cout<<endl<<"Stop code=";

 

switch(te){

case ob_obasic::ENDOPERATORDETECT :cout<<"ENDOPERATORDETECT";break;

case ob_obasic::ENDFILEEND :cout<<"ENDFILEEND";break;

case ob_obasic::BREAKPOINTEND :cout<<"BREAKPOINTEND";break;

case ob_obasic::NOLOADEND :cout<<"NOLOADEND";break;

case ob_obasic::BREAKBEFOREOPERATOR:cout<<"BREAKBEFOREOPERATOR";break;

case ob_obasic::BREAKAFTEROPERATOR :cout<<"BREAKAFTEROPERATOR";break;

case ob_obasic::EOLEND :cout<<"EOLEND";break;

default:cout<<"Unknown stop code";break;

}//switch

 

}//try

 

catch(ob_err& e){

 

cout<<endl<<"Stop by OB exception catch";//handling of the exception

ret=e.getcode(); //acquiring of error code

e.release(&cout,&ob_englmessage); //printing of text message in cout

 

}//OB catch

 

return ret;

}

 

ob_err class has getcode and release methods.

 

virtual ob_type_codeerror getcode();

virtual void release(ostream* os,ob_message* currentmessage);

 

getcode method does not have arguments and returns error code.

release method has two arguments: pointer on the stream and pointer on diagnostic messages table. release release method writes to the specified stream a text message from diagnostic messages table that corresponds to error code.

Open Basic provides ob_englmessage diagnostic messages table on English. User is able to create his own diagnostic messages table on other language and use this table as release method second argument.

In order to get the string in which the error occurred one should use ob_loadbreakstr function.

 

Detailed information about exceptions handling can be found in .\example\ob.cpp file.

 

3.17. Diagnostic messages table

 

Diagnostic messages table is located in ob5.cpp file.