yabasic, yet
another basic
for Unix and Windows
Current Version: 2.20
This document describes the syntax and features of yabasic.
In short, yabasic implements the most common (and simple)
elements of the basic-language, plus some graphic facilities;
anyone, who has ever written basic-programs on a C64
should feel at home.
This page covers all the features of yabasic, you don't need
any other text to learn it. In fact, there is no other text about
yabasic, neither a unix-man-page nor a Windows-helpfile.
This text doesn't teach basic from scratch, it rather assumes
some experience with the basic-programming-language.
Special thanx to Michael Cwikel for editing
this document !
There are three way to start yabasic:
1. |
You may write your basic-program to a
file (e.g. foo.yab) and call yabasic with this file as an
argument:
yabasic foo.yab
will make yabasic execute your program and terminate
if done.
|
2. |
You may start you yabasic without any
filename. Typing just
yabasic
makes yabasic start and prompt for a program to
execute; after you have typed in your program, press RETURN
twice and yabasic will execute your commands. This
behavior allows yabasic to be used as some sort of fancy
desktop calculator.
|
3. |
You may put your program into a file and
insert the following text as the very first line:
#!/usr/bin/yabasic
This is only an example and you should substitute for /usr/bin/yabasic
the full pathname of yabasic on your computer. Yabasic
will treat the line starting with #!
as a comment, but Unix will invoke yabasic to execute
this program.
|
Back to table of contents ...
-h
- Prints out a short help message;
-help
or -?
are accepted as well.
-fg
foreground-color
- Sets the foreground color for graphics. The usual X
colornames like red, green are accepted.
-bg
background-color
- Sets the background color.
-geometry
geometry-string
- The usual X geometry-string will work (e.g.
+10+10
),
but any window size will be ignored.
-display
Name-of-Display
- Name of the Display, where the window should appear.
-font
Name-of-font
- Name of the font, which will be used for graphics text.
-i
- Sets the initial infolevel. This
controls the amount of information one gets about the
progress of program execution, Every level contains all
lower levels (e.g.
w
contains f
and e
)
and can be one of:
d
- Set the infolevel to diagnostic
: This gives detailed debugging information;
much more output than you'd probably like to
read.
n
- note : Useful
information; e.g. about execution time and memory
consumption.
w
- warning :
Gives you warnings, that something has gone wrong
(e.g. division by zero); nevertheless execution
proceeds.
e
- error : A
serious error (e.g. an array boundary violation)
has occurred, stopping the program.
f
- fatal :
Something has gone wrong and cannot be fixed; the
interpreter exits immediately. This happens most
often in the course of an arithmetic fault
(floating point exception) but can also be a sign
of an internal error within yabasic.
The default infolevel is w
.
- -licence
- This makes yabasic print out its copyleft; have a look
and you will see, that almost anything is allowed.
-
- Back to table of contents
...
The colors, text-font and the window position should be set on
the command-line , or specified in the
users resource file (this is usually the file .Xresources in your
home-directory); e.g.:
yabasic*foreground: blue
yabasic*background: gold
yabasic*geometry: +10+10
yabasic*font: 9x15
This sets the foreground of the graphics-window
to blue, the background to gold, the window will appear at
position 10,10 and the text-font will be 9x15.
Back to table of contents ...
After you have run the setup program, yabasic can be invoked
in three ways:
1. |
Choose "yabasic" within the start-menu:
Yabasic will come up with a console window and will wait
for a program to be typed in directly. |
2. |
Click with the right mousebutton on your desktop.
Choose "new" within the context-menu that
appears; this will yield a new icon on your desktop. This
icons context-menu has the two entries
"execute" and "edit"; a double-click
executes the program. |
3. |
Create a file containing your yabasic-program. This
file should have the extension ".yab".
Double-click on this file then invokes yabasic, to execute
your program. |
Back to table of contents ...
-h
- Prints out a short help message;
-help
or -?
are accepted as well.
-geometry
geometry-string
- E.g.
+20+10
will place the
graphic-window 10 pixels below and 20 pixels left of the
upper left corner of the screen.
-font
Name-of-font
- Name of the font which will be used for graphics text.
Can be any of:
decorative, dontcare, modern, roman,
script, swiss
You can append (without space) a fontsize to any of these
identifiers, i.e. swiss30
chooses a swiss font, 30 pixels high.
-i
- Sets the initial infolevel. This
controls the amount of information one gets about the
progress of program execution, Every level contains all
lower levels (e.g.
w
contains f
and e
)
and can be one of:
d
- Set the inoflevel to diagnostic
: This gives detailed debugging information;
much more output than you'd probably like to
read.
n
- note : Useful
information; e.g. about execution time and memory
consumption.
w
- warning :
Gives you warnings, that something has gone wrong
(e.g. division by zero); nevertheless execution
proceeds.
e
- error : A
serious error (e.g. an array boundary violation)
has occurred, stopping the program.
f
- fatal :
Something has gone wrong and cannot be fixed; the
interpreter exits immediately. This happens most
often in the course of an arithmetic fault
(floating point exception) but can also be a sign
of an internal error within yabasic.
The default infolevel is w
.
- -licence
- This makes yabasic print out its copyleft; have a look
and you will see, that almost anything is allowed.
Back to table of contents ...
To choose the default-values for graphic-font, fontsize and
window position, you have to edit the registry.
Yabasic stores its defaults under:
HKEY_LOCAL_MACHINE/SOFTWARE/Yabasic
You may edit the subkeys "font" and
"geometry"; these subkeys accept the same values as the
corresponding command line options
-font and -geometry. Command
line options take precedence over registry defaults.
Back to table of contents ...
This is the first example:
REM this is the first yabasic-program
input "Enter two numbers:" a,b
print a,"+",b,"=",a+b
print "Please enter your Name:";
INPUT a$
print "Hello ",a$," !"
This program produces the following output (user input is
displayed like this):
Enter two numbers: 2 3
2+3=5
Please enter your Name: Bill
Hello Bill !
This simple program contains three different commands:
- REM
- The REM-statement
introduces comments; everything after REM up to the
end of the line is ignored.
- input
- This statement reads one or more variables from the user.
The optional prompt-string after the input-statement
("Enter a number:")
is printed on the terminal prior to reading any input.
Note that there is no semicolon after this prompt-string.
To learn more about, how input chops a line into pieces
you may refer to the section More
on Input. To learn, how to read input from the
keyboard without delay, check out Getting a key
from the keyboard.
- print
- The print-statement writes all its arguments to the
screen; after writing its last argument, print goes to
the next line (as in print
"Hello ",a$," !"); to
avoid this automatic newline, place a colon after the
last argument (as in print
"Please enter your Name:";).
Note that print can be abbreviated with a single question
mark (?). If you want to print (or input) at a specific
location, you may go to the section Prining on your
Screen.
Furthermore some general properties of yabasic should be
noted:
- Case
- Commands can be entered in any case: input is the
same as INPUT
and even as InPUt.
This applies to every command in yabasic but not to
variables, i.e. a$
and A$
are different variables.
- Variables
- Variable names are case sensitive (i.e. types of
variables: a$
and A$
are different) and can be of any length. There are two
sorts of variables:
-
- String variables
- e.g. a$,
b12$
or VeryLongName$
may contain strings of any length. String
variables always have a Dollar-sign ($) as
the last character of their names.
- Numerical variables
- e.g. a,
c3po
or ThisIsAnEvenLongerName
contain real numbers like 2, -1.3, 15.3e44 or 0.
Variables (with the exception of arrays) need not be
declared, their initial values are "" (for
string variables) and 0.0 (for numerical variables).
Back to table of contents ...
Yabasic has five arithmetic operators: + (addition), - (subtraction), * (multiplication), / (division)
and ^ (power);
they all behave as expected, i.e. this line of code
print 1+2,2*3,4/2,2^3
produces this line of output:
3 6 2 8
Note that the power operator (^)
handles fractional powers: 8^(1/3)
gives 2 as a
result.
This section demonstrates and explains the arithmetic
functions of yabasic.
- Trigonometric
functions:
- There are 6 trigonometric functions:
print sin(1.0),cos(pi),tan(3)
print asin(0.5),acos(0.7)
print atan(2),atan(1,2)
- These lines produce this output:
0.841471 -1 -0.142547
0.523599 0.795399
1.10715 0.463648
- As you can see yabasic can calculate sine, cosine,
tangent and their inverses. And, if you have an eye for
trigonometry, you may have noticed that all these
functions expect their argument in radians; to facilitate
the transformation from degrees to radians (radian=degree*pi/180),
there is a predefined variable named pi (or PI) which has
an initial value of 3.14159.
- Finally note that the atan()-function
comes in two flavors: Called with a
single argument (e.g. atan(2))
atan()returns
a value between -pi/2 ... +pi/2. Called with two
arguments (e.g. atan(2,-1))
atan()
returns a value between -pi and +pi; (This can be useful
e.g. when transforming from cartesian to polar
coordinates).
- Exponentiation:
- The exp()
functions comes with its inverse. the log()-function:
print exp(1),log(2),log(euler)
log()
and exp()
operate with the base e (=2.17828), which comes as a
predefined variable named euler.
Knowing this you won't be surprised to get the following
output:
2.71828 0.693147 1
- Integer
and fractional parts:
- The functions int() and frac() split their argument at
the decimal point:
print
int(2.34),frac(2.34) produces:
2 0.34
- Remainder
- To get the remainder of a division employ the mod()-function;
e.g. mod(11,4)
produces 3,
because when dividing 11 by 4 you get 2 and a remainder
of 3.
- Minimum and
Maximum:
- Return the lower and higher value of their two arguments:
print min(2,3),max(2,3)
gives: 2 3
- The square root:
- is calculated by the sqrt()-function:
print sqrt(2)
gives 1.41421
- Random numbers:
- are returned by the ran()-function;
this function comes in two flavours:
Called without arguments (e.g. print
ran()) you will get a random number
between 0 and 1. Called with a single argument (e.g. print ran(2))
you will get a random number between 0 and the supplied
argument.
The ran()-function
of yabasic uses the ran()-function
of the C standard library, so you had better not expect
too much randomness ...
Back to table of contents ...
To make decisions you have to use the if-statement:
input "Please enter a number" a
if (a>10) then
print "Hello":print "Your number is bigger than 10"
else
print "Byebye":print "Your number is less or equal 10"
endif
As you can see, the condition has to be enclosed in
parentheses (...). The else-part
of the if-statement
is optional and can be omitted, as in this example:
input "Please enter a number" a
if a>10 and a<20 then : rem parantheses are optional ...<
print "bigger than 10":print "but less than 20"
fi
Note that endif
can be written as fi
too.
Next, have a look at the condition (a>10
and a<20)of the if-statement:
- Conditions:
- Numbers or arithmetic expressions can be compared with
the usual relational operators: =
(equal), <>
(not equal), <
(less than), <=
(less or equal), >
(greater than) and >=
(greater or equal).
Strings can be compared with just the same set of
operators, where characters are ordered according to the
ascii-charset; e.g. ("a"<"b")
is true (because "a"
precedes "b"
within the ascii-charset) and likewise ("a"="b")
is false.
More than one comparison can be combined with parentheses
() and
these keywords: or,
and, not; Note that
not
precedes and,
which in turn precedes or
(in the same way as *
precedes +
within arithmetic expressions).
Finally, the enclosing parantheses can be omitted, i.e. if a<10 then ... is
a valid statement.
- Multiple
commands on one line
- Note that more than one command can appear on one line,
as in
print "bigger than 10":print "but less
than 20"
as long as you separate them with colons
(:).
Back to table of contents ...
Basic has always been simple and strong in string-processing;
and yabasic also tries to continue in this tradition:
input "Please enter a word" a$
for a=len(a$) to 1 step -1:print mid$(a$,a,1);:next a
print " is ",a$," reversed !"
If you try this program, you will get this output:
Please enter a word: hello
olleh is hello reversed !
- for-next-loop
- The heart of the above program is the for-loop:
everything from for
to next
is repeated, while the variable (a)
goes from its initial value len(a$)
to its final value 1.
As you might have anticipated, len(a$)
returns the length of its string-argument.
Note the step-clause:
the number after step
(here: -1)
is added to a
after every repetition; in the example the step-clause
makes a
go down with every iteration. If you omit the
step-clause, step 1
is assumed.
Within the for-next-loop above the string-functions len() and mid$() are applied,
but there are many more string functions:
- Getting
pieces out of a string:
- There are three functions which give back parts of a
string:
a$="123456"
print
left$(a$,2),"-",mid$(a$,2,3),"-",right$(a$,3)
gives you the following output:
12-234-456
As you see left$()
cuts off as many characters as specified by its second
argument from the left of your string. right$() cuts
from the right, and mid$()
cuts in the middle, where the first argument is the
starting point and the second one is the length of the
string to be cut out.
Furthermore mid$()
and its friends can even be used to selectively change
parts of a string:
a$="123456":left$(a$,2)="abcd":print
a$
results in
ab3456
As you see only the two leftmost
characters are changed (even though the string "abcd"
contains four characters); the same can be done with mid$() or right$().
- strings
to numbers (and reverse):
- The function str$()converts
its numeric argument to a string:
print str$(12)
gives the string "12"
as a result. The formatting of the number can be
influenced by an optional second argument:
print
str$(12.123455,"%08.5f")
returns the string 12.12346.
The second argument is essentially a format-string as
used by the printf()-function within the C-language, some
examples:
Print-statement
|
Output produced
|
print "==",str$(12.123455,"%08.3f"),"=="
|
==0012.123==
|
print "==",str$(12.123455,"%8.2f"),"=="
|
== 12.12==
|
print "==",str$(12.123455,"%-6.2f"),"=="
|
==12.12 ==
|
Further information can be found in any textbook on
the C-language.
Just the opposite is done by the function val(): print 2+val("23")
gives 25
as a result, whereas print
val("e2") delivers 0 (because "e2"
is not a valid number).
- The ascii-charset:
- yabasic offers two functions to work with the
ascii-charset. asc()
gives you a specific ascii-character: print asc("e")
gives 101 as a result, because the character "e"
has position 101
within the ascii-charset. Likewise the function chr$() returns
the ascii-char for a given position within the charset,
e.g. chr$(98)
returns "b".
- Escape-sequences
- Nevertheless you won't use chr$()
as often as you might think, because the most important
nonprintable characters can be constructed using
escape-sequences with the \-character:
You might use \n
instead of chr$(10)
wherever you want to use the newline-character.
- The following table lists all escape sequences of yabasic
(of course, these are just the sequences known within the
C-language):
Escape-sequence |
Resulting Char |
\n |
newline |
\t |
tabulator |
\v |
vertical tabulator |
\b |
backspace |
\r |
carriage return |
\f |
formfeed |
\a |
alert |
\\ |
backslash |
\` |
single quote |
\" |
double quote |
These escape sequences are replaced within every pair of
doublequotes (""),
i.e. within literal strings; user input read with the input-statement
is not affected in any way.
Finally note, that escape sequences have a profound
impact, when specifying Window-pathnames.
-
Here is another example which introduces the rest of yabasic's
string-functions:
label loop
print "Please enter a string containing the word \"yabasic\""
input a$
if (instr(lower$(a$),"yabasic")<>0) then
gosub thanx
else
print "No, please try again !"
endif
goto loop
label thanx
print "Thanks a lot !"
return
If you run this program you will receive the following output:
Please enter a string containing the word "yabasic"
?thequickbrownfox
No, please try again !
Please enter a string containing the word "yabasic"
?jumpedyabasicoverthelazydog
Thanx.
- Marking
locations in a program
- The first line in the example-program (label loop) is
a label: As yabasic has no line-numbers, you need labels
to mark a specific location within your program. You can
compose labels out of letters and digits; the keyword label is
required and the label itself should be unique within
your program. Note that yabasic allows for line numbers too.
- Jumping
around in your program
- A label by itself causes no special action. Only in
conjunction with the goto-statement
(or gosub
or restore)
does a label have any function. If yabasic encounters a goto-statement
(here: goto loop)
then it searches for the matching label (here: label loop)
and proceeds to execute at the position of the label.
Note that you can even leave (and enter !) a for-next
loop with goto.
Closely related to the goto-command
is the gosub-command;
if yabasic encounters a gosub-statement
then it searches for the matching label (label thanx in
the example) and proceeds with execution at the position
of the label, until it finds a return-statement.
return
makes yabasic return to the position of the original
gosub and proceed from there.
Note that both goto
and gosub
can be used as on goto
and on
gosub.
- Finding
strings in strings
- The example program above checks whether the user input
contains the string "yabasic";
this is done with the help of the instr()-function;
instr()
gives back the position of its second string-argument
within the first or zero, if it can't be found. E.g. instr("Hallo","al")
gives back 2, because "al"
appears at position 2 within "Hallo";
whereas instr("Hallo","Al")
returns 0, because "Al"
is not contained in "Hallo"
(the case doesn't match).
- Changing
the case of strings
- The sample-program contains some further
string-functions: lower$()
and its counterpart upper$()
convert their string-argument to all lower or all upper
case characters respectively, i.e. lower$("aBcD12fG")
gives back "abcd12fg".
Back to table of contents ...
Yabasic provides some functions for simple graphics:
open window 400,400
line 0,0 to 400,400
circle 200,200,150
dot 200,200
a$=inkey$
clear window
text 100,200,"Hello !"
print "Press a key to close the window"
inkey$
close window
- Drawing
- If you run this program, you will see a window with size
of 400 pixels in x- and y-direction (the window size is
given along with the open
window-statement). Not surprising: The line-command
draws a line, the circle-command
draws a circle (the arguments determine x- and y-position
of the center and the radius of the circle) and the dot-command
draws a single dot at the specified location.
After the user has pressed a key (see the next paragraph)
the window contents is cleared with the clear window-statement.
Afterwards the text-statement
writes its text at the specified position.
Finally close window
closes the graphics-window.
- Getting
a key from the keyboard
- But before the window is closed, the inkey$-statement
waits, until the user presses any key and returns this
key as a string. In this example the key, which is
actually pressed is not important, so you may just write inkey$
(without assignment). Unlike other versions of basic,
yabasic's inkey$
waits until the user presses a key, so that you will
never receive an empty string. Many nonprintable keys
(e.g. the function or cursor keys) are returned as
strings: up, down, left, right, f1, f2, f3, f4,
f5, f6, f7, f8, f9, f10, f11, f12, esc, ins, del, home,
end, scrnup, scrndown, enter, tab, backspace, ctrl-w,
ctrl-e, ctrl-r, ctrl-t, ctrl-u, ctrl-o, ctrl-p, ctrl-a,
ctrl-d, ctrl-f, ctrl-g, ctrl-h, ctrl-j, ctrl-k, ctrl-l,
ctrl-y, ctrl-x, ctrl-v, ctrl-b, ctrl-n. If your
keyboard gives other keycodes than mine, or if you press
a key, which is unknown to yabasic, you will receive a
rather lengthy string (e.g. key1b5b31317e).
- Printing
- Getting a hardcopy of your graphics involves two new
commands:
open window 200,200
open printer
circle 100,100,80
close printer
close window
- Everything between open
printer and close
printer appears on paper. If you prefer
sending your hardcopy to a file, you may add a filename,
e.g. open printer
"foo" sends the output to the
file foo.
Note that the open
printer statement has to appear after the
window has been opened. close
printer can be omitted; it is done
automatically, if the window is closed.
Back to table of contents ...
Now and then the need arises to supply a program with initial
data. The next sample-program converts numbers to strings:
restore names
read maxnum
dim names$(maxnum)
for a=1 to maxnum:read names$(a):next a
label loop
input "Please enter a number: " number:number=int(number)
if (number>=1 and number<=maxnum) then
print number,"=",names$(number)
goto loop
endif
print "Sorry, can't convert ",number
label names
data 9,"one","two","three","four","five","six"
data "seven","eight","nine"
If you run this program, it goes like this:
Please enter a number: 2
2=two
Please enter a number: 3
3=three
Please enter a number: 8
8=eight
Please enter a number: 12
Sorry, can't convert 12
- Reading Data
- As you see this program just converts numbers to their
textual representation; for this purpose, it needs to
know the numbers from 1 to 9 as text. This information is
stored in the data-lines
at the bottom of the program: With the read-command
the program gets one piece of data after the other.
If you want to deviate from the linear ordering while
reading the data-statements,
you may use the restore-statement:
In the example above restore
names makes sure, that the next read-statement
reads its data after the label names.
- Arrays
- In the example above the words "one" ...
"nine" are stored within a string-array names$(). You
may use arrays to process large quantities of data. There
are numerical arrays as well as a string-arrays, but both
sorts of arrays need to be declared prior to their first
use; this is necessary, because yabasic needs to know,
how much memory has to be reserved for the array. The
example uses dim
names$(maxnum) to declare a string array,
another example would be dim
numbers(200) to create a numerical array
with 200 elements.
More complex tasks may even require multidimensional
arrays with more than one index: dim
matrix(10,10) defines a two dimensional
array. Array-dimension can be up to ten, if needed.
It should be mentioned, that the functionality of the above
sample-program can be achieved by using totally different
language-constructs:
label loop
input "Please enter a number: " number:number=int(number)
on number+1 gosub sorry,one,two,three,four,five,sorry
goto loop
label sorry:print "Sorry, can't convert ",number:end
label one:print "1=one":return
label two:print "2=two":return
label three:print "3=three":return
label four:print "4=four":return
label five:print "5=five":return
This program produces the same output as the example above.
- on gosub, on goto
- The heart of this sample is the on
gosub-statement, which is followed by a
list of labels (sorry,one,two,...).
Depending on the value of the expression (number+1) the
corresponding label in the list is chosen: E.g. if number+1 gives
3, the third label (three)
is selected and a gosub
to this label is performed.
- A gosub
is always performed, regardless of the value of the
expression. More specifically, if number+1 gives
anything less or equal to 1, then the first label (sorry) is
chosen; if number+1
gives anything greater or equal to the number of elements
in the list (which is 7 in the example), then the last
label (sorry)
is chosen. Therefore the label sorry
is chosen whenever the program can't convert the given
number.
Finally, note that the on-construct
can be used as on goto too.
- End of your program
- Another new appearance in the above sample is the end-statement,
which ends your program immediately.
Back to table of contents ...
To understand the examples in this section, let us assume that
a file named test.dat exists in the current
directory and that it contains the following three lines:
one two three
four five
six seven eight nine
The next example opens that file and prints out its content:
open 1,"test.dat","r"
label loop
if (eof(1)) then end fi
input #1 a$,b$
print "a$=\"",a$,"\", b$=\"",b$,"\""
goto loop
- Opening a file
- The first thing to do if you want to use a file is to
open it: open
1,"test.dat","r"
opens the file test.dat
and gives it the file number 1.
This file number is used to refer to the file later on
(e.g. input #1).
File numbers can range from #1
to #9,
the hash is traditionally required. The optional third
argument ("r")
of the open-statement gives the filemode; depending on
whether you want to open a file for reading or writing
you should choose a different mode. Filemodes are
borrowed from the C-language; here are the possible
choices:
Filemode |
Result |
"r" |
Open file for reading, start reading at the
beginning of the file |
"w" |
Open file for writing, overwrite old contents |
"a" |
Append to an existing file for writing or
open a new one if no file with the specified name
exists |
If you are done with a file, you should close it,
making the file number available for another
open-statement.
- Specifying
Window-pathnames
- Be careful, when specifying an absolute pathname: "C:\yabasic\test.dat"
is not a valid pathname, because the sequence "\t" within
this string is interpreted as an escape sequence, and will be
translated into the Tab-character. To
avoid problems like these, you should always double your
backslashes like
"C:\\yabasic\\test.dat",
because "\\" is
an escape sequence and translated into "\".
- Reading and Writings
- You can write to file just the same way as you would
write to your screen; the only difference is the file
number, that comes with the print-statement: print #1 "Hello"
writes the string "Hello"
to the file with file number #1;
note that there is no comma between the file number (#1) and the
text to be written ("Hello").
Reading works the same way: input
#1 a$, reads the variable a$ from the
file with file number #1.
Back to our sample program. If your run it, you will get the
following output:
a$="one", b$="two three"
a$="four", b$="five"
a$="six", b$="seven eight nine"
- End of File
- As you can see, the program loops until the file has been
fully read; this is achieved by means of the
end-of-file-function eof(1),
which returns false, if there are more
characters in the file, whose file number is given as an
argument, and returns true if the end of
the file has been reached.
- More on input
- You may already have been wondering about how the three
lines of test.dat are distributed among
the variables of the input-statement; There are three
rules:
- Every input-statement reads exactly one line;
(e.g. "one two three")
- The contents of this line is chopped into words
separated by spaces or tabs; in the example the
line consists of three words: "one",
"two", "three"
- Every variable gets one word, except for the last
one, which receives all of what is left of the
line: a$
receives "one" and b$
(which is the last variable of the input-statement)
receives the rest of the line, i.e. "two
three". As a special case of these rules, if
the input-statement
contains just one variable (e.g. input #1 a$)
this variable receives the whole line unmodified.
This behaviour is the same regardless of whether you
read from a file (using input
#1 a$) or from the terminal (using input a$).
Back to table of contents ...
Although yabasic is by no means designed as a
scripting-language, it can interact with the Operating System in
a limited way:
if (yabos$="unix") then
command$="ls"
else
command$="dir /w"
endif
cont$=system$(command$)
print "This is the contents of the current directory:"
print cont$
print len(cont$)," characters have been printed."
The system$()-function
is the heart of this program: It hands its argument over for
execution to the shell of the underlying operating system; under
Unix it is the bourne-shell sh and under Windows
it is command.com, which will execute the
argument of the system()-function.
If I run this program under Windows95, I receive the following
output:
This is the contents of the current directory:
Datenträger in Laufwerk C: heißt WIN95
Seriennummer des Datenträgers: 0B1D-10F8
Verzeichnis von C:\WINDOWS\Desktop
[.] [..] FLOPPY.LNK EMACS.LNK DRUCKER.LNK
T.YAB TELNET.LNK TEST.YAB MICROS~1.LNK CD.LNK
PLATTE.LNK WATCOM~1.LNK [YABDOK~1] TEST.DAT WINDOW~1.LNK
[KINO]
12 Datei(en) 2.693 Bytes
4 Verzeichnis(se) 199.753.728 Bytes frei
456 characters have been printed.
Of course, you may get something different on your system.
As this yabasic-program runs under Unix, as well as under
Windows, the argument of the system$()-function
(command$) has
to be chosen according to the operating system. To find out,
what the operating system is, there is a predefined variable
named yabos$,
which either contains "unix" or "windows".
Finally, there is a very similar command named system() (without a
trailing $),
which doesn't catch the output of the executed command, which
instead goes directly to your terminal. system()
returns a numerical value, which is generated by the executed
command. If you don't care about this value, you can safely
ignore it; e.g. system("dir")
(without assignment) is just as valid as a=system("dir").
Back to table of contents ...
For interactive programs you might want to print output at
specific locations. Try the next example:
clear screen
print at(10,5) "1 -- Setup"
print at(10,7) "2 -- Save"
print reverse at(10,9) "3 -- Quit"
input at(5,12) "Your choice: " a$
If you run this program, you will get a screen resembling the
following layout (note that the third line will be displayed in
reverse video):
1 -- Setup
2 -- Save
3 -- Quit This line is displayed in reverse !
Your choice:
This is not a very fancy screen layout, but it might be enough
for many tasks. Before you can do any such things, you have to
call clear screen ,
which leaves your terminal blank.
Afterwards, you may use the at()-clause
in print or input-statements to move to any location (specified
by the two arguments of the at()-clause)
on your screen. Note that at()
can be written as @()
too.
Since not all terminals have the same size (of course 80x25 is
the most common size), you might want to know what are the actual
dimensions of your screen; There are two predefined variables for
this purpose: The width of your screen can be found in yabscreenwidth, its
height in yabscreenheight;
both variables have meaningful values only after the first call
to clear screen.
To emphasize a piece of text you may use the keyword reverse, which prints
the line in reverse video.
Back to table of contents ...
Some properties of yabasic are still left to explain; here is
a sample program, that employs them:
10 beep
pause 1
goto 10
This program beeps once every second:
- beep
does the beeping (can be written as bell too) and
- pause
does the waiting (can be written as wait too), its
argument is the delay in seconds
Finally, the program employs a line
number (10)
to mark a specific line; this feature makes yabasic more
compatible with traditional basics. Line numbers are just special
types of labels; they have the following properties:
- Line numbers can appear only at the beginning of a line.
- Not every line needs a number and line numbers need not
be consecutive.
- Line numbers can be used with the restore-statement
too.
A feature you might need is the ability to suppress
keyboard-interrupts (i.e. pressing of Ctrl-C);
normally yabasic terminates immediately, if the user presses Ctrl-C.
This can be suppressed like this:
on interrupt continue
After processing of this statement keyboard
interrupts are completely ignored. The default behaviour is
restored with the command
on interrupt break.
Back to table of contents ...
+,-,*,/,^ ? @ : #
A: acos() and asc() asin() at() atan()
B: beep bell break
C: chr$() circle clear screen clear window close close
printer
close window continue cos()
D: data dim dot
E: else end endif eof() euler exp()
F: fi for frac()
G: gosub goto
H:
I: if inkey$ input input at input
#
instr() int() interrupt
J:
K:
L: label left$() len() line log() lower$()
M: max() mid$() min() mod()
N: next not
O: on
gosub
on goto open open
printer
open window or
P: pause pi print print at print
#
printer
Q:
R: ran() read rem restore return reverse right$()
S: sin() step sqrt() str$() system() system$()
T: tan() text then to
U: upper$()
V: val()
W: wait window
X:
Y: yabos$ yabscreenheight yabscreenwidth
Z:
Back to table of contents ...
Arrays
Case of Keywords and Variables
Conditions in the if-statement
Escape Sequences within strings
How the input-statement
chops a line into pieces
Keyboard interrupts
Line numbers
Multiple commands in
one line
Specifying
Windows-pathnames
Variables
Back to table of contents ...
History
I started off with yabasic sometime around eastern 1995; a
first version was completed about one month later, still missing
many features. After this quick start a long period of adding
features and squashing bugs followed, which has more or less
persisted until today.
The only interruption during those peaceful days came in the
summer of 1996, when I got my Windows95-machine: Porting yabasic
took two weeks and writing an installation program took me a
month.
Flex and Bison
You may have noticed from the previous section, that yabasic
made quite a rapid start; this is mainly due to flex and
bison, the prime tools, used to implement
yabasic.
Bison and flex take the grammar (written in a simple,
Backus-Nauer-style notation) and produce a C-program, which
implements this grammar. The only thing left to the programmer is
to put flesh on this skeleton.
This process is remarkably efficient: 17 KBytes of flex and
bison instructions generate 129 KBytes of C-code, which has to be
compared with the 108 KBytes of C-code which I wrote. Together
these implement the functionality of yabasic. So actually most of
the code has been generated by flex and bison !
Execution of a program
Although yabasic behaves mostly like an interpreter, in fact
it is not. Rather it's a compiler: If you give it any basic-code
for execution, the code is compiled, yielding instructions for a
simple stack-machine; these instructions are then interpreted
immediately, so that you will never get in touch with the
stack-machine. You can find out the time needed for this process
if you invoke yabasic with infolevel set to note
.
Back to table of contents ...
Yabasic is subject to the GNU copyleft, which (in a nutshell)
gives you every freedom to use modify or redistribute this
software, except the right to restrict other people's freedom. To
get an idea of it I just reproduce the preamble
of the GNU copyleft; the exact terms can be found in the file
COPYING
which
comes along as part of the distribution, or can be obtained from
the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
02139, USA.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General
Public License is intended to guarantee your freedom to share and
change free software--to make sure the software is free for all
its users. This General Public License applies to most of the
Free Software Foundation's software and to any other program
whose authors commit to using it. (Some other Free Software
Foundation software is covered by the GNU Library General Public
License instead.) You can apply it to your programs, too.
When we speak of free software, we are referring to freedom,
not price. Our General Public Licenses are designed to make sure
that you have the freedom to distribute copies of free software
(and charge for this service if you wish), that you receive
source code or can get it if you want it, that you can change the
software or use pieces of it in new free programs; and that you
know you can do these things.
To protect your rights, we need to make restrictions that
forbid anyone to deny you these rights or to ask you to surrender
the rights. These restrictions translate to certain
responsibilities for you if you distribute copies of the
software, or if you modify it.
For example, if you distribute copies of such a program,
whether gratis or for a fee, you must give the recipients all the
rights that you have. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so
they know their rights.
We protect your rights with two steps: (1) copyright the
software, and (2) offer you this license which gives you legal
permission to copy, distribute and/or modify the software.
Also, for each author's protection and ours, we want to make
certain that everyone understands that there is no warranty for
this free software. If the software is modified by someone else
and passed on, we want its recipients to know that what they have
is not the original, so that any problems introduced by others
will not reflect on the original authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a
free program will individually obtain patent licenses, in effect
making the program proprietary. To prevent this, we have made it
clear that any patent must be licensed for everyone's free use or
not licensed at all.
Back to table of contents ...