Yabasic Additions and Modifications


Table of Contents

  1. Introduction
  2. Interactive Console
  3. Functions
    ucase$(), lcase$() - convert a string to upper case, lower case
    ucfirst$(), lcfirst$() - convert the first character of a string to uppercase, lowercase
    environ$() - return an environment variable
    space$() - return a string of space characters
    string$() - return a string of a single character
    join$() - return a string joined with elements of an array
    pos() - return the cursor column
    csrlin() - return the cursor row
    kill(), unlink() - delete a file
    peek$ - retrieve various internal string-information
  4. Statements
    environ - set an environment variable
    system - terminate the program and return to operating system
    shell, shell() - start a new command shell, send a command to the command shell
    cls - clear the screen
    poke - change selected internals of yabasic
    clear screen - erases the text window
    color - print with color

Introduction

This document describes Yabasic version 2.75105, an experimental version of Yabasic 2.751 built for Windows with several additions and modifications. The Windows binary is packaged in the file yabasic-2.75105.win32.zip which also includes all the files distributed with Yabasic 2.751. Modified source files are in the file yabasic-2.75105.src.zip. While the modified source files should compile on Linux, most of the additions and modifications are not tested on Linux, and some are either not applicable, or are known to cause problems. See the file yabasic-2.75105.txt for additional notes.

The home page for Yabasic is http://www.yabasic.de/ were you will find the current version and main documentation. The home for this experimental version is http://www.mhuffman.com/resource/basic/. The numbering system for this version adds .00001 incrementally to the base Yabasic version it was derived from. For example: 2.75101, 2.75102, etc.

Yabasic is a traditional BASIC interpreter, however it is not a QBasic clone (QBasic shipped with versions of Microsoft DOS 5.0 through Windows 95). The author of Yabasic has added many useful functions and statements with some noticeable roots from the UNIX shell, C, and perhaps Perl. He has also omitted some QBasic functions and statements, implemented identical functionality with different key words, and implemented slightly different syntax in places. The additions and modifications described here are intended to add a bit more compatibility with QBasic and GW-Basic; and to add some additional functionality I personally find useful.


Interactive Console

The vast majority of additions and modifications are merely "syntactic sugar" added to an already fine BASIC interpreter implementation. The most noticeable difference, however, is the modified interactive console, which was inspired directly by Python.

BASIC stands for Beginners All-purpose Symbolic Instruction Code . A beginning programmer is more likely to experiment with ideas and sample code fragments if the code is easy to enter and experiment with. While high-level language interpreters are a vast improvement over most compiler environments, one usually must open a text editor, possibly set up a working directory structure, usually open a command-line console, then repeat an edit-save-run cycle. This implementation of Yabasic supports an interactive console where statements can be entered and evaluated immediately without closing the console; and the interactive session command history is accessible during the session and can be saved to a disk file.

Using this version of Yabasic in interactive mode is as simple as:

Example

C:\>yabasic
This is yabasic version 2.75105 built on Windows Sun Jul 25 21:35:53 2004

Copyright 1995-2004 by Marc-Oliver Ihm

Enter Yabasic statements; End of File (Ctrl-Z / Ctrl-D) to quit.
s$ = peek$("history", "filename") appends console buffer to filename.
See the documentation within the start-menu for more information.
: a = 3 : b = 8
: print a + b, "\t", a - b
11      -5
: do
+   input "Enter a number, 'Q' to quit: " n$
+   if (ucase$(left$(n$, 1)) = "Q") break
+   for i = a to b
+     print val(n$) * i, "\t";
+   next i
+   print
+ loop
Enter a number, 'Q' to quit: 2.33
6.99    9.32    11.65   13.98   16.31   18.64
Enter a number, 'Q' to quit: q
: h$ = peek$("history", "history.txt")
: shell("dir history.txt | find \"history.txt\"")
07/25/2004  09:46 PM               286 history.txt
: ^Z

C:\>

The example shows an interactive session where some single-line statements are executed, a for loop inside a do loop, then the history buffer is saved to the file history.txt. A shell command is run to verify the file, and finally the interactive session is terminated. The resulting history file is shown below.

# Yabasic history: Sun Jul 25 21:45:27 2004
a = 3 : b = 8
print a + b, "\t", a - b
do
  input "Enter a number, 'Q' to quit: " n$
  if (ucase$(left$(n$, 1)) = "Q") break
  for i = a to b
    print val(n$) * i, "\t";
  next i
  print
loop
h$ = peek$("history", "history.txt")

See also

peek, ucase, shell


New and Modified Functions

ucase$()

Name

ucase$() — convert a string to upper case

Synopsis

u$ = ucase$(a$)

Description

The ucase$() function accepts a single string argument and converts it to all upper case. Duplicates the upper$() function; added for compatibility with QBasic and GW-Basic.

Example

    repeat
        line input "Enter a string, 'Quit' to exit: " input$
        print "You entered: ", input$
    until (ucase$(input$) = "QUIT")
    

This example prompts for input, and converts the input string to all upper case so that it can make a single test against the string literal "QUIT"

See also

lcase, ucfirst lcfirst

lcase$()

Name

lcase$() — convert a string to lower case

Synopsis

l$ = lcase$(a$)

Description

The lcase$() function accepts a single string argument and converts it to all lower case. Duplicates the lower$() function; added for compatibility with QBasic and GW-Basic.

Example

    input "User Name: " uname$
    if (uname$ <>> lower$(uname$)) error "User names must be all lowercase."
    

This example prompts for a user name and checks if it is all lower case.

See also

ucase, ucfirst, lcfirst

ucfirst$()

Name

ucfirst$() — convert the first character of a string to uppercase

Synopsis

uf$ = ucfirst$(a$)

Description

The ucfirst$() function accepts a single string argument and converts the first character to upper case.

Example

input "Enter your first name: " fname$
input "Enter your last name:  " lname$
print ucfirst$(lcase$(fname$)) + " " + ucfirst$(lcase$(lname$))

This example converts each input string to "capital case." Example input and output:

Enter your first name: boris
Enter your last name:  BADENOV
Boris Badenov

See also

lcfirst, ucase, lcase

lcfirst$()

Name

lcfirst$() — convert the first character of a string to lowercase

Synopsis

lf$ = lcfirst$(a$)

Description

The lcfirst$() function accepts a single string argument and converts the first character to lower case.

Example

    words$(0) = "zero" : words$(1) = "ONE" : words$(2) = "TwO" : words$(3) = "thREE"
    for i = 0 to 3
        print lcfirst$(words$(i)),
    next i
    

This example will print:

    zero    oNE     twO     thREE
    

See also

ucfirst, ucase, lcase

environ$()

Name

environ$() — return an environment variable

Synopsis

evar$ = environ$(key$)

Description

The environ$() function requires one augment, the name of an environment variable; and returns the value of the environment variable. This function duplicates the action performed by peek$("env","NAME") and is added for compatibility with QBasic and GW-Basic.

Example

    if (environ$("OS") = "Windows_NT") then
        print "Probably Windows 2000 or XP"
    else
        print "Probably Windows ME, 98 or 95"
    endif
    

This example reports a best guess of the user's operating system based on the OS environment variable.

See also

environ statement, peek, poke

space$()

Name

space$() — return a string of space characters

Synopsis

pad$ = space$(n)

Description

The space$() function takes a numeric argument and returns a string containing that number of spaces.

Example

    item$ = "Basketball,103,Gas Grill,8,Rowing Machine,20,Lawn Mower,4"
    dim part$(1)
    n = token(item$, part$(), ",")
    name_width = 20

    field1$ = "Item Name"                   // record field names
    field2$ = "On Hand"
    pad = name_width - len(field1$)         // calculate number of spaces
    print field1$, space$(pad), field2$     // pad string with trailing spaces
    print string$(len(field1$), "-"), space$(pad), string$(len(field2$), "-")

    for i = 1 to n step 2                   // count by 2's (record has 2 fields)
        name$ = part$(i)
        onhand = val(part$(i + 1))
        pad = name_width - len(name$)       // calculate number of spaces
        print name$, space$(pad), str$(onhand, "%3.0f")
    next
    

This example uses several Yabasic functions to format data records in columnar format producing the following output:

    Item Name           On Hand
    ---------           -------
    Basketball          103
    Gas Grill             8
    Rowing Machine       20
    Lawn Mower            4
    

See also

string

string$()

Name

string$() — return a string of a single character

Synopsis

c$ = string$(n, char$)

Description

The string$() function takes 2 arguments: one numeric argument and one string argument. It returns a string equal in length to the numeric argument composed of the first character in the string argument.

Example

    title$ = "The Adventures of Rocky and Bullwinkle"
    title_len = len(title$)
    page_width = 80
    n = int((page_width - title_len) / 2)

    print space$(n), title$
    print space$(n), string$(title_len, "*")
    

This example centers a title on a screen 80 columns wide "underlined" with a string of '*' characters the same length as the title.

See also

space

join$()

Name

join$() — return a string joined with elements of an array

Synopsis

a$ = join$(str$, str_array$()), a$ = join$(str$, num_array())

Description

The join$() function takes 2 arguments: a string of zero or more characters; and either a string array reference or a number array reference. A string is returned with the string argument placed between each element of the array. In the case of multi-dimensional arrays all dimensions of the array are joined beginning with each element of the first dimension, then the next dimension, etc.

join$() is more or less the opposite of token(), but not quite. The string returned from an array joined with j$, then later tokenized (using token()) using j$, will have one more element than the original array because token() (and split()) return arrays with an empty first element. Also, while join$() can join arrays of strings or numbers, token() and split() always return a string.

Example

    dim parts(7)                            // 8-element array of numbers
    for i = 0 to arraysize(parts(), 1)
        parts(i) = 2^i                      // fill with powers of 2
    next i

    glue$ = ", "
    joined_str$ = join$(glue$, parts())
    print joined_str$                       // "1, 2, 4, 8, 16, 32, 64, 128"

    dim tokenized$(1)
    n = token(joined_str$, tokenized$(), glue$)     // 9-element array of strings
    print arraysize(parts(), 1), n, arraysize(tokenized$(), 1)  // 7 8 8

    dim parts2(arraysize(tokenized$(), 1) - 1)      // 1 element smaller than tokenized$()
    for i = 0 to arraysize(parts2(), 1)
        parts2(i) = val(tokenized$(i+1))            // convert strings back to numbers
    next i
    

This example creates and fills an array of numbers, then joins the array with a comma and a space. To demonstrate the relationship between join$() and token() the example code creates a second array from the string returned by join$() using the same "glue" string for the token. Note that the return value from token() is the same as the return value from arraysize() for the new array, which is 1 greater than the original array of numbers. Note also that the new array is an array of strings. Finally, a third array of numbers is created (1 element smaller than the second array) and filled with the value of each string element from the second array, starting with the second element (because token() returns arrays with an empty first element).

See also

token, split

pos(), pos(n)

Name

pos(), pos(n) — return the cursor column

Synopsis

col = pos(), col = pos(n)

Description

The pos() function returns the 0-based cursor column (e.g. the first column is 0) The alternate form with a single numeric argument is for compatibility with QBasic and GW-Basic; the argument is simply a dummy parameter and is ignored. Like other "advanced" screen functions, the clear screen statement must be issued before calling pos() .

Example

    clear screen
    print pos(), ", ", csrlin()             // 0, 0
    print "pos(), csrlin(): ";
    x = pos()
    y = csrlin()
    print x, ", ", y                        // pos(), csrlin(): 17, 1

    print at(50, 10) pos(), ", ", csrlin()  // 50, 10
    

This example shows the upper-left cursor coordinates as (0, 0) immediately after clear screen, the cursor on column 17, row 1 after printing the string "pos(), csrlin(): " (without printing a newline), and finally matches the coordinates pass as the arguments to at().

See also

csrlin

csrlin()

Name

csrlin() — return the cursor row

Synopsis

row = pos()

Description

The csrlin() function returns the 0-based cursor row (e.g. the first row is 0) Like other "advanced" screen functions, the clear screen statement must be issued before calling csrlin() .

Example

Seepos

See also

pos

kill()

Name

kill() — delete a file

Synopsis

n = kill(file_spec$)

Description

The kill() function accepts one argument: a string that specifies a file, including path if desired, to be deleted. It returns 0 if the file is deleted successfully, otherwise it returns a system error code. kill() is added for compatibility with QBasic and GW- Basic (although those languages implement it as a statement, which does not return a status) and as a convenience. The alternate way to delete files in Yabasic is via the system() or system$() functions, also accept the applicable operating system wild-card characters for file name expansion.

Example

    NUM_RECORDS = 4
    tempfile$ = "temp.txt"

    fh = open(tempfile$, "w")                           // open temp file for writing
    if (not fh) error "Could not open " + tempfile$

    for i = 0 to NUM_RECORDS - 1
        read name$                              // read data records into temp file
        print #fh name$
    next i
    close #fh                                   // close temp file

    name$ = system$("sort " + tempfile$)        // sort file, capturing the output

    dim sorted$(1)                              // new array for sorted records
    dim_max = token(name$, sorted$(), "\n")     // fill array of records
    for i = 1 to dim_max                        //  (5-element array, element 0 is empty)
        print sorted$(i)                        // display sorted names
    next i

    if (kill(tempfile$)) then                   // delete the temp file
        print "File deletion error: " + tempfile$
    else
        print "File deleted: " + tempfile$
    endif

    data "Do-Right,Dudley,017"
    data "Badenov,Boris,010"
    data "Whiplash,Snidely,004"
    data "Fatal,Natasha,008"
    

This example uses the operating system to sort a set of data records that have first been written to a temporary file, then deletes the file. Note that system("del " + tempfile$) (Windows) or system("rem " + tempfile$) (Linux) would also work.

Yabasic does not have a built-in sort function (nor most other "traditional" BASIC implementations that I know of), therefore I could either write my own routine in Yabasic or call on the operating system. Linux and Windows (versions > Win98) have many useful and powerful sort options; and I do not have the confidence that I can improve on the sort routines written by the designers of my operating system. The Yabasic system$() that returns the system's STDOUT makes it practical to let the operating system do some of the work and get the results back into a Yabasic program.

See also

unlink

unlink()

Name

unlink() — delete a file

Synopsis

n = unlink(file_spec$)

Description

The unlink() function duplicates, and is a synonym for, the kill() function.

Example

See kill

See also

kill

peek$

Name

peek$ — retrieve various internal string-information

Synopsis

print peek$("foo")

Description

The following sub-functions have been added to peek$():

peek$("yabasic")

Returns the full path to yabasic.exe that executed this program, or, if the Yabasic program has been bound to yabasic.exe, the full path to the bound program.

peek$("name")

Returns the name of the source file being executed by Yabasic; if the program is bound an empty string is returned.

peek$("fullname")

Returns the full path to the source file being executed by Yabasic; if the program is bound an empty string is returned.

peek$("shortpath", longpath$)

Returns the Windows short path name for a Windows long path.

peek$("history")

Returns the interactive buffer as a string.

peek$("history", "filespec")

Saves the interactive buffer to a file and returns the buffer as a string. The file is opened in append mode: if it already exists the current history buffer will be appended to the end; if the file does not already exist a new file will be created.

Example

    # peek.yab
    # bind command line: yabasic -bind peek.exe peek.yab

    name$ = peek$("name")
    if (peek("isbound")) then
        p$ = peek$("yabasic")
        i = rinstr(p$, "\\")
        name$ = mid$(p$, i+1)
    endif

    print "program name: ", name$
    print

    print "peek$(\"yabasic\"):  ", peek$("yabasic")
    print "peek$(\"fullname\"): ", peek$("fullname")
    print "peek$(\"name\"):     ", peek$("name")

    longpath$ = "C:\Documents and Settings\mike\My Documents\long_name.txt"
    print "longpath:          ", longpath$
    print "shortpath:         ", peek$("shortpath", longpath$)
    

Executed by yabasic.exe (located in D:\Util\) the following output is produced:

    D:\yabasic-2.751\doc>yabasic peek.yab
    program name: peek.yab

    peek$("yabasic"):  D:\Util\yabasic.exe
    peek$("fullname"): D:\yabasic-2.751\doc\peek.yab
    peek$("name"):     peek.yab
    longpath:          C:\Documents and Settings\mike\My Documents\long_name.txt
    shortpath:         C:\DOCUME~1\mike\MYDOCU~1\LONG_N~1.TXT
    

Executed from the same working directory as above, however bound to yabasic.exe as peek.exe, the following output is produced:

    D:\yabasic-2.751\doc>.\peek
    program name: peek.exe

    peek$("yabasic"):  D:\yabasic-2.751\doc\peek.exe
    peek$("fullname"):
    peek$("name"):
    longpath:          C:\Documents and Settings\mike\My Documents\long_name.txt
    shortpath:         C:\DOCUME~1\mike\MYDOCU~1\LONG_N~1.TXT
    

See also

Interactive Mode


New and Modified Statements

environ

Name

environ — set an environment variable

Synopsis

environ "NAME=KEY"

Description

environ sets a system environment variable with a single string of the form "VAR_NAME=VALUE". When Yabasic executes a source file, or when Yabasic runs in interactive mode, it starts a new command shell at the beginning and exits that command shell when the program ends or when the interactive session is terminated. The new environment variable is only available to the current running shell. Any environment variables set within Yabasic will not be available when the program or interactive session terminates.

Example

    # env.yab
    # set new TEMP variable with environ statement

    print "environ$(\"TEMP\") before environ statement: ", environ$("TEMP")

    new_temp$ = "TEMP=" + system$("CD")
    environ new_temp$

    print "environ$(\"TEMP\") after environ statement:  ", environ$("TEMP")
    print "system$(\"echo %TEMP%\"):                    ", system$("echo %TEMP%")
    

This example sets the TEMP variable to the current working directory for the current shell; upon termination of the program TEMP will have its original value. Output from the example on a Windows XP system is shown below bracketed by echo commands to show the value of TEMP before and after execution of the program; environ$() is called to show the value of TEMP within the program's shell.

    D:\yabasic-2.751\doc>echo %TEMP%
    C:\DOCUME~1\mike\LOCALS~1\Temp

    D:\yabasic-2.751\doc>yabasic env.yab
    environ$("TEMP") before environ statement: C:\DOCUME~1\mike\LOCALS~1\Temp
    environ$("TEMP") after environ statement:  D:\yabasic-2.751\doc

    system$("echo %TEMP%"):                    D:\yabasic-2.751\doc


    D:\yabasic-2.751\doc>echo %TEMP%
    C:\DOCUME~1\mike\LOCALS~1\Temp
    

See also

environ$(), poke

system

Name

system — terminate the program and return to operating system

Synopsis

system

Description

Terminates the program and returns to the operating system. Synonym for exit, added for compatibility with QBasic and GW-Basic to facilitate comparing code fragments between the 2 implementations.

Example

    do
        print "Do you want to continue ?"
        input "Please answer y(es) or n(o): " a$
        if (lcase$(left$(a$, 1)) = "n") then
            system
        end if
    loop
    

This example will run almost unaltered under MS QBasic (QBasic requires a coma between the input statement prompt and variable name)

See also

exit

shell, shell()

Name

shell, shell() — start a new command shell, send a command to the command shell

Synopsis

shell, shell(command$)

Description

The shell statement without an argument simply launches a new command shell and remains in the shell until the user enters exit. Used with a command string argument shell is similar to system() or system$(), however as a statement it does not return a value. Added for compatibility with QBasic and GW- Basic as well as a convenience so that a "throw away" variable does not need to be assigned when a return value is not needed.

Example

    clear screen
    print "Please verify that the file foo.ini is in the current directory"
    print "and that the [BAR] section contains the following line:"
    print
    print "  buffer: .\\tmp.txt"
    print

    do
        input "[S]tart a command shell; [E]dit foo.ini; [C]ontinue: " a$
        if (ucase$(left$(a$, 1)) = "S") then
            shell : break
        elsif (ucase$(left$(a$, 1)) = "E") then
            shell("edit foo.ini") : break
        elsif (ucase$(left$(a$, 1)) = "C") then
            break
        else
            print "Enter S, E, or C"
        endif
    loop

    shell("type foo.ini")
    print "Press any key to continue...";
    a$ = inkey$
    

This example allows a user to open a shell to perform directory/file maintenance, directly edit a file, or continue with the program.

See also

system

cls

Name

cls — clear the screen

Synopsis

cls

Description

Clears the screen with a call to system("cls") under Windows or system("clear") under Linux. Added for compatibility with QBasic and GW-Basic, brevity, and originally as a kludge to clear the screen without changing the default screen color attributes. Note that cls is not a synonym for clear screen; you must still call clear screen before using any of the advanced I/O functions and statements such as print at(), etc.

Example

    cls                         // clears the screen
    print at(5, 5) "test"       // Error: need to call 'clear screen'
    

See also

clear screen

poke

Name

poke — change selected internals of yabasic

Synopsis

poke "foo", "bar"

Description

The following sub-function has been added to poke:

poke "env", "VAR_NAME=VALUE"

Sets a system environment variable; duplicates the environ statement, with the same limitations on the scope of the variable being set.

Example

    new_temp$ = "TEMP=" + system$("CD")
    poke "env", new_temp$
    

This example sets the TEMP variable to the current working directory for the current shell

See also

environ

clear_screen

Name

clear_screen — erases the text window

Synopsis

erases the text window

Description

Under Windows 2000 or XP a user can control the console (command prompt) window foreground and background colors, either via the properties dialog, or the COLOR command. Yabasic sets a gray foreground on black background when clear screen is called regardless what attributes a user was previously using. This implementation of Yabasic preserves the user's screen attributes and uses them for clear screen and subsequent I/O on the console.

Example

See the main Yabasic documentation

See also

color

color

Name

color — print with color

Synopsis

    print color(fore$) text$
    print color(fore$, back$) text$
    

Description

Not a separate command, but part of the print-command; may be included just after print and can only be issued after clear screen has been executed.

color() takes one or two string-arguments, specifying the color of the text and (optionally) the background. This implementation of Yabasic expands the original 8 colors to 16 colors as supported by Windows 2000 and XP.

The one or two strings passed to color() can be one of the following:

Original Yabasic Colors
Full Name Abbreviation Windows
Attribute
"black" "bla" "0"
"blue" "blu" "1"
"green" "gre" "2"
"cyan" "cya" "3"
"red" "red" "4"
"magenta" "mag" "5"
"yellow" "yel" "E"
"white" "whi" "7"
Additional Colors
Full Name Abbreviation Windows
Attribute
"gray" "gra" "8"
"light blue" "lbl" "9"
"light green" "lgr" "A"
"aqua" "aqu" "3"
"light aqua" "laq" "B"
"light red" "lre" "C"
"purple" "pur" "5"
"light purple" "lpu" "D"
"gold" "gol" "6"
"bright white" "bwh" "F"
Notes
  1. "aqua" and "purple" are synonyms for original Yabasic names "cyan" and "magenta" respectively.
  2. "gold" maps to "yellow" since Yabasic already uses yellow for "light yellow".
  3. Support has also been added for the use of the same hexadecimal codes that the Windows COLOR command uses. Note, however, that Yabasic requires one or two string arguments, therefore the equivalent Windows attributes must be quoted.
  4. color() string arguments are not case sensitive.

color() can only be used, if clear screen has been issued at least once.

Example

clear screen
for i = 0 to 15
    fg$ = hex$(i)
    for j = 0 to 15
        bg$ = hex$(j)
        print color(fg$, bg$) " " + fg$ + bg$ + " ";
    next j
    print
next i

This example prints a table of all possible color combinations using the equivalent Windows color attribute codes.

See also

clear_screen


Revised: 26 JUL 2004