Yjasl Reference Manual

Introduction :: Reference Manual :: Internals :: Yjasl Examples :: Programming Guidelines :: Download/sf.net :: About/Contact

for Yjasl version 2.0.5 © by René 'Neotec' Jeschke in 2006, 2007
Last updated: 11 JUN 2007

0. Syntax And Functionality
Syntax of Yjasl
1. Variables And Arrays
Syntax of variables and arrays
2. Operators
List of all operators
3. Conditions And Loops
Syntax of loops and IF
4. Functions And Subs
Syntax of function and sub declaration
5. Reserved Words
List of reserved words and brief explanation
6. Standard Library Functions
List of all standard library functions and subs
7. YjaslRun.exe
Usage of YjaslRun.exe
8. YjaslGRE.exe
Usage of YjaslGRE.exe



[Previous] [Top] [Next]

0. Syntax And Functionality

0.0 Rems
0.1 The Semicolon
0.2 Variables
0.3 Expressions
0.4 Global And Local Variables
0.5 Namespaces
0.6 Limitations, Maximum And Minimum Values


0.0 Rems

Yjasl accepts C style remarks.

// This is a one line rem
/* This
is more than
one line ! */

0.1 The Semicolon

Yjasl accepts C use of semicolons, but doesn't need them except in the case of function prototypes. I added the semicolon just to make some parts of my sources more readable (and because it's quite confusing switching from C# with semicolons to Yjasl without semicolons ... this solution produces less 'syntax error' exceptions. *g*)

// The next line looks nicer with semicolons also they're not needed
fnum = 6; x_min = -0.274188704403; x_max = -0.274188253684; y_min = 0.841196557584; y_max = 0.841196897085

sub proto_sub(a, b, c);       // Sub prototype
function proto_func(a, b, c); // Function prototype

0.2 Variables

Variables do not have to be defined with a type, like in C. The type of a variable is determined by its last assign.

var = 3.1415926536                             // var is a number
var = "Hello world!"                           // var is now a string
var = {.hello = "Hello", .world = "world!"}    // var is now an array
var = sin                                      // var is now a function

0.3 Expressions

Expressions allways evaluate to a value. If you use logical operators, the expression will evaluate to true or false.

bool = 0 == 1
a = 10
b = a * 5 + 2
term = pow(a, 2) + 2 * a * b + pow(b, 2)
term2 = (a + (b + (a * b) * 100) / 10) - 3.33333333

0.4 Global And Local Variables

In functions or subs all variables are assigned as follows:

var = 10

1. Check if local variable 'var' exists, if so: local 'var' = 10 -> done
2. Check if global variable 'var' exists, if so: global 'var' = 10 -> done
3. Create local variable 'var', local 'var' = 10 -> done

Remark: Local variables are faster than global variables.


0.5 Namespaces

A namespace holds functions, subs and globals.

Example:

namespace test
    function testfunc(a)
        return a * 2
    end

    _::println("Hello from namespace 'test'!")    // _ is the standard namespace

    var = 100
end

println(test::testfunc(10))
println(test::var)

test::var = 100
test::new_var = 2000                              // will define a new variable 'new_var' in namespace 'test'

The above could also be done like this:

function test::testfunc(a)
    return a * 2
end

println("No other namespace!")

test::var = 100

println(test::testfunc(10))
println(test::var)

test::var = 100
test::new_var = 2000                              // will define a new variable 'new_var' in namespace 'test'

0.6 Limitations, Maximum And Minimum Values

Numbers Maximum: +1.79769313486232E+308, minimum: -1.79769313486232E+308, epsilon = 4.94065645841247E-324
Strings The maximum number of constant string values is: 65536
Arrays Maximum number of members: 2147483647
Namespaces Maximum number of namespaces is: 256.
Functions Maximum number of functions and subs per namespace is: 65536.
Globals Maximum number of global variables per namespace is: 65536.
Locals Maximum number of local variables per function is: 65536. (Remark: Parameters are also local variables.)
Code Maximum code size for a function and the main VM when using 'small' is 64K, otherwise it's 16M. This leads to a total code size of 1T (small) and 256T.



[Previous] [Top] [Next]

1. Variables And Arrays

Variable names may start with _ or a letter, may contain letters, digits and _ and are case-insensitive.

Example:

x = 10
str = "Hello world!"

You can assign strings, numbers, arrays and functions to variables. The type of a variable is specified by its content. You can use typeof() to get the type of a variable. (See Variables Library)

Yjasl does only have two variable scope types: global and local. All variables assigned in main code are global variables and can be accessed by all subs and functions. Variables declared in functions or sub are only available in this function or sub.

Yjasl's arrays are very flexible. Instead of explaining them, I'll just give some examples:

// Example #0

    arr     = {}
    arr[0]  = "Test"
    arr[10] = "Unordered!"
    arr[2]  = 10

// Example #1

    arr = {1, 2, "three"}
    println(arr[0].." + "..arr[1].." = "..arr[2])

// Example #2

    arr = {{0, 1, 2, 3}, {4, 5, 6, 7}}
    println(arr[0][2]..", "..arr[1][3])

// Example #3

    arr = {.name = "Foo", .age = 99}

    println(arr.name.." is "..arr.age.." years old")

// Example #4

    arr = {{.a = 10, .b = 20}, {.a = 30, .b = 40}}

    println(arr[0].a)


// Example #5

    arr = array(1000, 0)		// creates an ordered array with size 1000, filled with zeros


// Example #6

    arr      = {}
    arr.test = "Hello"
    arr.worx = " world!"
    println(arr.test..arr.worx)


// Example #7

    arr  = {sin, cos, timetick}
    temp = arr[0]
    println(temp(pi / 3))
    println(arr[2]())


// Example #8

    arr  = {}
    arr[] = 10				// arr[0] = 10
    arr[] = 12				// arr[1] = 12
    arr[] = pi				// arr[2] = pi


// Example #9

    function garr(a);
    function func(a);

    arr = {}

    arr.println = findsub("println", 1)
    arr.garr = findfunction("garr", 1)
    arr.func = findfunction("func", 1)

    arr.println("Hello world!")
    arr.garr(findsub("println", 1)).ret("Foo")
    arr.garr(arr.func(100))[0]("Bar")

    function garr(a)
        local arr = {}
        arr[0] = a
        arr.ret = a
        return arr
    end

    function func(a)
        return findsub("println", 1)
    end

Remarks: Whenever possible, use array() to initialize arrays. Due to runtime table access performance, resizing gets very slow.

arr0 = array(65536)
arr1 = {}

t0 = timetick()
for x = 0, 65535 do
    arr0[x] = x
end
t1 = timetick()
println((t1 - t0).." ms")

t0 = timetick()
for x = 0, 65535 do
    arr1[x] = x
end
t1 = timetick()
println((t1 - t0).." ms")

/* on my AMD Athlon 1000MHz, 512MB RAM, WinXPpro this outputs:
    130 ms
    5999 ms
*/

Remarks: If your array uses number indexes only, make sure you add values in order. You can also use array() as seen in Example #5. This ensures that your array is an ordered array and will give a great advantage in performance. (See Example #0 for an unordered array.)

Remarks: Arrays are references:

arr0    = {1, 2, 3, 4}
arr1    = arr0
arr1[2] = 10
println(arr0[2])    // will output 10

If you want a copy of an array, use arrclone(). (See Variables Library)




[Previous] [Top] [Next]

2. Operators

Here is a list of all available operators and what they'll do:

+ Addition
- Subtraction
* Multiplication
/ Division
& Binary AND
| Binary OR
^ Binary XOR
~ Binary NOT
== Equal
!= Not equal
< Less than
<= Less or equal
> Greater than
>= Greater or equal
! Logical not
&& Logical AND
|| Logical OR
.. String concatenation (a wrapper for strcat())
+= Add and assign. (Right now only supported for variables, not arrays)
-= Sub and assign. (Right now only supported for variables, not arrays)
*= Mul and assign. (Right now only supported for variables, not arrays)
/= Div and assign. (Right now only supported for variables, not arrays)



[Previous] [Top] [Next]

3. Conditions And Loops

3.0 IF Blocks
3.1 FOR Blocks
3.2 FOREACH Blocks
3.3 DO ... UNTIL Blocks
3.4 WHILE Blocks
3.5 CFOR Blocks
3.6 SWITCH Blocks


3.0 IF Blocks

IF blocks contain at least one IF clause, zero or more ELSEIF clauses and zero or one ELSE clause:

if cond then
    ...
[elseif cond then]
    ...
[elseif cond then]
    ...
[else]
    ...
end

cond is a term which evaluates to true or false.
true is defined as -1.0, but may be any value except 0.0.
false is defined as 0.0.


3.1 FOR Blocks

for var = start, end[, step] do
    ...
    [continue]
    ...
    [break]
    ...
end

var is a variable name.
start is an expression which sets the initial value of var.
end is an expression which sets the destination value.
step is optional (default is 1.0), and (when given) must be a number, no expression.
continue = forced continue of the loop (following code gets skipped)
break = exits the loop.

Examples:

for i = 0, 9 do
    println(i)    // prints numbers 0 ... 9
end

for i = 9, 0, -1 do
    println(i)    // prints numbers 9 ... 0
end

Remark: The 'end' expression is evaluated only once and its value gets stored for later compares, so 4 - 10 + 100 is as fast as 94 during loop execution.


3.2 FOREACH Blocks

foreach var in array do
    ...
    [continue]
    ...
    [break]
    ...
end

This iterates through all elements in table 'array'.

var is a variable name.
array is an array.

Example:

arr = {.hello = "Help!", .world = 100, .foo = "lalala", .bar = sin}

foreach var in arr do
    println("arr."..getindex(var).." = "..var)
end

/* This will print:
    arr.hello = Help!
    arr.world = 100
    arr.foo = lalala
    arr.bar = FUNCTION[...]
*/

3.3 DO ... UNTIL Blocks

do
    ...
    [continue]
    ...
    [break]
    ...
until cond

Executes the loop until cond evaluates to true.


3.4 WHILE Blocks

while cond do
    ...
    [continue]
    ...
    [break]
    ...
end

Executes the loop while cond evaluates to true.


3.5 CFOR Blocks

The cfor block is an implementation of the C-style for loops.

cfor (init; cond; change) do
    ...
    [continue]
    ...
    [break]
    ...
end

init is one or more optional initial assign(s) or function call(s)
cond is an optional single condition
change is one or more optional change assign(s) or function call(s)

Examples:

cfor (x = 0; x < 10; x += 1) do
    println(x)
end

cfor (x = 0, y = 0; x < 10 && y < 12; x += 1, y += 2) do
    println(x..", "..y)
end

// The above could also be written like this:

x = 0
y = 0
while x < 10 && y < 12 do
    println(x..", "..y)
    x += 1
    y += 2
end

cfor (;;) do   // This is the fastest endless loop in Yjasl
    println("endless ")
end

3.6 SWITCH Blocks

switch exp do
    [case exp2:]
        ...
        [break]
    ...
    [default:]
        ...
end

Remark: The 'exp' expression is evaluated only once and its value gets stored for later compares.




[Previous] [Top] [Next]

4. Functions And Subs

Function/sub names may start with _ or a letter, may contain letters, digits and _ and are case-insensitive.

The only difference between funcions and sub is that functions allways return a value and subs allways don't.

Functions and subs need to be defined before their first use. You may use protypes to define the them.

function name([parameter-list]);    // Prototype definition

function name([parameter-list])
    ...
    return value
end

sub name([parameter-list])
    ...
    [exit]
    ...
end

Parameter-list may be empty or contain names. The values passed to a function/sub are stored in local variables.

You do not need to place the return statement at the end of the function, but make sure you return a value somewhere in your function. The Yjasl VM checks the stack after a function call and if neccessary just pushes a NULL onto the stack when a return value is missing.

function test(a, b)
    c = a + b
end

println(test(1, 2))        // will output NULL

Here are some more examples to give you an impression of how functions work:

sub add_print(p0, p1)
    println(p0.." + "..p1.." = "..(p0 + p1))
end

sub add_print(p0, p1, p2)
    println(p0.." + "..p1.." + "..p2.." = "..(p0 + p1 + p2))
end

function my_add(a, b)
    return a + b
end

add_print(1, 2)
add_print(1, 2, 3)
println(my_add(2, 5))

arr = {my_add}
println(arr[0](2, 5))

Remark: Direct assigning of an overloaded function/sub to a variable doesn't work correctly. Use the return value of findfunction() and findsub() (See Variables Library) instead.

Remark: If you call a function/sub by a variable, Yjasl doesn't check for parameter count or return values (except that functions still allways return a value). So make sure you call your functions/sub in the right way or stack underruns or overflows may occur. callsub() and callfunc() (See Jasl Library) do these calls in a safe way by throwing exceptions when parameters don't match.

Remark: You can use the keyword override to replace an existing function or sub by another (See Reserved Words for an example).




[Previous] [Top] [Next]

5. Reserved Words

break See Conditions And Loops
continue See Conditions And Loops
do See Conditions And Loops
else See Conditions And Loops
elseif See Conditions And Loops
end Closes most blocks and function/sub bodies
exit Exits main code or a sub, see also Functions And Subs
false Number: 0.0
for See Conditions And Loops
foreach See Conditions And Loops
function See Functions And Subs
global global is an easy way to define a lot of global vars. See local for details.
if See Conditions And Loops
in See Conditions And Loops
include include must be followed by a string (no expression). You can't include in function/sub bodies.
local local is used to explicit declare variables in functions or subs local. local must be followed by one or more variables.
Example:
function func(a, b)
    local c, d = 0, f = {}
    local z
    ...
end
namespace Starts a namespace
null The object type NULL
override Modifier for function/sub definition, to override previous function/sub definitions
Example:
override sub println(a)
    print(a.."\n")
end

Remark: Functions are overriden during compile-time, nto run-time.
Warning: Once a function is overridden, there is no possibility to restore the old function during runtime.

return See Functions And Subs
sub See Functions And Subs
then See Conditions And Loops
true Number: -1.0
until See Conditions And Loops
while See Conditions And Loops




[Previous] [Top] [Next]

6. Standard Library Functions

6.0 Yjasl Library
6.1 Variables Library
6.2 String Library
6.3 System Library
6.4 IO Library
6.5 Timer Library
6.6 Math Library
6.7 Console Library
6.8 GZip Library
6.9 Socket Library

6.0 Yjasl Library (low)

yjasl.name Yjasl vx.xx (..., xk stack)
yjasl.version Yjasl version number (currently 2.03)
yjasl.author Yjasl's author name
security.low Standard security level. All functions may be executed.
security.med Medium security level. Functions using security level 'high' are blocked.
security.high High security level. Functions using security levels 'high' or 'med' are blocked.
error(a) Displays error message 'a' and stops the VM
quit() Stops the VM
r = compile(a) Compiles a sub or functions contained in string 'a' and returns a reference to this function or sub. You need not specify a name because it won't be stored. The only way to access this function or sub is via its reference supplied by compile().
r = callfunc(a, b) Calls function 'a'. Parameters are in array 'b' which must be an ordered array, starting at index 0.
Example:
println(callfunc(pow, {2, 8}))
func = sin
println(callfunc(func, {pi}))
callsub(a, b) Calls sub 'a'. Parameters are in array 'b' which must be an ordered array, starting at index 0.
r = runenv() Returns either "console" or "window" determined by the interpreter type.
r = scallfunc(a, b, c) Calls function 'a'. Parameters are in array 'b' which must be an ordered array, starting at index 0. 'c' is the security level for this function call.
Remarks:
You can't call a function or sub using a lower security level than the current, i.e. e.g. calling a sub with 'low', when running with 'med' is prohibited.
scallsub(a, b, c) Calls sub 'a'. Parameters are in array 'b' which must be an ordered array, starting at index 0. 'c' is the security level for this sub call.
r = getsecurity() Returns the current security level (0 (low) - 10 (high)).

[Previous] [Top] [Next]


6.1 Variables Library (low)

r = isnull(a) Returns true if 'a' equals null otherwise false
r = istable(a) Returns true if 'a' is a table otherwise false
r = isnumber(a) Returns true if 'a' is a number otherwise false
r = isstring(a) Returns true if 'a' is a string otherwise false
r = isset(a) Returns true if global variable 'a' is set. 'a' must be a string, containing the variable's name
r = typeof(a) Returns a string containing the type of 'a' ("string", "number", "table", "sub", "function", "null", "data")
r = arrcount(a) Returns the number of entries in table 'a'
r = array(a) Returns an array with size 'a'
r = array(a, b) Returns an array with size 'a', filled with 'b'
r = arrclone(a) Returns a copy of table 'a'
r = paramcount(a) Returns the number of parameters of function or sub 'a'
r = findfunction(a) Returns a reference to function named 'a', null if function was not found
r = findfunction(a, b) Returns a reference to function named 'a' with 'b' parameters, null if function was not found
r = findsub(a) Returns a reference to sub named 'a', null if sub was not found
r = findsub(a, b) Returns a reference to sub named 'a' with 'b' parameters, null if sub was not found
r = getindex(a) Returns the array index of variable 'a' (See FOREACH Blocks for an example)
r = chkzero(a, b) If 'a' is 0, "", TABLE[0] or NULL 'b' is returned, otherwise 'a'
r = chknull(a, b) If 'a' is NULL 'b' is returned, otherwise 'a'

[Previous] [Top] [Next]


6.2 String Library (low)

r = strcat(a, b) Returns 'a' + 'b'
r = tostr(a) Returns 'a' converted into a string
r = tonum(a) Returns 'a' converted from string to a number
r = tohex(a) Returns 'a' converted from number to a hex string
r = tochar(a) Returns 'a' converted to a char number value
r = strlen(a) Returns the length of string 'a'
r = strsub(a, b, c) Returns a part of string 'a', starting at 'b', length 'c'
r = strchr(a, b) Returns char at position 'b' in string 'a'
r = strlower(a) Returns string 'a' converted to lower-case characters
r = strupper(a) Returns string 'a' converted to upper-case characters
r = char(a) If 'a' is a number, returns 'a' as a char. If 'a' is a string, returns the first char of string 'a'
r = strtrim(a) Returns a string with leading and trailing whitespaces of 'a' removed
r = strright(a, b) Returns a string containing the last 'b' chars of string 'a'
r = strleft(a, b) Returns a string containing the first 'b' chars of string 'a'
r = instr(a, b) Returns the first position of string 'b' in string 'a', -1 if not found
r = instr(a, b, c) Returns the first position of string 'b' in string 'a' starting at position 'c', -1 if not found
r = strtok(a, b) Returns array of strings by seperating string 'a' by string 'b'
r = strglue(a, b) Returns a string with all elements of table 'a' concatenated using separator string 'b'
r = strrep(a, b) Returns 'b' times 'a'
r = strpadr(a, b, c) Pads right side of 'a' with 'c' up to total length of 'b' chars
r = strpadl(a, b, c) Pads left side of 'a' with 'c' up to total length of 'b' chars
r = strrem(a, b, c) Removes 'c' chars at position 'b' from string 'a'
r = strins(a, b, c) Inserts string 'b' at position 'c' into string 'a'
r = strrepl(a, b, c) Replaces all occurences of string 'b' in string 'a' with 'c'
r = strreplat(a, b, c) Replaces string at position 'c' in string 'a' with string 'b'
r = stresc(a) Escapes string 'a'
r = strunesc(a) Removes escapes from string 'a'
r = strstarts(a, b) Returns true or false wether 'a' starts with 'b' or not
r = strends(a, b) Returns true or false wether 'a' ends with 'b' or not

[Previous] [Top] [Next]


6.3 System Library (low)

r = timetick() Returns the time in milliseconds since computer power on
r = timestamp() Returns a UN*X timestamp
sleep(a) Interrupts the VM execution for 'a' milliseconds
r = time() Returns an array containing the current system time (0 = day, month, year, hour, minute, second, millisecond).
r = time(timestamp) Returns an array containing the UN*X timestamp's time (0 = day, month, year, hour, minute, second, millisecond).

[Previous] [Top] [Next]


6.4 IO Library (high)

r = fopen(a, b) Opens file 'a' with mode 'b', returns a file handle. Mode can be: "r" for read, "w" for write and create new, "w+" for write and append if exists.
fclose(a) Closes file with file-handle 'a'
r = fexists(a) Returns true if file 'a' exists
r = fread(a) Reads a byte from file with file-handle 'a', returns null on EOF
r = freadln(a) Reads a line from file with file-handle 'a', returns null on EOF
fwrite(a, b) Writes char or byte 'b' into file with file-handle 'a'
fwriteln(a, b) Writes line 'b' into file with file-handle 'a'
r = fkill(a) Deletes file 'a', returns true on success
r = frename(a, b) Renames file 'a' to 'b', returns true on success
r = fread(a) Reads a byte from file with file-handle 'a', returns null on EOF
r = readdir(a) Reads directory 'a', returns an array of entries:
files = readdir(".")
foreach var in files do
    println("Name: "..var.name)
    println("Type: "..var.type)           // either "dir" or "file"
    println("Size: "..var.size)
    println("Extension: "..var.ext)
    println("Full name: "..var.fullname)
end
r = readdir(a, b) Reads directory 'a' using mask 'b', returns an array of entries
r = currentdir() Returns the current directory
r = chdir(a) Change current directory to 'a', returns true on success
r = mkdir(a) Creates directory 'a', returns true on success
r = rmdir(a) Removes empty directory 'a', returns true on success
r = killdir(a) Deletes directory 'a' and all of its content, returns true on success
r = dexists(a) Returns true if directory 'a' exists

[Previous] [Top] [Next]


6.5 Timer Library (low)

r = timeradd(a, b) Installs sub 'a' as a timer with interval 'b' milliseconds. 'a' must be a sub without any parameters. Timers get started when main VM code ends. Return value is the timer number.
timerstop(a) Stops timer number 'a'
r = timersleep(a) Toggles the state of timer 'a'. Returns the new state: true == timer is running, false == timer is paused.
timerdelay(a, b) Sets the interval of timer 'a' to 'b'.

[Previous] [Top] [Next]


6.6 Math Library (low)

pi PI
euler E
r = sin(a) Returns sin of 'a' (rad)
r = asin(a) Returns asin of 'a' (rad)
r = cos(a) Returns cos of 'a' (rad)
r = acos(a) Returns acos of 'a' (rad)
r = tan(a) Returns tan of 'a' (rad)
r = atan(a) Returns atan of 'a' (rad)
r = rand(a) Returns a random number between 0 and 'a' - 1
r = rand(a, b) Returns a random number between 'a' and 'b' - 1
r = floor(a) Returns floor(a)
r = ceil(a) Returns ceil(a)
r = round(a) Returns round(a)
r = abs(a) Returns 'a' without sign
r = pow(a, b) Returns 'a' power of 'b'
r = sqrt(a) Returns square root of 'a'
r = mod(a, b) Returns 'a' modulo 'b'
r = exp(a) Returns exp(a)
r = log(a) Returns log(a) (base E)
r = log10(a) Returns log10(a)
r = max(a, b) If a > b return a, else b
r = min(a, b) If a < b return a, else b

[Previous] [Top] [Next]


6.7 Console Library (low)

print(a) Prints 'a'
println() Prints a newline
println(a) Prints 'a' + newline
r = getkey() Returns current key pressed, null if none
r = waitkey() Waits for a pressed key, returns it
r = creadln() Reads a line from console and returns it
cclear() Clears the console window
chome() Sets the cursor position to (0, 0)
ccsrpos(x, y) Sets the console's cursor position to 'x', 'y'
r = ccsrpos() Returns an array (.x, .y) containing the cursor's position
r = cfgcolor() Returns the current foreground color
cfgcolor(a) Change foreground color to 'a' ('a' is a number between 0 and 15)
r = cbgcolor() Returns the current background color
cbgcolor(a) Change background color to 'a' ('a' is a number between 0 and 15)
crcolors() Resets all colors
ccsrvisible(a) Shows ('a' = true) or hides ('a' = false) the cursor
ccsrsize(a) Sets the cursor size (1 <= 'a' <= 100)
r = ccsrsize() Gets the cursor size

[Previous] [Top] [Next]


6.8 GZip Library (high)

r = gzip::open(a, b) Opens file 'a' with mode 'b', returns a file handle. Mode can be: "r" for read or "w" for write.
gzip::close(a) Closes file with file-handle 'a'
r = gzip::read(a) Reads a byte from file with file-handle 'a', returns null on EOF
r = gzip::readln(a) Reads a line from file with file-handle 'a', returns null on EOF
gzip::write(a, b) Writes char or byte 'b' into file with file-handle 'a'
gzip::writeln(a, b) Writes line 'b' into file with file-handle 'a'

[Previous] [Top] [Next]


6.9 Socket Library (high)

r = httpread(url) Reads HTML page from url. Returns a string on success, null otherwise.

[Previous] [Top] [Next]




[Previous] [Top] [Next]

7. YjaslRun.exe




[Previous] [Top] [Next]

8. YjaslGRE.exe



© by René 'Neotec' Jeschke in 2006, 2007
Last updated: 14 JUN 2007 (under construction)
SourceForge.net Logo