Blunt_Axe_Basic Project Copyright:(c) sarbayo, 2001,02,03,04 Alpha Version 1.05 _Bxbasm_ (Blunt Axe Basic) Welcome to Bxbasm TABLE OF CONTENTS: What is Bxbasm .................................... 3 How to use Bxbasic .............................. 4 Compiling Error .................................... 5 Bxbasic Commands .................................... 6 String and Math functions ........................ 7 Examples: line numbers, REM, CLS, PRINT, BEEP, END 8 GOTO ................................................ 9 LET ................................................ 10 LOCATE .......................................... 12 Math expressions .................................... 13 Optional usage: line numbers, REM, LET ............ 14 Block Labels .................................... 15 CLEAR ................................................ 17 Numeric data types .............................. 19 String variables .................................... 24 PRINT ................................................ 25 GOSUB/RETURN .................................... 26 FOR/NEXT .......................................... 30 Power and Modulus .................................... 32 IF/ELSE .......................................... 33 String functions .................................... 35 INKEY$ .......................................... 39 INPUT .......................................... 40 INPUT$ .......................................... 41 LINE INPUT .......................................... 42 Algebraic functions .............................. 43 Disk File I/O: OPEN, CLOSE ........................ 45 EOF ................................................ 48 WRITE .......................................... 50 LINE INPUT# .......................................... 52 PRINT# .......................................... 53 Random I/O .......................................... 54 FIELD, LSET, RSET, PUT .............................. 55 GET ................................................ 56 I/O string functions: MKD$, MKS$, MKI$, CVD, CVS, CVI 58 Count to A Million program ........................ 62 Summary .......................................... 63 What is Bxbasm ? What is Bxbasm and the Blunt_Axe_Basic Project ? Bxbasm is a compiler. Bxbasic is a language subset or dialect of Basic. Bxbasm is a work in progress and at this stage of developmentis a Console Mode 32 bit Native Code Compiler. The Bxbasic dialect is presently a subset of and is not yet a complete implementation of the QBasic/QuickBasic_4.5 dialect and is currently in development. It is fully intended to develop Bxbasic into: * a full featured QBasic/QuickBasic-4.5 and RapidQ work-alike, * running in 32 bit Console and Windows Modes, * as a Native Code Compiler. This is not a commercial product or project! It is not intended for this project to become a commercial product. How to use Bxbasic: The user need not be familiar with assembly language, nor how to use a compiler, assembler or linker, to compile Bxbasic scripts. Bxbasic comes with a text editor (Qedit) which allows the programmer to load, create, edit and save or cut-n-paste basic scripts and compile and execute those programs directly from within Qedit. The Bxbasic components are: * Bxbasm.exe: a stand-alone Basic Compiler. A Bxbasic script, written using Notepad, Wordpad , Edit, or any other ascii text editor may be compiled into x86 assembly language while in a Dos Window or in Console Mode, (i.e. command line). * Qeditor.exe: is a component of Masm32 and is a stand alone ascii text editor. Qedit is the key to the ease of use of Bxbasic. * ML.exe: is the Masm32 assembler. * Link.exe:is the Masm32 linker. Bxbasm may be used in the following manner: *) follow the instruction, exactly, for installing Bxbasm, *) from Windows, load Qeditor, *) enter, or cut-n-paste the following text: (case is sensitive) ' begin:> CLS BEEP PRINT "hello world! END ' end:> *) now, from the File menu, select Save and save the file as TEST1.BAS, in the \Masm32\Bxbasm\ directory, *) from the Menu-bar, select Compiler and then from the drop-down menu, select Console Compile, a Dos-Box will open and dialog will appear on the screen: * first from: Bxbasic, * then the: Assembler, (this will take several seconds), * then the: Linker, and finally, a listing of "Test1" files: Test1.bas Test1.asm Test1.obj Test1.exe (examine the file size for Test1.exe) *) press the [enter] key and then close the Dos-Box: [X] *) to execute Test1.exe: from the Menu-bar, again select Compiler and from the drop-down menu, select Run Program *) the Dos-Box remains open until you press [enter]. That's all there is to it!!! Was there an error compiling?: *)If there was an error in the Basic script or any other error during compile, assembly or linking, the error message would be displayed in the Dos-Box, indicating what the error was. Bxbasm does have a limited amount of error checking and if it encounters an error, a message will be displayed and the compile will terminate at the point of error. Bxbasm will not compile and assemble a program with a known error. *)If you did not follow the instructions exactly for installing Masm32 and Bxbasm, that will cause an error! *)There are aspects of Masm32 that require that it be installed in the ROOT directory, ie: C:\Masm32\... Masm32 will not work any other way. Attempting to relocate the \Masm32\ directory and it's entire contents to a subdirectory elsewhere on the drive will not work! What functions does Bxbasic support? Since Bxbasic is a work in progress, as of this date it consists of a subset of the Basic language. New commands and functions are being added at regular intervals. At present the KEYWORD list is as follows: Keyword: Description: ASM passes assembly language code to the assembler BEEP beep sound on pc speaker BREAK used in a WHILE, DO, or LOOP routine CLEAR erase variables CLOSE terminate disk file access CLS clear screen CHDIR change disk directory CHDRIVE change drives COLOR selects foreground and background colors DIM * dimensions arrays, *(presently strings) DO/WHILE creates a loop routine END terminate program FIELD fields strings to I/O Buffer FOR/NEXT creates a loop routine FILES displays directory file list GET device input, random access GOSUB/RETURN branch to, return from subroutine GOTO absolute jump to line label IF/ELSEIF/ELSE/ENDIF conditional expression, alternate condition default action, condition terminator INPUT keyboard input INPUT# device input KILL delete file LET assignment to variable LINE INPUT keyboard input LINE INPUT# device input LOCATE position cursor on console screen LSET moves data to I/O Buffer LOOP/ENDLOOP creates a loop routine LPRINT text output to line printer on LPT1 MKDIR make new directory NAME/RENAME rename a disk file OPEN open disk file for access PRINT display data to console screen PRINT# write text image to file PUT device output REM comments. may substitute with: ' RSET moves data to i/o buffer RANDOM produce a pseudo-random number READ# device input, file RMDIR remove directory SHELL drop to DOS console THEN used with IF statement WRITE# device output WHILE/WEND creates a loop routine **Note: Bxbasic is case sensitive. All keywords and functions must appear in upper case. Additionally, there are several string, algebraic and device functions. Strings: Function: Description: CHR$() ascii character assignment DATE$ returns the current date LEFT$() left string slicing MID$() middle string slicing MKD$() convert double precision to string (file I/O) MKI$() convert integer to string (file I/O) MKS$() convert single precision to string (file I/O) RIGHT$() right string slicing SPACE$() blank space(s) assignment STR$() numeric to string assignment STRING$() ascii character string assignment TIME$ returns the current time Algebraic/Numeric: Function: Description: ABS(exp) absolute value of expression ASC(str$) numeric value of ascii character ATN(exp) arctangent of expression ATN2(exp) arctangent of y/x ACOS(exp) arc cosine of x ASIN(exp) arc sine of x COS(exp) cosine of expression COSH(exp) hyperbolic cosine of x CEIL(exp) smallest whole number not less than x CLOCK() elapsed time in clock ticks CVD(str$) convert string to double precision (file I/O) CVI(str$) convert string to integer (file I/O) CVS(str$) convert string to single precision (file I/O) FLOOR(exp) largest whole number not greater than x HYPOT(exp) length of hypotenuse for x and y INT(exp) integer value of a number LEN(str$) length of ascii string LOG(exp) logarithm of x LOG10(exp) base 10 logarithm of x RAND(seed) seeds random number generator SIN(exp) sine of expression SINH(exp) hyperbolic sine of x SQRT(exp) square root of expression TAN(exp) tangent of expression TANH(exp) hyperbolic tangent of x VAL(str$) numeric value of a number-string Device: Function: Description: INKEY$ a single keyboard character INPUT$ a string of keyboard characters EOF(hndl) returns true if end-of-file LOC(hndl) returns current file-record position LOF(hndl) returns length of file in bytes Usage examples: Here are some 'cut-n-paste' examples that you can try. Merely 'cut-n-paste' them to the Qedit text editor and save them as Test.bas. Then compile and execute them. Line Numbers, REM, CLS, PRINT, BEEP, END: In it's most basic from, the program statement looks like this: 1 REM test.bas version 1 2 CLS 3 PRINT "hello world!" 4 BEEP 5 END Line Numbers: Program lines may or may not be numbered. Line numbers have a minimal practical use and their usage is not recommended, but, their usage is included for compatibility. If line numbers are used, the must appear in column #1, the far left side, only. Line numbers will appear here for illustrative purposes only. In the above example: REM in line 1: is a comment, CLS in line 2: clears the display screen PRINT in line 3: prints a message on the display screen BEEP in line 4: sounds a beep on the pc speaker END in line 5: terminates the program PRINT The PRINT command takes the form: PRINT (generates a newline) or PRINT "text" or PRINT variable or PRINT (expression) END Every program must have an END command. However, it need not be at the end of the program. GOTO: In the example below, using the GOTO command: line 5: performs an absolute jump to line #9 line 11: an absolute jump to line #6 line 8: terminates the program 1 REM test.bas version 2 2 CLS 3 PRINT "hello world!" 4 BEEP 5 GOTO 9 6 PRINT "Back at line #6" 7 PRINT "The End." 8 END 9 PRINT "Now at line #9" 10 BEEP 11 GOTO 6 LET: The LET command has the form: LET variable = value or LET variable = variable or LET variable = "text string" In this example, line 5: keyword LET assigns a numeric value to integer variable: "abc". 1 REM test.bas version 3 2 CLS 3 PRINT "hello world!" 4 BEEP 5 LET abc = 100 6 PRINT "abc = 100" 7 END Variable names are limited to 32 alpha-numeric characters only. No punctuation characters are permitted (at this time). Variables are distinguished into five types: Symbol: Type: $ character string # double precision floating point ! single precision float % long integer none integer If a variable name has no type specifier, it is assumed to be of type integer. Here, in: line 12 thru 14: three integer assignments are made. line 15: variable 'abc' is re-assigned a new value: 1 REM test.bas version 4 2 CLS 3 PRINT "hello world!" 4 BEEP ' ... 12 LET abc = 100 13 LET xyz = 999 14 LET qwerty = 12345 15 LET abc = 32123 16 END In this next example, variables: abc, xyz and qwerty are assigned values. Then PRINT command is used to display each variable's contents. 1 REM test.bas version 5 2 CLS 3 PRINT "hello world!" 4 LET abc = 100 5 PRINT abc, 6 LET xyz = 999 7 LET qwerty = 12345 8 LET abc = 32123 9 PRINT xyz, 10 PRINT qwerty, 11 PRINT abc 12 PRINT "The End." 13 END LOCATE: The LOCATE command has the form: LOCATE row, column In lines 4 and 5, variables: row and column are each given a value. Then on line 6, the LOCATE command it used to position the cursor, at: Row: 2 Column: 10 and again in line 10: 1 REM test.bas version 6 2 CLS 3 PRINT "hello world!" 4 LET Row = 2 5 LET Column = 10 6 LOCATE Row, Column 7 PRINT "hello world!" 8 LET Row = 4 9 LET Column = 20 10 LOCATE Row, Column 11 PRINT "hello world!" 12 END The console mode screen is character based and has the dimensions of 25x80. The upper left corner is row 0, column 0. Math Expression Assignments: A variable assignment can be in the form of a mathematical expressions. As shown in line 4: 1 REM test.bas version 7 2 CLS 3 PRINT "hello world!" 4 LET abc = 2 + 2 5 PRINT abc 6 END Complex algebraic expressions can be used in an assignment: 1 REM test.bas version 8 2 CLS 3 PRINT "hello world!" 4 LET xylophone = 50 5 LET yazoo = 100 6 LET abc = yazoo/xylophone 7 LET xyz = yazoo/10 8 LOCATE abc , xyz 9 PRINT "hello world!" 10 LET quasar = 2 11 LET zapp = 4 12 LET abc = (quasar * quasar * zapp + zapp)/5 13 LET xyz = ((quasar*quasar)*zapp)+zapp 14 LOCATE abc, xyz 15 PRINT "hello world!" 50 END Optional: Line Numbers, REM, LET: As stated previously, line numbers are entirely optional and in most cases un-needed. The only time they may actually be needed is as line labels. Here, even the REM is optional, as well. The REM keyword may be replaced with the apostrophy (') character. Blank or empty lines are ignored by the compiler and often times help to make the source code more readable. Also, the LET keyword is optional. ' test.bas version 9 ' CLS PRINT "hello world!" LET xylophone = 50 LET yazoo = 100 LET abc = yazoo/xylophone xyz = yazoo/10 ' LOCATE abc , xyz PRINT "hello world!" ' ------------------------------------------ quasar = 2 zapp = 4 abc = (quasar * quasar * zapp + zapp)/5 xyz = ((quasar * quasar) * zapp) + zapp ' LOCATE abc, xyz PRINT "hello world!" ' ------------------------------------------ ' PRINT PRINT " 2*(3+4)*5/10 = "; abc = 2*(3+4)*5/10 PRINT abc ' TheEnd: END ' ------------------------------------------ In the above code, examine the PRINT statements. PRINT has several forms: PRINT abc prints variable followed by newline PRINT generates a newline PRINT "" also a newline PRINT a; semi-colon does not send a newline PRINT a, comma sends a tab, no newline BLOCK LABELS: "Block Labels" are preferred over line numbers and give symbolic meaning to a routine or a block of code. ' test.bas version 10 CLS ' now jump to a block label GOTO OverThere ' TheBeginning: PRINT "We"; CHR$(39); "re at The Beginning!" GOTO TheEnd ' There: PRINT "We"; CHR$(39); "re There!" GOTO TheBeginning ' JumpBack1: PRINT "We Jumped Back 1!" GOTO There ' OverThere: PRINT "We"; CHR$(39); "re Over There!" GOTO JumpBack1 ' TheEnd: END ' ------------------------------------------ **NOTE (Neither single nor double quotes may be used within a text string, as they are mis-interpreted by the assembler as being assembler directives. As in the above example, ascii character 39 is a single quote (') mark.) Where used, line Labels or "Block Labels" must start at the far left column, as shown above. A Label name: * may contain up to 32 alpha-numeric characters, * must contain no punctuation characters, * must be terminated by a colon (:), * is case sensitive, so: label: Label: and LABEL: are each unique. When used with a GOTO statement, the label name is not terminated by the colon. i.e.: GOTO Label1 ' test.bas version 11 Start1: CLS GOTO Jump Return: GOTO TheEnd Jump: PRINT "hello world!" ' ------------ LET xylophone = 50 LET yazoo = 100 LET abc = yazoo/xylophone xyz = yazoo/10 LOCATE abc , xyz PRINT "hello world!" ' ------------------------------------------ quasar = 2 zapp = 4 abc = (quasar * quasar * zapp + zapp)/5 xyz = ((quasar * quasar) * zapp) + zapp LOCATE abc, xyz PRINT "hello world!" ' ------------------------------------------ PRINT PRINT " 2*(3+4)*5/10 = "; abc = 2*(3+4)*5/10 PRINT abc GOTO Return TheEnd: END ' ------------------------------------------ CLEAR: The CLEAR command has the form: CLEAR or CLEAR variable-name ' test.bas version 12 Start1: CLS PRINT "hello world!" ' ------------ LET xylophone# = 50.3 LET yazoo# = 101.25 LET abc = yazoo#/xylophone# xyz = yazoo#/10 quasar = 2 zapp = 4 abc = (quasar * quasar * zapp + zapp)/5 xyz = ((quasar * quasar) * zapp) + zapp abc = 2*(3+4)*5/10 ' CLEAR ' ------------------------------------------ TheEnd: END ' ------------------------------------------ A plain CLEAR statement will erase all variables. If a variable does not any longer exist, or has previously been erased, the CLEAR command will ignore that fact. It will not cause an error. In the example below, the CLEAR command may be used selectively to erase variables. ' test.bas version 13 Start1: CLS PRINT "hello world!" ' ------------------------------------------ abc = 11100 xyz = 32000 abc% = 33000 xyz% = 99000 abc! = 33000.33 xyz! = 99000.47 abc# = 333000.33 xyz# = 999000.47 test$ = "test" ' CLEAR abc, xyz, INT, abc%, xyz%, LNG, abc!, xyz!, FLT CLEAR abc#, xyz#, DBL, test$, STR CLEAR ' ------------------------------------------ TheEnd: END ' ------------------------------------------ NUMERICAL DATA TYPES: **NOTE: Bxbasm is a strongly typed language. That means that data types must be indicated by the use of a data-type specifier at the end of each variable name. If no data type specifier is appended to a variable, then Bxbasic will assume the default data type of Integer. Bxbasm uses four (4) numeric data types: data type: symbol: example: Integer % ivariable% = 99 Long Integer @ lvariable@ = 987654321 Float ! fvariable! = 1.123456 Double Float # dvariable# = 123.123456789 Simple integers have a limited range and can not handle fractional or "real" numbers. As shown here, an expression may contain mixed data types. The result will be the destination variable's type. ' test.bas version 14 Start1: CLS PRINT "hello world!" ' ------------ LET xylophone# = 50.3 LET yazoo# = 101.25 LET abc = yazoo#/xylophone# xyz = yazoo#/10 LOCATE abc , xyz PRINT "hello world!" ' ------------------------------------------ quasar = 2 zapp = 4 abc = (quasar * quasar * zapp + zapp)/5 xyz = ((quasar * quasar) * zapp) + zapp LOCATE abc, xyz PRINT "hello world!" ' ------------------------------------------ PRINT PRINT " 2*(3+4)*5/10 = "; abc = 2*(3+4)*5/10 PRINT abc ' ------------------------------------------ PRINT PRINT "xylophone# = "; PRINT xylophone# PRINT "yazoo# = "; PRINT yazoo# TheEnd: CLEAR END ' ------------------------------------------ Here are some examples of expressions using different data types. ' test.bas version 15 Start1: CLS PRINT "hello world!" ' ------------------------------------------double float LET xylophone# = 50.3 LET yazoo# = 101.25 LET abc = yazoo#/xylophone# xyz = yazoo#/10 LOCATE abc , xyz PRINT "hello world!" ' ------------------------------------------long integers quasar% = 2 zapp% = 4 abc% = (quasar% * quasar% * zapp% + zapp%)/5 xyz% = ((quasar% * quasar%) * zapp%) + zapp% LOCATE abc%, xyz% PRINT "hello world!" ' ------------------------------------------ PRINT PRINT " 2*(3+4)*5/10 = "; abc = 2*(3+4)*5/10 PRINT abc ' ------------------------------------------ PRINT PRINT "xylophone# = "; PRINT xylophone# PRINT "yazoo# = "; PRINT yazoo# PRINT PRINT "abc%="; PRINT abc% PRINT "xyz%="; PRINT xyz% ' ------------------------------------------ TheEnd: CLEAR END ' ------------------------------------------ ' test.bas version 16 Start1: CLS ' ------------------------------------------ abc = 11100 xyz = 32000 abc% = 33000 xyz% = 99000 abc! = 33000.33 xyz! = 99000.47 abc# = 333000.33 xyz# = 999000.47 ' integer PRINT PRINT "abc="; PRINT abc PRINT "xyz="; PRINT xyz ' long PRINT "abc%="; PRINT abc% PRINT "xyz%="; PRINT xyz% ' float PRINT "abc!="; PRINT abc! PRINT "xyz!="; PRINT xyz! ' double PRINT "abc#="; PRINT abc# PRINT "xyz#="; PRINT xyz# ' ------------------------------------------ TheEnd: CLEAR END ' ------------------------------------------ ' test.bas version 17 Start1: CLS PRINT "hello world!" ' ------------------------------------------double float LET xylophone# = 50.3 LET yazoo# = 101.25 LET abc = yazoo#/xylophone# xyz = yazoo#/10 LOCATE abc , xyz PRINT "hello world!" ' ------------------------------------------long integers quasar% = 2 zapp% = 4 abc% = (quasar% * quasar% * zapp% + zapp%)/5 xyz% = ((quasar% * quasar%) * zapp%) + zapp% LOCATE abc%, xyz% PRINT "hello world!" ' ------------------------------------------ PRINT PRINT " 2*(3+4)*5/10 = "; abc = 2*(3+4)*5/10 PRINT abc ' ------------------------------------------ abc = 11100 xyz = 32000 abc% = 33000 xyz% = 99000 abc! = 33000.33 xyz! = 99000.47 abc# = 333000.33 xyz# = 999000.47 ' integers PRINT PRINT "abc="; PRINT abc PRINT "xyz="; PRINT xyz ' long integers PRINT "abc%="; PRINT abc% PRINT "xyz%="; PRINT xyz% ' float PRINT "abc!="; PRINT abc! PRINT "xyz!="; PRINT xyz! ' double PRINT "abc#="; PRINT abc# PRINT "xyz#="; PRINT xyz# ' ------------------------------------------ TheEnd: CLEAR END ' ------------------------------------------ STRING VARIABLES: String variable assignments may be expressed in several ways. To begin with, a string variable is terminated by the '$' symbol. A string variable may be a single character, no character, or a number of characters, with a maximum of 255 characters. ' test.bas version 18 Start1: CLS PRINT "hello world!" abc$ = "test" xyz$ = "" ' ^---------------here, xyz is null, empty! END '------------------------- ' test.bas version 19 CLS abc$ = "testing" xyz$ = abc$ PRINT abc$ PRINT xyz$ ' ------------------------------------------ TheEnd: END ' ------------------------------------------ COMPLEX PRINTING: The PRINT statement can be used in complex ways to create the desired display. ' test.bas version 20 Start1: CLS PRINT "hello world!" ' ------------------------------------------ abc = 2*(3+4)*5/10 PRINT PRINT " 2*(3+4)*5/10 = "; abc PRINT ' ------------------------------------------ abc = 11100 xyz = 32000 abc% = 33000 xyz% = 99000 abc! = 33000.33 xyz! = 99000.47 abc# = 333000.33 xyz# = 999000.47 ' integers PRINT "abc="; abc, "xyz="; xyz ' long integers PRINT "abc%="; abc%, "xyz%="; xyz% ' float PRINT "abc!="; abc!, "xyz!="; xyz! ' double PRINT "abc#="; abc#, "xyz#="; xyz# ' ------------------------------------------ TheEnd: CLEAR END ' ------------------------------------------ GOSUB RETURN: Subroutines are the preferred method of program branching. Subroutines allow for a more structured style of programming over the absolute jump of a GOTO statement. Subroutines are identified by a block label and called with the GOSUB command. Each GOSUB command has a matching RETURN command. If you GOSUB, you must RETURN from the subroutine. ' test.bas version 21 GOSUB Start1 GOSUB DoubleFloat GOSUB LongIntegers GOSUB RDParser GOSUB PrintVars GOSUB ClearVars GOTO TheEnd ' ------------------------------------------ Start1: CLS Hello$ = "hello world!" PRINT Hello$ RETURN ' ------------------------------------------double float DoubleFloat: LET xylophone# = 50.3 LET yazoo# = 101.25 LET abc = yazoo#/xylophone# xyz = yazoo#/10 LOCATE abc , xyz PRINT Hello$ RETURN ' ------------------------------------------long integers LongIntegers: quasar% = 2 zapp% = 4 abc% = (quasar% * quasar% * zapp% + zapp%)/5 xyz% = ((quasar% * quasar%) * zapp%) + zapp% LOCATE abc%, xyz% PRINT Hello$ RETURN ' ------------------------------------------ RDParser: abc = 2*(3+4)*5/10 PRINT PRINT " 2*(3+4)*5/10 = "; abc PRINT RETURN ' ------------------------------------------ PrintVars: abc = 11100 xyz = 32000 abc% = 33000 xyz% = 99000 abc! = 33000.33 xyz! = 99000.47 abc# = 333000.33 xyz# = 999000.47 ' integers PRINT "abc="; abc, "xyz="; xyz ' long integers PRINT "abc%="; abc%, "xyz%="; xyz% ' float PRINT "abc!="; abc!, "xyz!="; xyz! ' double PRINT "abc#="; abc#, "xyz#="; xyz# RETURN ' ------------------------------------------ ClearVars: test$ = "test" CLEAR abc, xyz, INT, abc%, xyz%, LNG, abc!, xyz!, FLT CLEAR abc#, xyz#, DBL, test$, STR CLEAR RETURN ' ------------------------------------------ TheEnd: END ' ------------------------------------------ GOSUB's may be nested. That means that a second GOSUB may be called even before RETURNing from the first subroutine. The second subroutine may even call a third subroutine, etc. As long as there are an equal number of RETURNs as GOSUBs. ' test.bas version 22 GOSUB Start1 GOTO TheEnd ' ------------------------------------------ Start1: CLS Hello$ = "hello world!" PRINT Hello$ GOSUB DoubleFloat RETURN ' ------------------------------------------double float DoubleFloat: LET xylophone# = 50.3 LET yazoo# = 101.25 LET abc = yazoo#/xylophone# xyz = yazoo#/10 LOCATE abc , xyz PRINT Hello$ GOSUB LongIntegers RETURN ' ------------------------------------------long integers LongIntegers: quasar% = 2 zapp% = 4 abc% = (quasar% * quasar% * zapp% + zapp%)/5 xyz% = ((quasar% * quasar%) * zapp%) + zapp% LOCATE abc%, xyz% PRINT Hello$ GOSUB RDParser RETURN ' ------------------------------------------ RDParser: abc = 2*(3+4)*5/10 PRINT PRINT " 2*(3+4)*5/10 = "; abc PRINT GOSUB PrintVars RETURN ' ------------------------------------------ PrintVars: abc = 11100 xyz = 32000 abc% = 33000 xyz% = 99000 abc! = 33000.33 xyz! = 99000.47 abc# = 333000.33 xyz# = 999000.47 ' integers PRINT "abc="; abc, "xyz="; xyz ' long integers PRINT "abc%="; abc%, "xyz%="; xyz% ' float PRINT "abc!="; abc!, "xyz!="; xyz! ' double PRINT "abc#="; abc#, "xyz#="; xyz# GOSUB ClearVars RETURN ' ------------------------------------------ ClearVars: test$ = "test" CLEAR abc, xyz, INT, abc%, xyz%, LNG, abc!, xyz!, FLT CLEAR abc#, xyz#, DBL, test$, STR CLEAR RETURN ' ------------------------------------------ TheEnd: END ' ------------------------------------------ FOR NEXT: The FOR/NEXT commands allow for the creation of complex loop structures. The basic syntax is: FOR (condition, increment) program... NEXT (increment loop) The 'conditional expression' and 'increment' take the form of: variable% = start TO end, STEP increment variable%: is the object of the condition start: is the starting value for 'variable' end: is the destination for 'variable' increment: is the amount by which to increment 'variable' Where: FOR x% = 1 TO 100 STEP 1 x% = 1: Assigns the starting value of 1 to variable 'x%'. Variable 'x' must be of type: LONG: (%). TO 100: Sets a desired value of: 100 for 'x'. STEP 1: The amount by which to increment. If the STEP value were: 3 'x%' would be incremented by 3 after each loop cycle. If no STEP value is stated, the default is: 1. NEXT is little more than a block label, or block delimiter, but, it also keeps track of which variable we need to increment for the next cycle. FOR/NEXTs may be nested. i.e.: FOR (cond-1) [outer loop] FOR (cond-2) [inner loop] program... NEXT (inc) [inner loop] NEXT (inc) [outer loop] However, you may not exit an outer loop before exiting an inner loop. An inner loop may be terminated, however. To terminate an inner loop, an IF/ELSE expression can be used to test for a condition and based on the result, object variable can be forced to the destination value. Example: FOR x% = 1 TO 10 FOR y% = 1 TO 100 ......[inner loop] IF y% = 50 THEN y% = 100 [force: y% = 100] ENDIF PRINT CHR$(32); NEXT y% ......[inner loop] NEXT x% This will have the desired effect of satisfying the condition: FOR y% = 1 TO 100 ' test.bas version 23 CLS GOSUB TOP GOSUB Center GOSUB Bottom GOTO TheEnd '---------------------- Center: FOR x% = 1 TO 5 PRINT "*"; FOR y% = 1 TO 28 PRINT " "; NEXT y% PRINT "*" NEXT x% RETURN '---------------------- TOP: Bottom: FOR x% = 1 TO 30 PRINT "*"; NEXT x% PRINT "" RETURN '---------------------- TheEnd: END '---------------------- This example will generate a box made of stars in the upper left corner of the display, like this: ****************************** * * * * * * * * * * ****************************** POWER, MODULUS: Besides the numerical operators: +,-,/ and *, Bxbasic also uses the Power symbol: ^ and the Modulo symbol: %. Power: The symbol ^ represents the Power function. The effect is to raise a number to the Power of a second number. Example: result = 10 ^ 2 "result" equals: 10 raised to the power of 2. The product, (100) is assigned to "result" Modulo: The symbol % represents the Modulus function. The effect is to capture the remainder of a division operation. Example: mod = 10 % 3 "mod" equals the remainder of 10/3. The product, (1) is assigned to variable "mod" ' test.bas version 24 GOSUB Start1 END ' ------------------------------------------ Start1: CLS power = 10 ^ 2 PRINT "power="; power ' ten = 10 three = 3 ' we can use the modulus operator: % mod = ten % three PRINT "mod="; mod ' or we can use the keyword: MOD mod = 30 MOD 9 mod = ten MOD mod PRINT "mod="; mod RETURN ' ------------------------------------------ The word MOD may be used in place of the % symbol. One word of caution: when used with numeric variables, the % symbol has to have a blank space on either side of it, or the variable may be confused as a LONG integer. i.e.: var1 % var2 correct. var1%var2 incorrect! IF/ELSE: The IF/ELSE conditional expression uses the form: IF (condition) THEN first condition [program...] ELSEIF (condition) THEN second condition [program...] ELSE default action [program...] ENDIF terminator In the above, there are two conditional expressions: Condition #1: if condition #1 is TRUE, then: [the following action is taken] [program resumes at point beyond the ENDIF] if condition #1 is FALSE, then: [evaluate expression #2] -------------------------------------- Condition #2: elseif condition #2 is TRUE, then: [the following action is taken] [program resumes at point beyond the ENDIF] elseif condition #2 is FALSE, then: [take default action] -------------------------------------- Default: else [the following action is taken] [program resumes at point beyond the ENDIF] endif The simplest conditional expression might be: IF (condition) THEN conditional expression [program...] ENDIF terminator where only one condition is evaluated. Conditional expressions may also use the Boolean AND/OR operators. Example: IF a = b AND x = y THEN ...etc. or: IF a = b OR x = y THEN ...etc. These condition operators may be used: operator description = is equal to <> is not equal to < is less than > is greater than <= is less or equal to >= is greater or equal to ' test.bas version 25 CLS abc = 99 xyz = 33 abc$ = "test" xyz$ = "testing" ' IF xyz$ = "testing" AND abc >= xyz THEN PRINT "if:expression = true" ELSEIF abc <= 100 OR abc$ <= "hello" THEN PRINT "elseif:expression = true" ELSE PRINT "else:expressions = false" ENDIF PRINT "done" ' ------------------------------------------ TheEnd: END ' ------------------------------------------ STRING FUNCTIONS: Function: Usage: CHR$() a$ = CHR$(n) where: (n) is an ascii value. LEFT$() a$ = LEFT$(s$,n) where: s$ is a string variable name, 'n' is the number of characters to copy from the left. RIGHT$() a$ = RIGHT$(s$,n) where: s$ is a string variable name, 'n' is the number of characters to copy from the right. MID$() a$ = MID$(s$,x,n) where: s$ is a string variable name, 'x' is the character starting position from the left, 'n' is the number of characters to copy. SPACE$() a$ = SPACE$(n) where: 'n' is the number of blank spaces STR$() a$ = STR$(n) where: 'n' is a numeric value to be converted to a character string. STRING$() a$ = STRING$(n,x) where: 'n' is the number of characters, 'x' is an ascii value. ' test.bas version 26 CLS xyz = 42 abc$ = CHR$(xyz) PRINT "abc$ = ";abc$ ' xyz$ = "testing" abc$ = LEFT$(xyz$, 4) PRINT abc$ ' abc$ = RIGHT$(xyz$, 5) PRINT abc$ ' abc$ = MID$(xyz$, 3, 3) PRINT abc$ ' abc$ = SPACE$(3) PRINT ">";abc$;"<" ' abc$ = STR$(199) PRINT abc$ ' abc$ = STRING$(10, xyz) PRINT ">";abc$;"<" ' ------------------------------------------ TheEnd: END ' ------------------------------------------ ' test.bas version 27 CLS xyz = 42 xyz$ = "testing" ' abc$ = LEFT$(xyz$, 4) + CHR$(xyz) + RIGHT$(xyz$, 5) + SPACE$(3) + MID$(xyz$, 3, 3) + STR$(-199) + STRING$(10, xyz) PRINT abc$ ' abc$ = CHR$(34) + "Hello" + CHR$(32) + "world!" + CHR$(34) PRINT abc$ ' ------------------------------------------ TheEnd: END ' ------------------------------------------ ' test.bas version 28 CLS abc$ = "This is a test of the Emergency Broadcast System" PRINT "Test: >"; CHR$(251); "< End Test" PRINT ">"; LEFT$(abc$, 14); "<" PRINT ">"; RIGHT$(abc$, 26); "<" PRINT ">"; MID$(abc$, 23, 19); "<" PRINT ">"; SPACE$(10); "<" PRINT ">"; STR$(1000); "<" PRINT ">"; STRING$(10, 251); "<" ' ------------------------------------------ TheEnd: END ' ------------------------------------------ ' test.bas version 29 CLS PRINT ">"; STR$(1000); "<" PRINT ">"; STRING$(10, 251); "<" PRINT CHR$(247) abc = 10 xyz = 3 PRINT abc * xyz PRINT 1 + (abc * xyz) PRINT (abc / xyz) * 2 PRINT 1+(2*5)/3 ' ------------------------------------------ TheEnd: END ' ------------------------------------------ INKEY$: The INKEY$ function captures the character currently entered in the keyboard buffer. INKEY$ has a unique quality that makes it quite different from other types of keyboard input. When INKEY$ is called, it does not wait for the user to strike a key. Instead, after collecting the character, even if there is no character in the buffer, it continues on to the next instruction. You may be wondering what good is that? I doesn't wait for you to type a character? The short answer is no, it doesn't wait. On the other hand the user doesn't have to strike the return key, either. What does this mean? INKEY$ is especially well suited for a loop construct or a subroutine call that polls the keyboard buffer. Here is an example of how to use INKEY$: ' test.bas version 30 CLS Start: abc$ = INKEY$ IF abc$ = "" THEN GOTO Start ENDIF PRINT abc$ ' ------------------------------------------ TheEnd: END ' ------------------------------------------ In the above example, INKEY$ is used in a continuous loop, that tests the keyboard buffer for a character. If there is no character, then abc$ will be null, or empty. In that event, program control jumps back up to Start: and repeats the loop. Does this look familiar? Press any key to continue._ ' test.bas version 31 CLS PRINT "Press any key: "; Start: abc$ = INKEY$ IF abc$ = "" THEN GOTO Start ENDIF PRINT abc$ ' ------------------------------------------ TheEnd: END ' ------------------------------------------ INPUT: The INPUT command accepts standard input from the keyboard. The INPUT command requires a return or newline character to terminate input. Example: INPUT a$ accepts a character string INPUT val accepts a numeric value In this example: INPUT ;"First: "; first$; " Last: "; last$: the display shows: First: _ while the cursor waits for the contents of first$ to be entered. Which then displays: First: Bill Last:_ on the same line, waiting for the contents of last$ to be entered. INPUT, in this example, acts as both an INPUT and a PRINT command. Since the return key is required to end input, by placing a semi-colon after the INPUT command, tells Bxbasic not to echo the newline character. Example: INPUT ; "Enter your Name: "; name$ This will have the effect of keeping the cursor on the same line. ' test.bas version 32 CLS PRINT "Press any key to begin: "; Start: abc$ = INKEY$ IF abc$ = "" THEN GOTO Start ENDIF PRINT abc$ ' PRINT "Enter your name:" INPUT ;"First: "; first$; " Initial: "; init$; " Last: "; last$ PRINT "Enter your age and birth date:" INPUT ;"Age: "; age; " Month: "; mo; "/Day: "; day; "/Year: "; year% ' PRINT first$, init$, last$ PRINT age, mo, day, year% INPUT a$ ' ------------------------------------------ TheEnd: END ' ------------------------------------------ INPUT$: The INPUT$ function differs from the INPUT command in the way in which it is used. The INPUT$ function is a character string function and is used to input string data, as opposed to numeric data. The characters entered are assigned to a string variable. The INPUT$ function accepts a parameter, in the form of an integer value. That value is the number of characters that INPUT$ will accept. Example: a$ = INPUT$(n) where 'n' is an integer Once the total number of characters have been entered, the program moves on to the next instruction. Hitting the return key is not required, but, entering the total number of characters is. An example of where this might be used is in accepting data entry of a known fixed length. ' test.bas version 33 CLS abc$ = INPUT$(10) PRINT abc$ ' ------------------------------------------ TheEnd: END ' ------------------------------------------ LINE INPUT: The LINE INPUT command is very similar to the plain INPUT command, except that all the data entered is assigned to a single string variable. Also, LINE INPUT will accept an entire line of text, up to 255 characters and is terminated by a newline character. LINE INPUT can be used much the same way as the INPUT command, with or without a prompt string: Example: LINE INPUT "Enter your: Address, City and State: "; a$ or LINE INPUT a$ The return key terminates input. ' test.bas version 34 CLS PRINT "1: "; LINE INPUT abc$ ' ^-----notice no prompt PRINT abc$ LINE INPUT "2:enter a string: "; abc$ PRINT abc$ LINE INPUT ;"3:enter a string: "; abc$ ' ^------no echo:return PRINT abc$ LINE INPUT ;"4:enter a string: "; abc$, ' no echo---^ insert tab-------^ PRINT abc$ INPUT a$ ' ------------------------------------------ TheEnd: END ' ------------------------------------------ ALGEBRAIC FUNCTIONS: Function: Usage: ABS(n) num% = ABS(number) returns the absolute value of a number. ASC(c$) num = ASC(char$) returns the value of an ascii character. ATN(n) num# = ATN(num) returns the arctangent of a number. COS(n) num# = COS(num) returns the cosine of a number. SIN(n) num# = SIN(num) returns the sine of a number. TAN(n) num# = TAN(num) returns the tangent of a number. SQRT(n) num# = SQRT(num) returns the square root of a number. INT(n) num% = INT(num#) returns the integer value of a floating point number. ' test.bas version 35 CLS xyz = 99 abc = ABS(xyz - 1.75) PRINT abc abc = ASC("A") PRINT abc abc! = ATN(xyz / 3) PRINT abc! abc! = COS(5.8 * .0174533) PRINT abc! abc! = SIN(xyz / 11) PRINT abc! abc! = TAN(xyz / 10) PRINT abc! abc! = SQRT(xyz) PRINT abc! abc = INT(xyz / 3.1) PRINT abc ' ------------------------------------------ TheEnd: END ' ------------------------------------------ ' test.bas version 36 CLS abc = 10 xyz = 99 PRINT ABS(xyz - 1.75) PRINT ASC("A") PRINT ATN(xyz / 3) PRINT COS(5.8 * .0174533) PRINT SIN(xyz / 11) PRINT TAN(xyz / 10) PRINT SQRT(xyz) PRINT INT(xyz / 3.1) ' ------------------------------------------ TheEnd: END ' ------------------------------------------ DISK FILE I/O: OPEN, CLOSE: File I/O is dependant on the abiliy to OPEN and CLOSE disk files. The OPEN command requires a specific format using three parameters. i.e.: 1) I/O Mode 2) File Handle 3) Filename/Path Example: OPEN "I", #1, "data.fil" I/O Mode------^ ^ ^-------Filename ^-----File Handle The I/O Modes are: I = Input read a file O = Output create/write to file A = Append write to existing file File Handle numbers can range from 1 to 99. The CLOSE command can be used in two ways: CLOSE close all open files CLOSE 1,2,3 close files #1, #2 and #3 Before we can run this next program, you will need to create a file named Test.txt. Using Notepad, create an empty file, just hit the return key about three or four times, then save the file to your working directory, naming it "Test.txt", and close it. Now copy this to Test.bas, then compile and run it: ' test.bas version 37 CLS ' PRINT "Opening Test File" OPEN "I", #1, "test.txt" PRINT "Closing Test File" CLOSE 1 ' ------------------------------------------ TheEnd: END ' ------------------------------------------ Okay, maybe that wasn't all that impressive, but, it did OPEN Test.txt for Input and then CLOSE it. In this next example, a character string, filename$, is assigned the file-name information. Either a quoted string, as used in the above, or a string variable may be used for this purpose. ' test.bas version 38 CLS filename$ = "test.txt" ' PRINT "Opening Test File" OPEN "I", #1, filename$ PRINT "Closing Test File" CLOSE 1 ' ------------------------------------------ TheEnd: END ' ------------------------------------------ For the next example, copy this line of data to our data file, Test.txt: hello world,next string,32000,650000,1.123,3000000.123 Make sure this is at the very top line. Also, delete any blank lines that may come after it, so that this is the only thing in Test.txt. Now, compile and run this Test.bas: ' test.bas version 39 CLS ' PRINT "Opening Test File" OPEN "I", #1, "test.txt" INPUT#1, input$, next$, valuea, valueb%, valuec!, valued# CLOSE 1 PRINT input$, next$, valuea, valueb%, valuec!, valued# ' ------------------------------------------ TheEnd: END ' ------------------------------------------ When executed, Bxbasic OPENs Test.txt for Input, using Handle #1 and INPUTs two string variables and four numeric variables. It then CLOSEs Handle #1 and prints out the information. Now, let's try something a little more challenging. Copy the following into the data file: Test.txt hello world,next string,32000,650000,1.123,3000000.123 hello ,world,2000,50000,0.123,5000000.123 Now compile and run this Test.bas: ' test.bas version 40 CLS ' PRINT "Opening Test File" OPEN "I", #1, "test.txt" INPUT#1, input$, next$, valuea, valueb%, valuec!, valued# PRINT input$, next$, valuea, valueb%, valuec!, valued# ' INPUT#1, input$, next$, valuea, valueb%, valuec!, valued# PRINT input$, next$, valuea, valueb%, valuec!, valued# CLOSE 1 ' ------------------------------------------ TheEnd: END ' ------------------------------------------ In this example, Bxbasic reads in two seperate lines of data and processed it as before. This is okay, if you only have one or two lines of data to input. In practice, though, it's not very practical. EOF(): If you have a data file that contains twenty lines of data to input, you don't want to code twenty identical lines of INPUT instructions. Instead, a more practical application would be to read the data in, in some form of loop. For example: OPEN "I", #1, "test.txt" ' Start: INPUT#1, input$, next$, valuea, valueb%, valuec!, valued# PRINT input$, next$, valuea, valueb%, valuec!, valued# GOTO Start ... Here, the program loops through the data file, inputing each line of data. There is one major problem with this though. The code above forms a continuous loop that would end in an error or program crash. Why ? It has to do with the fact that when the program gets to the end of the file, it just tries to keep on reading. This is not a good thing. The solution is to have a means of detecting when we have reached the end of the file and terminate the process before it does any harm. That is where EOF comes in. EOF is a file or device function. The sole purpose is to detect the End-Of-File. Using the sample code from above, all we need to do is to add a condition test to the loop, that will test for End-Of-File. Like this: OPEN "I", #1, "test.txt" ' Start: IF EOF(1) THEN GOTO Finish ENDIF INPUT#1, input$, next$, valuea, valueb%, valuec!, valued# PRINT input$, next$, valuea, valueb%, valuec!, valued# GOTO Start Finish: CLOSE 1 In this example, we keep looping, reading-in data, until we detect an End-Of-File condition. Then we stop trying to read. Below, is a Test.bas that we can try it on. Before we can test this out, we need to modify Test.txt. Copy the following into Test.txt: hello world,next string,32000,650000,1.123,3000000.123 hello ,world,2000,50000,0.123,5000000.123 hello world,next string,32000,650000,1.123,3000000.123 Save and close it. Now compile this: ' test.bas version 41 CLS PRINT "Opening Test File" OPEN "I", #1, "test.txt" ' Start: IF EOF(1) THEN GOTO Finish ENDIF INPUT#1, input$, next$, valuea, valueb%, valuec!, valued# ' IF input$="" THEN GOTO Start ENDIF PRINT input$, next$, valuea, valueb%, valuec!, valued# GOTO Start ' Finish: CLOSE 1 ' ------------------------------------------ TheEnd: END ' ------------------------------------------ In line 12, is another status test. There, it is testing for the possibility of a mis-read, where a read attempt was made but for some reason it was unable to. In this case, it loops back up to see if it has reached the End-Of-File. WRITE: Inputing data is only half of file I/O. The other half is WRITEing data to a disk file. The WRITE command looks identical to the INPUT command. In fact, the WRITE command is the mirror image of the INPUT command. Except that the data flows in the opposite direction. Here is an example where we open a second file for OUTPUT and WRITE to it the data we have INPUT from the first file. Notice that the data written out need not be in the same order as was read-in. ' test.bas version 42 CLS ' PRINT "Opening Test File" OPEN "I", #1, "test.txt" ' OPEN "O", #2, "test2.txt" ' Start: IF EOF(1) THEN GOTO Finish ENDIF INPUT#1, input$, next$, valuea, valueb%, valuec!, valued# IF input$="" THEN GOTO Start ENDIF PRINT input$, next$, valuea, valueb%, valuec!, valued# ' WRITE#2, valued#, valuec!, valueb%, valuea, next$, input$ ' ..................write data in reversed order! GOTO Start ' Finish: CLOSE 1, 2 ' ------------------------------------------ TheEnd: END ' ------------------------------------------ Compile and execute the above Test.bas and then examine the contents of Test2.txt. Now try this next one: ' test.bas version 43 CLS ' PRINT "Opening Test File" OPEN "I", #1, "test.txt" ' OPEN "A", #2, "test2.txt" ' Start: IF EOF(1) THEN GOTO Finish ENDIF INPUT#1, input$, next$, valuea, valueb%, valuec!, valued# IF input$="" THEN GOTO Start ENDIF PRINT input$, next$, valuea, valueb%, valuec!, valued# WRITE#2, input$, next$, valuea, valueb%, valuec!, valued# GOTO Start ' Finish: CLOSE 1, 2 ' ------------------------------------------ TheEnd: END ' ------------------------------------------ Is there going to be anything different in the result ? After executing it, examine Test2.txt. LINE INPUT#: Just as we can use the LINE INPUT command to enter an entire line of text from the keyboard, we can also us it to INPUT an entire line of data from a disk file. An entire line of data, up to 255 characters, terminated by a newline character, can be read in to a single string variable. Now try this Test.bas: ' test.bas version 44 CLS ' PRINT "Opening Test File" OPEN "I", #1, "test.txt" ' Start: IF EOF(1) THEN GOTO Finish ENDIF LINE INPUT#1, input$ ' IF input$="" THEN GOTO Start ENDIF PRINT input$ GOTO Start ' Finish: CLOSE 1 ' ------------------------------------------ TheEnd: END ' ------------------------------------------ PRINT#: The function that mirrors LINE INPUT, oddly enough is not LINE WRITE, but, PRINT#. We are using the PRINT command and the hash-mark (#) indicates that we are PRINTing to a device. Try this Test.bas and then examine Test2.txt: ' test.bas version 45 CLS ' PRINT "Opening Test File" OPEN "I", #1, "test.txt" OPEN "O", #2, "test2.txt" ' Start: IF EOF(1) THEN GOTO Finish ENDIF LINE INPUT#1, input$ ' IF input$="" THEN GOTO Start ENDIF PRINT input$ PRINT#2, input$ GOTO Start ' Finish: CLOSE 1, 2 ' ------------------------------------------ TheEnd: END ' ------------------------------------------ RANDOM I/O An additional method of disk I/O is called Random Access. Unlike sequential file access, which requires that disk file data be accessed sequentially, from beginning to end, Random access allows individual records to be written or read from a disk file in any desired order. Generally, in a random access file, records have a fixed length, with a predetermined number of characters or bytes. There by allowing records to be stored with each record having a known distance from the beginning of the file. For instance, assume for a moment that a database will contain an unknown number of records, but, that each record will have a fixed length of one hundred ascii characters. Example: first name:[ ] = 15 characters last name:[ ] = 15 characters address:[ ] = 30 characters information:[ ] = 20 characters information:[ ] = 20 characters The record consists of the clients: name, address and information, for a total of 100 characters. If this record were to be stored as record number one, then record number two would be stored beginning one hundred bytes away from the beginning of the file. You would say that record number two has an offset of one hundred bytes. Record number three would begin two hundred bytes from the start of the file and therefore have an offset of two hundred bytes. A disk file of this description, opened for random access, would have the ability to read-in or write-out data using a disk buffer one hundred bytes in length. Reading in or writing out information one hundred bytes at a time, beginning at a calculated offset for a particular record. Since a random access file has the ability to read or write individual records without disturbing the surrounding records, it need not be opened strictly for INPUT or for OUTPUT. Once a random access file is opened, it may be both read from and written to, at the same time. Opening a random access file is no different from opening a sequential access file, with the exception that an "R" is used for the mode specifier and the filename/path is followed by the record length. i.e.: OPEN "R", #1, "test.txt", 50 The record length indicates the number of bytes the buffer will read or write for each record and will be used to calculate the offsets for each record. There are five commands that are used when dealing with random access files: FIELD, LSET, RSET, PUT and GET. FIELD: divides the I/O buffer into it's individual parts or strings of information that will comprise the record. Using the above example data: first name: = 15 characters last name: = 15 characters address: = 30 characters information: = 20 characters information: = 20 characters the I/O buffer will be divided up like this: I/O BUFFER [first$ ][last$ ][address$ ][info1$ ][info2$ ] ( 15 chars )( 15 chars )( 30 chars )( 20 chars )( 20 chars ) The usage for the FIELD command is: FIELD #1, 15 AS F$, 15 AS L$, 30 AS A$, 20 AS I1$, (etc...) LSET/RSET: are abbreviations for Left-Set and Right-Set. In the event that the data contained in a particular string is too short, for instance if first$ only contains five characters and not all fifteen, LSET or RSET may be used to add padding, (blank spaces) to fill in the required length. The difference between LSET and RSET is that: LSET pushes the existing string information to the far left of the string and adds any required padding to the right of the data. RSET pushes the existing string information to the far right of the string and adds any required padding to the left of the data. Example: First$ = "Fred" LSET [Fred...........] RSET [...........Fred] LSET and RSET guarantee that each data string is the proper length when put into the buffer before writing it to the file. Usage for LSET and RSET are: LSET F$ = first$ LSET L$ = last$ LSET A$ = address$ RSET I1$ = info1$ RSET I2$ = info2$ As a result of the LSET or RSET commands, the data is set to the proper lengths and placed into the I/O buffer. PUT: is the command to write the buffer to the file. The usage is: PUT 1,(record #) PUT 1, 99 PUT 1, rec% (where rec% is a long integer variable) GET: is the command to read-in a file record into the buffer. Usage is: GET 1,(record #) GET 1, 99 GET 1, rec% (where rec% is a long integer variable) Here is an example of using the above random access commands: **(first, begin by deleteing "Test.txt"): ' test.bas version 46 CLS ' q$ = "This" x$ = "is" y$ = "a" z$ = "test" w$ = "record" ' OPEN "R", #1, "test.txt", 50 FIELD #1, 10 AS A$, 10 AS B$, 10 AS C$, 10 AS D$, 10 AS E$ LSET A$ = q$ LSET B$ = x$ LSET C$ = y$ LSET D$ = z$ RSET E$ = w$ PUT 1, 1 CLOSE 1 PRINT "Done!" ' ------------------------------------------ TheEnd: END ' ------------------------------------------ Cut-n-paste Test.bas #46 and try it, then examine file: "test.txt". Now, still using #46, change the record number in the PUT statement to read: PUT 1, 2 then re-compile Test.bas and after you run it, examine "test.txt". Now try this Test.bas: ' test.bas version 47 CLS ' q$ = "This" x$ = "is" y$ = "a" z$ = "test" w$ = "record" rec% = 1 ' OPEN "R", #1, "test.txt", 50 FIELD #1, 10 AS A$, 10 AS B$, 10 AS C$, 10 AS D$, 10 AS E$ FOR x% = 1 TO 5 STEP 1 LSET A$ = q$ LSET B$ = x$ LSET C$ = y$ LSET D$ = z$ RSET E$ = w$ ' PUT 1, rec% rec% = rec% + 1 NEXT x% CLOSE 1 CLEAR ' OPEN "R", #1, "test.txt", 50 FIELD 1, 10 AS A$, 10 AS B$, 10 AS C$, 10 AS D$, 10 AS E$ GET 1, 2 ' PRINT A$ PRINT B$ PRINT C$ PRINT D$ PRINT E$ CLOSE 1 ' ------------------------------------------ TheEnd: END ' ------------------------------------------ I/O STRING FUNCTIONS: As you've seen in the above, when reading from or writing to a random I/O file, the buffer is made up of fixed length strings. You may be wondering how then do we read or write numeric information, such as floating point numbers or the results of a calculation. This is accomplished with the "make" and "convert" functions. The make functions are: MKD$() = make a double float into a string MKS$() = make a single float into a string MKI$() = make an integer into a string and are used for writing binary numeric data to a file. The usage would be: LSET A$ = MKD$(double#) LSET B$ = MKS$(single!) LSET C$ = MKI$(integer) or (integer%) or (integer@) The convert functions are: CVD() = convert a string into a double float CVS() = convert a string into a single float CVI() = convert a string into an integer The usage would be: double# = CVD(A$) single! = CVS(B$) integer% = CVI(C$) Here is a new Test.bas, using these new functions to try: ' test.bas version 48 CLS az#=1.012345 bz!=123.456 cz%=123456 dz = 12345 w$ = "end" rec% = 1 ' OPEN "R", #1, "test.txt", 34 FIELD #1, 4 AS A$, 4 AS B$, 8 AS C$, 8 AS D$, 10 AS E$ FOR x% = 1 TO 5 STEP 1 LSET A$ = MKI$(dz) LSET B$ = MKI$(cz%) LSET C$ = MKS$(bz!) LSET D$ = MKD$(az#) RSET E$ = w$ PUT 1, rec% rec% = rec% + 1 NEXT x% CLOSE 1 CLEAR ' OPEN "R", #1, "test.txt", 34 FIELD #1, 4 AS A$, 4 AS B$, 8 AS C$, 8 AS D$, 10 AS E$ GET 1, 1 ' az# = CVD(D$) bz! = CVS(C$) cz% = CVI(B$) dz = CVI(A$) PRINT "az#="; az# PRINT "bz!="; bz! PRINT "cz%="; cz% PRINT "dz ="; dz CLOSE 1 ' ------------------------------------------ TheEnd: END ' ------------------------------------------ This example uses a FOR/NEXT loop to write five consecutive records to disk. Now examine Test.txt. Looks pretty weird, huh? Remember, with the exception of string variable w$, all the variables were numeric values. And, that's what number values look like in their binary form. The reason we wrote w$ ('end') was simply for the purpose of placing a visible marker, so that we could see where the record ends. Not only do random access files allow access to individual records within the file, numbers are written to disk in a visually 'encrypted' form. There is one more important thing to know about FIELDing numbers. That is, that regular integers, (of type: integer and integer%) must be FIELDed to a length of four (4) bytes and ALL other number types must be FIELDed to eight (8) bytes. Example: FIELD #1, 4 AS integer$, 4 AS integerX$,... FIELD #1, 8 AS float$, 8 AS double$, 8 AS longinteger$,... where integer = variable (4 bytes) and integerX = variable% (4 bytes) and longinteger = variable@ (8 bytes) and float = variable! (8 bytes) and double = variable# (8 bytes) Some other useful functions are: LOC() = returns the offset pointer within the current file LOF() = returns the length, in bytes, of the current file LEN() = returns the length of a string variable Usages would be: pointer% = LOC(buffer) len% = LOF(buffer) len = LEN(mystring$) Here is a Test.bas showing them in use: ' test.bas version 49 CLS ' OPEN "R", #1, "test.txt", 34 FIELD #1, 4 AS A$, 4 AS B$, 8 AS C$, 8 AS D$, 10 AS E$ GET 1, 2 ' pointer% = LOC(1) PRINT "file offset = "; pointer% ' len% = LOF(1) PRINT "file length = "; len% ' string$ = E$ len = LEN(string$) PRINT "len string$ = "; len, ">"; string$; "<" ' az# = CVD(D$) bz! = CVS(C$) cz% = CVI(B$) dz = CVI(A$) PRINT "az# = "; az# PRINT "bz! = "; bz! PRINT "cz% = "; cz% PRINT "dz = "; dz CLOSE 1 ' ------------------------------------------ TheEnd: END ' ------------------------------------------ ' Count to One Million - program ' PRINT "counting to one million..." PRINT curtime$ = TIME$ PRINT "Start time is:", curtime$ PRINT FOR ndx = 1 TO 1000000 STEP 1 NEXT ndx curtime$ = TIME$ PRINT "End time is:", curtime$ ' ------------------------------------------ TheEnd: END ' ------------------------------------------ Summary: This document is a only a brief description of the Bxbasic language syntax and by no means anywhere near to being complete. This document doesn't even include all of the Bxbasic commands nor string and math functions. Future releases will add new features, resolve bugs and other undocumented features. If you have any suggestions or functions you'd like to see added (sooner than later), your feedback is very welcome. If you do find any errors or typos you'd like to report, you can contact me through the QDepartment at: http://groups.yahoo.com/groups/QDepartment/ -or- QDept_Group at: http://groups.yahoo.com/groups/QDept_Group/ The Author, Steve ----------------------------------------------------- Blunt_Axe_Basic Project Bxbasm/Bxbasic Copyright:(c) sarbayo, 2001,02,03,04 Alpha Version 1.05 -----------------------------------------------------