Objetivo
O bloco FUNCTION define uma sub-rotina que pode ser invocada a partir da macro Net.Data. As instruções executáveis em um bloco FUNCTION podem ser instruções de linguagem diretamente interpretadas por um ambiente de linguagem, ou elas podem indicar uma chamada para um programa externo.
Caso utilize a instrução ou bloco EXEC dentro de uma definição de função, esta deve ser a única instrução executável no bloco FUNCTION. Antes de passar a instrução executável para o ambiente de linguagem, o nome do arquivo do programa na instrução EXEC é anexado a um nome de caminho determinado pela instrução de configuração EXEC_PATH no arquivo de inicialização. A cadeia resultante é passada para o ambiente de linguagem a ser executado.
O método que o ambiente de linguagem usa para processar a instrução EXEC depende do ambiente particular da linguagem. Os únicos ambientes de linguagem que suportam a instrução EXEC são os ambientes REXX, System e Perl.
Sintaxe
>>-%function--(--amb_ling--)--nome_função--| definição de parâmetro |-->
+-;----------------------------------------------+
>--+-| retorna spec |--{--| corpo da função |---%}--+----------><
definição de parâmetro
|--(--+-------------------------------------+--)---------------|
| +-,-----------------------------+ |
| V | |
+---+-------+-Nome do repositório--+--+
+-IN----+
+-OUT---+
+-INOUT-+
retorna spec
|--+-------------------------------------+---------------------|
+-RETURNS--(--Nome do repositório--)--+
corpo da função
|--+----------------------------+------------------------------->
| +------------------------+ |
| V | |
+--instrução da linguagem--+-+
+-bloco exec-----------------+
>--+--------------------------------------------+--------------|
+-bloco de relatório--+--------------------+-+
| +-bloco de mensagem--+ |
+-bloco de mensagem--+---------------------+-+
+-bloco de relatório--+
Parâmetros
Contexto
Deve estar fora de blocos e instruções na parte da declaração da macro Net.Data.
Restrições
Pode conter estes elementos:
Exemplos
Os exemplos a seguir são gerais e não abrangem todos os ambientes de linguagem. Consulte o Net.Data Lanuage Environment Guide para obter mais informações sobre a utilização dos blocos FUNCTION com um ambiente de linguagem específico.
Exemplo 1: Uma função de subcadeia REXX.
%DEFINE lstring = "longstring"
%FUNCTION(DTW_REXX) substring(IN x, y, z) RETURNS(s) {
s = substr("$(x)", $(y), $(z));
%}
%DEFINE a = {@substring(lstring, "1", "4")%} %{ assigns "long" to a %}
Quando a é avaliado, a chamada de função @substring é encontrada e o bloco FUNCTION de subcadeia é executado. Variáveis são substituídas nas instruções executáveis no bloco FUNCTION, então, a cadeia de texto
s = substr("longstring", 1, 4)
é passada para o interpretador de REXX executar. Como a condição RETURNS foi especificada, o valor da chamada de função @substring na avaliação de a é substituído por "long", o valor de s.
Exemplo 2: Invocando um programa REXX externo.
%FUNCTION(DTW_REXX) my_rexx_pgm(INOUT a, b, IN c, OUT d) {
%EXEC{ mypgm.cmd this is a test %}
%}
%HTML(INPUT) {
<P> Valores originais de variável: $(w) $(x) $(z)
<P> @my_rexx_pgm(w, x, y, z)
<P> Valores modificados de variável: $(w) $(x) $(z)
%}
As variáveis w e x correspondem aos parâmetros de INOUT a e b na função. Seus valores e o valor de y, que corresponde ao parâmetro c de IN, já devem estar definidos a partir da entrada de formato HTML ou a partir de uma instrução DEFINE. ·s variáveis a e b são atribuídos novos valores quando os parâmetros a e b retornam valores. A variável z é definida quando o parâmetro de OUT d retorna um valor.
/* Exemplo de Programa REXX para o Exemplo 2 */ /* Argumentos de Teste */ num_args = arg(); say 'Há' num_args 'argumentos'; do i = 1 to num_args; say 'arg' i 'is "'arg(i)'"' end; /* Conjunto de variáveis passado do Net.Data */ d = a || b || c; /* concatenar a, b, e c gerando d */ a = ''; /* redefina a para uma cadeia nula */ b = ''; /* redefina b para uma cadeia nula */ return;
There are 1 arguments arg 1 is "isto é um teste"
A instrução EXEC informa ao ambiente de linguagem REXX que solicite que o interpretador do REXX e execute o programa externo do REXX mypgm.cmd. Como o ambiente de linguagem do REXX pode compartilhar diretamente variáveis do Net.Data com o programa do REXX, este atribui às variáveis do REXX a, b e c os valores das variáveis do Net.Data w, x e y antes de executar mypgm.cmd. Mypgm.cmd pode utilizar diretamente as variáveis a, b e c em instruções do REXX. Quando o programa é finalizado, as variáveis do REXX a, b e d são recuperadas do programa do REXX e seus valores são atribuídos às variáveis do Net.Data w, x e z. Como a condição RETURNS não é usada na definição do bloco my_rexx_pgm %FUNCTION, o valor da chamada de função @my_rexx_pgm é a cadeia nula "" (se o código de retorno for 0) ou o valor do código de retorno do programa REXX (se o código de retorno for diferente de zero).
Exemplo 3: Uma consulta e relatório SQL.
%FUNCTION(DTW_SQL) query_1(IN x, IN y) {
SELECT num.cliente, num.pedido, num.parte, status
FROM cliente, pedido, shippingpart
WHERE num.cliente = '$(x)'
AND cliente.numpedido = num.pedido
AND num.pedido= '$(y)'
AND pedido.numpeça = num.peça
%REPORT{
<P>Aqui está o status de seu pedido:
<P>$(NLIST)
<UL>
%ROW{
<LI>$(V1) $(V2) $(V3) $(V4)
%}
</UL>
%}
%}
%DEFINE cliente_nome="IBM"
%DEFINE cliente_pedido="12345"
%HTML(REPORT) {
@query_1(cliente_nome, cliente_pedido)
%}
A chamada de função @pedido_1 substitui "IBM" por $(x) e "12345" por
$(y) na instrução SELECT. Como a definição da função SQL query_1 não
identifica uma variável de tabela de saída, a tabela padrão é usada (veja o
bloco de variáveis TABLE para obter detalhes). As variáveis NLIST e Vi
referenciadas no bloco REPORT são definidas pela definição da tabela padrão. O
relatório produzido pelo bloco REPORT é colocado no HTML de saída onde a
função query_1 é invocada.
Exemplo 4: Uma chamada do system para executar um script Perl.
%FUNCTION(DTW_SYSTEM) today() RETURNS(result) {
%exec{ perl "today.prl" %}
%}
%HTML(INPUT) {
@today()
%}
$date = `date`;
chop $date;
open(DTW, "> $ENV{DTWPIPE}") || die "Não pôde abrir: $!";
print DTW "result = \"$date\"\n";
O ambiente de linguagem de System interpreta as instruções executáveis em um bloco FUNCTION passando-as para o sistema operacional através da chamada de função system() de linguagem C. Este método não permite que as variáveis do Net.Data sejam passadas ou recuperadas diretamente para as instruções executáveis, como faz o ambiente de linguagem do REXX, então o ambiente de linguagem do System passa e recupera variáveis como descrito aqui:
Quando a chamada de função @today for encontrada, o Net.Data executará a substituição de variável nas instruções executáveis. Nesse exemplo, não há variáveis do Net.Data nas instruções executáveis, assim nenhuma substituição de variável é executada. As instruções e parâmetros executáveis são passados ao ambiente de linguagem System, que cria um canal nomeado e define a variável de ambiente DTWPIPE com o nome do canal.
Então o programa externo é chamado com a chamada de função system(). O programa externo abre o canal como apenas-de-gravação e grava o canal como se esse fosse um arquivo de fluxo padrão. Quando se utiliza Net.Data no modo CGI, a saída HTML é gravada no fluxo STDOUT. Neste exemplo, a saída do programa de data do sistema é atribuída à variável result, que é a variável identificada na condição RETURNS do bloco FUNCTION. Este valor da variável result substitui a chamada de função @today() no bloco HTML.
Exemplo 5: Ambiente de linguagem Perl.
%FUNCTION(DTW_PERL) today() RETURNS(result) {
$date = `data`;
chop $date;
open(DTW, "> $ENV{DTWPIPE}") || die "Não pôde abrir: $!";
print DTW "result = \"$date\"\n";
%}
%HTML(INPUT) {
@today()
%}
Compare este exemplo ao Exemplo 4 para ver como a instrução EXEC é
utilizada. No exemplo 4, o ambiente de linguagem de System não sabe como
interpretar programas Perl, porém sabe como chamar programas externos. A
instrução EXEC diz ao ambiente para chamar um programa chamado perl como um
programa externo. As verdadeiras instruções de linguagem Perl são
interpretadas pelo programa externo Perl. O exemplo 5 não possui instrução
EXEC porque o ambiente de linguagem Perl é capaz de interpretar diretamente
instruções de linguagem Perl.