PBASRM.WS4
----------

- "Personal BASIC Reference Manual"
  First Edition: April 1983

(Retyped by Emmanuel ROCHE.)

(ROCHE> The 16 pages of errata found in the READ.ME file dated August 1983  of 
Personal  BASIC Version 1.1 have been incorporated in this file which  is,  as 
far as I know, the ultimate reference.)


Foreword
--------

Personal BASIC is an interpreted programming language designed for  beginners, 
hobbyists,  and  experienced  programmers  alike. You  need  no  knowledge  of 
computers or programming to learn Personal BASIC. The Personal BASIC  language 
manuals  supply  all the information that you need to start  programming  your 
computer.  With  a  little practice, you can  easily  write  programs  custom-
tailored to your personal and professional needs.

If you are a newcomer to computer programming, start with the "Personal  BASIC 
Tutorial".  The tutorial takes you through Personal BASIC one step at a  time, 
teaching   you  the  elementary  lessons  of  programming  through   examples, 
participation, and challenges.

As  your  programming  skill develop, the "Personal  BASIC  Reference  Manual" 
becomes your main source of information. The Reference Manual is divided  into 
5 sections:

      - Section  1  explains how to write, edit, and debug  a  Personal  BASIC 
        program.

      - Section  2 explains how to represent data in a program  --  constants, 
        variables, and arrays.

      - Section  3  explains  how to work with numbers  and  characters  in  a 
        program.

      - Section  4  explains how to put information into a  program,  and  get 
        information out.

      - Section  5  presents  every Personal  BASIC  command,  statement,  and 
        function in alphabetical order, with diagrams and examples.

Personal BASIC runs under the CP/M-86, MP/M-86, and Concurrent CP/M  operating 
systems, based on the Intel 8086, 8088 family of microprocessors.

We,  at  Digital  Research, are interested in your comments  on  programs  and 
documentation.  Please, use the Software Performance Reports enclosed in  each 
product package to help us provide you with better software products.


Table of Contents
-----------------

1     Programming in Personal BASIC
1.1   Personal BASIC basics
1.2   Personal BASIC characters
1.3   Line format
1.4   The Personal BASIC program editor
1.4.1 The Edit Mode
1.4.2 Syntax errors
1.5   Program errors and debugging
1.5.1 Break Mode

2     Constants and variables
2.1   Constants
2.1.1 Numeric constants
2.1.2 String constants
2.2   Variables
2.2.1 Variable names
2.2.2 Type declarations
2.2.3 Arrays
2.3   Type conversion
2.3.1 Numeric conversion
2.3.2 String conversion

3     Expressions and operators
3.1   Numeric expressions
3.1.1 Arithmetic operators
3.1.2 Relational operators
3.1.3 Logical operators
3.1.4 Numeric functions
3.1.5 Order of execution
3.2   String expressions
3.2.1 String concatenation
3.2.2 String comparisons
3.2.3 String functions

4     Input and output
4.1   Console input
4.2   Printing
4.2.1 Formatted printing
4.2.2 String field formatting characters
4.2.3 Numeric field formatting characters
4.3   Disk files
4.3.1 File specification
4.3.2 Sequential files
4.3.3 Random files

5     Commands, statements, and functions


Appendixes
----------

A Personal BASIC keywords
B Decimal-ASCII-Hex table
C Creating a Personal BASIC system disk under CP/M-86
D Personal BASIC error messages
E The Option Table
F Machine-language linking conventions


Tables
------

1-1. Personal BASIC Special characters
1-2. EDIT subcommands
1-3. Debugging commands in Break Mode

2-1. Variable declaration characters
2-2. String conversion functions
2-3. Buffer string conversion functions

3-1. Arithmetic operators
3-2. Relational operators
3-3. Numeric functions
3-4. Order of execution for operators
3-5. String functions

4-1. Print statements
4-2. Print functions
4-3. Sequential file statements
4-4. Sequential file functions
4-5. Random file statements
4-6. Random access functions

5-1. EDIT subcommands
5-2. String field formatting characters
5-3. Numeric field formatting characters

B-1. ASCII symbols
B-2. ASCII conversion table

D-1. Personal BASIC error messages


Figures
-------

2-1. One-dimensional array
2-2. Two-dimensional array
2-3. Example of two-dimensional array

3-1. Logical operation truth tables

4-1. PRINT USING syntax


Listings
--------

2-1. Program using one-dimensional array

4-1. Program creating a sequential file
4-2. Sample sequential file program
4-3. Random file program
4-4. Sample program accessing random file data


Section 1: Programming in Personal BASIC
----------------------------------------

Personal BASIC is an interpreted high-level programming language. A high-level 
language  is  one that is close to the natural language that you  speak  every 
day and, therefore, easy for you to use.

Computers,  however, do not speak high-level languages. They respond  to  low-
level machine language, which is nothing but combinations of ones and zeros.

Personal  BASIC is a language that both you and your computer can  understand. 
Personal BASIC contains an interpreter. An interpreter is a program that takes 
each line as you enter it and translates it to the computer as ones and zeros. 
The  interpreter  takes  a program that you write in  Personal  BASIC  as  its 
source, and interprets and runs each line, one after another.

Personal BASIC's interpreter lets you enter a program and run it  immediately, 
write  a  line and test it on the spot. Interpreted Personal BASIC  tells  you 
when you make an error, checks your syntax and the spelling of your  commands, 
and provides you with an excellent editor to change and correct your programs. 
The  advantages of an interpreter, combined with Personal BASIC's  versatility 
and  completeness, make Personal BASIC an outstanding language  for  beginners 
and experienced programmers alike.


1.1 Personal BASIC basics
-------------------------

The  PBASIC.CMD file on your product disk is the Personal BASIC  program.  See 
Appendix C for start-up procedures. Once you start Personal BASIC, it displays 
the prompt Ok in the left-hand column. The Ok indicates that Personal BASIC is 
at command level and ready to accept your instructions. At command level,  you 
can enter Personal BASIC commands or statements.

Commands  work mainly on programs that you have already written. For  example, 
you  can  RUN  an existing program, LIST it on the screen, or  bring  it  into 
memory  with  the  OLD  command. Because  Personal  BASIC  processes  commands 
directly, you cannot use commands inside a Personal BASIC program. You  cannot 
assign a line number to a command and put it in the middle of a program.

Personal  BASIC programs contain mostly statements and functions,  although  a 
program can consist of just one statement. There are 2 kinds of statements  in 
Personal BASIC: executable and non-executable.

Executable statements perform tasks and control the flow of execution within a 
program.  You PRINT a message, OPEN a disk file, and GOTO another part of  the 
program using executable statements.

Non-executable statements provide information. The DATA statement, which lists 
data  to  assign to variables, and the REM statement, which signals  a  remark 
within the program, are non-executable statements. A non-executable  statement 
causes no program action.

Functions are predefined routines that perform tasks and return values to  the 
program.  A function works as part of a statement, not alone. If you  want  to 
find the square of 7, for example, you can write:

        PRINT SQR(7)

or you can assign the value to a variable in an assignment statement:

        Ok 10 X = SQR(7)

You  can  write  your own functions with the DEF  FN  statement  described  in 
Section 5. You cannot define a function at command level.

You  can instruct Personal BASIC in direct or indirect mode. Direct mode  lets 
you use Personal BASIC as a calculator for quick computations. Personal  BASIC 
can run only one line in direct mode. To write a program in direct mode,  type 
the statement without a line number, then press the Carriage Return [CR]  key. 
Personal BASIC runs the line and returns to command level. You can write  more 
than one statement on a line by separating the statements with colons [:]. The 
number of characters in the line cannot exceed 255.

Here  is an example of a program in direct mode. The bolded print is the  part 
that you type; the rest is printed by the computer.

        PRINT "HOW DO YOU DO?" : PRINT 2 + 2 [CR]
        HOW DO YOU DO?
         4

Most  programs  consist  of many program lines. Use  indirect  mode  to  write 
programs that contain more than one line. To write a program in indirect mode, 
begin  each line with a new line number. The line number tells Personal  BASIC 
that the line is part of a program. Personal BASIC stores the lines in  memory 
for  execution  later. When the program is complete, type the command  RUN  to 
execute it. Personal BASIC returns to command level after running the program. 
Here is an example of a program in indirect mode:

        Ok 10 INPUT "WHAT IS YOUR NAME"; NAME$
        Ok 20 PRINT "HOW DO YOU DO, "NAME$"."
        Ok 30 PRINT "SHALL WE BEGIN PROGRAMMING?"
        Ok RUN
        WHAT IS YOUR NAME? STEVEN STARTER
        HOW DO YOU DO, STEVEN STARTER.
        SHALL WE BEGIN PROGRAMMING?


1.2 Personal BASIC characters
-----------------------------

The  Personal  BASIC  character set consists of the  alphabetic  characters  A 
through  Z in upper- and lower-case, the numeric characters 0 through  9,  and 
special  characters that have meaning in Personal BASIC. The  following  table 
lists the special characters that Personal BASIC recognizes.

Table 1-1. Personal BASIC special characters

Char.   Meaning
----    -------
        Blank
  =     Equal sign or assignment symbol
  +     Plus sign or concatenation symbol
  -     Minus sign
  *     Asterisk or multiplication symbol
  /     Slash or division symbol
  \     Backslash or integer division symbol
  ^     Caret or exponentiation symbol
  (     Left parenthesis
  )     Right parenthesis
  %     Percent sign or integer type declaration character
  #     Pound (or number) sign or double precision declaration character
  $     Dollar sign or string type declaration character
  ,     Comma
  .     Period or decimal point
  '     Single quotation mark (apostrophe) or remark delimiter symbol
  ;     Semicolon
  :     Colon or multiple statement separator
  ?     Question mark
  <     Less than symbol or left angle bracket
  >     Greater than symbol or right angle bracket
  "     Double quotation mark or string delimiter
  _     Underline
 [CR]   Carriage Return
 [LF]   Line-Feed
 tab    Tab character

Personal  BASIC  can  print many other characters, even though  they  have  no 
special  meaning.  See  Appendix B for a list of ASCII  characters  and  their 
numeric values.


1.3 Line format
---------------

Most Personal BASIC programs use the indirect mode. In indirect mode, you must 
begin  every  line  in the program with a line number. The order  in  which  a 
program  line runs depends on its line number. Lines automatically  re-arrange 
according to their line numbers if you write the numbers out of sequence. Line 
numbers show the order in which Personal BASIC stores program lines in memory; 
they  serve  as reference points for branching and editing. Lines  that  begin 
with a line number are called source program lines.

Line  numbers consist of a one- to five-digit number ranging from 1 to  65529. 
Line number 0 is allowed if you do not use the renumber feature. You can use a 
period  [.] instead of a line number with the commands LIST, EDIT,  AUTO,  and 
DELETE to refer to the current program line, the line that you are working  on 
at  the  moment. Write Personal BASIC source program lines  according  to  the 
following format:

        10 PRINT "WELCOME TO PERSONAL BASIC":GOTO 10 'THIS PROGRAM LOOPS
         │ └──────────────┬────────────────┘    │    └────┬────────────┘
         │                │                     │         └──> {'Remark}
         └──> Line number └──> Statement        └──> {:Statement}

Personal  BASIC  program  lines can span more than one physical  line  if  the 
length  of the logical line does not exceed 255 characters. Use the  Line-Feed 
(Ctrl-J)  key  to continue a program line on the next  physical  line  without 
ending the logical line. The Line-Feed [LF] is stored as a single character in 
the line.

You can write remarks to document your program. Remarks make it easier for you 
to remember what your program is supposed to do. Place remarks at the end of a 
program  line  or  use the REM statement. At the end of a  program  line,  the 
remark is separated from the rest of the line by a single quotation mark  [']. 
The following example illustrates Personal BASIC source program lines:

        Ok 10 PRINT
        Ok 20 FOR I = 1 TO 5 'Loop five times
        Ok 30 PRINT I; "TESTING Personal BASIC"
        Ok 40 NEXT I
        Ok 50 PRINT : PRINT : PRINT
        Ok 60 PRINT "FINISHED!"
        Ok RUN
         1 TESTING Personal BASIC
         2 TESTING Personal BASIC
         3 TESTING Personal BASIC
         4 TESTING Personal BASIC
         5 TESTING Personal BASIC



        FINISHED!


1.4 The Personal BASIC program editor
-------------------------------------

The  Personal BASIC editor lets you enter error-free programs. You  can  enter 
commands  and program lines, delete a character, a line, or an entire  program 
from  memory,  or change an existing program one line at a  time.  The  editor 
controls  the cursor, which marks the position of the next character.  To  use 
Personal  BASIC  effectively,  you  must become  familiar  with  the  editor's 
features.  Section  4 in the "Personal BASIC Tutorial"  presents  step-by-step 
instructions on program editing.


1.4.1 The Edit Mode
-------------------

To  begin editing, type the command EDIT, followed by the line number  of  the 
program line that you want to change. The following example prepares  Personal 
BASIC to edit program line number 50.

        EDIT 50

You  can  use a period [.] in place of line number 50 if 50 is the  last  line 
that  you  wrote. The period tells Personal BASIC that you want  to  edit  the 
current program line. You can edit only one program line at a time.

Once in the edit mode, Personal BASIC displays the line that you request.  The 
prompt Ed indicates that Personal BASIC is in edit mode. Personal BASIC places 
the  cursor on the edit line, beneath the first character of the program  line 
that follows the line number, as shown:

        Ok EDIT 50                              Edit command
           50 PRINT "The average is";AVG        Program line
        Ed    _                                 Edit line

To edit, move the cursor along the edit line to the point in the program  line 
where  you want to make a change. Then, use any of the EDIT  subcommands.  The 
Personal BASIC edit subcommands perform the following tasks:

        - Move the cursor to the right or left
        - Insert characters
        - Delete characters
        - Search for characters
        - Replace characters
        - Exit and re-enter edit mode

Use  the  spacebar to move the cursor to the right. Use  the  BackSpace  [BS], 
RubOut,  or Ctrl-H to move the cursor to the left. You can move any number  of 
characters  to  the  left  by typing a number  and  one  backspace.  The  EDIT 
subcommands R and L move the cursor to the rightmost and leftmost position  in 
the edit line, respectively.

Type  a Carriage Return [CR] to save any editing changes that you  make  using 
EDIT  subcommands.  The editor returns Personal BASIC to  command  level.  The 
following table lists the 17 EDIT subcommands.

Table 1-2. EDIT subcommands

Subcom. Description
------- -----------
   A    Instructs  the editor to ignore all changes made to the current  line, 
        and to place the cursor at the beginning of the edit line. Enables you 
        to  start  editing a line over again. This command is  valid  only  if 
        there is no other subcommand on the line.

   B    Brings the cursor to the beginning of a logical line.

  [n]C  Deletes  the character that appears directly above it in  the  program 
        line,  and inserts the character that you specify to the right of  the 
        C. nC deletes n characters, and inserts all characters after the C.

  [n]D  Deletes the character that appears directly above it in the edit line.

   E    Saves  all changes and returns Personal BASIC to command level.  Works 
        like  a Carriage Return. This command is only valid if it is the  only 
        subcommand on the line.

 [ESC]  Entered  while  typing in a program line, [ESC] drops  Personal  BASIC 
        into  Edit  mode.  Used during insert mode,  [ESC]  ends  insert  mode 
        without ending the command line.

   H    Deletes  all characters in the program line up to the  next  Line-Feed 
        [LF], then automatically activates the insert subcommand: I.

   I    Inserts  characters  into  the program line,  starting  at  the  point 
        immediately  above the cursor position. All characters up to the  next 
        [ESC]  or [CR] are inserted, including Line-Feeds. I[LF] works in  the 
        way,  but  starts  by inserting a Line-Feed. [ESC]  ends  insert  mode 
        without ending the command line.

   K    Works  much  like  subcommand  S. Searches  the  program  line  for  a 
        specified  character, and positions the cursor directly  beneath  that 
        character.  However,  the  editor deletes all  characters  up  to  the 
        specified   character.  Specify  the  character  in  the   edit   line 
        immediately  after  the K. If the character is not found,  the  cursor 
        does  not  move  from the original position,  and  no  characters  are 
        deleted.

   L    Repositions  the  cursor below the leftmost character in  the  program 
        line.

  [LF]  To  edit succeeding lines of multi-line statements, press [LF]  before 
        entering insert mode. This brings you down to the next physical line.

   Q    Instructs  the editor to ignore all changes made to the current  line, 
        quits  editing,  and  returns Personal BASIC to  command  level.  This 
        command is valid only if it is the only subcommand on the line.

   R    Moves the cursor below an imaginary character one to the right of  the 
        rightmost character in the program line.

  [n]S  Searches the program line for a specified character, and positions the 
        cursor  under  the character. Specify the character in the  edit  line 
        immediately  after  the S. If the character is not found,  the  cursor 
        does  not move from the original position. A command like  99SX  finds 
        the last occurrence of X in the line, and the cursor stays there.

   U    Moves the cursor back to the previous physical line.

   X    Positions the cursor at the end of a physical line, up to a Line-Feed, 
        and  enters insert mode. X[LF] inserts a Line-Feed  first.  Subsequent 
        characters appear on a new physical line.

   Z    Deletes a Line-Feed [LF]. Merges 2 physical lines.


1.4.2 Syntax errors
-------------------

Syntax  errors  are usually typing mistakes, such as misspelled  or  misplaced 
keywords,  or  misused characters. Personal BASIC detects  syntax  errors  and 
reports them, as shown in the following example:

        Ok 10 PRINT "START"
        Ok 20 PRINT
        Ok 30 PRNIT "Testing Personal BASIC"
                 ^
        Something is wrong
        Ok EDIT 30
           30 PRNIT "Testing Personal BASIC"
        Ed      D IN
           30 PRINT "Testing Personal BASIC"
        Ed    _

Personal  BASIC detects the misspelled keyword "PRINT" in line 30 and  puts  a 
caret  [^]  under the place where you made a mistake. To  correct  the  error, 
enter  the edit mode by typing EDIT and the line number, or EDIT and a  period 
[.]  if you want to edit the line that you just typed. The editor  prints  the 
line  containing the error, and places the cursor directly beneath  the  first 
character  that follows the line number. At this point, you can space  forward 
to  the  N  in PRNIT, delete it with subcommand D, space to  the  T,  and  use 
subcommand  I  to insert an N before the T. For short lines, it  is  sometimes 
more efficient to retype the line from the beginning.


1.5 Program errors and debugging
--------------------------------

Program  errors,  or bugs, are common. Even the most  experienced  programmers 
spend  a lot of time finding and fixing errors that make their programs  fail. 
These errors might be mistakes in program flow, such as loops that do not end, 
branches  to statements that do not exist, or improper data type  assignments, 
such  as  assigning  a person's name to a  numeric  variable.  Personal  BASIC 
provides  a  break mode and a complete set of debugging command to  helps  you 
find program errors.


1.5.1 Break Mode
----------------

In  break  mode, you can suspend execution anywhere in the program.  To  enter 
break  mode, type the BREAK command after the Ok prompt, and run the  program. 
Personal  BASIC  indicates break mode with the prompt Br.  See  the  "Personal 
BASIC  Tutorial",  Section  11.1, for a simple  and  thorough  explanation  of 
debugging and break mode.

Ctrl-C  is  useful for breaking execution of an endless  loop.  The  following 
example shows a program that is interrupted by a break. Notice the Br prompt.

        Ok RUN
           10
           ...
           100
        -- Break -- at line 110
        Br _

You  can  stop  program execution wherever you want by using BREAK  to  set  a 
breakpoint at a given line number. You can set breakpoints from command  level 
or  in break mode. The following example sets a breakpoint from command  level 
at program line 40:

        Ok BREAK 40

If  you  omit the line number after the keyword BREAK, Personal BASIC  sets  a 
breakpoint  at every line in the program. Personal BASIC marks breakpoints  in 
the program listing with a lower-case b, as shown in the next example:

        Ok LIST

           10   PRINT:PRINT
           20   FOR I% = 1 TO 10
           30   PRINT "TESTING Personal BASIC!"
        b  40   NEXT I%
           50   END

If  you  run  the  preceding program after  entering  the  BREAK  40  command, 
execution breaks at line 40. Personal BASIC prints a b before the program line 
where the break occurs, as shown in the following example:

        Ok BREAK 40
        Ok RUN

        TESTING Personal BASIC!
        b  40    NEXT I%
        Br _

Once in break mode, you can use the debugging commands in Table 1-3 to monitor 
the flow of execution. See Section 5 for more information and examples of each 
command.

Table 1-3. Debugging commands in break mode

Command Explanation
------- -----------
  CONT  Resumes  program execution following a break. You cannot use the  CONT 
        command from command level.

  STEP  Lets  you execute a program one line at a time. Each  Carriage  Return 
        [CR] executes the next line, prints the line and the output  generated 
        by the line.

UNBREAK Removes all breakpoints from a program.

 TRACE  Prints  each program line with its output, but does not  stop  program 
        execution. In other words, execution does not break unless you type  a 
        Ctrl-C. Personal BASIC indicates tracing in the program listing with a 
        lower-case t.

UNTRACE Turns off the TRACE facility.

  TRON  Prints each program line number in the order it is run with the output 
        from  each  corresponding line. Line numbers are  enclosed  in  square 
        brackets: [10].

  TROFF Turns off the TRON facility.

 FOLLOW Keeps  track  of all program variables as the value of  each  variable 
        changes. FOLLOW lists the value of each variable every time that value 
        changes.  FOLLOW prints the variable name, the value of the  variable, 
        and the line number where the value changes.

UNFOLLOW Turns off the FOLLOW facility.

You can use all of the commands listed in Table 1-3 from command level and  in 
break mode, except for CONT.


Section 2: Constants and variables
----------------------------------

Computers  work with several types of data. This data consists of  characters, 
such  as John Public, or numbers, such as 99. The letters and characters  that 
you  use  as  text in your program are called strings,  or  string  data.  For 
example,  the  address of an employee in a program  that  maintains  personnel 
information is a string.

Personal  BASIC  recognizes 4 data types. Strings and numbers are the  2  main 
types of data. Numeric data is divided further into 3 types. The 4 data  types 
are:

        - strings
        - single-precision real numbers
        - double-precision real numbers
        - integers

Strings  can consist of any combination of characters, including  digits.  You 
can write a social security number in a personnel program as a string. If  you 
write it with dashes [-], as in 546-67-7845, you have to write it as a string, 
because numbers cannot contain dashes.

Numbers, or numeric data, are the values that you use to make calculations  in 
a  program.  For  example,  an employee's net  salary  is  numeric  data.  You 
calculate it using other numeric data, such as gross salary and taxes. You can 
represent  the  salary  as  a  string.  If  you  do,  you  cannot  use  it  in 
calculations. The computer treats it as a string of characters, not a  number. 
Using  strings of numbers for arithmetic would be like subtracting the  string 
John from the string Bill.

Personal BASIC automatically converts one numeric type to another in programs. 
You  can  also convert string and numeric data types by  means  of  conversion 
functions. You can represent any type of data in a Personal BASIC program as a 
constant  or  a  variable,  and you can group  the  data  in  dynamic,  multi-
dimensional arrays, as explained in Section 2.2.3.


2.1 Constants
-------------

Constants  are the values that a program uses and processes. A constant  is  a 
piece of data that does not change during the execution of a program.

For example, to write a program that calculates the area of a circle, you need 
to  use  the  value PI, or 3.14159. The value of PI never  changes;  it  is  a 
constant.  In Personal BASIC, you can give PI a name, such as X. The name  for 
PI might change. It might be X at one point, and X1 at another. But the  value 
behind that name, the value PI, is always the same.

In  Personal BASIC, you can write constants that are numeric, such as  PI,  or 
constants  that  are  strings  of characters, such as  "Enter  your  name  and 
address".  There  are  formal  rules  for  writing  both  numeric  and  string 
constants.


2.1.1 Numeric constants
-----------------------

Numeric  constants,  the numbers that you use as values in a program,  can  be 
positive or negative. You write them without commas [,]: for example, 5,000 is 
written 5000. There are 3 kinds of numeric constants in Personal BASIC:

        - single-precision real numbers
        - double-precision real numbers
        - integers

A  real number is a number that contains a decimal point [.] and  a  fraction. 
Personal  BASIC  automatically converts whole numbers, or  integers,  to  real 
numbers where necessary.

You  can  write  all  real numbers in  Personal  BASIC  in  exponential  form. 
Exponential form is an especially convenient notation for very large and  very 
small numbers. Scientists use it as shorthand, to avoid writing a long  series 
of zeros. A number in exponential form consists of:

      - a positive or negative real number (the mantissa)
      - E or D (letters for single- and double-precision)
      - a positive or negative whole number from -38 to +38 (the exponent)

The format for exponential notation is:

        (mantissa)(E or D)(exponent)

Examples:

        2E+2
        2D+20
        33E+5
        3345D-5
        .17E7
        33.45D-5

There  is an implied decimal point [.] after the mantissa. The exponent  tells 
you how many places to the right or left to move the decimal point in order to 
get  the value of the number in standard notation. A positive  exponent  gives 
the  number  of  places to move the decimal point to  the  right.  A  negative 
exponent gives the number of places to move the decimal point to the left.

For example, 45E+4 tells you to move the decimal point 4 places to the  right. 
The  number  45E+4 in standard notation is 450000. The decimal point  moves  4 
places  to  the right, and the gap is filled with zeros. The  value  45E-4  in 
standard notation is .0045. You move the decimal 4 places to the left. Do  not 
confuse the sign of the exponent with the sign of the mantissa.

The  following examples lists some numbers in exponential notation  and  their 
standard notation equivalents:

                 2E+2   =   200.
                2D+10   =   20000000000.
                33E+5   =   3300000.
              3345D-5   =   .03345
         12345.678D-3   =   12.345678
        -12345.678D+3   =   -12345678.

Remember that there are 2 types of real numbers: single-precision and  double-
precision.  Double-precision  numbers have a greater degree of  accuracy  than 
single-precision numbers.

Single-precision  numbers are accurate up to 6.8 digits internally, but  print 
with 6 digits of accuracy. Double-precision reals are accurate up to 15 digits 
and print with 15 digits of accuracy.

You  specify  a number's degree of accuracy according to your  needs  and  the 
storage  available to you -- double-precision reals take more room in  memory. 
If you do not dictate a number's precision, it is single-precision by default. 
In exponential form, signify that the number is single precision by using E or 
e after the mantissa. If the number is double precision, use D or d.

Single-precision numbers have one or more of the following characteristics:

        - 6 or fewer digits
        - E or e in the exponential form
        - a trailing exclamation mark [!]

Double-precision numbers have one or more of the following characteristics:

        - 7 or more digits
        - D or d in the exponential form
        - a trailing pound sign [#]

A  real  number  might have characteristics of both types.  For  example,  the 
number  55D+2 is only 4 digits, but include a D. In such cases, the letter  in 
the exponential form overrules the length. So, 55D+2 is double precision. If a 
number is 20 digits long but contains an E, it truncates to single  precision. 
The  type declaration characters ! and # overrule both length and  exponential 
letter. The number 5# is double precision.

The following are single-precision numbers:

        34.6!   23.9847423E+12  98.23023243!

The following are double-precision numbers:

        34.6#   354634.3434D-3  43.54D-2

In  addition  to single- and double-precision reals,  Personal  BASIC  accepts 
integers  as  numeric constant data. An integer is a whole number,  without  a 
fraction  or a decimal point. Personal BASIC integers must be in the  range  -
32768 to +32767.

You  can  write integers in decimal notation (base 10), or in  octal  notation 
(base 8), or in hexadecimal notation (base 16). For hexadecimal integers,  the 
letters  A-F, in upper- or lower-case, stand for the digits 10 through 15.  To 
write integers in hexadecimal notation, prefix them with &H. To write integers 
in octal notation, prefix them with &O, or simply &.

Here are some examples of hexadecimal and octal notation:

        Hexadecimal notation:

        &H234   (equals 564  in decimal)
        &H234B  (equals 9035 in decimal)

        Octal notation:

        &O567   (equals 375 in decimal)
        &537    (equals 351 in decimal)


2.1.2 String constants
----------------------

A  string  constant is a character, or succession of characters,  enclosed  by 
double quotation marks ["]. Strings constants cannot exceed 255 characters.

Strings  can  contain only the characters listed in Table 1-1.  You  can  also 
write  strings  with no characters. Two double adjacent quotation  marks  [""] 
form a null string. A null string contains no characters, not even a space.

If you want to write a double quotation mark within a string, write it twice.

The following are examples of string constants.

        "Please enter your name."

        "9 to 5 "

        "*&#$@!)"

        ""      (represents a null string)

        "Today's story: Faulkner's ""The Bear"""


2.2 Variables
-------------

A variable is a name for a constant value. A variable can assume the value  of 
many  different  constants  during the execution of a program. It  is  like  a 
mailbox that holds different pieces of mail on different days. A variable  can 
be assigned only one constant at a time.

You can write statements to assign constant values to variables, or a variable 
can  assume  the result of some calculation or function in  the  program.  The 
initial  value  of a numeric variable is zero. The initial value of  a  string 
variable is null.


2.2.1 Variable names
--------------------

A  variable name can be as long as you like, but only the first 31  characters 
are  meaningful for distinguishing one name from another. Variable names  must 
start  with  a letter. They can contain letters, numbers, and  decimal  points 
[.]. You cannot use spaces in a variable name.

Variables  that  represent  strings must end with  a  string  type-declaration 
character.  There are also type-declaration characters for numbers,  but  they 
are optional. Type-declaration characters are described in Section 2.2.2.

If you write your own functions in Personal BASIC, the variable names that you 
assign them must begin with FN. See the DEF FN statement in Section 5 to learn 
how to write your own functions.

A  variable  name  cannot be a Personal BASIC keyword.  Keywords  include  all 
Personal  BASIC commands, statements, functions, and operators, such as  TRON, 
END, INT, and OLD. You can embed keywords in variables, however: for  example, 
PRINT1  or  BLIST  are  legal variable names. See Appendix A  for  a  list  of 
Personal BASIC keywords.

The following are valid variable names:

        A!      X99     ZIPCODE%        Childrens.Names$

        Printed%   CHANGE.IN.VELOCITY#  RADIUS!  TOTAL%

The following are invalid variable names:

        CHILDREN'S.AGES (The apostrophe ['] starts a remark)

        Playing Field$  (Contains a blank)

        1st.value       (Start with a number)


2.2.2 Type declarations
-----------------------

Type-declaration  characters  determine the kind of constants a  variable  can 
represent.  You  must declare string variables as strings. Numeric  types  are 
optional.  Declare a type by ending the variable name with a  type-declaration 
character.  For  example, in BIRTHPLACE$, the $ indicates  that  the  variable 
BIRTHPLACE  is  a string variable. Table 2-1 shows the  Personal  BASIC  type-
declaration characters for variables.

Table 2-1. variable declaration characters

        Char.   Variable type        Example
        -----   -------------        -------
          $     String               NAME$

          %     Integer              RECORD.NUMBER%

          !     Single precision     TOTAL.PROFIT!

          #     Double precision     DIAMETER#

All  string  variables  must  end with a dollar sign  [$].  If  you  omit  the 
declaration  character at the end of a variable name, Personal  BASIC  assumes 
that the variable stands for a single-precision real number.

You  can also use declaration statements to specify variable data  types.  The 
following declaration statements are described in more detail in Section 5:

        - The DEFSTR statement declares string variables.
        - The DEFINT statement declares integer variables.
        - The DEFSNG statement declares single-precision variables.
        - The DEFDBL statement declares double-precision variables.

If there is a conflict between statement type declarations and character  type 
declarations,  the  type  that you declare using trailing  characters  on  the 
variable overrides the type that you gave in a type-declaration statement.


2.2.3 Arrays
------------

An  array is a table of values referenced by the same variable name.  You  can 
picture  an  array as a series of numbered pigeonholes or cells. An  array  of 
colors with 4 cells looks like this:

        ┌───────┬────────┬──────────┬──────────┐
        │ "RED" │ "BLUE" │ "YELLOW" │ "VIOLET" │
        └───────┴────────┴──────────┴──────────┘
           (0)      (1)       (2)        (3)

        Figure 2-1. One-dimensional array

You  reference  the elements in the array by array name and  cell  number,  or 
subscript.  Subscripts  are numeric expressions. For example,  the  cell  with 
subscript  3  of COLORS$ contains the element "VIOLET". To refer  to  it,  you 
write COLORS$(3).

COLORS$  is  one-dimensional,  but arrays can have more  than  one  dimension. 
COLORS$ as a two-dimensional array looks like this:

              ┌──────────┬─────────┐
        Row 0 │  "GRAY"  │ "GREEN" │
              ├───(0,0)──┼──(0,1)──┤
        Row 1 │ "ORANGE" │ "BROWN" │
              └───(1,0)──┴──(1,1)──┘

                Column 0   Column 1

        Figure 2-2. Two-dimensional array

Notice that the first number in the subscript refers to the row, the second to 
the  column. In a three-dimensional array, which would look like a  cube,  the 
order is rows, columns, planes.

The elements in an array can be integers or single- or double-precision  reals 
or  strings, but they must all have the type of the array variable that  names 
them.  For  example, all the elements in COLORS$ are string  values.  All  the 
elements in CHART% must be integers.

Array  variables look like regular variables, with an added subscript list  in 
parentheses ["(" and ")"]. For example:

        y$ (i$,j$,k$)
        address% (5)
        grade! (x,y,z)

Anything  you  can assign to a variable, you can assign to an  array  element. 
Anywhere you can use a simple variable, you can use an array reference.

        A(5) = 6
        Q = J(4) + 3
        Y% * WAGES! = COMPENSATION!(3,4)

An  array  subscript  can  be  an expression, such  as  j(x+y)  =  3.  Integer 
expressions are the most efficient subscripts, as real convert to the  nearest 
integer, anyway.

The  subscript  numbers  in  an  array have an assumed  base  of  0  for  each 
dimension,  which means that the elements in array X(3) are numbered 0, 1,  2, 
and  3.  If  you want an array to begin numbering at 1,  use  an  OPTION  BASE 
statement before the DIM statement declaring that array. See Section 5.

You  use the DIM statement to set the number of dimensions and the  number  of 
elements  in  each array. The fewer elements you have in each  dimension,  the 
more  dimensions  you can have, and vice versa; the theoretical limits  are  1 
element and 15 dimensions. The syntax for a DIM statement is:

        DIM (array variable name)'(subscript list)'

The  following  example  establishes  an  array  called  SUBDIVISIONS  with  2 
dimensions.

        DIM SUBDIVISIONS%(5,6)

There  are  6 elements in the first dimension, and 7 elements  in  the  second 
dimension (remember that the base is zero). See the DIM statement in Section 5 
for more information on DIM.

You  need  not  use DIM to declare an array's dimensions.  The  default  array 
subscript  range is 0 to 10 or 1 to 10, depending upon your option  base.  The 
default number of dimensions allowed is 4 for integers, and 3 for strings  and 
single-  and double-precision reals. The true maximum number of  elements  per 
dimension  for  any data type is limited by the amount  of  available  memory. 
Elements of the different data types occupy different amounts of space:

        - integer elements occupy 2 bytes
        - single-precision number elements occupy 4 bytes
        - double-precision number elements occupy 8 bytes
        - string elements occupy 6 bytes

Personal  BASIC arrays are dynamic, which means that you can declare an  array 
with DIM, erase it, and re-declare it later in the program, using the old name 
with  new dimensions. If you have a subroutine that references an  array,  you 
can  change  the  size of the array whenever you  wish  without  changing  the 
reference  in  the subroutine. Dynamic arrays also let you use a  variable  to 
dimension  an  array. Thus, you need not know the size of an  array  when  you 
dimension it.

        10 INPUT "SIZE";N
        20 DIM A(N)
        ...
        1000 INPUT "NEW SIZE";N
        1010 ERASE A
        1020 DIM A(N)

This example uses a variable, N, that you enter at the keyboard in response to 
an  INPUT request. The number that you give for N can be different every  time 
that  you  run the program. The DIM statement uses N to  dimension  the  array 
instead  of  a  constant number, so that you do not have  to  change  the  DIM 
statement  with every execution of the program. Halfway through  the  program, 
you  input  a new number for the array's dimensions.  Because  Personal  BASIC 
arrays  are dynamic, you can assign a new constant value to N, erase  the  old 
array,  and restate the array with DIM, the old array name, and the new  value 
for N.

You  can access the elements in an array using a loop. The following  FOR-NEXT 
loop  accesses all 4 elements in the COLORS$ array, and prints the  4  strings 
"RED", "YELLOW", "BLUE", and "VIOLET".

        Ok 10 FOR X% = 0 TO 3
        Ok 20 PRINT COLORS$ (X%)
        Ok 30 NEXT X%
        Ok 40 END

The  example  program in Listing 2-1 creates an array called  TEMPERATURE%  to 
calculate  average  daily  temperatures for a week.  TEMPERATURE%  is  a  two-
dimensional integer array with 7 elements in the first dimension and 3 in  the 
second dimension.

The TEMPERATURE% array organizes temperature readings taken 3 times a day  for 
one  week. The 7 elements in the first dimension correspond to the days  in  a 
week.  The 3 elements in the second dimension correspond to the 3  temperature 
readings taken each day. The array holds a total of 21 temperature readings.

Try  the program on your computer, and enter some sample temperature  readings 
to see how a multi-dimensional array works.

        Ok 10  DIM TEMPERATURE% (6,2)
        Ok 20  FOR I% = 0 TO 6
        Ok 30     FOR J% = 0 TO 2
        Ok 40  INPUT "Enter degree value", VAL%
        Ok 50  TEMPERATURE% (I%, j%) = VAL%
        Ok 60     NEXT J%
        Ok 70  NEXT I%
        Ok 80  FOR K% = 0 TO 6
        Ok 90     FOR L% = 0 TO 2
        Ok 100 TOTAL% = TOTAL% + TEMPERATURE% (K%, L%)
        Ok 110    NEXT L%
        Ok 120 AVERAGE% = TOTAL% / 3
        Ok 130 PRINT "Average temp for day" ;K% ;"is" ;AVERAGE%
        Ok 140 NEXT K%
        Ok 150 END

        Listing 2-1. Program using multi-dimensional array

(ROCHE> This example program is indented (sort of...). However, the only way I 
manage to indent a Personal BASIC program is when using Line-Feeds (Ctrl-J) to 
continue  the logical line on the next physical line. Only then does  Personal 
BASIC  keep the spaces that I insert. (It does not accept tabs  [HT],  too...) 
One  problem  is that those lines cannot contain more than  255  characters... 
Another  is that you must not forget the colon [:], else Personal  BASIC  will 
reject the line as an error...)

Line  130  prints the average temperature for each day, and  indicates  a  day 
number  ranging from 0 to 6. Day 0 refers to Sunday, day 1 refers  to  Monday, 
and  so  on. You can reset the day numbers any way you  like.  Personal  BASIC 
organizes  a two-dimensional array like a grid, with the first  dimension  the 
horizontal  coordinate,  or  row,  and  the  second  dimension  the   vertical 
coordinate, or column.

Figure 2-3 represents array TEMPERATURE% in the computer's memory.

                 (0)       (1)       (2)
             ┌─────────┬─────────┬─────────┐
        (0)  │  (0,0)  │  (0,1)  │  (0,2)  │ SUN
             ├─────────┼─────────┼─────────┤
        (1)  │  (1,0)  │  (1,1)  │  (1,2)  │ MON
             ├─────────┼─────────┼─────────┤
        (2)  │  (2,0)  │  (2,1)  │  (2,2)  │ TUE
             ├─────────┼─────────┼─────────┤
        (3)  │  (3,0)  │  (3,1)  │  (3,2)  │ WED
             ├─────────┼─────────┼─────────┤
        (4)  │  (4,0)  │  (4,1)  │  (4,2)  │ THU
             ├─────────┼─────────┼─────────┤
        (5)  │  (5,0)  │  (5,1)  │  (5,2)  │ FRI
             ├─────────┼─────────┼─────────┤
        (6)  │  (6,0)  │  (6,1)  │  (6,2)  │ SAT
             └─────────┴─────────┴─────────┘
                6 A.M.    2 P.M.   10 P.M.

        Figure 2-3. Two-dimensional array

Each  temperature  reading has a unique coordinate. For example,  the  2  P.M. 
temperature  reading  for  Thursday has the  array  coordinates  (4,1).  Every 
dimension that you add to an array creates an additional category or criterion 
for the grouping of data.


2.3 Type conversion
-------------------

The  type  of  a numeric constant converts automatically to the  type  of  the 
variable  that you assign it. Real numbers convert to integers if  you  assign 
them to an integer variable, for example. Strings do not automatically convert 
to  numbers, however, nor numbers to strings. To convert between  numbers  and 
strings,  you  must  use  conversion  functions.  See  Section  2.3.2  for   a 
description of string and numeric conversions.


2.3.1 Numeric conversion
------------------------

If you assign a number of one data type to a numeric variable of another type, 
Personal  BASIC  stores  the value using the type of the  variable.  In  other 
words,  Personal  BASIC automatically converts the number's data type  to  the 
data  type of the variable. For example, the following statements assign  real 
numbers to integer variables:

        I% = 15.25      (Converts to 15)
        J% = 33.56      (Converts to 34)
        K% = 199.99     (Converts to 200)

Note that Personal BASIC does not truncate the digits after the decimal  point 
[.], but rounds to the nearest whole number instead.

When  you assign a double-precision constant to a  single-precision  variable, 
Personal  BASIC  rounds to the nearest digit. The  following  examples  assign 
double-precision constants to single-precision variables:

        X! = 18.333346998999    (Converts to 18.3333)
        Y! = 556.89755578884    (Converts to 556.898)

If  you  assign a single-precision constant to  a  double-precision  variable, 
Personal  BASIC converts the data type of the value to double  precision,  but 
the result is only as accurate as the original single-precision value.

Personal  BASIC  provides  the  following functions  to  convert  between  the 
different numeric data types. See Section 5 for more detailed explanations and 
examples of each function.

      - The CDBL function converts a number to double precision.
      - The CINT function converts a number to an integer, by rounding.
      - The CSNG function converts a number to single-precision.
      - The FIX function truncates a number to the integer portion.
      - The  INT  function returns the largest integer that is  less  than  or 
        equal to a specified number.


2.3.2 String conversion
-----------------------

Personal BASIC provides the following functions to convert strings to numbers, 
and  to  convert ASCII characters to their numeric values. See Section  5  for 
more detailed explanations and examples of each function.

Table 2-2. String conversion functions

        Func.   Explanation
        -----   -----------
        ASC     Returns the ASCII value of the first character in a string
        CHR$    Returns  the  ASCII  character that  corresponds  to  a  given 
                numeric value.
        FLOAT   Converts an integer to a single-precision real number
        HEX$    Returns  the  hexadecimal equivalent of  a  specified  decimal 
                number as a string.
        OCT$    Returns the octal equivalent of a specified decimal number  as 
                a string.
        STR$    Returns a specified number as a string
        VAL     Returns the numeric value of a string

Personal BASIC supports conversion functions for use with random-access files. 
Because  random-access  files  work only with strings,  you  need  to  convert 
numeric  variables to buffer strings if you want to store them on a  disk.  To 
retrieve them and use them in a program, convert them back into numbers. Table 
2-3  lists the conversion functions for file buffer strings.  These  functions 
are sometimes called mapping functions. See Section 5 for further information.

Table 2-3. Buffer string conversion functions

        Func.   Explanation
        -----   -----------
        CVD     Converts a string to a double-precision real
        CVI     Converts a string to an integer
        CVS     Converts a string to a single-precision real
        MKD$    Converts a double-precision real to a string
        MKI$    Converts an integer to a string
        MKS$    Converts a single-precision real to a string


Section 3: Expressions and operators
------------------------------------

There are many ways to represent data in a computer program. For instance, you 
can write the number ten as 10, 5 + 5, 12 - 2, 550/50-1, or I%, if you  assign 
10  to  the variable I%. All of these groups of symbols and data  express  the 
number 10. Each of these groups is an expression.

An expression is a combination of symbols, such as + and -, and data, such  as 
5  and I%, that expresses a single value. The value can be a number, like  10, 
or a string, like ten. Finding the value is called evaluating the expression.

The symbols that tell you to add or subtract or multiply are called operators. 
An operator indicates a kind of calculation, such as division, or a condition, 
such as inequality. The strings and numbers they work on are called  operands. 
In the expression 5 + 5, the + is an operator and the fives are operands.  The 
expression evaluates to, or equals, 10.

You  can write expressions using strings, numbers, or variables  as  operands. 
Five  + five, 5 + 5, and 5 + X are all valid. Personal BASIC  expressions  are 
divided  into  2 classes: numeric and string. 5 + 5 is a  numeric  expression; 
Five  +  Five is a string expression. There are several kinds  of  expressions 
within each class.


3.1 Numeric expressions
-----------------------

A numeric expression consists of at least one number and at least one  numeric 
operator.  The numbers that you use can be reals, such as 12.3,  or  integers, 
such  as  12  (see  Section 2.1.1). You can use  constants  or  variables  for 
numbers.

Numeric operators are divided into 4 types:

        - arithmetic
        - relational
        - logical
        - functional


3.1.1 Arithmetic operators
--------------------------

The operators that perform arithmetic in Personal BASIC are listed in Table 3-
1. Personal BASIC integer division and modulus are explained in detail below.

Table 3-1. Arithmetic operators

        Symbol  Name            Example
        ------  ----            -------
          +     Addition        X + Y
          -     Subtraction     X - Y
          *     Multiplication  X * Y
          /     Division        X / Y
          \   Integer division  X \ Y
         MOD    Modulus         X MOD Y
          ^     Exponentiation  X ^ Y

Integer  division,  unlike regular division, rounds the operands  to  integers 
before  dividing,  and truncates the quotient to a whole number.  Division  by 
zero is invalid.

The  MOD operator is another integer function. It yields the remainder  of  an 
integer division. MOD drops any fraction after the decimal point [.].

        Integer division            Modulus
           45 \ 8 = 5              45 MOD 8 = 5
        19.23 \ 5.25 = 3        19.23 MOD 5.25 = 4
        19.50 \ 5.25 = 4        19.50 MOD 5.25 = 0


3.1.2 Relational operators
--------------------------

Every  comparison is a statement that is either true or false. To say that  an 
acorn is smaller than an oak, for example, is to compare 2 values, the size of 
an acorn and the size of an oak, and to state a relationship between them.  In 
this case, the statement is true.

In  Personal BASIC, you can compare values by means of  relational  operators. 
Relational  operators  make statements of comparison that are either  true  or 
false. If a relational statement is true, its value is -1. If false, its value 
is  0. For example, .50 > 1 = 0 (false). 50 * 4 < 400 = -1 (true).  Used  with 
the  IF  and GOTO statements, relational operators  commonly  control  program 
flow.

        9 > 10  returns  0  (0 = false)
        9 < 10  returns -1  (-1 = true)
        IF X * 5 <= 5^3 THEN GOTO 100
        IF A! / 8 = 7 MOD X THEN PRINT Z$

Table 3-2. Relational operators

        Symbol  Name                            Example
        ------  ----                            -------
          =     Equals                          X =  Y
          <>    Does not equal                  X <> Y
          <     Is less than                    X <  Y
          >     Is greater than                 X >  Y
          <=    Is less than or equal to        X <= Y
          >=    Is greater than or equal to     X >= Y

The logical expression

    IF (logical expression) THEN ...

should be evaluated only so far as is necessary to determine the result of the 
expression. In the following example:

    IF A% > 0 AND A% <= 10 AND B(A%) > 5 THEN ...

array elements outside the limits 1 to 10 should never be accessed, because if 
A% <= 0, the whole expression is known to be false.

However, this is not the case. All the subexpressions in a logical  expression 
are always evaluated, which could give rise to a "Subscript refers to  element 
outside the array" error in the above example.


3.1.3 Logical operators
-----------------------

Logical  operators  perform  another  kind  of  comparison.  Like   relational 
operators, they assert a relationship between 2 values, and that  relationship 
is either true or false. But logical operators are not concerned with  numeric 
values. They compare bit patterns.

Every  piece of data that you put into a computer, including decimal  numbers, 
is  stored  in  binary form. The number 8, for example,  might  be  stored  as 
00001000. Every one of those digits is a bit (bit = Binary digIT: 0 or 1), and 
the  sequence of zeros and ones creates a pattern of bits. A logical  operator 
lines up the bit pattern of one binary value with the bit pattern of another:

        00010000
        01010101

If  then  tests  each column of ones and zeros. The ones  and  zeros  are  not 
important  as numbers; rather, 1 stands for true and 0 stands for  false.  The 
operator compares the columns to find whether each combination of bits  yields 
a true or false bit. As a result, a new bit pattern emerges.

An operator tests these bit patterns according to its truth table. There is  a 
truth table for each of the 6 logical operators. Truth tables are charts  that 
predict  whether a given combination of 0s and 1s, or trues and falses, has  a 
true or a false value. The new bit pattern is made up of ones and zeros. If it 
is all zeros, the truth value of the new pattern is false (0). If it  contains 
a one or ones, its truth value is true (1).

Notice  that the truth values that logical operators return do not  correspond 
to  the  conventional  symbols for true (-1) and  false  (0)  that  relational 
operators  return  (see Section 3.1.2). Logical operators return  1  for  true 
because they work with bits to form new combination of bits. A single bit  can 
never have any other value than one or zero, meaning on or off, true or false. 
The truth value of a new bit is one or zero, and the truth value of a new  bit 
pattern is one or zero.

Here  is an example of a logical operation using the OR operator to compare  2 
bit patterns. The truth table for OR is:

         OR│ X   Y   X OR Y
           ├───────────────
           │ 0   0     0
           │ 0   1     1
           │ 1   0     1
           │ 1   1     1

We make the following comparison:

        0 1 0 0 0 0 0 1  (bit pattern)
       OR                (logical operator)
        0 0 0 0 0 0 0 1  (bit pattern)

Starting  from the left column, compare the first bit of one pattern with  the 
first  bit of the other. According to the truth table of the logical  operator 
OR, 0 OR 0 = 0. The first bit of the new bit pattern is zero.

In  the second position, we have 1 and 0. The OR truth table indicates that  1 
OR 0 equals 1. Therefore, the second bit of the pattern that results from this 
operation is a 1.

In the third through seventh positions, both the first and second bit patterns 
have  zeros. Because 0 OR 0 equals 0, the new pattern also contains  zeros  in 
the third through seventh positions.

There  are 1s in the last place of both bit patterns. Looking at the OR  truth 
table, 1 OR 1 = 1.

The entire operation looks like this:

        0   1   0   0   0   0   0   1
       OR  OR  OR  OR  OR  OR  OR  OR
        0   0   0   0   0   0   0   1
        ──  ──  ──  ──  ──  ──  ──  ──
        0   1   0   0   0   0   0   1

The resulting bit pattern, because it contains 1s, has a value of true.

Notice that the new bit pattern is the same as the first bit pattern. You  can 
read  these  patterns as binary digits or control characters or  ASCII  codes, 
depending  upon context. But, for the purpose of logical operations, they  are 
no  more than bit patterns. The important thing is whether their truth  values 
are true or false.

Logical operations are useful decision-making tools. They control program flow 
and structure, and make assignments:

        Ok 120 IF A OR B THEN X = Y
        Ok 130 IF NOT A THEN GOTO 50

Logical  operators  look more like words than mathematical symbols.  But  they 
operate just as any other mathematical symbol. Although the truth tables use 1 
and 0, they are easier to read if you mentally substitute true and false.  For 
example:

        NOT│ X        NOT X
           ├───────────────
           │ false    true
           │ true     false

The NOT operator asserts that, if X is false, then NOT X is true; and, if X is 
true, then NOT X must be false.

Here are the logical operators and their truth tables. In these tables, X  and 
Y are not bit patterns. They are single bits. Logical operators always compare 
bit X with bit Y, one column at a time.

        NOT│ X        NOT X
           ├───────────────
           │ 0          1
           │ 1          0

        AND│ X   Y  X AND Y
           ├───────────────
           │ 0   0     0
           │ 0   1     0
           │ 1   0     0
           │ 1   1     1

         OR│ X   Y   X OR Y
           ├───────────────
           │ 0   0     0
           │ 0   1     1
           │ 1   0     1
           │ 1   1     1

        XOR│ X   Y  X XOR Y
           ├───────────────
           │ 0   0     0
           │ 0   1     1
           │ 1   0     1
           │ 1   1     0

        IMP│ X   Y  X IMP Y
           ├───────────────
           │ 0   0     1
           │ 0   1     1
           │ 1   0     0
           │ 1   1     1

        EQV│ X   Y  X EQV Y
           ├───────────────
           │ 0   0     1
           │ 0   1     0
           │ 1   0     0
           │ 1   1     1

        Figure 3-1. Logical operation truth tables

In the preceding figure, the following is true:

      - The NOT operator is simple contradiction: if X is not true, then it is 
        false.

      - The AND operator is true if both X and Y are true.

      - The OR operator is true if either X or Y is true.

      - XOR  is  the exclusive OR. XOR results in true when either X or  Y  is 
        true, but not both.

      - IMP  is the abbreviation for implies. IMP treats X as a premise and  Y 
        as a conclusion. Logically, it is impossible for true premises to lead 
        to  a  false  conclusion.  You can have  false  premises  and  a  true 
        conclusion,  false premises and a false conclusion, or  true  premises 
        and  a true conclusion. For this reason, IMP is true except where  the 
        premise is true and the conclusion is false.

      - EQV stands for equivalent. It is true when X and Y are the same.


3.1.4 Numeric functions
-----------------------

The  numeric functions in Table 3-3 are built into Personal BASIC. You do  not 
have  to write your own functions to make these computations. You can use  the 
functions anywhere a numeric operator is used in an expression.

Table 3-3. Numeric functions

        Func.   Explanation
        -----   -----------
        ABS     Returns the absolute value of a number
        ATN     Returns the arctangent of a number in radians
        COS     Returns the cosine of a number in radians
        EXP     Returns e to the power of a given value
        LOG     Returns the natural logarithm of a number
        LOG10   Returns the base-10 logarithm of a number
        RND     Generates a sequence of random numbers
        SIN     Returns the sine of a number in radians
        SQR     Returns the square root of a number
        TAN     Returns the tangent of a number in radians


3.1.5 Order of execution
------------------------

Numeric  expressions  can  contain a combination  of  arithmetic,  relational, 
logical, and functional operators, or only one operator. For expressions  with 
more  than  one  operator, Table 3-4 gives the order in  which  they  execute. 
Expressions  are evaluated from left to right. If two operators have the  same 
precedence, the one on the left is evaluated first.

Table 3-4. Order of execution for operators

        Operator        Explanation
        --------        -----------
          (  )          Items in parentheses have highest priority
           ^            Exponentiation
           -            Negation
          *, /          Multiplication, floating-point division
           \            Integer division
          MOD           Modulus
          +, -          Addition, subtraction
          =, <>         Relational operators
          <, >
         <=, >=
        NOT, AND        Logical operators, in order given
        OR,  XOR
        IMP, EQV


3.2 String expressions
----------------------

The  second  class of expressions in Personal BASIC is string  expressions.  A 
string expression consists of one or more strings or string variables and  one 
or more string operators. You can write string expressions to modify  strings, 
compare  them, convert between strings and numbers, and manipulate strings  in 
programs and files.


3.2.1 String concatenation
--------------------------

To  concatenate  means  to connect in a  series;  string  concatenation  means 
linking  two  or  more  strings  to  form  a  new  string.  The  operator  for 
concatenation is the plus sign [+]. Notice that + does not work for strings as 
it  does  for numbers: it does not add. Concatenating five +  five  gives  you 
fivefive, not ten or 10. The syntax for concatenation is:

        (string 1) + (string 2) = (new string 1 + 2)

The following program concatenate 3 strings, using their variable names:

        Ok 10 X$ = "TO
        Ok 20 Y$ = "GET"
        Ok 30 Z$ = "HER"
        Ok 40 A$ = X$ + Y$ + Z$
        Ok 50 PRINT A$
        Ok RUN
        TOGETHER

The example forms a new string by concatenating string variable names. You can 
also   concatenate  string  constants  directly,  or  combine  constants   and 
variables:

        Ok 10 Z$ = "look "
        Ok 20 X$ = Z$ + "at " + "me " + "now!"
        Ok 30 PRINT X$
        Ok RUN
        look at me now!


3.2.2 String comparisons
------------------------

You  can  compare  one  string to another  or  alphabetize  strings  with  the 
relational operators =, <>, <, >, <=, and >=. Personal BASIC reads the strings 
and  compares their ASCII values character by character, up to the end of  the 
string. As in the alphabet, a < b < c, and the lower value precedes the higher 
value.  See the ASCII value table in Appendix B. Notice that the ASCII  values 
for upper- and lower-case are different.

If one string is longer than another, but they are otherwise identical (at and 
ate,  for example), the longer string is greater. Because ate is greater  than 
at, and attenuate is greater than ate, their order is:

        at
        ate
        attenuate

Remember  that  blanks are characters. If a string has a trailing  blank,  its 
value  increases  because it is longer. If it has a leading blank,  its  value 
decreases,  because blanks have the smallest ASCII value of all the  printable 
characters.

          "A" < "B"     (A's ASCII value is 65; B's is 66.)

        "A  " > "A"     (A  trailing blank makes "A " longer and greater  than 
                        "A".)

        "Dog" < "Dot"   (These  are  alike  until  the  last  character.  But, 
                        because t > g, dot > dog.)

        "yes" = "yes"   (These are identical.)

You  can  use  string  comparisons for controlling program  flow,  as  in  the 
following example:

        Ok 100 INPUT "Are you calling heads or tails"; C$
        Ok 110 IF C$ = "heads" THEN GOTO 160
        Ok 120 IF C$ = "tails" THEN GOTO 170 ELSE GOTO 90


3.2.3 String functions
----------------------

With  Personal  BASIC string functions, you can find strings  within  strings, 
convert numbers to strings, and pad lines with spaces. Personal BASIC provides 
the string functions listed in Table 3-5. You can use these functions anywhere 
you  use a string operator. See Section 5 for more detailed  explanations  and 
examples.

Table 3-5. String functions

        Func.   Explanation
        -----   -----------
        INSTR   Finds  the  first  occurrence  of  a  particular  sequence  of 
                characters within a string, and returns its position.
        LEFT$   Returns the leftmost characters in a string.
        LEN     Returns the number of characters in a string.
        MID$    Extracts a string from within a string, beginning at  whatever 
                point you specify.
        RIGHT$  Returns the rightmost characters in a string.
        SPACE$  Returns a string of spaces.
        STR$    Converts a number to a string.
        STRING$ Returns a string of a given length.


Section 4: Input and output
---------------------------

Input and output refers to the passing of data between the various  components 
that  make  up your microcomputer system. For example, data can  pass  from  a 
program  to  the screen for display or to a disk drive for  storage.  Personal 
BASIC  provides  a  variety  of  statements  and  functions  to  control   the 
interaction between programs, consoles, printers, and disk drives.


4.1 Console input
-----------------

Console  input  is  data that you enter into a program while  the  program  is 
running. The following Personal BASIC statements let you enter data from  your 
console.  See  Section  5  for detailed  explanations  and  examples  of  each 
statement.

      - The  INPUT statements asks you to enter data from the keyboard  during 
        program  execution.  INPUT  assigns the data to a  string  or  numeric 
        variable.

      - The  LINE  INPUT  statement reads one entire line  of  data  from  the 
        keyboard, ignoring commas [,] and other delimiters. LINE INPUT assigns 
        the data to a string variable.


4.2 Printing
------------

To print with Personal BASIC means to send data to a screen, line printer,  or 
disk file. Your program can print information on the screen or on paper, using 
a  printer. You can write a program that sends the information to a disk  file 
for storage. The PRINT statement is the main data output statement in Personal 
BASIC. PRINT sends data from a program to the screen. Variations of PRINT  let 
you send data to other destinations or tailor your print formats for different 
kinds of data.

The  statements in Table 4-1 and the functions in Table 4-2 control  printing. 
See Section 5 for details and examples of each statement and function.

Table 4-1. Print statements

        Statement       Explanation
        ---------       -----------
        LPRINT          Directs program output to the printer.
        LPRINT USING    Lets  you specify a special format for program  output 
                        directed to the printer.
        PRINT           Directs program output to the screen.
        PRINT USING     Lets  you specify a special format for program  output 
                        directed to the screen.
        WRITE           Similar to PRINT. WRITE directs program output to  the 
                        screen  but  inserts commas [,] between the  items  as 
                        they display and delimits strings with quotation marks 
                        ["].

Table 4-2. Print functions

        Func.   Explanation
        -----   -----------
        LPOS    Returns  the  current position of the print  head  within  the 
                printer buffer.
        POS     Returns the current cursor column position on the console.
        SPC     Moves  the cursor a specified number of spaces on a line.  Use 
                SPC with PRINT, LPRINT, or PRINT#.
        TAB     Moves  the cursor to a specified column number on a line.  Use 
                TAB with PRINT or LPRINT.


4.2.1 Formatted printing
------------------------

The PRINT USING statement lets you specify special formats for program output. 
There  are 2 variations of the PRINT USING statement: LPRINT USING and  PRINT# 
USING. Each statement specifies a different destination for formatted output.

      - The PRINT USING statement sends formatted data to the console.

      - The  PRINT# USING statement sends formatted data to a  specified  disk 
        file.

      - The LPRINT USING statement sends formatted data to the printer.

The  syntax of the LPRINT USING and PRINT# USING statements differs  slightly. 
See Section 5 for the syntaxes of all PRINT statements. Write the PRINT  USING 
statement with the following syntax:

        PRINT USING (format string); (expression list)

The  following figure gives a literal example of a PRINT USING statement,  and 
points out the syntax elements.

        Ok 10 PRINT USING BLOCKFORMAT$;NAME$,AGE%,ADDRESS$
              └────┬────┘ └─────┬─────┘└────────┬────────┘
               STATEMENT  FORMAT STRING  EXPRESSION LIST

        Figure 4-1. PRINT USING syntax

The  expression list consists of the string or numeric expressions  to  format 
and print. You can use commas [,] or semicolons [;] to separate expressions in 
the  list.  The format string is a model or image of the  output.  The  format 
string  can  be  a  string  constant or  variable  that  consists  of  special 
formatting  characters  and  literal  characters.  The  formatting  characters 
determine  fields  of  data for the printed strings or  numbers.  A  formatted 
printing statement contains only one format string, but can format any  number 
of  expressions.  The following example shows how  the  formatting  characters 
relate to the actual output.

        Ok 10 A$ = "DAVID"                      Expressions
        Ok 20 B$ = "ALAN"
        Ok 30 C$ = "JONES"
        Ok 40 N = 1500
        Ok 50 FMAT$ = "!. !. &  $####.##"       Format string
        Ok 60 PRINT USING FMAT$; A$, B$, C$, N  Format statement
        Ok RUN
        D. A. JONES  $1500.00                   Output

The format string in the preceding example defines 4 fields of data: 3  string 
and  1  numeric. Each field corresponds to an appropriate expression.  If  you 
specify more fields in the format string than expressions, PRINT USING ignores 
the  additional  fields. If you specify more expressions than  fields  in  the 
format  string,  PRINT  USING  re-uses the format string  to  format  all  the 
expressions. The format types must be equal to the expression types.


4.2.2 String field formatting characters
----------------------------------------

Exclamation point

An exclamation point [!] tells the statement to print only the first character 
from each specified string.

        Ok 10 A$ = "TESTING"
        Ok 20 B$ = "Personal BASIC"
        Ok 30 PRINT USING "!";A$,B$
        Ok RUN
        TP


Spaces

The  number of characters or spaces that you place between the  2  backslashes 
[\]  plus  2 indicates the number of characters to print  from  the  specified 
string.  If  you  place no characters or spaces  between  the  backslashes,  2 
characters  are  printed.  If you place one character  or  space  between  the 
backslashes,  3 characters are printed. If the number of characters or  spaces 
plus 2 is less than the number of characters to output, the statement  ignores 
the extra characters. If the number of characters or spaces plus 2 is  greater 
than  the  number of characters to output, the string  is  left-justified  and 
padded on the right with spaces.

You can use periods [.] and numbers between the backslashes to easily see  how 
many characters are in your printing field. For example, this field:

        \...5....0...4\

is 15 characters long.

        Ok 10 A$ = "TESTING"
        Ok 20 B$ = "Personal BASIC"
        Ok 30 PRINT USING "\     \";A$;B$
        Ok 40 PRINT USING "\      \";A$;B$;"!"
        Ok RUN
        TESTINGPersonal BASIC
        TESTING Personal BASIC  !


Ampersand

An  ampersand  [&]  specifies a variable-length string  field.  The  statement 
prints the string exactly as entered.

        Ok 10 A$ = "TESTING"
        Ok 20 B$ = " Personal BASIC"
        Ok 30 PRINT USING "&";A$,B$
        Ok RUN
        TESTING Personal BASIC


4.2.3 Numeric field formatting characters
-----------------------------------------

Pound sign

A  pound  sign  [#] represents each digit position in  a  numeric  field.  The 
statement  fills  all  digit positions. If the number has  fewer  digits  than 
positions specified in the format string, the number is right-justified in the 
field.

        Ok PRINT USING "######";1024
         1024


Decimal point

You can insert a decimal point [.] at any position in the field. The statement 
inserts  a zero to fill digit positions, and rounds numbers as  necessary.  In 
the  following example, the 2 spaces inserted at the end of the format  string 
separate the printed numbers on the line.

        Ok 10 X = 765.432 : Y = 234.5
        Ok 20 Z = .765
        Ok 30 PRINT USING "###.##  ";X;Y;Z
        Ok RUN
        765.43  234.50    0.77


Plus sign

A  plus sign [+] at the beginning of the format string tells the statement  to 
print  the  sign  of the number, plus [+] or minus  [-],  before  the  printed 
number.  If  you  place the plus sign at the end of  the  format  string,  the 
statement prints the sign after the printed number.

        Ok 10 X = 765.432 : Y = -234.5
        Ok 20 Z = -.765 : W = 87.9
        Ok 30 PRINT USING "+###.##  ";X;Y;Z;W
        Ok RUN
        +765.43  -234.50    -0.77   +87.90


Minus sign

A minus sign [-] at the end of the format string tells the statement to  print 
negative numbers with a trailing minus sign.

        Ok PRINT USING "##.##-  ";-.765;87.9
        0.77-  87.90


Asterisk

A  double  asterisk  [**]  at the beginning of the  format  string  tells  the 
statement  to  fill leading spaces in the numeric field  with  asterisks.  The 
double asterisk reserves positions for 2 more digits.

        Ok 10 X = 765.43
        Ok 20 Y = -0.765 : Z = 2345.9
        Ok 30 PRINT USING "**##.#  ";X;Y;Z
        Ok RUN
        *765.4  **-0.8  2345.9


Dollar sign

A  double dollar sign [$$] tells the statement to insert a dollar sign to  the 
immediate  left of the printed number. The double dollar sign reserves 2  more 
digit positions. One position is for the printed dollar sign. You can use  the 
double dollar sign with negative numbers only if the minus sign [-] trails  to 
the right. You cannot use exponential format with the double dollar sign.

        Ok PRINT USING "$$###.##";765.486
         $765.49


Asterisks and dollar signs

A double asterisk and dollar sign [**$] at the beginning of the format  string 
tells the statement to fill leading spaces with asterisks and insert a  dollar 
sign  to  the  immediate left of the number. The **$  reserves  3  more  digit 
positions. One position is for the printed dollar sign.

        Ok PRINT USING "**$##.##  ";765.486;3.04
        *$765.49  ***$3.04


Comma

A  comma [,] placed to the left of the decimal point [.] in the format  string 
tells the statement to insert a comma between every 3rd digit on the left side 
of the decimal point in the printed number. The comma reserves one more  digit 
position.  A  comma  at the end of the format string prints  as  part  of  the 
string.

        Ok 10 X = 5432.1
        Ok 20 PRINT USING "####,.##";X
        Ok 30 PRINT USING "####.##,";X
        Ok RUN
         5,432.10
         5432.10,


Carets

Four carets [^^^^] following the digit position characters specify exponential 
format. The 4 carets reserve space for the characters E+nn. See Section  2.1.1 
for  information on Personal BASIC exponential notation. The position  of  the 
decimal  point  [.]  in  the format  string  determines  the  exponent  value. 
Significant  digits are left-justified. One digit position is reserved on  the 
left  of the printed number for the sign. The statement prints a blank on  the 
left  if the number is positive, and a minus sign [-] if negative, unless  you 
specify a leading + or trailing + or - in the format string.

Any number of carets following a numeric specification in a PRINT USING string 
will  cause  the  number to be printed in exponential form.  If  you  wish  to 
specify  that  a  caret [^] is to print immediately after a  number,  use  the 
literalising character [_] before the first caret. For example:

     PRINT USING "###.##_^"; 79.5

prints as 79.50^.

        Ok PRINT USING "##.##^^^^  ";-100.00;.0036
        -1.00E+02   3.60E-03
        Ok PRINT USING "+##.##^^^^  ";-100.00;.0036
        -10.00E+01  +36.00E-04
        Ok PRINT USING "####.##^^^^  ";100.00;.0036
        100.00E+00  360.00E-05
        Ok PRINT USING ".###^^^^-  ";100.00;.0036
        .100E+03   .360E-02-


Underscore

An  underscore [_] in the format string tells the statement to print the  next 
character  as a literal character. Place 2 adjacent underscores in the  format 
string to print one underscore as a literal character.

        Ok PRINT USING "_#####_!";1024
        #1024!


Percent sign

The statement places a percent sign [%] in front of the printed number if  the 
number has more digits than the numeric format string. If rounding causes  the 
printed  number  to  exceed  the field specified in  the  format  string,  the 
statement places a percent sign in front of the printed number. The number  of 
digits specified in the format string cannot exceed 24.

        Ok PRINT USING "##.##";333.42
        %333.42
        Ok PRINT USING ".###";.9999
        %1.000

You  can  include  string  constants in the format string,  as  shown  in  the 
following example:

        Ok PRINT USING "THIS IS FILE _##";4
        THIS IS FILE #4


4.3 Disk files
--------------

The  operating system organizes information into files on the  disk.  Personal 
BASIC  supports a number of statements and functions that interface with  your 
operating  system, enabling you to save your Personal BASIC programs and  data 
in  disk files for later use. Personal BASIC supports 2 types of  disk  files: 
sequential  files  and  random  files. You  identify  files  by  filename  and 
filetype.


4.3.1 File specification
------------------------

Each  Personal BASIC file must have a unique file specification, or  filespec, 
that conform to standard Digital Research filespec format. A standard filespec 
consists of 3 parts: a drive specifier, a filename, and a filetype. The  drive 
specifier  and  the  filetype  are optional. The  following  are  examples  of 
Personal BASIC filespecs:

        - B:ACCOUNTS.BAS
        - TOTAL.FEB
        - CLIENTS

The  drive specifier, or drivespec, identifies which disk drive has the  file. 
The  drivespec can be any letter from A to P that corresponds to  any  logical 
disk  drive.  Place  a  colon [:] after the drive  letter.  If  you  omit  the 
drivespec, Personal BASIC assumes that the file is on the default drive.

The  filename  can contain 1 to 8 characters. It cannot contain  blanks  [  ], 
periods  [.],  or  colons  [:]. It is good policy  to  choose  filenames  that 
indicate  what  the  file  contains. For examples,  the  filename  CLIENTS  is 
appropriate  for  a  file containing information about  clients.  ACCOUNTS  is 
appropriate for a file that contains an accounts-receivable program.

The  filetype can contain up to 3 characters. Separate the filename  from  the 
filetype with a period [.]. Use filetypes to identify groups of similar files. 
For example, the filetype BAS identifies a file as a BASIC program. A filetype 
of FEB could identify a group of files that contain all your business data for 
February,  such  as SALES.FEB, CLIENTS.FEB, or PROFITS.FEB.  The  filetype  is 
optional.


4.3.2 Sequential files
----------------------

Sequential files organize data in a continuous stream. Data items written to a 
sequential  file  using PRINT#, PRINT# USING or WRITE# statements  are  stored 
sequentially,  one item after another. When you access data from a  sequential 
file using INPUT# or LINE INPUT# statements, the data items are read from  the 
file  in the same sequential order as they were stored. All items in the  file 
are  read  from  the first item to the last. Sequential files  are  easier  to 
create than random files, but are not as flexible when accessing the data.

Personal BASIC supports the statements in Table 4-3 and functions in Table 4-4 
for  use with sequential files. See Section 5 for more  detailed  explanations 
and examples.

Table 4-3. Sequential file statements

        Statement       Explanation
        ---------       -----------
        CLOSE           Concludes input and output to a file.
        INPUT#          Reads  data items from a sequential file, and  assigns 
                        them to program variables.
        LINE INPUT#     Reads  one line of data from a sequential file into  a 
                        string variable. LINE INPUT# ignores delimiters.
        OPEN            Lets you read and write to a file.
        PRINT#          Writes data sequentially to a file. PRINT# writes  the 
                        data  uncompressed,  exactly as is. You  must  delimit 
                        data fields.
        PRINT# USING    Writes formatted data sequentially to a file.
        WRITE#          Writes  data  sequentially to a file.  WRITE#  inserts 
                        commas  [,] between data items, and  delimits  strings 
                        with quotation marks ["].


Table 4-4. Sequential file functions

        Func.   Explanation
        -----   -----------
        LOC     Returns  the  number of records read from, or  written  to,  a 
                sequential  file.  LOC indicates the current position  in  the 
                file.
        LOF     Returns  the number of 128-byte segments in a file  while  the 
                file is open.
        EOF     Indicates  an end-of-file condition. EOF returns true (-1)  if 
                the  end  of  a given file has been  reached,  and  false  (0) 
                otherwise.

The  following 4 steps outline the procedure used to create a sequential  file 
and access the data in the file:

     1) OPEN the file to output data (O mode) from your program.

     2) Output  data  to the file using the PRINT#, PRINT#  USING,  or  WRITE# 
        statements.

     3) CLOSE the file, then OPEN it to input data to your program.

     4) Read the data from the new sequential file into your program using the 
        INPUT#, or LINE INPUT# statements.

In  many  cases, more than one program must access the data  in  a  sequential 
file.  Therefore,  the  program  that creates the  sequential  file,  and  the 
programs  that  access  the data in the file, can be  separate  programs.  For 
example, you can have one program that creates a new file upon each execution, 
and  several  programs that use the data in the file. Alternatively,  you  can 
have one large program that performs a variety of tasks.

The  following example program creates a sequential file named  BUSINESS  that 
lets  you  store  some simple business information. Try the  program  on  your 
computer and enter some hypothetical data to see how a sequential file works.

        Ok 5 REM - CREATE SEQUENTIAL BUSINESS INFO FILE
        Ok 10 OPEN "O", #1, "BUSINESS"
        Ok 20 PRINT "TO END THIS PROGRAM... TYPE ""DONE""."
        Ok 30 INPUT "PLEASE ENTER DATE... MO/DA/YR"; DATE$
        Ok 40 IF DATE$ = "DONE" THEN GOTO 80
        Ok 50 INPUT "PLEASE ENTER TOTAL SALES..."; AMT
        Ok 60 WRITE#1, DATE$, AMT
        Ok 70 PRINT: GOTO 20
        Ok 80 PRINT "FINISHED... THANK YOU!"
        Ok 90 END

        Listing 4-1. Program creating a sequential file

The  first time that you RUN the program, it creates a sequential  file  named 
BUSINESS.  If you RUN the program again, it erases the existing BUSINESS  file 
and creates a new one.

Any number of programs can use the data in the BUSINESS file. For example, you 
can  write a program that lists the daily sales totals for each day in  April. 
You can write another program that calculates sales by month, and displays the 
totals  in a table. You can write one large program that performs both  tasks. 
The  following example program uses the data in the BUSINESS file  to  display 
the dates on which total sales exceeded $1,500.

        Ok 5 REM - DISPLAY DATES WHEN SALES TOPPED $1500
        Ok 10 OPEN "I", #1, "BUSINESS"
        Ok 20 WHILE NOT EOF(1)
        Ok 30 INPUT#1, DATE$, AMT
        Ok 40 IF AMT > 1500.00 THEN PRINT DATE$
        Ok 50 WEND
        Ok 60 END

        Listing 4-2. Sample sequential file program

This program searches all the data in the BUSINESS file from beginning to end. 
Notice that line 20 searches BUSINESS for the end-of-file marker, enabling the 
program to conclude properly. Personal BASIC reports an error message if there 
is no end-of-file search during a sequential file access.


4.3.3 Random files
------------------

Random  files organize data into records. Records cannot exceed  4,096  bytes. 
Within a record, data is organized like a small sequential file.

Random  files  have advantages over sequential files,  although  random  files 
require  a  few  more programming steps to create  and  access.  Random  files 
usually  store  numbers in binary format. Sequential files  store  numbers  in 
ASCII  format. Usually, random files require less disk space  than  sequential 
files.

The  most  significant advantage to random files is random  access.  In  other 
words,  you  can  access any record in a file by assigned number.  It  is  not 
necessary  to  read  through  all  the data from  beginning  to  end  as  with 
sequential files. The PUT statement, used within the program that creates  the 
random file, assigns a record number automatically, beginning with the  number 
1.  Or, you can specify a record number in the PUT statement.  Record  numbers 
can range from 1 to 32767.

(ROCHE>  Hum... 32767 records of 4,096 bytes = 134,213,632 bytes.  Divided  by 
1,024 bytes (1 kilobyte) = 131,068 kilobytes. Divided again by 1,024 =  127.99 
megabytes...  Curious! I don't recognize the 8 megabyte limit of CP/M  2.2  or 
the 32 megabyte limit of CP/M Plus? And Personal BASIC was only available,  in 
1983, under CP/M-86, the 8086 version of CP/M 2.2...)

Personal BASIC supports the statements in Table 4-5 and functions in Table 4-6 
for  use  with random files. See Section 5 for more detailed  information  and 
examples.

Table 4-5. Random file statements

        Statement       Explanation
        ---------       -----------
        CLOSE           Concludes input and output to a specified disk file.
        FIELD           Allocates  space in a random file buffer,  enabling  a 
                        program  to  write data to a random  file.  The  FIELD 
                        statement specifies the size of the data fields within 
                        a record.
        GET             Reads  a record from a random file into a random  file 
                        buffer.
        LSET            Assigns data to the string variables in a random  file 
                        buffer,  and  left-justifies the data  in  its  proper 
                        field.
        OPEN            Lets you read and write to a file.
        PUT             Writes a record from a random file buffer to a  random 
                        file.  You  can specify the record number in  the  PUT 
                        statement.
        RSET            Assigns data to the string variables in a random  file 
                        buffer,  and  right-justifies the data in  its  proper 
                        field.


Table 4-6. Random access functions

        Func.   Explanation
        -----   -----------
        CVI     Converts  a  2-byte  string to an  integer,  enabling  integer 
                values to be read from a random file buffer.
        CVD     Converts  an 8-byte string to a double-precision real  number, 
                enabling double-precision real values to be read from a random 
                file buffer.
        CVS     Converts  a 4-byte string to a single-precision  real  number, 
                enabling  single-precision  real  numbers to be  read  from  a 
                random file buffer.
        LOC     Returns  the record number of the last record read or  written 
                to a random file.
        MKD$    Converts  a double-precision real number to an 8-byte  string, 
                enabling double-precision real values to be placed in a random 
                file buffer.
        MKI$    Converts  an  integer  to a 2-byte  string,  enabling  integer 
                values to be placed in a random file buffer.
        MKS$    Converts  a single-precision real number to a  4-byte  string, 
                enabling  single-precision  real  numbers to be  placed  in  a 
                random file buffer.

Take the following 4 steps to create a random file:

     1) OPEN the file for random access (R mode).

     2) Specify  the size of the data fields in the random file buffer,  using 
        the FIELD statement.

     3) Use the LSET or RSET statements to read data from the program into the 
        random  file  buffer. Convert numeric values into strings,  using  the 
        MKI$, MKS$, and MKD$ functions.

     4) Write the data from the buffer to the disk, using the PUT statement.

As  with  sequential  files, more than one program can access the  data  in  a 
random  file.  Therefore,  the program that creates the random  file  and  the 
programs  that  access  the data in the file can  be  separate  programs.  The 
following  example program creates a random file named EMPLOYEE that lets  you 
store simple employee personnel information. Try the program on your  computer 
and enter some hypothetical information to see how a random file works. Notice 
that the employee number also serves as the record number.

        Ok 5 REM - CREATE A RANDOM PERSONNEL FILE
        Ok 100 OPEN ""R", #2, "EMPLOYEE", 45
        Ok 110 FIELD #2, 25 AS N$, 12 AS J$, 8 AS D$
        Ok 120 INPUT "ENTER EMPLOYEE NUMBER... ENTER 0 TO STOP"; NUM%
        Ok 130 IF NUM% = 0 THEN GOTO 220
        Ok 140 INPUT "ENTER EMPLOYEE NAME..."; NAME$
        Ok 150 INPUT "ENTER EMPLOYEE JOB TITLE..."; JOB$
        Ok 160 INPUT "ENTER DATE HIRED... MO/DA/YR"; DATE$
        Ok 170 LSET N$ = NAME$
        Ok 180 LSET J$ = JOB$
        Ok 190 LSET D$ = DATE$
        Ok 200 PUT #2, NUM%
        Ok 210 PRINT : GOTO 120
        Ok 220 PRINT "FINISHED... THANK YOU!"
        Ok 230 END

        Listing 4-3. Random file program

The  first time that you execute the program, it creates a random  file  named 
EMPLOYEE.  If you RUN the program again, it erases the existing EMPLOYEE  file 
and creates a new one. However, if you want to save the data in the file after 
the  first execution and add to it, you can write a new program or modify  the 
preceding  program,  enabling you to append data. You can change line  100  to 
OPEN  the EMPLOYEE file in the append mode. Then, run the program to  add  new 
information to the file.

Notice that line 210 causes the program to loop continuously to line 120.  The 
program  does not end until you instruct it to. Line 120 asks you to  enter  a 
zero  in response to the INPUT statement if you want to end the program.  Line 
130  checks  for the zero. If you enter a zero, the program branches  to  line 
220, ending the program.

Like sequential files, any number of programs can access the data in a  random 
file. You access data in a random file as follows:

     1) OPEN the file for random access (R mode).

     2) Specify  the size of the data fields in the random file buffer,  using 
        the FIELD statement.

     3) Use  the GET statement to read a specified record from the  file  into 
        the random file buffer.

     4) The record in the buffer is available to the program. Convert  numeric 
        string  values  back  into  numbers,  using  the  CVI,  CVS,  and  CVD 
        functions.

The following example program lets you access any data record in the  EMPLOYEE 
file. When you enter an employee number, the program returns a list of all the 
personnel information contained in the random file pertaining to the employee. 
The employee number also serves as the record number.

        Ok 5 REM - DISPLAY PERSONNEL INFORMATION
        Ok 500 OPEN "R", #2, "EMPLOYEE", 45
        Ok 510 FIELD #2, 25 AS N$, 12 AS J$, 8 AS D%
        Ok 520 INPUT "ENTER EMPLOYEE NUMBER... ENTER 0 TO STOP"; NUM%
        Ok 530 IF NUM% = 0 THEN GOTO 610
        Ok 540 GET #2, NUM%
        Ok 550 ON ERROR GOTO 600
        Ok 560 PRINT "EMPLOYEE NUMBER - "; NUM% : PRINT
        Ok 570 PRINT N$, J$ : PRINT
        Ok 580 PRINT "DATE HIRED - "; D$
        Ok 590 GOTO 520
        Ok 600 PRINT "UNASSIGNED EMPLOYEE NUMBER." : PRINT : GOTO 520
        Ok 610 PRINT "FINISHED... THANK YOU!"
        Ok 620 END

        Listing 4-4. Sample program accessing random file data

If you enter an employee number that does not exist as a record number in  the 
EMPLOYEE file, Personal BASIC displays an error message and ends the  program, 
unless you write an ON ERROR statement. See the ON ERROR statement in  Section 
5. The ON ERROR statement in line 550 traps such errors, and sends control  to 
line 600. Line 600 prints a message telling you of the invalid employee number 
and branches to line 520, so you can enter another number.


Section 5: Commands, statements, and functions
----------------------------------------------

This section describes the Personal BASIC commands, functions, and statements, 
in  alphabetical  order.  The syntax formats in this section  conform  to  the 
following typographical conventions:

      - Words in single quotation marks ['] describe the kind of data that you 
        must  insert in their places. They are self-explanatory. For  example, 
        'variable'  means that, when you are writing a statement, you write  a 
        variable in 'variable's place.

      - Items  enclosed  in square brackets, [ ], are optional and  cannot  be 
        repeated.

      - Items  enclosed  in  curly braces, { }, are  optional  and  cannot  be 
        repeated.

      - Words in uppercase are Personal BASIC keywords.


ABS Function


The ABS function returns the absolute value of a number.


Syntax:

        X = ABS ('numeric expression')


Explanation:

The  absolute  value  of a number is always positive or zero.  ABS  returns  a 
number in the same form as its argument.

ABS  returns  an integer value for integers. For real  numbers,  the  returned 
value has the same precision as the argument. You can change the precision  or 
type of the number by assignment in the usual way (see Section 2.2.2).


Example:

        Ok 10 I% = ABS(-9)
        Ok 20 PRINT I%
        Ok 30 X! = ABS(325556.244)
        Ok 40 PRINT X!
        Ok 50 Y# = ABS(-289878787.98992)
        Ok 60 PRINT Y#
        Ok 70 END
        Ok RUN
         9
         325556
         289878787.98992


ASC Function

The ASC function returns the ASCII value of the first character in a string.


Syntax:

        I% = ASC ('string expression')


Explanation:

ASC returns an integer between 0 and 255. The string must contain at least one 
character.  If the string expression is a null string, error number  5  occurs 
(see Appendix D for error messages).

The  CHR$ function is the inverse of ASC. See Appendix B for a list  of  ASCII 
characters and corresponding numeric values.


Example:

        Ok 10 A$ = "Murphy, James"
        Ok 20 PRINT ASC(A$)
        Ok RUN
         77


ATN Function

The ATN function returns the arctangent of a number.


Syntax:

        X! = ATN('numeric expression')


Explanation:

The  ATN  function returns a single-precision real number. The  number  is  an 
angle  in  radians  that ranges from -PI/2 to PI/2. The TAN  function  is  the 
inverse of ATN.


Example:

        Ok 10 RADIANS! = ATN(0.99999)
        Ok 20 PRINT "The angle in radians is ";RADIANS!
        Ok 30 PRINT
        Ok 40 PI = 3.14159
        Ok 50 DEGREES = RADIANS! * 180/PI
        Ok 60 PRINT "The angle in degrees is ";CINT(DEGREES)
        Ok RUN
        The angle in radians is 0.78540

        The angle in degrees is 45


AUTO Command

The  AUTO  command generates a line number automatically each  time  that  you 
press the Carriage Return [CR] key. Ctrl-C turns AUTO off.


Syntax:

        AUTO ['starting line number'] [,'increment']


Explanation:

You  can  specify the starting line number and an increment  value  after  the 
keyword  AUTO.  The increment value is a number added to each line  number  to 
generate the next line number.

You  can omit the starting line number or the increment, or both. If you  omit 
the  starting  line number, Personal BASIC starts numbering at  10.  You  must 
write  a comma [,] before the increment number, in place of the starting  line 
number.

If  you  omit  the increment, Personal BASIC uses the increment  of  the  most 
recent AUTO command, or 10 if no other AUTO command.

Personal  BASIC prints an asterisk [*] before the line number if  that  number 
already  exists  in the program. If you enter a program line  after  the  line 
number, Personal BASIC deletes the existing line in the program. If you type a 
Carriage  Return [CR] after the line number, Personal BASIC does  not  replace 
the existing line.

Ctrl-C  turns AUTO off. Personal BASIC does not save the last line  that  AUTO 
generates  when  you type the Ctrl-C. Anything on the last line is  lost,  and 
does  not become part of the program. If the line that you entered last  would 
have replaced a line already in the program, the existing line is retained.


Example:

The  following  command uses the AUTO default values, and generates  the  line 
numbers 10, 20, 30, 40, 50, ...

        Ok AUTO

The following command generates the line numbers 50, 75, 100, 125, 150, ...

        Ok AUTO 50, 25

The following command generates the line numbers 10, 60, 110, 160, 210, ...

        Ok AUTO , 50

The following command generates the line numbers 5, 55, 105, 155, 205, ...

        Ok AUTO 5, 50


BLOAD Statement

The BLOAD statement loads a memory image file into memory.


Syntax:

        BLOAD 'filespec'[,'address']


Explanation:

BLOAD and BSAVE are used to save and load machine-language programs and arrays 
and  their  contents. These statements also save and  display  screen  images. 
BLOAD  loads a file into memory at the address that you give. The filespec  is 
the full name of the file, the filename and filetype. The address is where you 
want loading to start. The address is a numeric expression with a value from 0 
to  65535, an offset into the segment declared by the last DEF SEG  statement. 
If you omit the address, the offset that you specified with BSAVE is  assumed. 
The file loads into the same address it came from.

BLOAD does not check addresses. Although it is possible to BLOAD anywhere,  do 
not BLOAD over Personal BASIC's data areas or your program.


Example:

        Ok 100 DEF SEG = 34562
        Ok 110 BLOAD "ARRAY",23


BREAK Command

The BREAK command stops a program at any line number.


Syntax:

        BREAK ['list of line numbers']


Explanation:

The  list  of  line  numbers is optional. If you leave  it  out,  BREAK  stops 
execution  at every line number. You can direct where you want the  BREAKs  to 
occur by supplying a line number, or line numbers separated by commas [,].

At  a break, the program line and any output are printed. The UNBREAK  command 
removes  breaks.  The  CONT command or a Carriage  Return  [CR]  restarts  the 
program after a break.


Example:

        Ok 5 N = 5
        Ok 15 FOR X = 1 TO 5
        Ok 25 N = N - 1
        Ok 35 PRINT N
        Ok 45 NEXT X
        Ok BREAK 45
        Ok RUN
         4
        b   45 NEXT X
        Br


BSAVE Statement

The BSAVE statement saves part of memory on a specified device.


Syntax:

        BSAVE 'filespec','address','length'


Explanation:

BSAVE  works  with  BLOAD to load and save machine-language  programs  or  any 
program segment.

The  filespec  is the name of your file. It must conform to  CP/M  file-naming 
standards.

The  address  is  an  offset from the segment declared in  the  last  DEF  SEG 
statement, and must be in the range 0 to 65535.

The  length is the length of the memory image to be saved. It must be  in  the 
range 0 to 65535.


Example:

        Ok 100 DEF SEG = 34562
        Ok 110 BSAVE "ARRAY",23,650


CALL Statement

The CALL statement transfers control to an assembly-language subroutine.


Syntax:

        CALL 'numeric variable' [('parameter list')]


Explanation:

The  numeric  variable  must  equate to the starting  memory  address  of  the 
assembly routine. The address is an offset into the current memory segment, as 
defined by the most recent DEF SEG statement.

The optional parameter list consists of expressions that serve as arguments to 
pass  data  between the main program and the assembly routine.  The  parameter 
list  is  enclosed  in  parentheses ["(" and  ")"].  You  must  separate  each 
expression in the parameter list with commas [,].

See  Appendix  F for more information on using Personal BASIC  with  assembly-
language subroutines.


Example:

        Ok 500 DEF SEG = &H1000
        Ok 550 CHART = 0
        Ok 600 CALL CHART(I%, A$, X)


CDBL Function

The CDBL function converts a number to a double-precision real number.


Syntax:

        X# = CDBL('numeric expression')


Explanation:

You can use any numeric expression with the CDBL function.

See  Section  2.3 for more information on conversion. See the  CSNG  and  CINT 
functions.


Example:

        Ok 10 PRINT 7/3
        Ok 20 PRINT CDBL(7/3)
        Ok RUN
         2.33333
         2.333333253860047


CHAIN Statement

The  CHAIN  statement  transfers  control, and  passes  variables  to  another 
program.


Syntax:

        CHAIN 'filespec'[,'line number'][,ALL]
        CHAIN MERGE 'filespec'[,'line number'][,DELETE 'line number list']


Explanation:

The  program  that you specify in the CHAIN statement  actually  replaces  the 
original program in memory. The program that is chained to is sometimes called 
an  overlay,  because it overwrites all or part of the original  program.  The 
filespec  is  the name of the new program to chain to. It can  be  any  string 
expression.

The  MERGE  option  merges  a program with an  existing  program,  instead  of 
replacing it. CHAIN MERGE saves all variables, type declarations,  statements, 
and  options.  If  you omit the MERGE option, you must restate  all  DEF  type 
statements  in  each new program chained to. The MERGE option  interlists  the 
statements  from the new program with the statements in the original  program. 
If some statements in the new program have the same line numbers as statements 
in  the original, the new program lines replace the original lines. The  MERGE 
option  preserves  the most recent OPTION BASE setting. See  the  OPTION  BASE 
statement in this section for more information.

If  you  execute  a  CHAIN MERGE in a  subroutine,  the  subroutine  stack  is 
preserved. A RETURN after the CHAIN MERGE has the expected effect, unless  the 
CHAIN  MERGE replaced one of the lines to which you expect to RETURN  at  some 
point. If you do this, the results are unpredictable.

You  can specify a line number after the filespec, indicating where  to  begin 
execution  in  the  new program. Otherwise, execution begins  with  the  first 
executable  statement. If you use the RENUM command to renumber the  lines  in 
the new program, you might have to change the line number that you specify  in 
the CHAIN statement.

The ALL option indicates that all variables in the original program are passed 
to  the  new program. ALL is not valid with CHAIN MERGE. If you omit  the  ALL 
option,  you  must  use the COMMON statement to declare  which  variables  the 
original  program and the new program can share. See the COMMON  statement  in 
this section for more information.

Use the DELETE option only with CHAIN MERGE. The DELETE option enables you  to 
remove  parts  of  a program from memory after execution,  to  make  room  for 
another  program. The DELETE option works like the DELETE statement  described 
in this section. It deletes lines from the current program before merging  the 
program specified by 'filespec'. Specify the line numbers to delete after  the 
DELETE keyword.


Example:

The following statement chains to a program named CALCS.BAS.

        Ok 400 CHAIN "CALCS.BAS"

The  following statement chains to the CALCS.BAS program and begins  execution 
at line 1200. All program variables can pass from the original program to  the 
new program.

        Ok 400 CHAIN "CALCS.BAS", 1200, ALL

The following statement merges the lines from an overlay named TOTAL.OVR  with 
the  program already in memory. Execution begins at line 900.  Before  loading 
the merged file, the statement deletes the lines ranging from line 900 through 
line 2000.

        Ok 710 CHAIN MERGE "TOTAL.OVR", 900, DELETE 900-2000


CHR$ Function

The  CHR$  function  returns  the ASCII  character  that  corresponds  to  the 
specified ASCII decimal value.


Syntax:

        A$ = CHR$('numeric expression')


Explanation:

CHR$ returns a one-character string.

The  numeric expression must evaluate to a legal integer. The ASCII  value  of 
the character returned is 'expression' MOD 256. CHR$ converts real numbers  to 
integers.

Use  the CHR$ function to send special characters, such as Line-Feeds [LF]  or 
Carriage  Returns  [CR],  to the terminal. The ASC  function  is  the  inverse 
function  of CHR$. See Appendix B for a listing of ASCII characters and  their 
numeric values.


Example:

        Ok 10 PRINT CHR$(83)
        Ok 20 PRINT CHR$(115)
        Ok 30 PRINT CHR$(42)
        Ok RUN
        S
        s
        *


CINT Function

The CINT function rounds a number to the nearest integer.


Syntax:

        I% = CINT('numeric expression')


Explanation:

The  numeric  expression  must be within the acceptable  range  for  integers. 
Integers can range from -32768 to 32767. Otherwise, an overflow error occurs.

See  Section  2.3 for more information on numeric conversion.  See  the  CDBL, 
CSNG, FIX, and INT functions for more information.


Example:

        Ok 10 PRINT CINT(5.2)
        Ok 20 PRINT CINT(62.89)
        Ok 30 PRINT CINT(-456.61)
        Ok RUN
         5
         63
        -457


CLEAR Statement

The CLEAR statement frees all memory used for program data without erasing the 
program  currently  in  memory.  CLEAR can  define  the  amount  of  workspace 
available to Personal BASIC.


Syntax:

        CLEAR [,'numeric expression'][,'numeric expression']


Explanation:

CLEAR  sets all numeric variables to zero, and string variables to  null.  The 
CLEAR command undefines all arrays.

The  numeric  expression specifies the maximum number of  bytes  available  as 
Personal  BASIC  work space. Personal BASIC sets the top limit of  the  memory 
that  it  uses  as one less than the expression that you  give  in  the  CLEAR 
command.  Therefore, you can safely load a machine-language subroutine at  the 
address given in CLEAR.

If  the  memory limit specified is greater than the  total  memory  available, 
Personal  BASIC  resets the limit to its start-up value.  Thus,  CLEAR,  65535 
resets memory to its start-up value. If the memory limit specified is zero, it 
is ignored. Clear, 0 has the same effect as CLEAR.

Once  you establish a memory limit with CLEAR, it remains in effect until  you 
change it with another CLEAR command. CHAINing and RUNning the program do  not 
affect a CLEAR command.


Example:

The following example clears all data from memory without erasing the original 
program.

        Ok CLEAR

The  next example clears all data from memory, and defines the maximum  amount 
of Personal BASIC work space as 32K-bytes.

        Ok CLEAR , 32768


CLOSE Statement

The  CLOSE  statement  closes all open disk files,  concluding  any  input  or 
output.


Syntax:

        CLOSE {[#]'file number'}


Explanation:

The  CLOSE  statement closes all open files, releases the  file  numbers,  and 
frees  all  buffer space that the file use. The files must have  been  created 
using the OPEN statement.

The file number is a unique identification number that you assign to a file in 
the OPEN statement. You can specify any number of file numbers in the optional 
CLOSE  statement. Separate file numbers with commas [,]. A pound sign  [#]  in 
front of the file number is optional.

File numbers can be any numeric expression. The expression must evaluate to  a 
number  between 1 and 15, which is the maximum number of files allowed,  or  a 
"Bad File Number" error occurs. If file numbers evaluate to real values, CLOSE 
converts  them  to  integers. If you do not specify  file  numbers  after  the 
keyword CLOSE, the statement closes all files that have been opened.

RESET, NEW, END, RUN, and SYSTEM close all open files automatically. The  STOP 
statement does not close disk files.


Example:

The following statement closes all open disk files.

        Ok 310 CLOSE

The following statement closes the open disk files that have been assigned the 
file numbers 3 and 7.

        Ok 600 CLOSE #3, #7


COMMON Statement

The  COMMON  statement  declares the variables that a program can  pass  to  a 
chained program.


Syntax:

        COMMON 'variable'{,'variable'}


Explanation:

Use the COMMON statement with the CHAIN statement. See the CHAIN statement  in 
this section for additional information.

Personal  BASIC treats all COMMON statements in a program as  one  consecutive 
list  of  variables.  Therefore, a program can contain any  number  of  COMMON 
statements.  For  array variables, place a set of parentheses  ["("  and  ")"] 
after the array name.

COMMON  statements  can  appear anywhere in a program.  However,  it  is  good 
practice to place them at the beginning of each program.


Example:

The  following  example  chains to a program named EMPLOYEE,  and  passes  the 
variables VAL!, NAME$, and the array variable SCALE().

        Ok 350 COMMON VAL!, NAME$, SCALE()
        Ok 360 CHAIN "EMPLOYEE"


CONT Command

The CONT command ---> Missing Page! <---


Syntax:

        ---> Missing Page! <---


Explanation:

---> Missing Page! <---


Example:

        ---> Missing Page! <---


COS Function

The COS function returns the cosine of its argument expressed in radians.


Syntax:

        X = COS('numeric expression')


Explanation:

The  COS  function  assumes that the expression is an  angle  in  radians.  To 
convert  degrees  to  radians, multiply by PI/180, where PI  =  3.141593.  COS 
converts integers to real numbers, and returns a single-precision real number.


Example:

        Ok 10 PRINT COS(23)
        Ok RUN
        -.532838


CSNG Function

The CSNG function converts a number to single precision.


Syntax:

        X = CSNG('numeric expression')


Explanation:

The numeric expression can be of any type. See Section 2.3 for more  functions 
for numeric conversion.


Example:

        Ok 10 X# = 2757.9735265835
        Ok 20 PRINT CSNG(X#)
        Ok RUN
         2757.97


CVD, CVI, and CVS Functions

CVD, CVI, and CVS functions convert strings to numeric variable types.


Syntax:

        CVD('8-byte string')
        CVI('2-byte string')
        CVS('4-byte string')


Explanation:

Personal BASIC stores numbers in a random file as strings. To read the numbers 
from the file, the strings must be converted to the proper numeric data  type. 
The functions do not change the value of the number, only the data type.

The CVD function converts and 8-byte string to a double-precision real number, 
enabling double-precision real values to be read from a random file buffer.

The  CVI  function converts a 2-byte string to an  integer,  enabling  integer 
values to be read from a random file buffer.

The  CVS function converts a 4-byte string to a single-precision real  number, 
enabling single-precision real values to be read from a random file buffer.

If  the string is shorter than the length required, it is padded to the  right 
with  binary  zeros. See Section 4.3.3 for information on  random  files.  The 
reverse of these functions is the MKD$, MKI$, and MKS$ functions.


Example:

        Ok 10 OPEN "R", #1, "NUMBERS"
        Ok 20 FIELD #1, 2 AS A$, 4 AS B$, 8 AS C$
        Ok 30 GET #1, REC%
        Ok 40 I% = CVI(A$)
        Ok 50 X! = CVS(B$)
        Ok 60 Y# = CVD(C$)


DATA Statement

The  DATA  statement  defines a list of constants that a  READ  statement  can 
assign to variables.


Syntax:

        DATA 'constant'{,'constant'}


Explanation:

DATA statements allow you to assign variables to constants, according to their 
order  in  a  string.  Every DATA constant  must  have  a  corresponding  READ 
variable, and vice versa. The constants and variables match according to their 
order  in  the  lists;  the first DATA constant  relates  to  the  first  READ 
variable, and so on.

Members  of  the  constant list can be integers, reals,  or  strings,  in  any 
combination. The data types for the constants in the DATA list, however,  must 
match  the  variables assigned them in the READ statement. You  need  not  put 
quotation marks ["] around strings.

DATA  statements  can  be  as long as you like, but  you  cannot  write  other 
statements  on the same line. Though every constant must have a  corresponding 
variable,  you do not need a READ statement for every DATA statement. You  can 
have  many DATA statements scattered in the program, and you can  assign  them 
variables  in one READ statement. In such a case, they match according to  the 
constants' order in the program first, then by their order within the lines.


Example:

        Ok 10 READ X
        Ok 20 DATA 33.3, 5, "ALLOW ROOM FOR GROWTH"
        Ok 30 PRINT X
        Ok 40 READ X,Y$
        Ok 50 PRINT X,Y$
        Ok RUN
         33.3
         5       ALLOW ROOM FOR GROWTH


DEFDBL Statement

The DEFDBL statement declares a range of letters as defining  double-precision 
real numbers.


Syntax:

        DEFDBL 'letter'{'-letter'}


Explanation:

The DEFDBL statement declares that the variables whose names start with one of 
the given letters are double-precision reals. You can use a single letter as a 
parameter or a range of letters, such as M-Z.

Type   declaration  characters  always  overrule  DEFDBL  statements.   DEFDBL 
statements can only be entered as the first statements in a program.

Note  that  DEFDBL  statements alter Personal BASIC's  interpretation  of  the 
lines.  If you declare variable as double precision with a  DEFDBL  statement, 
Personal  BASIC treats them as double precision, even if you erase the  DEFDBL 
statement.


Example:

        Ok 10 DEFDBL X-Y
        Ok 20 X = 123123412345123456
        Ok 30 Y = &H333
        Ok 40 PRINT X,Y
        Ok RUN
         1.23123412345D+17      819


DEF FN Statement

The DEF FN statement defines a user-written function.


Syntax:

        DEF FN'function name'{('parameter','parameter')} = 'definition'


Explanation:

To  use a function that you yourself have written, you must define  it  before 
you call it in a program. The DEF FN statement defines user-written functions. 
The function name must be a legal variable name.

You can list any variables in the function in the parameter list. Variables in 
the parameter list are numeric or string. They cannot be array variables. They 
are formal parameters only, acting as place markers for the actual values that 
you  will give to the function when you call it in a program. The  number  and 
type of the actual values must match exactly the number and type of the formal 
parameters. Parameters are local to the function; that is to say: they have no 
effect on variables of the same name within the program.

You  can  have  variables  in  a  function  without  listing  them  among  the 
parameters. These variables are called global variables. Global variables take 
their values from outside the function, in the program. It finds a variable of 
the  same name within the program, and adopts its current value. For  example, 
in the function definition:

        Ok 10 DEF FNA%(A%) = A% * A% * B%

the  variable A% is local because it is included in the parameter list. B%  is 
not  in the parameter list. It is global: its value is taken from a B% in  the 
program.

Suppose that there is an A% and a B% in the program itself:

        Ok 20 A% = 7
        Ok 30 B% = 3

Because these are variables in the main program, they are global. Running  the 
function shows what happens to these variables:

        Ok 40 PRINT FNA%(5)
        Ok 50 PRINT A%
        Ok 60 PRINT B%
        Ok RUN
         75
         7
         3

The  function uses the value that you assign to the local A% variable,  5,  in 
the  computation of A% * A% * B% (5 * 5 * 3 = 75). The global variable A%  was 
not  involved  in  the  computation. Because the variable B%  is  not  in  the 
parameters,  Personal BASIC found a variable named B% in the program and  used 
its value, 3.

If there is no identical name and the variable's value is not supplied  within 
the function, the value defaults to zero or null.

The  definition  is an expression that describes what the  function  does;  it 
contains the function's process or algorithm. The expression is limited to one 
line.  If the function name includes a type specification, such as  a  string, 
the  value  of  the expression must conform to that type.  The  types  of  the 
function name and parameters must also match.


Example:

        Ok 10 INPUT "WIDTH OF MATERIAL IN INCHES";MATERIAL.WIDTH
        Ok 20 INPUT "WIDTH OF WINDOWSILL IN INCHES";WINDOW.WIDTH
        Ok 30 PANELS.NEEDED = WINDOW.WIDTH / MATERIAL.WIDTH
        Ok 40 INPUT "LENGTH OF WINDOWSILL IN INCHES";WINDOW.LENGTH
        Ok 50 YARDAGE.NEEDED = PANELS.NEEDED * WINDOW.LENGTH
        Ok 60 INPUT "PRICE OF MATERIAL PER YARD";PRICE.YARD!
        Ok 70 DEF FNSLACK = YARDAGE.NEEDED + YARDAGE.NEEDED / 15
        Ok 80 DEF FNCOST! = (PRICE.YARD!/36) * FNSLACK
        Ok 90 PRINT "YOU NEED" FNSLACK "INCHES OF" MATERIAL.WIDTH [LF]
              "INCH MATERIAL.  YOUR COST IS" FNCOST!
        Ok 100 DEF FNINYARD = FNSLACK / 36
        Ok 110 PRINT FNSLACK "INCHES IN YARDS IS" FNINYARD
        Ok RUN
        WIDTH OF MATERIAL IN INCHES? 30
        WIDTH OF WINDOWSILL IN INCHES? 60
        LENGTH OF WINDOWSILL IN INCHES? 60
        PRICE OF MATERIAL PER YARD? 2.00
        YOU NEED 128 INCHES OF 30 INCH MATERIAL. YOUR COST IS 7.1111.
         128 INCHES IN YARDS IS 3.5556


DEFINT Statement

The DEFINT statement declares a range of letters as defining integers.


Syntax:

        DEFINT 'letter'{-'letter'}


Explanation:

The DEFINT statement declares that the variables whose names start with one of 
the  given  letters are integers. You can use one letter as a parameter  or  a 
range of letters, such as M-Z.

Type  declaration characters overrule DEFINT statements. The default type  for 
numbers  is  single precision. The note of caution at DEFDBL applies  also  to 
DEFINT.


Example:

        Ok 10 DEFINT X-Y
        Ok 20 X = 78.9
        Ok 30 Y = 78.1
        Ok 40 PRINT X,Y
        Ok RUN
         79       78


DEF SEG Statement

The DEF SEG statement defines the current segment of storage.


Syntax:

        DEF SEG [='address']


Explanation:

After  DEF SEG defines the current segment of storage, the physical  addresses 
of  later  BLOAD, BSAVE, CALL, PEEK, POKE, and VARPTR operations  are  offsets 
into  the segment DEF SEG sets. The default value of the segment  is  Personal 
BASIC's Data Segment, the beginning of your workspace in memory.

The  optional address is a numeric expression from 0 to 65535, based on a  16-
byte boundary. Shift the segment address 4 bits and add the offset, if any, to 
get  the absolute address for the current operation. Personal BASIC  does  not 
check the validity of the segment value. If you omit the address, the  segment 
is set to the default data segment.


Example:

        Ok DEF SEG = 35000


DEFSNG Statement

The DEFSNG statement declares a range of letters as defining  single-precision 
real numbers.


Syntax:

        DEFSNG 'letter'{-'letter'}


Explanation:

The  DEFSNG  statement defines the variable names that start with one  of  the 
given letters as single-precision reals. You can use one letter as a parameter 
or a range of letters, such as M-Z.

Type  declaration  characters always overrule DEFSNG statements.  The  default 
type  for numbers is single-precision. The note of caution at  DEFDBL  applies 
also to DEFSNG.


Example:

        Ok 10 DEFSNG X-Y
        Ok 20 X = 23D+26
        Ok 30 Y = 456654456654
        Ok 40 PRINT X,Y
        Ok RUN
         2.3E+27      4.56654E+11


DEFSTR Statement

The DEFSTR statement declares a range of letters as defining strings.


Syntax:

        DEFSTR 'letter'{-'letter'}


Explanation:

The  DEFSTR statement declares that all variables whose first letters  are  on 
the parameter list are strings. The constant values of the strings must be  in 
quotation  marks  ["].  The parameters can be a single letter or  a  range  of 
letters, such as M-Z.

A type declaration character always overrules a DEFSTR statement. The  default 
type  of  variables is single-precision real numbers. The note of  caution  at 
DEFDBL applies also to DEFSTR.


Example:

        Ok 10 DEFSTR A-C
        Ok 20 A = "12.7.42
        Ok 30 B = "1066"
        Ok 40 C = "4.12.XX"
        Ok 50 PRINT A,B,C
        Ok RUN
        12.7.42     1066        4.12.XX

(ROCHE>  12.7.42  =  7 December 1942 = Date of birth of  the  author  of  this 
manual? According to Wikipedia, "1066" is the date of the "Norman Conquest  of 
England" (in France, 1066 is totally unknown...). (This confirms that Personal 
BASIC  was  created  in England.) Finally, I could not  find  the  meaning  of 
"4.12.XX".)


DEF USR Statement

The  DEF  USR  statement  gives the starting  address  of  a  machine-language 
subroutine, to be called by the USR function.


Syntax:

        DEF USR ['digit'] = 'offset'


Explanation:

The  optional digit is any digit from 0 to 9, corresponding to the  number  of 
the  USR routine whose address you are specifying. If you omit the digit,  DEF 
USR0 is implied.

The  offset  must evaluate to an integer expression from 0 to 65535.  Add  the 
value of the offset to the current segment value to yield the actual  starting 
address of the USR routine.

You can write any number of DEF USR statements to redefine subroutine starting 
addresses and allow access to subroutines. You can redefine the address for  a 
USR routine. The most recently executed value is used for the offset.


Example:

        Ok 100 DEF SEG = 3500
        Ok 110 DEF USR0 = 40000


DELETE Command

The DELETE command erases program lines.


Syntax:

        DELETE 'line number list'


Explanation:

DELETE  erases the line or range of lines that you specify. A  DELETE  command 
can  be issued only at command level. Delete a single line by typing the  line 
number and pressing Carriage Return [CR].


Example:

        Ok 10 X = 10
        Ok 20 Z = 20
        Ok 30 PRINT X,Z
        Ok RUN
         10        20
        Ok DELETE 20-30
        Ok LIST
        10 X = 10


DIM Statement

The DIM statement defines the number of dimensions and the number of  elements 
in an array.


Syntax:

        DIM 'array name'({'subscript'}{,'subscript'})
          {,'array name'({'subscript'}{,'subscript'})}


Explanation:

The  DIM statement reserves space for a string or numeric array by  specifying 
the  number of dimensions and the upper bound of elements in each. The  number 
of  dimensions depends upon the number of subscripts; one subscript means  one 
dimension,  and  so  forth.  The lower bound of each  dimension  is  0  or  1, 
depending  upon the OPTION BASE. DIM automatically sets the initial  value  of 
the elements at zero or null.

In  Personal BASIC, arrays are dynamic. That means that you can dimension  the 
array  with  DIM, erase the array later in the program, and declare  it  again 
with  DIM, using the same name but with new dimensions. With  dynamic  arrays, 
you can also use a numeric variable to dimension the array.

You  can use an array without declaring it first with a DIM statement. If  you 
do,  the  array  is declared automatically with a default upper  bound  of  10 
elements in each dimension. For example, if the first reference to array A is:

        ARRAY A(7,3)

the array is set up as if it had been declared with:

        DIM A(10,10)

The default number of dimensions allowed if 4 for integers, and 3 for  strings 
and single- and double-precision reals. See Section 2.2.3 for more information 
on arrays.


Example:

        Ok 10 DIM HOUSES$ (1,1,1)
        Ok 20 HOUSES$ (0,0,0) = "FLOORPLAN1"
        Ok 30 HOUSES$ (0,0,1) = "FLOORPLAN3"
        Ok 40 HOUSES$ (0,1,0) = "FLOORPLAN3"
        Ok 50 HOUSES$ (0,1,1) = "FLOORPLAN3"
        Ok 60 HOUSES$ (1,0,0) = "FLOORPLAN1"
        Ok 70 HOUSES$ (1,0,1) = "FLOORPLAN2"
        Ok 80 HOUSES$ (1,1,1) = "FLOORPLAN2"
        Ok 90 IF HOUSES$ (1,0,0) = "FLOORPLAN2" THEN GOTO 300


DIR Command

The DIR command lists the files on a disk.


Syntax:

        DIR ['disk drive:']['filename.filetype']


Explanation:

The DIR command displays the directory of the disk on the current drive.

You can also request a list of a particular type of file, such as TEX files or 
BAS  files, by replacing the filename with a wild card character [*]. You  can 
replace  the  filetype with a * to find files of the same name  but  different 
types,  such as FORM.BAS, FORM.TEX, FORM.LIB, and FORM.BAK. You can replace  a 
character  in the filename or type with a question mark [?] to list  similarly 
named  files.  For example, FIVE-A and FIVE-B are listed by  the  command  DIR 
FIVE-?.


Example:

        A>DIR B:
        B:TEST    .BAS : FILE1   .BAS : WS      .COM : FILE2   .TEX

        A>DIR B:*.BAS
        B:TEST    .BAS : FILE1   .BAS

        A>DIR B:FILE?.*
        B:FILE1   .BAS : FILE2   .TEX


EDIT Command

The EDIT command lets you change a program line.


Syntax:

        EDIT 'line number'


Explanation:

To  edit  a line, type EDIT, the line number, and press the  Carriage  Return, 
[CR].  The  line number appears underneath. You can make changes in  the  line 
with the subcommands listed in Table 5-1. See Section 1.4 for more information 
about the Personal BASIC program editor.

Table 5-1. EDIT subcommands

Subcom. Description
------- -----------
   A    Instructs  the editor to ignore all changes made to the current  line, 
        and to place the cursor at the beginning of the edit line. Enables you 
        to  start  editing a line over again. This command is  valid  only  if 
        there is no other subcommand on the line.

   B    Brings the cursor to the beginning of a logical line.

  [n]C  Deletes  the character that appears directly above it in  the  program 
        line,  and inserts the character that you specify to the right of  the 
        C. nC deletes n characters, and inserts all characters after the C.

  [n]D  Deletes the character that appears directly above it in the edit line.

   E    Saves  all changes and returns Personal BASIC to command level.  Works 
        like  a Carriage Return. This command is only valid if it is the  only 
        subcommand on the line.

 [ESC]  Entered  while  typing in a program line, [ESC] drops  Personal  BASIC 
        into  Edit  mode.  Used during insert mode,  [ESC]  ends  insert  mode 
        without ending the command line.

   H    Deletes  all characters in the program line up to the next  Line-Feed, 
        [LF] then automatically activates the insert subcommand, I.

   I    Inserts  characters  into  the program line,  starting  at  the  point 
        immediately  above the cursor position. All characters up to the  next 
        [ESC]  or [CR] are inserted, including Line-Feeds. I[LF] works in  the 
        way,  but  starts  by inserting a Line-Feed. [ESC]  ends  insert  mode 
        without ending the command line.

   K    Works  much  like  subcommand  S. Searches  the  program  line  for  a 
        specified  character, and positions the cursor directly  beneath  that 
        character.  However,  the  editor deletes all  characters  up  to  the 
        specified   character.  Specify  the  character  in  the   edit   line 
        immediately  after  the K. If the character is not found,  the  cursor 
        does  not  move  from the original position,  and  no  characters  are 
        deleted.

   L    Repositions  the  cursor below the leftmost character in  the  program 
        line.

  [LF]  To  edit succeeding lines of multi-line statements, press [LF]  before 
        entering insert mode. This brings you down to the next physical line.

   Q    Instructs  the editor to ignore all changes made to the current  line, 
        quits  editing,  and  returns Personal BASIC to  command  level.  This 
        command is valid only if it is the only subcommand on the line.

   R    Moves the cursor below an imaginary character one to the right of  the 
        rightmost character in the program line.

  [n]S  Searches the program line for a specified character, and positions the 
        cursor  under  the character. Specify the character in the  edit  line 
        immediately  after  the S. If the character is not found,  the  cursor 
        does  not move from the original position. A command like  99SX  finds 
        the last occurrence of X in the line, and the cursor stays there.

   U    Moves the cursor back to the previous physical line.

   X    Positions the cursor at the end of a physical line, up to a Line-Feed, 
        and  enters insert mode. X[LF] inserts a Line-Feed  first.  Subsequent 
        characters appear on a new physical line.

   Z    Deletes a Line-Feed [LF]. Merges 2 physical lines.


Example:

        Ok 10 X=COS(Y+Z
                      ^
        Something is wrong
        Ok EDIT 10
           10    X=COS(Y+Z
        Ed                I)    Missing parenthesis is added
           10    X=COS(Y+Z)     with the I subcommand.


END Statement

The  END statement stops the program, closes all files, and return to  command 
level.


Syntax:

        END


Explanation:

You can put an END statement anywhere you want to return to command level.  An 
END  at the end of the program is optional. END differs from STOP in  that  it 
closes  all  files, returns to command level, and it does not produce  a  STOP 
message.


Example:

        Ok 10 PRINT "THE PROGRAM"
        Ok 20 PRINT "IS RUNNING"
        Ok 30 PRINT "BUT WILL NEVER"
        Ok 40 PRINT "REACH THE LAST"
        Ok 50 PRINT "WORD OF THIS"
        Ok 60 END
        Ok 70 PRINT "PROGRAM"
        Ok RUN
        THE PROGRAM
        IS RUNNING
        BUT WILL NEVER
        REACH THE LAST
        WORD OF THIS


EOF Function

The EOF function returns true (-1) at the end of a sequential file.


Syntax:

        X = EOF('file number')


Explanation:

When  you  write  a sequential file, its end is  automatically  marked.  While 
inputting from the file, you can test whether you are at the end with the end-
of-file function, EOF. EOF returns -1 if you are at the end, 0 if not. If  you 
try  to  input  past the end of a file, an error results. EOF  is  useful  for 
controlling program flow.


Example:

        Ok NEW TYPE
        Ok 90 REM THIS PROGRAM PRINTS A TEXT FILE AT THE TERMINAL
        Ok 100 INPUT "FILE ";F$
        Ok 110 IF LEN(F$) = 0 THEN END
        Ok 120 ON ERROR GOTO 20000
        Ok 130 OPEN "I", 1, F$
        Ok 140 WHILE NOT EOF(1)
        Ok 150 LINE INPUT #1,R$: ?R$
        Ok 160 WEND
        Ok 200 ?:CLOSE 1:GOTO 100
        Ok 20000 IF ERR = 53 THEN [LF]
                 ?"FILE ";F$;" NOT FOUND": RESUME 100 [LF]
                 ELSE ON ERROR GOTO 0


ERA Command

The ERA command deletes a file from the disk.


Syntax:

        ERA ['disk drive']'filename'


Explanation:

The  ERA  command  erases  all  files matching  the  filename,  on  the  drive 
specified. Once you ERAse a file, it is irrecoverable. Erasing everything with 
ERA *.* is possible, but inadvisable.


Example:

        Ok ERA B:GRAPHICS


ERASE Statement

The ERASE statement erases arrays.


Syntax:

        ERASE 'array name'{,'array name'}


Explanation:

ERASE  erases  an array so that you can redimension it or reclaim  its  memory 
space.  You  must  erase  arrays before you  redimension  them.  See  the  DIM 
statement in this section.


Example:

        Ok 10 DIM PAYROLL$ (10,10)
        Ok 20 PAYROLL$ (0,0) = "BECKWITH, JOSEPHINE"
        ...
        Ok 500 ERASE PAYROLL$
        Ok 510 DIM PAYROLL$ (10,10,10)


ERL, ERR Variables

The  ERL  and  ERR variables are reserved  variables  used  in  error-handling 
subroutines.


Syntax:

        X = ERL
        Y = ERR


Explanation:

ERL  contains  the  line number where the error was found.  ERR  contains  the 
error's code. ERL and ERR are reserved variables, which means that you  cannot 
write them on the left of the equal sign [=] in an assignment statement.

If the statement or command in which the error occurred is in direct mode, the 
value  of ERL is 65530. If an error occurs in direct mode, the program  always 
halts.

If the statement is in indirect mode, write IF statements as follows:

        IF ERL = 'error line' THEN 'executable statement'
        IF ERR = 'error code' THEN 'executable statement'

See the ERROR statement for details on error trapping and examples of ERL  and 
ERR in an error-trapping subroutine.


ERROR Statement

The  ERROR statement simulates a Personal BASIC run-time error, and  transfers 
control to an error-trapping routine.


Syntax:

        ERROR 'numeric expression'


Explanation:

You  can  define  errors and error messages in your programs  with  the  ERROR 
statement.  ERROR  assigns a 'numeric expression', corresponding to  an  error 
code,  to  an error. The error code is an integer expression.  Each  time  the 
error  occurs, the program refers to the error code number. If the error  code 
corresponds  to a Personal BASIC error code, the Personal BASIC error  message 
prints. If an error trap that you have written is in effect, control passes to 
the error trap routine.

Two  predefined  variables are associated with the ERROR statement  and  error 
code:  ERL and ERR. ERR assumes the value of the error code constant. You  can 
use  it to write error messages: for example, IF ERR = 100 THEN PRINT  "PLEASE 
CHECK THE NUMBER AND RE-ENTER".

When an ERROR statement executes, the reserved variables ERR and ERL are  set. 
ERR  is  set to the value of the 'numeric expression', which  must  be  within 
integer range. ERL is set to the line that contains the ERROR statement.

If no user error trap is set, the message corresponding to the value in ERR is 
printed, and the program halts. This occurs if an ERROR statement is  executed 
in direct mode whether you set a trap or not.

If  you  set a trap, the program enters the error-trapping  routine.  You  can 
examine  ERR  and ERL in the usual way. To exit the error  trap,  use  RESUME, 
whether you entered the trap because of a trappable Personal BASIC error or an 
ERROR statement.

See the ERL and ERR variables in this section.

If  the error code equals a predefined Personal BASIC error code, the  program 
simulates  the error and prints the error message for that code. The  Personal 
BASIC error code messages are in Appendix D. When you define your own  errors, 
it is well to give your error codes values that are much greater than Personal 
BASIC's  codes.  In this way, your programs will not need  changing,  even  if 
Personal BASIC's error codes are revised.


Example:

You  can simulate errors in both direct and indirect mode. Here is an  example 
in direct mode:

        Ok ERROR 55
        You cannot OPEN or KILL a file already open

The following example is in indirect mode:

        ...
        Ok 500 ON ERROR GOTO 550
        Ok 510 INPUT "DO YOU WISH TO RECEIVE EARNED INCOME CREDIT"; E$
        Ok 515 IF E$ = "NO" THEN GOTO 600
        Ok 520 INPUT "IS THE AMOUNT LISTED ON LINE 33 LESS THAN $10,000";X$
        Ok 525 IF X$ = "NO" THEN ERROR 200
        Ok 530 IF ERR = 200 THEN [LF]
        Ok 535 PRINT "YOU ARE INELIGIBLE FOR EARNED INCOME CREDIT."
        Ok 540 IF ERL = 525 THEN GOTO 600
        Ok 550 RESUME
        ...
        Ok RUN
        DO YOU WISH TO RECEIVE EARNED INCOME CREDIT? YES
        IS THE AMOUNT LISTED ON LINE 33 LESS THAN $10,000? NO
        YOU ARE INELIGIBLE FOR EARNED INCOME CREDIT.


EXP Function

The EXP function returns the constant e raised to an exponent.


Syntax:

        X = EXP('numeric expression')


Explanation:

The  constant  e  is the base of natural logarithms,  approximately  equal  to 
2.7182. EXP returns a real number.

The numeric expression must evaluate to <= 87.3365. An overflow results in  an 
error message and signed machine infinity; the program continues running.


Example:

The constant e with EXP function.

        Ok 10 X = EXP(3.254)
        Ok 20 Y = EXP(8.97)
        Ok 30 PRINT X,Y
        Ok RUN
         25.8937        7863.6


FIELD Statement

The FIELD statement allocates variable space in random file buffers.


Syntax:

        FIELD #'file number','field width' AS 'string variable'
                           {,'field width' AS 'string variable'}


Explanation:

You  must write a FIELD statement to transfer information between random  file 
disks  and random buffers. The FIELD statement only allocates variable  space; 
it does not move data.

The  file number is the number that you gave to the file when you  opened  it. 
The  field width defines the number of bytes to give to the  string  variable. 
For  example,  FIELD #10, 20 AS X$, 30 AS Z$ allocates the first 20  bytes  of 
space to X$, and the next 30 bytes to Z$.

You cannot allocate more space than you created when you opened the file.  The 
default record length is 128 bytes. For any file, you can write as many  FIELD 
statements as you want. Re-allocating field space does not cancel the original 
mapping; rather, the two maps co-exist. For example, if you specify:

        FIELD #10, 20 AS X$, 40 AS Z$, 10 AS Y$
and
        FIELD #10, 70 AS N$

the first 20 bytes of N$ are also in X$, the next 40 also in Z$, and the final 
10 also in Y$.

Do  not use an INPUT or LET statement with a variable that was declared  in  a 
FIELD  statement.  Otherwise,  the variable's pointer moves  to  string  space 
instead of to the buffer.

Additional explanation:
In  a file buffer, there can be many fields of characters. The arrangement  of 
variable  fields in buffer constitutes a map. Fields have a starting point  in 
the buffer, and length, in bytes.

        P$ is a string variable:         P$
                                         |
                                         V
        The map created by      --------------------
        the FIELD statement:    | start  | length  |
                                ----|--------|------
                                    V _______V_______
        This is part   /-------------/---------------\-----\
        of a file      \            |                 |    /
        buffer:        /            |                 |    \
                       \-----------------------------------/

The starting place is where the first character of a field variable is mapped. 
The  starting place for each variable depends on its place in the FIELD  list. 
It is the sum of the variable lengths that came before it. The first  variable 
in a list starts at the beginning of the buffer.

In  line  110  of the example below, X$ is allocated bytes 1 to  20.  Z$,  the 
second  variable,  is allotted bytes 21 to 60. The third variable,  Y$,  takes 
bytes  61-70.  Although the total size of the record is 128 bytes,  the  total 
space mapped is 70 bytes.

You can have any number of FIELD statements for the same file number. A second 
mapping  does  does  not cancel the first. See the  example  mapping  and  its 
depiction below:

        100  OPEN "R", #10, "TAXES", 128
        110  FIELD #10, 20 AS X$, 40 AS Z$, 10 AS Y$

        Depiction of the above mapping:

               50 bytes as P$   20 bytes as Q$
                           ^                ^
                           |                |
          /----------------^--------\   /---^---\
         /                           \ /         \
        |     X$               Z$     |       Y$  |
        |  ____^___   __________^_____|__      ^  |
        | /  20    \ /    40          |   \  /10 \|
         /----------V-----------------|-----V-----\---\
        |           |                 |     |     |   /
        |  F I L E  |  B U F F E R    |     |     |   \
        +-----+-----+-----+-----+-----+-----+-----+---/
        0     10    20    30    40    50    60    70
     start----------- 128 total bytes ---------------->

Notice that you do not have to map all the space in a record; you can allocate 
fewer bytes than are available to you. However, the total number of bytes that 
you allocate cannot exceed the length of the record when you opened it, or  an 
error occurs.


Example:

        Ok 100 OPEN "R", #5, "TAXES", 40
        Ok 110 FIELD #5, 20 AS I$, 10 AS D$, 10 AS E$


FIX Function

The FIX function truncates a real number to an integer.


Syntax:

        X = FIX(number)


Explanation:

Unlike  CINT, FIX does not round the number. Unlike INT, FIX does  not  return 
the  next smallest integer for negative numbers; instead, it simply  truncates 
the number.


Example:

        Ok 10 X = 239.77
        Ok 20 PRINT FIX(X)
        Ok 30 PRINT FIX (-678.3)
        Ok RUN
         239
        -678


FLOAT Function

The FLOAT function converts an integer to a single-precision real number.


Syntax:

        X = FLOAT('integer expression')


Explanation:

FLOAT does not change the appearance of the integer, but assigns it more  room 
in storage. The integer expression must be within legal integer range.


Example:

        Ok 10 X = FLOAT(97)
        Ok 20 PRINT X
        Ok RUN
         97


FOLLOW Command

The FOLLOW command traces program variables, and cites the line number.


Syntax:

        FOLLOW 'variable'{,'variable'}


Explanation:

The  FOLLOW  command is a debugging facility that keeps track of  all  program 
variables as the value of each variable changes. FOLLOW lists the value of the 
given  variable  or variables as the value changes. FOLLOW prints  a  variable 
name,  the  value of the variable, and the line number  indicating  where  the 
value changes. The UNFOLLOW command cancels FOLLOW. The FOLLOW command  traces 
only simple variables -- that is to say: not array variables.


Example:

        Ok 10 FOR X = 1 TO 3
        Ok 20 N = N + 1
        Ok 30 B = B + 1
        Ok 40 PRINT N
        Ok 50 PRINT B
        Ok 60 NEXT X
        Ok RUN
         1
         1
         2
         2
         3
         3
        Ok FOLLOW N,B
        Ok RUN
        Var N! =  1 At line 20
        Var B! =  1 At line 30
         1
         1
        Var N! =  2 At line 20
        Var B! =  2 At line 30
         2
         2
        Var N! =  3 At line 20
        Var B! =  3 At line 30
         3
         3
        Ok UNFOLLOW


FOR Statement

The FOR statement creates a loop that executes instructions a given number  of 
times.


Syntax:

        FOR 'counter variable' = 'numeric expression' TO 'numeric expression'
            [STEP 'numeric expression']


Explanation:

The  FOR  statement  controls the execution of  a  FOR-NEXT  loop.  Statements 
between  a FOR statement and a corresponding NEXT execute repeatedly,  to  the 
number  of  times  that you specify. FOR-NEXT loops can contain  any  kind  of 
executable statement.

The expressions before and after TO determine how many times the loop repeats. 
The first numeric expression is the value at which the loop begins; the second 
is  the value at which it stops. The counter is a numeric variable that  takes 
the  value of the first expression before execution begins, and counts  up  or 
down until it exceeds the value of the second expression. If the initial value 
of the counter is outside the range specified by TO and STEP, the FOR loop  is 
never executed. See the second example below.

STEP  is  optional; its default value is 1. Every time the loop  repeats,  the 
value  of  the  counter increments or decrements by the  value  of  STEP.  For 
example,  in  FOR X = 2 TO 10 STEP 2, the initial value of X is 2.  After  one 
repetition of the loop, the value of X is 4; after two repetitions, 6. When  X 
= 10, the loop executes once more and stops. The number of execution is 5.

FOR  is  always  used with NEXT. After an execution of a FOR  loop,  the  NEXT 
statement sends program control back to the counter. The sign of the STEP  and 
the value of the counter determine whether the loop ends. If STEP is positive, 
the loop repeats as long as the value of the counter is less than or equal  to 
the  value of the final expression. If STEP is negative, the loop  repeats  as 
long as the counter is greater than or equal to the final expression.

You can write FOR-NEXT statements within FOR-NEXT statements; in other  words, 
you can have a loop within a loop. When you nest loops, the NEXT statement for 
the  second  loop  must  come before that of the  first  loop.  See  the  NEXT 
statement in this section.


Example:

        Ok 10 FOR X = 1 TO 5
        Ok 20 PRINT X
        Ok 30 NEXT
        Ok 40 PRINT "THE VALUE OF THE COUNTER VARIABLE IS"X
        Ok RUN
         1
         2
         3
         4
         5
        THE VALUE OF THE COUNTER VARIABLE IS 6
        Ok 40
        Ok 10 FOR X = 5 TO 1 STEP -1
        Ok RUN
         5
         4
         3
         2
         1


FRE Function

The FRE function returns the number of unused bytes in memory.


Syntax:

        X = FRE(0)
        Y = FRE(Z$)


Explanation:

FRE  requires  a dummy argument. Use any argument to find the number  of  free 
bytes  in  memory. The number of free bytes is a whole number  between  0  and 
65535.


Example:

        Ok PRINT FRE(0)
         43000


GET Statement

The GET command reads a record from a random disk file into a file buffer.


Syntax:

        GET [#]'file number'[,'record number']


Explanation:

The  file number is the number that you gave to the file when you  opened  it. 
The record number is optional. If you leave it out, the next record after  the 
last GET or PUT goes into the buffer. The greatest record number that you  can 
have is 32767. See the OPEN statement for an example of GET in context.


Example:

        Ok 100 IF X$ = "YES" THEN GET#5, TYPE%: GOTO 200


GOSUB Statement

The GOSUB statement sends program control to a subroutine.


Syntax:

        GOSUB 'line number'


Explanation:

The GOSUB statement is paired with the RETURN statement, which brings  control 
back  to the main program at the point where it branched off. You can  call  a 
subroutine from another subroutine.

The  line number is the line on which the subroutine begins. You can call  and 
write  subroutines  as often as you like, wherever you like. If  you  write  a 
subroutine  in  the middle of a program, take care that the program  does  not 
flow into it naturally by blocking it with STOP, END, or GOTO statements.

The  RETURN  statement  directs execution back to  the  statement  immediately 
following the last GOSUB. You can write more than one RETURN statement through 
GOSUB.  If  you  are  testing for  conditions  that  determine  the  program's 
progress, you might have several RETURNs in a subroutine. The example shows  a 
subroutine entered by the statement GOSUB 100.


Example:

        Ok 10 GOSUB 100
        Ok 20 REM RETURN POINT OF SUBROUTINE
        Ok 30 PRINT A
        Ok 40 GOTO 200
        Ok 50 '
        Ok 100 REM START OF SUBROUTINE
        Ok 110 A=5^6
        Ok 120 RETURN
        Ok 130 '
        Ok 200 END
        Ok RUN
         15625


GOTO Statement

The  GOTO  statement  sends program control unconditionally to  a  given  line 
number.


Syntax:

        GOTO 'line number'


Explanation:

The GOTO statement interrupts the normal order of program execution, jumps  to 
a  given  line number, and resumes execution from there. If you  GOTO  a  non-
executable statement, execution begins at the first executable statement after 
the given line number.

In  Personal  BASIC,  GOTO  and  GO TO  are  equivalents.  You  can  use  them 
interchangeably.


Example:

        Ok 10 INPUT "PLEASE ENTER BENEFICIARY'S NAME"; NAME$
        ...
        Ok 100 INPUT "DO YOU WISH TO END THIS PROGRAM";ANSWER$
        Ok 120 IF ANSWER$ = "YES" THEN GOTO 1000
        Ok 130 GOTO 10
        Ok 140 '
        Ok 1000 END


HEX$ Function

The  HEX$  function  returns  a  string that  is  the  hexadecimal  (base  16) 
representation of a number.


Syntax:

        X = HEX$(numeric expression)


Explanation:

A  hexadecimal number is a base 16 integer. The legal symbols for  hexadecimal 
numbers  are  the  digits 0 through 9 and the characters A  through  F,  which 
represent  the  values 10 through 15. HEX$ does not add a leading  &H  to  the 
hexadecimal  number it returns. If you want to use the value in  the  program, 
you  must  write it with &H to establish that it is in  hexadecimal  notation. 
Real numbers round to integers before HEX$ evaluates.

Because  HEX$  accepts machine addresses as arguments, the range  of  integers 
HEX$ accepts is -32768 to 65535. The normal legal range for integers is -32768 
to  32767. Attempting to assign an address expression to an  integer  variable 
leads  to  an  integer  overflow error, unless you assign  the  value  to  the 
variable with VAL, as in the following example.


Example:

        Ok 10 A% = VAL("&H" + HEX$(FRE(0)))
        Ok 20 PRINT A%
        Ok RUN
        -22536


IF Statement

The IF statement sets conditions that determine program flow.


Syntax:

        IF 'logical expression' THEN 'statement'{':statement'}
                               [ELSE 'statement'{':statement'}]


Explanation:

The  IF  statement evaluates an expression that is either true (-1)  or  false 
(0). If the expression is true, the statements following THEN are executed. If 
false,  execution continues at the statement after ELSE. If there is no  ELSE, 
execution continues at the next executable statement.

Separate  statements with colons [:] and use a Line-Feed (Ctrl-J) to  continue 
statements  over  several  lines.  You  can  write  IF  statements  within  IF 
statements. Each ELSE matches with the nearest lone THEN. THEN or ELSE clauses 
are valid only within the context of an IF statement.

You can write a FOR or WHILE statement within the THEN or ELSE clause of an IF 
statement. The FOR or WHILE statement must be complete within the THEN or ELSE 
clause: the matching NEXT must be in the same clause as the FOR statement, and 
the  matching WEND must be in the same clause as the WHILE statement. See  the 
first example below.

If an IF statement occurs within a FOR or WHILE statement (all as part of  the 
same  statement line), the closing NEXT or WEND also closes the IF  construct. 
See the second example below.


Example:

        Ok 5    A% = 5
        Ok 10   IF A% > 3 THEN [LF]
                FOR K% = 1 TO 5: PRINT A% * K%: NEXT [LF]
                ELSE FOR K% = 1 TO 5: PRINT A% / K%: NEXT
        Ok RUN
         5
         10
         15
         20
         25

        Ok 10   FOR X = 1 TO 5: [LF]
                    IF X < 3 THEN PRINT X * X : [LF]
                NEXT : [LF]
                PRINT "DONE"
        Ok RUN
         1
         4
        DONE        (The NEXT is always executed.)


INKEY$ Function

The INKEY$ function reads a character from the keyboard, if one is waiting.


Syntax:

        X$ = INKEY$


Explanation:

INKEY$  scans the keyboard to detect whether you hit a key. If you do,  INKEY$ 
returns the character. If you don't, INKEY$ returns a null string [""]. INKEY$ 
stores  only one character at a time, namely, the last character entered;  the 
previous keystroke is replaced and lost.

Unlike  the  INPUT  statement,  which suspends  program  execution  until  you 
respond, INKEY$ does not wait for your input. You can write a WHILE-WEND  loop 
that  runs until you enter a character. In this case, INKEY$ constantly  scans 
for  the character and the program is continuously looping; it has not  halted 
for your input.

You  can test INKEY$ for a particular character. INKEY$ reads  each  character 
from the keyboard buffer. Which character is there can determine program flow. 
For  example,  INKEY$  can  check a program to  see  whether  you  entered  an 
interrupt signal; the program jumps to an exit routine if so, or continues  if 
not.

None  of  the characters returned by INKEY$ print on the  screen,  unless  you 
print  them with a subsequent PRINT statement. All characters pass on  to  the 
program except Ctrl-C, Ctrl-S, and Ctrl-Q, which might or might not, depending 
upon the exact timing of your entry.

Notice  the  example program below. It constructs a WHILE-WEND loop  in  which 
INKEY$  reads and stores a keystroke, the current value of INKEY$ is  assigned 
to  a variable, the ASCII value of the character is printed, and  the  program 
loops back to the start. If you enter Ctrl-C while the program is on line  30, 
the Ctrl-C is read by INKEY$ and passed on to the program; the program is  not 
interrupted.  If you enter the Ctrl-C while the program is on any other  line, 
however,  it interrupts the loop just as it would in any other Personal  BASIC 
program.  It is possible to disable Ctrl-C's ability to break a  program.  See 
Appendix E, option 1 for more information on Ctrl-C.


Example:

        Ok 10 I$ = ""
        Ok 20 WHILE I$ = ""
        Ok 30 I$ = INKEY$
        Ok 40 WEND
        Ok 50 PRINT ASC(I$)
        Ok 60 GOTO 10
        Ok RUN
        53      ("5" was hit)
        27      ("ESC" was hit)
        76      ("L" was hit)
        65      ("A" was hit)
        104     ("h" was hit)


INP Function

The INP function returns a byte value from a selected input/output port.


Syntax:

        X = INP('port number')


Explanation:

The  port  number  must be in the range 0 to 65535. The INP  function  is  the 
complement of the OUT statement.


Example:

        Ok 200 IF INP(300) > X THEN GOTO 100


INPUT Statement

The  INPUT  statement lets you enter data while the program  is  running,  and 
assigns the data to program variables.


Syntax:

        INPUT [;] ['prompt string' '; or ,'] 'variable' {,'variable'}


Explanation:

The  INPUT  statement prompts you for input with a question  mark  [?]  during 
program  execution,  and waits for your response. After you type  a  response, 
press the Carriage Return [CR] to send it to the program.

The  prompt  string  is  a string constant, and must be  in  quotes  ["].  The 
variables can be string or numeric. Your responses must match the type of  the 
variables. String responses, however, need not be in quotes.

If  you write a prompt string, the INPUT statement prints it on the screen  as 
the prompt. The prompt string appears as a question or a statement,  depending 
on whether you use a comma [,] or a semicolon [;].

If you separate the prompt string from the variables with a semicolon [;], the 
INPUT  statement adds a question mark [?] to the end of the prompt string.  If 
you separate the prompt string from the variables with a comma [,], the prompt 
prints  without a question mark, and without a space after the last  character 
in  your  prompt  string. You type your response on the same  line.  For  this 
reason,  you  need  to include a space as the last character  in  your  prompt 
string if you want a clean division between the prompt and your response.

If  you  do not write a prompt string, or if you write a  null  string,  INPUT 
prints a question mark [?] and a space, and awaits your input.

The  INPUT  statement  prints a prompt for each variable,  and  each  response 
corresponds  to  an INPUT variable. If the number of variables  and  responses 
differ, a warning appears. You must separate individual responses with  commas 
[,];  however,  you can also use commas in your response if  you  enclose  the 
string in quotation marks ["].

You can enter one console line of characters in response to an INPUT  request. 
A  Carriage Return [CR], Line-Feed [LF], or [ESC] ends the line of input.  The 
maximum line length is 255 characters.

If you include a semicolon [;] after INPUT in the statement line, pressing the 
Carriage  Return [CR] after your response does not skip you down to  the  next 
line.


Example:

        Ok 10 INPUT "ENTER TODAY'S DATE:  ",X$
        Ok 20 INPUT "ENTER YOUR IDENTIFICATION NUMBER:  ",Z$
        Ok 30 IF Z$ = ACCEPTABLE GOTO 100
        Ok RUN
        ENTER TODAY'S DATE:  9 JULY 1983
        ENTER YOUR IDENTIFICATION NUMBER:  359152

(ROCHE> Notice that this book is dated April 1983... 3 months earlier!)


INPUT# Statement

The  INPUT#  statement  assigns data from a sequential disk  file  to  program 
variables.


Syntax:

        INPUT#'file number','variable'{,'variable'}


Explanation:

The  file number is the number that you gave to the file when you  opened  it. 
You assign the data in the file to variables. The types of a variable and  its 
assigned data must match.

The INPUT# statement works much like the INPUT statement, except that it  does 
not  prompt.  Before assigning the data item that you enter to  the  variable, 
INPUT#  skips  any leading spaces [ ], tabs [HT], Carriage Returns  [CR],  and 
Line-Feeds [LF] that you enter with the data. The first character that is  not 
one  of these is taken as the start of the data. A space [ ], Carriage  Return 
[CR], Line-Feed [LF], comma [,], or reaching 255 characters signals the end of 
the data.

There  are  3 kinds of data for the INPUT# statement: numbers, in any  of  the 
numeric formats; quoted strings; and unquoted strings. Data is interpreted  as 
a  number if the variable that you assign it to is numeric. Otherwise,  it  is 
taken  as  a  string.  Numbers  are  ended  by  reaching  end-of-file  or  255 
characters,  or by a Line-Feed [LF], Carriage Return [CR], comma [,],  or  any 
character that is not a valid part of a number.

Strings are treated as quoted if the first non-space character is a  quotation 
mark  ["].  Everything within a pair of quotation marks is taken  as  data  in 
quoted  strings.  You cannot use a quotation mark as a  character  within  the 
quoted  string  because  the second quotation mark  ends  the  string.  Quoted 
strings are also ended by reaching end-of-file or 255 characters.

Unquoted strings can include quotation marks ["]. They are ended by a Carriage 
Return  [CR],  Line-Feed  [LF],  comma [,], or  reaching  end-of-file  or  255 
characters. Trailing spaces in unquoted strings are ignored.

See Section 4.3.2 for more information on sequential files and INPUT#.


Example:

        Ok 10 OPEN "I", #10, "BILLING"
        Ok 20 INPUT#10, CUSTOMER$, INVOICE%, DATE$


INPUT$ Function

The INPUT$ function returns a specified number of characters from the terminal 
or a data file.


Syntax:

        X$ = INPUT$('number of characters'[,[#]'file number'])


Explanation:

The  string comes from the terminal or from a file, in which case you  specify 
the file number.

INPUT$  reads exactly the number of characters specified from the terminal  or 
file,  and  returns a string containing these characters. All  characters  are 
returned  without  translation, that is to say: exactly as you  put  them  in. 
Control characters are passed to the variable without exception: for  example, 
Ctrl-C from the terminal and Ctrl-Z from a data file are passed.

If  you input the string at the terminal, the characters are not echoed.  They 
do not appear on the screen. If you try to read beyond end-of-file, you  cause 
an error.


Example:

        Ok 10 PRINT "PASSWORD? ";
        Ok 20 X$ = INPUT$(6)
        Ok 30 IF X$ = "GEORGE" THEN 1000 ELSE PRINT "WRONG": END
        Ok 1000 PRINT "OK"
        Ok RUN
        PASSWORD? DANIEL
        PASSWORD? WRONG

(ROCHE>  In fact, Personal BASIC does not display "DANIEL" on the screen:  you 
type  "DANIEL"  blindly, then Personal BASIC displays "OK"  or  "WRONG"  after 
"PASSWORD? ", only after reading the 6-character input.)


INSTR Function

The  INSTR  function searches for one string within another, and  returns  its 
position.


Syntax:

        X = INSTR(['starting point',]'target string exp.','pattern string')


Explanation:

INSTR  looks  for  the first occurrence of a pattern string  within  a  target 
string,  and returns its position. The optional starting point is  an  integer 
between  1  and  255.  The target string and pattern  strings  can  be  string 
constants, expressions, or variables.

You  can  specify a character as a starting point in a string  by  giving  its 
ordinal  value in the string. For example, X=INSTR(3,"CBAABC","C") returns  6, 
because starting at the 3rd character, A, the first C is the 6th character. If 
you do not supply a starting point, the search starts from position 1.

If  the  pattern string is longer than the target pattern, or  if  the  target 
pattern is null, or if the pattern string is not in the target pattern,  INSTR 
returns 0. If the pattern string is null, INSTR returns the starting position, 
I or 1.


Example:

        Ok 10 X$ = "HOW DO YOU DO?"
        Ok 20 X = INSTR(3,X$,"DO")
        Ok 30 PRINT X
        Ok RUN
         5


INT Function

The INT function returns the integer portion of a number as a real number.


Syntax:

        X = INT(numeric expression)


Explanation:

INT returns the largest whole number not greater than its argument. The result 
is  double  precision if the argument is double precision;  otherwise,  it  is 
single precision.


Example:

        Ok 10 X# = INT(5570372182.5)
        Ok 20 PRINT X#
        Ok RUN
         5570372182


KILL Statement

The KILL statement deletes a disk file.


Syntax:

        KILL 'string expression'


Explanation:

The  string  expression  evaluates  to  a  filename.  KILL  deletes  the  file 
associated  with that filename. For example, KILL A$ deletes the file  ADDRESS 
where A$ = ADDRESS. You can KILL any kind of disk file. You cannot kill a file 
that  is open at the time; an error occurs if you try. The example  creates  a 
file named CALC.BAS and the file is deleted by KILL. KILL can be used within a 
Personal BASIC program.


Example:

        Ok NEW
        Ok 10 A=45:B=56
        Ok 20 PRINT A+B
        Ok 30 END
        Ok SAVE CALC
        Ok B$="CALC.BAS"
        Ok KILL B$


LEFT$ Function

The LEFT$ function returns a string that contains the leftmost characters of a 
string.


Syntax:

        X$ = LEFT$('target string','number of characters')


Explanation:

LEFT$  starts  at  the leftmost character, and  returns  as  many  consecutive 
characters as you specify. The number of characters must be a positive  number 
or  expression  with  a  value from 0 to  255.  Real  expressions  convert  to 
integers. The target string can be a string constant, variable, or expression. 
If  the number of characters is greater than the length of the target  string, 
LEFT$ returns the entire target string. If the number of characters is 0,  the 
null string returns.


Example:

        Ok 10 INPUT "RADIUS";R
        Ok 20 PRINT 3.1416*R^2
        Ok 30 INPUT "ANOTHER AREA";C$
        Ok 40 IF LEFT$(C$,1)="Y" THEN 10
        Ok 50 END


LEN Function

The LEN function returns the length of a string.


Syntax:

        X = LEN('string expression')


Explanation:

LEN  returns  the number of characters as an integer. If the expression  is  a 
null string, LEN returns zero.


Example:

        Ok 10 ADDRESS$ = "2114 PARKER ST, BIRDLAND, NEW YORK"
        Ok 20 FOR X = 1 TO LEN(ADDRESS$)
        Ok 30 PRINT CHR$(42);
        Ok 40 NEXT X
        Ok RUN
        **********************************


LET Statement

The LET statement assigns a value to a variable or array variable.


Syntax:

        LET 'variable'='expression'


Explanation:

Using LET to assign values to variables is optional. For example, LET X=Y  and 
X=Y  are identical in meaning. The variable and the expression can be  strings 
or numbers. For numeric variables and expressions, the type of the  expression 
converts to match the type of the variable.


Example:

        Ok 10 LET NAME$ = "ALYSON"
        Ok 20 TICKETOFFICE$ = "BATH, ENGLAND"
        Ok 30 LET DESTINATION$ = "CANTERBURY"
        Ok 40 DATE.OF.DEPARTURE = 4.1
        Ok 50 DATE.OF.ARRIVAL = 4.8
        Ok 60 LENGTH.OF.TRIP = DATE.OF.ARRIVAL - DATE.OF.DEPARTURE
        Ok 70 PRINT NAME$
        Ok 80 PRINT TICKETOFFICE$
        Ok 90 PRINT "DESTINATION:  " DESTINATION$
        Ok 100 PRINT "LENGTH OF TRIP:  " LENGTH.OF.TRIP
        Ok RUN
        ALYSON
        BATH, ENGLAND
        DESTINATION:  CANTERBURY
        LENGTH OF TRIP:  .7

(ROCHE> No doubt about it, Personal BASIC was made in England...)


LINE INPUT Statement

The LINE INPUT statement requests input from the keyboard, and assigns it to a 
string variable.


Syntax:

        LINE INPUT[;]["prompt"[, or ;]]'string variable'


Explanation:

LINE  INPUT is like the INPUT statement in that it asks you to enter  data  at 
the  keyboard,  but  it accepts an entire line of up to 255  characters  as  a 
response. Your response is assigned to the string variable. A Carriage  Return 
[CR], Line-Feed [LF], or [ESC] ends your input and sends it to the computer.

The optional prompt is a string that you write as an input request; LINE INPUT 
prints  it  on the terminal and waits for your response. LINE INPUT  does  not 
automatically add a question mark [?] or a space [ ] after the prompt, but you 
can write a question mark or space within the prompt string. Including a space 
is advisable, because otherwise your input abuts the prompt, on the same line. 
If  you  include  a  semicolon [;] after LINE INPUT  in  the  statement  line, 
pressing  the Carriage Return [CR] after your response does not skip you  down 
to the next line.


Example:

        Ok 10 LINE INPUT "REASON FOR RETURNING MERCHANDISE";R$
        Ok 20 PRINT "THANK YOU.  WE ARE PROCESSING YOUR COMPLAINT"
        Ok RUN
        REASON FOR RETURNING MERCHANDISE?
        WRONG SIZE, WRONG COLOR, TASTELESS STYLE.
        THANK YOU.  WE ARE PROCESSING YOUR COMPLAINT


LINE INPUT# Statement

The  LINE  INPUT# statement requests input from a sequential  disk  file,  and 
assigns it to a string variable.


Syntax:

        LINE INPUT#'file number','string variable'


Explanation:

Like  LINE INPUT, LINE INPUT# assigns a line of up to 254 characters as  input 
to  a  string variable, but the input comes from a sequential disk  file.  The 
file number is the number that you gave to the file when you opened it.

LINE  INPUT#  reads all characters in a sequential file until it  comes  to  a 
Carriage  Return [CR], and assigns them to the string variable. The next  LINE 
INPUT#  statement starts where the first left off, and assigns the next  line, 
up  to  a Carriage Return, to the next string variable. If  a  Line-Feed  [LF] 
immediately precedes a Carriage Return, they are treated as regular characters 
and do not end the line.


Example:

        Ok 10 OPEN "O", #4, "SCORES"
        Ok 20 LINE INPUT "GIVE TEAMS, WINNERS, AND SCORES.", S$
        Ok 30 PRINT#1, S$
        Ok 40 CLOSE #4
        Ok 50 OPEN "I", #4, "SCORES"
        Ok 60 LINE INPUT#4,S$
        Ok 70 PRINT S$
        Ok 80 CLOSE #4
        Ok RUN
        GIVE TEAMS, WINNERS, AND SCORES.
        USC & UCLA: USC. 50-3; CPSLO & FRESNO: CPSLO. 33-20
        USC & UCLA: USC. 50-3; CPSLO & FRESNO: CPSLO. 33-20

(ROCHE> No doubt about it, Personal BASIC was bought by Digital Research...)


LIST Command

The LIST command displays a program.


Syntax:

        LIST ['line number list']


Explanation:

LIST displays on the terminal the lines of the current program.

If you do not supply a line number, LIST lists the entire program, starting at 
the beginning of the program, the lowest line number. If the program is  long, 
the beginning flies by, and all you see is the end of the program.

You  can  direct where you want the listing to start or stop  by  giving  line 
numbers  in the line number list. You can direct the listing to begin  with  a 
particular  line  number, by giving that line number alone.  LIST  prints  the 
program  up to a particular line number if you supply a dash [-]  followed  by 
the line number with which you want it to end. If you supply both a  beginning 
and  ending  line  number, a range of line numbers, such as lines  30  to  70, 
prints.  You can give more than one range by specifying more than one pair  of 
line numbers: for example, LIST 20-100, 200-300.


Example:

        LIST                            Lists entire program
        LIST 70                         Lists line 70 only
        LIST -70                        Lists all lines, up to line 70
        LIST 30-70, 100-                Lists lines 30-70 and lines after 100
        LIST 30-70, 100-120, 300-999    Lists line 30-70, 100-120, and 300-999


LLIST Command

The LLIST command lists the program currently in memory on a printer.


Syntax:

        LLIST ['line number list']


Explanation:

LLIST works in the same way as LIST, but prints the lines on the printer.  You 
can set the assumed width of the line printer with the WIDTH LPRINT statement. 
Initially,  it  is  72 characters. After a LLIST, Personal  BASIC  returns  to 
command level.

(ROCHE> Notice that 72 characters was the width of the ASR-33 Teletype...  and 
that  the LIST Command explanation does not mention any width, and how to  set 
it... See WIDTH in this section and Appendix E: "The option table".)


Example:

        See the LIST command in this section.


LOC Function

The LOC function returns either a record number or the number of sectors  read 
from or written to a file.


Syntax:

        X = LOC('file number')


Explanation:

When  used after a GET or PUT in a random disk file, LOC returns  the  current 
record  number, that is to say: the record most recently read or written  with 
GET or PUT. For example:

        GET #1
        PUT #1,LOC(1)

replaces record #1 in the slot from which it is read.

Used with sequential files, LOC returns the number of sectors read or  written 
since the file was opened. A sector is a 128-byte block.


Example:

        Ok 10 OPEN "R", #8, "FILE"
        Ok 20 FIELD #8, 20 AS Z$, 3 AS V$
        Ok 30 GET #8, C%
        Ok 40 IF LOC(8) > 25 THEN GOTO 90


LOF Function

The LOF function returns the number of 128-byte sectors in the file.


Syntax:

        X = LOF('file number')


Explanation:

For a file just opened for output, the number of 128-byte sectors is zero.


Example:

        Ok 100 X = LOF(5)
        Ok 110 IF X > 100 THEN PRINT "OPEN NEW FILE": GOTO 200


LOG Function

The LOG function returns the natural logarithm of a number.


Syntax:

        X = LOG('numeric expression')


Explanation:

The numeric expression must evaluate to greater than zero.


Example:

        Ok 10 REM This program finds the base-2 logarithm of 23
        Ok 20 PRINT LOG(23)/LOG(2)
        Ok RUN
         4.52356


LOG10 Function

The LOG10 function returns the base-10 logarithm of a number.


Syntax:

        X = LOG10('numeric expression')


Explanation:

The numeric expression must evaluate to greater than zero.


Example:

        Ok 10 X = LOG10(1000)
        Ok 20 PRINT X
        Ok RUN
         3


LPOS Function

The  LPOS function returns the position of the line printer print head  within 
the line printer buffer.


Syntax:

        LPOS( )


Explanation:

The  position returned is the count of the characters printed since  the  last 
Carriage  Return [CR] character. The BackSpace [BS] counts as -1. If you  have 
printed  control  characters that alter the position of the print  head,  this 
count will not reflect the true position of the head.


Example:

        Ok 10 X = 90
        Ok 20 IF LPOS(X) > 45 THEN GOTO 100


LPRINT Statement

The LPRINT statement directs output to a printer.


Syntax:

        LPRINT ['list of expressions']
        LPRINT USING 'format string expression';'list of expressions'


Explanation:

The  LPRINT statement works like the PRINT and PRINT USING statements in  this 
section,  except that output goes to a line printer. You can set  the  assumed 
width of the line printer with the WIDTH LPRINT statement. Initially, it is 72 
characters.  The format string expression must be separated from the  variable 
list with a semicolon [;]. The listed expressions must be separated by  commas 
[,].


Example:

        Ok 10 LPRINT USING "&######"; X$,Y,Z$,B


LSET Statement

The  LSET statement moves a string into a specified string  variable,  without 
reassigning the string variable.


Syntax:

        LSET 'string variable'='string expression'


Explanation:

LSET is commonly used to move data to file buffers, by LSETing into  variables 
mapped into file buffers by a previous FIELD statement. LSET is not limited to 
this use, however.

If  the  string expression takes fewer bytes than you assigned to  the  string 
variable  in a FIELD statement, LSET justifies the left margin, and  pads  the 
string to the right with spaces. If the string is longer than the destination, 
LSET  ignores  the  extra characters. If a string takes more  bytes  than  you 
assigned  it in the FIELD statement, characters on the right are dropped.  You 
must convert numbers to strings with MKD$, MKI$, or MKS$ before you LSET them. 
The counterpart of LSET is RSET.


Example:

        Ok 10 A$ = STRING$(20,"X")
        Ok 20 INPUT "REPLACE"; B$
        Ok 30 PRINT A$
        Ok 40 LSET A$ = B$
        Ok 50 PRINT A$
        Ok 60 GOTO 10
        Ok RUN
        REPLACE? 3434DfrE~%^
        XXXXXXXXXXXXXXXXXXXX
        343DfrE~%^
        REPLACE? 7474747474747474747474747474747
        XXXXXXXXXXXXXXXXXXXX
        74747474747474747474


MERGE Command

The MERGE command inserts a disk file into a program in memory.


Syntax:

        MERGE 'filename'


Explanation:

The  MERGE  command inserts a file on disk into a file already in  memory.  As 
long  as the line numbers of the 2 files are different, MERGE does  not  erase 
the original file. If any line numbers in the disk file duplicate line numbers 
in the file in memory, the disk lines replace the memory lines.

For additional information, see the explanation of the CHAIN command.


Example:

        Ok 10 PRINT "THIS IS THE ORIGINAL PROGRAM"
        Ok 20 PRINT "THIS LINE WILL BE DELETED BY THE MERGE"
        Ok 30 PRINT "THIS LINE STAYS BECAUSE IT HAS A UNIQUE LINE NUMBER"
        Ok SAVE ORIGINAL
        Ok 15 PRINT "THIS IS THE OVERLAY"
        Ok 20 PRINT "THIS LINE REPLACES LINE 20 IN THE ORIGINAL PROGRAM"
        Ok SAVE OVERLAY
        Ok OLD ORIGINAL
        Ok MERGE OVERLAY
        Ok RUN
        THIS IS THE ORIGINAL PROGRAM
        THIS IS THE OVERLAY
        THIS LINE REPLACES LINE 20 IN THE ORIGINAL PROGRAM
        THIS LINE STAYS BECAUSE IT HAS A UNIQUE LINE NUMBER


MID$ Function

The MID$ function returns a segment of a string.


Syntax:

        X$ = MID$('string expression','starting point'[,'length'])


Explanation:

MID$  returns  a string from another string. The starting point is  a  numeric 
expression  representing  the point in the original string  where  the  string 
segment  begins. The length is a numeric expression specifying the  length  of 
the  segment, in number of characters to the right of the starting  point.  If 
you  omit  the  length parameter, MID$ returns all the  characters  after  the 
starting point.

If the starting number is greater than the string is long, MID$ returns a null 
string. If the length of the segment is greater than the number of  characters 
to  the right of the starting point, all characters after the  starting  point 
return.  See also the RIGHT$ and LEFT$ functions. You can also use MID$  as  a 
statement; see the MID$ Statement in this section.


Example:

        Ok 10 X$ = "MR. JAMES GRAHAM SCOTT"
        Ok 20 Y$ = MID$(X$,18,5)
        Ok 30 PRINT Y$
        Ok RUN
        SCOTT


MID$ Statement

The MID$ statement replaces part of one string with another.


Syntax:

        MID$('string variable','starting point'[,'length'])=('string expr.')


Explanation:

MID$  imposes  a replacement string upon the original string, beginning  at  a 
given  starting  point.  Characters are replaced only to  the  length  of  the 
original string.

You  can  specify  the number of characters from  the  replacement  string  to 
replace  the  characters in the original string.  Otherwise,  the  replacement 
characters  substitute  for  the  original characters to  the  length  of  the 
original string or replacement string, whichever is shorter.

The number of characters replaced is the least of:

     1) The length argument.

     2) The  number of characters in the original string to the right  of  the 
        starting point (that is to say: length - [starting point] + 1).

     3) The length of the replacement.


Example:

        Ok 10 DAY$ = "MONWEDFRI"
        Ok 20 RESCHEDULE$ = "TUE"
        Ok 30 INPUT "COURSE NUMBER";C$
        Ok 40 IF RIGHT$(C$,3) ="003" THEN [LF]
                 MID$(DAY$,4,3) = RESCHEDULE$
        Ok 50 PRINT DAY$
        Ok RUN
        COURSE NUMBER? 53-003
        MONTUEFRI


MKD$, MKI$, MKS$ Functions

The  MKD$,  MKI$, and MKS$ functions convert numbers to strings,  for  use  in 
random file buffers.


Syntax:

        X$ = MKD$('double-precision expression')
        Y$ = MKI$''integer')
        Z$ = MKS$('single-precision expression')


Explanation:

MKI$ returns a 2-byte string. MKS$ returns a 4-byte string. MKD$ returns an 8-
byte string. As an option, MKD$ can also change the internal representation of 
a double-precision number from IEEE to Microsoft BASIC format. See Appendix E, 
"The option table", for more information.

You  must convert numbers to strings with these functions before you can  move 
them  into  a  random file buffer with RSET or LSET. The  CVD,  CVI,  and  CVS 
functions are the reverse of MKD$, MKI$, and MKS$.


Example:

        Ok 100 FINAL = (100/X) * (100 - Y)
        Ok 110 FIELD #2, 5 AS Z$, 5 AS B$
        Ok 120 LSET Z$ = MKI$(FINAL)
        Ok 130 LSET B$ = T$
        Ok 140 PUT #2
        ...


NAME Statement

The NAME statement renames a file.


Syntax:

        NAME 'old string expression' AS 'new string expression'


Explanation:

The NAME statement simply gives a new name to a file that already exists. NAME 
does  not alter the file or disk space in any way. Be sure that the  old  file 
exists and the new name does not; otherwise, an error occurs.


Example:

        Ok NAME "VERSION2.BAS" AS "FINAL.BAS"


NEW Command

The  NEW  command  clears a file from memory, and  optionally  names  the  new 
program.


Syntax:

        NEW [filename]


Explanation:

Use  NEW in preparation for writing a new program. If you have not  saved  the 
current file, you lose it if you clear it with NEW. If you use the  [filename] 
option, you can use the SAVE command later without a name.


Example:

        Ok 10 X = SQR(25)
        Ok 20 PRINT X
        Ok NEW
        Ok LIST


NEXT Statement

The NEXT statement marks the end of a FOR-NEXT loop.


Syntax:

        NEXT ['counter']{,counter}


Explanation:

The  NEXT  statement after the instructions in a FOR-NEXT loop  sends  program 
control to the beginning of the loop. The loop runs again if the criteria  for 
stopping it are not fulfilled: that is to say: if the counter variable is  not 
greater than the second numeric expression in the FOR statement.

Supplying  the  name of the counter variable is optional. The  NEXT  statement 
assumes  the  nearest  counter variable. If you have nested  loops,  you  must 
specify  which counter variable you are returning to at the end of the  loop's 
execution. Use NEXT to direct execution first to the nested loop, then to  the 
outer loop by specifying first the nested counter variable, then the outer.


Example:

        Ok 10 FOR Z = 1 TO 3
        Ok 20 PRINT "Y"
        Ok 30 FOR Q = 1 TO 2
        Ok 40 PRINT "X"
        Ok 50 NEXT Q,Z
        Ok RUN
        Y
        X
        X
        Y
        X
        X
        Y
        X
        X


OCT$ Function

The OCT$ function returns a string expression of an octal (base 8) number.


Syntax:

        X$ = OCT$('numeric expression')


Explanation:

OCT$  returns  a  string  that  is the  base-8  equivalent  of  a  decimal  or 
hexadecimal  value.  The  value of the decimal or  hexadecimal  expression  is 
rounded  to an integer before conversion. It must be in legal  integer  range,   
-32768 to 32767.

OCT$ is similar to HEX$ and STR$. HEX$ returns the character representation of 
a  hexadecimal (base 16) number. STR$ returns the normal (base  10)  character 
representation of a number.


Example:

        Ok 10 X$ = OCT$(3.4)
        Ok 20 PRINT X$
        Ok RUN
         3


OLD Command

The OLD command loads an existing program file into memory.


Syntax:

        OLD 'filename'


Explanation:

OLD  closes all open files, and erases any variables or data in memory  before 
loading  the  named file. Thus, OLD performs an implicit  NEW  command.  After 
loading, Personal BASIC returns to command level.

The filename is the name that you gave to the file when you saved it. You need 
not include the default filetype, BAS.


Example:

        Ok OLD TEST
        Ok      (Program TEST in now in your working storage.)


ON Statement

The  ON statement transfers program control to one of a list of line  numbers, 
depending  on the computed result of the numeric expression. The ON  statement 
has 2 forms.


Syntax:

        ON 'numeric expression' GOTO  'label'{,'label'}
        ON 'numeric expression' GOSUB 'label'{,'label'}


Explanation:

The  value  of  the  numeric expression  determines  where  program  execution 
transfers.  If the expression evaluates to 1, ON branches to the first  label. 
If it evaluates to 2, ON branches to the second label, and so on.

You  can specify an optional label to control the action taken when the  value 
of  the  expression falls outside the range of line numbers. If  you  use  the 
optional  label and the numeric expression evaluates to zero or a  value  less 
than  or greater than the number of line numbers, control passes to  the  next 
statement  in  order, with no error. Test the value of the  expression  before 
writing an ON statement. Non-integer values round to the nearest whole number.

In  the ON-GOSUB statement, each numeric expression must be the number of  the 
first  line  of a subroutine. The RETURN statement in the  subroutine  returns 
control to the first executable statement following the ON statement. There is 
no limit to the line numbers that you can use in an ON statement, and you  can 
write an ON statement anywhere in your program.


Example:

        Ok 10     X = 1
        Ok 20     ON X GOTO 70,80,90,990
        Ok 70     PRINT "SEASON TO DATE:"X + 1
        Ok 80     PRINT "SEASON TO DATE:"X + 2
        Ok 90     PRINT "SEASON TO DATE:"X + 3
        Ok 120    X=X+1: GOTO 20
        Ok 990    END
        Ok RUN
        SEASON TO DATE:  2
        SEASON TO DATE:  3
        SEASON TO DATE:  4
        SEASON TO DATE:  4
        SEASON TO DATE:  5
        SEASON TO DATE:  6


ON ERROR GOTO Statement

The  ON ERROR GOTO statement enables you to trap run-time errors,  and  branch 
control to a line number when an error occurs.


Syntax:

        ON ERROR GOTO 'line number'


Explanation:

ON ERROR GOTO lets you trap run-time errors by jumping to a given line  number 
when Personal BASIC detects an error.

You can disable error trapping, or restore Personal BASIC's own error handling 
in an error trapping routine, by using ON ERROR GOTO 0.

When  you  use ON ERROR GOTO 0 in an error trapping  routine,  Personal  BASIC 
prints  its  original error message and then stops. It is a good  practice  to 
always use ON ERROR GOTO 0 in an error trapping routine, so that you can  trap 
unexpected errors.

If  you  have not written an error trap for numeric overflow,  Personal  BASIC 
prints its error message and continues running. However, if you have an  error 
trap, Personal BASIC prints its message and then stops.

The following errors are trappable with ON ERROR GOTO: 4-6, 9, 11, 14, 15, 23, 
50, 52-58, 61-64, 67, 99, 102, 107, 108. See Appendix D for the error  message 
text.


Example:

        Ok 80 ON ERROR GOTO 100


OPEN Statement

The OPEN statement lets you input and output to a file or device.


Syntax:

        OPEN 'mode',[#]'file number','filename'[,'record length']


Explanation:

You  must OPEN a disk file before you can move data into it or out of it.  The 
OPEN  statement assigns the file an I/O buffer, and determines the mode  under 
which the file is accessible to I/O.

The file number is an integer expression with a value between 1 and 15. A file 
number  belongs to a file for as long as it is open. Closing a file frees  its 
number for reassignment. The record length is an integer expression that  sets 
the record length for random files. It is optional. The default length is  128 
bytes. A record length given for a sequential file is ignored.

The file mode is either sequential output or sequential input, or random input 
and output. Specify the mode with one of the following initials:

        O  Output for sequential files
        I  Input  for sequential files
        R  Input and output for random files

When  you  open  a  file for output in "O" mode, if the  file  did  not  exist 
already,  it is created. If it did exist, the existing file is erased,  and  a 
new  file  by that name is created. In "I" mode, the file must  exist,  or  an 
error results. In "R" mode, if the file does not exist, it is created.


Example:

        Ok 10 OPEN "R", #1, "FUNDS"
        Ok 20 FIELD #1, 10 AS V$, 10 AS X$, 30 AS N$
        Ok 30 INPUT "ENTER A 4-DIGIT CODE", CODE!
        Ok 40 GET #1, CODE!


OPTION BASE Statement

The OPTION BASE statement sets the base for array dimensions.


Syntax:

        OPTION BASE '0 or 1'


Explanation:

You  use  OPTION BASE to set the minimum value for array subscripts  within  a 
dimension. The default base is zero; thus, the first element in an array has a 
subscript  of  zero. You can set the array dimensions so they begin at  1,  or 
reset them to zero.

You  can use OPTION BASE as many times as required. See the DIM statement  and 
Section 2.2.3.


Example:

        Ok 10 OPTION BASE 1
        Ok 20 DIM A%(10)
        Ok 30 OPTION BASE 0
        Ok 40 DIM B%(10)

        A% now has 10 elements, 1-10. B% has 11 elements, 0-10.


OUT Statement

The OUT statement sends a byte to a CPU output port.


Syntax:

        OUT 'integer expression','integer expression'


Explanation:

The first integer expression is the port number. The second expression is  the 
byte that you are sending to the port; it must evaluate to an integer  between 
0 and 65535.


Example:

        Ok 100 IF X% > 5 THEN OUT 9,(X-2)


PEEK Function

The PEEK function returns the contents of a memory location.


Syntax:

        X% = PEEK('memory location')


Explanation:

PEEK  returns  the  contents  of byte at the  specified  location.  The  value 
returned is a decimal integer from 0 to 255. The memory location is an integer 
from 0 to 65535. The complement of PEEK is the POKE statement.


Example:

        Ok 100 BYTE% = PEEK(234)


POKE Statement

The POKE statement writes a byte of data to a memory location.


Syntax:

        POKE 'location to poke','data to poke'


Explanation:

POKE  stores a value as a 1-byte integer. The location to poke is an  absolute 
address  expressed  as  an integer from 0 to 65535. The data  to  poke  is  an 
integer  expression  from 0 to 255. If the data expression  evaluates  outside 
this range, POKE stores the low-order byte of the result. For example:

        Ok 10 POKE X%, 257

has the same effect as:

        Ok 10 POKE X%, 1

The  complement  of  POKE  is PEEK. You can use  PEEK  and  POKE  for  passing 
arguments and data to machine-language subroutines.


Example:

        Ok 100 FOR LOC% = 1 TO LEN(OUT.MSG$)
        Ok 120 POKE MSG.LOC% + LOC%, ASC(MID$(OUT.MSG$,LOC$))
        Ok 130 NEXT LOC%


POS Function

The  POS function returns the current position of the cursor on a  console  or 
printer.


Syntax:

        X = POS('dummy argument')


Explanation:

The leftmost position of the cursor is zero. POS does not necessarily give the 
physical position of the print head. See also the LPOS function.


Example:

        Ok 40 X = POS(0)
        Ok 50 PRINT "THE PRINT HEAD IS AT COLUMN: "; X
        Ok 60 IF WIDTH.LINE < POS(0) THEN WIDTH.CHR = X


PRINT Statement

The PRINT statement outputs data to the console.


Syntax:

        PRINT ['expression' {', or ;' 'expression'} [', or ;']]


Explanation:

PRINT  outputs  the  expressions to the console. You can  use  any  number  of 
expressions  with the PRINT statement, separated by a comma [,]  or  semicolon 
[;].

The  punctuation used to separate the expressions determines the  position  of 
the expressions on the screen. Personal BASIC divides a line into print zones, 
consisting  of  14  spaces  each. When you use a comma  [,]  to  separate  the 
expressions  in  the PRINT statement, Personal BASIC  prints  each  expression 
individually  at  the next available print zone. If you use a  semicolon  [;], 
Personal  BASIC  prints  string  expressions  consecutively,  with  no  spaces 
separating the expressions. Numerical expressions are printed together, with a 
space for the sign.

If  you end a list of expressions with a comma [,], Personal BASIC  spaces  to 
the next print zone, but does not move to a new line. If you end a list with a 
semicolon  [;],  Personal  BASIC  leaves the cursor at the  end  of  the  last 
expression.

A question mark [?] can be used in Personal BASIC programs in place of  PRINT. 
? A means the same as PRINT A.


Example:

        Ok 10 PRINT "TESTING Personal BASIC"
        Ok 20 PRINT
        Ok 30 A$ = "ONE" : B$ = "TWO" : C$ = "THREE"
        Ok 35 A=23:B=567:C=5
        Ok 40 PRINT A$,B$,C$
        Ok 50 PRINT A$;B$;C$
        Ok 60 PRINT A,B,C
        Ok 70 PRINT A;B;C
        Ok 80 END
        Ok RUN
        TESTING Personal BASIC

        ONE           TWO            THREE
        ONETWOTHREE
         23            567            5
         23  567  5


PRINT# Statement

The PRINT# statement outputs data to a disk file.


Syntax:

        PRINT# 'file number','expression'{,'expression'}


Explanation:

The  PRINT#  statement writes expressions to the file specified  by  the  file 
number.  The  file  number is the number that you gave to the  file  when  you 
opened  it.  Each  PRINT# statement executed creates  a  single  record.  Each 
expression used in the PRINT# statement creates a single field.

You can use any number of expressions with the PRINT# statement, and  separate 
each one with a comma [,] or semicolon [;].

PRINT#  writes  the data to the file exactly as it would print on  the  screen 
using the PRINT statement.

You  must  express  exactly  how  you want the  data  to  appear  on  disk  by 
punctuating it properly.

For example, say:

        X$ = "Lewis"
        Z$ = " C. S."

and you want to write:

        Lewis, C. S.

to disk. Since neither variable contains a comma [,], either before "Lewis" or 
after " C. S.", the statement:

        Ok PRINT#1,X$;Z$

writes the data to disk as:

        Lewis C. S.

If you want to insert a comma [,] as a delimiter, you must use the statement:

        Ok PRINT#1,X$;",";Z$

with the comma as a literal string in quotation marks [","].

For more information, see Section 4.2.


Example:

        Ok 50 PRINT#FIVE.TEX, A$,B$,C$


PRINT USING Statement

The PRINT USING statement prints output according to a format.


Syntax:

        PRINT USING 'string expression';'list of expressions'
        PRINT#'file number', USING 'string expression';'list of expr.'


Explanation:

The  PRINT  USING statement prints the data on the screen.  The  PRINT#  USING 
statement  prints  the data on a disk file. You can print strings  or  numbers 
with either statement. For the PRINT# USING statement, the file number is  the 
number that you give to the file when you open it.

For both statements, the string expression in quotation marks ["] is a list of 
characters that determine the fields and formats of printed data. The list  of 
expressions contains the items to print, separated by commas [,] or semicolons 
[;].  If the list ends with a semicolon [;], the cursor is left at the end  of 
the  last expression. The characters in the format specification are  replaced 
by the data in the print list, unless they are literal characters.

The  following table summarizes Personal BASIC's formatting  characters.  They 
are described in detail in Section 4.2.1.

Table 5-2. String field formatting characters

Char.   Explanation
-----   -----------
  !     Tells  the  statement to print the first character of  each  specified 
        string.
\chars\ Chars  plus 2 indicates the total number of characters to  print  from 
        the specified string.
  &     Specifies a variable-length string field.
  #     Represents each digit position in a numeric field.
  .     Inserts a zero to fill digit positions as necessary.
  +     Prints  the  sign  of the number, plus [+] or minus  [-],  before  the 
        printed number.
  -     Prints negative numbers with a trailing minus sign [-].
  **    Fills leading spaces in the numeric field with asterisks [*].
  $$    Prints a dollar sign [$] to the immediate left of the printed number.
  **$   Fills leading spaces with asterisks [*] and inserts a dollar sign  [$] 
        to the left of the number.
  ,     Inserts  a comma [,] between every 3rd digit on the left side  of  the 
        decimal point [.].
  ^^^^  Specifies exponential format.
  _     (Underscore: _ ) Prints the next character as a literal character.

You  can  include  string  constants in the format string,  as  shown  in  the 
following example.


Example:

        Ok 10 PRINT USING "THIS IS FILE _##:";4%
        Ok RUN
        THIS IS FILE #4


PUT Statement

The PUT statement writes a record from a buffer to a random disk file.


Syntax:

        PUT [#]'file number'[,'record number']


Explanation:

The  file number is the number that you gave to the file when you  opened  it. 
The  record number is optional. If you do not give a record number,  PUT  uses 
the  next  record number in sequence after the last GET or  PUT.  The  largest 
valid record number is 32767.

You  should use LSET or RSET before a PUT, to place the data into  the  random 
buffer.


Example:

        Ok 100 LSET Q$ = X$
        Ok 120 PUT#2, RCORD%


RANDOMIZE Statement

The RANDOMIZE statement seeds the random number generator.


Syntax:

        RANDOMIZE ['numeric expression']


Explanation:

You  use  RANDOMIZE with the RND function to generate random numbers.  If  you 
omit  the optional numeric expression, Personal BASIC asks for a  random  seed 
number on which to base RANDOMIZE.

If  you  do  not use RANDOMIZE at the beginning of a program  that  relies  on 
random  numbers, the RND function returns the same sequence of  numbers  every 
time that you run the program. See the RND function for further information on 
generating random numbers.


Example:

        Ok 10 RANDOMIZE 45
        Ok 20 FOR X = 1 TO 10
        Ok 30 PRINT RND
        Ok 40 NEXT X
        Ok RUN
         .957395
         .427143
         .806267
         .0206223
         .86628
         .886706
         .435054
         .199773
         .505868
         .801594


READ Statement

The READ statement assigns values from a DATA statement to variables.


Syntax:

        READ 'variable'{,'variable'}


Explanation:

The  READ statement and DATA statement are always used together. READ  assigns 
the  values listed in DATA to a corresponding list of variables, one  by  one. 
The  variables  can be numeric and string. They must agree in  type  with  the 
constant values in the DATA statement; otherwise, an error results.

You  can  use  one READ with several DATA statements, or vice  versa.  If  the 
number of values in the DATA statement is greater than the number of variables 
in  the  READ  statement,  the next READ  statement  picks  up  the  remaining 
constants  where the first left off, and assigns them to the variables in  its 
list.  If there are no subsequent READ statements, however, the extra data  is 
ignored.

If  there  are fewer values in the DATA statement than variables in  the  READ 
statement,  the  next data statement is found and read. If there is  none,  an 
out-of-data error results.

You  can use the RESTORE statement to re-read DATA items from the start  of  a 
specified line number. See the RESTORE and DATA statements in this section.


Example:

        Ok 10 READ X,Y,Z
        Ok 20 RESTORE
        Ok 30 AVERAGE = (X + Y + Z)/3
        Ok 40 DATA 23.4, 89.2, 77
        Ok 50 PRINT AVERAGE
        Ok 60 READ X,Y,Z
        Ok 70 PRODUCT = X * Y * Z
        Ok 80 PRINT PRODUCT
        Ok 90 END
        Ok RUN
         63.2
         160721


REM Statement

The REM statement introduces a remark.


Syntax:

        REM 'remark'


Explanation:

Remarks  help  clarify the logic of a program. Remarks appear in  the  program 
listing as written, but they are not executable. Remarks can be as long as 255 
characters. If you write a remark longer than the width of the screen, you can 
extend the line with a Line-Feed [LF].

You can use a single apostrophe ['] to show a remark at the end of a line.  If 
you  branch  into  a REM line with a GOTO  statement,  the  program  continues 
executing at the first executable line after the REM.

The single apostrophe ['] character has the same effect as REM. For example:

        Ok 100 'This is a comment

is a valid statement.


Example:

        Ok 10 REM THIS PROGRAM FINDS THE SQUARE OF A NUMBER
        Ok 20 INPUT "ENTER A NUMBER TO BE SQUARED";X
        Ok 30 S = X * X
        Ok 40 PRINT S
        Ok 50 'RETURN FOR ANOTHER NUMBER
        Ok 60 GOTO 20
        Ok 70 END


RENUM Command

The RENUM command renumbers program lines.


Syntax:

        RENUM ['new first number'][,'new first line'][,'increment']


Explanation:

If your program line numbers are irregular because you have inserted new lines 
between existing lines, you can renumber the entire program without having  to 
change GOTO or other address-dependent statements.

Used  alone,  RENUM numbers the first line of the program  10  and  increments 
succeeding lines by 10. You can supply a new first number, which is the number 
where you want the renumbering to begin. You can also supply a new first line, 
which is the line number where you want the renumbering to begin.

You can also specify an increment for line numbering. For example:

        RENUM 10,30,10

begins  numbering at the old line 30, assigns it the line number 10, and  sets 
an increment of 10. The following line numbers are 20, 30, 40, and so on.

You  can use any of the RENUM options alone. However, if you specify  only  an 
increment, leave commas [,] as place markers to show that you are supplying an 
incremental  value,  rather  than a new first number or new  first  line.  For 
example, RENUM ,,20.

RENUM  adjusts all line number references in GOTO, GOSUB, THEN,  ON-GOTO,  and 
ON-GOSUB  statement,  to  reflect the new line numbers. If  you  have  a  non-
existent line in one of these statements, an error results.

You cannot use RENUM to change the order of program lines.

Additional documentation:
When  you  RENUMber programs, you must have enough free space in  memory.  The 
amount  of  free  space you need is 2 bytes per  numbered  program  line.  For 
example,  a program with 1200 program lines needs at least 2400 bytes of  free 
memory for RENUM to work. Use the FRE function to find the bytes available. 

You can now re-order lines and move program blocks with RENUM. The new  syntax 
is as follows:

        RENUM ['new line'][',increment'][',start line'][',end line']

Notice  the first 2 parameters refer to the new line numbers, the second 2  to 
the old. The new first line number is the new number you give an old line. The 
default  is 10. For the increment, the default is also 10. The start  line  is 
where  you want renumbering to begin. The default is line 0. The end  line  is 
the  line  where renumbering stops. The default is the end of the  program  -- 
take  care  not  to renumber your whole program accidentally.  RENUM  with  no 
arguments or only the new first line number behaves as before.

Useful  hint:  you  can  use RENUM with SAVE to  duplicate  line  numbers,  as 
follows:

        SAVE CALC, 100-200
        RENUM 1000,,100,200
        MERGE CALC

This  will result in lines 100-200 repeated both in their  original  positions 
and  as lines 1000-1100. BE CAREFUL: new line numbers overwrite old  identical 
line numbers. You might lose a line you wanted.


Example:

        Ok 15 X = 5
        Ok 20 Z = 3
        Ok 25 Y = 10
        Ok 30 PRINT X + Y - Z
        Ok RENUM

        10 X = 5
        20 Z = 3
        30 Y = 10
        40 PRINT X + Y -Z


REPLACE Command

The REPLACE command replaces an old version of a file with a new version.


Syntax:

        REPLACE ['filename'][,'line number list']


Explanation:

You  use REPLACE with OLD. After you have loaded an old file and  revised  it, 
REPLACE sends the revised version onto disk, replacing the old version.

If  you  specify a filename, REPLACE saves the source program  in  'filename', 
rather  than  the  current program name. You can save parts of  a  program  by 
specifying a line number list.

In general, REPLACE works exactly like SAVE, except that with REPLACE the name 
of  the  file that you want to save can already belong to  another  file.  The 
example  brings program COUNTPROG into working storage, adds or replaces  line 
130, and stores the revised program in permanent storage on disk.


Example:

        Ok OLD COUNTPROG
        Ok 130 IF X = 10 THEN END
        Ok REPLACE

(ROCHE>  I hope that I am not the only one to notice that "COUNTPROG" is a  9-
characters filename...)


RESET Statement

The RESET statement allows you to change disks while the program is running.


Syntax:

        RESET


Explanation:

RESET resets the CP/M disk system, then performs a log-in on the disk that was 
current  before your program executed the RESET. For example, if  the  current 
disk is B, after you use RESET the current disk is B, but both drives A and  B 
will be logged in.

You must ensure that no files are open before you change disks. After you make 
the  change,  use  the RESET statement so your program  can  continue  without 
rebooting.

(ROCHE> So, this means that Personal BASIC was programmed for CP/M-86,  itself 
a  direct  Intel 8086 translation of CP/M 2.2 (using BDOS  Version  2),  since 
CP/M-86 Plus and Concurrent CP/M (both using BDOS Version 3) no longer need to 
reset the disk system when changing disks...)


Example:

        200 RESET


RESTORE Statement

The RESTORE statement re-reads DATA statements.


Syntax:

        RESTORE ['line number']


Explanation:

RESTORE  lets you use more than one READ for a single DATA statement. After  a 
READ,  a  RESTORE  finds  the first item in  the  first  DATA  statement,  and 
establishes it as the starting point for the next READ statement.

You  can specify any DATA statement in the program as the object of a  RESTORE 
statement,  by  giving  its line number. The line number that  you  give  with 
RESTORE  does not have to refer to a DATA statement, or even exist.  The  next 
READ statement finds the next DATA statement after or equal to the line number 
specified.


Example:

        Ok 10 READ X,Y,Z
        Ok 20 RESTORE
        Ok 30 AVERAGE = (X + Y + Z)/3
        Ok 40 DATA 23.4, 89.2, 77
        Ok 50 PRINT AVERAGE
        Ok 60 READ X,Y,Z
        Ok 70 PRODUCT = X * Y * Z
        Ok 80 PRINT PRODUCT
        Ok 90 END
        Ok RUN
         63.2
         160721


RESUME Statement

The RESUME statement continues execution after an error.


Syntax:

        RESUME [0]
        RESUME NEXT
        RESUME 'line number'


Explanation:

After  an error has been detected and trapped, RESUME restores the program  to 
normal execution. You write a RESUME statement at the end of an error trapping 
routine,  and  only there. A RESUME statement executed anywhere except  in  an 
active error trap causes an untrappable error.

RESUME  used by itself, or followed by a zero, sends program control  back  to 
the statement where the error occurred.

RESUME  NEXT  sends program control to the statement following  the  one  that 
caused the error.

RESUME 'line number' sends program control to a given line number.


Example:

        Ok 100 ON ERROR GOTO 700
        ...
        Ok 700 IF (ERR = 300) AND (ERL = 150) THEN PRINT
           "MINIMUM NUMBER OF DEPENDENTS IS 1": RESUME 140


RETURN Statement

The  RETURN statement transfers control from a subroutine back to the  calling 
program.


Syntax:

        RETURN


Explanation:

RETURN  transfers execution of a program to the first executable statement  in 
the  main  program following a subroutine call. The subroutine call can  be  a 
GOSUB or ON-GOSUB statement.


Example:

        Ok 10 GOSUB 100
        Ok 20 REM RETURN POINT OF SUBROUTINE
        Ok 30 PRINT A
        Ok 40 GOTO 200
        Ok 50 '
        Ok 100 REM START OF SUBROUTINE
        Ok 110 A=5^6
        Ok 120 RETURN
        Ok 130 '
        Ok 200 END
        Ok RUN
         15625


RIGHT$ Function

The RIGHT$ function returns the rightmost characters of a string.


Syntax:

        X$ = RIGHT$('target string','number of characters')


Explanation:

RIGHT$  assigns  the number of characters that you specify on the right  of  a 
target  string to a new string variable. If the number of characters that  you 
ask  for  is  greater than or equal to the length of the  string,  the  entire 
string returns; if you ask for zero characters, a null string returns.


Example:

        Ok 10 A$ = "Marketing Strategies"
        Ok 20 B$ = "Regional Responses"
        Ok 30 C$ = "Test Results"
        Ok 40 INPUT "CATALOG NUMBER"; CATALOG$
        Ok 50 IF RIGHT$(CATALOG$,1) = "1" THEN PRINT "YOU HAVE CHOSEN"
        Ok 60 PRINT "TESTPRO CATALOG SERIES1"
        Ok 70 PRINT "PLEASE CHOOSE FROM THE FOLLOWING HEADINGS:  "
        Ok 80 PRINT A$
        Ok 90 PRINT B$
        Ok 100 PRINT C$
        Ok RUN
        CATALOG NUMBER? CASPAR BLEEBLEBOX CATALOG 201
        YOU HAVE CHOSEN
        TESTPRO CATALOG SERIES1.
        PLEASE CHOOSE FROM THE FOLLOWING HEADINGS:
        Marketing Strategies
        Regional Responses
        Test Results


RND Function

The RND function generates and returns a random number.


Syntax:

        X = RND [('numeric expression')]


Explanation:

RND returns a uniformly-distributed random number in the open interval between 
zero  and 1. Unless you write a RANDOMIZE statement before the RND  statement, 
the same sequence of random numbers always generates on every run.

RND  acts differently depending upon whether the numeric expression  evaluates 
to a positive number, negative number, or zero:

      - RND  ('positive  expression') returns the next number in  the  current 
        sequence.

      - RND  ('negative expression') reseeds the random number generator  with 
        the  negative number, and returns the first random number in  the  new 
        sequence.

      - RND  (0) returns the last random number generated,  without  affecting 
        the current sequence.

The numeric expression is optional. If you do not give one, RND acts as if you 
had given a positive expression as an argument.


Example:

        Ok 10 RANDOMIZE
        Ok 20 X = RND
        Ok 30 ROLL$ = "TAILS"
        Ok 40 IF X > .5 THEN ROLL$ = "HEADS"
        Ok 50 INPUT "HEADS OR TAILS";R$
        Ok 60 IF R$ = ROLL$ THEN PRINT "YOU WIN" ELSE PRINT "YOU LOSE"
        Ok RUN
        Random number seed (-32768 to 32767)? 2
        HEADS OR TAILS? HEADS
        YOU WIN


RSET Statement

The RSET statement moves a string into a specified string variable without re-
assigning the string variable.


Syntax:

        RSET 'string variable'='string expression'


Explanation:

RSET  is  commonly used to move data to file buffers by  resetting  them  into 
variables dropped into file buffers by a previous FIELD statement.

If  the  string  being  moved is shorter than  the  destination,  RSET  right-
justifies  the string and pads the left with spaces. If the string  is  longer 
than the destination, RSET ignores the extra characters.

You  must  RSET or LSET numbers before you can use them with  MKD$,  MKI$,  or 
MKS$.


Example:

        Ok 10 A$ = STRING$(20,"X")
        Ok 20 INPUT "REPLACE"; B$
        Ok 30 PRINT A$
        Ok 40 RSET A$ = B$
        Ok 50 PRINT A$
        Ok 60 GOTO 10
        Ok RUN
        REPLACE? 3434DfrE~%^
        XXXXXXXXXXXXXXXXXXXX
                  343DfrE~%^
        REPLACE? 7474747474747474747474747474747
        XXXXXXXXXXXXXXXXXXXX
        74747474747474747474


RUN Command

The RUN command executes a program.


Syntax:

        RUN
        RUN 'filename'
        RUN 'filename, line number'
        RUN ', line number'


Explanation:

Written  alone,  RUN executes the program in memory from the start.  You  have 
several options that determine where the program begins running.

With the second syntax, RUN 'filename', RUN loads a disk file into memory  and 
runs  it  from the start. The filename is the name that you gave to  the  file 
when  you saved it. The default filetype BAS is assumed. RUN closes  all  open 
files, and clears memory before bringing in the file on disk.

With the 3rd syntax, RUN 'filename, line number', RUN loads the file and  runs 
it from the line number specified.

The  4th syntax, RUN ', line number', runs the current program from  the  line 
number specified.


Example:

        Ok 10 FOR Y = 1 TO 5
        Ok 20 X = X + 1
        Ok 30 PRINT X
        Ok 40 NEXT Y
        Ok RUN
         1
         2
         3
         4
         5


SAVE Command

The SAVE command saves a program on disk.


Syntax:

        SAVE ['filename'][,'line number list']


Explanation:

To make a file permanent, you must SAVE it. The filename is the name that  you 
assign  to  the file. You do not need to supply a filetype;  filetype  BAS  is 
assumed.  If  the filename already belongs to another file, an  error  occurs. 
SAVE does not replace an old file in memory with a new version. Commonly,  you 
use SAVE to save a file that you just created with NEW, and REPLACE to save  a 
file that you summoned with OLD.


Example:

        Ok SAVE MERGEFILE

(ROCHE>  I hope that I am not the only one to notice that "MERGEFILE" is a  9-
characters filename...)


SGN Function

The SGN function returns the sign of a number.


Syntax:

        X = SGN('numeric expression')


Explanation:

SGN  returns 1 if the numeric expression is positive, -1 if the expression  is 
negative, and 0 if the expression evaluates to zero.


Example:

        Ok 10 INPUT "CARGO CAPACITY"; X
        Ok 20 INPUT "TONNAGE"; Y
        Ok 30 INPUT "VOLUME"; V
        Ok 40 C = X + Y - V
        Ok 50 IF SGN(C) > 0 THEN PRINT "SUFFICIENT SPACE": GOTO 100
        Ok 60 PRINT "INSUFFICIENT SPACE.  CAN LOAD BE DIVIDED?"
        Ok RUN
        CARGO CAPACITY? 23
        TONNAGE? 14
        VOLUME? 450.5
        INSUFFICIENT SPACE.  CAN LOAD BE DIVIDED?


SIN Function

The SIN function returns the sine of its argument expressed in radians.


Syntax:

        X = SIN('numeric expression')


Explanation:

The  SIN  function  assumes that the expression is an  angle  in  radians.  To 
convert  degrees  to  radians, multiply by PI/180, where PI  =  3.141593.  SIN 
converts integers to real numbers, and returns a single-precision real number.


Example:

        Ok 10 PRINT SIN(23)
        Ok RUN
        -.84622


SPACE$ Function

The SPACE$ function returns a string of spaces.


Syntax:

        X$ = SPACE$('numeric expression')


Explanation:

SPACE$  returns as many spaces as you specify in the numeric  expression.  The 
value of the expression must be in the range 0 to 255.


Example:

        Ok 10 X = 10
        Ok 20 FOR V = 1 TO 5
        Ok 30 PRINT SPACE$(X); "|"
        Ok 40 NEXT V
        Ok 50 FOR Z = 1 TO 21
        Ok 60 PRINT "-";
        Ok 70 NEXT Z
        Ok RUN
                  |
                  |
                  |
                  |
                  |
        ---------------------

Note:  If you want to generate a number of spaces purely for printing,  it  is 
more efficient to use the SPC(X) function.


SPC Function

The SPC function outputs spaces to a PRINT statement.


Syntax:

        PRINT SPC('numeric expression')


Explanation:

SPC  prints  as  many spaces as you specify in  the  numeric  expression.  The 
expression must evaluate to the range -32768 to 32767. If the number of spaces 
is  greater  than  the width of the printer, the value  used  is  the  numeric 
expression  MOD  width.  For  example, if the width  is  72  and  the  numeric 
expression  equals 100, 28 spaces will be inserted. If the numeric  expression 
is > 255, the number of spaces is n MOD 255.

You use SPC only with the PRINT, LPRINT, and PRINT# statements.


Example:

        Ok 10 PRINT "ALPHABET"
        Ok 20 PRINT
        Ok 30 PRINT "A"SPC(3)"a"SPC(7)"B"SPC(3)"b"SPC(7)"C"SPC(3)"c"
        Ok RUN
        ALPHABET

        A   a       B   b       C   c


SQR Function

The SQR function returns the square root of a number.


Syntax:

        X = SQR('numeric expression')


Explanation:

The number must not be negative. SQR returns a real number.


Example:

        Ok 10 PRINT SQR(9)
        Ok RUN
         3


STEP Command

The STEP command executes a program line by line.


Syntax:

        STEP
        STEP 'filename'
        STEP 'filename, line number'
        STEP ',line number'


Explanation:

Written alone, STEP runs the program in memory from the start, single-stepping 
line  by line. The second syntax, STEP 'filename', brings a file  into  memory 
and begins stepping through it from the start.

Written  with  the 3rd syntax, STEP brings a program into  memory  and  begins 
stepping  through it at the line number specified. With the 4th  syntax,  STEP 
steps through the current program, beginning at the specified line number.

Before  a  line  executes,  Personal BASIC prints the line  and  waits  for  a 
Carriage Return [CR]. A Carriage Return executes the line. To exit from  STEP, 
use the CONT command.


Example:

        Ok 10 X = 9
        Ok 20 PRINT X
        Ok 30 PRINT "HOW DO YOU DO?"
        Ok 40 END
        Ok STEP, 10
        s  10     X = 9
        Br [CR]
        s  20     PRINT X
         9
        Br [CR]
        s  30     PRINT "HOW DO YOU DO?"
        Br [CR]
        HOW DO YOU DO?
        s  40     END
        Br CONT


STOP Statement

The STOP statement stops program execution.


Syntax:

        STOP


Explanation:

After a STOP, the program is at break level. You can stop a program  anywhere. 
Unlike  END, STOP leaves files open, enters Break mode and can  be  continued, 
and  prints  the message "STOP". A CONT command, explained  in  this  section, 
resumes program execution.


Example:

        Ok 10 A=4:B=6:C=8
        Ok 20 PRINT A, A*B
        Ok 30 STOP
        Ok 40 PRINT C*A
        Ok 50 END
        Ok RUN
         4             24
        Stop at line 30
        Br CONT
         32


STR$ Function

The   STR$  function  returns  a  string  containing  the  decimal   character 
representation of its argument.


Syntax:

        X$ = STR$('numeric expression')


Explanation:

The string returned contains the standard representation of the expression. It 
contains the characters that would print if a PRINT statement was executed.

For  positive  numbers, STR$ adds a leading blank for the plus sign  [+],  and 
STR$  deletes any space that follows a number. See also the complementary  VAL 
function, and OCT$ and HEX$.


Example:

        Ok 10 ZIPCODE = 91889
        Ok 20 PRINT STR$(ZIPCODE) + " (CALIFORNIA)"
        Ok RUN
         91889 (CALIFORNIA)


STRING$ Function

The  STRING$ function returns a string of a given length. The  characters  are 
defined by the second argument.


Syntax:

        X$ = STRING$('numeric expression','numeric or string expression')


Explanation:

The first numeric expression is the length of the string that STRING$ returns. 
It  must be in the range 0 to 255. You can use a numeric or string  expression 
for  the  second parameter. A numeric expression must be an ASCII code  for  a 
character. A string expression can be of any kind. STRING$ returns a string of 
a  given  length consisting of the character for the given ASCII code  or  the 
first character of the string expression.

STRING$ produces less memory fragmentation and works significantly faster than 
concatenation.  When  building  a  string containing  a  number  of  different 
characters,  it is more efficient to use STRING$ or SPACE$ to create a  string 
of  the required length, and then use MID$ to move individual characters  into 
the string than to concatenate.


Example:

        Ok 20 Z$ = STRING$(20,"*")
        Ok 30 PRINT Z$
        Ok RUN
        ********************


SWAP Statement

The SWAP statement trades the values of 2 variables.


Syntax:

        SWAP 'first variable','second variable'


Explanation:

You can swap any type of variable but the variables must be of the same  type. 
You can swap array variables, but not arrays themselves.

        SWAP A%(3), B%(7,5)     Is okay
        SWAP A%(), B%()         Does not work


Example:

        Ok 10 X$ = "TOM BRENTMEYER"
        Ok 20 Y$ = "SUSAN STEIGER"
        Ok 30 O$ = "FORMER"
        Ok 40 C$ = "CURRENT"
        Ok 50 M$ = " MARKETING MANAGER:  "
        Ok 60 PRINT O$,M$,X$
        Ok 70 SWAP X$, Y$
        Ok 80 SWAP O$, C$
        Ok 90 PRINT O$,M$,X$
        Ok RUN
        FORMER MARKETING MANAGER:  TOM BRENTMEYER
        CURRENT MARKETING MANAGER:  SUSAN STEIGER


SYSTEM Command

The SYSTEM command leaves Personal BASIC and returns to CP/M.


Syntax:

        SYSTEM


Explanation:

Unless  you save the file you are working with, it is lost when you  exit  the 
Personal  BASIC interpreter. SYSTEM closes all files and returns you  to  CP/M 
command level.


Example:

        Ok SYSTEM
        A>


TAB Function

The TAB function moves the cursor to a given tab position.


Syntax:

        PRINT TAB('tab position')


Explanation:

TAB is used with PRINT, LPRINT, and PRINT#.

The  tab position must evaluate to the range -32768 to 32767. If  the  current 
print  position is already beyond the tab position that you specify, TAB  goes 
to the next line and stops at the tab position that you specify. The  leftmost 
position  is  space 1; the rightmost is defined by a WIDTH statement.  If  the 
position  evaluates  greater  than  255, the position is n  MOD  256.  If  the 
position is greater than or equal to the width, n is n MOD width.


Example:

        Ok 10 PRINT "1985 QUARTERLY EARNINGS"
        Ok 20 PRINT
        Ok 30 PRINT TAB (10)"WINTER"
        Ok 40 PRINT TAB (70)"Too FAR"
        Ok 50 PRINT TAB (100)"SUMMER"
        Ok 60 END
        Ok RUN
        1985 QUARTERLY EARNINGS

                  WINTER
        Too FAR
                                    SUMMER

(ROCHE>  For the record, this book, the program, and its READ.ME file are  all 
dated  1983...  As delivered, Personal BASIC had a width of  72  columns,  the 
width  of  the ASR-33 Teletype. (See Appendix E: The option  table.)  So,  the 
PRINT  TAB (70)"Too FAR" statement causes it to wrap to the next line.  It  is 
the same thing with the PRINT TAB(100)"SUMMER" statement: 100 is greater  than 
72, so "SUMMER" is printed at column 28 of the next line.)


TAN Function

The TAN function returns the tangent of a number.


Syntax:

        X = TAN('angle in radians')


Explanation:

The  TAN  function operates on radian values, and returns  a  single-precision 
real number. To convert degrees to radians, multiply them by PI/180, where  PI 
= 3.141593.


Example:

        Ok 10 RADIAN! = 34
        Ok 20 TANGENT! = TAN(RADIAN!)
        Ok 30 PRINT TANGENT!
        Ok RUN
        -.62351


TRACE Command Function

The  TRACE  command follows program execution line by  line,  and  selectively 
prints the entire line.


Syntax:

        TRACE ['line number list']


Explanation:

You can use the TRACE command in debugging to print program lines as they run. 
TRACE  without  a  line number prints each line before executing  it.  If  you 
include  a list of line numbers, TRACE prints only those lines.  Unlike  TRON, 
TRACE  prints the entire line, including line number,  statements,  functions, 
and  variables. The UNTRACE command turns TRACE off. See the TRON  and  FOLLOW 
commands as well.


Example:

        Ok 10 FOR X = 1 TO 2
        Ok 20 N = N + 1
        Ok 30 B = B + 1
        Ok 40 PRINT N
        Ok 50 PRINT B
        Ok 60 NEXT X
        Ok RUN
         1
         1
         2
         2
        Ok TRACE
        Ok RUN
        t  10 FOR X = 1 TO 2
        t  20 N = N + 1
        t  30 B = B + 1
        t  40 PRINT N
         1
        t  50 PRINT B
         1
        t  60 NEXT X
        t  10 FOR X = 1 TO 2
        t  20 N = N + 1
        t  30 B = B + 1
        t  40 PRINT N
         2
        t  50 PRINT B
         2
        t  60 NEXT Y
        Ok UNTRACE


TRON Command

The TRON command selectively traces program execution line by line, and prints 
the line numbers and variable values.


Syntax:

        TRON ['line number list']


Explanation:

Use  TRON in debugging to follow the course of the program line by line.  TRON 
prints  each line number of the program as it executes, and traces the  values 
of variables. The line numbers appear in square brackets, [ ], followed by the 
current variable values.

After  you give a TRON command, Personal BASIC is at command  level,  prepared 
for  a  RUN  command. TRON is turned off by TROFF. See the  TRACE  and  FOLLOW 
commands as well.


Example:

        Ok 10 FOR X = 1 TO 3
        Ok 20 N = N + 1
        Ok 30 B = B + 1
        Ok 40 PRINT N
        Ok 50 PRINT B
        Ok 60 NEXT X
        Ok RUN
         1
         1
         2
         2
         3
         3
        Ok TRACE
        Ok RUN
        [10][20][30][40] 1
        [50] 1
        [60][20][30][40] 2
        [50] 2
        [60][20][30][40] 3
        [50] 3
        [60]
        Ok TROFF


TROFF Command

The TROFF command turns off the TRON command.


Syntax:

        TROFF ['line number list']


Explanation:

You  can  cancel  TRON by writing TROFF alone, or stop  tracing  certain  line 
numbers by giving them in the line number list.


UNBREAK Command

The UNBREAK command selectively cancels a BREAK command.


Syntax:

        UNBREAK ['line number list']


Explanation:

With  no line number list, UNBREAK cancels all BREAKs within the program.  You 
can UNBREAK particular breaks by giving their line numbers in the line  number 
list.


Example:

        Ok UNBREAK


UNFOLLOW Command

The UNFOLLOW command turns off the FOLLOW command.


Syntax:

        UNFOLLOW ['variable']{,'variable'}


Explanation:

Used alone, UNFOLLOW cancels the FOLLOW command entirely. If you want to  stop 
following  only  one  variable, or several variables, you  can  specify  which 
variables  you  want  to  leave out. List them  after  the  UNFOLLOW  command, 
separated by commas [,]. See the example at the FOLLOW command.


USR Function

The USR function calls a machine-language subroutine, passing arguments values 
on the stack.


Syntax:

        X = USR['digit'](arg1[,arg2, ..., arg15])


Explanation:

The optional digit is the number that you supplied in a corresponding DEF  USR 
statement  for the subroutine. It can be from 0 to 9. If you omit  the  digit, 
USR0 is assumed.

The  type  of  the result variable and the first argument  must  be  the  same 
(string  or  numeric). Up to 15 arguments can be specified. The  USR  function 
returns a value that BASIC assumes is the same type as the first argument.

If you use USR with small numeric constants from 0 to 15, BASIC returns system 
error  3. You can correct this by forcing the constants to type  integer  with 
CINT. For example,

        A% = USR(CINT(0))

For  variables and constants greater than 15, USR performs as documented.  You 
can also solve this problem by assigning small numeric constants to  variables 
and using the variables with USR.


Example:

        Ok 10 DEF USR2 = 2350
        Ok 20 X = USR2(C)
        Ok 30 Z = USR2(45(8+Z))


UNTRACE Command

The UNTRACE command turns off the TRACE command.


Syntax:

        UNTRACE ['line number list']


Explanation:

You  can  UNTRACE  all traced lines by leaving out the line  number  list,  or 
UNTRACE  certain  lines  by  including them in the  list.  After  an  UNTRACE, 
Personal  BASIC  returns  to  command level. See the  TRACE  command  in  this 
section.


VAL Function

The  VAL  function scans a string of characters, and converts them to  a  real 
number, if possible.


Syntax:

        X = VAL('digit string expression')


Explanation:

VAL  scans the string from left to right, skipping leading tabs  [HT],  spaces 
[ ],  and Line-Feeds [LF], until it reaches the end of the string or  finds  a 
character  that  is not a digit. VAL scans strings in the same  way  that  the 
INPUT# statement reads into a numeric variable.

If  the  first character of the string is not a valid part of  a  number,  VAL 
returns 0. The VAL function is the counterpart of the STR$ function, described 
in this section.


Example:

        Ok 10 INPUT "ENTER ID NUMBER, 0 TO STOP: ",ID$
        Ok 15 IF ID$ = "0" THEN END
        Ok 20 IF VAL(ID$) <= 300 THEN [LF]
                 EXPIRATION$ = "JAN 1, 1985"
        Ok 30 IF VAL(ID$) > 300 THEN [LF]
                 EXPIRATION$ = "JAN 1, 1990"
        Ok 40 PRINT EXPIRATION$ : GOTO 10
        Ok RUN
        ENTER ID NUMBER, 0 TO STOP: 3443475949876
        JAN 1, 1990

(ROCHE>  Again,  this book, the program, and its READ.ME file  are  all  dated 
1983... They were clearly planning into the future!)


VARPTR Function

The VARPTR function returns the address of a variable.


Syntax:

        X = VARPTR('variable')
        X = VARPTR(#'file number')


Explanation:

You can use VARPTR to find the address of a variable, so that you can pass  it 
to an assembly language subroutine.

In  the first form, the variable can be of any type, including array, but  you 
must have assigned it a value before you can find its address with VARPTR. The 
VARPTR function returns the address of the first byte of data associated  with 
the variable. The address is an integer between -32768 and 32767, representing 
the offset into Personal BASIC's Data Segment. It is not affected by a DEF SEG 
segment.  If  you get a negative address, add 65536 to it to find  the  actual 
address.

When  using VARPTR to pass array addresses, you usually give the form  of  the 
VARPTR  function as VARPTR ('array'(0)), so that the lowest-addressed  element 
of  the array returns. Assign values to all simple variables before  you  pass 
arrays, because the addresses of arrays change whenever you assign to a simple 
variable.

In the second form, the file number is the number that you assigned to a  disk 
file  when  you opened it. VARPTR returns the starting address of  the  file's 
input/output buffer.


Example:

        Ok 50 X = VARPTR(MATERIALS)


WAIT Statement

The WAIT statement halts the program while waiting for an I/O port to  develop 
a bit pattern.


Syntax:

        WAIT 'port number','integer expression'[,'integer expression']


Explanation:

WAIT  stops program execution until a given bit pattern develops in a  machine 
input port. The logical operator XOR tests the data from the port to determine 
whether it corresponds to the optional second integer expression. If you  omit 
the optional expression, it is assumed zero.

The AND operator then tests the data against the first integer expression.  If 
the  result of the test is zero, execution loops back and grabs the next  data 
at  the  port.  When the result is non-zero, execution goes  on  to  the  next 
statement.

If  WAIT  does  not  find  a  bit pattern  that  results  in  zero,  it  loops 
infinitely. You must reboot the machine.


Example:

        Ok 100 WAIT 5, &H2, &H3
        Ok 110 PRINT "NUMBER FOUND"


WEND Statement

The WEND statement signals the end of a WHILE-WEND loop.


Syntax:

        WEND


Explanation:

WEND  is  used  solely  with WHILE, to direct program flow  up  to  the  WHILE 
statement.  Nested  WENDs  associate with the nearest  WHILE.  See  the  WHILE 
statement in this section.


Example:

        Ok 10 X=7
        Ok 20 WHILE X
        Ok 30 PRINT "$";
        Ok 40 X=X-1
        Ok 50 WEND
        Ok 60 END
        Ok RUN
        $$$$$$


WHILE Statement

The WHILE statement states a condition that controls a WHILE-WEND loop.


Syntax:

        WHILE 'logical expression'


Explanation:

WHILE  initiates a WHILE-WEND loop of statements that continues running  until 
the  logical  expression is false (0). The statements between WHILE  and  WEND 
execute while the conditional expression in the WHILE statement is true (-1).

The WEND statement at the end of the loop sends program flow back to the WHILE 
condition.  The condition at the WHILE loop is evaluated and the loop  repeats 
while  the condition is true (non-zero). When the condition is  false  (zero), 
execution continues at the statement following the end of the loop.

You can nest WHILE-WEND loops to any level. Each WEND matches the most  recent 
WHILE. A WHILE without a WEND or a WEND without a WHILE causes an error.

See  the WEND statement in this section. Loops can also be written  with  FOR-
NEXT statements. In the example, the words COUNT LOOP are printed 5 times.


Example:

        Ok 10 M=10
        Ok 20 P=5
        Ok 30 WHILE M > P
        Ok 40 PRINT "COUNT LOOP"
        Ok 50 M=M-1
        Ok 60 WEND
        Ok END


WIDTH Statement

The WIDTH statement sets the line width of a terminal or printer.


Syntax:

        WIDTH [LPRINT] 'integer expression'


Explanation:

The default width on a terminal or printer is 72 characters. You can change it 
with WIDTH.

The  integer expression is the line width in number of characters; it must  be 
in  the  range 14 to 255. The LPRINT option sets the line width  at  the  line 
printer. Otherwise, the line width is set at the terminal.

When printing, Personal BASIC prints a Carriage Return [CR] before a character 
that  would, otherwise, run over the line width. To prevent unwanted  Carriage 
Returns in your output, set the line width to 255. Personal BASIC assumes then 
that the device has infinite width, and does not insert Carriage Returns.  The 
position  of the cursor or print head returned by LPOS or POS returns to  zero 
after reaching 255.


Example:

        Ok 10 WIDTH 33
        Ok 20 FOR I = 1 TO 50
        Ok 30 PRINT "-";
        Ok 40 NEXT
        Ok RUN
        ---------------------------------
        -----------------


WRITE Statement

The WRITE statement outputs data to the terminal.


Syntax:

        WRITE ['expression']{,'expression'}


Explanation:

Like  PRINT,  WRITE sends output to the screen, but WRITE  prints  commas  [,] 
between  the  items,  and quotation marks ["] around the  strings.  WRITE#  is 
preferable  to  PRINT# when you plan to read the data back with  a  series  of 
INPUT#  statements. The output from WRITE# is in exactly the form required  to 
read back the data accurately.

The  rules for forming the expression are the same as those for  PRINT#.  Each 
item  is  separated  from the next on the terminal with a  comma  [,].  String 
values  print  with quotation marks ["] and, after the last item,  the  cursor 
spaces down to the start of the next line.

WRITE  sends  a  blank line to the terminal if you do not specify  a  list  of 
expressions  to  output.  See  the PRINT statement in  this  section  for  the 
formatting of WRITE statements.


Example:

        Ok 100 X$ = "HAPPY MOTORING"
        Ok 110 Z = 010583
        Ok 120 WRITE Z
        Ok 130 WRITE
        Ok 140 WRITE X$
        Ok RUN
         10583

        "HAPPY MOTORING"

(ROCHE> Notice the "010583" date, that is to say: 5 January 1983...)


WRITE# Statement

The WRITE# statement writes data to a file.


Syntax:

        WRITE# 'file number','expression'{,'expression'}


Explanation:

WRITE#  works  like  WRITE but sends the data to a sequential  file,  not  the 
terminal.  The  file number is the number that you opened the file  with.  You 
must have opened the file in O or R mode.

The  expressions  are  string or numeric. They are written to  the  disk  with 
commas [,] between them, and quotation marks ["] around the strings. In  this, 
WRITE#  differs from PRINT#. Personal BASIC inserts a Carriage Return /  Line-
Feed [CR-LF] after the last item on the list.


Example:

        Ok 10 KWH = 34.275
        Ok 20 K$ = "AVERAGE KILOWATT HOURS PER WEEK"
        Ok 30 WRITE#2,K$,KWH

This writes to disk as:

        "AVERAGE KILOWATT HOURS PER WEEK",34.275

Close the file, re-open for input, then read the file:

        Ok 40 INPUT#2,K$,KWH

This assigns:

        "AVERAGE KILOWATT PER WEEK" to K$, and 34.275 to B$.


Appendix A: Personal BASIC keywords
-----------------------------------

Certain  words, known as keywords, have fixed meanings in Personal BASIC.  You 
cannot use them as variable or function names, or assign them meanings of your 
own.


ABS
ALL
AND
AS
ASC
ATN
AUTO
BASE
BLOAD
BREAK
BSAVE
CALL
CDBL
CHAIN
CHR$
CINT
CLEAR
CLOSE
COMMON
CONT
COS
CSNG
CVD
CVI
CVS
DATA
DEF
DEFDBL
DEFINT
DEFSNG
DEFSTR
DELETE
DIM
DIR
DO
EDIT
ELSE
END
EOF
EQV
ERA
ERASE
ERL
ERR
ERROR
EXP
FIELD
FIX
FLOAT
FOLLOW
FOR
FRE
GET
GO
GOSUB
GOTO
HEX$
IF
INKEY$
IMP
INP
INPUT
INPUT#
INPUT$
INSTR
INT
KILL
LEFT$
LEN
LET
LINE
LIST
LLIST
LOC
LOF
LOG
LOG10
LPOS
LPRINT
LSET
MERGE
MID$
MKD$
MKI$
MKS$
MOD
NAME
NEW
NEXT
NOT
OCT$
OLD
ON
OPEN
OPTION
OR
OUT
PEEK
POKE
POS
PRINT
PRINT#
PUT
RANDOMIZE
READ
REM
RENUM
REPLACE
RESET
RESTORE
RESUME
RETURN
RIGHT$
RND
RSET
RUN
SAVE
SEG
SGN
SIN
SPACE$
SPC
SQR
STEP
STOP
STRING$
STR$
SWAP
SYSTEM
TAB
TAN
THEN
TO
TRACE
TRON
TROFF
UNBREAK
UNFOLLOW
UNTRACE
USING
USR
VAL
VARPTR
WAIT
WEND
WHILE
WIDTH
WRITE
WRITE#
XOR


Appendix B: Decimal-ASCII-Hex table
-----------------------------------

ASCII stands for American Standard Code for Information Interchange. The  code 
contains  96 printing and 32 non-printing characters used to store data  on  a 
disk.  Table  B-1 defines ASCII symbols, then Table B-2 lists  the  ASCII  and 
hexadecimal conversions. The table includes binary, decimal, hexadecimal,  and 
ASCII conversions.

Table B-1.  ASCII Symbols

Symbol  Meaning                 Symbol  Meaning
------  -------                 ------  -------
ACK     acknowledge             FS      file separator
BEL     bell                    GS      group separator
BS      backspace               HT      horizontal tabulation
CAN     cancel                  LF      line feed
CR      carriage return         NAK     negative acknowledge
DC      device control          NUL     null
DEL     delete                  RS      record separator
DLE     data link escape        SI      shift in
EM      end of medium           SO      shift out
ENQ     enquiry                 SOH     start of heading
EOT     end of transmission     SP      space
ESC     escape                  STX     start of text
ETB     end of transmission     SUB     substitute
ETX     end of text             SYN     synchronous idle
FF      form-feed               US      unit separator
                                VT      vertical tabulation


Table B-2.  ASCII Conversion Table

 Binary     Decimal   Hexa      ASCII
--------    -------   ----      -----
00000000        0       0       NUL (CTRL-@)
00000001        1       1       SOH (CTRL-A)
00000010        2       2       STX (CTRL-B)
00000011        3       3       ETX (CTRL-C)
00000100        4       4       EOT (CTRL-D)
00000101        5       5       ENQ (CTRL-E)
00000110        6       6       ACK (CTRL-F)
00000111        7       7       BEL (CTRL-G)
00001000        8       8       BS  (CTRL-H)
00001001        9       9       HT  (CTRL-I)
00001010       10       A       LF  (CTRL-J)
00001011       11       B       VT  (CTRL-K)
00001100       12       C       FF  (CTRL-L)
00001101       13       D       CR  (CTRL-M)
00001110       14       E       SO  (CTRL-N)
00001111       15       F       SI  (CTRL-O)
00010000       16      10       DLE (CTRL-P)
00010001       17      11       DC1 (CTRL-Q)
00010010       18      12       DC2 (CTRL-R)
00010011       19      13       DC3 (CTRL-S)
00010100       20      14       DC4 (CTRL-T)
00010101       21      15       NAK (CTRL-U)
00010110       22      16       SYN (CTRL-V)
00010111       23      17       ETB (CTRL-W)
00011000       24      18       CAN (CTRL-X)
00011001       25      19       EM  (CTRL-Y)
00011010       26      1A       SUB (CTRL-Z)
00011011       27      1B       ESC (CTRL-[)
00011100       28      1C       FS  (CTRL-\)
00011101       29      1D       GS  (CTRL-])
00011110       30      1E       RS  (CTRL-^)
00011111       31      1F       US  (CTRL-_)
00100000       32      20       (SPACE)
00100001       33      21       !
00100010       34      22       "
00100011       35      23       #
00100100       36      24       $
00100101       37      25       %
00100110       38      26       &
00100111       39      27       '
00101000       40      28       (
00101001       41      29       )
00101010       42      2A       *
00101011       43      2B       +
00101100       44      2C       ,
00101101       45      2D       -
00101110       46      2E       .
00101111       47      2F       /
00110000       48      30       0
00110001       49      31       1
00110010       50      32       2
00110011       51      33       3
00110100       52      34       4
00110101       53      35       5
00110110       54      36       6
00110111       55      37       7
00111000       56      38       8
00111001       57      39       9
00111010       58      3A       :
00111011       59      3B       ;
00111100       60      3C       <
00111101       61      3D       =
00111110       62      3E       >
00111111       63      3F       ?
01000000       64      40       @
01000001       65      41       A
01000010       66      42       B
01000011       67      43       C
01000100       68      44       D
01000101       69      45       E
01000110       70      46       F
01000111       71      47       G
01001000       72      48       H
01001001       73      49       I
01001010       74      4A       J
01001011       75      4B       K
01001100       76      4C       L
01001101       77      4D       M
01001110       78      4E       N
01001111       79      4F       O
01010000       80      50       P
01010001       81      51       Q
01010010       82      52       R
01010011       83      53       S
01010100       84      54       T
01010101       85      55       U
01010110       86      56       V
01010111       87      57       W
01011000       88      58       X
01011001       89      59       Y
01011010       90      5A       Z
01011011       91      5B       [
01011100       92      5C       \
01011101       93      5D       ]
01011110       94      5E       ^
01011111       95      5F       _
01100000       96      60       '
01100001       97      61       a
01100010       98      62       b
01100011       99      63       c
01100100      100      64       d
01100101      101      65       e
01100110      102      66       f
01100111      103      67       g
01101000      104      68       h
01101001      105      69       i
01101010      106      6A       j
01101011      107      6B       k
01101100      108      6C       l
01101101      109      6D       m
01101110      110      6E       n
01101111      111      6F       o
01110000      112      70       p
01110001      113      71       q
01110010      114      72       r
01110011      115      73       s
01110100      116      74       t
01110101      117      75       u
01110110      118      76       v
01110111      119      77       w
01111000      120      78       x
01111001      121      79       y
01111010      122      7A       z
01111011      123      7B       {
01111100      124      7C       |
01111101      125      7D       }
01111110      126      7E       ~
01111111      127      7F       DEL


Appendix C: Creating a Personal BASIC system disk under CP/M-86
---------------------------------------------------------------

The most important step that you take before using Personal BASIC is to make a 
copy  of  your  Personal BASIC product disk. (ROCHE> This used  to  be  called 
a "Distribution Diskette"...) A mistyped command or an electrical failure  can 
accidentally erase these important programs permanently.

Copying  an  operating system onto a disk is called generating a  system.  The 
COPYDISK  program  on your CP/M-86 disk generates an operating system  on  the 
disk  drive that you specify. Once you have generated a new CP/M-86 disk,  you 
can  use  the PIP program to copy Personal BASIC to the new system  disk.  The 
instructions  in this Appendix assume that you have CP/M-86 and 2 floppy  disk 
drives.

You  should  now create a system disk containing Personal BASIC.  Consult  the 
operating manual with your operating system for instructions on how to  create 
a system disk.

When  you have a new CP/M-86 disk with utilities, remove the original  CP/M-86 
disk  from drive A and store it in a safe place. Remove the new  CP/M-86  disk 
from drive B and put it in drive A. Press the RESET button on your computer to 
reboot  the system on the new disk. (ROCHE> Intel microcomputers had  a  RESET 
button...) Then, put your Personal BASIC product disk in drive B. PIP Personal 
BASIC over to the new system disk in drive A. Type the following command:

        A>PIP A:=B:PBASIC.CMD

Remove  your Personal BASIC product disk from drive B and store it in  a  safe 
place.  Your new Personal BASIC system disk in drive A is now ready. Type  the 
following command to start Personal BASIC:

        A>PBASIC

Personal BASIC responds with the prompt Ok.

        --------------------------------------------------
        Personal Basic                         Version 1.1
        Serial No. xxxx-0000-654321    All Rights Reserved
        Copyright (c) 1983          Digital Research, Inc.
        --------------------------------------------------
        Ok

To  exit  Personal  BASIC and return control to CP/M-86,  type  the  following 
command:

        Ok SYSTEM

Make  copies  of all your programs. Remember to store  your  original  product 
disks in a safe place.


Appendix D: Personal BASIC error messages
-----------------------------------------

The following table shows error numbers and their meanings.

Table D-1. Personal BASIC error messages

Number  Message
------  -------
  1     Undefined error

  2     Something is wrong

  3     RETURN statement needs matching GOSUB

  4     READ statement ran out of data

  5     Function call not allowed

  6     Number too large

  7     Program is too large for memory

  8     A statement or command refers to a nonexistent line

  9     Subscript refers to element outside the array

  10    You defined an array more than once

  11    You cannot divide by zero

  12    Statement is illegal in direct mode

  13    Types of values do not match

  14    Undefined error

  15    Strings cannot be over 255 characters long

  16    Expression is too long or too complex

  17    CONT works only in BREAK mode

  18    Function needs prior definition with DEF FN

  19    Undefined error

  20    RESUME statement found before error routine entered

  21    Undefined error

  22    Expression has operator with no following operand

  23    Program line too long

 24-49  Undefined error

  50    FIELD statement caused overflow

  51    Undefined error

  52    File number or filename invalid

  53    File not found on disk drive specified

  54    File mode is not valid

  55    You cannot OPEN or KILL a file already open

  56    Undefined error

  57    Disk input/output error, restart your operation (MP/M)

  58    File exists

  59    Undefined error

  60    Undefined error

  61    Disk is full

  62    You have reached end-of-file

  63    The record number in PUT or GET is more than 32767 or zero

  64    Invalid filename

  65    Invalid character :123: in program file

  66    Program file has statement with no line number

 67-98  Undefined error

  99    -- Break --

  100   Undefined error

  101   Program exceeds memory size

  102   ON statement is out of range

  103   Invalid line number

  104   A variable is required

  105   Undefined error

  106   Line number does not exist

  107   Number too large for an integer

  108   Input data is not valid, restart input from first item

  109   Stop

  110   You have nested subroutine calls too deep

  111   Invalid BLOAD file

112-201 Undefined error

  202   Command not allowed here

  203   Line number is required

  204   FOR statement needs a NEXT or WHILE needs a WEND

  205   NEXT statement needs a FOR or WEND needs a WHILE

  206   A comma is expected

  207   A parenthesis is expected

  208   Option Base must be 0 or 1

  209   Statement end is expected

  210   Too many arguments in your list

  211   Undefined error

  212   Cannot re-define variable(s)

  213   Function defined more than once

  214   You are trying to jump into a loop

215-220 Undefined error

  221   System error #216, please restart

  222   Program not run

  223   To many FOR loops

224-255 Undefined error


Appendix E: The Option Table
----------------------------

Personal  BASIC  has a table of option bytes at a fixed  memory  address.  The 
options determine how Personal BASIC treats certain features of the  language. 
You  can  examine the options' settings with PEEK, or change them  with  POKE. 
Once  you set an option, it remains set until you change it or  exit  Personal 
BASIC.

The  base  of the option table is 102H, within the default Data  Segment.  The 
default  Data  Segment is the location that you get if you execute a  DEF  SEG 
without  specifying an address. From version to version, the location  of  the 
option table base might change.

(ROCHE> Well, as far as I know, there was only one version of Personal  BASIC, 
Version 1.1, so we have no problem of versions...)

Be  careful  when  POKing  or  PEEKing around  the  Data  Segment.  You  could 
accidentally  change  data essential to the operation of Personal  BASIC.  You 
might get unexpected results.

The following diagram summarizes the options and their offsets.

                         BASE + OFFSET
        ┌─────────────┐
        │     DP      │ &H102 + 0 
        ├─────────────┤
        │   Ctrl-C    │ &H102 + 1
        ├─────────────┤
        │     ON      │ &H102 + 2
        ├─────────────┤
        │  *UNUSED*   │ &H102 + 3 to 13
        ├─────────────┤
        │   CONSOLE   │ &H102 + 14
        ├─────────────┤
        │   PRINTER   │ &H102 + 15
        └─────────────┘

        Figure E-1. Option table

The options, with their offsets within the table, are as follows:

Offset:         0
Regards:        Microsoft BASIC double-precision format
Initial value:  0

If  the value equals zero, double-precision numbers mapped to strings  through 
the MKD$ function are mapped in IEEE format, which is the format in which they 
are held internally.

If  the value does not equal zero, double-precision numbers are  converted  to 
Microsoft  BASIC format by the MKD$ function, and back to IEEE format  by  the 
CVD  function.  By setting the switch, Personal BASIC can read  files  created 
with Microsoft BASIC.

Note  that double-precision overflow might occur when converting from IEEE  to 
Microsoft BASIC format.


Offset:         1
Regards:        Control-C trap
Initial value:  0

If  the value equals zero, a Ctrl-C entered at the terminal halts the  program 
and  puts  it  into  Break Mode. Ctrl-C never  produces  a  break  during  the 
execution of an INPUT$ statement.

If  the value does not equal zero, and if an error trap has been set (that  is 
to  say: an ON ERROR GOTO statement has been executed), then a Ctrl-C  entered 
at the terminal generates a trappable error with code 99. Further, the program 
does  not acknowledge a Ctrl-C during an error-trap routine. By  setting  this 
switch, a program can make itself unbreakable.

(ROCHE> This is the OPTION STOP / OPTION RUN switch of Mallard BASIC...)

Note:  If  you  set the switch and your program has an error  that  causes  an 
infinite loop, there is no way to stop it, unless you reboot the machine.


Offset:         2
Regards:        ON 'expression' GOTO 'line number list'
Initial value:  0

This switch affects the way Personal BASIC handles an ON-GOTO statement if the 
expression evaluates outside the range implied by the number of labels in  the 
line number list.

If the value equals zero, Personal BASIC drops through to the next  statement. 
If  the value does not equal zero, Personal BASIC generates a  trappable  run-
time error.


        *** Offsets 3 through 13 are unused. ***


Offset:         14
Regards:        Default console width
Initial value:  72 (decimal)

The  console width is set to this value every time a RUN, CHAIN, NEW,  or  OLD 
command executes.


Offset:         15
Regards:        Default printer width
Initial value:  72 (decimal)

The printer width is set to this value in the same way as the console width.


Appendix F: Machine-language linking conventions
------------------------------------------------

The  linkage used for CALL statements and USR functions is  identical.  Before 
the new routine is called, the expressions in the argument list are  evaluated 
and  placed  on the Personal BASIC (soft) stack, in the order  in  which  they 
appear  in the argument list. All parameters are passed by value; if you  want 
to access a variable, the appropriate parameter is VARPTR('variable'), not the 
variable name itself.

The  address  of the base of the argument list is placed in  register  BX  and 
Personal BASIC executes a Far Call (CALLF) to the offset specified by the CALL 
variable or USR definition, in the segment defined by the most recent DEF  SEG 
statement.

Any  expressions  are  allowed  in the argument list, but  it  is  the  user's 
responsibility  to ensure that the argument types correspond to the types  the 
machine-language function is expecting. In particular, note that an expression 
involving only integers might result in a floating-point result. For example,

        A% * B%

gives a floating-point result.

If you want to pass the result of an expression as an integer, it is safest to 
use CINT to force the result to an integer. For example,

        CINT(A% * B%)

will generate an integer or an error.

The  user routine must preserve the data segment register (DS) over the  call, 
and  would  normally return control via a Far Return  (RETF),  which  restores 
Personal BASIC's Code Segment register.

On  return  from  a call to a user routine called in the  context  of  a  USRn 
function,  the  resulting value is taken from the first argument area  of  the 
soft  stack; that is, the user function is assumed to have replaced the  first 
argument (pointed directly to by BX) with the function result.

Argument Types:

        o Integers are stored in 2 bytes.

        o Single-precision floating-point numbers are stored in 4 bytes.

        o Double-precision floating-point numbers are stored in 8 bytes.

        o String descriptors are stored in 6 bytes.

All  numbers are stored in the following order: least significant byte  first, 
most significant byte last.


        Integer Format

a               a + 1
----------------------------------
:               :                :
:    LSB        :    MSB         :
----------------------------------


        Single-Precision Format

a           a + 1      a + 2      a + 3
-----------------------------------------------
:           :          :        : :           :
:  LSB      :          : MSB    : :           :
:           :          :        : :           :
-----------------------------------------------
\                              / | \          /
 \\\\\\\\\\\\\\  //////////////  |  \\\\  ////
               \/                V      \/
              mantissa           sign   exponent


        Double-Precision Format

a     a+1   a+2   a+3   a+4   a+5   a+6   a+7
---------------------------------------------------
:     :     :     :     :     :     :     :     : :
:LSB  :     :     :     :     :     :MSB  :     : :
:     :     :     :     :     :     :     :     : :
---------------------------------------------------
\                                      /\        /|
 \\\\\\\\\\\\\\\\  ////////////////////  \\\\  // V
                 \/                          \/  sign
              mantissa,                  exponent,
               53 bits                    11 bits


        String Format

-----------------------------------------------------
:   :       :       :       :       :       :       :
: 4 :  12   :       :       :       :       :       :
:   :       :       :       :       :       :       :
-----------------------------------------------------
: \               /\              /\              /
:  \\\\\\\  //////  \\\\\\  //////  \\\\\\  /////
V         \/              \/              \/
type,    length,        address1        address2
4 bits    12 bits

Type is a 4-bit code, as follows:

0 = short string
 
        Up  to  4  bytes in length, the characters are  in  the  address1  and 
        address2 fields.

1 = variable

        Address1  and address2 combined give the address of the first byte  in 
        the  string. Address1 must be shifted left one before being  added  to 
        address2.

2 = field

        Address1 is composed of a 4-bit file number and 12-bit offset into the 
        file user's buffer. Address2 is used for other purposes.

3 = constant

        Address1  and address2 are combined as for type 1. The result  address 
        may  point at program text, so do not change the string to which  this 
        points.

4 is not used

5 and 6 as for type 1.


Index
-----

To be done by WS4...


EOF