There are many procedure attributes you can access through the procedure’s handle. This section introduces you to a few of them.

FILE-NAME attribute

After you run a persistent procedure, you can query its FILE-NAME attribute to see the name of the procedure file, including any pathname it was run with. This attribute can be useful to identify a procedure so that you can run something in its handle or access other attributes.

PRIVATE-DATA attribute

There is a character attribute available on every handle, including procedure handles, called PRIVATE-DATA. It is there specifically so that you can store any value you want on the handle, to help identify the object it points to, or to store other information about the object. The PRIVATE-DATA attribute is not used by ABL in any way; it is strictly there for your application use. You could, for example, store a category of object in the PRIVATE-DATA handle when you run the procedure, or the value of one or more parameters that were passed in to the procedure to give it a distinctive function. Because you might run the same procedure file in numerous ways, for example with different input parameters or different settings that you establish in other ways, the PRIVATE-DATA attribute gives you the ability to identify it in any way you need to.

INTERNAL-ENTRIES attribute

The INTERNAL-ENTRIES attribute returns a comma-separated list of all the internal procedures in the procedure file, and also any user-defined functions, which you’ll learn about a little later. This can help you identify the location of a routine you need to run.

GET-SIGNATURE() method

Given the name of any internal procedure or function in a procedure file, you can get its signature, that is, the list of parameters it requires, using the GET-SIGNATURE( ) method on the procedure handle. This is considered a method rather than an attribute simply because it requires an input parameter, the name of the routine you want the signature for. You can also pass in a blank argument to get the signature of the external procedure itself.

GET-SIGNATURE() returns a string in this format:
type, fn-return-type, mode name data-type [ , mode name data-type ], . . .
The type is the type of entry point and its possible values are:
  • MAIN for the external procedure itself (when you pass in an empty string).
  • PROCEDURE for an internal procedure.
  • FUNCTION for a user-defined function.

The fn-return-type is the data type that a function returns. For an internal procedure, this element of the signature is blank.

Following the second comma is a list of the parameter descriptions. Each description is a space-delimited list of three elements:
  • The mode is INPUT, OUTPUT, or INPUT-OUTPUT.
  • The name is the parameter name as defined in the entry point.
  • The data-type is the data type of the parameter.
As an example, here is a very simple procedure file that contains an internal procedure and a user-defined function:
/* h-testsig.p -- tests GET-SIGNATURE */
DEFINE INPUT PARAMETER cVar AS CHAR.

PROCEDURE TestProc:
  DEFINE OUTPUT PARAMETER iValue AS INT.
  /* some procedure code */
END.

FUNCTION TestFunc RETURNS INTEGER (INPUT dValue AS DECIMAL):
  /* some function code */
END.

The h-testsig.p procedure takes an INPUT parameter, the TestProc internal procedure uses an OUTPUT parameter, and the TestFunc function takes an INPUT parameter and returns the data type INTEGER.

Here’s another procedure that uses GET-SIGNATURE to get the signatures of all these routines:
/* Procedure h-mainsig.p -- uses GET-SIGNATURE to return the signatures
  of a procedure and its internal-entries */
VAR HANDLE hProc.
VAR INTEGER iProc.
VAR CHARACTER cEntries.
VAR CHARACTER cMessage.

RUN h-testsig.p PERSISTENT SET hProc (INPUT "aa").

cEntries = hproc:INTERNAL-ENTRIES.
cMessage = THIS-PROCEDURE:FILE-NAME + ": " + hproc:GET-SIGNATURE("").
DO iProc = 1 TO NUM-ENTRIES(cEntries):
  cMessage = cMessage + CHR(10) +
  ENTRY(iProc, cEntries) + ": " +
  hproc:GET-SIGNATURE(ENTRY(iProc, cEntries)).

END.
MESSAGE cMessage VIEW-AS ALERT-BOX.
This procedure executes as follows:
  1. h-mainsig.p runs h-testsig.p persistent and saves off its procedure handle.
  2. h-mainsig.p gets the INTERNAL-ENTRIES attribute of the procedure, which should have the value TestProp,TestFunc.
  3. It begins to build up a character string to display later with a MESSAGE statement. The first entry in the message string is THIS-PROCEDURE:FILE-NAME. Because the built-in THIS-PROCEDURE system handle evaluates to the handle of the currently running procedure, this should return its filename, h-mainsig.p. Passing the empty string to GET-SIGNATURE returns the signature of the external procedure itself.
  4. The code loops through all the entries in the INTERNAL-ENTRIES attribute, and for each once, saves off its name and signature.
  5. To simulate a series of SKIP keywords that you could put into a MESSAGE statement, the code adds a new line character after the signature of each entry. The CHR(n) ABL built-in function takes an INTEGER value that represents the ASCII character code of any character, whether printable or not, and returns that ASCII character. In this case, 10 represents the new line character.
This shows the message you see when you run h-mainsig.p:
h-mainsig.p: MAIN,,INPUT cVar CHARACTER
TestProc: PROCEDURE,,OUTPUT iValue INTEGER
TestFunc: FUNCTION,integer,INPUT dValue DECIMAL