OpenEuphoria: Euphoria v4.1

# OpenEuphoria Manual

## Euphoria v4.1

routine or constant name search

| Up |  |  | TOC | Index
<< 7 Included Tools | < 8.43 Pseudo Memory | Up: 8 API Reference | 8.46 Memory Constants > | 9 Release Notes >>

## 8.44 Machine Level Access

#### 8.44.0.1 Marchine Level Access Summary

Warning: Some of these routines require a knowledge of machine-level programming. You could crash your system!

These routines, along with peek, poke and call, let you access all of the features of your computer. You can read and write to any allowed memory location, and you can create and execute machine code subroutines.

If you are manipulating 32-bit addresses or values, remember to use variables declared as atom. The integer type only goes up to 31 bits.

If you choose to call `machine_proc` or `machine_func` directly (to save a bit of overhead) you *must* pass valid arguments or Euphoria could crash.

##### Some example programs to look at:

- `demo/callmach.ex` -- calling a machine language routine

#### 8.44.0.2 peek_longs

    include std/machine.e
    namespace machine
    public function peek_longs(object x)

@nodoc

#### 8.44.0.3 MAP_ANONYMOUS

    include std/machine.e
    namespace machine
    export constant MAP_ANONYMOUS

#### 8.44.0.4 MAP_FAILED

    include std/machine.e
    namespace machine
    export constant MAP_FAILED

### 8.44.1 Safe Mode

#### 8.44.1.1 Safe Mode Summary

During the development of your application, you can define the word `SAFE` to cause `machine.e` to use alternative memory functions. These functions are slower but help in the debugging stages. In general, `SAFE` mode should not be enabled during production phases but only for development phases.

To define the word `SAFE` run your application with the `-D SAFE` command line option, or add to the top of your main file:

    with define safe

before the first appearance of `include std/machine.e`

The implementation of the Machine Level Access routines used are controled with the define word `SAFE`. The use of `SAFE` switches the routines included here to use debugging versions which will allow you to catch all kinds of bugs that might otherwise may not always crash your program where in the line your program is written. There may be bugs that are invisible until you port the program they are in to another platform. There has been no bench marking for how much of a speed penalty there is using `SAFE`.

You can take advantage of `SAFE` debugging by:

- If necessary, call register_block(address, length, memory_protection) to add additional "external" blocks of memory to the safe_address_list. These are blocks of memory that are safe to use but which you did not acquire through Euphoria's allocate, allocate_data, allocate_code or allocate_protect, allocate_string, allocate_wstring. Call unregister_block(address) when you want to prevent further access to an external block. When `SAFE` is not enabled these functions will do nothing and will be converted into nothing by the inline code in the front-end.

- You will be notified if memory that you haven't allocated is accessed, or if memory is freed twice, or if memory is used in the wrong way. Your application will can be ready for D.E.P. enabled systems even if the system you test on doesn't have D.E.P..

- If a bug is caught, you will hear some "beep" sounds. Press Enter to clear the screen and see the error message. There will be a descriptive crash message and a traceback in ex.err so you can find the statement that is making the illegal memory access.

#### 8.44.1.2 check_calls

Define block checking policy.

    include std/machine.e
    public integer check_calls

##### Comments:

If this integer is 1, (the default), check all blocks for edge corruption after each Executable Memory, call, c_proc or c_func. To save time, your program can turn off this checking by setting check_calls to 0.

#### 8.44.1.3 edges_only

    include std/machine.e
    public integer edges_only

Determine whether to flag accesses to remote memory areas.

##### Comments:

If this integer is 1 (the default under Windows), only check for references to the leader or trailer areas just outside each registered block, and don't complain about addresses that are far out of bounds (it's probably a legitimate block from another source)

For a stronger check, set this to 0 if your program will never read/write an unregistered block of memory.

On Windows people often use unregistered blocks. Please do not be one of them.

#### 8.44.1.4 check_all_blocks

    include std/machine.e
    check_all_blocks()

Scans the list of registered blocks for any corruption.

##### Comments:

safe.e maintains a list of acquired memory blocks. Those gained through `allocate` are automatically included. Any other block, for debugging purposes, must be registered by register_block and unregistered by unregister_block.

The list is scanned and, if any block shows signs of corruption, it is displayed on the screen and the program terminates. Otherwise, nothing happens.

Unless `SAFE` is defined, this routine does nothing. It is there to make switching between debugged and normal version of your program easier.

##### See Also:

register_block, unregister_block

#### 8.44.1.5 register_block

    include std/machine.e
    procedure register_block(machine_addr block_addr, positive_int block_len,
                valid_memory_protection_constant memory_protection = PAGE_READ_WRITE )

Adds a block of memory to the list of safe blocks maintained by safe.e (the debug version of memory.e). The block starts at address a. The length of the block is i bytes.

##### Parameters:

1. `block_addr` : an atom, the start address of the block
2. `block_len` : an integer, the size of the block.
3. `protection` : a constant integer, of the memory protection constants found in machine.e, that describes what access we have to the memory.

##### Comments:

In memory.e, this procedure does nothing. It is there to simplify switching between the normal and debug version of the library.

This routine is only meant to be used for debugging purposes. safe.e tracks the blocks of memory that your program is allowed to peek, poke, mem_copy etc. These are normally just the blocks that you have allocated using Euphoria's allocate routine, and which you have not yet freed using Euphoria's free. In some cases, you may acquire additional, external, blocks of memory, perhaps as a result of calling a C routine.

If you are debugging your program using `safe.e`, you must register these external blocks of memory or `safe.e` will prevent you from accessing them. When you are finished using an external block you can unregister it using `unregister_block`.

##### Example 1:

    atom addr

    addr = c_func(x, {})
    register_block(addr, 5)
    poke(addr, "ABCDE")
    unregister_block(addr)

##### See Also:

unregister_block, Safe Mode

#### 8.44.1.6 unregister_block

    include std/machine.e
    public procedure unregister_block(machine_addr block_addr)

removes a block of memory from the list of safe blocks maintained by safe.e (the debug version of memory.e).

##### Parameters:

1. `block_addr` : an atom, the start address of the block

##### Comments:

In memory.e, this procedure does nothing. It is there to simplify switching between the normal and debug version of the library.

This routine is only meant to be used for debugging purposes. Use it to unregister blocks of memory that you have previously registered using register_block. By unregistering a block, you remove it from the list of safe blocks maintained by safe.e. This prevents your program from performing any further reads or writes of memory within the block.

See register_block for further comments and an example.

##### See Also:

register_block, Safe Mode

### 8.44.2 Data Execute Mode and Data Execute Protection

`Data Execute Mode` makes data that will be returned from allocate executable. On some systems you will not be allowed to run code in memory returned from allocate unless this mode has been enabled. This restriction is called Data Execute Protection or D.E.P.. When writing software you should use allocate_code or allocate_protect to get memory for execution. This is more efficient and more secure than using `Data Execute mode`. Because many hacker exploits of software use data buffers and then trick software into running this data, Data Execute Protection stops an entire class of exploits.

If you get a Data Execute Protection Exception from running software, it means that D.E.P. could have thwarted an attack! Your application crashes and your computer wasn't infected. However, many people will decide that they want to disable D.E.P. because they know that they call memory returned by allocate or perhaps they are simply careless.

### 8.44.3 Type Sorted Function List

#### 8.44.3.1 Executable Memory

Executable Memory is the way to run code on the stack in a completly portable way.

##### Use the following Routines:

Use allocate_code to allocate some executable machine-code, call to call the code, and free_code to free the machine-code.

#### 8.44.3.2 Using Data Bytes

In C, bytes are called 'char' or 'BOOL' or 'boolean'. They sometimes are used for very small numbers but mostly, they are used in C-strings. See Using Strings.

Use allocate_data to allocate data and return an address. Use poke to save atoms or sequences to at an address. Use peeks or peek to read from an address. Use mem_set and mem_copy to set and copy sections of memory. Use free to free or use delete if you enabled `cleanup` in allocate_data.

#### 8.44.3.3 Using Data Words

Words are 16-bit integers and are big enough to hold most integers in common use as far as whole numbers go. So they often are used to hold numbers. In C, they are declared as WORD or short.

Use allocate_data to allocate data and return its address. Use poke2 to write to the data at an address. Use peek2 or peek2s to read from an address. Use free to free or use delete if you enabled `cleanup` in allocate_data.

#### 8.44.3.4 Using Data Double Words

Double words are 32-bit integers. In C, they are typically declared as int, or long (on Windows and other 32-bit architectures), or DWORD. They are big enough to hold pointers to other values in memory on 32-bit architectures.

Use allocate_data to allocate data and return its address. Use poke4 to write to the data at an address. Use peek4 or peek4s to read from an address. Use free to free or use delete if you enabled `cleanup` in allocate_data.

#### 8.44.3.5 Using Data Quad Words

Quad words are 64-bit integers. In C, they are typically declared as long long int, or long int (on 64-bit architectures other than Windows). They are big enough to hold pointers to other values in memory on 64-bit architectures.

##### Be careful:

Recall that atoms in EUPHORIA (32 bit) have 15 digits of accuracy. Integral Values whose absolute value exceeds 253 might not be representable exactly.

Use allocate_data to allocate data and return its address. Use poke8 to write to the data at an address. Use peek8u or peek8s to read from an address. Use free to free or use delete if you enabled `cleanup` in allocate_data.

#### 8.44.3.6 Using Pointers

A Euphoria atom should be used to store pointer values. On 32-bit architectures, pointers may be larger than a Euphoria integer. On 64-bit architectures, a Euphoria integer is large enough to hold pointer values, since current 64-bit architectures use only a 48-bit memory space

To portably peek and poke pointers, you should use peek_pointer and poke_pointer. These routines automatically detect the architecture and use the correct size for a pointer.

#### 8.44.3.7 Using Long Integers

When interfacing with C code, some data will be defined as `long` or `long int`. This data type can be tricky to use in a portable manner, due to the way that different architectures and operating systems define it.

On all 32-bit architectures on which Euphoria runs, a `long int` is defined as 32-bits. On 64-bit Windows, a `long int` is also 32-bits. However, on other 64-bit operating systems, a `long int` is defined as 64-bits.

To portably peek and poke `long int` data, you should use peek_longs, peek_longu and poke_long. You can also use `sizeof( C_LONG )` to determine the size (in bytes) of a native `long int`.

#### 8.44.3.8 Using Strings

You can create legal ANSI and 16-bit UNICODE Strings with these routines. In C, strings are often declared as some pointer to a character: char * or wchar *.

Microsoft Windows uses 8-bit ANSI and 16-bit UNICODE in its routines.

Use allocate_string or allocate_wstring to allocate a string pointer. Use peek_string, peek_wstring, peek4, to read from memory byte strings, word strings and double word strings repsectively. Use poke, poke2, or poke4 to write to memory byte strings, word strings and double word strings. Use free to free or use delete if you enabled `cleanup` in allocate_data.

#### 8.44.3.9 Using Pointer Arrays

Use allocate_string_pointer_array to allocate a string array from a sequence of strings. Use allocate_pointer_array to allocate and then write to an array for pointers . Use free_pointer_array to deallocate or use delete if you enabled `cleanup` in allocate_data.

### 8.44.4 Memory Allocation

#### 8.44.4.1 allocate

    include std/machine.e
    namespace machine
    public function allocate(memory :positive_int n, types :boolean cleanup = 0)

This does the same as allocate_data but allows the DATA_EXECUTE defined word to cause it to return executable memory.

##### See Also:

allocate_data, allocate_code, free

#### 8.44.4.2 allocate_data

    include std/machine.e
    namespace machine
    public function allocate_data(memory :positive_int n, types :boolean cleanup = 0)

Allocate a contiguous block of data memory.

##### Parameters:

1. `n` : a positive integer, the size of the requested block.
2. `cleanup` : an integer, if non-zero, then the returned pointer will be automatically freed when its reference count drops to zero, or when passed as a parameter to delete.

##### Returns:

An atom, the address of the allocated memory or 0 if the memory can't be allocated. NOTE you must use either an atom or object to receive the returned value as sometimes the returned memory address is too larger for an integer to hold.

##### Comments:

- Since `allocate` acquires memory from the system, it is your responsiblity to return that memory when your application is done with it. There are two ways to do that - automatically or manually.
  - Automatically - If the `cleanup` parameter is non-zero, then the memory is returned when the variable that receives the address goes out of scope and is not referenced by anything else. Alternatively you can force it be released by calling the delete function.
  - Manually - If the `cleanup` parameter is zero, then you must call the free function at some point in your program to release the memory back to the system.
- When your program terminates, the operating system will reclaim all memory that your applicaiton acquired anyway.
- An address returned by this function shouldn't be passed to `call`. For that purpose you should use `allocate_code` instead.
- The address returned will be at least 8-byte aligned.

##### Example 1:

    buffer = allocate(100)
    for i = 0 to 99 do
        poke(buffer+i, 0)
    end for

##### See Also:

Using Data Bytes, Using Data Words, Using Data Double Words, Using Strings, allocate_code, free

#### 8.44.4.3 allocate_pointer_array

    include std/machine.e
    namespace machine
    public function allocate_pointer_array(sequence pointers, types :boolean cleanup = 0)

Allocate a NULL terminated pointer array.

##### Parameters:

1. `pointers` : a sequence of pointers to add to the pointer array.
2. `cleanup` : an integer, if non-zero, then the returned pointer will be automatically freed when its reference count drops to zero, or when passed as a parameter to delete

##### Comments:

This function adds the NULL terminator.

##### Example 1:

    atom pa
    pa = allocate_pointer_array({ allocate_string("1"), allocate_string("2") })

##### See Also:

Using Pointer Arrays, allocate_string_pointer_array, free_pointer_array

#### 8.44.4.4 free_pointer_array

    include std/machine.e
    namespace machine
    public procedure free_pointer_array(atom pointers_array)

Free a NULL terminated pointers array.

##### Parameters:

1. `pointers_array` : memory address of where the NULL terminated array exists at.

##### Comments:

This is for NULL terminated lists, such as allocated by allocate_pointer_array. Do not call `free_pointer_array` for a pointer that was allocated to be cleaned up automatically. Instead, use delete.

##### See Also:

allocate_pointer_array, allocate_string_pointer_array

#### 8.44.4.5 allocate_string_pointer_array

    include std/machine.e
    namespace machine
    public function allocate_string_pointer_array(object string_list, types :boolean cleanup = 0)

Allocate a C-style null-terminated array of strings in memory

##### Parameters:

1. `string_list` : sequence of strings to store in RAM.
2. `cleanup` : an integer, if non-zero, then the returned pointer will be automatically freed when its reference count drops to zero, or when passed as a parameter to delete

##### Returns:

An atom, the address of the memory block where the string pointer array was stored.

##### Example 1:

    atom p = allocate_string_pointer_array({ "One", "Two", "Three" })
    -- Same as C: char *p = { "One", "Two", "Three", NULL };

##### See Also:

Using Pointer Arrays, free_pointer_array

#### 8.44.4.6 allocate_wstring

    include std/machine.e
    namespace machine
    public function allocate_wstring(sequence s, types :boolean cleanup = 0)

Create a C-style null-terminated wchar_t string in memory

##### Parameters:

1. `s` : a unicode (utf16) string

##### Returns:

An atom, the address of the allocated string, or 0 on failure.

##### See Also:

Using Strings, allocate_string

### 8.44.5 Reading from Memory

#### 8.44.5.1 peek

    <built-in> function peek(object addr_n_length)

fetches a byte, or some bytes, from an address in memory.

##### Parameters:

1. `addr_n_length` : an object, either of
   - an atom `addr` -- to fetch one byte at `addr`, or
   - a pair {`addr,len}` -- to fetch `len` bytes at `addr`

##### Returns:

An object, either an integer if the input was a single address, or a sequence of integers if a sequence was passed. In both cases, integers returned are bytes, in the range 0..255.

##### Errors:

Peeking in memory you don't own may be blocked by the OS, and cause a machine exception. If you use the define safe these routines will catch these problems with a EUPHORIA error.

When supplying a {address, count} sequence, the count must not be negative.

##### Comments:

Since addresses are 32-bit numbers on 32-bit architectures, they can be larger than the largest value of type integer (31-bits). Variables that hold an address should therefore be declared as atoms.

It is faster to read several bytes at once using the second form of `peek` than it is to read one byte at a time in a loop. The returned sequence has the length you asked for on input.

Remember that `peek` takes just one argument, which in the second form is actually a 2-element sequence.

##### Example 1:

    -- The following are equivalent:
    -- first way
    s = {peek(100), peek(101), peek(102), peek(103)}

    -- second way
    s = peek({100, 4})

##### See Also:

Using Data Bytes, poke, peeks, peek4u, allocate, free, peek2u

#### 8.44.5.2 peeks

    <built-in> function peeks(object addr_n_length)

fetches a byte, or some bytes, from an address in memory.

##### Parameters:

1. `addr_n_length` : an object, either of
   - an atom `addr` : to fetch one byte at `addr`, or
   - a pair {`addr,len}` : to fetch `len` bytes at `addr`

##### Returns:

An object, either an integer if the input was a single address, or a sequence of integers if a sequence was passed. In both cases, integers returned are bytes, in the range -128..127.

##### Errors:

Peeking in memory you do not own may be blocked by the OS, and cause a machine exception. If you use the define safe these routines will catch these problems with a Euphoria error.

When supplying a {address, count} sequence, the count must not be negative.

##### Comments:

Since addresses are 32-bit numbers on 32-bit architectures, they can be larger than the largest value of type integer (31-bits). Variables that hold an address should therefore be declared as atoms.

It is faster to read several bytes at once using the second form of `peek` than it is to read one byte at a time in a loop. The returned sequence has the length you asked for on input.

Remember that `peeks` takes just one argument, which in the second form is actually a 2-element sequence.

##### Example 1:

    -- The following are equivalent:
    -- first way
    s = {peeks(100), peek(101), peek(102), peek(103)}

    -- second way
    s = peeks({100, 4})

##### See Also:

Using Data Bytes, poke, peek4s, allocate, free, peek2s, peek

#### 8.44.5.3 peek2s

    <built-in> function peek2s(object addr_n_length)

Fetches a signed word, or some signed words , from an address in memory.

##### Parameters:

1. `addr_n_length` : an object, either of
   - an atom `addr` -- to fetch one word at `addr`, or
   - a pair `{ addr, len}`, to fetch `len` words at `addr`

##### Returns:

An object, either an integer if the input was a single address, or a sequence of integers if a sequence was passed. In both cases, integers returned are double words, in the range -32768..32767.

##### Errors:

Peeking in memory you don't own may be blocked by the OS, and cause a machine exception. If you use the define safe these routines will catch these problems with a EUPHORIA error.

When supplying a `{address, count}` sequence, the count must not be negative.

##### Comments:

Since addresses are 32-bit numbers on 32-bit architectures, they can be larger than the largest value of type integer (31-bits). Variables that hold an address should therefore be declared as atoms.

It is faster to read several words at once using the second form of `peek` than it is to read one word at a time in a loop. The returned sequence has the length you asked for on input.

Remember that `peek2s` takes just one argument, which in the second form is actually a 2-element sequence.

The only difference between `peek2s` and `peek2u` is how words with the highest bit set are returned. `peek2s` assumes them to be negative, while `peek2u` just assumes them to be large and positive.

##### Example 1:

    -- The following are equivalent:
    -- first way
    s = {peek2s(100), peek2s(102), peek2s(104), peek2s(106)}

    -- second way
    s = peek2s({100, 4})

##### See Also:

Using Data Words, poke2, peeks, peek4s, allocate, free peek2u

#### 8.44.5.4 peek2u

    <built-in> function peek2u(object addr_n_length)

fetches an unsigned word, or some unsigned words, from an address in memory.

##### Parameters:

1. `addr_n_length` : an object, either of
   - an atom `addr` -- to fetch one double word at `addr`, or
   - a pair {`addr,len}` -- to fetch `len` double words at `addr`

##### Returns:

An object, either an integer if the input was a single address, or a sequence of integers if a sequence was passed. In both cases, integers returned are words, in the range 0..65535.

##### Errors:

Peeking in memory you do not own may be blocked by the OS, and cause a machine exception. If you use the define safe these routines will catch these problems with a Euphoria error.

When supplying a `{address, count}` sequence, the count must not be negative.

##### Comments:

Since addresses are 32-bit numbers on 32-bit architectures, they can be larger than the largest value of type integer (31-bits). Variables that hold an address should therefore be declared as atoms.

It is faster to read several words at once using the second form of `peek` than it is to read one word at a time in a loop. The returned sequence has the length you asked for on input.

Remember that `peek2u` takes just one argument, which in the second form is actually a 2-element sequence.

The only difference between `peek2s` and `peek2u` is how words with the highest bit set are returned. `peek2s` assumes them to be negative, while `peek2u` just assumes them to be large and positive.

##### Example 1:

    -- The following are equivalent:
    -- first way
    Get 4 2-byte numbers starting address 100.
    s = {peek2u(100), peek2u(102), peek2u(104), peek2u(106)}

    -- second way
    Get 4 2-byte numbers starting address 100.
    s = peek2u({100, 4})

##### See Also:

Using Data Words, poke2, peek, peek2s, allocate, free peek4u

#### 8.44.5.5 peek4s

    <built-in> function peek4s(object addr_n_length)

fetches a signed double words, or some signed double words, from an address in memory.

##### Parameters:

1. `addr_n_length` : an object, either of
   - an atom `addr` -- to fetch one double word at `addr`, or
   - a pair `{ addr, len }` -- to fetch `len` double words at `addr`

##### Returns:

An object, either an atom if the input was a single address, or a sequence of atoms if a sequence was passed. In both cases, atoms returned are double words, in the range -(231)..231-1.

##### Errors:

Peeking in memory you don't own may be blocked by the OS, and cause a machine exception. If you use the define safe these routines will catch these problems with a Euphoria error.

When supplying a `{address, count}` sequence, the count must not be negative.

##### Comments:

On 32-bit machines, the information provided by peek8 will be an approximation due to the way numbers are stored. If you want to peek in a lossless way use peek4u or peek4s

Since addresses are 32-bit numbers on 32-bit architectures, they can be larger than the largest value of type integer (31-bits). Variables that hold an address should therefore be declared as atoms.

It is faster to read several double words at once using the second form of `peek` than it is to read one double word at a time in a loop. The returned sequence has the length you asked for on input.

Remember that `peek4s` takes just one argument, which in the second form is actually a 2-element sequence.

The only difference between `peek4s` and peek4u is how double words with the highest bit set are returned. `peek4s` assumes them to be negative, while peek4u just assumes them to be large and positive.

##### Example 1:

    -- The following are equivalent:
    -- first way
    s = {peek4s(100), peek4s(104), peek4s(108), peek4s(112)}

    -- second way
    s = peek4s({100, 4})

##### See Also:

Using Data Double Words, poke4, peeks, peek4u, allocate, free, peek2s

#### 8.44.5.6 peek8s

    <built-in> function peek8s(object addr_n_length)

fetches a signed quad words, or some signed quad words, from an address in memory.

##### Parameters:

1. `addr_n_length` : an object, either of
   - an atom `addr` -- to fetch one double word at `addr`, or
   - a pair `{ addr, len }` -- to fetch `len` quad words at `addr`

##### Returns:

An object, either an atom if the input was a single address, or a sequence of atoms if a sequence was passed. In both cases, atoms returned are quad words, in the range -power(2,63)..power(2,63)-1.

##### Errors:

Peeking in memory you don't own may be blocked by the OS, and cause a machine exception. If you use the define safe these routines will catch these problems with a Euphoria error.

When supplying a `{address, count}` sequence, the count must not be negative.

##### Comments:

On 32-bit machines, the information provided by peek8s will be an approximation due to the limitations on atoms. If you want to peek in a lossless way use peek4u or peek4s

Since addresses are 32-bit numbers on 32-bit architectures, they can be larger than the largest value of type integer (31-bits). Variables that hold an address should therefore be declared as atoms.

It is faster to read several quad words at once using the second form of `peek` than it is to read one quad word at a time in a loop. The returned sequence has the length you asked for on input.

Remember that `peek8s` takes just one argument, which in the second form is actually a 2-element sequence.

The only difference between `peek8s` and peek8u is how quad words with the highest bit set are returned. `peek4s` assumes them to be negative, while peek4u just assumes them to be large and positive.

##### Example 1:

    -- The following are equivalent:
    -- first way
    s = {peek8s(100), peek8s(108), peek8s(116), peek8s(124)}

    -- second way
    s = peek8s({100, 4})

##### See Also:

Using Data Double Words, poke4, peeks, peek4u, allocate, free, peek2s

#### 8.44.5.7 peek4u

    <built-in> function peek4u(object addr_n_length)

fetches an unsigned double word, or some unsigned double words, from an address in memory.

##### Parameters:

1. `addr_n_length` : an object, either of
   - an atom `addr` -- to fetch one double word at `addr`, or
   - a pair {`addr,len}` -- to fetch `len` double words at `addr`

##### Returns:

An object, either an atom if the input was a single address, or a sequence of atoms if a sequence was passed. In both cases, atoms returned are double words, in the range 0..232-1.

##### Errors:

Peeking in memory you do not own may be blocked by the OS, and cause a machine exception. If you use the define safe these routines will catch these problems with a Euphoria error.

When supplying a `{address, count}` sequence, the count must not be negative.

##### Comments:

Since addresses are 32-bit numbers on 32-bit architectures, they can be larger than the largest value of type integer (31-bits). Variables that hold an address should therefore be declared as atoms.

It is faster to read several double words at once using the second form of `peek` than it is to read one double word at a time in a loop. The returned sequence has the length you asked for on input.

Remember that `peek4u` takes just one argument, which in the second form is actually a 2-element sequence.

The only difference between `peek4s` and `peek4u` is how double words with the highest bit set are returned. `peek4s` assumes them to be negative, while `peek4u` just assumes them to be large and positive.

##### Example 1:

    -- The following are equivalent:
    -- first way
    s = {peek4u(100), peek4u(104), peek4u(108), peek4u(112)}

    -- second way
    s = peek4u({100, 4})

##### See Also:

Using Data Double Words, poke4, peek, peek4s, allocate, free, peek2u

#### 8.44.5.8 peek8u

    <built-in> function peek8u(object addr_n_length)

fetches an unsigned quad word, or some unsigned quad words, from an address in memory.

##### Parameters:

1. `addr_n_length` : an object, either of
   - an atom `addr` -- to fetch one double word at `addr`, or
   - a pair {`addr,len}` -- to fetch `len` double words at `addr`

##### Returns:

An object, either an atom if the input was a single address, or a sequence of atoms if a sequence was passed. In both cases, atoms returned are quad words, in the range 0..power(2,64)-1.

##### Errors:

Peeking in memory you do not own may be blocked by the OS, and cause a machine exception. If you use the define safe these routines will catch these problems with a Euphoria error.

When supplying a `{address, count}` sequence, the count must not be negative.

##### Comments:

On 32-bit machines, the information provided by peek8u will be an approximation due to the limitations on atoms. If you want to peek in a lossless way use peek4u or peek4s

Since addresses are 32-bit numbers on 32-bit architectures, they can be larger than the largest value of type integer (31-bits). Variables that hold an address should therefore be declared as atoms.

It is faster to read several quad words at once using the second form of `peek` than it is to read one quad word at a time in a loop. The returned sequence has the length you asked for on input.

Remember that `peek8u` takes just one argument, which in the second form is actually a 2-element sequence.

The only difference between `peek8s` and `peek8u` is how quad words with the highest bit set are returned. `peek8s` assumes them to be negative, while `peek8u` just assumes them to be large and positive.

##### Example 1:

    -- The following are equivalent:
    --first way
    s = {peek8u(100), peek8u(108), peek8u(116), peek8u(124)}

    -- second way
    s = peek8u({100, 4})

##### See Also:

Using Data Double Words, poke4, peek, peek4s, allocate, free, peek2u

#### 8.44.5.9 peek_longu

    <built-in> function peek_longu(object addr_n_length)

fetches an unsigned integer, or some unsigned integers, from an address in memory.

##### Parameters:

1. `addr_n_length` : an object, either of
   - an atom `addr` -- to fetch one double word at `addr`, or
   - a pair {`addr,len}` -- to fetch `len` double words at `addr`

##### Returns:

An object, either an atom if the input was a single address, or a sequence of atoms if a sequence was passed. In both cases, atoms returned are based on the native size of a "long int." On Windows and all other 32-bit architectures, the number will be in the range 0..power(2,32)-1. On other 64-bit architectures, the number will be in the range of 0..power(2,64)-1.

##### Errors:

Peeking in memory you do not own may be blocked by the OS, and cause a machine exception. If you use the define safe these routines will catch these problems with a Euphoria error.

When supplying a `{address, count}` sequence, the count must not be negative.

##### Comments:

Since addresses are 32-bit numbers on 32-bit architectures, they can be larger than the largest value of type integer (31-bits). Variables that hold an address should therefore be declared as atoms.

It is faster to read several integers at once using the second form of `peek` than it is to read one integer at a time in a loop. The returned sequence has the length you asked for on input.

Remember that `peek_longu` takes just one argument, which in the second form is actually a 2-element sequence.

The only difference between `peek_longs` and `peek_longu` is how double words with the highest bit set are returned. `peek4s` assumes them to be negative, while `peek_longu` just assumes them to be large and positive.

##### Example 1:

    -- The following are equivalent (on a 32-bit architecture, or Windows):
    -- first way
    s = {peek_longu(100), peek4u(104), peek4u(108), peek4u(112)}

    -- second way
    s = peek_longu({100, 4})

##### See Also:

Using Data Double Words, poke4, peek, peek4s, allocate, free, peek2u, peek2s, peek8u, peek8s, peek_longs, poke_long

#### 8.44.5.10 peek_string

    <built-in> function peek_string(atom addr)

reads an ASCII string in RAM, starting from a supplied address.

##### Parameters:

1. `addr` : an atom, the address at which to start reading.

##### Returns:

A sequence, of bytes, the string that could be read.

##### Errors:

Further, peeking in memory that does not belong to your process is something the operating system could prevent, and you'd crash with a machine level exception.

##### Comments:

An ASCII string is any sequence of bytes and ends with a 0 byte. If you `peek_string` at some place where there is no string, you will get a sequence of garbage.

##### See Also:

Using Strings, peek, peek_wstring, allocate_string

#### 8.44.5.11 peek_pointer

    <built-in> function peek_pointer(object addr_n_length)

#### 8.44.5.12 peek_wstring

    include std/machine.e
    namespace machine
    public function peek_wstring(atom addr)

returns a unicode (utf16) string that are stored at machine address a.

##### Parameters:

1. `addr` : an atom, the address of the string in memory

##### Returns:

The string, at the memory position. The terminator is the null word (two bytes equal to 0).

##### See Also:

Using Strings, peek_string

### 8.44.6 Writing to Memory

#### 8.44.6.1 poke

    <built-in> procedure poke(atom addr, object x)

stores one or more bytes, starting at a memory location.

##### Parameters:

1. `addr` : an atom, the address at which to store
2. `x` : an object, either a byte or a non empty sequence of bytes.

##### Errors:

Poking in memory you do not own may be blocked by the OS, and cause a machine exception. The `-D SAFE` option will make `poke` catch this sort of issues.

##### Comments:

The lower 8-bits of each byte value (such as `remainder(x, 256)`) is actually stored in memory.

It is faster to write several bytes at once by poking a sequence of values, than it is to write one byte at a time in a loop.

Writing to the screen memory with `poke` can be much faster than using `puts` or `printf`, but the programming is more difficult. In most cases the speed is not needed. For example, the Euphoria editor, `ed`, never uses `poke`.

##### Example 1:

    a = allocate(100)   -- allocate 100 bytes in memory

    -- poke one byte at a time:
    poke(a, 97)
    poke(a+1, 98)
    poke(a+2, 99)

    -- poke 3 bytes at once:
    poke(a, {97, 98, 99})

##### Example 2:

`demo/callmach.ex`

##### See Also:

Using Data Bytes, peek, peeks, poke4, allocate, free, poke2, mem_copy, mem_set

#### 8.44.6.2 poke2

    <built-in> procedure poke2(atom addr, object x)

stores one or more words, starting at a memory location.

##### Parameters:

1. `addr` : an atom, the address at which to store
2. `x` : an object, either a word or a non empty sequence of words.

##### Errors:

Poking in memory you do not own may be blocked by the OS, and cause a machine exception. If you use the define safe these routines will catch these problems with a Euphoria error.

##### Comments:

There is no point in having `poke2s` or `poke2u`. For example, both 32768 and -32768 are stored as `#F000` when stored as words. It is up to whoever reads the value to figure it out.

It is faster to write several words at once by poking a sequence of values, than it is to write one words at a time in a loop.

Writing to the screen memory with `poke2` can be much faster than using `puts` or `printf`, but the programming is more difficult. In most cases the speed is not needed. For example, the Euphoria editor, ed, never uses `poke2`.

The 2-byte values to be stored can be negative or positive. You can read them back with either `peek2s` or `peek2u`. Actually, only `remainder(`x`,65536)` is being stored.

##### Example 1:

    a = allocate(100)   -- allocate 100 bytes in memory

    -- poke one 2-byte value at a time:
    poke2(a, 12345)
    poke2(a+2, #FF00)
    poke2(a+4, -12345)

    -- poke 3 2-byte values at once:
    poke2(a, {12345, #FF00, -12345})

##### See Also:

Using Data Words, peek2s, peek2u, poke, poke4, allocate, free

#### 8.44.6.3 poke4

    <built-in> procedure poke4(atom addr, object x)

stores one or more double words, starting at a memory location.

##### Parameters:

1. `addr` : an atom, the address at which to store
2. `x` : an object, either a double word or a non empty sequence of double words.

##### Errors:

Poking in memory you do not own may be blocked by the OS, and cause a machine exception. If you use the define safe these routines will catch these problems with a Euphoria error.

##### Comments:

There is no point in having `poke4s` or `poke4u`. For example, both +231 and -(231) are stored as `#F0000000`. It is up to whoever reads the value to figure it out.

It is faster to write several double words at once by poking a sequence of values, than it is to write one double words at a time in a loop.

Writing to the screen memory with `poke4` can be much faster than using `puts` or `printf`, but the programming is more difficult. In most cases the speed is not needed. For example, the Euphoria editor, ed, never uses `poke4`.

The 4-byte values to be stored can be negative or positive. You can read them back with either `peek4s` or `peek4u`. However, the results are unpredictable if you want to store values with a fractional part or a magnitude greater than 232, even though Euphoria represents them all as atoms.

##### Example 1:

    a = allocate(100)   -- allocate 100 bytes in memory

    -- poke one 4-byte value at a time:
    poke4(a, 9712345)
    poke4(a+4, #FF00FF00)
    poke4(a+8, -12345)

    -- poke 3 4-byte values at once:
    poke4(a, {9712345, #FF00FF00, -12345})

##### See Also:

Using Data Double Words, peek4s, peek4u, poke, poke2, allocate, free, call

#### 8.44.6.4 poke8

    <built-in> procedure poke8(atom addr, object x)

stores one or more quad words, starting at a memory location.

##### Parameters:

1. `addr` : an atom, the address at which to store
2. `x` : an object, either a quad word or a non empty sequence of double words.

##### Errors:

Poking in memory you do not own may be blocked by the OS, and cause a machine exception. If you use the define safe these routines will catch these problems with a Euphoria error.

##### Comments:

On 32-bit machines, the number you supply to poke8 will already be an approximate value before it can reach the memory. If you want to poke exact values way use poke4u or poke4s

There is no point in having `poke8s` or `poke8u`. For example, both +power(2,63) and -power(2,63) are stored as `#F000000000000000`. It is up to whoever reads the value to figure it out.

It is faster to write several quad words at once by poking a sequence of values, than it is to write one quad words at a time in a loop.

The 8-byte values to be stored can be negative or positive. You can read them back with either `peek8s` or `peek8u`. However, the results are unpredictable if you want to store values with a fractional part or a magnitude greater than 264, even though Euphoria represents them all as atoms.

##### Example 1:

    a = allocate(100)   -- allocate 100 bytes in memory

    -- poke one 8-byte value at a time:
    poke8(a, 9712345)
    poke8(a+8, #FF00FF00)
    poke8(a+16, -12345)

    -- poke 3 8-byte values at once:
    poke8(a, {9712345, #FF00FF00, -12345})

##### See Also:

Using Data Quad Words, peek4s, peek4u, poke, poke2, allocate, free, call

#### 8.44.6.5 poke_long

    <built-in> procedure poke_long(atom addr, object x)

stores one or more integers, starting at a memory location.

##### Parameters:

1. `addr` : an atom, the address at which to store
2. `x` : an object, either an integer or a non empty sequence of double words.

##### Errors:

Poking in memory you do not own may be blocked by the OS, and cause a machine exception. If you use the define safe these routines will catch these problems with a Euphoria error.

##### Comments:

There is no point in having `poke_longs` or `poke_longu`. For example, both +power(2,31) and -power(2,31) are stored as `#F0000000` on a 32-bit architecture. It is up to whoever reads the value to figure it out.

On all Windows and other 32-bit operating systems, the `poke_long` uses 4-byte integers. On 64-bit architectures using operating systems other than Windows, `poke_long` uses 8-byte integers.

It is faster to write several integers at once by poking a sequence of values, than it is to write one double words at a time in a loop.

The 4-byte (or 8-byte) values to be stored can be negative or positive. You can read them back with either `peek_longs` or `peek_longu`. However, the results are unpredictable if you want to store values with a fractional part or a magnitude greater than the size of a native `long int`, even though Euphoria represents them all as atoms.

##### Example 1:

    a = allocate(100)   -- allocate 100 bytes in memory

    -- poke one 4-byte value at a time (on Windows or other 32-bit operating system):
    poke_long(a, 9712345)
    poke_long(a+4, #FF00FF00)
    poke_long(a+8, -12345)

    -- poke 3 long int values at once:
    poke_long(a, {9712345, #FF00FF00, -12345})

##### See Also:

Using Data Double Words, peek4s, peek4u, poke, poke2, allocate, free, call

#### 8.44.6.6 poke_pointer

    <built-in> procedure poke_pointer(atom addr, object x)

stores one or more pointers, starting at a memory location.

##### Parameters:

1. `addr` : an atom, the address at which to store
2. `x` : an object, either an integer or a non empty sequence of pointers.

##### Errors:

Poking in memory you do not own may be blocked by the OS, and cause a machine exception. If you use the define safe these routines will catch these problems with a Euphoria error.

##### Comments:

There is no point in having `poke_pointers` or `poke_pointersu`. For example, both +power(2,31) and -power(2,31) are stored as `#F0000000` on a 32-bit architecture. It is up to whoever reads the value to figure it out.

On all 32-bit operating systems, the `poke_pointer` uses 4-byte integers. On 64-bit architectures using operating systems, `poke_pointer` uses 8-byte integers.

It is faster to write several pointers at once by poking a sequence of values, than it is to write one double words at a time in a loop.

The 4-byte (or 8-byte) values to be stored can be negative or positive. You can read them back with either `peek_pointer` or any other peek function of the correctsize. However, the results are unpredictable if you want to store values with a fractional part or a magnitude greater than the size of a native `pointer`, even though Euphoria represents them all as atoms.

##### Example 1:

    a = allocate(100)   -- allocate 100 bytes in memory

    -- poke one 4-byte value at a time (on a 32-bit operating system):
    poke_pointer(a, 9712345)
    poke_pointer(a+4, #FF00FF00)
    poke_pointer(a+8, -12345)

    -- poke 3 long int values at once:
    poke_pointer(a, {9712345, #FF00FF00, -12345})

##### See Also:

Using Data Double Words, peek4s, peek4u, peek8u, peek8s, peek_pointer poke, poke2, allocate, free, call

#### 8.44.6.7 poke_string

    include std/machine.e
    namespace machine
    public function poke_string(atom buffaddr, integer buffsize, sequence s)

Stores a C-style null-terminated ANSI string in memory

##### Parameters:

1. `buffaddr`: an atom, the RAM address to to the string at.
2. `buffsize`: an integer, the number of bytes available, starting from `buffaddr`.
3. `s` : a sequence, the string to store at address `buffaddr`.

##### Comments:

- This does not allocate an RAM. You must supply the preallocated area.
- This can only be used on ANSI strings. It cannot be used for double-byte strings.
- If `s` is not a string, nothing is stored and a zero is returned.

##### Returns:

An atom. If this is zero, then nothing was stored, otherwise it is the address of the first byte after the stored string.

##### Example 1:

    atom title

    title = allocate(1000)
    if poke_string(title, 1000, "The Wizard of Oz") then
        -- successful
    else
        -- failed
    end if

##### See Also:

Using Strings, allocate, allocate_string

#### 8.44.6.8 poke_wstring

    include std/machine.e
    namespace machine
    public function poke_wstring(atom buffaddr, integer buffsize, sequence s)

stores a C-style null-terminated Double-Byte string in memory.

##### Parameters:

1. `buffaddr`: an atom, the RAM address to to the string at.
2. `buffsize`: an integer, the number of bytes available, starting from `buffaddr`.
3. `s` : a sequence, the string to store at address `buffaddr`.

##### Comments:

- This does not allocate an RAM. You must supply the preallocated area.
- This uses two bytes per string character. Note that `buffsize` is the number of bytes available in the buffer and not the number of characters available.
- If `s` is not a double-byte string, nothing is stored and a zero is returned.

##### Returns:

An atom. If this is zero, then nothing was stored, otherwise it is the address of the first byte after the stored string.

##### Example 1:

    atom title

    title = allocate(1000)
    if poke_wstring(title, 1000, "The Wizard of Oz") then
        -- successful
    else
        -- failed
    end if

##### See Also:

Using Strings, allocate, allocate_wstring

### 8.44.7 Memory Manipulation

#### 8.44.7.1 mem_copy

    <built-in> procedure mem_copy(atom destination, atom origin, integer len)

copies a block of memory from an address to another.

##### Parameters:

1. `destination` : an atom, the address at which data is to be copied
2. `origin` : an atom, the address from which data is to be copied
3. `len` : an integer, how many bytes are to be copied.

##### Comments:

The bytes of memory will be copied correctly even if the block of memory at `destination` overlaps with the block of memory at `origin`.

mem_copy(destination, origin, len) is equivalent to: poke(destination, peek({origin, len})) but is much faster.

##### Example 1:

    dest = allocate(50)
    src = allocate(100)
    poke(src, {1,2,3,4,5,6,7,8,9})
    mem_copy(dest, src, 9)

##### See Also:

Using Data Bytes, mem_set, peek, poke, allocate, free

#### 8.44.7.2 mem_set

    <built-in> procedure mem_set(atom destination, integer byte_value, integer how_many))

sets a contiguous range of memory locations to a single value.

##### Parameters:

1. `destination` : an atom, the address starting the range to set.
2. `byte_value` : an integer, the value to copy at all addresses in the range.
3. `how_many` : an integer, how many bytes are to be set.

##### Comments:

The low order 8 bits of `byte_value` are actually stored in each byte. mem_set(destination, byte_value, how_many) is equivalent to: poke(destination, repeat(byte_value, how_many)) but is much faster.

##### Example 1:

    destination = allocate(1000)
    mem_set(destination, ' ', 1000)
    -- 1000 consecutive bytes in memory will be set to 32
    -- (the ASCII code for ' ')

##### See Also:

Using Data Bytes, peek, poke, allocate, free, mem_copy

### 8.44.8 Calling Into Memory

#### 8.44.8.1 call

    <built-in> procedure call(atom addr)

calls a machine language routine which was stored in memory prior.

##### Parameters:

1. `addr` : an atom, the address at which to transfer execution control.

##### Comments:

The machine code routine must execute a RET instruction #C3 to return control to Euphoria. The routine should save and restore any registers that it uses.

You can allocate a block of memory for the routine and then poke in the bytes of machine code using `allocate_code`. You might allocate other blocks of memory for data and parameters that the machine code can operate on using `allocate`. The addresses of these blocks could be part of the machine code.

If your machine code uses the stack, use `c_proc` instead of `call`.

##### Example 1:

`demo/callmach.ex`

##### See Also:

Executable Memory, allocate_code, free_code, c_proc, define_c_proc

### 8.44.9 Allocating and Writing to memory:

#### 8.44.9.1 allocate_code

    include std/machine.e
    namespace machine
    public function allocate_code(object data, memconst :valid_wordsize wordsize = 1)

allocates and copies data into executable memory.

##### Parameters:

1. `a_sequence_of_machine_code` : is the machine code to be put into memory to be later called with call
2. the `word length` : of the said code. You can specify your code as 1-byte, 2-byte or 4-byte chunks if you wish. If your machine code is byte code specify 1. The default is 1.

##### Returns:

An address, The function returns the address in memory of the code, that can be safely executed whether DEP is enabled or not or 0 if it fails. On the other hand, if you try to execute a code address returned by allocate with DEP enabled the program will receive a machine exception.

##### Comments:

Use this for the machine code you want to run in memory. The copying is done for you and when the routine returns the memory may not be readable or writeable but it is guaranteed to be executable. If you want to also write to this memory after the machine code has been copied you should use allocate_protect instead and you should read about having memory executable and writeable at the same time is a bad idea. You mustn't use `free` on memory returned from this function. You may instead use `free_code` but since you will probably need the code throughout the life of your program's process this normally is not necessary. If you want to put only data in the memory to be read and written use allocate.

##### See Also:

Executable Memory, allocate, free_code, allocate_protect

#### 8.44.9.2 allocate_string

    include std/machine.e
    namespace machine
    public function allocate_string(sequence s, types :boolean cleanup = 0)

Allocate a C-style null-terminated string in memory

##### Parameters:

1. `s` : a sequence, the string to store in RAM.
2. `cleanup` : an integer, if non-zero, then the returned pointer will be automatically freed when its reference count drops to zero, or when passed as a parameter to delete.

##### Returns:

An atom, the address of the memory block where the string was stored, or 0 on failure.

##### Comments:

Only the 8 lowest bits of each atom in `s` is stored. Use `allocate_wstring` for storing double byte encoded strings.

There is no `allocate_string_low` function. However, you could easily craft one by adapting the code for `allocate_string`.

Since `allocate_string` allocates memory, you are responsible to free the block when done with it if `cleanup` is zero. If `cleanup` is non-zero, then the memory can be freed by calling delete, or when the pointer's reference count drops to zero.

##### Example 1:

    atom title

    title = allocate_string("The Wizard of Oz")

##### See Also:

Using Strings, allocate, allocate_wstring

#### 8.44.9.3 allocate_protect

    include std/machine.e
    namespace machine
    public function allocate_protect(object data, memconst :valid_wordsize wordsize = 1,
            valid_memory_protection_constant protection)

Allocates and copies data into memory and gives it protection using Standard Library Memory Protection Constants or Microsoft Windows Memory Protection Constants. The user may only pass in one of these constants. If you only wish to execute a sequence as machine code use `allocate_code`. If you only want to read and write data into memory use `allocate`.

See MSDN: Microsoft's Memory Protection Constants

##### Parameters:

1. `data` : is the machine code to be put into memory.
2. `wordsize` : is the size each element of data will take in memory. Are they 1-byte, 2-bytes, 4-bytes or 8-bytes long? Specify here. The default is 1.
3. `protection` : is the particular Windows protection.

##### Returns:

An address, The function returns the address to the required memory or 0 if it fails. This function is guaranteed to return memory on the 8 byte boundary. It also guarantees that the memory returned with at least the protection given (but you may get more).

If you want to call `allocate_protect( data, PAGE_READWRITE )`, you can use allocate instead. It is more efficient and simpler.

If you want to call `allocate_protect( data, PAGE_EXECUTE )`, you can use allocate_code instead. It is simpler.

You must not use free on memory returned from this function, instead use free_code.

##### See Also:

Executable Memory

### 8.44.10 Memory Disposal

#### 8.44.10.1 free

    include std/machine.e
    namespace machine
    public procedure free(object addr)

frees up a previously allocated block of memory.

##### Parameters:

1. `addr`, either a single atom or a sequence of atoms; these are addresses of a blocks to free.

##### Comments:

- Use `free` to return blocks of memory the during execution. This will reduce the chance of running out of memory or getting into excessive virtual memory swapping to disk.
- Do not reference a block of memory that has been freed.
- When your program terminates, all allocated memory will be returned to the system.
- `addr` must have been allocated previously using allocate. You cannot use it to relinquish part of a block. Instead, you have to allocate a block of the new size, copy useful contents from old block there and then `free` the old block.
- If the memory was allocated and automatic cleanup was specified, then do not call `free` directly. Instead, use delete.
- An `addr` of zero is simply ignored.

##### Example 1:

`demo/callmach.ex`

##### See Also:

Using Data Bytes, Using Data Words, Using Data Double Words, Using Strings, allocate_data, free_code

#### 8.44.10.2 free_code

    include std/machine.e
    public procedure free_code( atom addr, integer size, valid_wordsize wordsize = 1 )

frees up allocated code memory.

##### Parameters:

1. `addr` : must be an address returned by allocate_code or allocate_protect. Do not pass memory returned from allocate here!
2. `size` : is the length of the sequence passed to `alllocate_code` or the size you specified when you called `allocate_protect`.
3. `wordsize`: valid_wordsize default = 1

##### Comments:

Chances are you will not need to call this function because code allocations are typically public scope operations that you want to have available until your process exits.

See Also: Executable Memory, allocate_code, free

### 8.44.11 Automatic Resource Management

Euphoria objects are automatically garbage collected when they are no longer referenced anywhere. Euphoria also provides the ability to manage resources associated with euphoria objects. These resources could be open file handles, allocated memory, or other euphoria objects. There are two built-in routines for managing these external resources.

#### 8.44.11.1 delete_routine

    <built-in> function delete_routine( object x, integer rid )

associates a routine for cleaning up after a Euphoria object.

##### Comments:

`delete_routine` associates a euphoria object with a routine id meant to clean up any allocated resources. It always returns an atom (double) or a sequence, depending on what was passed (integers are promoted to atoms).

The routine specified by `delete_routine` should be a procedure that takes a single parameter, being the object to be cleaned up after. Objects are cleaned up under one of two circumstances. The first is if it's called as a parameter to `delete`. After the call, the association with the delete routine is removed.

The second way for the delete routine to be called is when its reference count is reduced to 0. Before its memory is freed, the delete routine is called. A default delete will be used if the cleanup parameter to one of the allocate routines is true.

`delete_routine` may be called multiple times for the same object. In this case, the routines are called in reverse order compared to how they were associated.

#### 8.44.11.2 delete

    <built-in> procedure delete( object x )

calls the cleanup routines associated with the object, and removes the association with those routines.

##### Comments:

The cleanup routines associated with the object are called in reverse order than they were added. If the object is an integer, or if no cleanup routines are associated with the object, then nothing happens.

After the cleanup routines are called, the value of the object is unchanged, though the cleanup routine will no longer be associated with the object.

### 8.44.12 Types and Constants

#### 8.44.12.1 std_library_address

    include std/machine.e
    namespace machine
    public type std_library_address(object addr)

an address returned from `allocate` or `allocate_protect` or `allocate_code` or the value 0.

##### Returns:

An integer, The type will return 1 if the parameter, an address, was returned from one of these Machine Level functions (and has not yet been freeed)

##### Comments:

This type is equivalent to atom unless SAFE is defined. Only values that satisfy this type may be passed into free or free_code.

#### 8.44.12.2 valid_memory_protection_constant

    include std/machine.e
    public type valid_memory_protection_constant(object a)

protection constants type

#### 8.44.12.3 machine_addr

    include std/machine.e
    public type machine_addr(object a)

a 32-bit non-null machine address

#### 8.44.12.4 safe_address

    include std/machine.e
    public function safe_address(machine_addr start, natural len,
                  positive_int action )

action is some bitwise-or combination of the following constants: A_READ, A_WRITE and A_EXECUTE.

##### Returns:

When Safe Mode is turned on, this returns true iff it is ok to perform action all addresses from start to start+len-1.

When Safe Mode is not turned on, this always returns true.

##### Comments:

This is used mostly inside the safe library itself to check whenever you call Machine Level Access Functions or Procedures. It should only be used for debugging purposes.

#### 8.44.12.5 ADDRESS_LENGTH

    include std/machine.e
    namespace machine
    public constant ADDRESS_LENGTH

The number of bytes required to hold a pointer.

#### 8.44.12.6 PAGE_SIZE

    include std/machine.e
    namespace machine
    public constant PAGE_SIZE

The operating system's memory page length in bytes.

## 8.45 Indirect Routine Calling

### 8.45.1 Accessing Euphoria coded routines

#### 8.45.1.1 routine_id

    <built-in> function routine_id(sequence routine_name)

returns an integer id number for a user-defined Euphoria procedure or function.

##### Parameters:

1. `routine_name` : a string, the name of the procedure or function.

##### Returns:

An integer, known as a routine id, -1 if the named routine can't be found, else zero or more.

##### Errors:

`routine_name` should not exceed 1,024 characters.

##### Comments:

The id number can be passed to call_proc or call_func, to indirectly call the routine named by `routine_name`. This id depends on the internal process of parsing your code, not on `routine_name`.

The routine named `routine_name` must be visible (that is callable) at the place where `routine_id` is used to get the id number. If it is not, -1 is returned.

Indirect calls to the routine can appear earlier in the program than the definition of the routine, but the id number can only be obtained in code that comes after the definition of the routine - see example 2 below.

Once obtained, a valid routine id can be used at any place in the program to call a routine indirectly via call_proc or call_func, including at places where the routine is no longer in scope.

Some typical uses of `routine_id` are:

1. Creating a subroutine that takes another routine as a parameter. (See Example 2 below)
2. Using a sequence of routine id's to make a case (switch) statement. Using the switch statement is more efficient.
3. Setting up an Object-Oriented system.
4. Getting a routine id so you can pass it to call_back. (See Platform-Specific Issues)
5. Getting a routine id so you can pass it to task_create. (See Multitasking in Euphoria)
6. Calling a routine that is defined later in a program. This is no longer needed from v4.0 onward.

Note that C routines, callable by Euphoria, also have ids, but they cannot be used where routine ids are, because of the different type checking and other technical issues.

##### See Also:

define_c_proc and define_c_func

##### Example 1:

    procedure foo()
        puts(1, "Hello World\n")
    end procedure

    integer foo_num
    foo_num = routine_id("foo")

    call_proc(foo_num, {})  -- same as calling foo()

##### Example 2:

    function apply_to_all(sequence s, integer f)
        -- apply a function to all elements of a sequence
        sequence result
        result = {}
        for i = 1 to length(s) do
            -- we can call add1() here although it comes later in the program
            result = append(result, call_func(f, {s[i]}))
        end for
        return result
    end function

    function add1(atom x)
        return x + 1
    end function

    -- add1() is visible here, so we can ask for its routine id
    ? apply_to_all({1, 2, 3}, routine_id("add1"))
    -- displays {2,3,4}

##### See Also:

call_proc, call_func, call_back, define_c_func, define_c_proc, task_create, Platform-Specific Issues, Indirect routine calling

#### 8.45.1.2 call_func

    <built-in> function call_func(integer id, sequence args={})

calls the user-defined Euphoria function by routine id.

##### Parameters:

1. `id` : an integer, the routine id of the function to call
2. `args` : a sequence, the parameters to pass to the function.

##### Returns:

The value, the called function returns.

##### Errors:

If `id` is negative or otherwise unknown, an error occurs.

If the length of `args` is not the number of parameters the function takes, an error occurs.

##### Comments:

`id` must be a valid routine id returned by routine_id.

`args` must be a sequence of argument values of length n, where n is the number of arguments required by the called function. Defaulted parameters currently cannot be synthesized while making a indirect call.

If the function with id `id` does not take any arguments then `args` should be `{}`.

##### Example 1:

Take a look at the sample program called `demo/csort.ex`

##### See Also:

call_proc, routine_id, c_func

#### 8.45.1.3 call_proc

    <built-in> procedure call_proc(integer id, sequence args={})

calls a user-defined Euphoria procedure by routine id.

##### Parameters:

1. `id` : an integer, the routine id of the procedure to call
2. `args` : a sequence, the parameters to pass to the function.

##### Errors:

If `id` is negative or otherwise unknown, an error occurs.

If the length of `args` is not the number of parameters the function takes, an error occurs.

##### Comments:

`id` must be a valid routine id returned by routine_id.

`args` must be a sequence of argument values of length n, where n is the number of arguments required by the called procedure. Defaulted parameters currently cannot be synthesized while making a indirect call.

If the procedure with id `id` does not take any arguments then `args` should be `{}`.

##### Example 1:

    public integer foo_id

    procedure x()
        call_proc(foo_id, {1, "Hello World\n"})
    end procedure

    procedure foo(integer a, sequence s)
        puts(a, s)
    end procedure

    foo_id = routine_id("foo")

    x()

##### See Also:

call_func, routine_id, c_proc

### 8.45.2 Accessing Euphoria Internals

#### 8.45.2.1 machine_func

    <built-in> function machine_func(integer machine_id, object args={})

performs a machine-specific operation that returns a value.

##### Returns:

Depends on the called internal facility.

##### Comments:

This function us mainly used by the standard library files to implement machine dependent operations such as graphics and sound effects. This routine should normally be called indirectly via one of the library routines in a Euphoria include file. User programs normally do not need to call `machine_func`.

A direct call might cause a machine exception if done incorrectly.

##### See Also:

machine_proc

#### 8.45.2.2 machine_proc

    <built-in> procedure machine_proc(integer machine_id, object args={})

perform a machine-specific operation that does not return a value.

##### Comments:

This procedure us mainly used by the standard library files to implement machine dependent operations such as graphics and sound effects. This routine should normally be called indirectly via one of the library routines in a Euphoria include file. User programs normally do not need to call `machine_proc`.

A direct call might cause a machine exception if done incorrectly.

##### See Also:

machine_func

| Up |  |  | TOC | Index
<< 7 Included Tools | < 8.43 Pseudo Memory | Up: 8 API Reference | 8.46 Memory Constants > | 9 Release Notes >>