http://t3x.org/nmhbasic/basic3.0.html   (light|dark)

NMH BASIC III Man Page

BASIC(1)             General Commands Manual            BASIC(1)



*** USAGE ***
       BASIC [FILE ...]

*** DESCRIPTION ***
       NMH BASIC is a minimal BASIC interpreter for systems with
       little memory.  It provides a basic  (sic!)  command  set
       and  a  built-in editor.  Programs may either be typed in
       interactively or read from an external  file  or  device.
       Programs  can even be saved to and loaded from five-chan-
       nel paper tape.  NMH BASIC is intended for  fun  program-
       ming.

*** STARTUP PARAMETERS ***
       NMH BASIC  treats  each  command  line  parameter that is
       passed to it as a file name and attempts to open the  re-
       quested  files  for  reading  or writing.  It prints each
       file name and the unit number assigned to  it.   When  it
       fails  to  open a file, it prints an exclamation mark (!)
       followed by the file name.

       If a file name is prefixed with an exclamation mark,  the
       file  will  be  opened for writing and otherwise the file
       will be opened  for  reading.  The  access  mode  can  be
       changed later using the IOCTL function.

*** EDITING ***
       There is a simple builtin editor that allows the program-
       mer to enter and modify programs interactively.
       NMH BASIC program memory consists of a sequence  of  num-
       bered  lines. Each command that starts with a number will
       not be executed immediately but is inserted into  program
       memory  instead.  When entering a line with a line number
       that already exists, the given line will be replaced. En-
       tering  a  line number with no following text will delete
       the given line.
       The length of each line  is  limited  to  64  characters.
       Longer lines will cause an error.
       The LIST command may be used to view lines stored in pro-
       gram memory.
       The NMH BASIC editor  performs  some  on  the  fly  error
       checking. It checks only at scanner level, but this helps
       to catch many typos while entering a  program.  When  the
       editor finds an error, it discards the erroneous line.

       When  entering  programs, typing the first few characters
       of a command name is typically enough. For example PR  is
       interpreted as PRINT, NE as NEXT, and SY as SYSTEM.

       When  entering  program text or data, the backspace (<--)
       or delete (DEL) key can be used to delete already entered
       characters. Pressing Control-U will erase all input char-
       acters. Pressing Control-C will abort  the  input  opera-
       tion.

       When a program is executing, pressing Control-C will stop
       the program and return to interactive mode.

*** PROGRAMS ***
       A program consists of a number of lines,  and  each  line
       contains  at  least  one BASIC statement, also known as a
       command.  Multiple statements may be placed in  a  single
       line by separating them with colons (:).

*** EXPRESSIONS ***
       An  expression  is everything that evaluates to a numeric
       value at run time.  NMH BASIC recognizes the  four  basic
       math  operators  (+,  -, *, /) and some other arithmetic,
       comparison, and logic operators. Operators  are  used  to
       combine  factors  (binary  operators)  or  modify factors
       (unary operators). Valid factors are: numbers, variables,
       and function values.

       Numbers  are  numeric  literals  in  the  range -32767 to
       32767. They represent themselves.
       Variables are two-character sequences  that  represent  a
       variable  numeric  value.   There are 260 numeric integer
       variables in NMH BASIC that are named A0...Z9. The  first
       character  must  always be a letter, and the second one a
       digit. Variables of the form X0 can also be written X.
       Function values  are  the  values  returned  by  function
       calls.
       A  function  is  called by typing the function name, fol-
       lowed by a left parenthesis, some function arguments, and
       a right parenthesis.

       NMH BASIC accepts the following operators:

        +-----+-----+------+-----------------------------------+
        |Oper | Alt | Type | Description                       |
        +-----+-----+------+-----------------------------------+
        | ( ) |     |  4   | grouping, array subscripts        |
        | -   |     | U4   | unary minus, negative prefix      |
        +-----+-----+------+-----------------------------------+
        | *   | !   | B3   | multiplication                    |
        | /   |     | B3   | division                          |
        | //  |     | B3   | division remainder                |
        | +   | &   | B2   | addition, string concatenation    |
        | -   |     | B2   | subtraction                       |
        +-----+-----+------+-----------------------------------+
        | =   | EQ  | B1   | equal to, same string             |
        | <>  | UE  | B1   | not equal to, not same string     |
        | <   | LT  | B1   | less than, earlier in alphabet    |
        | >   | GT  | B1   | greater than, later in alphabet   |
        | <=  | LS  | B1   | less/equal, earlier/same          |
        | >=  | GS  | B1   | greater/equal, later/same         |
        +-----+-----+------+-----------------------------------+
        | #   |     | U0   | logical NOT                       |
        | =   |     | B0   | assignment (only in LET commands) |
        +-----+-----+------+-----------------------------------+
       Types: U = unary, B = binary, number = precedence level

       A  higher  precedence  level  indicates  that an operator
       binds stronger to its arguments. For example, the expres-
       sion A+B*C will be interpreted as A+(B*C).
       The  comparison  operators (=, <>, <, >, <=, >=) are only
       accepted in condition contexts, i.e. in IF commands.

*** ARRAYS ***
       Normally there are 260 integer variables. All these vari-
       ables  have  a unique name (A0...Z9). Sometimes, however,
       it is more practical to access variables like vector ele-
       ments  (through  an index, or subscript).  Each NMH BASIC
       variable may be treated as an array  without  making  any
       special  declarations.  `A', for example, may also be ad-
       dressed as `A(0)', A1 is equal to A(1), A(9) is equal  to
       A9. Larger subscripts cause on overflow to the next vari-
       able letter: A(10) would be equal to  B0,  A(25)  to  C5,
       etc. Z(10), finally, will cause a subscript error.

       When more space is needed, or no variable letters must be
       `wasted', there is the possibility to dimension an array.
       Usually,  the  `Z'  variables are used to build an array,
       because they cannot have  common  memory  locations  with
       other variables.
       The statement

              DIM Z(200)

       will  increase  the size of Z0 to 200 elements. Note that
       the free space for program text will be decreased by this
       operation.
       Dimensioning  a  different  variable will not occupy that
       much dynamic memory  because  the  space  for  subsequent
       variables is used up first. Using A0 as an array with 200
       elements [DIM A(200)], for example, will not  occupy  any
       dynamic  memory,  but  will  make  the  variables A1...T9
       aliases of A(1)...A(199).  In fact, of  course,  this  is
       already  so,  even without any DIM statement.  The state-
       ment

              DIM A(200)

       is essentially a null-statement, but may serve as  a  re-
       minder.

*** STRING EXPRESSIONS ***
       The  second  NMH BASIC  data type is the string.  Strings
       are fixed-length memory locations that can be filled with
       characters. They are used to store ASCII text.
       There  is  only  one  operation  that may be performed on
       strings: the concatenation, which is done by the + opera-
       tor.
       Valid  factors  in  string expressions are text literals,
       string variables, and function values.
       A text literal is a  string  of  characters  enclosed  by
       apostrophes.   A  literal  apostrophe  may be inserted by
       typing it two times in a row.  Text  literals,  like  nu-
       meric literals, represent themselves.
       A string variable is a variable letter followed by a dol-
       lar sign ($).  There are 36 string variables: A$...Z$ and
       0$...9$.  String  variables  may  not be dimensioned, but
       they can be treated as arrays. For example, A$(1) is  the
       same  as B$ or B$(0). Typically 0$ is used as an array of
       10 strings.
       The length of NMH BASIC strings is limited to 64  charac-
       ters.

*** STATEMENTS ***
       A statement (also called a "command") is the smallest ex-
       ecutable element of  a  basic  program.   Each  statement
       starts with a keyword and is usually followed by some pa-
       rameters and additional keywords.  There are three  kinds
       of statements: simple statements, conditional statements,
       and loop statements.

       Most statements in NMH BASIC are simple statements.   Ex-
       amples are:

              LET I = 195
              GOTO 420
              PRINT ASC(A$)

       Conditional  statements will only be executed when a con-
       dition is true. There is only one form of the conditional
       statement:

              IF condition statement

       The  keyword  IF  is  followed by a condition.  Only when
       this condition is true, the statement part will  be  exe-
       cuted. For example,

              IF A < 0 PRINT 'NEGATIVE'

       will print 'NEGATIVE' only if A is less than zero.

       Loop  statements  consist of three parts, the introducing
       statement (FOR), a  body  consisting  of  any  number  of
       statements,  and a scope terminator (NEXT).  In NMH BASIC
       there is only one block statement and it looks like this:

              FOR I = 1 TO 100
              PRINT I,
              NEXT

       It implements a counting loop.  In the  example  the  en-
       closed  statement  "PRINT I," will be executed 100 times.
       Each time the loop is passed, the variable I will be  in-
       creased  by  one  (at  the end of the loop). So this loop
       will print the numbers from 1 to 100.
       NEXT is the scope terminator. When  it  is  reached,  the
       counting  variable  is  incremented,  and  if  it has not
       passed the limit, the enclosed  statements  are  executed
       again.

       Multiple  statements  may  be  placed in the same line by
       separating them with colons. E.g.:

              FOR I = 1 TO 100 : PRINT I, : NEXT

*** COMMENTS ***
       REM {string | command}
            Ignore the given command or string. The REM  command
            can be used to temporarily disable a command without
            removing it or, using a string, it can  be  used  to
            insert comments into a program.

*** ASSIGNMENT COMMANDS ***
       LET var = expr
            Evaluate  expr and assign the result to var.  If var
            is a string variable, expr must be a string  expres-
            sion.

       LET var(expr) = expr2
            Evaluate  expr2 and assign the result to the expr'th
            slot of var.  Slots start at an index of 0.  If  var
            is a string variable, expr2 must be a string expres-
            sion.

*** CONTROL COMMANDS ***
       END
            End program  execution  and  return  to  interactive
            mode.

       FOR var = expr TO expr2 : [command ... :] NEXT
       FOR var = expr TO expr2 STEP expr3 : [command ... :] NEXT
            A  counting  loop. First set the variable var to the
            value of expr, and then execute all statements up to
            a  matching  NEXT  keyword.  Then  increment  var by
            expr3.  When no STEP and expr3 are  given,  incrment
            by  one. If, after incrementing, var is smaller than
            or equal to expr2, execute  all  statements  between
            FOR and NEXT again.

            When  the  increment  expr3 is negative, the loop is
            repeated while var  is  greater  than  or  equal  to
            expr2.

            All  expressions  are only evaluated once before the
            first iteration of the loop!

            FOR statements may be nested. The NEXT keyword  then
            pairs  up with the most recently executed FOR state-
            ment.

       GOSUB line
       RETURN
            Perform a jump (like GOTO) to the given line number,
            remembering  the  return address. The return address
            is pushed onto an internal stack. A RETURN statement
            may  be  used  to pop this address off the stack and
            continue execution at the statement immediately  af-
            ter GOSUB. Subroutine calls may be nested.

       GOTO line
            Jump  to  the given line number. Execution continues
            with the first statement in the specified  line.  In
            fact line may be any expression.

       IF condition [, ...] command [: command ...]
            Evaluate  the  condition, and execute the command(s)
            only if the condition is true. When the condition is
            false,  execution continues with the first statement
            in the following line (if any).

            The condition may be any comparison operation,  like
            A=B or A<=B, where A and B are expressions. If there
            is no comparison operation in  the  condition,  then
            the  condition  is  considered  to be `true', if its
            value is non-zero.

            The comparison operators  can  be  used  to  compare
            strings.  In this case the equal operator (=) checks
            if two strings are exactly equal, i.e.  contain  the
            same characters in the same positions. The less-than
            (<) operator checks if the first string  would  come
            before  the second string in a lexicon where entries
            are ordered using the ASCII alphabet. The other com-
            parison  operators  can  also  be  used and have the
            meaning described in the EXPRESSIONS section.

            Multiple conditions may be separated by  commas.  In
            this  case  all  conditions have to be true in order
            for the command(s) to be executed.

       STOP
            Stop program execution with an STP error.

       SYSTEM
            Exit from the interpreter. This will even work  when
            executing a program stored in memory.

*** INPUT/OUTPUT COMMANDS ***
       INPUT #expr
            Redirect input to the given unit number.  All subse-
            quent input will be read from the file or device as-
            sociated with the unit number.

       INPUT {var | strvar} [, ...]
            Read  input  from  the terminal (or redirected unit)
            and assign each line of input to a  variable.  Input
            will  be  automatically converted to the proper for-
            mat.
            When reading a string A$ from a unit on which no in-
            put is available, the string will have the character
            255 in its first slot, i.e. ASC(A$) = 255.
            The INPUT command does not emit a prompt. Use
            PRINT 'prompt';
            for that.

       PRINT
            Print a newline sequence.

       PRINT #expr
            Redirect all output to the given unit  number.  Note
            that  the  interpreter will reset the default output
            unit when entering interactive mode.

       PRINT {expr |  strexpr}  [{,|;}  {expr  |  strexpr}  ...]
       [{,|;}]
            Evaluate  each given expression (string or numeric),
            and write its value to  the  output  unit  (default:
            terminal).   Expressions  may be separated by commas
            or semicolons. A comma emits a horizontal TAB and  a
            semicolon pastes output together.
            A  newline  character  is emitted after the last ex-
            pression unless the  print  statement  ends  with  a
            comma or semicolon.

       READ {var | strvar} [, ...]
       DATA {number | string} [, ...]
            Read  DATA  items  into the specified variables. The
            items are taken from DATA lists which may be  speci-
            fied  at any place in the program (but are typically
            placed at the end).
            Each item in the list must have the same type as the
            corresponding  variable in READ or an error will oc-
            cur. Each READ operation advances the  data  pointer
            by  n  items,  where n is the number of variables in
            the READ statement.
            When the data pointer is moved past the end  of  the
            list  while  READ  executes, the operation will fail
            with an error.

            Each DATA statement defines a list of initialization
            data.  The data objects (string or numeric literals)
            follow the DATA keyword as a space-separated list.

       RESTOR
            Reset the data pointer to the beginning of the  ini-
            tialization  list  (the  first  element of the first
            DATA statement in the program).

*** PROGRAM AND STORAGE COMMANDS ***
       CLEAR
            Clear all variables and array dimensions. After  is-
            suing  CLEAR,  variables  will  be  set  to zero and
            string variables will contain empty strings.

       DIM var ( expr ) [, ...]
            Define variable var as an array with size  elements.
            DIM  does not actually allocate any memory to arrays
            in most cases and serves documentary purposes  only.
            When  the  variable  A  is dimensioned with 100 ele-
            ments, for example, the space used by the subsequent
            variables  (C,D,  is used, so A(10) becomes an alias
            of B0 and A(25) an alias of C5, etc.  Only when  the
            end  of  the  array  moves  beyond Z9, the space for
            variables is actually extended. In this case program
            memory is reduced.

       LIST [expr1 [, expr2]]
            List  all  lines from expr1 to expr2.  When only one
            line is given, list just that line.  When  no  lines
            are given, list all lines.

       LOAD #expr
            Redirect input to the specified unit number and pass
            each line of input to the interpreter. When the  end
            of input is reached, redirect input back to the ter-
            minal.
            When done, LOAD leaves the file pointer at  the  EOF
            of the given unit.
            LOAD does not erase program memory, so multiple pro-
            grams can  be  merged  with  LOAD.  Merged  programs
            should not share line numbers.

       NEW
            Clear program memory and all variables and array di-
            mensions.

       RUN
            Clear all variables and dimensions and then run  the
            program in program memory.

       SAVE #expr
            Redirect  output  to  the given unit number and then
            call LIST to write the program in program memory  to
            the  associated  file  or  device. After writing the
            program, redirect output back to the terminal.
            SAVE leaves the file pointer of the unit at the  end
            of the listing.

*** FUNCTIONS ***
       ASC( strexpr )
            Return  the  ASCII  code  of  the first character in
            string.  Return 0 for an empty string.

       FRE(0)
            Return the number of free bytes in program memory.

       IOCTL( expr1, expr2 )
            Request the specified service (expr2) for unit  num-
            ber expr1.
            Available services are:

            100  rewind unit and switch to read-only mode
            103  rewind and truncate unit and switch to write-only mode
            200  switch unit to ASCII mode
            201  switch unit to Baudot (CCITT-2) mode

            When  an  input  unit  is in Baudot mode, input read
            from the unit will be expected in  CCITT-2  encoding
            and  will  be  automatically  converted to to ASCII.
            When an output unit is in Baudot mode,  output  will
            be automatically converted to CCITT-2 encoding.

            IOCTL  returns  a  code that indicates the status of
            the requested operation.  Generally, zero means suc-
            cess and non-zero means failure.
            When  an  invalid service number is passed to IOCTL,
            an error occurs.

       LEN( strexpr )
            Return the length of the  given  string  expression.
            An empty string has a length of zero.

       VAL( strexpr )
            Compute  the  decimal value represented by the given
            string expression and return  it.  A  leading  minus
            sign  is  recognized.  Trailing non-digit characters
            are ignored.  Non-numeric strings will return zero.

*** STRING FUNCTIONS ***
       CHR$( expr )
            Return a  one-character  string  that  contains  the
            character corresponding to the ASCII code expr.

       MID$( strexpr, expr [, expr2] )
            Extract  a substring from strexpr and return it. The
            position expr1 specifies the first character  to  be
            extracted  and expr2 gives the length of the desired
            substring.
            When the position is greater then the length of  the
            string, an empty string will be returned.
            When  position+length  is greater than the length of
            strexpr, all characters from the position up to  the
            end of the string are returned.
            The abbreviation

            MID$(strexpr, expr)

            can  be  used  to  extract  all  characters from the
            starting position to the end of the string.
            The first character in a string is at position  one,
            not zero, but zero is treated as an alias for one.

       STR$( expr )
            Convert  the given value to a string of decimal dig-
            its and return it.  Negative  numbers  will  have  a
            leading minus sign.

*** MACHINE CODE COMMANDS AND FUNCTIONS ***
       On the processor-specific versions of NMH BASIC there are
       commands and functions for reading and writing memory lo-
       cations and calling machine code functions. These are not
       present in the portable (T3X/0)  version  of  the  inter-
       preter.

       POKE expr1,expr2
            Write  the value expr2 to the memory location expr1.
            The value is written to a  byte-sized  cell,  so  it
            will be truncated to eight bits.

       PEEK( expr )
            Read  the  byte  stored at the given memory location
            and return it.

       USR( expr )
            Call the machine code function stored at  the  given
            address  and  return  the value returned by it. On a
            Z80 CPU, this would be the value contained in the HL
            register when the machine code function returns.

*** ERROR CODES ***
       When  NMH BASIC  detects  an error, it will print a three
       letter code, followed by a colon and the line that caused
       the  error.  When  an error occurs in execution mode, the
       program will stop.

       ARG
            Bad argument - an invalid value has been passed to a
            function.

       BRK
            Break - program stopped by user.

       DIV
            Division by zero. Also caused by X // 0.

       EOD
            End  of  data - a READ statement contains more vari-
            ables than there are remaining items in the initial-
            ization lists (DATA).

       ILN
            Invalid line number - a GOTO or GOSUB statement con-
            tains a non-existant line number.

       LLO
            Line too long - a line exceeds the maximum length of
            64 characters.

       MEM
            Insufficient  memory - caused by DIM or by inserting
            lines into program memory.

       NST
            Nesting error - a RETURN statement occurs where NEXT
            has been expected, or vice versa. Also occurs when a
            statement that is being LOADed attempts to LOAD  an-
            other  program  (LOAD may not be nested) or when the
            return stack is not empty when a program terminates.

       OVF
            Overflow - a numeric literal does not fit in 15 bits
            +  1 sign bit.  The valid range for numeric literals
            is -32767 to 32767.

       PTX
            Paper tape error - a program could not be  saved  to
            paper  tape, because it contains unconvertible char-
            acters.

       SBO
            String buffer overflow - the  concatenation  of  two
            strings is longer than 64 characters.

       SXO
            String  expression  overflow.  This happens when too
            few temporary buffers are available in string opera-
            tions. A string expression is too complex.

       STP
            Stop - program stopped by a STOP command.

       STK
            Stack  error  -  the internal return stack has over-
            flowed. Caused by nesting  subroutines  or  FOR-NEXT
            loops too deeply.

       SUB
            Bad  subscript  -  caused  by an attempt to access a
            non-existant array element.  This happens, for exam-
            ple, when an element beyond Z(9) is referenced with-
            out first allocating storage to it via DIM.

       SYN
            Syntax error - the most common error with  an  infi-
            nite  number  of possible causes . Frequently caused
            by typos. Generally, the input that causes this  er-
            ror is not a valid BASIC statement.

       TYP
            Type mismatch - a variable in a READ statement has a
            different type than the current item in the initial-
            ization list (DATA).

       XXX
            Aaah!  - interpreter in hopeless confusion - time to
            bail out!

*** EXAMPLES ***
       Print a sixbit ASCII table.
              100 FOR I = 32 TO 95
              110 PRINT CHR$(I); ' '; I-32,
              120 NEXT

       Load (and merge) programs from units 3 and 4,  then  save
       the  merged program to unit 5. The IOCTL call rewinds and
       truncates unit 5.
              LOAD #3
              LOAD #4
              PRINT IOCTL(5, 103)
              SAVE #5

       Print data from unit 5. The IOCTL call rewinds the unit.
              100 LET X = IOCTL(5, 100) : INPUT #5
              110 INPUT A$ : IF ASC(A$) = 255 INPUT #0 : END
              120 PRINT A$ : GOTO 110

*** DIFFERENCES BETWEEN THE INTERPRETERS ***
       The CP/M version of the interpreter connects unit two  to
       AUX:/RDR:  and  unit  three  to AUX:/PUN:. There are only
       seven units in total, i.e. only units 4,5,6 can  be  con-
       nected to files.
       The  DOS  version connects unit two to SYSERR, unit three
       to AUX:, and unit four to PRN:.
       The Unix versions connect unit two to SYSERR.
*** DIFFERENCES TO EARLIER VERSIONS ***
       The CMPS function has been replaced with string  compari-
       son operators, like A$ = 'FOO', A$ < B$, etc.
       Expressions  can  no longer contain comparison operators.
       These are limited to IF statements. E.g. LET X = A < B is
       no longer a valid statement.
       The division remainder operator is // instead of \.
       Commands  can be abbreviated, e.g. PR for PRINT or SY for
       SYSTEM.
       There are baudot-compatible keywords and symbols for some
       operators, e.g.  LT for <, GS (greater or same) for >=, &
       for +, etc.
       The IOCTL services 101 (truncate) and 102  (append)  have
       been  removed.  The service 103 (rewind and truncate) has
       been added.
       The IOCTL service 100 (rewind) now switches its  unit  to
       read-only mode.
       The  new  IOCTL  service 200 (ASCII) switches a device to
       ASCII mode.
       The new IOCTL service 201 (Baudot) switches a  device  to
       baudot mode.
       The CALL, TRON, and TROFF commands have been removed.
       The  POKE command and the PEEK function have been removed
       from the portable T3X/0 version, but remain in  the  CP/M
       version.
       The USR function was added to the CP/M version.
       The  ESXO  (string  expression  overflow) and EPTX (paper
       tape transcoding) errors have been added.
       The ENIM (not implemented) error has been removed.
       Units are now opened read-only by default.  They  can  be
       opened  write-only  by using the !file syntax on the com-
       mand line.

*** NOTES ***
       Some versions of the interpreter expect programs  in  DOS
       file  format, i.e.  lines terminated with CR,LF. All ver-
       sions of the interpreter do accept DOS format, some  also
       accept Unix (LF) format.

       When  saving programs or data using baudot encoding, some
       characters will be replaced with  alternative  characters
       or sequences. When reading such data back, only BASIC to-
       kens will be converted back. E.g., the line

              100 LET X = X+1 : REM 'X = X + 1'

       will be saved as

              100 LET X EQ X&1 : REM 'X EQ X & 1'

       and then read back as

              100 LET X = X+1 : REM 'X EQ X & 1'

       Characters in strings will not be converted back, because
       they are not BASIC tokens. Characters read via INPUT will
       never be converted.

***** BUGS *****
       The interpreter will misinterpret string expression  when
       they  are too complex. It will catch some of these condi-
       tions, but not all of them, so it is best to keep  string
       expressions short and simple.
       In  particular, nesting MID$ or concatenation (via string
       function arguments) will probably cause trouble.
       When the interpreter misinterprets expressions or reports
       SXO errors, rewrite the offending expression using string
       variables for intermediate results.

       When the INPUT function reads data from  the  console  on
       CP/M,  it  is possible to backspace past the beginning of
       the input. This is only a visual artefact, though, and no
       data corruption will occur.

       When loading baudot-encoded programs from a file on CP/M,
       a syntax error will occur, if the program size is not  an
       exact  multiple  of 128.  The offending line will consist
       of a number of 'J' or apostrophe characters.  This  error
       can  be  ignored. The reason for this error is that 01Ah,
       which CP/M uses for padding, is a valid baudot character.

*** LICENSE ***
       NMH BASIC
       By Nils M Holm, 1991-1994,2023-2025
       MAIL: fs29@rummelplatz.uni-mannheim.de (DEFUNCT!)

       NMH BASIC is free software, do whatever you want with it.
       If it breaks something, don't blame me!



                                                        BASIC(1)
 

contact | privacy