[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Inconsistent HIGH values with 'ARRAY OF CHAR'
From: |
Gaius Mulley |
Subject: |
Re: Inconsistent HIGH values with 'ARRAY OF CHAR' |
Date: |
Wed, 10 May 2023 14:27:24 +0100 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/27.1 (gnu/linux) |
Rudolf Schubert <rudolf@muc.de> writes:
> Hi Gaius,
>
> I'm still hunting miscellaneous bugs which occurred with my 'big squash file'.
>
> One thing I noted today is:
>
> the HIGH values seen inside a PROCEDURE do not reflect the expectations.
>
> Again, I've written a small example program which shows the problem:
>
>
> MODULE port_test8_gm2;
>
> FROM IOChan IMPORT
> ChanId;
> FROM StdChans IMPORT
> StdOutChan;
> FROM Strings IMPORT
> Length;
> FROM TextIO IMPORT
> WriteLn, WriteString;
> FROM WholeIO IMPORT
> WriteCard;
>
>
> VAR
> str_a: ARRAY[0..0] OF CHAR;
> str_b: ARRAY[0..1] OF CHAR;
> str_c: ARRAY[0..2] OF CHAR;
>
>
> PROCEDURE ShowStringInfos(the_str: ARRAY OF CHAR);
> VAR
> cid_out: ChanId;
>
> BEGIN (* PROCEDURE ShowStringInfos *)
> cid_out:=StdOutChan();
>
> WriteString(cid_out, 'Length(the_str): ');
> WriteCard(cid_out, Length(the_str), 1);
> WriteLn(cid_out);
>
> WriteString(cid_out, 'HIGH(the_str): ');
> WriteCard(cid_out, HIGH(the_str), 1);
> WriteLn(cid_out);
>
> WriteString(cid_out, 'the_str: ');
> WriteString(cid_out, the_str);
> WriteLn(cid_out);
>
> WriteLn(cid_out);
> END ShowStringInfos;
>
>
> BEGIN (* MODULE port_test8_gm2 *)
> ShowStringInfos('1');
> ShowStringInfos('12');
> ShowStringInfos('123');
>
> str_a:='a';
> ShowStringInfos(str_a);
> str_b:='ab';
> ShowStringInfos(str_b);
> str_c:='abc';
> ShowStringInfos(str_c);
>
> str_c:='d';
> ShowStringInfos(str_c);
> END port_test8_gm2.
>
>
> ShowStringInfos just prints out the Length, the HIGH value and the
> string proper which is passed to the PROCEDURE. When using literals
> '1', '12' and '123' the HIGH values are 0, 2 and 3. So I guess either
> for '1' the HIGH value should be 1 and not 0 or for '12' and '123'
> the HIGH values should be 1 and 2 and not 2 and 3. I can only compare
> with GPM and there they report a HIGH value of 1 for '1' (and 2 and 3
> for '12' and '123'). So the question is what will be the correct behaviour?
>
>
> BR
>
> Rudolf
Hi Rudolf,
[As an aside I've checked various reference texts and I'm still to find
the correct behaviour :-).
As far as can tell PIM[234] and ISO is silent on the matter.]
Interesting, given the last accessible char in a string is defined as
HIGH (a) = i or a[i] = 0C
so I think the behaviour in the test code above is logically correct,
but it is certainly looks inconsistant :-).
However it appears that gm2 does not append a 0C to a string when it
passes a single char literal as an actual parameter to an open array. I
suspect it makes sense to change the actual parameter '1' to deliver a
HIGH value of 1 (and add a 0C terminator). This would seem more
consistant as the single char literal is now viewed as a string. (I
remind myself that a single char variable cannot be passed to an open
array).
For example here is some test code:
MODULE hightests ;
FROM libc IMPORT printf, exit ;
FROM StrLib IMPORT StrCopy ;
PROCEDURE testhigh (a: ARRAY OF CHAR; expected: CARDINAL; first: CHAR;
checkNul: BOOLEAN) ;
VAR
copy: ARRAY [0..10] OF CHAR ;
BEGIN
StrCopy (a, copy) ;
IF HIGH (a) # expected
THEN
printf ("unexpected high value, HIGH(%s) should be %d but was passed
%d\n",
copy, expected, HIGH (a)) ;
code := 1
END ;
IF a[0] # first
THEN
printf ("unexpected first value in open array, %s, a[0] should be %c but
was passed %c\n",
a, first, a[0]) ;
code := 2
END ;
IF checkNul AND (a[HIGH(a)] # 0C)
THEN
printf ("expected the array to contain a 0C terminator\n") ;
code := 3
END
END testhigh ;
VAR
str0: ARRAY [0..0] OF CHAR ;
str1: ARRAY [0..1] OF CHAR ;
str2: ARRAY [0..2] OF CHAR ;
str3: ARRAY [0..3] OF CHAR ;
ch : CHAR ;
code: INTEGER ;
BEGIN
str0 := '_' ;
str1 := '_1' ;
str2 := '_2' ;
str3 := '_3' ;
code := 0 ;
testhigh ('', 0, 0C, TRUE) ;
testhigh ('1', 1, '1', FALSE) ;
testhigh ('12', 2, '1', TRUE) ;
testhigh ('123', 3, '1', TRUE) ;
testhigh ('1234', 4, '1', TRUE) ;
testhigh (str0, 0, '_', FALSE) ;
testhigh (str1, 1, '_', FALSE) ;
testhigh (str2, 2, '_', TRUE) ;
testhigh (str3, 3, '_', TRUE) ;
IF code = 0
THEN
printf ("all tests pass\n")
ELSE
exit (1)
END
END hightests.
regards,
Gaius