64940313 Lenguaje RPG

17
Lenguaje RPG RPG es un lenguaje de programacion de IBM orientado al desarrollo de aplicaciones empresariales, y que es muy usado en la plataforma de servidores intermedios de IBM. Ha sido la base de los antiguos sistemas S/32, S/34, S/36, S/38, AS/400, iSeries, System i, así como de la nueva plataforma Power 7. En el curso del tiempo ha tenido incontables mejoras continuas hasta convertirlo en lo que es hoy, un lenguaje muy poderoso para hacer aplicaciones de negocios. Es un lenguaje "propietario", inventado por IBM para facilitar la programación de tareas de negocio en las Empresas. La historia del lenguaje RPG está llena de continuas mejoras y versiones, y la realidad ahora es que es la base (junto con Cobol) de los programas que funcionan en muchas empresas. En los últimos años, IBM ha mejorado en mucho RPG, ahora llamado RPG IV o RPG ILE, dotándolo de muchas opciones y funciones (como rpg-free y %bifs), mejoras en el compilador y creando el entorno ILE para facilitar la programación más estructurada y la combinación de múltiples lenguajes, como Java, C++, etc. Un ejemplo de la flexibilidad y potencia de RPG es RpgForWeb, un entorno que facilita la creación de Aplicaciones Web usando RPG IV y el estándar de la Web; html y javascript. Las Aplicaciones se pueden desarrollar con muchos lenguajes, incluso puede ser bueno combinar varios lenguajes en una Aplicación, y en la mayoría de las ocasiones no importa tanto el lenguaje con el que está desarrollada una Aplicación como el conocimiento del medio y la inteligencia del programador. tema del mes 68 noviembre 1996 El ILE en acción En los AS/400 CISC, la V3R1 ha demostrado que es estable y pronto será sustituida por la V3R2; en los AS/400 RISC, que iniciaron su andadura con la V3R6, pronto dispondrán de la nueva V3R7: Muchos de nosotros hemos instalado alguna de estas releases o lo haremos muy pronto. De hecho, la consultora Gartner Group opina que a nivel mundial, y antes de que finalice 1996, estarán en producción (no las que se habrán vendido) más de 100.000 copias de la V3R1/V3R2. Muchos programadores se hallan a punto de arremangarse para ponerse a trabajar con las nuevas funciones de la

Transcript of 64940313 Lenguaje RPG

Page 1: 64940313 Lenguaje RPG

Lenguaje RPG

RPG es un lenguaje de programacion de IBM orientado al desarrollo de aplicaciones

empresariales, y que es muy usado en la plataforma de servidores intermedios de IBM. Ha

sido la base de los antiguos sistemas S/32, S/34, S/36, S/38, AS/400, iSeries, System i, así

como de la nueva plataforma Power 7. En el curso del tiempo ha tenido incontables mejoras

continuas hasta convertirlo en lo que es hoy, un lenguaje muy poderoso para hacer

aplicaciones de negocios.

Es un lenguaje "propietario", inventado por IBM para facilitar la programación de tareas de

negocio en las Empresas. La historia del lenguaje RPG está llena de continuas mejoras y

versiones, y la realidad ahora es que es la base (junto con Cobol) de los programas que

funcionan en muchas empresas.

En los últimos años, IBM ha mejorado en mucho RPG, ahora llamado RPG IV o RPG

ILE, dotándolo de muchas opciones y funciones (como rpg-free y %bifs), mejoras en el

compilador y creando el entorno ILE para facilitar la programación más estructurada y la

combinación de múltiples lenguajes, como Java, C++, etc.

Un ejemplo de la flexibilidad y potencia de RPG es RpgForWeb, un entorno que facilita la

creación de Aplicaciones Web usando RPG IV y el estándar de la Web; html y javascript.

Las Aplicaciones se pueden desarrollar con muchos lenguajes, incluso puede ser bueno

combinar varios lenguajes en una Aplicación, y en la mayoría de las ocasiones no importa

tanto el lenguaje con el que está desarrollada una Aplicación como el conocimiento del

medio y la inteligencia del programador.

tema del mes 68

noviembre 1996

El ILE en acción

En los AS/400 CISC, la V3R1 ha demostrado que es estable y pronto

será sustituida por la V3R2; en los AS/400 RISC, que iniciaron su

andadura con la V3R6, pronto dispondrán de la nueva V3R7: Muchos

de nosotros hemos instalado alguna de estas releases o lo haremos

muy pronto. De hecho, la consultora Gartner Group opina que a

nivel mundial, y antes de que finalice 1996, estarán en producción

(no las que se habrán vendido) más de 100.000 copias de la

V3R1/V3R2. Muchos programadores se hallan a punto de

arremangarse para ponerse a trabajar con las nuevas funciones de la

Page 2: 64940313 Lenguaje RPG

Versión 3 (Release x). Y uno de sus retos más inmediatos será el

entorno ILE de programación entender como aplicarlo con la

suficiente astucia para conseguir el máximo partido posible del nuevo modelo de programación y de lo que éste ofrece.

Si ya has jugado un poco con el ILE sabrás que no es fácil hacerse

con él a la primera y que incluso resulta fustrante aprenderlo. Dada

la abundancia de nuevos conceptos, la escasa documentación de IBM

y los escasos ejemplos, incluso un veterano programador en RPG

puede desmoralizarse. Afortunadamente, podemos separar las

funciones del lenguaje ILE (RPG IV y su nueva sintaxis) de las

características de la nueva arquitectura ILE (utilización de recursos

como grupos de activación, llamadas estáticas...). Establecer esta división nos ayudará a aprender y utilizar este entorno con eficacia.

En números anteriores de NEWS/400 ya se han tratado algunos

aspectos del ILE y del RPG IV. Así, en abril del 94, anticipándonos a

la salida de la V3, con el título de "El próximo ILE RPG IV" publicamos

una avanzadilla sobre cómo evolucionaría el RPG en el futuro. Luego

hemos publicado artículos generales como "Por fin, ILE para todos" y

"Del RPG III al ILE RPG IV y al revés..." (Marzo 95, núm. 52), o más

detallados, como "Los Grupos de Activación" (Mayo 95, núm. 54),

"Las especificaciones tipo D del RPG IV" y dos partes del artículo

sobre las "Operaciones de fecha/hora del RPG IV" (Junio y

Septiembre 95, números 55 y 56, respectivamente). A partir de este

número, además de los artículos Las funciones incorporadas y los

Subprocedimientos en RPG IV que explican otras posibilidades

añadidas al RPG, incluimos una Utilidad (CVTRPG) para convertir los

campos definidos en cálculo a las nuevas especificaciones D y diez

Trucos & Técnicas sobre el tratamiento de fechas, iniciamos una serie

que, de forma práctica, pretende familiarizar al lector en el ILE. Así,

para el próximo número tenemos previstos dos nuevos artículos, uno

sobre cómo crear programas de servicio y otro sobre las nuevas

operaciones de llamada y programación modular, dejando para el

siguiente un repaso a los Grupos de Activación, el manejo de errores en ILE o el código de operación EVAL.

Creemos que esta serie de artículos pueden ser una buena

ayuda para el aprendizaje de ILE. Tanto para aquellos que ya

habéis pasado a V3, porque podréis aprovechar su contenido

de inmediato, como para los que todavía continuáis en V2,

puesto que con ellos podréis valorar las posibilidades del ILE y

prepararos convenientemente para el futuro. Mi consejo

personal: si queréis poneros al día, no perdáis esta serie e intentad recuperar los números con lo que ya se ha publicado.

Carlos Bell

1 - Las funciones incorporadas del RPG IV

Muchos lenguajes del AS/400, incluidas las CLs, tienen funciones

Page 3: 64940313 Lenguaje RPG

incorporadas (BIF o Built-In Function) desde hace bastante

tiempo. Pero para el RPG, las funciones incorporadas son totalmente nuevas.

Podemos pensar que las BIFs son códigos de operación que

devuelven un valor sin necesidad de tener que colocar un campo de

resultado. Hasta la llegada de la V3R1, realizaba alguna de estas

funciones con códigos de operación (por ejemplo SUBST) metiendo a

presión los argumentos en el primer o en el segundo factor,

añadiendo el carácter ‘:’ para separarlos cuando era preciso. O

directamente no soportaba la función y era necesario que uno mismo se creara las sentencias para realizar el trabajo.

Con RPG IV se pueden utilizar las funciones incorporadas que son

eficientes y fáciles de entender, e incluso pueden hacer tareas que previamente requerían de ciertos trucos de programación.

Lo básico de las BIFs

IBM ha añadido las BIFs con sólo unas cuantas operaciones básicas,

pero se espera que expanda estas funciones en próximos releases. En la V3R1 el RPG IV soporta las siguientes funciones incorporadas:

%SUBST

%TRIM, %TRIML, %TRIMR

%SIZE

%ELEM

%ADDR, %PADDR

En la V3R6, además, se ha añadido la función incorporada

%PARMS.Cuando se utiliza una BIF se debe indicar los argumentos

de la función de acuerdo con el siguiente formato:

%funcion(argumento:argumento) . Los argumentos pueden ser

variables, constantes, expresiones e incluso otras funciones

incorporadas. Aunque normalmente se utilizan en los cálculos del

programa, también están soportadas por las especificaciones D utilizando valores en tiempo de compilación.

La función %SUBST

La función incorporada %SUBST (subserie) extrae una parte de una

serie de caracteres y expande las posibilidades del código de

operación SUBST. Se debe especificar la serie de caracteres, la

posición inicial desde la cual se extraerán los caracteres y la longitud, esta última es opcional.

En el ejemplo A de la figura 1 la función %SUBST coloca el valor ABC

en la variable Start, que son los primeros tres caracteres de la

constante con nombre UpperCase. La variable Middle tendrá los

caracteres LMNOP, cinco caracteres a partir de la posición 12.

Finalmente la variable End tendrá los caracteres XYX, los tres últimos

caracteres. Como en el último ejemplo no se ha especificado la

longitud de la subserie a extraer, la función %SUBST extrae todos los

Page 4: 64940313 Lenguaje RPG

caracteres hasta el final de la serie.

Si es necesario, el código de operación EVAL mueve la subserie a la

izquierda del campo de resultado, blanquea los bytes de la derecha

no rellenados por %SUBST y trunca la serie si el campo de resultado es demasiado pequeño.

Los argumentos de %SUBST también pueden ser expresiones, tal

como se ve en el ejemplo B de la figura 1. Las sentencias del ejemplo

extraen el nombre y el apellido de una serie que contiene el nombre

completo con un signo "/" como separador. Por ejemplo si el

contenido del campo LastFirst es SMITH/JOHN, las sentencias del

ejemplo extraen SMITH y lo colocan en el campo Last y hacen lo

mismo con JOHN en el campo First. Cuando se utilizan expresiones

como argumentos de las funciones incorporadas es necesario

asegurar que los argumentos y que los valores devueltos por la BIF

son correctos o el programa dará un error durante la ejecución.

Además de utilizar %SUBST para extraer una serie de caracteres,

también se puede utilizar como resultado de una asignación, o sea

para cambiar una parte de una serie de caracteres. En el ejemplo C

cambia el contenido de la variable Swine a "PigPigPigPearlsPigPig" al

especificar la función %SUBST a la izquierda del signo igual de la operación EVAL.

Probablemente es más practico utilizar %SUBST para insertar el valor

de una variable (en lugar de un literal) en una serie de caracteres, tal

como muestra el ejemplo D. En este ejemplo, la variable BarGraph

contiene el valor hexadecimal ‘20’, que las pantallas del AS/400

identifican como final de campo. La sentencia EVAL cambia el valor

de BarGraph de forma que la regla aparece por el lado izquierdo del

campo y muestra el número de caracteres indicado por la variable Percent.

Quitar caracteres en blanco con las BIFs de ajuste de blancos

Las tres funciones %TRIM x devuelven una serie de caracteres a la

que se le han recortado los blancos del comienzo y/o del final. La

función %TRIM recorta los blancos del comienzo y del final, %TRIML

sólo recorta los blancos del comienzo (izquierda) y %TRIMR sólo

recorta los blancos del final (derecha).

Las funciones %TRIM x reducen las sentencias necesarias para

concatenar campos cuando es necesario eliminar los blancos

intermedios. El RPG III necesita bastantes sentencias con

operaciones SCAN, CHECK, CHEKR y CAT para hacer lo mismo que

una sentencia EVAL de RPG IV con una o más funciones %TRIM x .

El único argumento de las funciones %TRIM x es la serie de

caracteres que será ajustada. Este argumento puede ser una variable, un literal o una constante.

El tamaño del campo

La función incorporada %SIZE da al RPG una función totalmente

Page 5: 64940313 Lenguaje RPG

nueva: devuelve el número de bytes que tiene un campo, un literal,

una estructura de datos o una constante con nombre.

Los ejemplos A y B de la figura 3 combinan las funciones %SIZE y

%TRIM para determinar si la línea a imprimir supera los 35

caracteres de longitud. Es importante destacar que en el ejemplo B el

argumento de una de las funciones incorpora otras funciones, lo que

permite eliminar sentencias y campos intermedios de trabajo.

Cuando se utiliza una serie o una tabla, o una estructura de datos de

múltiples ocurrencias como argumento de la función %SIZE, esta

devuelve el tamaño de un elemento o una ocurrencia. Para recuperar

el tamaño de toda la serie, tabla o estructura de datos de apariciones múltiples se debe incluir *ALL como segundo argumento.

Es importante recordar que la función %SIZE devuelve el número de

bytes. Cuando se utiliza para determinar el tamaño de un campo

empaquetado o binario no devuelve el número de dígitos del campo.

La función %ELEM

Esta función devuelve el número de elementos de una serie, una

tabla o el número de ocurrencias de una estructura de datos de apariciones múltiples.

Se puede utilizar esta función para que sea más sencillo mantener el

programa. Por ejemplo, en la figura 4 la serie WeeklySIs contiene las

ventas por semana y tiene 53 elementos que es el máximo número

de semanas que puede tener un año. La serie WeeklyComm, que

contiene las comisiones por semana y está definida como asociada a

la serie WeeklySIs, tiene los mismos atributos. También tiene el

mismo número de elementos que WeeklySIs, ya que la sentencia con

la palabra clave DIM utiliza la función %ELEM(WeeklySIs). Con esta

definición, si se cambia el número de elementos de WeeklySIs

también se ajustará automáticamente el número de elementos de

WeeklyComm cuando se vuelva a compilar el programa. Es necesario

recordar que las BIFs se pueden resolver durante la compilación lo

que permite utilizarlas en las especificaciones D.

Otro ejemplo que mejora la claridad del programa, y por lo tanto

hace más fácil posteriores modificaciones, se puede ver en la figura

5. La estructura de datos contiene un campo de trabajo que además

es contenido por una serie con elementos de 1 byte de longitud. La

función %ELEM coloca el número de elementos de la serie en el

campo ArrayLimit. Si la longitud del campo CustName, en el que se

basan todas las definiciones, cambia, sólo es necesario recompilar el

programa y se ajustarán todos los valores y tamaños de las variables que dependen de él.

También se puede utilizar la función %ELEM en los cálculos, tal como

se muestra en el ejemplo B. En este ejemplo se limita el número de

veces que se ejecuta el DOU con el número de elementos de la serie

WeeklySIS. De esta forma, no es necesario modificar ninguna

sentencia si cambia el número de elementos de la serie. Además,

Page 6: 64940313 Lenguaje RPG

como regalo, si se escribe de esta forma la sentencia DOU, queda

documentado el motivo del bucle: para procesar cada elemento de la serie.

Apuntando a %ADDR y %PADDR

Las funciones %ADDR (Dirección) y %PADDR (Dirección de

Procedimiento) son dos formas de dar soporte de punteros al RPG.

Aunque trataremos más ampliamente el tema de punteros en

próximos números, en este artículo daremos una visión rápida para estas dos BIFs.

Los punteros son variables que contienen las direcciones de otras

variables (o procedimientos) de un programa en lugar de contener el

valor de las variables. La función %ADDR coloca la dirección de una

variable, un elemento de una serie o una expresión en un puntero. El

resultado es una variable (del nuevo tipo de datos puntero) con la

dirección de la variable especificada.

En A en la figura 6 se ha definido DayPtr con el tipo de datos *, lo

que indica que el campo es un puntero. Se ha utilizado la palabra

clave INZ junto con la palabra clave %ADDR para inicializar este

puntero con la dirección de la serie DayOfWeeks. Se puede cambiar

el valor de la dirección del puntero asignándole un nuevo valor en las

sentencias de cálculo, tal como se puede ver en el ejemplo B. En este

caso se ha incluido la función %ADDR en una sentencia EVAL para

asignarle a DayPtr la dirección del cuarto elemento de la serie DaysOfWeek.

La función %PADDR devuelve la dirección del punto de entrada de un

procedimiento (programa). La variable que recibe la dirección debe

ser del tipo de datos puntero. Se pueden utilizar los punteros de

procedimientos con el código de operación CALLB (Llamar a un

procedimiento enlazado) para enlazar estáticamente una llamada a un procedimiento.

En el ejemplo C de la figura 6 se define un puntero de procedimiento

(tipo de datos *) con la palabra clave PROCPTR. Luego se inicializa el

puntero con la dirección del procedimiento ADDCUST utilizando la

función %PADDR en la palabra clave INZ. Después, en las

especificaciones de cálculo, se llama al procedimiento ADDCUST

mediante la operación CALLB. Normalmente, se ejecuta más

rápidamente la llamada a un procedimiento por su dirección que si se utiliza un literal o una constante con nombre en el segundo factor.

La función incorporada más reciente

En la V3R6 se ha incorporado la función %PARMS. Esta BIF devuelve

el número de parámetros que se han pasado al procedimiento donde

se está utilizando la función %PARMS. Para el procedimiento principal

la función %PARMS es equivalente a la palabra especial *PARMS de

la estructura de datos del programa. Puede obtener más información

sobre procedimientos, procedimiento principal y subprocedimientos

Page 7: 64940313 Lenguaje RPG

en el artículo "Subprocedimientos en RPG IV" en este mismo número.

Si el número de parámetros es desconocido el valor devuelto es -1. El

valor devuelto por %PARMS no está disponible si al programa o

procedimiento que llama al procedimiento que ejecuta la función

%PARMS no envía un mínimo de información de la descripción

operacional. El ILE RPG/400 siempre pasa esta descripción

operacional pero otros lenguajes no pasan ninguna.

¿Algo más sobre las BIFs?

Ahora que conoce las funciones incorporadas puede comenzar a

utilizar estas nueve BIFs que IBM ha incorporado en el RPG. Puede

mirar otros lenguajes como C, CLs o Basic para ver algunas de las

posibilidades que las funciones incorporadas al ILE RPG IV ofrecen al programador.

Examine sus aplicaciones e intente ver dónde puede utilizar las BIFs

(conjuntamente con las demás novedades del RPG IV) para conseguir

que sus programas RPG sean más fáciles de mantener, más fiables, más entendibles, más eficiente y, en general, mejores.

Bryan Meyers, es director de los servicios de información de KOA y miembro del equipo de redactores técnicos internacionales de NEWS/400.

2 - Subprocedimientos en RPG IV

La introducción e implementación del RPG IV ha tenido muchas

controversias, compromisos y concesiones. A pesar de que la nueva

sintaxis del lenguaje añade muchas funciones, en la primera release

no se encontraban algunas de las más esperadas. En la parte

superior de esa hipotética lista se encontraba poder pasar

parámetros a las subrutinas. Y un poco después, la posibilidad de

definir variables locales en una subrutina, de forma que cambiar

alguna de ellas no afectara al resto del programa. Después de un año

y pico de la presentación del RPG IV, IBM ha empezado a atender

esta lista de deseos y está añadiendo nuevas funciones. Para

comenzar, ha añadido los subprocedimiento y las variables locales,

que probablemente sean dos de las funciones más

deseadas/necesarias.

La finalidad de los subprocedimientos es muy similar a la de las

subrutinas, pero existen diferencias. Las mayores diferencias entre

ambas son las siguientes:

• Se pueden pasar parámetros a los subprocedimientos.

• Con subprocedimientos se pueden definir datos y variables locales.

• Los subprocedimientos pueden devolver un valor.

• Los subprocedimientos se pueden utilizar directamente en expresiones.

Los subprocedimientos ayudan a crear código fuente modular y crear

"funciones incorporadas" (built-in-functions, BIF) propias para las

Page 8: 64940313 Lenguaje RPG

aplicaciones RPG. Oficialmente los subprocedimientos son una mejora

añadida al RPG IV en la V3R6, pero también estarán disponibles en la

V3R2 para los modelos CISC, por lo tanto no es necesario que se compre un nuevo AS/400 RISC para poder utilizarlos.

Procedimientos dentro de un procedimiento

Hasta ahora, los programas RPG eran programas con un sólo

procedimiento, con un sólo punto de entrada al programa. Esto

significa que solamente se podía llamar a "todo" el programa, pero no

se podía ejecutar una sola subrutina del programa. Con el nuevo

soporte de subprocedimientos, se pueden escribir programas RPG

que tengan un procedimiento principal y, opcionalmente, que tengan

uno o más subprocedimientos. A éstos se les pueden pasar

parámetros y pueden tener sus propias variables locales que no

interfieren con el resto de variables del programa. Se pueden incluir

todas las sentencias del procedimiento principal y de cada uno de los

subprocedimientos en el mismo miembro fuente o se puede tener el

código correspondiente a los subprocedimientos en otro, u otros, miembros fuentes que se compilará, o compilarán, por separado.

Desde el procedimiento principal se pueden llamar a los

subprocedimientos utilizando una sintaxis similar a la utilizada para

ejecutar las funciones incorporadas (BIF) del RPG IV. Por ejemplo

para llamar al subprocedimiento DayOfWeek puede escribir la siguiente sentencia:

EVAL WeekDay = DayOfWeek(TodaysDate)

O puede utilizar el subprocedimiento en una sentencia IF:

IF DayOfWeek(TodaysDate) > 1

Normalmente, un subprocedimiento devuelve un valor al

procedimiento principal. En el ejemplo anterior, el valor devuelto será

el número que le corresponde al día de la semana. Una función de un

subprocedimiento, sin embargo, puede actualizar una variable global

o posicionar el puntero de un archivo.Para poder entender mejor los

subprocedimientos y en qué casos se pueden utilizar, veamos un

ejemplo que convierte una subrutina RPG IV en un subprocedimiento.

La metamorfosis

Nuestra subrutina ejemplo convierte una fecha en el día de la

semana correspondiente. La figura 1 muestra esta subrutina dentro

de una parte de un programa RPG IV y se ha seleccionado de un

ejemplo del artículo "Trucos de fechas en RPG IV", publicado en

este mismo número. Para ejecutarla sólo es necesario escribir una

sentencia con el código de operación EXSR y el nombre de la

subrutina. La figura 2 muestra la misma subrutina escrita como un

subprocedimiento que devuelve un valor numérico que representa el

día de la semana (1=Domingo, 2=Lunes, etc.). Para ejecutar este

subprocedimiento debe utilizarse el mismo tipo de llamada que se

utiliza con las nuevas BIF (funciones incorporadas o built-in-

Page 9: 64940313 Lenguaje RPG

functions). A primera vista, las sentencias de la figura 2 parecen ser

las de un programa normal en RPG IV, sin embargo, cuando se mira

con profundidad aparecen las diferencias entre la subrutina y el

subprocedimiento. Para empezar, aparece la nueva especificación

tipo "P" (de procedimiento) que define el comienzo y el final del

subprocedimiento. La especificación P contiene sólo el nombre del

procedimiento y una letra B si se está definiendo el inicio del

procedimiento o una E si se define el final. Digamos que la sentencia

que contiene la B es equivalente al código de operación BEGSR en la subrutina y la que contiene la E es equivalente a ENDSR.

Después de la especificación P se define la interfase de

procedimiento (PI), que es similar a la lista de parámetros *ENTRY.

Para definir el PI se utilizan las especificaciones D y se debe indicar PI

como tipo de estructura en las columnas 24 y 25. En la misma línea

también se puede definir la longitud, el tipo de datos y las posiciones

decimales del valor que será devuelto, en este ejemplo el campo es

de un dígito empaquetado con cero posiciones decimales. Los campos

siguientes definen los parámetros que son pasados al procedimiento, en el ejemplo de la figura 2 el campo pasado es DateIn.

A continuación se colocan las especificaciones D que definen las

variables locales que necesita el subprocedimiento. Como estas

variables son definidas dentro de los limites del subprocedimiento,

son variables locales especificas para él. Si otro procedimiento en el

programa (incluido el procedimiento principal) define un campo con el

mismo nombre, por ejemplo el campo DayNbr, ambos campos

representarán variables distintas. El sistema no conserva los valores

de las variables locales en las distintas llamadas a un procedimiento.

Si esto ocurre varias veces, los valores de las variables locales de una

llamada anterior, no se conservan en la siguiente llamada.

Las sentencias C de la figura 2 son concisas. Es importante señalar

que se ha incluido el código de operación RETURN con una nueva

función. No solamente es una forma de finalizar el subprocedimiento

sino que también indica el nombre de la variable cuyo valor será

devuelto al programa que ha llamado al subprocedimiento. En este caso, se devuelve el valor de DayNbr.

El código de operación RETURN puede devolver el valor de una

variable (como en la figura 2) y también el resultado de una

expresión de formato libre (como por ejemplo, DayNbr + 2). Un

subprocedimiento puede tener más de un código de operación

RETURN, pero sólo se puede devolver un valor. Por lo tanto, las sentencias de la figura 2 se pueden escribir de la siguiente forma:

IF DayNbr < 1

RETURN DayNbr + 7

ELSE

Page 10: 64940313 Lenguaje RPG

RETURN DayNbr

ENDIF

Cuando se ejecuta una operación RETURN el subprocedimiento

finaliza, tanto si devuelve el valor de una variable como si devuelve el resultado de un cálculo.

Esto es prototípico

Antes de que pueda utilizar un subprocedimiento en un programa hay

un concepto más que debe entender: la definición prototipo . Una

definición prototipo es una lista de los parámetros de los

subprocedimientos en orden, describiendo el tipo de datos del valor

devuelto y el tipo de datos de los parámetros que se envían. Los

prototipos suministran una verificación de seguridad entre

procedimientos y subprocedimientos, permitiendo que el compilador

compruebe si la llamada al subprocedimiento es correcta. Sin la

definición prototipo podrían crearse misteriosos errores de programas

causados por pasar datos inválidos a un subprocedimiento o asumiendo tipos de datos devueltos incorrectamente.

Los prototipos aparecen, normalmente, en el procedimiento principal

de un programa que utiliza subprocedimientos. Cada procedimiento

utilizado por un programa tiene su propia definición prototipo que

tiene, usualmente, el mismo formato que el PI. La figura 3 muestra

la definición prototipo para el subprocedimiento DayofWeek del

ejemplo. Se puede ver que el tipo de estructura, en las columnas 24

y 25, es PR y aparece junto con el nombre del subprocedimiento en

la primera línea de la definición prototipo. La definición de la figura 3

también indica que cada vez que el programa llame al

subprocedimiento DayofWeek, el programa debe pasar una variable

de fecha y debe esperar que la devolución de un número empaquetado de 1 byte.

A pesar de que es una practica habitual en muchos lenguajes utilizar

el mismo nombre de variable que utiliza el subprocedimiento, no es

algo obligatorio. Los nombres de variables aparecen en la lista de

parámetros del prototipo pero se puede utilizar cualquier nombre de variable e incluso no utilizar ninguno.

Normalmente se copia la definición prototipo en el programa que

utiliza el subprocedimiento. De hecho se pueden agrupar todas las

definiciones prototipo de todos los subprocedimientos en un miembro

fuente y luego copiar el miembro en los programas. El compilador

pasa por alto los prototipos no referenciados en el código. Para no

tener que escribirlas varias veces en distintos programas, y evitar los

posibles errores, se puede utilizar /COPY para copiar las diferentes definiciones prototipo.

Además de copiar el prototipo en los programas que llaman a los

subprocedimientos, debería incluir el prototipo en el fuente que

contiene los subprocedimientos. Esto permite al compilador asegurar

Page 11: 64940313 Lenguaje RPG

que el prototipo que utilizará en sus programas coincide con el

subprocedimiento que está definiendo. Cuando se compila el

subprocedimiento, el compilador indicará cualquier diferencia en las longitudes y los tipos de datos.

Se puede utilizar esta capacidad de los prototipos para asegurar que

son correctos la cantidad y tipo de parámetros pasados cuando se

utiliza RPG para llamar un programa o un subprocedimiento hecho en

cualquier lenguaje ILE, esto incluye todas las APIs para ILE (con la

condición de que el RPG soporte los mismo tipos de datos que utiliza

la API). Si se utiliza un prototipo para definir los parámetros, se

puede llamar al programa (o a la API) con la misma sintaxis que se utiliza para ejecutar las funciones incorporadas.

También se pueden utilizar los prototipos con el nuevo código de

operación CALLP (Llamar subprocedimiento), en lugar de utilizar el

subprocedimiento en una sentencia EVAL o IF, para llamar a

subprocedimientos o subprogramas que no devuelven un valor. La

operación CALLP permite especificar los parámetros en formato libre y tiene la siguiente sintaxis:

CALLP Prototype(Parm1:Parm2: ... :ParmN)

La última palabra en subprocedimientos

Probablemente ya estará pensando en las diferentes formas de

incorporar subprocedimientos en sus programas. Puede utilizarlos

para crear su propio conjunto de herramientas y luego las podrá

incluir en sus aplicaciones fácilmente, sin tener que preocuparse de

posibles conflictos con los nombres de campo o con los indicadores. Y

por supuesto, también puede utilizarlos para crear funciones que se salgan del estándar suministrado por IBM en el RPG.

Los subprocedimientos pueden crear una industria totalmente nueva

en el mundo del RPG: podrán suministrar juegos de herramientas

especializados para que aquellas instalaciones de AS/400 con pocos

medios técnicos, puedan armar en aplicaciones completas. Aunque

esta industria nunca pueda competir con el mercado de custom

controls VBX del Visual Basic, los componentes pueden ser un buen

negocio para muchos suministradores de software y cambiar la forma en que se compran las aplicaciones para el AS/400.

Bryan Meyers , es director de los servicios de información de KOA y miembro del equipo de redactores técnicos internacionales de NEWS/400. Jon Paris, con más de 20 años de experiencia en proceso de datos, actualmente es asesor de desarrollos en los Laboratorios de IBM Toronto.

© Publicaciones HELP400, S.L. (Todos los derechos reservados)

Page 12: 64940313 Lenguaje RPG

help400.es

Información técnica y de gestión para IBM i

- AS/400

Acceda al Sumario de

cualquier número

Número (y pulse INTRO)

Actualizado el 31 Julio 2011

1024 x 768

de resolución

MENU de OPCIONES

RPG IV %BIFs

Page 13: 64940313 Lenguaje RPG

funciones incorporadas en Lenguaje IBM RPG IV

información provisional

RPG es un Lenguaje de Programación de IBM, principalmente usado en su plataforma intermedia, y con una historia de 40 años, en los cuales ha tenido incontables mejoras sucesivas hasta alcanzar hoy dia la version RPG IV (tambien llamado ILE), que incluye un formato de escritura libre denominado rpg-free y contando con un montón de funciones incorporadas denominadas %bif.

En la página RPG hay algunos enlaces interesantes de IBM

Los %bif son funciones incorporadas dentro del lenguaje para hacerlo más poderoso. Por ejemplo:

Alfa = %trim(PgmName); la funcion %trim elimina los blancos

Alfa = %edit(Saldo:'J'); edita el campo Saldo con el codigo de edicion J

Alfa = %trim(%edit(Saldo:'J')); ya que al editar un campo quizá queden espacios en blanco, la %trim anidada los quita

Hay un montón de funciones %bif, creciendo con cada versión del Operativo y del Lenguaje...

%mseconds, %seconds, %minutes, %hours, %days, %months y %years

%DIFF, para restar un valor de fecha, hora o indicación de la hora de otro

Funciones para convertir una serie de caracteres (o fecha o indicación de la hora) en una fecha, hora o indicación de la hora: %DATE, %TIME y %TIMESTAMP.

La función %SUBDT, para extraer un subconjunto de una fecha, hora o indicación de la hora

– Funciones para asignar o reasignar almacenamiento: %ALLOC y %REALLOC.

– Funciones para buscar un elemento en una matriz: %LOOKUP, %LOOKUPGT, %LOOKUPGE, %LOOKUPLT y %LOOKUPLE.

– Funciones para buscar un elemento en una tabla: %TLOOKUP, %TLOOKUPGT, %TLOOKUPGE, %TLOOKUPLT y %TLOOKUPLE.

Page 14: 64940313 Lenguaje RPG

– Funciones para verificar que una serie contenga sólo los caracteres especificados (o buscar la primera o última excepción a esta norma): %CHECK y %CHECKR

– La función %XLATE, para convertir una serie a partir de una lista de caracteres origen en caracteres destino.

– La función %OCCUR, para obtener o establecer la aparición actual de una estructura de datos de apariciones múltiples.

– La función %SHTDN, para determinar si el operador ha solicitado la conclusión.

– La función %SQRT, para calcular la raíz cuadrada de un número.

%SCAN

La función incorporada %PADDR ahora puede tomar un nombre de prototipo o un nombre de punto de entrada como argumento

Direct conversion of date/time/timestamp to numeric, using %DEC:

%DEC is enhanced (v5r3) to allow the first parameter to be a date, time or timestamp, and the optional second parameter to specify the format of the resulting numeric value.

Example:

D numDdMmYy s 6p 0

D date s d datfmt(*jul)

date = D'2003-08-21';

numDdMmYy = %dec(date : *dmy);

// now numDdMmYy = 210803

Conversion from character to numeric

Built-in functions %DEC, %DECH, %INT, %INTH, %UNS, %UNSH and %FLOAT are enhanced to allow character parameters. For example, %DEC('-12345.67' : 7 : 2) returns the numeric value -12345.67.

---

New assignment operators

Page 15: 64940313 Lenguaje RPG

The new assignment operators +=, -=, *=, /=, **= allow a variable to be modified based on its old value in a more concise manner.

Example: totals(current_customer) += count;

This statement adds "count" to the value currently in "totals(current_customer)" without having to code "totals(current_customer)" twice

----

%KDS(data structure) Used in free-form keyed operation codes CHAIN, SETLL, SETGT, READE and READPE, to indicate that the keys for the operation are in the data structure.

Functions for verifying that a string contains only specified characters (or finding the first or last exception to this rule): %CHECK and %CHECKR

The %XLATE function, for translating a string based on a list of from-characters and to-characters.

The %OCCUR function, for getting or setting the current occurrence in a multiple-occurrence data structure.

The %SHTDN function, for determining if the operator has requested shutdown

%XFOOT built-in function sums all elements of a specified array expression

EVALR operation code evaluates expressions and assigns the result to a fixed-length character or graphic result. The assignment right-adjusts the data within the result.

The new FOR operation code performs an iterative loop and allows free-form expressions for the initial, increment, and limit values.

The new LEAVESR operation code can be used to exit from any point within a subroutine.

The new *NEXT parameter on the OVERLAY(name:*NEXT) keyword indicates that a subfield overlays another subfield at the next available position.

The new *START and *END values for the SETLL operation code position to the beginning or end of the file.

Built-in functions %EOF, %EQUAL, %FOUND, and %OPEN have been added to query the results of input/output operations. Built-in functions %ERROR and

Page 16: 64940313 Lenguaje RPG

%STATUS, and the operation code extender 'E' have been added for error handling.

Built-in functions %CHAR and %REPLACE have been added to make string manipulation easier

New support for externally defined *CMDY, *CDMY, and *LONGJUL date data formats

Built-in functions %CHAR(graphic, date, time or timestamp expression) Returns the value in a character data type.

%EOF{file name} Returns '1' if the most recent file input operation or write to a subfile (for a particular file, if specified) ended in an end-of-file or beginning-of-file condition; otherwise, it returns '0'.

%EQUAL{file name} Returns '1' if the most recent SETLL (for a particular file, if specified) or LOOKUP operation found an exact match; otherwise, it returns '0'.

%ERROR Returns '1' if the most recent operation code with extender 'E' specified resulted in an error; otherwise, it returns '0'.

%FOUND{file name} Returns '1' if the most recent relevant operation (for a particular file, if specified) found a record (CHAIN, DELETE, SETGT, SETLL), an element (LOOKUP), or a match (CHECK, CHECKR and SCAN); otherwise, it returns '0'.

%OPEN(file name) Returns '1' if the specified file is open and '0' if the specified file is closed.

%REPLACE(replacement string: source string {:start position {:source length to replace}}) Returns the string produced by inserting a replacement string into a source string, starting at the start position and replacing the specified number of characters.

%STATUS{file name} If no program or file error occurred since the most recent operation code with extender 'E' specified, it returns 0. If an error occurred, it returns the most recent value set for any program or file status. If a file is specified, the value returned is the most recent status for that file.

Operation code Extender E Allows for error handling using the %ERROR and %STATUS built-in functions on the CALLP operation and all operations that allow error indicators.

Page 17: 64940313 Lenguaje RPG

New century formats *CMDY (cmm/dd/yy) To be used by the MOVE, MOVEL, and TEST operations.

*CDMY (cdd/mm/yy) To be used by the MOVE, MOVEL, and TEST operations.

New 4-digit year format *LONGJUL (yyyy/ddd) To be used by the MOVE, MOVEL, and TEST operations.

editing (%EDITW, %EDITC, %EDITFLT)

scanning strings (%SCAN)

type conversions (%INT, %FLOAT, %DEC, %UNS)

type conversions with half-adjust (%INTH, %DECH, %UNSH)

precision of intermediate results for decimal expressions (%DEC)

length and decimals of variables and expressions (%LEN, %DECPOS)

absolute value (%ABS)

set and test null-capable fields (%NULLIND)

handle null terminated strings (%STR)