Brian said:
...
> > Also, XCODETRAP/XARITRAP/XSYSTRAP and the POSIX signal handlers
> > are also forms of error handling and recovery.
>
> I suspect it is in this area that my interest lies. I had a brief
...
> Being able to treat a divide by zero or de-reference of a null pointer
> with the same mechanism as a user thrown exception would be nice.
Pascal:
...code A...
try
begin
...code B...
end
recover
begin
...code C...
end;
...code D...
In the above, if a trap occurs in code block B, an implicit "goto"
(sort of) is done, sending you to the start of the code in the
"recover" block (code block C), with a magic variable "escapecode"
setup with a 32-bit error value (to tell you what happened).
What's a trap. Some or all of:
- Pascal range violation (e.g., index out of range)
- divide by 0
- integer overflow
- illegal pointer
Here's example code that "safely" tries to load a 32-bit integer
from a pointer, without aborting if the pointer is bad in some way
(and there are at least 3 ways it can be bad!):
NOTE: try/recover isn't perfect. See at least *commentary* note #2-7 in:
http://www.allegro.com/papers/htpp.html (there are two "#2-7" strings
on the page)
--------------------------------------cut here-------------------------
{load32.source 97/04/08}
$standard_level 'os_features'$
$type_coercion 'representation'$
$set 'USE2 = false'$ {if TRUE, makes load_from_iptr32}
{ handle 2-byte aligned }
{ addresses as well as }
{ 4-byte aligned ones. }
program m;
type
i32_a2 = $alignment 2$ integer;
$if 'USE2'$
iptr32_type = ^ i32_a2;
$else$
iptr32_type = ^ integer;
$endif$
str32 = string [32];
str256 = string [256];
{---------------------- intrinsics --------------------}
Function dascii : shortint; intrinsic;
Procedure hperrmsg; intrinsic;
Procedure print; intrinsic;
{---------------------forward routines----------------}
Function hex32 (n : integer) : str32;
forward;
Function num32 (n : integer) : str32;
forward;
Procedure ws (s : str256);
forward;
{********************************************************}
procedure load_from_iptr32 (
var status : integer;
ptr : iptr32_type;
var result : integer);
{Returns status = 0 if no error, otherwise}
{status has an error code. }
begin
status := 0; {assume no error}
try
begin
result := ptr^;
{Note: if ptr is not on a 4-byte boundary,}
{we will trap. If ptr has an unknown }
{virtual address, we will trap. If the }
{virtual address is valid, but not }
{readable by our process, we will trap. }
{in all cases, the "trap" takes us to the }
{recover block, with a non-0 value in }
{escapecode. }
end
recover
begin
result := 0; {because the := above was interrupted}
status := escapecode; {oops, we trapped}
end;
end {load_from_iptr32 proc};
{********************************************************}
function hex32 (n : integer) : str32;
var
dummy : integer;
s : str32;
begin
setstrlen (s, 8);
dummy := dascii (n, 16, s);
hex32 := '$' + s;
end {hex32 proc};
{********************************************************}
function num32 (n : integer) : str32;
var
s : str32;
begin
setstrlen (s, dascii (n, 10, s));
num32 := s;
end {num32 proc};
{********************************************************}
procedure test;
var
i : integer;
i16_array : array [0..9] of shortint;
test_data : integer;
{--------------------------}
Procedure sub_test (addr : integer);
const
Trap_Ill_Pointer = 3473608; {HP-UX,MPE/iX}
Trap_Data_Mem_Prot_Trap = 3408072; {HP-UX,MPE/iX}
Trap_Instr_Mem_Prot_Trap = 3408072; {HP-UX,MPE/iX}
{above from: PASESC.PUB.SYS... }
{ }
{Note that sometimes multiple errors share the}
{same error code! }
{ }
{NOTE: a misaligned address trap looks like }
{a memory protection trap. }
var
altstatus: integer;
i : integer;
ptr : iptr32_type;
status : integer;
begin
ws ('---------------');
ptr := iptr32_type (addr);
load_from_iptr32 (status, ptr, i);
if status = 0 then
ws ('Load from ' + hex32 (addr) +
' ok, data = ' +
num32 (i))
else
begin
ws ('Load from ' + hex32 (addr) +
' failed, status = ' +
hex32 (status) + ' (' +
num32 (status) +
'), data = ' + num32 (i));
ws (' '); {blank line}
{try to decode the status into an "english" msg...}
if status = Trap_Ill_Pointer then
ws ('Illegal Pointer')
else if status = Trap_Data_Mem_Prot_Trap then
ws ('Memory protection trap')
else {...maybe in error catalog?}
hperrmsg (2, 1, , status, , , altstatus);
{Note: the above "Trap_..." values are not}
{ in the system error catalog! }
end;
ws (' '); {blank line}
end {sub_test Proc};
{--------------------------}
begin
test_data := 123;
for i := 0 to 9 do
i16_array [i] := i;
{tests that should work...}
sub_test (baddress (test_data));
{tests that should fail...}
sub_test (-8);
sub_test (3);
sub_test (0); {0 == NIL}
{tests that may fail...}
sub_test (hex ('80450000'));
{tests that work only if load_from_iptr32 is }
{compiled with USE2 option on... }
sub_test (baddress (i16_array [0]));
sub_test (baddress (i16_array [1]));
sub_test (baddress (i16_array [2]));
sub_test (baddress (i16_array [3]));
end {test proc};
{********************************************************}
procedure ws (s : str256);
begin
print (s, - strlen (s), 0);
end {ws proc};
{********************************************************}
begin
test;
end.
--------------------------------------cut here----------------------------
--
Stan Sieler [log in to unmask]
http://www.allegro.com/sieler.html
|