Can CALLNAT be used with a variable field that will contain the natural program to be call? If so what is the syntax?
Sure. Use a variable instead of a constant.
The variable must be defined as alpha with a length of 1 to 8.
DEFINE DATA LOCAL 1 #SUBPGM (A8) INIT <"ABCDEF"> END-DEFINE CALLNAT "ABCDEF" CALLNAT #SUBPGM END
Just the same as with a literal subprogram name, specify an A variable ( length 1 to 8 ) as operand 1
CALLNAT #MYSUBPROGRAM ...
There are 2 main solutions to make a dynamic call:
- use an A8 Parameter-Field in the PDA. The main caller deciedes which subprogramm will be called
- The programm reads a config-, database-file, etc to get the name of the subprogramm and stores the name into an A8 local variable.
If you want to break dependencies, this is the best solution in Natrual.
And this is indeed flexible !
But remember that “all magic comes with a price”
In this case neither the predict X-REF nor the Dependencies-view in NaturalOne will be able to give you any hint on where a given subprog is used.
Not even a free-text search will help - so remember to comment it heavily in the calling source for the benefit of your successors!
If you know the list of modules that you will be calling, you can mitigate the X-REF issue that Finn mentions by creating an internal subroutine in your program that never gets performed and put explicit callnats to each subprogram in your list.
* ----------------------- DEFINE SUBROUTINE NEVER-PERFORMED * ----------------------- CALLNAT 'SUBPGM1' #PDA CALLNAT 'SUBPGM2' #PDA CALLNAT 'SUBPGM3' #PDA CALLNAT 'SUBPGM4' #PDA * END-SUBROUTINE
On the other hand, if they all share the same PDA (and they should) you can use the PDA in XREF to find possible dependencies on SUBPGM1.
If you are using dynamic calls, that there is no need for the X-Ref-Data.
You want to decide on runtime, which subprogramm will be called.
You are decoupling the moduls and they are independend.
The only connected is the PDA. The PDA is the “Interface” of the subprogramms and the subpgrogramms are the implementer of the “Interface” (PDA).
My advice is that you need at least one special PDA for implementer subprogramms. Then you can use the X-Ref-Data from the PDA to see the dependecies.
The only problem is, that you cann’t easyly differentiated between caller and implementer.
Another way we use in Testscases. Is like this:
IF P-DADP510N EQ ' ' CALLNAT 'DADP510N' SUBFUNP SUBERGP DADP510P(*) ELSE CALLNAT P-DADP510N SUBFUNP SUBERGP DADP510P(*) END-IF
In normel mode, the program calls DADP510N. Under test we set the P-DADP510N to a stub modul. The stub modul delivers the testdata needed for the Testcase.
With this solution you get the X-Ref-Data and you can break the dependencies under test. There is no need to see the dependences to the sub moduls.
Dynamic calls are usefull, but have some drawbacks. If you want to break dependencies there is no better way in Natural.