El modelo de compilacion moderno de IBM i: modulos, service programs, binding directories, activation groups, prototipos, binder language y la migracion desde OPM.
ILE (Integrated Language Environment) es el modelo de compilacion y ejecucion moderno de IBM i, introducido con OS/400 V3R1 en 1994. Reemplaza al modelo OPM (Original Program Model) y permite crear programas a partir de multiples modulos compilados independientemente, escritos potencialmente en distintos lenguajes (RPG, COBOL, C, CL). Es el equivalente conceptual a compilar archivos .o y enlazarlos con un linker en C/C++, o empaquetar clases en un JAR en Java.
OPM (Original Program Model)
ILE (Integrated Language Environment)
La cadena de compilacion ILE
Fuente
QRPGLESRC
QCLSRC
Modulo
*MODULE
CRTRPGMOD
Programa
*PGM o *SRVPGM
CRTPGM / CRTSRVPGM
Un modulo (*MODULE) es el resultado de compilar un fuente individual. No es ejecutable por si solo. Un programa (*PGM) se crea enlazando uno o mas modulos con CRTPGM. Es como compilar archivos .c en .o y luego enlazarlos en un ejecutable con gcc.
/* Crear modulo desde fuente RPG */
CRTRPGMOD MODULE(MILIB/UTILSTR)
SRCFILE(MILIB/QRPGLESRC)
SRCMBR(UTILSTR)
DBGVIEW(*SOURCE)
OPTION(*SRCSTMT *NODEBUGIO)
/* Crear modulo desde fuente CL */
CRTCLMOD MODULE(MILIB/UTILCL)
SRCFILE(MILIB/QCLSRC)
SRCMBR(UTILCL)
DBGVIEW(*SOURCE)
/* Crear modulo desde fuente C */
CRTCMOD MODULE(MILIB/UTILC)
SRCFILE(MILIB/QCSRC)
DBGVIEW(*SOURCE)
/* Crear modulo SQLRPGLE */
CRTSQLRPGI OBJ(MILIB/UTILSQL)
SRCFILE(MILIB/QRPGLESRC)
OBJTYPE(*MODULE)
DBGVIEW(*SOURCE)
COMMIT(*NONE)
/* Listar modulos existentes */
WRKOBJ OBJ(MILIB/*ALL) OBJTYPE(*MODULE)/* Programa simple: un solo modulo */
CRTPGM PGM(MILIB/MIPGM)
MODULE(MILIB/MIPGM)
ACTGRP(*CALLER)
/* Programa con multiples modulos */
/* El primer modulo contiene el entry point (PEP) */
CRTPGM PGM(MILIB/GESTCLI)
MODULE(MILIB/GESTCLI +
MILIB/UTILSTR +
MILIB/UTILFECHA +
MILIB/VALIDA)
ACTGRP(*CALLER)
DETAIL(*FULL)
/* Programa enlazado a modulos y service programs */
CRTPGM PGM(MILIB/GESTCLI)
MODULE(MILIB/GESTCLI)
BNDSRVPGM(MILIB/UTILITARIOS +
MILIB/VALIDACION)
ACTGRP(*CALLER)
/* Shortcut: CRTBNDRPG = CRTRPGMOD + CRTPGM en un paso */
CRTBNDRPG PGM(MILIB/SIMPLE)
SRCFILE(MILIB/QRPGLESRC)
DBGVIEW(*SOURCE)
DFTACTGRP(*NO)
ACTGRP(*CALLER)gcc -o programa fuente.c y los dos pasos como gcc -c fuente.c + gcc -o programa fuente.o.Un service program (*SRVPGM) es una coleccion de procedimientos reutilizables que multiples programas pueden compartir. Es el equivalente directo de una shared library (.so en Linux, .dll en Windows) o un package/JAR en Java. Los procedimientos se ejecutan dentro del espacio de activacion del programa llamador, sin el overhead de un CALL externo.
**free
// ---------------------------------------------------------------
// UTILSTR: Service program de utilidades de string
// Exporta procedimientos reutilizables
// ---------------------------------------------------------------
ctl-opt nomain; // Sin mainline: solo exporta procedimientos
// ---------------------------------------------------------------
// toUpper: convierte string a mayusculas
// ---------------------------------------------------------------
dcl-proc toUpper export;
dcl-pi *n varchar(1000);
texto varchar(1000) const;
end-pi;
dcl-s resultado varchar(1000);
exec sql
SET :resultado = UPPER(:texto);
return resultado;
end-proc;
// ---------------------------------------------------------------
// toLower: convierte string a minusculas
// ---------------------------------------------------------------
dcl-proc toLower export;
dcl-pi *n varchar(1000);
texto varchar(1000) const;
end-pi;
dcl-s resultado varchar(1000);
exec sql
SET :resultado = LOWER(:texto);
return resultado;
end-proc;
// ---------------------------------------------------------------
// contiene: busca substring (retorna *on/*off)
// ---------------------------------------------------------------
dcl-proc contiene export;
dcl-pi *n ind;
texto varchar(1000) const;
buscar varchar(100) const;
end-pi;
return %scan(buscar : texto) > 0;
end-proc;
// ---------------------------------------------------------------
// padLeft: rellena a la izquierda con un caracter
// ---------------------------------------------------------------
dcl-proc padLeft export;
dcl-pi *n varchar(1000);
texto varchar(1000) const;
largo int(10) const;
relleno char(1) const options(*nopass);
end-pi;
dcl-s car char(1) inz('0');
dcl-s resultado varchar(1000);
dcl-s faltan int(10);
if %parms >= 3;
car = relleno;
endif;
faltan = largo - %len(%trim(texto));
if faltan <= 0;
return texto;
endif;
resultado = '';
for i = 1 to faltan;
resultado += car;
endfor;
resultado += %trim(texto);
return resultado;
end-proc;/* Paso 1: Compilar como modulo */
CRTSQLRPGI OBJ(MILIB/UTILSTR)
SRCFILE(MILIB/QRPGLESRC)
SRCMBR(UTILSTR)
OBJTYPE(*MODULE)
DBGVIEW(*SOURCE)
COMMIT(*NONE)
/* Paso 2: Crear service program */
CRTSRVPGM SRVPGM(MILIB/UTILSTR)
MODULE(MILIB/UTILSTR)
EXPORT(*ALL)
ACTGRP(*CALLER)
/* Con binder language (mejor control de exports) */
CRTSRVPGM SRVPGM(MILIB/UTILSTR)
MODULE(MILIB/UTILSTR)
SRCFILE(MILIB/QSRVSRC)
SRCMBR(UTILSTR)
ACTGRP(*CALLER)
/* Service program con multiples modulos */
CRTSRVPGM SRVPGM(MILIB/UTILITARIOS)
MODULE(MILIB/UTILSTR +
MILIB/UTILFECHA +
MILIB/UTILNUM)
EXPORT(*ALL)
ACTGRP(*CALLER)**free
// Programa que usa procedimientos del service program UTILSTR
ctl-opt dftactgrp(*no) actgrp(*caller);
ctl-opt bnddir('MILIB/MYBNDDIR');
// Prototipos de los procedimientos exportados
dcl-pr toUpper varchar(1000) extproc('TOUPPER');
texto varchar(1000) const;
end-pr;
dcl-pr toLower varchar(1000) extproc('TOLOWER');
texto varchar(1000) const;
end-pr;
dcl-pr contiene ind extproc('CONTIENE');
texto varchar(1000) const;
buscar varchar(100) const;
end-pr;
dcl-pr padLeft varchar(1000) extproc('PADLEFT');
texto varchar(1000) const;
largo int(10) const;
relleno char(1) const options(*nopass);
end-pr;
// Uso directo (llamada bound, sin CALL overhead)
dcl-s nombre varchar(100);
dcl-s codigo varchar(10);
nombre = toUpper('fernando secchi');
// nombre = 'FERNANDO SECCHI'
codigo = padLeft('42' : 7 : '0');
// codigo = '0000042'
if contiene(nombre : 'SECCHI');
dsply 'Apellido encontrado';
endif;
*inlr = *on;
return;Un binding directory (*BNDDIR) es una lista de modulos y service programs que el enlazador (binder) busca automaticamente al crear un programa. Es el equivalente a los paths de libreria ( -L en gcc) o las dependencias en un pom.xml de Maven. En lugar de especificar cada modulo y service program manualmente en CRTPGM, los agrupos en un binding directory.
/* Crear binding directory */
CRTBNDDIR BNDDIR(MILIB/MYBNDDIR)
TEXT('Utilidades de la aplicacion')
/* Agregar service programs al binding directory */
ADDBNDDIRE BNDDIR(MILIB/MYBNDDIR)
OBJ((MILIB/UTILSTR *SRVPGM) +
(MILIB/UTILFECHA *SRVPGM) +
(MILIB/VALIDACION *SRVPGM))
/* Agregar modulos individuales tambien */
ADDBNDDIRE BNDDIR(MILIB/MYBNDDIR)
OBJ((MILIB/ERRHANDLER *MODULE))
/* Ver contenido de un binding directory */
DSPBNDDIR BNDDIR(MILIB/MYBNDDIR)
/* Remover entrada del binding directory */
RMVBNDDIRE BNDDIR(MILIB/MYBNDDIR)
OBJ((MILIB/UTILSTR *SRVPGM))**free
// El CTL-OPT referencia el binding directory
// El binder resuelve automaticamente los procedimientos
ctl-opt dftactgrp(*no) actgrp(*caller);
ctl-opt bnddir('MILIB/MYBNDDIR');
// Ahora puedo usar procedimientos de UTILSTR, UTILFECHA,
// VALIDACION sin especificarlos manualmente en CRTPGM
dcl-pr toUpper varchar(1000) extproc('TOUPPER');
texto varchar(1000) const;
end-pr;
dcl-pr formatFecha varchar(10) extproc('FORMATFECHA');
fecha date(*iso) const;
formato char(10) const;
end-pr;
dcl-pr validarCUIT ind extproc('VALIDARCUIT');
cuit varchar(13) const;
end-pr;
// Uso transparente
dcl-s nombre varchar(100);
nombre = toUpper('test');
dcl-s fechaStr varchar(10);
fechaStr = formatFecha(%date() : 'DD/MM/YYYY');
if validarCUIT('20-12345678-9');
dsply 'CUIT valido';
endif;/* El BNDDIR en el CTL-OPT hace que CRTBNDRPG busque ahi */
CRTBNDRPG PGM(MILIB/MIPGM)
SRCFILE(MILIB/QRPGLESRC)
DBGVIEW(*SOURCE)
DFTACTGRP(*NO)
ACTGRP(*CALLER)
/* Alternativa: especificar BNDDIR en el comando */
CRTBNDRPG PGM(MILIB/MIPGM)
SRCFILE(MILIB/QRPGLESRC)
BNDDIR(MILIB/MYBNDDIR)
DFTACTGRP(*NO)
/* Con dos pasos (modulo + programa) */
CRTRPGMOD MODULE(MILIB/MIPGM)
SRCFILE(MILIB/QRPGLESRC)
DBGVIEW(*SOURCE)
CRTPGM PGM(MILIB/MIPGM)
MODULE(MILIB/MIPGM)
BNDDIR(MILIB/MYBNDDIR)
ACTGRP(*CALLER)Un activation group es un contexto de ejecucion aislado dentro de un job. Controla el scope de recursos compartidos: archivos abiertos, commitment control, variables estaticas y manejo de errores. Es conceptualmente similar a un application domain en .NET o un class loader en Java: define los limites de aislamiento entre componentes.
*NEWCrea un AG nuevo cada vez que se activa el programaProgramas totalmente aislados, sin estado compartido*CALLERUsa el AG del programa que lo llamaRecomendado para la mayoria de programas y SRVPGMNombre fijoUsa un AG con el nombre dado (se crea si no existe)Agrupar programas que comparten archivos y commitQILEAG default del sistema para programas ILEUsado cuando no se especifica (legacy)*DFTACTGRPAG default para OPM (compatibilidad)Solo para programas OPM, no usar en ILE nuevo**free
// Recomendado: *CALLER (comparte AG con el llamador)
ctl-opt dftactgrp(*no) actgrp(*caller);
// Programa aislado: *NEW (AG propio cada vez)
ctl-opt dftactgrp(*no) actgrp(*new);
// AG nombrado: agrupa programas relacionados
ctl-opt dftactgrp(*no) actgrp('MIAPP');
// IMPORTANTE: dftactgrp(*no) es OBLIGATORIO para ILE
// Si usas dftactgrp(*yes), el programa corre en el
// default activation group OPM y pierde beneficios ILE/* Recuperar AG actual desde RPG via RTVJOBA */
RTVJOBA ACTGRP(&ACTGRP)
/* Reclamar (destruir) un AG por nombre */
RCLACTGRP ACTGRP('MIAPP')
/* Reclamar todos los AG elegibles */
RCLACTGRP ACTGRP(*ELIGIBLE)ACTGRP(*CALLER) para el 90% de tus programas y service programs. Solo usa *NEW cuando necesitas aislamiento total (ej: un programa que podria fallar y no quieres que afecte al llamador). Usa un AG nombrado cuando necesitas que multiples programas compartan archivos abiertos y commitment control.Los prototipos (DCL-PR) declaran la interfaz de un procedimiento o programa externo: su nombre, parametros y tipo de retorno. La procedure interface (DCL-PI) define los parametros que recibe el procedimiento actual. Son como los header files (.h) en C o las interfaces en Java: permiten al compilador verificar tipos en tiempo de compilacion.
// Prototipo para un PROGRAMA externo (CALL)
dcl-pr enviarEmail extpgm('MILIB/SNDMAIL');
destinatario varchar(200) const;
asunto varchar(100) const;
cuerpo varchar(5000) const;
end-pr;
// Prototipo para un PROCEDIMIENTO en service program
dcl-pr toUpper varchar(1000) extproc('TOUPPER');
texto varchar(1000) const;
end-pr;
// Prototipo para API del sistema (C function)
dcl-pr sleep int(10) extproc('sleep');
segundos int(10) value;
end-pr;
// Prototipo con parametros opcionales
dcl-pr log extproc('LOG');
mensaje varchar(500) const;
nivel char(10) const options(*nopass);
programa char(10) const options(*nopass);
end-pr;
// Prototipo con LIKEDS (estructura como parametro)
dcl-ds clienteT qualified template;
id packed(7:0);
nombre varchar(100);
email varchar(200);
end-ds;
dcl-pr grabarCliente extproc('GRABARCLIENTE');
cliente likeds(clienteT) const;
end-pr;// En el service program: procedimiento exportado
dcl-proc calcularDescuento export;
// Procedure interface: define parametros y retorno
dcl-pi *n packed(11:2);
monto packed(11:2) const; // CONST = por valor
porcentaje packed(5:2) const;
aplicarIVA ind const options(*nopass);
end-pi;
dcl-s resultado packed(11:2);
dcl-s conIVA ind inz(*off);
// Verificar parametro opcional
if %parms >= 3;
conIVA = aplicarIVA;
endif;
resultado = monto * (porcentaje / 100);
if conIVA;
resultado *= 1.21; // IVA 21%
endif;
return resultado;
end-proc;
// Procedimiento interno (NO exportado, privado al modulo)
dcl-proc validarPorcentaje;
dcl-pi *n ind;
pct packed(5:2) const;
end-pi;
return (pct >= 0 and pct <= 100);
end-proc;CONSTParametro por valor (no modificable). Recomendado por defecto.
VALUEPasa por valor (copia). Para APIs C y funciones.
OPTIONS(*NOPASS)Parametro opcional. Verificar con %PARMS.
OPTIONS(*OMIT)Se puede pasar *OMIT. Verificar con %ADDR.
EXTPGM('nombre')El target es un programa (*PGM) externo.
EXTPROC('nombre')El target es un procedimiento (en SRVPGM).
LIKEDS(template)Parametro con estructura de una DS template.
DIM(n)Parametro es un array de n elementos.
El binder language es un fuente que define explicitamente que procedimientos y variables exporta un service program. Sin binder language, se usa EXPORT(*ALL) que exporta todo. Con binder language se tiene control fino y se puede evolucionar la interfaz sin romper programas existentes. Es el equivalente a un archivo .def de exports en Windows o un version script en Linux.
/* ================================================== */
/* Binder language para service program UTILSTR */
/* Fuente: MILIB/QSRVSRC miembro UTILSTR */
/* ================================================== */
STRPGMEXP PGMLVL(*CURRENT) SIGNATURE('UTILSTR_V2')
/* Procedimientos exportados (interface publica) */
EXPORT SYMBOL('TOUPPER')
EXPORT SYMBOL('TOLOWER')
EXPORT SYMBOL('CONTIENE')
EXPORT SYMBOL('PADLEFT')
/* V2: nuevos procedimientos agregados */
EXPORT SYMBOL('TRIM_ALL')
EXPORT SYMBOL('REPLACE')
ENDPGMEXP
/* Signature anterior para compatibilidad */
STRPGMEXP PGMLVL(*PRV) SIGNATURE('UTILSTR_V1')
EXPORT SYMBOL('TOUPPER')
EXPORT SYMBOL('TOLOWER')
EXPORT SYMBOL('CONTIENE')
EXPORT SYMBOL('PADLEFT')
ENDPGMEXP/* Crear service program usando binder language */
CRTSRVPGM SRVPGM(MILIB/UTILSTR)
MODULE(MILIB/UTILSTR)
SRCFILE(MILIB/QSRVSRC)
SRCMBR(UTILSTR)
ACTGRP(*CALLER)
/* El binder language controla:
1. Que procedimientos son visibles externamente
2. La signature (version) del service program
3. Compatibilidad con versiones anteriores (PGMLVL(*PRV))
Cuando agregas nuevos procedimientos:
1. La CURRENT signature cambia (ej: V1 -> V2)
2. La V1 se convierte en *PRV (compatible)
3. Programas viejos siguen funcionando con V1
4. Programas nuevos compilados usan V2 */El depurador de IBM i soporta depuracion de programas ILE compuestos por multiples modulos, incluyendo modulos de distintos lenguajes (RPG, CL, C). Los programas y service programs deben compilarse con DBGVIEW(*SOURCE) o DBGVIEW(*ALL).
/* Iniciar debug de un programa ILE */
STRDBG PGM(MILIB/GESTCLI)
UPDPROD(*YES) /* Permitir cambios en prod */
/* Agregar service program al debug (si no se agrego auto) */
/* Desde la pantalla de debug: */
/* ADDPGM SRVPGM(MILIB/UTILSTR) */
/* Debug con multiples programas */
STRDBG PGM(MILIB/GESTCLI MILIB/VALIDA)
/* Teclas del depurador ILE: */
/* F5 = Reanudar ejecucion */
/* F6 = Agregar breakpoint */
/* F10 = Step over */
/* F11 = Step into (entrar al proc) */
/* F22 = Step out (salir del proc) */
/* F17 = Watch (monitorear variable) */
/* Desde linea de comandos del depurador: */
/* EVAL wkNombre Ver variable */
/* EVAL clienteDS Ver data structure */
/* EVAL clienteDS.saldo Ver campo de DS */
/* EVAL wkNombre = 'TEST' Modificar valor */
/* EVAL *IN50 Ver indicador */
/* BREAK 45 Breakpoint linea 45*/
/* BREAK calcular BP en procedimiento*/
/* CLEAR 45 Quitar breakpoint */
/* WATCH wkSaldo Monitorear cambios */
/* Terminar debug */
ENDDBG/* Opciones de DBGVIEW al compilar: */
/* *SOURCE: ve el fuente original (recomendado) */
CRTRPGMOD MODULE(MILIB/MIPGM) SRCFILE(MILIB/QRPGLESRC) +
DBGVIEW(*SOURCE)
/* *LIST: ve el listing (fuente expandido) */
CRTRPGMOD MODULE(MILIB/MIPGM) SRCFILE(MILIB/QRPGLESRC) +
DBGVIEW(*LIST)
/* *ALL: ve fuente original + listing */
CRTRPGMOD MODULE(MILIB/MIPGM) SRCFILE(MILIB/QRPGLESRC) +
DBGVIEW(*ALL)
/* *STMT: solo breakpoints por numero de sentencia */
CRTRPGMOD MODULE(MILIB/MIPGM) SRCFILE(MILIB/QRPGLESRC) +
DBGVIEW(*STMT)
/* *NONE: sin debug info (produccion final) */
CRTRPGMOD MODULE(MILIB/MIPGM) SRCFILE(MILIB/QRPGLESRC) +
DBGVIEW(*NONE)
/* Tip: para SQLRPGLE, usa DBGVIEW(*SOURCE) */
/* y el debug muestra el fuente RPG original, */
/* no el fuente expandido por el precompilador SQL */Migrar de OPM a ILE no requiere reescribir codigo. La estrategia recomendada es incremental: primero recompilar los programas existentes como ILE, luego gradualmente extraer logica comun en service programs.
Programa OPM (antes)
Programa ILE (despues)
/* ================================================ */
/* PASO 1: Recompilar programas como ILE */
/* (cambio minimo, maximo beneficio) */
/* ================================================ */
/* ANTES (OPM): */
CRTCLPGM PGM(MILIB/MIPGMCL) SRCFILE(MILIB/QCLSRC)
/* AHORA (ILE): agregar DFTACTGRP(*NO) al fuente
y compilar con CRTBNDCL */
CRTBNDCL PGM(MILIB/MIPGMCL) SRCFILE(MILIB/QCLSRC) +
DFTACTGRP(*NO) ACTGRP(*CALLER) +
DBGVIEW(*SOURCE)
/* Para RPG: */
/* ANTES: CRTRPGPGM */
/* AHORA: CRTBNDRPG con DFTACTGRP(*NO) */
/* Agregar **free y ctl-opt dftactgrp(*no) al fuente */
/* ================================================ */
/* PASO 2: Identificar logica comun */
/* Buscar programas que hacen CALL a rutinas */
/* de utilidad compartida */
/* ================================================ */
/* Candidatos a service program: */
/* - Validaciones compartidas */
/* - Formateo de strings y fechas */
/* - Acceso a tablas comunes */
/* - Calculo de impuestos, descuentos */
/* ================================================ */
/* PASO 3: Extraer a service programs */
/* ================================================ */
/* 1. Mover subprocedimientos a fuente separado */
/* 2. Agregar EXPORT a los procedimientos */
/* 3. Agregar CTL-OPT NOMAIN al fuente */
/* 4. Compilar como *MODULE: CRTRPGMOD */
/* 5. Crear *SRVPGM: CRTSRVPGM */
/* 6. Crear binding directory con el SRVPGM */
/* 7. Actualizar programas consumidores: */
/* - Agregar prototipos (DCL-PR) */
/* - Agregar BNDDIR al CTL-OPT */
/* - Reemplazar CALL externo por llamada */
/* directa al procedimiento */
/* ================================================ */
/* PASO 4: Crear binding directory */
/* ================================================ */
CRTBNDDIR BNDDIR(MILIB/APPBNDDIR)
ADDBNDDIRE BNDDIR(MILIB/APPBNDDIR) +
OBJ((MILIB/UTILSTR *SRVPGM) +
(MILIB/UTILFECHA *SRVPGM) +
(MILIB/VALIDA *SRVPGM))Los siguientes son patrones arquitectonicos que se repiten en aplicaciones IBM i bien estructuradas usando el modelo ILE.
Patron: Aplicacion en capas con ILE
Capa de presentacion
Programas *PGM con display files
Reciben input del usuario
Llaman a la capa de negocio
Capa de negocio
Service programs *SRVPGM
Reglas de negocio
Validaciones y calculos
Capa de datos
Service programs *SRVPGM
CRUD sobre tablas Db2
SQL embebido
// ---------------------------------------------------------------
// UTILSTR_H: Copy book con prototipos del SRVPGM UTILSTR
// Fuente: MILIB/QRPGLESRC miembro UTILSTR_H
// Incluir con /COPY en cada programa que use UTILSTR
// ---------------------------------------------------------------
dcl-pr toUpper varchar(1000) extproc('TOUPPER');
texto varchar(1000) const;
end-pr;
dcl-pr toLower varchar(1000) extproc('TOLOWER');
texto varchar(1000) const;
end-pr;
dcl-pr contiene ind extproc('CONTIENE');
texto varchar(1000) const;
buscar varchar(100) const;
end-pr;
dcl-pr padLeft varchar(1000) extproc('PADLEFT');
texto varchar(1000) const;
largo int(10) const;
relleno char(1) const options(*nopass);
end-pr;**free
ctl-opt dftactgrp(*no) actgrp(*caller);
ctl-opt bnddir('MILIB/MYBNDDIR');
// Incluir prototipos del service program
/copy milib/qrpglesrc,utilstr_h
/copy milib/qrpglesrc,utilfec_h
/copy milib/qrpglesrc,valida_h
// Templates de data structures compartidas
/copy milib/qrpglesrc,cliente_t
/copy milib/qrpglesrc,factura_t
// Interfaz del programa
dcl-pi *n;
prmCliente packed(7:0);
end-pi;
// Uso transparente de procedimientos de service programs
dcl-s nombre varchar(100);
dcl-s valido ind;
nombre = toUpper('fernando'); // de UTILSTR
valido = validarCUIT('20-12345678-9'); // de VALIDA
dsply formatFecha(%date() : 'DD/MM'); // de UTILFEC
*inlr = *on;
return;PGM
MONMSG MSGID(CPF0000) EXEC(GOTO CMDLBL(ERROR))
/* ======================================= */
/* BUILD: Aplicacion de Gestion */
/* ======================================= */
/* --- Compilar modulos de service programs --- */
CRTSQLRPGI OBJ(MILIB/UTILSTR) SRCFILE(MILIB/QRPGLESRC) +
OBJTYPE(*MODULE) DBGVIEW(*SOURCE) COMMIT(*NONE)
CRTSQLRPGI OBJ(MILIB/UTILFECHA) SRCFILE(MILIB/QRPGLESRC) +
OBJTYPE(*MODULE) DBGVIEW(*SOURCE) COMMIT(*NONE)
CRTSQLRPGI OBJ(MILIB/VALIDACION) SRCFILE(MILIB/QRPGLESRC) +
OBJTYPE(*MODULE) DBGVIEW(*SOURCE) COMMIT(*NONE)
CRTSQLRPGI OBJ(MILIB/DATOSCLI) SRCFILE(MILIB/QRPGLESRC) +
OBJTYPE(*MODULE) DBGVIEW(*SOURCE) COMMIT(*NONE)
/* --- Crear service programs --- */
CRTSRVPGM SRVPGM(MILIB/UTILSTR) MODULE(MILIB/UTILSTR) +
SRCFILE(MILIB/QSRVSRC) ACTGRP(*CALLER)
CRTSRVPGM SRVPGM(MILIB/UTILFECHA) MODULE(MILIB/UTILFECHA) +
SRCFILE(MILIB/QSRVSRC) ACTGRP(*CALLER)
CRTSRVPGM SRVPGM(MILIB/VALIDACION) MODULE(MILIB/VALIDACION) +
SRCFILE(MILIB/QSRVSRC) ACTGRP(*CALLER)
CRTSRVPGM SRVPGM(MILIB/DATOSCLI) MODULE(MILIB/DATOSCLI) +
SRCFILE(MILIB/QSRVSRC) ACTGRP(*CALLER)
/* --- Actualizar binding directory --- */
CRTBNDDIR BNDDIR(MILIB/APPBNDDIR)
MONMSG MSGID(CPF9801) /* Ya existe */
RMVBNDDIRE BNDDIR(MILIB/APPBNDDIR) OBJ((*ALL))
MONMSG MSGID(CPF0000)
ADDBNDDIRE BNDDIR(MILIB/APPBNDDIR) +
OBJ((MILIB/UTILSTR *SRVPGM) +
(MILIB/UTILFECHA *SRVPGM) +
(MILIB/VALIDACION *SRVPGM) +
(MILIB/DATOSCLI *SRVPGM))
/* --- Compilar programas principales --- */
CRTBNDRPG PGM(MILIB/GESTCLI) SRCFILE(MILIB/QRPGLESRC) +
DBGVIEW(*SOURCE) DFTACTGRP(*NO) ACTGRP(*CALLER)
CRTBNDRPG PGM(MILIB/RPTVENTAS) SRCFILE(MILIB/QRPGLESRC) +
DBGVIEW(*SOURCE) DFTACTGRP(*NO) ACTGRP(*CALLER)
CRTBNDCL PGM(MILIB/BATCHCLI) SRCFILE(MILIB/QCLSRC) +
DBGVIEW(*SOURCE) DFTACTGRP(*NO) ACTGRP(*CALLER)
SNDPGMMSG MSG('=== BUILD completado OK ===') TOPGMQ(*EXT)
GOTO CMDLBL(FIN)
ERROR:
DCL VAR(&ERRMSG) TYPE(*CHAR) LEN(256)
RCVMSG MSGTYPE(*EXCP) MSG(&ERRMSG)
SNDPGMMSG MSG('BUILD FALLO: ' *CAT &ERRMSG) TOPGMQ(*EXT)
FIN:
ENDPGM