This page presents a summary of the Benton Harbor Basic programming language dialect. This material is believed to be correct and complete, if somewhat terse, but if you have additional material or notice an error in this material, please forward it to the author for inclusion in the next update.

Resets the workspace to its initial state as if you had just started the Basic interpreter. Use this command before starting a new program. You will need to confirm this command by answering "y" to the prompt.

List the program source. If entered without the optional argument, the entire program will be listed. You can enter one line number to list only that line, or two line numbers to list a block of statements.

If the running program stopped due to execution of a STOP statement, or because you pressed Ctl-C, this command will cause the program to continue operation where it left off. A CONTINUE command following a CLEAR command or an END statement is treated the same as a RUN command; the program is started at the first line.

These commands are used to read Basic programs from disk, save them to disk, and otherwise manage source program files.

In each of these commands, "filename" refers to a file on one of the H-17 disk drives. You may specify the drive ("sy1:myprog") or leave it off to read from sy0: ("myprog"). You may include the .bas file extension, but it is not necessary.

OLD "filename"

Opens the program file and reads it into memory. If a program was already in memory when this command was entered, the Basic interpreter will clear the workspace before reading the new program. You do not need to enter SCRATCH first.

Basic language statements start with a line number and contain one or more program statements.

You may place more than one statement on a line by separating them with a colon (":"). Example:

00010 PRINT "There is one statement on this line."
00020 PRINT:PRINT:PRINT "But there are three on this line."

Be aware that you can only GOTO or GOSUB to the beginning of a numbered line, so if a given statement is to be the target of a GOTO or GOSUB, it must be at the beginning of a line of code.

Variables are dynamically created when a value is first assigned to them. Variable names consist of a single letter or a letter and number. String variables add a "$" to the end of the name. Letter case is ignored.

Prints output to the console. (See also File Access Statements below for the form of PRINT to write to files.)

One PRINT statement can print a number of variables, literals, expressions or strings. If the arguments are separated by commas, they will be printed in zones that are 14 print positions wide by default (see CNTRL 3 in Hardware Access Statements). If the arguments are separated by semicolons, they will be printed one after the other. Examples:

Branch to a different line in the program and run that section of code as a subroutine. When a RETURN statement is executed, execution will continue at the statement following the GOSUB command. Example:

The ON command is a simple "computed GOTO/GOSUB" which will branch to one of a list of program statements depending on the value of a variable. (See also the LNO() function in Data Conversion Functions.) Example program fragment:

Use CHAIN to read a new program off the disk and begin execution of that program. Any open files are still open; all defined variables are still defined. You can use CHAIN as a command; it's the same as using OLD followed by RUN.

The only difference between STOP and END involves the CONTINUE statement. If you enter CONTINUE after a STOP, the program will continue operation with the statement following the STOP statement. If you enter CONTINUE after an END, the program will start at the top as if you had entered a RUN command.

Use PAUSE to pause execution. If you include the optional integer argument, the program will pause for "ticks" clock ticks (or ticks * 2 milliseconds). If this is omitted, the program will pause until the user presses the enter key.

DEF FN is used to create user-defined functions. These functions can accept one or more arguments of either numeric or string type and can return a numeric or string value. The following program uses a function to convert degrees to radians for use with the SIN() function:

The standard rules of algebra apply: multiply and divide operations are done before add and subtract. The expression 1+2*3 will evaluate to 7.

Parenthesis can be used to change the order of evaluation. (1+2)*3 will evaluate to 9. Parenthesis can be nested to any reasonable level. (If you think that 15 levels is "reasonable," the author suggests that you forget about Basic and switch to Lisp!)

There is no end-of-file indication available; if you read past the end of the file, the next INPUT statement will cause an error and the program will end. You should include an end-of-data marker in the data, or see the CIN() function below for another approach.

This exactly duplicates the INPUT statement and has the same format. But LINE INPUT will accept null input and return a zero-length string, so LINE INPUT may be preferred, depending on what you are reading from the file.

This function reads a single character from a file open for read access, and returns the ordinal value of the ASCII character. CIN returns the value -1 at end of file. This example reads and prints "errormsg.sys" one character at a time... slowly:

You might use this function to, say, report progress on demand in a long-running program.... "We are on loop 345 of 10,000. Be patient!" You can see an example of this in the RND() function example in Mathmatical Functions.

CNTRL 1,value

This sets the number of digits (1 to 6) to print to the left of the E in scientific format. If a number is too big to print in this many digits, it will be changed to scientific format. Example:

*PRINT 12345
12345
*CNTRL 1,3
*PRINT 12345
1.23E+04

CNTRL 2,value

This controls the front panel LED display. A value of zero turns the display off (default condition after loading the Basic interpeter; the LEDs are normally off becaise updating the display takes up to 15% of the processor and you need all you can get to run Basic at a 2 mhz clock rate.)

A value of one turns the display on, but with update disabled. This allows you to write to the display yourself. See examples with the SEG() function below.

A value of two turns the display on with updates enabled, as it normally is when HDOS is running.

CNTRL 3,value

This command sets the width of the print zones. By default, the print zones are 14 columns wide, but they can be made larger or smaller with this command. Example:

*PRINT 1,2,3
1 2 3
*CNTRL 3,4
*PRINT 1,2,3
1 2 3

CNTRL 4,value

This command is used to load and unload the main HDOS overlay, HDOSOVL0. This is a command only; this cannot be used as a program statement. It should be used before a program is loaded into memory.

Normally, Basic allocates the maximum amount of available memory for your program, leaving the overlay on disk. This slows the execution of statements like OPEN and CLOSE, and slows the delivery of error messages, which are read from errormsg.sys. Loading the overlay into memory will reduce available memory by about 2.9 K/bytes, but will greatly speed the execution of your programs.

*CNTRL 4,1 - load the overlay
*CNTRL 4,0 - unload the overlay

This command has no effect if you are running HDOS in stand-alone mode.

This function will take a decimal value from zero through nine and convert it to the binary pattern needed to display that value in the front-panel LEDs. The following example will put the digits 9 through 1 into the front panel LEDs:

This is the pseudo-random number function. "arg" has three possible value ranges:

< 0: sets the random number "seed";

> 0: returns the next random number in the sequence;

= 0: returns the same random number as the last one.

If you start with the same seed value, you will get the same sequence of random numbers out of the generator. This can be good for testing but terrible for any real use, so the seed should be different from run to run. PAM/8's 16-bit .TICCNT is a reasonable source for a different number every time, as shown in this sample, which shows the average value of 10,000 random numbers. (The closer to .5, the better.)

This program will run quite a long time, so we included a line-of-dots progress indicator (one dot per 1000 generated numbers) and an on-demand progress report accessed by typing Ctl-B. (Refer to CNTRL 0 in Hardware Access Statements.)

This function searches 'stringa' for an occurrence of 'stringb', starting at 'start' offset into 'stringa'.

The following example looks for every occurrence of a given substring in a string, and prints the location where it is found, as well as the breakdown of the string to the left and right of the substring. This is a comprehensive example showing the use of MATCH, GOSUB, LEFT$(), MID$(), RIGHT$() and LEN().

The value function will return the numeric value of the first numeric substring in the passed string. Evaluation starts with the first non-blank character in the string and ends with the first non-numeric character.

VAL("123.45") - returns the number 123.45
VAL("123 456 876") - returns the number 123
VAL(" 123 is my address") - returns the number 123
VAL("12digits long") - returns the number 12
VAL("my name is Dave") - returns the number 0

POS(0) returns the postion of the cursor on the console, based on the number of characters printed with PRINT statements. If you move the cursor to the right by hand using the cursor keys or the space bar, POS() will not register the move. Example:

00010 INPUT "enter a number from 1 to 50: ";n
00020 IF n<1 or n>50 THEN 10
00030 FOR i=1 TO n
00040 PRINT ".";
00050 NEXT i
00060 p=POS(0)
00070 PRINT "x"
00080 PRINT "that 'x' is in column";p;"of the screen"
00090 END

Only pass the value zero to the function, as shown. Other positive values will return a nonsense result.