home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Acorn User 10
/
AU_CD10.iso
/
Archived
/
Updates
/
Perl
/
RPC
/
perl_113_riscpc
/
Docs
/
RISCOS-Library-Docs
/
SWI.pm
< prev
next >
Wrap
Text File
|
1999-04-17
|
7KB
|
191 lines
NAME
RISCOS::SWI -- perl interface to SWI calls
SYNOPSIS
use RISCOS::SWI;
$number = RISCOS::SWI::swix ('OS_SWINumberFromString', regmask([1]), $name);
@regs = unpack 'I10', kernelswi ('OS_File', 5, $filename);
DESCRIPTION
This module provides a SWI interface for perl. There are two
alternative interfaces supported - kernelswi and swi/swix. Both
take the SWI to call as the first parameter, which can be
specified by name or number. Although calling a SWI by name
makes for highly readable code, the name lookup itself often
takes longer than the actual SWI, so for production code it is
wise to perform the name lookup once at initialisation using
`SWINumberFromString' and cache the number in a variable.
`kernelswi' and `swix' both automatically call the `X' (error
returning) version of the SWI, return undefined on error and
copy the error block number and message to `$^E'. `swi' calls
`swix', but will terminate the script with the error number and
message if an error occurs.
For both interfaces registers are initialised from perl
variables according to the following rules:
the undefined value is passed as zero
"numbers" are passed as integers
"strings" are passed as pointers to the strings - perl automatically adds
a `"\0"' at the end to create null terminated strings.
Overwriting the contents alters the variable's value - it is
up to the script to ensure that the perl scalar value is
made long enough before calling the SWI. Note also that
string constants are treated as read only so attempting to
call
$number = RISCOS::SWI::swix ('OS_SWINumberFromString', regmask([1]),
'OS_SWINumberFromString');
would cause a fatal runtime error.
"strings" and "numbers" are in quotes because the internals rely
on perl's flags to determine whether a scalar is a number or
string. The trouble comes when perl has been implicitly
converting between the two and thinks that the result of `6*7'
is `"42"', which it will try to pass in as a pointer to a
string. The work around is to add zero to parameters that must
be numeric, and concatenate `''' to parameters that are strings:
$number += 0;
$string = "0"; # This may be interpreted as the number zero
kernelswi ($swi, 0, $string . '') # Not now.
The latter is, to quote Paul Moore, "fairly obscure magic
(deliberately invalidating the flag which says that the string
has a valid numeric value, and then using the string before perl
has a chance to notice that the numeric value is still OK), but
works fine."
The two interfaces are both built into the perl binary and so
are always available, with or without this module. They differ
in the method of passing in and returning results from
registers.
kernelswi <name>|<number>, [<R0 value>, [<R1 value], ...
is similar to the C library function of the same name. It
takes as parameters the SWI to call and optionally up to 10
more values assigned to `R0' - `R9' in order. Unassigned
registers have undefined values (not zero, unlike `BASIC').
If the SWI generates an error then undefined is returned,
and `$^E' is set to the error number and message from the
error block (*c.f.* `$!'). If there is no error then
`kernelswi' returning a single scalar block of length 40,
the packed return results from `R0' - `R9'. For example,
these may be converted to an array of integers with code of
the form
@regs = unpack 'I10', $kernelswi_result;
swix <name>|<number>, [<mask>, [<value> ...
is similar to the alternative C veneer written by Edward
Nevill and Jonathan Roach and supplied with Acorn C versions
4 and later.
Like `kernelswi', swix returns undefined and sets `$^E' if
an error is generated. If there is no error, swix returns
the contents of `R0'
*mask* is a bitmask that describes the interpretation to
place on the remaining parameters. If it is omitted it is
treated as zero (no parameters). Otherwise it is best
generated by the `regmask' function. *mask* must be numeric
- string values are reserved and cause a fatal error at
runtime.
regmask <in>, [<out>, [<block>]]
*in* and *out* are references to arrays of register
numbers to respectively pass into and out from the SWI.
If either is undefined it is treated as an empty array.
Registers 0 to 9 can be passed in, 0 to 9 and 15
returned.
If present, *block* is the number of register to set up
to point to any remaining parameters "left over". This
provides a convenient way of generating parameter blocks
for SWIs such as `Wimp_CreateWindow'.
values follow in register number order - first values to
pass in, then scalars in which the value of registers out
are returned. The script must ensure that these scalars are
at least 4 bytes long, as the assembler `swix' veneer makes
no checks.
Although this interface seems considerably more complex than
`kernelswi', it does allow much greater flexibility in
exactly which registers are wanted.
Integer results can be retrieved with code such as
unpack('i', $len)
string results by dereferencing pointers
unpack('p', $addr)
swi calls `swix', returning `R0 + 0' to ensure a number, or `die's
with the numeric and string values of `$^E' if there was an
error.
`RISCOS::SWI' also provides conversion functions between SWI
names and numbers, and symbolic constants for the 4 ARM flags
and the OS 'X' bit.
V_Flag
C_Flag
Z_Flag
N_Flag
return the bit corresponding to the position of flag in the
`PC/PSR'.
XOS_Bit
returns 0x20000 - which when set marks the error returning
form of a SWI.
SWINumberToString <SWI number>
converts a SWI number to a name using the SWI
`OS_SWINumberToString'. Returns the name of the SWI, or
undefined if there was an error. Unknown SWI numbers which
the SWI `OS_SWINumberToString' converts to '`User'' or
'`XUser'' are returned as '`User (&C00FEE)'' or '`XUser
(&0B100D)''.
SWINumberFromString <SWI name>
provides a full inverse to `SWINumberToString'. "User" SWIs
described above are recognised, as are `OS_WriteI' variants.
Other SWIs numbers are converted using the SWI
`OS_SWINumberFromString'.
BUGS
`swix' doesn't automatically ensure that scalars for return
values exist and are long enough. Additionally the current mask
system doesn't allow the script to specify whether it wants a
number, string or fixed length block to be returned, and let the
perl internals convert and assign the return values
automatically. String "masks" are reserved for this purpose.
AUTHOR
Nicholas Clark <nick@unfortu.net>, based on the previous perl
ports.
The `swi' interface is `syscall' from the perl 5.001 port. The
`kernelswi' interface is `syscall' from the perl 3 port.