Opened 2 years ago
#338 new defect
The PL1 charno built-in function incorrectly evaluates a multi-element argument
| Reported by: | Gary Dixon | Owned by: | Eric Swenson |
|---|---|---|---|
| Priority: | major | Milestone: | |
| Component: | General | Version: | MR12.8 |
| Keywords: | PL1 | Cc: |
Description
The following test program demonstrates several problems in handling of any multi-element or complicated argument given to the PL1 charno built-in function. charno is documented in the pl1.new_features.info segment as follows:
The charno, bitno, wordno, and segno functions:
These builtins extract information from pointers, and are defined as follows:
C = charno (P);
P must be a scalar pointer value. The result, C, is a real fixed binary of
precision (21, 0), containing the zero origined character address of P [relative to baseptr(P) ].
However, the following test program demonstrates a significant failure in the compiler's handling of the argument to the charno built-in function. Arguments such as:
charno( stmt.P )
charno( stmt.last_tokenP -> token.P )
are mishandled by the compiler in some unknown fashion.
test_charno.pl1 08/15/24 2355.8 pdt Thu
test_charno:
proc();
dcl my_statement char(42) init( "positional pos(1) ctl(-name -nm) required;" )
int static options(constant);
dcl semi_colon char(1) defined(my_statement) pos(42);
dcl 1 auto_stmt aligned like stmt;
dcl 1 (token1, token2) aligned like token;
dcl (P1, P2) ptr,
(n1, n2) fixed bin(21);
dcl ioa_ entry() options(variable);
dcl 1 stmt aligned based (stmtP),
2 P ptr unal,
2 L fixed bin(18),
2 first_tokenP ptr unal,
2 last_tokenP ptr unal,
stmtStr char(stmt.L) based (stmt.P),
stmtP ptr;
dcl 1 token aligned based (tokenP),
2 P ptr unal,
2 L fixed bin(21),
tokenP ptr,
tokenStr char(token.L) based(token.P);
tokenP = addr(token1);
unspec(token) = "0"b;
token.P = addr(my_statement);
token.L = 1;
stmtP = addr(auto_stmt);
unspec(stmt) = "0"b;
stmt.P = addr(my_statement);
stmt.L = 1;
stmt.first_tokenP = tokenP;
tokenP = addr(token2);
unspec(token) = "0"b;
token.P = addr(semi_colon);
token.L = length(semi_colon);
stmt.last_tokenP = tokenP;
stmt.L = charno( stmt.last_tokenP -> token.P )
+ stmt.last_tokenP -> token.L
- charno( stmt.P );
call ioa_( "First, tried to set stmt.L using the statement:
stmt.L = charno( stmt.last_tokenP -> token.P )
+ stmt.last_tokenP -> token.L
- charno( stmt.P );" );
call ioa_( "^/Expect stmt.L to equal: 42 (000000000052)" );
call ioa_( "^19t Got: ^11d (^w)", stmt.L, stmt.L );
/* ---------- */
call ioa_( "^2/Second, tried to break down clauses in the expression." );
call ioa_( " A: n1 = charno( stmt.last_tokenP -> token.P );" );
n1 = charno( stmt.last_tokenP -> token.P );
call ioa_( "^19t Got: ^11d (^w)", n1, n1 );
call ioa_( " B: n2 = charno( stmt.P );" );
n2 = charno( stmt.P );
call ioa_( "^19t Got: ^11d (^w)", n2, n2 );
call ioa_( " stmt.L = n1 + stmt.last_tokenP -> token.L - n2;" );
stmt.L = n1 + stmt.last_tokenP -> token.L - n2;
call ioa_( "^19t Got: ^11d (^w)", stmt.L, stmt.L );
/* ---------- */
call ioa_( "^2/Third, tried to remove pointer indirection from the ""A"" charno argument." );
call ioa_( " A: P1 = stmt.last_tokenP -> token.P;
n1 = charno( P1 );" );
P1 = stmt.last_tokenP -> token.P;
n1 = charno( P1 );
call ioa_( "^19t Got: ^11d (^w)", n1, n1 );
call ioa_( " B: n2 = charno( stmt.P );" );
n2 = charno( stmt.P );
call ioa_( "^19t Got: ^11d (^w)", n2, n2 );
call ioa_( " stmt.L = n1 + stmt.last_tokenP -> token.L - n2;" );
stmt.L = n1 + stmt.last_tokenP -> token.L - n2;
call ioa_( "^19t Got: ^11d (^w)", stmt.L, stmt.L );
/* ---------- */
call ioa_( "^2/Fourth, tried to remove structure element from ""B"" charno argument." );
call ioa_( " A: P1 = stmt.last_tokenP -> token.P;
n1 = charno( P1 );" );
P1 = stmt.last_tokenP -> token.P;
n1 = charno( P1 );
call ioa_( "^19t Got: ^11d (^w)", n1, n1 );
call ioa_( " B: P2 = stmt.P;
n2 = charno( P2 );" );
P2 = stmt.P;
n2 = charno( P2 );
call ioa_( "^19t Got: ^11d (^w)", n2, n2 );
call ioa_( " stmt.L = n1 + stmt.last_tokenP -> token.L - n2;" );
stmt.L = n1 + stmt.last_tokenP -> token.L - n2;
call ioa_( "^19t Got: ^11d (^w)", stmt.L, stmt.L );
call ioa_( "^2/Display of the entire stmtStr now works OK.
stmtStr: ""^a"";", stmtStr );
call ioa_( "^2/Thus, the charno built-in function appears to have argument processing problems." );
end test_charno;
Results of running this program demonstrate that expected values were obtained only when a single scalar pointer was passed as the argument to charno. Attempting to pass a scaler pointer element of a containing structure did not work.
test_charno
First, tried to set stmt.L using the statement:
stmt.L = charno( stmt.last_tokenP -> token.P )
+ stmt.last_tokenP -> token.L
- charno( stmt.P );
Expect stmt.L to equal: 42 (000000000052)
Got: 9663676427 (110000000013)
Second, tried to break down clauses in the expression.
A: n1 = charno( stmt.last_tokenP -> token.P );
Got: 9741008906 (110447000012)
B: n2 = charno( stmt.P );
Got: 77332480 (000447000000)
stmt.L = n1 + stmt.last_tokenP -> token.L - n2;
Got: 9663676427 (110000000013)
Third, tried to remove pointer indirection from the "A" charno argument.
A: P1 = stmt.last_tokenP -> token.P;
n1 = charno( P1 );
Got: 41 (000000000051)
B: n2 = charno( stmt.P );
Got: 77332480 (000447000000)
stmt.L = n1 + stmt.last_tokenP -> token.L - n2;
Got: -77332438 (777331000052)
Fourth, tried to remove structure element from "B" charno argument.
A: P1 = stmt.last_tokenP -> token.P;
n1 = charno( P1 );
Got: 41 (000000000051)
B: P2 = stmt.P;
n2 = charno( P2 );
Got: 0 (000000000000)
stmt.L = n1 + stmt.last_tokenP -> token.L - n2;
Got: 42 (000000000052)
Display of the entire stmtStr now works OK.
stmtStr: "positional pos(1) ctl(-name -nm) required;";
Thus, the charno built-in function appears to have argument processing problems.
r 00:10 0.270 0
