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