/
driver3.2@242/autoconf/
driver3.2@242/doc/LPC/
driver3.2@242/hosts/
driver3.2@242/hosts/amiga/NetIncl/
driver3.2@242/hosts/amiga/NetIncl/netinet/
driver3.2@242/hosts/amiga/NetIncl/sys/
driver3.2@242/hosts/atari/
driver3.2@242/hosts/fcrypt/
driver3.2@242/mudlib/
driver3.2@242/mudlib/sys/
driver3.2@242/util/
driver3.2@242/util/indent/hosts/next/
driver3.2@242/util/make_docs/
THIS IS A DOCUMENT THAT DESCRIBES HOW A VIRTUAL STACK MACHINE HAS BEEN
DEFINED, TO EXECUTE COMPILED LPC CODE.

There are two stacks:

1.    The stack of values, used for evaluation, local variables and arguments.
Note that arguments are treated as local variables. Every element on the
value stack will have the format "struct svalue", as defined in interpret.h.
The value stack is stored in an array, with limited size. The first push
operation will store a value into element 0. Access of arguments and local
variables are supposed to be fast, by simply indexing in the value stack
using the frame pointer as offset.

Start of stack 	-----
		|
Frame pointer->	|	Argument number 0
		|	Argument number 1
		|	etc.
		|	Local variable number 0
		|	Local variable number 1
		|	etc.
		|	break addresses for case
		|	Temporary stack values
		|	etc
		v

2.    The control stack that contains return addresses, frame pointer etc.


1. CALLING LOCAL FUNCTIONS.

All arguments are evaluated and pushed to the value stack. The last argument
is the last pushed. It is important that the called function gets exactly as
many arguments as it wants. The number of arguments will be stored in the
control stack, so that the return instruction not needs to know it
explicitely.

Instruction format:

b0 b1 b2 b3

b0     = F_CALL_FUNCTION_BY_ADDRESS.
b1, b2 = The number of the function to be called.
b3     = Number of arguments sent.

The F_CALL_FUNCTION_BY_ADDRESS instruction will also initiate the frame pointer
to point to the first argument.

The number of arguments are stored in the 'struct function' which is found
using the number of the function and indexing in ob->prog->functions[];
The number of arguments will be adjusted to fit the called function.
This is done by either pushing zeroes, or poping excessive
arguments. F_CALL_FUNCTION_BY_ADDRESS will also initiate local variables, by
pusing a 0 for each of them.

The called function must ensure that exactly one value remains on the
stack when returning. The caller is responsible of deallocating the
returned value.

When a function returns, it will use the instruction F_RETURN, which will
deallocate all arguments and local variables, and only let the top of stack
entry remain. The number of arguments and local variables are stored in the
control stack, so that the evaluator knows hoh much to deallocate.

If flag 'extern_call' is set, then the evaluator should return. Otherwise,
the evaluator will continue to execute the instruction at the returned
address.

Format:

b0

b0 = F_RETURN.

Format:

b0 b1 b2 b3 b4 b5

b0     = F_CALL_EXPLICIT_INHERITED
b1, b2 = The index in the inherit table to find the struct program.
b3, b4 = The number of the function to be called in the inherited program.
b5     = number of arguments sent.


2. CALLING PREDEFINED FUNCTIONS.

Arguments are pushed to the stack. A value is always returned (on the stack).

Instruction format:

b0

b0 = The F_ code of the called function.

If a variable number of arguments are allowed, then an extra byte will
follow the instruction, that states number of actual arguments.

The number of arguments has already been checked at compile time, if this was
possible.
The execution unit will check the types of the arguments.

Instruction format:

b0 b1

b0 = F_ESCAPE
b1 = the F_ code of the called function.

See above.

3. F_SSCANF

The function sscanf is special, in that arguments are passed by reference.
This is done with a new type, T_LVALUE. The compiler will recognize
sscanf() as a special function, pass the value of the two first arguments
as normal rvalues and pass the rest as lvalues. The total number of arguments
is given as a one byte code supplied to the F_SSCANF instruction.

4. F_CALL_OTHER

This command takes one argument, a byte which gives the number of arguments.

b0, b1

b0 = F_CALL_OTHER, b1 = number of arguments.

5. F_AGGREGATE

This command takes one argument, the size of the array. The elements of
the array are picked from the top of stack.

b0, b1, b2

b0 = F_AGGREGATE, (b1,b2) = Size of the array (max 0xffff).

6. F_CATCH

The compiler constructs a call to F_CATCH before the code to evaluate the
argument of F_CATCH. After the code, a call to F_END_CATCH is made.

F_CATCH will when executed do setjmp() and call eval_instruction()
recursively. That means that a new frame has to be set up.
It will also save some extra context information, which need to be cleaned
up by F_END_CATCH if it isn't used up by F_THROW .

F_THROW will do a longjmp().

format:

F_CATCH, b1, (instructions...), F_END_CATCH

Where b1 is the an offset to the instruction after the return instruction.

7. F_RETURN

Will deallocate the current frame, and restore the previous. If the flag
extern_call is set, then a return from eval_instruction() will be done.