Conocimientos mínimos que debe tener antes de leer código fuente COBOL
· Actualizado el: · Go Komura · COBOL, Tecnología heredada, Sistemas empresariales, Mantenimiento, Mainframe
Traspasos de responsabilidad, atención de incidencias, mantenimiento de paquetes de proveedores. En situaciones así, puede ocurrir que un día, de repente, le llegue código fuente COBOL.
- El nombre de archivo es
.cblo.cpy - Los nombres de variable están todos en mayúsculas
- Aparecen en fila
01,05,77,88 - Aparecen expresiones como
PIC S9(7)V99 COMP-3, a medio camino entre un conjuro y un programa de contabilidad - Y, para colmo, está lleno de
COPY, así que con solo el archivo abierto no se ve el conjunto completo
En este punto, la mayoría de las personas se detiene un momento.
Sin embargo, el mapa necesario para leerlo no es tan grande. COBOL tiene diferencias según el compilador o el producto, pero el esqueleto que conviene dominar primero para leer un sistema empresarial existente es bastante común entre ellos. Este artículo, pensando sobre todo en los entornos de tipo IBM y en el COBOL empresarial típico, organiza el conjunto mínimo para quienes de repente deben leer código fuente.
1. Conclusión primero (en pocas palabras)
Dicho de forma bastante directa pero útil en la práctica, es así:
- COBOL es, antes que un lenguaje de lógica, muy marcadamente un lenguaje de definición de registros
- Leer solo el
PROCEDURE DIVISIONle dará únicamente la mitad del panorama. Primero hay que mirar elDATA DIVISION PICes la forma del campo yUSAGEes en qué representación se guardaCOMP-3es packed decimal. Aparece con frecuencia en el mundo de los importes y las cantidades88no es tanto una variable aparte como un nombre de condición asociado al valor del campo inmediatamente anteriorREDEFINESes un mecanismo para ver la misma memoria con otra forma. No es una copia- Si hay un
COPY, el código fuente que tiene abierto todavía está incompleto. Sin consultar el copybook no se ve el conjunto completo - Si puede seguir
PERFORM,IF,EVALUATE,READ,WRITEyCALL, ya captará el flujo general - El código fuente antiguo está en formato fijo, donde la posición de columna tiene significado. Los espacios en blanco que se ven no son solo decoración1
En resumen: DIVISION, PIC, USAGE, COMP-3, REDEFINES, OCCURS, 88, COPY, PERFORM. Si puede leer estos elementos, la probabilidad de perderse baja considerablemente.
2. Piense primero en COBOL como el lenguaje de «la forma de los datos»
Si lo lee con la mentalidad de C# o Java, al principio querrá seguir los if, los for y las llamadas a funciones.
Pero en COBOL, antes de llegar ahí, resulta más rápido tener claro «qué registros recibe este programa, qué registros produce y qué búferes maneja».
Un COBOL empresarial típico sigue, a grandes rasgos, este flujo.
- Lee un registro de un archivo o de una base de datos
- Lo coloca en un campo de
WORKING-STORAGE - Realiza una bifurcación condicional
- Lo reorganiza en otro registro
- Lo escribe
Es decir, el diseño (layout) suele imponerse antes que el algoritmo.
Por ejemplo, este es el esqueleto típico:
IDENTIFICATION DIVISION.
PROGRAM-ID. SAMPLE01.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT SALES-FILE ASSIGN TO ...
DATA DIVISION.
FILE SECTION.
FD SALES-FILE.
01 SALES-REC.
05 SALE-ID PIC 9(8).
05 SALE-AMOUNT PIC S9(7)V99 COMP-3.
WORKING-STORAGE SECTION.
01 WS-EOF PIC X VALUE 'N'.
88 EOF VALUE 'Y'.
PROCEDURE DIVISION.
PERFORM UNTIL EOF
READ SALES-FILE
AT END
SET EOF TO TRUE
NOT AT END
PERFORM PROCESS-SALE
END-READ
END-PERFORM
STOP RUN.
Al leer este código, lo primero que conviene mirar, antes que el PERFORM, es el tipo de SALE-AMOUNT y el significado de EOF.
Si se lee en ese orden, COBOL de repente se vuelve mucho más tranquilo de leer.
3. Mire primero los cuatro DIVISION
El código fuente COBOL se divide, a grandes rasgos, en cuatro DIVISION.
| DIVISION | Qué mirar primero |
|---|---|
IDENTIFICATION DIVISION |
Nombre del programa, comentarios antiguos, origen |
ENVIRONMENT DIVISION |
Archivos, recursos externos, condiciones de entrada y salida |
DATA DIVISION |
Definición de registros, área de trabajo, argumentos |
PROCEDURE DIVISION |
El procedimiento de procesamiento real |
Lo que resulta especialmente importante es lo siguiente.
FILE SECTIONContiene la definición de registro de los archivos de entrada y salidaWORKING-STORAGE SECTIONContiene las variables, banderas, contadores y búferes de trabajo de uso habitualLOCAL-STORAGE SECTIONPuede contener áreas que se inicializan en cada llamadaLINKAGE SECTIONPuede contener los argumentos que se pasan desde fuera, o el punto de entrada de un subprograma
Si ve LINKAGE SECTION junto con PROCEDURE DIVISION USING ..., es muy probable que ese programa no sea autónomo, sino que funcione recibiendo datos desde fuera.
4. No se asuste con el aspecto del formato fijo
En el COBOL antiguo, la propia posición de columna de cada línea del código fuente tiene significado. Si lo mira sin saber esto, nunca llegará a entender «por qué hay ese margen raro a la izquierda».1
En el formato fijo, a grandes rasgos, es así:
- Columnas 1-6: número de secuencia
- Columna 7: indicador (indicator)
- Columnas 8-11: Área A (Area A)
- Columnas 12-72: Área B (Area B)
La columna 7 es especialmente importante.
*o/: línea de comentario-: línea de continuaciónD: línea de depuración (debugging line)*>: comentario que también puede escribirse en medio de la línea
Si se representa la correspondencia entre columna y contenido con una regla graduada, queda así. La primera línea marca las decenas y la segunda línea marca las unidades.
1 2 3 4 5 6 7 8
12345678901234567890123456789012345678901234567890123456789012345678901234567890
SSSSSSIAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB........
S= número de secuencia (columnas 1-6)I= indicador (columna 7)A= Área A (columnas 8-11)B= Área B (columnas 12-72).= a partir de la columna 73. Según el compilador, puede usarse como campo de identificación, pero no afecta al significado del programa
Aplicado a un código fuente real, queda así:
000100* Esta línea es un comentario porque la columna 7 es *
000200 IDENTIFICATION DIVISION.
000300 PROGRAM-ID. SAMPLE01.
000400 DATA DIVISION.
000500 WORKING-STORAGE SECTION.
000600 01 WS-ORDER.
000700 05 WS-ORDER-ID PIC 9(8).
000800 05 WS-LONG-NAME PIC X(30) VALUE 'ABCDEFGHIJKLMNOPQRST
000900- 'UVWXYZ0123'.
Hay cuatro puntos clave para leerlo.
- Las columnas 1-6 son el número de secuencia. En el ejemplo anterior es lo que aparece numerado como
000100, y no afecta al funcionamiento del programa. A veces está en blanco. - La columna 7 es el indicador.
*significa comentario y-significa línea de continuación. La línea000900del ejemplo anterior es justamente eso: la continuación del literal de cadena de la línea previa. - Las columnas 8-11 son el Área A.
DIVISION,SECTION, los nombres de párrafo,FD, y los números de nivel01y77empiezan aquí. En el ejemplo anterior,IDENTIFICATION DIVISION.y01 WS-ORDER.comienzan en el Área A. - Las columnas 12-72 son el Área B. Ahí se escriben las sentencias normales y los niveles inferiores como
05. En el ejemplo anterior,05 WS-ORDER-IDcomienza en el Área B.
Los espacios en blanco aquí no son un «formateo» en el sentido moderno, sino parte de la sintaxis. Si el editor convierte tabulaciones, alinea todo a la izquierda o se copia y pega sin cuidado, el código se rompe con facilidad. Al ver código fuente antiguo, sospeche primero si el archivo está en formato fijo (fixed format) o en formato libre (free format). Si se aplica un autoformateo moderno a un código fuente en formato fijo, el límite entre el Área A y el Área B se rompe y deja de compilar.
5. Lo mínimo del DATA DIVISION
5.1 Números de nivel
La definición de datos en COBOL construye la jerarquía mediante números de nivel, no mediante la sangría.2
01 WS-ORDER.
05 WS-ORDER-ID PIC 9(8).
05 WS-AMOUNT PIC S9(7)V99 COMP-3.
05 WS-STATUS PIC X.
88 WS-OK VALUE '0'.
88 WS-ERROR VALUE '9'.
77 WS-COUNT PIC 9(4).
Basta con recordar, como mínimo, lo siguiente.
01: el registro o grupo de nivel superior que forma una unidad02-49: los niveles jerárquicos por debajo de ese77: un elemento único e independiente88: condition-name (nombre de condición). Da nombre al valor del campo inmediatamente anterior366: paraRENAMES. No es muy frecuente encontrarlo, pero existe
Lo importante es no pensar que 88 es una variable booleana aparte.
No existe una zona separada llamada WS-OK; más bien, cuando WS-STATUS vale '0', se puede leer con el nombre WS-OK.
Otro punto importante es que lo que determina la jerarquía es el número de nivel, no los espacios en blanco.
La sangría visual sirve de referencia, pero en última instancia hay que confiar en 01 / 05 / 10 / 88.2
5.2 PICTURE
PIC representa la forma de ese campo.
Lo que más se ve es lo siguiente.
| Notación | Significado aproximado |
|---|---|
X |
Carácter |
9 |
Dígito numérico |
S |
Con signo |
V |
Punto decimal solo lógico |
X(10) |
10 caracteres |
9(5) |
Número de 5 dígitos |
S9(7)V99 |
Con signo, 7 dígitos enteros + 2 dígitos decimales |
Por ejemplo:
PIC X(10)→ 10 caracteresPIC 9(5)V99→ 5 dígitos enteros + 2 dígitos decimalesPIC S9(7)V99→ con signo, 7 dígitos enteros + 2 dígitos decimales
eso es todo.
Aquí lo especialmente importante es la V.
La V no tiene un carácter . real.
PIC 9(5)V99 se trata como «un número con 2 dígitos decimales», pero no hay ningún carácter de punto en los datos.
Por eso, interpretar el archivo o el volcado como «una cadena de texto tal cual» casi siempre lleva al error.
5.3 USAGE / DISPLAY / COMP / COMP-3
Si PIC es la forma, USAGE es en qué representación se guarda.
Con dominar solo lo siguiente, ya se puede leer bastante bien.45
| Notación | Significado aproximado | Precaución al leer |
|---|---|---|
DISPLAY |
Decimal externo visible como carácter | En mainframe a veces se asume EBCDIC6 |
COMP / BINARY |
Número binario | El número de dígitos visible y la representación interna son cosas distintas |
COMP-3 / PACKED-DECIMAL |
packed decimal | Al leerlo como texto se ve como datos corruptos |
Por ejemplo:
01 WS-AMOUNT-DISP PIC S9(7)V99.
01 WS-AMOUNT-BIN PIC S9(7) COMP.
01 WS-AMOUNT-PACK PIC S9(7)V99 COMP-3.
Estos tres son todos «numéricos», pero la forma en que guardan el contenido es distinta.
Lo que más rinde en la práctica es la reacción inmediata al ver COMP-3.
- Es packed decimal
- Probablemente se trate de un importe, un impuesto, una cantidad o una tasa
- Es normal que se vea como datos corruptos si se lee como texto
- Mirarlo con la mentalidad de un CSV o de UTF-8 lleva al error
Tener esto claro evita que se alarme innecesariamente al ver el aspecto de un volcado o de un archivo binario.
Qué bytes produce realmente COMP-3
Si sigue este cálculo a mano una sola vez, su forma de ver esto cambiará a partir de entonces.
Las reglas del packed decimal son solo dos.45
- Cada byte guarda dos dígitos decimales
- Salvo que el byte más a la derecha usa 1 dígito bajo más el signo en ese único byte
El signo se representa con un valor de 4 bits: C es positivo, D es negativo y F es sin signo.
Vamos a comprobarlo con los ejemplos que aparecen en el manual de IBM.4
| Definición | Valor | Secuencia de bytes |
|---|---|---|
PIC S9(4) PACKED-DECIMAL |
+1234 |
01 23 4C |
PIC S9(4) PACKED-DECIMAL |
-1234 |
01 23 4D |
PIC 9(4) PACKED-DECIMAL |
1234 |
01 23 4F |
Como 1234 tiene 4 dígitos, la regla 2 deja un hueco de 1 dígito al principio. Ese es el 0 inicial.
Siguiendo el mismo procedimiento, vamos a seguir PIC S9(7)V99 COMP-3, que ha aparecido varias veces en este artículo.
S9(7)V99son 7 dígitos enteros + 2 dígitos decimales = 9 dígitos- La
Vsolo indica la posición del punto decimal, así que no consume ni un solo byte - Al empaquetar los 9 dígitos de 2 en 2 se obtienen 4 bytes, y el dígito restante junto con el signo ocupan 1 byte más. En total, 5 bytes
Si el valor es +12345.67, al ajustarlo a 9 dígitos queda 001234567, así que resulta lo siguiente:
Valor : +12345.67
9 dígitos : 0 0 1 2 3 4 5 6 7 y signo
Bytes : 00 12 34 56 7C
^ signo C = positivo
Si el valor fuera negativo, -12345.67, lo único que cambia es que el final es 7D.
Bytes : 00 12 34 56 7D
Lo importante es cómo se ve esto si se abre como texto. Si se fuerza 00 12 34 56 7C a corresponder con ASCII, un byte por carácter:
00es NUL y12es un carácter de control; ninguno de los dos se puede mostrar como carácter34es4,56esVy7Ces|
Es decir, en pantalla se ve algo así como «varios caracteres no representables seguidos de 4V|». La secuencia 12345.67 no aparece por ninguna parte.
Esto es lo que hay detrás de «parece corrupto pero no lo está». Si al abrir un volcado se encuentra con una secuencia sin sentido, sospeche primero si el USAGE de ese campo no será COMP-3.
De paso, aquí tiene una tabla de referencia rápida para calcular el número de bytes a partir del número de dígitos. El número de bytes se obtiene «dividiendo entre 2 la cantidad de nueves, redondeando hacia abajo, y sumando 1».
| Cantidad de nueves en el PICTURE | Bytes de COMP-3 |
|---|---|
| 1 | 1 |
| 2 - 3 | 2 |
| 4 - 5 | 3 |
| 6 - 7 | 4 |
| 8 - 9 | 5 |
| 10 - 11 | 6 |
| 12 - 13 | 7 |
Que dos cantidades de dígitos compartan el mismo número de bytes se debe a que solo cuando la cantidad de nueves es par se genera un hueco de 1 dígito al principio. Por eso S9(4) ocupa 3 bytes como 01 23 4C, y S9(5) también cabe en los mismos 3 bytes.
Al cotejar el diseño con un archivo externo, sin esta tabla el desfase avanza byte a byte.
Una última aclaración: que un campo sea DISPLAY no garantiza que sea una cadena ASCII.
En los entornos z/OS se asume EBCDIC, así que aunque los dígitos se vean como caracteres, el valor de byte puede ser distinto de '0'-'9' en ASCII.6
5.4 REDEFINES / OCCURS / COPY / FILLER
Estos cuatro elementos son los puntos donde más se atasca la lectura.
REDEFINES
REDEFINES es un mecanismo para ver la misma zona con otra forma. No es una copia.7
01 REC-BUF.
05 REC-TYPE PIC X.
05 REC-DATA PIC X(99).
01 HEADER-REC REDEFINES REC-BUF.
05 HDR-TYPE PIC X.
05 HDR-DATE PIC 9(8).
05 FILLER PIC X(91).
Esto se parece a la sensación de un union en lenguajes de la familia C.
Aparece con frecuencia en escrituras del tipo «distinguir un mismo bloque de 100 bytes como distintos tipos de registro».
OCCURS
OCCURS es un arreglo (array). En COBOL suele llamarse table.
05 WS-ITEM OCCURS 12 TIMES.
10 WS-PRICE PIC 9(5).
Además, si aparece OCCURS DEPENDING ON, se trata de una tabla de longitud variable.
En ese caso, puede afectar incluso a la posición de los campos posteriores, así que si se sigue con la mentalidad de longitud fija se pierde el paso.8
COPY
COPY es un include que se resuelve en tiempo de compilación.
Es decir, el código fuente que tiene abierto puede no ser todavía la forma completa.9
COPY CUSTOMER-REC.
COPY ERROR-MAP.
Es bastante habitual que las definiciones de registro, las banderas comunes, las host variables para SQL y las interfaces externas estén metidas dentro de los copybooks.
Cuando hay tantos COPY que resulta difícil de leer, lo más rápido es comprobar si puede consultar el código fuente ya expandido o el compiler listing. IBM Enterprise COBOL cuenta además con una opción llamada MDECK para volcar el código fuente de entrada después del procesamiento de biblioteca.10
FILLER
FILLER es un campo sin nombre.
Sin embargo, eso no significa que sea «irrelevante porque no se referencia».
- Área reservada
- Un hueco para compatibilidad con una especificación anterior
- Ajuste de la longitud del registro
- Margen para
REDEFINES
y cumple estas funciones con normalidad.
FILLER solo carece de nombre, pero existe como cantidad de bytes.
Si se olvida esto, la correspondencia con un archivo externo se va desalineando byte a byte.
6. Lo mínimo del PROCEDURE DIVISION
Si el DATA DIVISION es el mapa, el PROCEDURE DIVISION es la ruta de desplazamiento.
6.1 PERFORM
PERFORM es la transferencia de control básica de COBOL.
Dicho de forma sencilla, es llamar a un proceso y volver.11
La forma más habitual es la siguiente.
PERFORM INIT-PROC
PERFORM UNTIL EOF
PERFORM READ-PROC
IF NOT EOF
PERFORM EDIT-PROC
PERFORM WRITE-PROC
END-IF
END-PERFORM
PERFORM tiene, a grandes rasgos, dos variantes.
- El
PERFORMout-of-line, que indica un párrafo o una sección - El
PERFORM ... END-PERFORMinline, que escribe el bloque en el propio lugar
En código todavía más antiguo, también aparece con normalidad la indicación de un rango, como PERFORM A-100 THRU A-199.
Esto es cómodo, pero si se añade un párrafo en medio es fácil provocar un incidente por arrastre, así que al leer conviene fijarse bien en dónde termina el rango.
6.2 IF / EVALUATE / el alcance (scope)
La bifurcación condicional básica es IF.
Pensar en EVALUATE como algo similar a un switch/case es, en general, correcto.
Lo que hay que vigilar es cómo termina el alcance (scope).12
END-IFEND-PERFORMEND-READ
el código que tiene un cierre explícito como estos todavía es fácil de leer.
El problema es el código antiguo. En COBOL, el . funciona como un terminador de alcance implícito y cierra de golpe todas las sentencias que aún no se habían cerrado.12
Es decir, con un único punto,
- hasta dónde llega el
IF - hasta dónde llega el
PERFORM - dónde se pasa a la siguiente sentence
puede cambiar.
Además, NEXT SENTENCE no es lo mismo que CONTINUE.
NEXT SENTENCE avanza hasta después del siguiente punto, así que el destino del salto cambia según dónde esté ese . posterior.12
Al leer COBOL antiguo, conviene tener presente que hay que fijarse en el punto, no en el final de línea.
6.3 READ / WRITE / CALL
En el COBOL empresarial, lo que aparece con más frecuencia es lo siguiente.
READWRITEREWRITESTARTCALL
En particular, READ ... AT END ... es el patrón clásico por excelencia.
READ IN-FILE
AT END
SET EOF TO TRUE
NOT AT END
PERFORM PROCESS-REC
END-READ
Si hay CALL 'SUBPGM' USING ..., el control salta a otro programa.
En ese caso, mirar el LINKAGE SECTION y el PROCEDURE DIVISION USING del programa llamado deja bastante claro cómo se realiza el paso de datos.
7. Lo que queda fuera de COBOL
En COBOL, es bastante frecuente que el mundo no se complete solo con el código fuente.
- La definición de archivos
- El entorno de ejecución
- La conexión a la base de datos
- El entorno transaccional
- El control de jobs
quedan separados fuera del código fuente.
Como mínimo, dominar lo siguiente facilita la lectura.
Los archivos y FILE STATUS
El FILE-CONTROL del ENVIRONMENT DIVISION y el FILE SECTION / FD del DATA DIVISION se leen como un conjunto.13
SELECT IN-FILE ASSIGN TO ...
FILE STATUS IS WS-FS.
FD IN-FILE.
01 IN-REC.
05 ...
Si hay FILE STATUS, en él se guarda el código de resultado tras cada operación de E/S.
Al leer fallos relacionados con archivos o la determinación del EOF, no se puede empezar sin consultarlo.14
EXEC SQL
Cuando aparece esto, se trata de SQL embebido.
EXEC SQL
SELECT ...
END-EXEC.
En este caso, COBOL actúa como «el contenedor de las host variables», mientras que las condiciones de obtención reales o el objetivo de la actualización están del lado del SQL.
Por eso, el camino más corto es leer el contenido de EXEC SQL como SQL normal.
EXEC CICS
Cuando aparece esto, se trata del contexto transaccional de CICS.15
EXEC CICS
RECEIVE MAP(...)
END-EXEC.
En ese momento, deja de ser una simple lectura de proceso por lotes. Hay que leerlo incluyendo el contexto externo: pantallas, transacciones, códigos de respuesta, COMMAREA, etc.
JCL y las definiciones de ejecución
En los procesos por lotes de mainframe, no es raro que qué dataset se asigna realmente o en qué orden se ejecutan los jobs queden fuera del código fuente COBOL. Cuando, mirando solo el código, no se entiende «dónde está este archivo», lo habitual no es que el código esté mal, sino simplemente que el alcance que se está mirando todavía es insuficiente.
Diferencias entre compiladores (procesadores del lenguaje)
Este artículo está escrito pensando sobre todo en el entorno IBM, pero en la práctica también puede encontrarse con Micro Focus o con COBOL sobre Linux / Windows. Como el esqueleto es común, la forma de leer no cambia, pero los puntos donde «la misma forma de escribir da resultados distintos» están bien delimitados, así que conocerlos de antemano evita sorpresas.
| Aspecto a revisar | Entorno z/OS (IBM Enterprise COBOL) | Entornos abiertos (Micro Focus, versiones para Linux / Windows, etc.) |
|---|---|---|
| Codificación de caracteres | Se asume EBCDIC6 | Se asume ASCII6 |
| Formato de referencia | El formato fijo (fixed) es la opción predeterminada tradicional. También puede elegirse el formato libre (free)1 | Admite tanto fixed como free, y cuál es el predeterminado depende de la configuración de compilación1 |
| Cómo se localizan los copybooks | Mediante la indicación de una biblioteca | Mediante la indicación de una ruta de búsqueda en las opciones del compilador |
| Dialecto | — | Existe una opción para cambiar «a qué compilador se ajusta» |
Lo que más pesa en la práctica es la codificación de caracteres. Incluso con el mismo PIC X(10), si un archivo escrito en z/OS se lee tal cual en Windows, incluso los dígitos numéricos tienen valores de byte distintos. Muchos casos de «al transferirlo todo se corrompió» se deben a esto, y es un problema distinto del de COMP-3.
Hay otro punto donde suele haber diferencias: la representación interna de los valores numéricos. En IBM Enterprise COBOL, BINARY / COMP-4 trunca según la cantidad de dígitos escrita en el PICTURE, mientras que COMP-5 mantiene el valor hasta la capacidad nativa del binario, de 2, 4 u 8 bytes, y el truncamiento se produce según el tamaño del binario.16 Es decir, PIC S9(4) COMP y PIC S9(4) COMP-5 parecen iguales, pero el límite superior del valor que admiten es distinto. Si se encuentra con COMP-5 en código que intercambia valores en binario puro con otro sistema, interprételo como que está escrito así a propósito.
El procedimiento más corto para contrastarlo con su propio entorno es este.
- Abra primero la definición de compilación (makefile, JCL, configuración del proyecto). Antes que el código fuente, esto le dirá con qué compilador y con qué opciones se compila.
- Determine el formato de referencia (fixed / free). Si se equivoca aquí y formatea con el editor, el código se rompe.
- Determine la codificación de caracteres. La forma de leer un volcado cambia según sea EBCDIC o ASCII.
- Marque los campos de la familia
COMP. Es prácticamente ahí donde aparecen las diferencias entre compiladores.
8. El orden mínimo de lectura
Cuando de repente le toque leer COBOL, el siguiente orden es el más seguro.
- Revise todos los
COPY. Si puede abrir el copybook, ábralo. Si no puede, busque el listing o el código fuente ya expandido. - Recoja las definiciones de registro de nivel
01. Elabore un listado de los niveles superiores deFILE SECTION,WORKING-STORAGEyLINKAGE SECTION. - Lea
PICyUSAGE. Identifique los importes, las fechas, las cantidades, los códigos y las banderas. - Busque
READ/WRITE/REWRITE/CALL/EXEC SQL/EXEC CICS. Capte primero la entrada, la salida y los límites externos. - Siga solo la ruta principal, al principio.
Recorra la cadena de
PERFORMdesde el inicio delPROCEDURE DIVISION. - Mire el
88y los campos de estado. Así resulta más fácil leer el significado del EOF, de normal/anormal y de los códigos de tipo. - Marque
REDEFINES/OCCURS DEPENDING ON/COMP-3. Como seguro que le afectarán más adelante, márquelos de antemano como elementos de riesgo. - Si es un archivo, mire
FILE STATUS. Esto reduce considerablemente los errores de interpretación en los fallos de E/S.
Con este orden, no hace falta leer todo el texto en detalle desde el principio. En COBOL, en lugar de intentar entenderlo todo al 100 % desde el inicio, es mucho más cómodo dominar primero los tres puntos —los registros, los límites externos y la ruta principal— y luego pasar a los detalles.
8.1 Ejercicio: lea esta definición de registro
Solo con la explicación de cómo leer no queda del todo asimilado, así que le dejamos un registro pequeño. Primero intente responder usted mismo y después mire las respuestas que aparecen abajo.
01 CUST-REC.
05 CUST-ID PIC X(8).
05 CUST-NAME PIC X(20).
05 CUST-KBN PIC X.
88 CUST-NORMAL VALUE '0'.
88 CUST-VIP VALUE '1'.
05 CUST-BALANCE PIC S9(7)V99 COMP-3.
05 CUST-HIST OCCURS 3 TIMES.
10 HIST-DATE PIC 9(8).
10 HIST-AMOUNT PIC S9(5)V99 COMP-3.
05 FILLER PIC X(4).
Preguntas
- ¿Cuántos bytes ocupa
CUST-RECen total? - ¿A partir de qué byte, contando desde el inicio del registro, empieza
CUST-BALANCE? - ¿A partir de qué byte, contando desde el inicio, empieza el segundo
HIST-AMOUNT? - Cuando
CUST-KBNcontiene'1', ¿qué nombre de condición se vuelve verdadero? - Al abrir este archivo en un editor de texto, ¿qué campos se ven como datos corruptos?
- Mencione dos cosas que no se pueden saber solo con esta definición.
Respuestas
-
74 bytes. El desglose es el siguiente.
Campo Cálculo Bytes CUST-IDX(8)8 CUST-NAMEX(20)20 CUST-KBNX1 CUST-BALANCECOMP-3 de 9 dígitos 5 CUST-HIST(8 + 4)× 3 veces36 FILLERX(4)4 Total 74 El nivel
88es un nombre de condición, así que no consume bytes. Contarlo es un error frecuente.FILLERsolo carece de nombre; los 4 bytes existen de forma efectiva. -
A partir del byte 30. Antes hay
8 + 20 + 1 = 29bytes, así que empieza justo después de esos. -
A partir del byte 55.
CUST-HISTempieza en el byte 35, y como cada elemento ocupa 12 bytes, el primero va del byte 35 al 46 y el segundo del 47 al 58. De esos, los primeros 8 bytes sonHIST-DATE, así queHIST-AMOUNTempieza en el byte 55. -
CUST-VIP. No existe una zona separada llamadaCUST-VIP; simplemente, cuandoCUST-KBNvale'1', se puede leer con ese nombre. -
CUST-BALANCEyHIST-AMOUNT. Como ambos sonCOMP-3, al leerlos como caracteres se convierten en secuencias sin sentido.HIST-DATEesDISPLAYconPIC 9(8), así que en un entorno ASCII se puede leer como un número, por ejemplo20260317. Sin embargo, en un entorno EBCDIC, aunque parezca un número, el valor de byte es distinto del de ASCII. -
Por ejemplo, cosas como estas.
- Si esta definición en sí se importa mediante
COPY. Sin mirar el copybook no se sabe si es la versión realmente en uso. - Si la codificación de caracteres del archivo es EBCDIC o ASCII. El aspecto de
PIC Xy dePIC 9 DISPLAYcambia según eso. - Si en la operación real
CUST-KBNpuede recibir valores distintos de'0'y'1'. Solo hay dos nombres de condición definidos, pero eso no garantiza que no lleguen otros valores. - Los atributos del propio archivo (la longitud de registro, si es de longitud variable,
FILE STATUS). Esto no se puede saber sin mirar elENVIRONMENT DIVISIONy elFD.
- Si esta definición en sí se importa mediante
Si se equivocó en las preguntas 1 y 3, vuelva a la tabla de dígitos y bytes de la sección 5.3. Los errores de interpretación en COBOL casi siempre empiezan por aquí.
9. Puntos habituales donde se atasca la lectura
Por último, resumimos los puntos donde los principiantes suelen atascarse con bastante frecuencia.
Pensar que REDEFINES es «otra variable»
No es así. Se está leyendo la misma zona con otra forma. Si se modifica una de las dos, la forma en que se ve la otra también cambia.7
Pensar que 88 es «un bool independiente»
No es así.
Solo se le ha dado un nombre al valor del campo inmediatamente anterior. SET WS-OK TO TRUE, por detrás, coloca el valor correspondiente en el campo base.3
Ignorar el COPY y leer solo el cuerpo
El archivo que tiene abierto todavía es, en el mejor de los casos, la mitad del conjunto. Es normal que las definiciones de campo, las banderas comunes y las host variables estén, en su mayor parte, fuera de él.9
Pensar que MOVE es una simple asignación
MOVE no es un simple memcpy.
Según el tipo del campo de destino, puede implicar conversión, ajuste de dígitos, relleno con ceros, truncamiento, y edición o edición inversa.17
Subestimar el efecto del .
El . en COBOL pesa más de lo que uno imagina.
En código antiguo sin cierre explícito, si se malinterpreta hasta dónde cierra ese punto, se lee mal el flujo de control.12
Pensar que packed decimal o EBCDIC son «datos corruptos»
No siempre están corruptos. Con bastante frecuencia, simplemente no son una cadena de caracteres desde el principio, o no están en ASCII.46
Pensar que lo que sigue a OCCURS DEPENDING ON está en una posición fija
Los campos que siguen a una tabla de longitud variable pueden cambiar de posición según el valor. Si se lee con la mentalidad de longitud fija, todos los cálculos de desplazamiento (offset) quedan desalineados.8
10. Tabla de referencia rápida
| Palabra encontrada | Qué pensar primero |
|---|---|
01 |
El nivel superior de un registro o grupo. A partir de aquí se capta el panorama general |
88 |
El nombre con significado de una bandera o código de estado. La clave para leer las bifurcaciones |
PIC X(...) |
Campo de caracteres |
PIC 9(...) / S9(...)V... |
Campo numérico. Verifique el número de dígitos y la posición del decimal |
COMP |
binario |
COMP-3 |
packed decimal. Es muy probable que sea un importe o una cantidad |
REDEFINES |
Se está interpretando la misma zona de otra forma |
OCCURS |
Arreglo / table |
OCCURS DEPENDING ON |
Longitud variable. Tenga cuidado también con las posiciones posteriores |
FILLER |
No tiene nombre, pero sí longitud |
COPY |
Sin ver el copybook no se ve la forma completa |
PERFORM |
El esqueleto de la ruta principal |
READ / WRITE / REWRITE |
E/S de archivos |
EXEC SQL |
Procesamiento de base de datos |
EXEC CICS |
Procesamiento transaccional |
FILE STATUS |
Código de resultado de la E/S |
11. Resumen
COBOL no es difícil porque sea antiguo. Simplemente, la definición de datos, los archivos externos y el contexto de ejecución están estrechamente entrelazados, por lo que la puerta de entrada inicial cuesta más de ver.
El conjunto mínimo para leerlo, resumido de nuevo, es este:
- Captar el mapa mediante los
DIVISION - Leer primero el
DATA DIVISION - Leer la forma de los campos mediante
PICyUSAGE - Marcar
COMP-3,REDEFINES,OCCURS,88yCOPY - Seguir
PERFORM,READ,WRITEyCALL - Dominar los límites externos mediante
FILE STATUS,EXEC SQLyEXEC CICS - No subestimar cómo actúa el
.
Cuando esto se ve con claridad, COBOL deja de ser una «magia antigua y misteriosa» para convertirse en «un lenguaje de procesamiento de registros». Las tecnologías legadas no dan miedo porque su nombre sea antiguo; simplemente, si se equivoca la escala con la que se mira al principio, se vuelve de repente difícil de entender. Si la escala del mapa es la correcta, se lee sorprendentemente bien.
12. Referencias
Estas son las principales referencias citadas en el cuerpo del artículo. Los números en superíndice del texto son enlaces directos a esta lista, y la flecha al final de cada elemento permite volver a la posición original.
-
IBM, “Reference format” / IBM, “Area A or Area B” / Micro Focus, “Fixed Format” ↩ ↩2 ↩3 ↩4
-
IBM, “Level-numbers” ↩ ↩2
-
IBM, “Format 2: condition-name value” ↩ ↩2
-
IBM, “Examples: numeric data and internal representation” ↩ ↩2 ↩3 ↩4
-
IBM, “PACKED-DECIMAL (COMP-3)” ↩ ↩2
-
IBM, “The EBCDIC character set” / IBM, “Handling differences in ASCII SBCS and EBCDIC SBCS characters” ↩ ↩2 ↩3 ↩4 ↩5
-
IBM, “Cláusula REDEFINES” ↩ ↩2
-
IBM, “OCCURS DEPENDING ON clause” ↩ ↩2
-
IBM, “Instrucción COPY” ↩ ↩2
-
IBM, “PERFORM statement” / IBM, “Procedure division structure” ↩
-
IBM, “Scope terminators” / IBM, “Coding a choice of actions” ↩ ↩2 ↩3 ↩4
-
IBM, “FILE STATUS clause” / IBM, “Using file status keys” ↩
-
IBM, “Codificación de programas COBOL que se ejecutan bajo CICS” ↩
-
IBM, “Computational items” ↩
-
IBM, “Elementary move rules” ↩
Artículos relacionados
Artículos recientes con las mismas etiquetas para profundizar en temas cercanos.
No confíe en el valor decodificado de un código QR sin validarlo — que la corrección de errores funcione no garantiza que el valor sea correcto
La corrección de errores del QR no garantiza que el valor leído sea correcto. Con pruebas reales y dos decodificadores explicamos por qué...
Integrar PowerShell con una API REST ── el uso práctico de Invoke-RestMethod
Resumen práctico para llamar a APIs internas y REST de SaaS desde PowerShell: cabeceras de autenticación, JSON en japonés sin errores de ...
Diseño de códigos en sistemas empresariales ── Cómo definir códigos de producto y cliente, y el dígito de control
Guía práctica para diseñar códigos de producto y cliente en sistemas empresariales: código significativo frente a secuencial, fórmulas de...
El manejo de incidentes no termina con la recuperación ── el modelo de postmortem (prevención de recurrencia) para equipos de desarrollo pequeños
Si un incidente se cierra con «arreglarlo y disculparse», se repite. Adaptamos el postmortem blameless a equipos pequeños: plantilla de u...
Introducción a ADR (Architecture Decision Record) — El método mínimo para dejar constancia de «por qué se eligió este diseño» en desarrollos de pequeña escala
El código no dice «por qué» se hizo así. Aprenda a registrar cada decisión de diseño con ADR (Architecture Decision Record): plantilla, t...
Temas relacionados
Estas páginas sitúan el tema en un contexto más amplio de servicios y decisiones.
Temas técnicos de Windows
Portal sobre desarrollo de Windows, investigación de fallos y aprovechamiento de activos existentes.
Servicios relacionados con este tema
El artículo está directamente relacionado con los siguientes servicios.
Consultoría técnica y revisión de diseño
Un tema que encaja bien con la consultoría técnica y la revisión de diseño, ya que abarca desde cómo interpretar los activos COBOL existentes hasta el punto de entrada para las modificaciones, la comprensión de los límites externos y la organización del diagnóstico previo a una migración.
Investigación de fallos y causas
La atención de incidencias justo después de una transferencia de responsabilidad, así como el rastreo de dónde se producen las inconsistencias en los activos COBOL, son tareas que avanzan bien como investigación de fallos y análisis de causa raíz.
Preguntas frecuentes
Preguntas habituales en las consultas sobre el tema del artículo.
- ¿Por dónde debo empezar a leer el código fuente COBOL?
- Leer solo el PROCEDURE DIVISION le dará únicamente la mitad del panorama. COBOL es, antes que un lenguaje de lógica, un lenguaje de definición de registros muy marcado, así que primero conviene mirar el DATA DIVISION. El orden de lectura seguro consiste en revisar todos los COPY y comprobar los copybooks, listar las definiciones de registro de nivel 01, leer la forma de cada campo mediante PIC y USAGE, buscar READ, WRITE, CALL, EXEC SQL y EXEC CICS para captar las entradas, salidas y los límites externos, y finalmente seguir solo la ruta principal a través de la cadena de PERFORM que arranca al inicio del PROCEDURE DIVISION.
- ¿Qué significa PIC S9(7)V99 COMP-3?
- PIC indica la forma del campo y USAGE indica en qué representación se guarda. S9(7)V99 es un número con signo de 7 dígitos enteros más 2 dígitos decimales, pero la V es un punto decimal lógico: no hay ningún carácter de punto real en los datos. COMP-3 es packed decimal y aparece con frecuencia en campos de importes, impuestos, cantidades o tasas. Es normal que se vea como datos corruptos si se lee como texto, así que examinar un volcado con la mentalidad de un CSV o de UTF-8 lleva directo al error.
- ¿Cómo debo entender el nivel 88 y REDEFINES en COBOL?
- El nivel 88 no es una variable booleana independiente, sino un nombre de condición (condition-name) que se le da al valor del campo inmediatamente anterior. SET WS-OK TO TRUE, por detrás, coloca el valor correspondiente en el campo base. REDEFINES es un mecanismo para ver la misma zona de memoria con otra forma; no es una copia, sino algo más cercano a un union del estilo de C. Como modificar una de las formas cambia también cómo se ve la otra, esta técnica aparece con frecuencia para distinguir el tipo de registro dentro de una misma zona.
- ¿Qué hacer cuando hay tantas instrucciones COPY que no se puede ver el conjunto completo?
- COPY es un include que se resuelve en tiempo de compilación, así que el código fuente que tiene abierto puede no ser todavía la forma completa. Es bastante habitual que las definiciones de registro, las banderas comunes, las host variables para SQL y las interfaces externas estén metidas dentro de los copybooks. Cuando resulta difícil de leer, lo más rápido es comprobar si puede consultar el código fuente ya expandido o el compiler listing; IBM Enterprise COBOL cuenta además con una opción llamada MDECK que vuelca el código fuente de entrada después del procesamiento de biblioteca.
Perfil del autor
Página de presentación del autor del artículo.
Go Komura
Representante de KomuraSoft LLC
Especializado en desarrollo de software para Windows, consultoría técnica e investigación de fallos, sobre todo en proyectos con sistemas existentes y errores difíciles de reproducir.