|
|
DataMuseum.dkPresents historical artifacts from the history of: Rational R1000/400 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Rational R1000/400 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 32768 (0x8000)
Types: Ada Source
Notes: 03_class, FILE, R1k_Segment, e3_tag, package body Number_Io, seg_04ba6e
└─⟦8527c1e9b⟧ Bits:30000544 8mm tape, Rational 1000, Arrival backup of disks in PAM's R1000
└─⟦5a81ac88f⟧ »Space Info Vol 1«
└─⟦this⟧
with File_Support;
use File_Support;
with Text_Supprt;
use Text_Supprt;
package body Number_Io is
pragma Suppress (Access_Check);
pragma Suppress (Discriminant_Check);
pragma Suppress (Index_Check);
pragma Suppress (Length_Check);
pragma Suppress (Range_Check);
pragma Suppress (Division_Check);
pragma Suppress (Elaboration_Check);
-- for input
type Signed_Cases is (No_Sign, Plus_Only, Sign_Allowed, Already_Negated);
No_Point : constant Boolean := False;
Point_Needed : constant Boolean := True;
Use_E : constant Boolean := True;
Not_Using_E : constant Boolean := False;
Doing_Whole : constant Boolean := False;
Doing_Fraction : constant Boolean := True;
To_String : constant Boolean := True;
To_File : constant Boolean := False;
-- for output
Number : constant String := "001234567899";
Max_Exp : constant Integer := 5;
Exp_Divisor : constant array (Integer range 1 .. Max_Exp) of Integer :=
(1, 10, 100, 1000, 10000);
----------------------------------------------------------
-- The following routines are used for input --
----------------------------------------------------------
function Val_Of (C : in Character) return Integer is
begin
case C is
when 'a' .. 'f' =>
return Character'Pos (C) - Lc_A + 10;
when 'A' .. 'F' =>
return Character'Pos (C) - Uc_A + 10;
when '0' .. '9' =>
return Character'Pos (C) - Cnvt_Digit;
when others =>
return 16;
end case;
end Val_Of;
function F_Val_Of (C : in Character) return Io_Float is
begin
case C is
when 'a' .. 'f' =>
return Io_Float (Character'Pos (C) - Lc_A + 10);
when 'A' .. 'F' =>
return Io_Float (Character'Pos (C) - Uc_A + 10);
when '0' .. '9' =>
return Io_Float (Character'Pos (C) - Cnvt_Digit);
when others =>
return 16.0;
end case;
end F_Val_Of;
function Is_Digit
(C : in Character; Base : in Integer := 16) return Boolean is
I : Integer := Val_Of (C);
begin
case C is
when 'a' .. 'f' =>
return (Character'Pos (C) - Lc_A + 10) < Base;
when 'A' .. 'F' =>
return (Character'Pos (C) - Uc_A + 10) < Base;
when '0' .. '9' =>
return (Character'Pos (C) - Cnvt_Digit) < Base;
when others =>
return False;
end case;
end Is_Digit;
function F_Is_Digit
(C : in Character; Base : in Io_Float := 16.0) return Boolean is
begin
case C is
when 'a' .. 'f' =>
return (Character'Pos (C) - Lc_A + 10) < Integer (Base);
when 'A' .. 'F' =>
return (Character'Pos (C) - Uc_A + 10) < Integer (Base);
when '0' .. '9' =>
return (Character'Pos (C) - Cnvt_Digit) < Integer (Base);
when others =>
return False;
end case;
end F_Is_Digit;
function Next_Real_Char (Text : String; I : Integer) return Character is
begin
if I > Text'Last then
return ' ';
else
return Text (I);
end if;
end Next_Real_Char;
pragma Inline (Next_Real_Char);
procedure Get_Simple_Num (Text : String;
I : in out Integer;
Result : out Integer;
Base : Integer;
Sign_Case : Signed_Cases;
Error : out Boolean) is
Sign : Integer := 1;
Sum : Integer := 0;
begin
Error := False;
case Sign_Case is
when Already_Negated =>
Sign := -1;
when Plus_Only | Sign_Allowed =>
if Text (I) = '+' or Text (I) = '-' then
if Text (I) = '-' then
Sign := -1;
end if;
I := I + 1;
end if;
when No_Sign =>
null;
end case;
if not Is_Digit (Text (I), Base) then
raise Data_Error;
end if;
begin
loop
if I > Text'Last then
exit;
end if;
if Text (I) = '_' then
I := I + 1;
if not Is_Digit (Text (I), Base) then
raise Data_Error;
end if;
elsif not Is_Digit (Text (I), Base) then
exit;
end if;
Sum := Sum * Base + Sign * Val_Of (Text (I));
I := I + 1;
end loop;
exception
when Numeric_Error =>
raise Data_Error;
end;
if Sign_Case = Plus_Only and then Sign < 0 then
raise Data_Error;
end if;
Result := Sum;
exception
when Constraint_Error | Data_Error =>
Error := True;
end Get_Simple_Num;
procedure Get_Simple_F_Num (Text : String;
I : in out Integer;
Result : out Io_Float;
F_Base : Io_Float;
Sign : in out Io_Float;
Doing_Fraction : Boolean;
Error : out Boolean) is
Sum : Io_Float := 0.0;
Base : Integer := Integer (F_Base);
Fraction_Base : Io_Float := 1.0 / F_Base;
Sign_Ok : Boolean := (Sign /= 0.0);
begin
if Sign_Ok and then (Text (I) = '+' or Text (I) = '-') then
if Text (I) = '-' then
Sign := -1.0;
end if;
I := I + 1;
else
Sign := 1.0;
end if;
if not Is_Digit (Text (I), Base) then
raise Data_Error;
end if;
loop
if Text (I) = '_' then
I := I + 1;
if not Is_Digit (Text (I), Base) then
raise Data_Error;
end if;
elsif not Is_Digit (Text (I), Base) then
exit;
end if;
if Doing_Fraction then
Sum := Sum + F_Val_Of (Text (I)) * Fraction_Base;
Fraction_Base := Fraction_Base / F_Base;
else
Sum := Sum * F_Base + F_Val_Of (Text (I));
end if;
I := I + 1;
if I > Text'Last then
exit;
end if;
end loop;
Result := Sum;
Error := False;
exception
when Data_Error | Constraint_Error =>
Error := True;
end Get_Simple_F_Num;
procedure Complete_Based_Lit (Text : String;
I : in out Integer;
Point_Needed : Boolean;
Separator : Character) is
-----------------------------------------------------------------------
--| This procedure is used to set file_for_more.in_ptr to the
--| last character read, in the cases where data_error is known to
--| be pending due to a digit outside the base. Ada requires that the
--| input be parsed as a literal BEFORE being analyzed for base, etc.
--|
-----------------------------------------------------------------------
Point_Expected : Boolean := Point_Needed; C : Character := '0'; -- not underline;
Was_Underline : Boolean;
Exp : Integer;
Error : Boolean;
begin
begin -- for exception region on data_error
Based_Loop:
loop
Was_Underline := (C = '_');
I := I + 1;
C := Text (I);
case C is
when 'a' .. 'z' | 'A' .. 'Z' | '0' .. '9' =>
null;
when '_' =>
if Was_Underline then
return;
end if;
when '#' | ':' =>
if Point_Expected or C /= Separator then
return;
end if;
exit Based_Loop;
when '.' =>
if not Point_Expected then
return;
end if;
Point_Expected := False;
when others =>
return;
end case;
end loop Based_Loop;
end;
I := I + 1;
C := Text (I);
if C = 'e' or else C = 'E' then
I := I + 1;
Get_Simple_Num (Text, I, Exp, 10, Plus_Only, Error);
end if;
end Complete_Based_Lit;
procedure Getnum (Text : String;
Item : out Integer;
Last : out Integer;
Error : in out Boolean) is
C : Character;
I : Integer := Text'First;
Finish : Integer := Text'Last;
Result : Integer := 0;
Base : Integer := 10;
Exp : Integer := 0;
After_Base : Integer;
Sign_Case : Signed_Cases;
Sep : Character;
begin Error := False;
--
-- skip blanks
--
while Text (I) = ' ' or else Text (I) = Ascii.Ht loop
I := I + 1;
end loop;
--
-- DR0568 let get_simple_num take care of the sign (so that
-- a get of integer'first does not cause an overflow).
--
-- get number (base 10)
--
Get_Simple_Num (Text => Text,
I => I,
Result => Result,
Base => 10,
Sign_Case => Sign_Allowed,
Error => Error);
if Error then
Last := I - 1;
return;
end if;
--
-- is there a '#' or ':'
--
if I <= Text'Last and then (Text (I) = '#' or Text (I) = ':') then
-- yes, number is the base
if Result < 0 then
Sign_Case := Already_Negated;
Result := -Result;
else
Sign_Case := No_Sign;
end if;
Sep := Text (I);
Base := Result;
Result := 0;
I := I + 1;
--
-- get number
--
After_Base := I;
Get_Simple_Num (Text, I, Result, Base, Sign_Case, Error);
if Error then
I := After_Base;
Complete_Based_Lit (Text, I, No_Point, Sep);
Last := I - 1;
return;
end if;
--
-- get '#' or ':'
--
if Text (I) /= Sep then
I := I - 1;
Complete_Based_Lit (Text, I, No_Point, Sep);
Error := True;
Last := I - 1;
return;
end if;
I := I + 1;
end if;
--
-- get 'e' or 'E'
--
if I > Text'Last or else (Text (I) /= 'e' and Text (I) /= 'E') then
Exp := 0;
else
I := I + 1;
--
-- get option exponent (base 10)
--
Get_Simple_Num (Text, I, Exp, 10, Plus_Only, Error);
end if;
Last := I - 1;
if Exp < 0 or else Base < 2 or else Base > 16 then
Error := True;
else
if not Error then
Item := Result * (Base ** Exp);
end if;
end if;
end Getnum;
-- Upon entry/exit: file is locked
procedure Getnum (File : in File_Type; Item : out Integer) is
Fp : File_Ptr := To_Fptr (File);
Error : Boolean := False;
begin
--
-- skip blanks and lines
--
Skip_Blanks_And_Lines (Fp);
Refill_Buffer (Fp);
--
-- get number from buffer
--
Getnum (String (Fp.Buffer.Elem (Fp.In_Ptr .. Fp.Last)),
Item, Fp.In_Ptr, Error);
if Error then
raise Data_Error;
end if;
end Getnum;
procedure Getnum (Text : String;
Item : out Io_Float;
Last : out Integer;
Error : in out Boolean) is
Result : Io_Float := 0.0;
Scale : Io_Float := 1.0;
Base : Io_Float := 10.0;
Fraction : Io_Float;
I : Integer := Text'First;
Finish : Integer := Text'Last;
C : Character;
Sign : Integer := 1;
Exp : Integer := 0;
Based : Boolean := False;
Sep : Character := '#';
F_Sign : Io_Float := 1.0;
No_F_Sign : Io_Float := 0.0;
No_Frac_Sign : Io_Float := 0.0;
Bad_Base : Boolean := False;
pragma Optimize_Code (Off);
begin
Error := False;
--
-- skip blanks
--
while Text (I) = ' ' or else Text (I) = Ascii.Ht loop
I := I + 1;
if I > Text'Last then
Error := True;
Last := I - 1;
return;
end if;
end loop;
--
-- get number (base 10)
--
Get_Simple_F_Num (Text, I, Result, 10.0, F_Sign, Doing_Whole, Error);
if Error then
Last := I - 1;
return;
end if;
--
-- is there a '#' or ':'
--
if I <= Text'Last and then (Text (I) = '#' or Text (I) = ':') then
-- yes, number is the base
Sep := Text (I);
Based := True;
Base := Result;
Bad_Base := Integer (Base) < 2 or Integer (Base) > 16;
if Bad_Base then
Base := 16.0;
end if;
Result := 0.0;
I := I + 1;
Get_Simple_F_Num (Text, I, Result, Base,
No_F_Sign, Doing_Whole, Error);
if Error then
Complete_Based_Lit (Text, I, Point_Needed, Sep);
Last := I - 1;
return;
end if;
end if;
if I > Finish or else Text (I) /= '.' then
Error := True;
Last := I - 1;
return;
end if;
I := I + 1;
--
-- get fractional part
--
Get_Simple_F_Num (Text, I, Fraction, Base,
No_Frac_Sign, Doing_Fraction, Error);
if Error then
if Based then
Complete_Based_Lit (Text, I, No_Point, Sep);
end if;
Last := I - 1;
return;
end if;
--
-- At this point, result contains the left-hand-side of
-- the point and fraction contains the right-hand-side.
-- Now get the exponent.
--
if Based then
if Text (I) /= Sep then
I := I - 1;
Complete_Based_Lit (Text, I, Point_Needed, Sep);
Error := True;
Last := I - 1;
return;
end if;
I := I + 1;
end if;
if I > Text'Last or else (Text (I) /= 'e' and Text (I) /= 'E') then
Exp := 0;
else
I := I + 1;
--
-- get exponent
--
Get_Simple_Num (Text, I, Exp, 10, Sign_Allowed, Error);
if Error then
Last := I - 1;
return;
end if;
end if;
if Bad_Base then
Error := True;
Last := I - 1;
return;
end if;
--
-- Build final result from partial result and fraction.
-- Adjust by exponent. Note, to preserve accuracy, we
-- avoid negative exponentiation.
--
begin
if Exp >= 0 then
Result := Result * (Base ** Exp);
Fraction := Fraction * (Base ** Exp);
else
Result := Result / (Base ** (-Exp));
Fraction := Fraction / (Base ** (-Exp));
end if;
exception
when Numeric_Error | Constraint_Error =>
Error := True;
Last := I - 1;
return;
end;
-- combine both sides of point
Result := Result + Fraction;
-- handle negatives
if F_Sign /= 1.0 then
Result := -Result;
end if;
Item := Result;
Last := I - 1;
end Getnum;
-- Upon entry/exit: file is locked
procedure Getnum (File : in File_Type; Item : out Io_Float) is
Fp : File_Ptr := To_Fptr (File);
Error : Boolean := False;
begin
--
-- skip blanks and lines
--
Skip_Blanks_And_Lines (Fp);
Refill_Buffer (Fp);
--
-- get number from buffer
--
Getnum (String (Fp.Buffer.Elem (Fp.In_Ptr .. Fp.Last)),
Item, Fp.In_Ptr, Error);
if Error then
raise Data_Error;
end if;
end Getnum;
-- Upon entry/exit: file is locked
procedure Get_Float (File : in File_Type;
Result : out Io_Float;
Width : in Field) is
End_Ptr : Integer;
Fp : File_Ptr := To_Fptr (File);
Error : Boolean := False;
begin
Must_Be_Input (File);
if Width /= 0 then
if Tstfile (Fp) /= At_Char then
raise Data_Error;
end if;
End_Ptr := Fp.In_Ptr + Width;
if End_Ptr > Fp.Last then
-- We need to get width characters into the buffer,
-- but since they may not all fit we'll stick the next
-- width characters into an array, and getnum on that.
declare
Str : String (1 .. Width);
Len : Integer := 0;
I : Integer;
begin
while Len < Width loop
Len := Len + 1;
Str (Len) := Getchar (Fp);
exit when Tstfile (Fp) /= At_Char;
end loop;
I := 1;
Getnum (Str (1 .. Len), Result, I, Error);
if I /= Len or Error then
raise Data_Error;
end if;
end;
else
Getnum (String (Fp.Buffer.Elem (Fp.In_Ptr + 1 .. End_Ptr)),
Result, Fp.In_Ptr, Error);
if End_Ptr /= Fp.In_Ptr and then Tstfile (Fp) = At_Char then
raise Data_Error;
elsif Error then
raise Data_Error;
end if;
end if;
else
Getnum (File, Result);
end if;
end Get_Float;
-------------------------------------------------------------------
-- the following routines are used for output --
-------------------------------------------------------------------
function Truncate (F : Io_Float; Almost_One : Io_Float) return Integer is
I_Trunc : Integer;
F_Trunc : Io_Float;
begin
I_Trunc := Integer (F - 0.5);
F_Trunc := Io_Float (I_Trunc);
if F - F_Trunc >= Almost_One then
-- the rounding mode rounded down instead of up
--\x09or cumulative round_off occurred
I_Trunc := I_Trunc + 1;
end if;
if I_Trunc < 0 then
I_Trunc := 0;
end if;
return I_Trunc;
end Truncate;
procedure Decompose_Real (Num : Io_Float;
Fore : Integer;
Aft : Integer;
Using_E : Boolean;
Is_Neg : out Boolean;
Exponent : out Integer;
Digit_Str : out String) is
R : Io_Float := Num;
Number : constant String := "0123456789";
Million : constant Io_Float := Io_Float (1_000_000);
Rounder : Io_Float;
Shift_Count : Integer := 0;
Too_Small : Io_Float;
Almost_One : Io_Float;
Exp, M, I : Integer;
begin
if R < 0.0 then
Is_Neg := True;
R := -R;
else
Is_Neg := False;
end if;
if R = 0.0 then
Digit_Str (1 .. Aft + Fore) := (others => '0');
Exponent := 0;
return;
end if;
Too_Small := (0.1 ** Aft);
Rounder := 0.5 * Too_Small;
Almost_One := 1.0 - (Rounder * 0.1);
if not Using_E then
R := R + Rounder;
end if;
-- make integer part of r within integer range
Exp := 0;
while R > Million loop
R := R / Million;
Almost_One := (Almost_One * 0.000001) + 0.999999;
Exp := Exp + 6;
Shift_Count := Shift_Count + 6;
end loop;
I := Truncate (R, Almost_One);
if I = 0 then
loop
R := R * 10.0;
Exp := Exp - 1;
I := Truncate (R, Almost_One);
exit when I > 0;
end loop;
else
while I >= 10 loop
R := R * 0.1;
Almost_One := (Almost_One * 0.1) + 0.9;
Shift_Count := Shift_Count + 1;
Exp := Exp + 1;
I := I / 10;
end loop;
end if;
if not Using_E and then Exp + 1 > Fore then
M := Aft + Exp + 1;
else
M := Aft + Fore;
end if;
if Using_E then
R := R + Rounder;
end if;
I := Truncate (R, Almost_One);
if I = 10 then
I := 1;
R := R * 0.1;
Exp := Exp + 1;
M := M + 1;
elsif I = 0 then
I := 1;
end if;
Digit_Str (1) := Character'Val (I + Character'Pos ('0'));
for K in 2 .. M loop
R := (R - Io_Float (I)) * 10.0;
if Shift_Count > 0 then
Almost_One := (Almost_One * 10.0) - 9.0;
Shift_Count := Shift_Count - 1;
end if;
if R < Float'Safe_Small then
R := 0.0;
end if;
I := Truncate (R, Almost_One);
Digit_Str (K) := Number (I + 1);
end loop;
Exponent := Exp;
end Decompose_Real;
procedure Cvt_Num (Str : out String;
Len : in out Integer;
Num : Io_Float;
My_Fore, After : Integer) is
Max_Len : constant Integer := 250;
Cvtbuf : String (1 .. Max_Len + 6);
Fore : Integer := My_Fore;
Original_Len : Integer;
Aft : Integer := After;
P, S : Integer := Str'First;
Exponent, Fore_Used : Integer;
Is_Neg : Boolean;
begin
while Fore > Max_Len - Aft - 3 loop
Str (P) := ' ';
P := P + 1;
Fore := Fore - 1;
if Fore <= 1 then
raise Layout_Error;
end if;
end loop;
Decompose_Real (Num, Fore, Aft, Not_Using_E, Is_Neg, Exponent, Cvtbuf);
if Exponent > 0 then
Fore_Used := Exponent + 1;
else
Fore_Used := 1;
end if;
S := P + Fore - Fore_Used - 1;
if S < Str'First then
S := Str'First - 1;
end if;
for J in P .. S loop
Str (J) := ' ';
end loop;
if Is_Neg then
if S < Str'First then
S := S + 1;
end if;
Str (S) := '-';
end if;
S := S + 1;
P := S + Fore_Used;
if Exponent >= 0 then
if P > Str'Last then
raise Layout_Error;
end if;
Str (S .. P - 1) := Cvtbuf (1 .. Fore_Used);
Str (P) := '.';
else
-- Zero-fill to first digit. Decimal point is at s+1.
-- First digit will go at s+1+(-exponent)
P := S + (-Exponent);
if P > Str'Last then
raise Layout_Error;
end if;
Str (S .. S + 1) := "0.";
Str (S + 2 .. P) := (others => '0');
Aft := Aft - (P - (S + 1)); -- decrement aft by number of 0's
Fore_Used := 0;
end if;
S := P + Aft;
P := P + 1;
if S - Str'First + 1 > Len then
raise Layout_Error;
end if;
if S > Str'Last then
raise Layout_Error;
end if;
Str (P .. S) := Cvtbuf (Fore_Used + 1 .. Fore_Used + Aft);
Len := S - Str'First + 1;
exception
when Constraint_Error =>
raise Layout_Error;
end Cvt_Num;
procedure Cvt_Num_Using_E (Str : out String;
Len : in out Integer;
Num : Io_Float;
My_Fore, My_Aft, My_Exp : Integer;
String_Target : Boolean) is
Max_Len : constant Integer := 250;
Cvtbuf : String (1 .. Max_Len + 6);
I, S, M : Integer;
Fore : Integer := My_Fore;
Aft : Integer := My_Aft;
Exp : Integer := My_Exp;
P : Integer := Str'First;
Exponent : Integer;
Leading_0s : Integer := 0;
Size_Of_E_Field : Integer;
Is_Neg : Boolean;
begin
Decompose_Real (Num, 1, Aft, Use_E, Is_Neg, Exponent, Cvtbuf);
--
-- DR 1143 - if negative minimum value for fore is 2
--
if Is_Neg and then Fore = 1 then
Fore := 2;
end if;
-- figure space needed for exponent
Exp := Exp - 1; -- sign
while Exp > Max_Exp loop
Leading_0s := Leading_0s + 1;
Exp := Exp - 1;
end loop;
loop
M := Exp_Divisor (Exp);
exit when abs (Exponent / 10) < M;
Exp := Exp + 1; -- exponent too large for field size
if String_Target then
Fore := Fore - 1;
end if;
end loop;
-- put out leading spaces
Size_Of_E_Field := Exp + Leading_0s + 2; -- one for E and one for sign
while Fore > Max_Len - 1 - Aft - Size_Of_E_Field loop
Str (P) := ' ';
P := P + 1;
Fore := Fore - 1;
end loop;
S := P + Fore - 2;
for J in P .. S loop
Str (J) := ' ';
end loop;
if Is_Neg then
if S < Str'First then
raise Layout_Error;
end if;
Str (S) := '-'; -- was written as ' ' above
end if;
S := S + 1;
if S < Str'First then
raise Layout_Error;
end if;
Str (S) := Cvtbuf (1);
Str (S + 1) := '.';
P := S + 2;
Str (P .. P + Aft - 1) := Cvtbuf (2 .. Aft + 1);
P := P + Aft + 2;
Str (P - 2) := 'E';
if Exponent < 0 then
Str (P - 1) := '-';
Exponent := -Exponent;
else
Str (P - 1) := '+';
end if;
while Leading_0s > 0 loop
Str (P) := '0';
P := P + 1;
Leading_0s := Leading_0s - 1;
end loop;
while M > 0 loop -- m was set above
I := Exponent / M;
Str (P) := Number (I + 2);
P := P + 1;
Exponent := Exponent - I * M;
M := M / 10;
end loop;
P := P - Str'First;
if P > Len then
raise Layout_Error;
end if;
Len := P;
exception
when Constraint_Error =>
raise Layout_Error;
end Cvt_Num_Using_E;
procedure Put_Float (To : out String;
Item : in Io_Float;
Fore : Integer;
Aft : in Field;
Exp : in Field;
Len : in out Integer) is
My_Fore : Integer := Fore;
My_Exp : Integer := Exp;
My_Aft : Integer := Aft;
begin
if My_Exp = 1 then
My_Exp := 2; -- minimum sign plus one digit
end if;
if My_Fore = -1 then
-- put to string, so there was no fore given.
My_Fore := Len - Aft - 1;
if Aft = 0 then
My_Fore := My_Fore - 1; -- aft is always >= 1
end if;
if My_Exp /= 0 then
My_Fore := My_Fore - My_Exp - 1;
end if;
end if;
if My_Fore < 1 then
My_Fore := 1;
end if;
if My_Aft < 1 then
My_Aft := 1;
end if;
if My_Exp = 0 then
Cvt_Num (To, Len, Item, My_Fore, My_Aft);
else
Cvt_Num_Using_E (To, Len, Item, My_Fore, My_Aft, My_Exp, Fore = -1);
end if;
end Put_Float;
end Number_Io;
nblk1=1f
nid=0
hdr6=3e
[0x00] rec0=1e rec1=00 rec2=01 rec3=066
[0x01] rec0=1c rec1=00 rec2=02 rec3=080
[0x02] rec0=1d rec1=00 rec2=03 rec3=086
[0x03] rec0=1e rec1=00 rec2=04 rec3=01e
[0x04] rec0=1f rec1=00 rec2=05 rec3=00a
[0x05] rec0=1c rec1=00 rec2=06 rec3=020
[0x06] rec0=1e rec1=00 rec2=07 rec3=03c
[0x07] rec0=17 rec1=00 rec2=08 rec3=002
[0x08] rec0=18 rec1=00 rec2=09 rec3=06c
[0x09] rec0=1f rec1=00 rec2=0a rec3=002
[0x0a] rec0=1e rec1=00 rec2=0b rec3=024
[0x0b] rec0=24 rec1=00 rec2=0c rec3=020
[0x0c] rec0=21 rec1=00 rec2=0d rec3=072
[0x0d] rec0=20 rec1=00 rec2=0e rec3=04a
[0x0e] rec0=20 rec1=00 rec2=0f rec3=032
[0x0f] rec0=20 rec1=00 rec2=10 rec3=00e
[0x10] rec0=20 rec1=00 rec2=11 rec3=014
[0x11] rec0=20 rec1=00 rec2=12 rec3=014
[0x12] rec0=1d rec1=00 rec2=13 rec3=072
[0x13] rec0=17 rec1=00 rec2=14 rec3=014
[0x14] rec0=20 rec1=00 rec2=15 rec3=012
[0x15] rec0=1d rec1=00 rec2=16 rec3=044
[0x16] rec0=20 rec1=00 rec2=17 rec3=010
[0x17] rec0=21 rec1=00 rec2=18 rec3=01a
[0x18] rec0=1f rec1=00 rec2=19 rec3=00e
[0x19] rec0=1e rec1=00 rec2=1a rec3=036
[0x1a] rec0=1c rec1=00 rec2=1b rec3=010
[0x1b] rec0=1f rec1=00 rec2=1c rec3=034
[0x1c] rec0=21 rec1=00 rec2=1d rec3=006
[0x1d] rec0=1f rec1=00 rec2=1e rec3=00a
[0x1e] rec0=1c rec1=00 rec2=1f rec3=000
tail 0x21548d5ba86843b9dd90c 0x42a00088462060003