GNU COBOL
Bem, eles disseram que não poderia ser feito. Na verdade, fui eu quem disse que não poderia ser feito. Agora está pronto e um recurso de linguagem obsoleta reimplementado usando o método aplicado.
A pergunta afirma:
Se qualquer espaço em branco ou instrução adicional (que não interrompa o fluxo do código) for adicionado ao código-fonte, ele deverá ser refletido no tempo de execução (após a compilação, se aplicável).
Qualquer quantidade de material pode ser inserida antes dos três DISPLAY
s que causam o início da saída e qualquer coisa após os DISPLAY
"interromperia o fluxo do código", então tudo bem.
O COBOL costumava ter um TRACE
verbo (instrução) que simplesmente listava os números das linhas de origem conforme eram executados (sem acesso ao número da linha no programa). Embora de uso limitado, incluí uma implementação do TRACE.
ID Division.
Program-ID. HIWHERE.
ENVIRONMENT DIVISION.
configuration section.
source-computer. TinkerToy with debugging mode.
Procedure Division.
Declaratives.
Debug-Declaratives Section.
Use For Debugging on a b
.
Debug-Declaratives-Paragraph.
Display Debug-Line "!"
.
End Declaratives
.
Main-Program Section.
DISPLAY "Perform"
Display "Hello World, from line " no advancing Perform b
display "GO TO"
Display "Hello World, from line " no advancing GO TO a
.
a.
dISPLay "Fall through"
Display "Hello World, from line " no advancing. b.
The-Last-bit-OF-the-PROGRAM.
GOBACK
.
A saída é
Perform
Hello World, from line 18!
GO TO
Hello World, from line 20!
Fall through
Hello World, from line 23!
Como uma demonstração do poder e da flexibilidade de escrever a linguagem, este exemplo usa letras maiúsculas, minúsculas e totalmente maiúsculas, tudo ao mesmo tempo. Não importa, pois quando processado, tudo é "dobrado" para MAIÚSCULAS.
A única maneira padrão de COBOL de obter um número de linha de origem no programa em execução, a partir do programa em execução, é com a DEBUGGING
DECLARATIVE
. Dentro de SECTION
, estritamente dentro de um parágrafo dentro de SECTION
, de um declarativo, você tem acesso ao registro especial DEBUG-LINE
. Contém o número da linha de origem do verbo (instrução) que causou a transferência do controle para um nome de procedimento específico (parágrafo ou SECTION
).
Portanto, com PERFORM
, ou GO TO
, ou "falha", o parágrafo nos declarativos de depuração SECTION
é executado.
OK, mas DISPLAY
não causa transferência de controle.
Sem problemas. Coloque-o na mesma linha da transferência de controle.
Problema, pois se "qualquer espaço em branco ou instrução adicional (que não interrompa o fluxo do código) for adicionado ao código-fonte, ele deverá ser refletido no tempo de execução (após a compilação, se aplicável)".
Portanto, coloque-o na mesma linha, mas na frente de uma transferência de controle, divida o conteúdo do arquivo DISPLAY
em duas partes (lembre-se: "Nesse contexto, queremos o primeiro número da linha da instrução que gera a string a ser exibida" ) e produza a primeira parte antes da transferência do controle e a segunda parte do DEBUG-LINE
, uma vez dentro do procedimento de depuração.
O truque final é para o "fall through" ("procedures" podem ser PERFORM
editados, podem ser o alvo de um GO TO
ou podem ser inseridos simplesmente sendo a próxima linha). Nesse caso, coloque o DISPLAY
na linha que define o procedimento, mas na frente da definição .
Os nomes dos "procedimentos" ( a
e b
) foram severamente abreviados para permitir que eles se ajustem à mesma linha de origem que a DISPLAY
. Estritamente, um nome de procedimento COBOL deve começar em algum lugar da coluna oito à coluna 11. No entanto, atualmente, a sintaxe é muito mais tranqüila quanto a isso. Na medida em que eu possa definir um nome de procedimento na mesma linha que algum código. Inclusive incorporado no código. É necessário cuidado e um ponto final ocasional.
Em PROCEDURE DIVISION
cada ponto final mostrado é necessário, e não mais.
Compilar:
cobc -x -g hiwhere.cbl
Para executar (linux):
COB_SET_DEBUG=Y ./hiwhere
Finalmente, o retorno do TRACE (sem READY / RESET).
ID Division.
Program-ID. tRacE.
ENVIRONMENT DIVISION.
configuration section.
source-computer. TinkerToy with debugging mode.
Procedure Division.
Declaratives.
Debug-Declaratives Section.
Use For Debugging on a
.
Debug-Declaratives-Paragraph.
Display Debug-Line
.
End Declaratives
.
Main-Program Section.
* Just append "perform a" to a single-line statement.
DISPLAY "1" . perform a
Display "2" . perform a
display "3" . perform a
* Or prepend "perform a." for a multi-line statement, or a
* statement which won't "come back".
perform a. GOBACK
.
a.
CONTINUE
.
A saída é:
1
17
2
18
3
19
20
Onde 1, 2 e 3 são emitidos pelas três instruções DISPLAY, e 17, 18, 19 e 20 são os números de linha das linhas "executáveis" (sem depuração).