There are still some problems with packed arrays of subrange types.
(1) Initializers don't work properly.
[pas]% cat packed1.pas
program P (Output);
type
T = packed array [0 .. 2] of 0 .. 1000;
var
A: T value (1, 2, 0);
begin
if (A[0] = 1) and (A[1] = 2) and (A[2] = 0) then WriteLn ('OK')
else WriteLn ('Failed: ', A[0] : 4, A[1] : 4, A[2] : 4)
end.
[pas]% uname -a ; gpc -v
Linux localhost.localdomain 2.4.2-2 #1 Sun Apr 8 19:37:14 EDT 2001 i586 unknown
Reading specs from /usr/local/lib/gcc-lib/i586-pc-linux-gnu/2.95.2/specs
gpc version 20011222, based on 2.95.2 19991024 (release)
[pas]% gpc packed1.pas
packed1.pas:9: warning: too few initializers for array
[pas]% ./a.out
Failed: 1 0 0
[pas]%
(2) In certain situations, assignment statements work incorrectly when
the same subscribed packed array variable is accessed on both sides of the
assignment.
[pas]% cat packed2.pas
program P (Output);
var
A: packed array [0 .. 2] of 0 .. 1000;
function F (N: Integer): Integer;
begin
if N = 0 then F := 0
else begin
A[N] := F (A[N]);
F := A[N] + 1
end
end;
begin
A[0] := 1;
A[1] := 2;
A[2] := 0;
A[0] := F (A[0]);
if A[0] = 2 then WriteLn ('OK') else WriteLn ('Failed: ', A[0])
end.
[pas]% gpc packed2.pas
[pas]% ./a.out
Failed: 1
[pas]%
The problem is in the statement "A[N] := F (A[N]);" in the body of F.
During its execution, A[N] is _cleared_ before the function call,
in particular the argument passed to F is always 0. The debugger session below
illustrates this behavior.
(gdb 5.0 doesn't understand packed arrays; I used a type-cast to Integer
as a workaround. Integer(A)=A[0]+1024*A[1]+1048576*A[2], i.e.
2049=(1,2,0) and 1=(1,0,0).)
[pas]% gpc -g packed2.pas
[pas]% gdb a.out
GNU gdb 5.0rh-5 Red Hat Linux 7.1
Copyright 2001 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux"...
(gdb) break F
Breakpoint 1 at 0x8049c2c: file packed2.pas, line 8.
(gdb) run
Starting program: /home/emil/pascal/pas/a.out
Breakpoint 1, F (N=1) at packed2.pas:8
8 if N = 0 then F := 0
Current language: auto; currently pascal
(gdb) watch Integer(A)
Hardware watchpoint 2: (Integer) A
(gdb) step
10 A[N] := F (A[N]);
(gdb) step
Hardware watchpoint 2: (Integer) A
Old value = 2049
New value = 1
$08049cb4 in F (N=1) at packed2.pas:10
10 A[N] := F (A[N]);
(gdb) bt
#0 $08049cb4 in F (N=1) at packed2.pas:10
#1 $0804a1a9 in pascal_main_program () at packed2.pas:19
#2 $0804a2bb in main (argc=1, argv=$bffffacc, envp=$bffffad4)
at <implicit code>:21
#3 $40064e5e in __libc_start_main (main=$804a294 <main>, argc=1,
ubp_av=$bffffacc, init=$80494c8 <_init>, fini=$8066b50 <_fini>,
rtld_fini=$4000d3c4 <_dl_fini>, stack_end=$bffffabc)
at ../sysdeps/generic/libc-start.c:129
(gdb) step
Breakpoint 1, F (N=0) at packed2.pas:8
8 if N = 0 then F := 0
(gdb)
Emil Jerabek