INTERNAL and EXTERNAL attributes

The INTERNAL and EXTERNAL attributes define the scope of a name.

Read syntax diagramSkip visual syntax diagram
>>-+-INTERNAL-----------------------------+--------------------><
   '-EXTERNAL--+------------------------+-'   
               '-(--environment-name--)-'     

Abbreviations: INT for INTERNAL, EXT for EXTERNAL

environment-name
Specifies the name by which the procedure or variable is known outside of the compilation unit.

When so specified, the name being declared effectively becomes internal and is not known outside of the compilation unit. The environment name is known instead.

The environment name must be a character string constant, and is used as is without any translation to uppercase.

See the following example:
  dcl X entry external ('koala');

Environment names should not start with a break character (_). Names starting with this character are reserved for the library.

On platforms where the linker decorates environment names, if an environment name is specified with the external attribute, it will still be decorated if it differs only in case from the variable name. Consider the following declaration:

  dcl abc ext('kLm'), xyz ext('xYz' );

The name for xyz is decorated. For more information about the decoration of environment names, see the "Understanding linkage considerations" topic in the "Calling conventions" chapter in the PL/I for Windows Programming Guide.

INTERNAL is the default for entry names of internal procedures and for all other variables except for entry constants, file constants and programmer defined conditions. INTERNAL specifies that the name can be known only in the declaring block. Any other explicit declaration of that name refers to a new object with a different scope that does not overlap.

Note: INTERNAL can be specified on level-1 procedures in a package. If the package is declared with EXPORTS(*), an INTERNAL procedure is not visible outside the package.

EXTERNAL is the default for file constants, entry constants (other than internal procedures) and programmer-defined conditions. A name with the EXTERNAL attribute can be declared more than once, either in different external procedures or within blocks contained in external procedures. All declarations of the same name with the EXTERNAL attribute refer to the same data. The scope of each declaration of the name (with the EXTERNAL attribute) includes the scopes of all the declarations of that name (with EXTERNAL) within the application.

When a major structure or union name is declared EXTERNAL in more than one block, the attributes of the members must be the same in each case, although the corresponding member names need not be identical.

Consider the following example:
  ProcA: procedure;
    declare 1 A external,
              2 B,
              2 C;
              .
              . 
              .
     end ProcA;

 
  %process;
  ProcB: procedure;
    declare 1 A external,
            2 B,
            2 D;
            .
            .
            .
    end ProcB;

If A.B is changed in ProcA, it is also changed for ProcB, and vice versa; if A.C is changed in ProcA, A.D is changed for ProcB, and vice versa.

Members of structures and unions always have the INTERNAL attribute.

Because external declarations for the same name all refer to the same data, they must all result in the same set of attributes. When EXTERNAL names are declared in different external procedures, the user has the responsibility to ensure that the attributes are matching. Figure 1 illustrates a variety of declarations and their scopes.
Figure 1. Example of scopes of various declarations
         Scope_Example:  package exports(*);
 1         A: procedure;
 2            declare S character (20);
 7            dcl Set entry(fixed decimal(1)),
 7                Out entry(label);
              call Set (3);
 9         E: get list (S,M,N);
 8         B: begin;
 4,5            declare X(M,N), Y(M);
                get list (X,Y);
                call C(X,Y);
 9,5       C:  procedure (P,Q);
                  declare
                    P(*,*),
                    Q(*),
 12,2               S binary fixed external;
                  S = 0;
 6                do I = 1 to M;
                    if sum (P(I,*)) = Q(I) then
 8                     go to B;
                    S = S+1;
                    if S = 3 then
 9                     call Out (E);
                    Call D(I);
 8         B:  end;
           end C;
 9         D:  procedure (N);
                 put list ('Error in row ',
 2,3                   N, 'Table Name ', S);
           end D;
           end B;
           go to E;
           end A;
 9        Out:  procedure (R);
                Declare
                  R Label,
 11               (K static internal,
 11,7                L static external) init (0),
 12               S binary fixed external,
                  Z fixed decimal(1);
                K = K+1; S=0;
                if K<L then
                  stop;
 10             else go to R;
          end;
          Set:  procedure (Z);
                declare Z fixed dec(1);
 7              L=Z;
                declare L external init(0);
                return;
                end;
            end Scope_Example;
 1 
A is an external procedure name. Its scope is all of block A, plus any other blocks where A is declared as external.
 2 
S is explicitly declared in block A and block C. The character variable declaration applies to all of block A except block C. The fixed binary declaration applies only within block C. Notice that although D is called from within block C, the reference to S in the PUT statement in D is to the character variable S, and not to the S declared in block C.
 3 
N appears as a parameter in block D, but is also used outside the block. Its appearance as a parameter establishes an explicit declaration of N within D. The references outside D cause an implicit declaration of N in block A. These two declarations of the name N refer to different objects, although in this case, the objects have the same data attributes, which are, by default, FIXED BINARY(15,0) and INTERNAL. Under DEFAULT(ANS), the precision is (31,0).
 4 
X and Y are known throughout B and can be referred to in block C or D within B, but not in that part of A outside B.
 5 
P and Q are parameters, and therefore if there were no other declaration of these names within the block, their appearance in the parameter list would be sufficient to constitute a contextual declaration. However, a separate, explicit declaration statement is required in order to specify that P and Q are arrays. Although the arguments X and Y are declared as arrays and are known in block C, it is still necessary to declare P and Q in a DECLARE statement to establish that they, too, are arrays. (The asterisk notation indicates that the bounds of the parameters are the same as the bounds of the arguments.)
 6 
I and M are not explicitly declared in the external procedure A. Therefore, they are implicitly declared and are known throughout A, even though I appears only within block C.
 7 
The Out and Set external procedures in the example have an external declaration of L that is common to both. They also must be declared explicitly with the ENTRY attribute in procedure A. Because ENTRY implies EXTERNAL, the two entry constants Set and Out are known throughout the two external procedures.
 8 
The label B appears twice in the program—first in A, as the label of a begin-block, which is an explicit declaration, and then redeclared as a label within block C by its appearance as a prefix to an END statement. The go to B statement within block C, therefore, refers to the label of the END statement within block C. Outside block C, any reference to B is to the label of the begin-block.
 9 
Blocks C and D can be called from any point within B but not from that part of A outside B, nor from another external procedure. Similarly, because label E is known throughout the external procedure A, a transfer to E can be made from any point within A. The label B within block C, however, can be referred to only from within C. Transfers out of a block by a GO TO statement can be made; but such transfers into a nested block generally cannot. An exception is shown in the external procedure Out, where the label E from block C is passed as an argument to the label parameter R.

Note that, with no files specified in the GET and PUT statements, SYSIN and SYSPRINT are implicitly declared.

 10 
The statement else go to R; transfers control to the label E, even though E is declared within A, and not known within Out.
 11 
The variables K (INTERNAL) and L (EXTERNAL) are declared as STATIC within the Out procedure block; their values are preserved between calls to Out.
 12 
In order to identify the S in the procedure Out as the same S in the procedure C, both are declared with the attribute EXTERNAL.





Published: 23 December 2018