Mostrando entradas con la etiqueta ACCEPT. Mostrar todas las entradas
Mostrando entradas con la etiqueta ACCEPT. Mostrar todas las entradas

lunes, 21 de febrero de 2011

Ejemplo 2: leer de SYSIN y escribir en fichero.

En este ejemplo vamos a ejecutar un programa SIN DB2, que recoge información de la SYSIN del JCL del mismo modo que vimos en el ejemplo 1. La diferencia estará en que en esta ocasión vamos a escribir la información en un fichero en lugar de en la SYSOUT.

JCL:

//******************************************************
//**************************** BORRADO *****************
//BORRADO EXEC PGM=IDCAMS
//SYSPRINT DD SYSOUT=*
//SYSIN DD *
DEL FICHERO.CON.NOMBRES
SET MAXCC = 0
//******************************************************
//*********** EJECUCION DEL PROGRAMA PRUEBA2 ***********
//PROG1 EXEC PGM=PRUEBA2
//SYSOUT  DD SYSOUT=*
//FICHERO DD DSN=FICHERO.CON.NOMBRES,
//           DISP=(NEW, CATLG, DELETE),

//           SPACE=(TRK,(50,10))
//SYSIN DD *
JOSE LOPEZ VAZQUEZ HUGO CASILLAS DIAZ JAVIER CARBONERO PACO GONZALEZ
/*


En este ejemplo añadimos un nuevo paso, el IDCAMS. Este programa sirve para borrar ficheros que se crean a lo largo del JCL. En nuestro caso borrará el fichero que se va a crear en el programa. Así podremos ejecutarlo tantas veces como queramos sin generar el mismo fichero una y otra vez.
El paso de ejecución del programa PRUEBA2 es similar al del ejemplo 1, sólo le hemos añadido la definición del fichero de salida "FICHERO".

PROGRAMA:

 IDENTIFICATION DIVISION.
 PROGRAM-ID. PRUEBA2.
*==========================================================*
*     PROGRAMA QUE LEE DE SYSIN Y ESCRIBE EN FICHERO
*==========================================================*
*
 ENVIRONMENT DIVISION.
*
 CONFIGURATION SECTION.
*
 SPECIAL-NAMES.
     DECIMAL-POINT IS COMMA.
*
 INPUT-OUTPUT SECTION.
*
 FILE-CONTROL.
*
 SELECT FICHERO ASSIGN TO FICHERO
                STATUS IS FS-FICHERO.
*
 DATA DIVISION.
*
 FILE SECTION.
*
* Fichero de salida de longitud fija (F) igual a 20.
 FD FICHERO RECORDING MODE IS F
            BLOCK CONTAINS 0 RECORDS
            RECORD CONTAINS 20 CHARACTERS.
 01 REG-FICHERO PIC X(20).
*
 WORKING-STORAGE SECTION.
* FILE STATUS
 01 FS-STATUS.
    05 FS-FICHERO        PIC X(2).
       88 FS-FICHERO-OK          VALUE '00'.
*
* VARIABLES
 01 WI-INDICE            PIC 9(4) COMP.
 01 WX-SYSIN             PIC X(80).
 01 WX-TABLA-NOMBRES.
    05 WX-NOMBRE         PIC X(20) OCCURS 4 TIMES.
 01 WX-REGISTRO-SALIDA   PIC X(20).
*
************************************************************
 PROCEDURE DIVISION.
************************************************************
*  |     0000 - PRINCIPAL
*--|------------------+----------><----------+-------------*
* 1| EJECUTA EL INICIO DEL PROGRAMA
* 2| EJECUTA EL PROCESO DEL PROGRAMA
* 3| EJECUTA EL FINAL DEL PROGRAMA
************************************************************
 00000-PRINCIPAL.
*
     PERFORM 10000-INICIO
*
     PERFORM 20000-PROCESO
*
     PERFORM 30000-FINAL
     .
************************************************************
*  |     10000 - INICIO
*--|------------+----------><----------+-------------------*
*  | SE REALIZA EL TRATAMIENTO DE INICIO:
* 1| Inicialización de Áreas de Trabajo
* 2| Primera lectura de SYSIN
************************************************************
 10000-INICIO.
*
     INITIALIZE WX-SYSIN

                WX-REGISTRO-SALIDA
                WX-TABLA-NOMBRES

     ACCEPT WX-SYSIN FROM SYSIN

     PERFORM 11000-ABRIR-FICHERO
     .
*
************************************************************
*               11000 - ABRIR FICHEROS
*--|------------------+----------><----------+-------------*
* Abrimos el fichero de salida
************************************************************
 11000-ABRIR-FICHERO.
*
     OPEN OUTPUT FICHERO
*
     IF NOT FS-FICHERO-OK
        DISPLAY 'ERROR EN OPEN DEL FICHERO:'FS-FICHERO
     END-IF
     .
*
************************************************************
*  |     20000 - PROCESO
*--|------------------+----------><------------------------*
*  | SE REALIZA EL TRATAMIENTO DE LOS DATOS:
* 1| Realiza el tratamiento de cada registro recuperado de
* la SYSIN
************************************************************
 20000-PROCESO.
*
     MOVE WX-SYSIN TO WX-TABLA-NOMBRES
     MOVE 1        TO WI-INDICE

     PERFORM UNTIL WI-INDICE GREATER 4
        PERFORM 21000-INFORMAR-REGISTRO
        PERFORM 22000-ESCRIBIR-FICHERO

        ADD 1 TO WI-INDICE
     END-PERFORM

     .
*
************************************************************
*               21000 - INFORMAR REGISTRO
*--|------------------+----------><----------+-------------*
* MOVEMOS LA INFORMACION DESDE NUESTRA TABLA INTERNA A LA
* VARIABLE WX-REGISTRO-SALIDA
************************************************************
 21000-INFORMAR-REGISTRO.
*
     MOVE WX-NOMBRE(WI-INDICE) TO WX-REGISTRO-SALIDA

     .
*
************************************************************
*               22000 - ESCRIBIR FICHERO
*--|------------------+----------><----------+-------------*
* ESCRIBIMOS EN EL FICHERO DE SALIDA LA INFORMACION GUARDADA
* WX-REGISTRO-SALIDA
************************************************************
 22000-ESCRIBIR-FICHERO.
*
     WRITE REG-FICHERO FROM WX-REGISTRO-SALIDA

     IF NOT FS-FICHERO-OK
        DISPLAY 'ERROR EN WRITE DEL FICHERO:'FS-FICHERO
     END-IF

     .
*
************************************************************
*  |     30000 - FINAL
*--|------------------+----------><----------+-------------*
*  | FINALIZA LA EJECUCION DEL PROGRAMA
************************************************************
 30000-FINAL.
*
     PERFORM 31000-CERRAR-FICHERO

     STOP RUN
     .
*
************************************************************
*  |     31000 - CERRAR FICHERO
*--|------------------+----------><----------+-------------*
*  | CERRAMOS EL FICHERO DE SALIDA
************************************************************
 31000-CERRAR-FICHERO.
*
     CLOSE FICHERO

     IF NOT FS-FICHERO-OK
        DISPLAY 'ERROR EN CLOSE DEL FICHERO:'FS-FICHERO
     END-IF
     .


En el programa podemos ver las siguientes divisiones/secciones:
IDENTIFICATION DIVISION: existirá siempre.
ENVIRONMENT DIVISION: existirá siempre.
  CONFIGURATION SECTION: existirá siempre.
  INPUT-OUTPUT SECTION: en este ejemplo existirá porque utilizamos un fichero de salida.
DATA DIVISION: existirá siempre.
  FILE SECTION: en este ejemplo existirá pues utilizamos un fichero de salida.
  WORKING-STORAGE SECTION: exisitirá siempre.
  En este caso no exisistirá la LINKAGE SECTION pues el programa no se comunica con otros programas.
PROCEDURE DIVISION: exisitirá siempre.


En el programa podemos ver las siguientes sentencias:
PERFORM: llamada a párrafo
INITIALIZE: para inicializar variable
ACCEPT: esta sentencia recoge la información del campo indicado en el "FROM". En este caso recoge la información almacenada en "SYSIN"; la que nosotros hemos introducido en el JCL.
OPEN: "Abre" los ficheros del programa. Lo acompañaremos de "INPUT" para los ficheros de entrada y "OUTPUT" para los ficheros de salida.
DISPLAY: escribe el contenido del campo indicado en la SYSOUT del JCL.
MOVE/TO: movemos la información de un campo a otro
PERFORM UNTIL: bucle
ADD:Operador de adición (suma)
WRITE: Escribe la información indicada en el "FROM" en el fichero indicado.
STOP RUN: sentencia de finalización de ejecución.
CLOSE: "Cierra" los ficheros del programa.

Descripción del programa:
En el párrafo de inicio, inicializamos las variables que utilizaremos a lo largo del programa:
WX-SYSIN: donde guardaremos posteriormente mediante un ACCEPT la información que hemos escrito en la SYSIN del JCL.
WX-TABLA-NOMBRES: donde moveremos la información de la SYSIN para dividirla en los diferentes nombres.
WX-REGISTRO-SALIDA: donde guardaremos la información que vamos a escribir en el fichero de salida.
Abriremos el fichero de salida (OPEN OUTPUT) y controlaremos el file-status. Si todo va bien el código del file-status valdrá '00'. Podéis ver la lista de los file-status más comunes.

En el párrafo de proceso, informamos la tabla interna WX-TABLA-NOMBRES, donde el campo WX-NOMBRES se repetirá 4 veces (occurs 4 times). Recordad que el tratamiento de las tablas internas está explicado en detalle en el ejemplo 1.
Montaremos un bucle para escribir cada uno de los nombres guardados en la tabla interna en el fichero de salida.
Informaremos la variable WX-REGISTRO-SALIDA con cada uno de los nombres de la tabla.
Escribiremos el fichero de salida. Para ellos indicaremos a continuación del WRITE la variable definida en la FILE-SECTION, y a continuación del FROM la variable donde tenemos guardada la información que queremos escribir.
Controlaremos el file-status.

Nota: es importante controlar el FILE-STATUS en los accesos a ficheros (OPEN, READ, WRITE, CLOSE...) para, en caso de fallo en la ejecución, tener información sobre la causa del error.

miércoles, 9 de febrero de 2011

Ejemplo 1: Leer de SYSIN y escribir en SYSOUT.

En cobol hay que diferenciar entre los programas que acceden a DB2 y los que no, pues se compilarán de maneras diferentes y se ejecutarán de forma diferente.
Enpezaremos por ver el programa sin DB2 más sencillo:

El programa más sencillo es aquel que recibe datos por SYSIN del JCL y los muestra por SYSOUT.

JCL:

//PROG1 EXEC PGM=PRUEBA1
//SYSOUT DD SYSOUT=*
//SYSIN DD *
JOSE LOPEZ VAZQUEZ HUGO CASILLAS DIAZ JAVIER CARBONERO PACO GONZALEZ
/*


donde EXEC PGM= indica el programa SIN DB2 que vamos a ejecutar
SYSOUT DD SYSOUT=* indica que la información "displayada" se quedará en la cola del SYSOUT (no lo vamos a guardar en un fichero)
en SYSIN DD * metemos la información que va a recibir el programa

Fijaos en las posiciones de los nombres de la SYSIN, para entender bien el programa:

----+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8
JOSE LOPEZ VAZQUEZ  HUGO CASILLAS DIAZ  JAVIER CARBONERO    PACO GONZALEZ


Como veis, la longitud máxima que se puede pasar a un programa a través de la SYSIN es de 80. En nuestro caso la hemos dividido en 4 trozos de 20 posiciones, cada uno con un nombre.

PROGRAMA:

 IDENTIFICATION DIVISION.
 PROGRAM-ID. PRUEBA1.
*==========================================================*
*     PROGRAMA QUE LEE DE SYSIN Y ESCRIBE EN SYSOUT
*==========================================================*
*
 ENVIRONMENT DIVISION.
*
 CONFIGURATION SECTION.
*
 SPECIAL-NAMES.
     DECIMAL-POINT IS COMMA.
*
 DATA DIVISION.
*
 WORKING-STORAGE SECTION.
*
 01 WI-INDICE PIC 9(4) COMP.
 01 WX-SYSIN PIC X(80).
 01 WX-TABLA-NOMBRES.
    05 WX-NOMBRE PIC X(20) OCCURS 4 TIMES.
*
************************************************************
 PROCEDURE DIVISION.
************************************************************
*  |     0000 - PRINCIPAL
*--|------------------+----------><----------+-------------*
* 1| EJECUTA EL INICIO DEL PROGRAMA
* 2| EJECUTA EL PROCESO DEL PROGRAMA
* 3| EJECUTA EL FINAL DEL PROGRAMA
************************************************************
 00000-PRINCIPAL.
*
     PERFORM 10000-INICIO
*
     PERFORM 20000-PROCESO
*
     PERFORM 30000-FINAL
     .
************************************************************
*  |     10000 - INICIO
*--|------------+----------><----------+-------------------*
*  | SE REALIZA EL TRATAMIENTO DE INICIO:
* 1| Inicialización de Áreas de Trabajo
* 2| Primera lectura de SYSIN
************************************************************
 10000-INICIO.
*
     INITIALIZE WX-SYSIN

     ACCEPT WX-SYSIN FROM SYSIN

     .
************************************************************
*  |     20000 - PROCESO
*--|------------------+----------><------------------------*
*  | SE REALIZA EL TRATAMIENTO DE LOS DATOS:
* 1| Realiza el tratamiento de cada registro leido
************************************************************
 20000-PROCESO.
*
     MOVE WX-SYSIN TO WX-TABLA-NOMBRES
     MOVE 1        TO WI-INDICE

     PERFORM UNTIL WI-INDICE GREATER 4
        DISPLAY 'WX-NOMBRE:'WX-NOMBRE(WI-INDICE)

        ADD 1 TO WI-INDICE
     END-PERFORM

     .
************************************************************
*  |     30000 - FINAL
*--|------------------+----------><----------+-------------*
*  | FINALIZA LA EJECUCION DEL PROGRAMA
************************************************************
 30000-FINAL.
*
     STOP RUN
     .



En el programa podemos ver las siguientes divisiones/secciones:
IDENTIFICATION DIVISION: existirá siempre.
ENVIRONMENT DIVISION: existirá siempre.
  CONFIGURATION SECTION: existirá siempre.
  En este caso no existirá la INPUT-OUTPUT SECTION, pues nuestro programa no utiliza ficheros.
DATA DIVISION: existirá siempre.
  En este caso no existirá la FILE SECTION, pues nuestro programa no utiliza ficheros.
  WORKING-STORAGE SECTION: exisitirá siempre.
  En este caso no exisistirá la LINKAGE SECTION pues el programa no se comunica con otros programas.
PROCEDURE DIVISION: exisitirá siempre.


En el programa podemos ver las siguientes sentencias:
PERFORM: llamada a párrafo
INITIALIZE: para inicializar variable
ACCEPT: esta sentencia recoge la información del campo indicado en el "FROM". En este caso recoge la información almacenada en "SYSIN"; la que nosotros hemos introducido en el JCL.
MOVE/TO: movemos la información de un campo a otro
PERFORM UNTIL: bucle
DISPLAY: escribe el contenido del campo indicado en la SYSOUT del JCL.
ADD:Operador de adición (suma)
STOP RUN: sentencia de finalización de ejecución.


Descripción del programa:
En el párrafo de inicio, inicializamos WX-SYSIN para guardar posteriormente mediante un ACCEPT la información que hemos escrito en la SYSIN del JCL.

En el párrafo de proceso, informamos la tabla interna WX-TABLA-NOMBRES, donde el campo WX-NOMBRES se repetirá 4 veces (occurs 4 times).

Informamos el campo WI-INDICE con un 1, pues vamos a utilizar los campos de la tabla interna:
Para utilizar un campo que pertenezca a una tabla interna (tiene occurs), debemos acompañar el campo de un "índice" entre paréntesis. De tal forma que indiquemos a que "ocurrencia" de la tabla nos estamos refiriendo. Por ejemplo, WX-NOMBRE(1) sería el primer nombre guardado (JOSE LOPEZ VAZQUEZ).
Como queremos displayar todas las ocurrencias de la tabla, haremos que el índice sea una variable que va aumentando.

A continuación montamos un bucle (perform until) con la condición WI-INDICE mayor (greater) de 4, pues la primera vez WI-INDICE valdrá 1, y necesitamos que el bucle se repita 4 veces:
WI-INDICE = 1: WX-NOMBRE(1) = JOSE LOPEZ VAZQUEZ
WI-INDICE = 2: WX-NOMBRE(2) = HUGO CASILLAS DIAZ
WI-INDICE = 3: WX-NOMBRE(3) = JAVIER CARBONERO
WI-INDICE = 4: WX-NOMBRE(4) = PACO GONZALEZ
WI-INDICE = 5: salimos del bucle porque se cumple WI-INDICE GREATER 4


NOTA: el índice de una tabla interna NUNCA puede ser cero, pues no existe la ocurrencia cero. Si no informásemos WI-INDICE con 1, el DISPLAY de WX-NOMBRE(0) nos daría un estupendo casque, de este estilo:

IGZ0006S The reference to table WX-NOMBRE by verb number 01 on line 001099 addressed an area outside the region of the table.
From compile unit R2BCTAN1 at entry point R2BCTAN1 at compile unit offset +00001122 at entry offset +00001122 at address 1965BBAA.

Aunque ahora ya sabemos cómo encontrar la línea que nos da el OFFSET :D

RESULTADO:
WX-NOMBRE: JOSE LOPEZ VAZQUEZ
WX-NOMBRE: HUGO CASILLAS DIAZ
WX-NOMBRE: JAVIER CARBONERO
WX-NOMBRE: PACO GONZALEZ