COBOL (akronym for common business-oriented language) er et programmeringsspråk som har vært i utstrakt bruk for koding av økonomiske og administrative transaksjonssystemer. Det ble konstruert i 1959, initiert av amerikanske forsvarsmyndigheter. COBOL brukes fortsatt i mange eksisterende systemer fordi disse ofte er store, godt uttestet og ikke er utsatt for sterke endringskrav. COBOL og systemene kodet i dette språket ble sterkt fokusert i forbindelse med år 2000-problemet.

Utbredelse På slutten av 1990-tallet gjennomførte Gartner Group en studie som viste at av et estimert antall på 300 milliarder kodelinjer av eksisterende kode er åtti prosent, dvs. rundt 240 milliarder linjer, skrevet i COBOL. De fant også ut at mer enn halvparten av driftskritiske nye applikasjoner fortsatt programmeres i COBOL.

Syntaks Filosofien bak COBOL er å kunne kode gjennom bruk av tilnærmet normalspråk. En kan alternativt bruke en mer kompakt notasjon.

En typisk egenskap i COBOL er at eksterne data blir formatert sammen med definisjonene av variablene i Data Division ved hjelp av egenskapen PICTURE, ikke i prosedyreanvisninger som for eksempel i C.

Procedure division Prosedyrer The sections and paragraphs in the procedure division (collectively called procedures) can be used as labels and as simple subroutines. Unlike in other divisions, paragraphs do not need to be in sections.

Execution goes down through the procedures of a program until it is terminated. To use procedures as subroutines, the verb is used.

A statement somewhat resembles a procedure call in a newer languages in the sense that execution returns to the code following the statement at the end of the called code; however, it does not provide a mechanism for parameter passing or for returning a result value. If a subroutine is invoked using a simple statement like , then control returns at the end of the called procedure. However, is unusual in that it may be used to call a range spanning a sequence of several adjacent procedures. This is done with the construct:

PROCEDURE so-and-so. PERFORM ALPHA PERFORM ALPHA THRU GAMMA STOP RUN. ALPHA. DISPLAY 'A'. BETA. DISPLAY 'B'. GAMMA. DISPLAY 'C'.

The output of this program will be: "A A B C".

also differs from conventional procedure calls in that there is, at least traditionally, no notion of a call stack. As a consequence, nested invocations are possible (a sequence of code being 'ed may execute a statement itself), but require extra care if parts of the same code are executed by both invocations. The problem arises when the code in the inner invocation reaches the exit point of the outer invocation. More formally, if control passes through the exit point of a invocation that was called earlier but has not yet completed, the COBOL 2002 standard stipulates that the behavior is undefined.

The reason is that COBOL, rather than a "return address", operates with what may be called a continuation address. When control flow reaches the end of any procedure, the continuation address is looked up and control is transferred to that address. Before the program runs, the continuation address for every procedure is initialized to the start address of the procedure that comes next in the program text so that, if no statements happen, control flows from top to bottom through the program. But when a statement executes, it modifies the continuation address of the called procedure (or the last procedure of the called range, if was used), so that control will return to the call site at the end. The original value is saved and is restored afterwards, but there is only one storage position. If two nested invocations operate on overlapping code, they may interfere which each other's management of the continuation address in several ways.

The following example (taken from ) illustrates the problem:

LABEL1. DISPLAY '1' PERFORM LABEL2 THRU LABEL3 STOP RUN. LABEL2. DISPLAY '2' PERFORM LABEL3 THRU LABEL4. LABEL3. DISPLAY '3'. LABEL4. DISPLAY '4'.

One might expect that the output of this program would be "1 2 3 4 3": After displaying "2", the second causes "3" and "4" to be displayed, and then the first invocation continues on with "3". In traditional COBOL implementations, this is not the case. Rather, the first statement sets the continuation address at the end of so that it will jump back to the call site inside . Den andre setter returen på slutten av , men endrer ikke fortsettelsesadressen til , og forventer at den skal være standard fortsettelse. Således, når den indre påkallelsen kommer til slutten av , hopper den tilbake til den ytre , programmet stopper etter å ha skrevet ut "1 2 3". I TinyCOBOL blander ikke de to -utsagnene seg med hverandre og utmatingen er "1 2 3 4 3". Adferden i slike tilfeller er ikke portabel.

En konsekvens er at ikke kan skrive rekursiv kode.

MOVE 1 TO A PERFORM LABEL STOP RUN. LABEL. DISPLAY A IF A < 3 ADD 1 TO A PERFORM LABEL END-IF DISPLAY 'END'.

Noen COBOL-kompilatorer skriver ut "1 2 3 END END END", mens IBM COBOL skriver ut "1 2 3 END END END END ..."; "END" skrives ut om og om igjen i en evig løkke. Siden det er begrenset lagringsplass, blir sikkerhetskopiene overskrevet i løpet av rekursive påkallinger, og alt som kan gjenopprettes er å hoppe tilbake til .

Utsagn COBOL 2014 har 47 verb, som kan grupperes i underkategorier.

Kontrollflyt COBOL's betingelser er og . er en switch-setning som evaluerer flere verdier og tilstander. Dette kan implementere beslutningstabeller som kontrollerer en CNC lathe:

EVALUATE TRUE ALSO desired-speed ALSO current-speed WHEN lid-closed ALSO min-speed THRU max-speed ALSO LESS THAN desired-speed PERFORM speed-up-machine WHEN lid-closed ALSO min-speed THRU max-speed ALSO GREATER THAN desired-speed PERFORM slow-down-machine WHEN lid-open ALSO ANY ALSO NOT ZERO PERFORM emergency-stop WHEN OTHER CONTINUE END-EVALUATE

definerer løkker som utføres inntil en tilstand er sann. Det brukes også til å kalle prosedyrer eller rekker av prosedyrer. og kaller delprogrammer og metoder. Navnet på delprogrammet/metoden inneholdes i en streng som kan være en litteral eller et dataelement. Parameterere kan sendes etter referanse, etter innhold eller etter verdi (hvis en funksjonsprototype er tilgjengelig). avlaster delprogrammer fra minnet. får programmet å hoppe til en spesifisert prosedyre.

er en retursetning og stanser programmet. har seks formater: Den kan brukes som en retur-setning, en avbrudd-setning, en fortsett-setning, en sluttmarkør eller til å forlate en prosedyre.

Unntakshåndtering oppstår fra et -utsagn og oppfanges av en håndterer, eller , som er definert i -porsjonen av prosedyredivisjonen. Deklarativene er seksjoner som begynner med et utsagn som spesifiserer feilene som skal håndteres. Unntak kan være navn eller objekter. brukes i et deklarativ for å hoppe til utsagnet etter det som reiste unntaket eller til en prosedyre utenfor . I motsetning til andre språk kan uoppdagede unntak ikke avslutte programmet, og programmet kan fortsette upåvirket.

Inn- og utmating Inn- og utmating fra og til datafil er håndtert av , , , og sammen med tre andre utsagn: som oppdaterer en record; , som velger påfølgende poster for tilgang ved å finne en record med en bestemt nøkkel; og , som frigjør en lås på den siste record som er aksessert.

Brukerinteraksjon skjer ved å bruke og .

Datamanipulasjon Følgende verb manipulerer data: setter dataelementer til deres standardverdier. tildeler verdier til dataelementer ; MOVE CORRESPONDING tildeler tilsvarende recordfelter med samme navn. , som har 15 formater, kan modifisere indekser, tildele objektreferanser og endre tabellkapasiteter. , , , , og håndterer aritmetikk. og , håndterer dynamisk hukommelse. validerer og distribuerer data som spesifisert i elementbeskrivelsen i datadivisjonen. og konkatinerer og splitter strenger. erstatter instanser av spesifiserte delstrenger innenfor en streng. søker i en tabell etter den første oppføringen som tilfredsstiller en betingelse

Datafiler og tabeller blir sortert ved å bruke og verbet slår sammen og sorterer datafiler. Verbet gir recorder for å sortere og returnerer sorterte recorder i rekkefølge.

Terminering av gyldighetsområde og , kan også inneholde utsagn. Slike utsagn kan termineres på to måter: av en periode (implisitt terminering), som terminerer alle uterminerte utsagn, eller av en terminator av gyldighetsområde, som terminerer den nærmeste matchende åpne setning.

*> Terminator periode («implisitt terminering») IF invalid-record IF no-more-records NEXT SENTENCE ELSE READ record-file AT END SET no-more-records TO TRUE.

*> Terminatorer av gyldighetsområde («eksplisitt terminering») IF invalid-record IF no-more-records CONTINUE ELSE READ record-file AT END SET no-more-records TO TRUE END-READ END-IF END-IF

Nøstede setninger som termineres med en periode er en vanlig kilde til programvarefeil. For eksempel:

IF x DISPLAY y. DISPLAY z.

Her er intensjonen å vise y og z hvis betingelsen x er sann. Z vil likevel bli vist uansett verdien av x fordi IF termineres feilaktig etter .

En annen programvarefeil er et resultat av dinglende else, når to IF utsagn kan assosieres med en ELSE.

IF x IF y DISPLAY a ELSE DISPLAY b.

I fragmentet ovenfor, er ELSE assosiert med    istedet for   , noe som forårsaker en programvarefeil. Eksplisitte terminatorer av gyldighetsområde, vil hindre kravet om at    plasseres etter den indre IF.

Selvmodifiserende kode Den opprinnelige (1959) COBOL-spesifikasjonen støttet det beryktede    utsagnet, for hvilke mange kompilatorer genererte selvmodifiserende kode. X og Y er prosedyrenavn, og et enkelt    utsagn i prosedyren X utført etter et slikt -utsagn betyr   . Eksempler på kompilatorer som støtter eller har støttet selvmodifiserende kode er:

GNU Cobol Micro Focus Visual COBOL 2.2 Fujitsu NetCOBOL IBMs Enterprise COBOL for z/OS

Det ble ansett som foreldet i COBOL 1985 standarden og slettet i 2002.

-utsagnet var dårlig ansett fordi det undergravde «sammenhengens lokalitet» og gjorde et programs overordnede logikk vanskelig å oppfatte. Som lærebokforfatteren Daniel D. McCracken skrev i 1976: «[Når] noen som aldri har sett programmet før må bli kjent med det så raskt som mulig, noen ganger under kritisk tidspress fordi programmet har feilet ... synet av et GO TO-utsagn i en paragraf i seg selv, som signaliserer eksistensen av et ukjent antall ALTER-utsagn på ukjente steder gjennom programmet, skaper frykt i hjertet til den modigste programmereren.»

Hallo, verden Eksempelprogrammet «Hallo, verden» i boken Programmeringsspråket C, ble publisert i 1978. Et lignende COBOL-program for stormaskiner ville ha blitt utskrevet gjennom Job Control Language (JCL), svært sannsynlig ved hjelp av en hullkortleser, og hullkort med 80 kolonner hullkort.

IDENTIFICATION DIVISION. PROGRAM-ID. HALLO-VERDEN.

ENVIRONMENT DIVISION.

DATA DIVISION.

PROCEDURE DIVISION. PARA-1. DISPLAY "Hallo, verden.".

EXIT PROGRAM. END PROGRAM HALLO-VERDEN.

eller i kompakt form:

Identification Division. Program-ID. HALLO-VERDEN. Procedure Division. Display "Hallo, verden.". STOP RUN.

Utlistingen nedenfor, med en tom DATA DIVISION, ble testet ved å bruke Linux på stormaskinen IBM System/370 med en Hercules emulator som kjører MVS 3.8J. Teksten i JCL ble skrevet i juli 2015, og er hentet fra et kurs i Hercules som ble avholdt av Jay Moseley. I tråd med COBOL-programmeringen på denne tiden, er HALLO VERDEN vist med storbokstaver.

//COBUCLG JOB (001),'COBOL BASE TEST', 00010000 // CLASS=A,MSGCLASS=A,MSGLEVEL=(1,1) 00020000 //BASETEST EXEC COBUCLG 00030000 //COB.SYSIN DD * 00040000 00000* VALIDATION OF BASE COBOL INSTALL 00050000 01000 IDENTIFICATION DIVISION. 00060000 01100 PROGRAM-ID. 'HALLO'. 00070000 02000 ENVIRONMENT DIVISION. 00080000 02100 CONFIGURATION SECTION. 00090000 02110 SOURCE-COMPUTER. GNULINUX. 00100000 02120 OBJECT-COMPUTER. HERCULES. 00110000