﻿id	summary	reporter	owner	description	type	status	priority	milestone	component	version	resolution	keywords	cc
338	The PL1 charno built-in function incorrectly evaluates a multi-element argument	Gary Dixon	Eric Swenson	"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
}}}

"	defect	new	major		General	MR12.8		PL1	
