IBM Books

Administration and Programming Guide for OS/400

Defining Functions

To define your own functions in the macro, use a FUNCTION block or MACRO_FUNCTION block:

FUNCTION block
Defines a subroutine that is invoked from a Net.Data macro and is processed by a language environment. FUNCTION blocks must contain language statements or calls to an external program.

MACRO_FUNCTION block
Defines a subroutine that is invoked from a Net.Data macro and is processed by Net.Data rather than a language environment. MACRO_FUNCTION blocks can contain any statement that is allowed in an HTML block.

Syntax: Use the following syntax to define functions:

FUNCTION block:

%FUNCTION(type) function-name([usage] [datatype] parameter, ...) [RETURNS(return-var)] {
  executable-statements
  [report-block]
  ...
  [report-block]
  [message-block]
%}

MACRO_ FUNCTION block:

%MACRO_FUNCTION function-name([usage] parameter, ...) [RETURNS(return-var)] {
  executable-statements
  report-block
  ...
  report-block
%}

Where:

type
Identifies a language environment that is configured in the initialization file. The language environment invokes a specific language processor (which processes the executable statements) and provides a standard interface between Net.Data and the language processor.

function-name
Specifies the name of the FUNCTION or MACRO_FUNCTION block. A function call specifies the function-name, preceded by an at (@) sign. See Calling Functions for details.

You can define multiple FUNCTION or MACRO_FUNCTION blocks with the same name so that they are processed at the same time. Each of the blocks must all have identical parameter lists. When Net.Data calls the function, all FUNCTION blocks with the same name or MACRO_FUNCTION blocks with the same name are executed in the order they are defined in the Net.Data macro.

usage
Specifies whether a parameter is an input (IN) parameter, an output (OUT) parameter, or both types (INOUT). This designation indicates whether the parameter is passed into or received back from the FUNCTION block, MACRO_FUNCTION block, or both. The usage type applies to all of the subsequent parameters in the parameter list until changed by another usage type. The default type is IN.

datatype
The data type of the parameter. Some language environments expect data types for the parameters that are passed. For example, the SQL language environment expects them when calling stored procedures, as does the Direct Call language environment when calling programs. See Using Language Environments to learn more about the supported data types for the language environment you are using.

parameter
The name of a variable with local scope that is replaced with the value of a corresponding argument specified on a function call. Parameter references, for example $(parm1), in the executable statements or REPORT block are replaced with the actual value of the parameter. In addition, parameters are passed to the language environment and are accessible to the executable statements using the natural syntax of that language or as environment variables. Parameter variable references are not valid outside the FUNCTION or MACRO_FUNCTION blocks.

return-var
Specify this parameter after the RETURNS keyword to identify a special OUT parameter. The value of the return variable is assigned in the function block, and its value is returned to the place in the macro from which the function was called. For example, in the following sentence, <p>My name is @my_name()., @my_name() gets replaced by the value of the return variable. If you do not specify the RETURNS clause, the value of the function call is:

executable-statements
The set of language statements that is passed to the specified language environment for processing after the variables are substituted and the functions are processed. executable-statements can contain Net.Data variable references and Net.Data function calls.

For FUNCTION blocks, Net.Data replaces all variable references with the variable values, executes all function calls, and replaces the function calls with their resulting values before the executable statements are passed to the language environment. Each language environment processes the statements differently. For more information about specifying executable statements or calling executable programs, see Executable Variables.

For MACRO_FUNCTION blocks, the executable statements are a combination of text and Net.Data macro language constructs. In this case, no language environment is involved because Net.Data acts as the language processor and processes the executable statements.

report-block
Defines one or more REPORT blocks for handling the output of the FUNCTION or MACRO_FUNCTION block. See Report Blocks.

message-block
Defines the MESSAGE block, which handles any messages returned by the FUNCTION block. See Message Blocks.

Define functions outside of any other block and before they are called in the Net.Data macro.

Using Special Characters in Functions

When characters that match Net.Data language constructs syntax are used in the language statements section of a function block as part of syntactically valid embedded program code (such as REXX or Perl), they can be misinterpreted as Net.Data language constructs, causing errors or unpredictable results in a macro.

For example, a Perl function might use the COMMENT block delimiter characters, %{. When the macro is run, the %{ characters are interpreted as the beginning of a COMMENT block. Net.Data then looks for the end of the COMMENT block, which it thinks it finds when it reads the end of the function block. Net.Data then proceeds to look for the end of the function block, and when it can't be found, issues an error.

Use one of the following methods to use COMMENT block delimiter characters, or any other Net.Data special characters as part of your embedded program code, without having them interpreted by Net.Data as special characters:

For example, the following Perl function contains characters representing a COMMENT block delimiter, %{, as part of its Perl language statements:

%FUNCTION(DTW_PERL) func() {
  ...           
  for $num_words (sort bynumber keys %{ $Rtitles{$num} }) {
    &make_links($Rtitles{$num}{$num_words});          
  }   
  ... 
%}   

To ensure that Net.Data interprets the %{ characters as Perl source code rather than as a Net.Data COMMENT block delimiter, rewrite the function in either of the following ways:

Message Blocks

The MESSAGE block lets you determine how to proceed after a function call, based on the success or failure of the function call, and lets you display information to the caller of the function. When processing a message, Net.Data sets the language environment variable RETURN_CODE for each function call to a FUNCTION block. RETURN_CODE is not set on a function call to a MACRO_FUNCTION block.

A MESSAGE block consists of a series of message statements, each of which specifies a return code value, message text, and an action to take. The syntax of a MESSAGE block is shown in the language constructs chapter of Net.Data Reference.

A MESSAGE block can have a global or a local scope. If the MESSAGE block is defined in a FUNCTION block, its scope is local to that FUNCTION block. If it is specified at the outermost macro layer, the MESSAGE block has global scope and is active for all function calls executed in the Net.Data macro. If you define more than one global MESSAGE block, the last one defined is active.

Net.Data uses these rules to process the value of the RETURN_CODE variable from a function call:

  1. Check local MESSAGE block for an exact match; exit or continue as specified.
  2. If RETURN_CODE is not 0, check local MESSAGE block for +default or -default; depending on the sign of RETURN_CODE, exit or continue as specified.
  3. If RETURN_CODE is not 0, check local MESSAGE block for default; exit or continue as specified.
  4. Check global MESSAGE block for an exact match; exit or continue as specified.
  5. If RETURN_CODE is not 0, check global MESSAGE block for +default or -default; depending on the sign of RETURN_CODE, exit or continue as specified.
  6. If RETURN_CODE is not 0, check global MESSAGE block for default; exit or continue as specified.
  7. If RETURN_CODE is not 0, issue Net.Data internal default message and exit.

The following example shows part of a Net.Data macro with a global MESSAGE block and a MESSAGE block for a function.

%{ global message block %}
%MESSAGE {
   -100     : "Return code -100 message"   : exit
    100     : "Return code 100 message"    : continue
   +default : {
This is a long message that spans more
than one line. You can use HTML tags, including
links and forms, in this message. %}   : continue  
%}
 
%{ local message block inside a FUNCTION block %}
%FUNCTION(DTW_REXX) my_function() {
  %EXEC { my_command.mbr %}
  %MESSAGE {
     -100     : "Return code -100 message"   : exit
      100     : "Return code 100 message"    : continue
     -default : {
This is a long message that spans more
than one line. You can use HTML tags, including
links and forms, in this message. %}   : exit  
  %}

If my_function() returns with a RETURN_CODE value of 50, Net.Data processes the error in this order:

  1. Check for an exact match in the local MESSAGE block.
  2. Check for +default in the local MESSAGE block.
  3. Check for default in the local MESSAGE block.
  4. Check for an exact match in the global MESSAGE block.
  5. Check for +default in the global MESSAGE block.

When Net.Data finds a match, it sends the message text to the Web browser and checks the requested action.

When you specify continue, Net.Data continues to process the Net.Data macro after printing the message text. For example, if a macro calls my_functions() five times and error 100 is found during processing with the MESSAGE block in the example, output from a program can look like this:

.
.
.
11 May 1997                  $245.45
13 May 1997                  $623.23
19 May 1997                  $ 83.02
return code 100 message
22 May 1997                  $ 42.67
 
Total:                       $994.37


[ Top of Page | Previous Page | Next Page | Table of Contents | Index ]