Technical Capabilities
Having trouble finding what you need?
Get in touch with us, so we can answer your specific questions directly.
Get In Touch

GnuCOBOL -fdec – DEC/VSI COBOL Language Extensions

Overview

-fdec is a compatibility mode Sector7 has built on top of GnuCOBOL, the open-source COBOL compiler, that lets DEC and VSI COBOL source code, written for OpenVMS, compile and run on Linux. It recognises the VMS-specific syntax, storage rules, and status conventions those programs rely on, so applications that call OpenVMS RTL routines or depend on RMS-style file handling can be rebuilt without rewriting the source.

The flag is a single, explicit gate: with -fdec off, every extension it enables becomes a compile-time error rather than a silent reinterpretation, so a standard COBOL program compiles identically whether or not the flag is used. Where Linux cannot reproduce an OpenVMS-specific mechanism exactly, such as link-time symbol resolution or VAX floating-point formats, the compiler takes the practical Linux equivalent and documents the difference instead of pretending to be VMS.

Architecture and components

Under -fdec, a compiled program is wired across four layers. Turning the flag off does not remove functionality gradually: every extension below becomes a compile-time error, and a standard COBOL program compiles identically whether or not the flag is used.

OpenVMS equivalentLinux componentRole
VSI COBOL compiler front endcobc with -fdecParses VSI syntax and applies VSI storage, naming, and status semantics.
OpenVMS RTL condition macrosLow-bit IS SUCCESS / IS FAILURE support in the runtimeTests the OpenVMS success/failure convention at runtime.
OpenVMS image linker symbol resolutionDEC-spelling fallback resolverFalls back to the DEC-style symbol spelling so a standard-built caller can still find an -fdec-built routine.
RMS (Record Management Services)External file handlerTranslates COBOL file operations into calls Sector7's VX/RMS understands.
RMS on OpenVMSVX/RMS (Sector7's RMS-on-Linux runtime)Performs the actual file opens, reads, writes, and key lookups.
VMS symbolic status constantsBuilt-in constant table, 11,388 entriesResolves VALUE IS EXTERNAL name constants at compile time instead of at link time.
VMS RTL / system-service call signaturesBuilt-in routine table, 565 routinesPads call arguments to each routine's expected count and remaps a handful of item-list services.

How a routine call resolves

For a program calling an OpenVMS RTL routine, for example CALL "LIB$PUT_OUTPUT" USING BY DESCRIPTOR MSG RETURNING ST, the compiler works through the call in a fixed sequence:

  1. Accepts the VMS-style routine name, the BY DESCRIPTOR call mode, and a RETURNING target.
  2. Looks up the routine in the built-in arity table and pads the argument list to the count that routine expects. Supplying too many arguments is a hard compile error.
  3. Emits each BY DESCRIPTOR argument as a 64-bit OpenVMS string descriptor.
  4. Maps the routine's return value into the RETURNING / GIVING item if present, otherwise into RETURN-CODE.
  5. Compiles IS SUCCESS / IS FAILURE tests against that status using the OpenVMS low-bit convention: bit 0 set means success.
  6. If the routine being called was itself built with -fdec, its exported symbol uses the DEC spelling. The runtime's fallback resolver tries that spelling automatically, so callers do not need to know which mode built the callee.

How file I/O routes through RMS

Any program that has files defaults to routing file I/O through VX/RMS:

  1. Every OPEN, READ, WRITE, REWRITE, DELETE, START, and CLOSE is handed to the external file handler.
  2. The handler builds the record and key blocks VX/RMS expects and calls through to the underlying open, create, connect, get, put, update, delete, and find operations.
  3. Each file's last RMS status is kept per file, ready to support the RMS status special registers.
  4. Setting an explicit file-handler flag overrides the RMS default and switches file I/O back to the compiler's built-in file layer.

Example: calling an OpenVMS routine

This program calls an OpenVMS RTL routine by descriptor and checks the result with the low-bit success and failure convention, no more code than a standard CALL needs:

IDENTIFICATION DIVISION.
PROGRAM-ID. LIB-PUT-OUTPUT-DEMO.

DATA DIVISION.
WORKING-STORAGE SECTION.
01  MESSAGE-TEXT PIC X(42)
    VALUE "Hello from COBOL via LIB$PUT_OUTPUT".
01  RETURN-STATUS PIC S9(9) COMP VALUE ZERO.

PROCEDURE DIVISION.
    CALL "LIB$PUT_OUTPUT"
         USING BY DESCRIPTOR MESSAGE-TEXT
         RETURNING RETURN-STATUS
    END-CALL.

    IF RETURN-STATUS IS FAILURE
       DISPLAY "LIB$PUT_OUTPUT failed, status " RETURN-STATUS
    END-IF.

    GOBACK.

Compiled with:

cobc -fdec prog.cob

Language extensions

-fdec activates a set of reserved words and syntax forms that only carry VSI meaning when the flag is on. With the flag off, using any of them is a compile error rather than a silent reinterpretation.

KeywordMeaning under -fdec
DESCRIPTORCALL ... USING BY DESCRIPTOR call mode.
POINTER-64USAGE POINTER-64 on 64-bit-pointer builds.
SUCCESS / FAILURESET ... TO SUCCESS/FAILURE, ... IS SUCCESS/FAILURE.
IDENTPROGRAM-ID. name WITH IDENT "literal", a module version string.
REGARDLESSREAD / START ... REGARDLESS [OF LOCK].
PRIORREAD ... PRIOR, equivalent to READ PREVIOUS.
LOCK-HOLDING, DEFERRED-WRITE, EXTENSION, FILL-SIZE, MASS-INSERT, PREALLOCATION, PRINT-CONTROL, WINDOWAPPLY clauses carrying RMS tuning hints.
ALLOWING, OTHERS, READERS, UPDATERS, WRITERSSharing and locking modifiers on OPEN / READ / WRITE / REWRITE / START.

Also recognised, without adding new reserved words: $ inside a user-defined word (not as the first character), REFERENCE OF as an equivalent to ADDRESS OF, VALUE IS EXTERNAL name, VALUE IS REFERENCE data-name or a literal, GIVING on PROCEDURE DIVISION, and logical-name mnemonics in SPECIAL-NAMES bound to environment name, environment value, and argument number or value.

Feature reference

Routine and call interop

FeatureBehaviour under -fdec
CALL ... USING BY DESCRIPTOREmits a 64-bit OpenVMS string descriptor per argument. Arguments must be alphanumeric. Caller-side only.
Routine arity paddingPads the call's argument list to the routine's expected count using the built-in 565-routine table. A handful of item-list services are remapped to their local equivalents.
USAGE POINTER-64Accepted on 64-bit-pointer builds, a hard error otherwise.
PROCEDURE DIVISION GIVING itemVSI return-value semantics: the named item holds the routine's return value on exit. The item can live in working storage or linkage.
CALL GIVING / RETURN-CODE mappingThe called routine's return value lands in the GIVING item if present, otherwise in RETURN-CODE; interoperates with IS SUCCESS / IS FAILURE.

Status conditions

FeatureBehaviour under -fdec
SET status TO SUCCESS / TO FAILURESets the OpenVMS low-bit condition state (bit 0 set means success). Targets are validated as word or longword numeric items.
status IS SUCCESS / IS FAILURECompiles to a runtime low-bit test on the status item.

Data initialisation

FeatureBehaviour under -fdec
VALUE IS EXTERNAL nameInitialises an integer item from a VMS symbolic constant. Hyphens and underscores are treated as equivalent, so SS$-NORMAL and SS$_NORMAL resolve the same way. Resolved from the built-in 11,388-entry table at compile time; an unknown name is a hard compile error, never a silent zero.
-fdec-constants=<file>Supplies additional application-level constants not in the built-in table. Accepts simple NAME = value lines. Checked before the built-in table, and can be repeated.
VALUE IS REFERENCE data-nameInitialises a pointer to the address of static data. The target may be declared later in the program.
VALUE IS REFERENCE numeric-literalInitialises a pointer to a literal integer address.
SET pointer TO REFERENCE OF itemThe VSI address-of spelling, equivalent to ADDRESS OF.

Storage and numeric model

FeatureBehaviour under -fdec
Binary storage model-fdec implies word-sized COMP for 1 to 4 digits, longword for 5 to 9, and quadword for 10 to 18, with native (little-endian) byte order. Each part can be overridden explicitly.
Floating-point usagesCOMP-1 is IEEE single precision, COMP-2 is IEEE double precision, and FLOAT-EXTENDED is treated as an 8-byte synonym for COMP-2, matching the VSI usage rule.

Names and symbols

FeatureBehaviour under -fdec
$ in user-defined wordsAllowed anywhere except as the first character, so names like SYS$TRNLNM are valid.
Hyphen and underscore equivalenceIn user-defined words, _ and - fold together, so C_NINE and C-NINE are the same word. External names (PROGRAM-ID, and constant CALL / ENTRY / CANCEL names) encode a hyphen as an underscore in the exported symbol, matching VSI's own link-symbol spelling.
PROGRAM-ID. name WITH IDENT "literal"A VSI module version string, validated as non-numeric text between 1 and 31 characters.
Logical-name mnemonics in SPECIAL-NAMESLets DISPLAY ... UPON and ACCEPT ... FROM target environment name, environment value, and argument mnemonics. Off OpenVMS, logical names map to environment variables.

Control flow

-fdec turns on OSVS-style PERFORM range semantics by default, matching the dynamic range behaviour described in the VSI reference material: a GO TO between the start and end of a performed range, with multiple logical paths back to the return point. This can be turned off explicitly for programs that need standard PERFORM semantics instead.

File I/O through RMS

Programs with files default to routing every file operation through VX/RMS. This covers sequential, line sequential, relative, and indexed organisation, including alternate keys with duplicates and split keys. An explicit file-handler flag can switch a program back to the compiler's own file layer.

Extended file I/O syntax

Every clause below is a hard compile error without -fdec:

INPUT-OUTPUT SECTION.
FILE-CONTROL.
    SELECT F1 ASSIGN TO "f1.dat"
        ORGANIZATION INDEXED ACCESS DYNAMIC
        RECORD KEY IS SK = R1-A R1-B
        ALTERNATE RECORD KEY IS R1-C WITH DUPLICATES.
I-O-CONTROL.
    APPLY LOCK-HOLDING ON F1.
    APPLY DEFERRED-WRITE ON F1.
    APPLY EXTENSION 100 ON F1.
    APPLY PREALLOCATION 500 ON F1.
    APPLY WINDOW 7 ON F1.
PROCEDURE DIVISION.
    OPEN I-O F1 ALLOWING ALL
    START F1 KEY IS >= SK REGARDLESS
    READ F1 ALLOWING NO OTHERS KEY IS SK END-READ
    READ F1 NEXT REGARDLESS OF LOCK END-READ
    READ F1 PRIOR END-READ
    REWRITE R1 ALLOWING UPDATERS END-REWRITE
    UNLOCK F1 ALL RECORDS
    CLOSE F1
    STOP RUN.

Clause reference

ClauseBehaviour
VALUE OF ID IS "x" (FD)Overrides the file spec given on ASSIGN.
APPLY LOCK-HOLDING ON fSwitches the file to manual lock mode, normally paired with OPEN ALLOWING / READ REGARDLESS.
APPLY DEFERRED-WRITE / EXTENSION n / FILL-SIZE / MASS-INSERT / PREALLOCATION n / WINDOW n / PRINT-CONTROLAccepted as RMS tuning hints with a default-on warning; they have no effect on this build and can be silenced with a compiler flag.
READ f [NEXT/PRIOR] ... REGARDLESS [OF LOCK]Reads while ignoring locks. READ PRIOR is equivalent to READ PREVIOUS.
READ/WRITE/REWRITE ... ALLOWING NO OTHERS / READERS / UPDATERS / WRITERS / ALLNO OTHERS takes a lock; UPDATERS, WRITERS, and ALL take no lock; READERS is treated as NO OTHERS with a warning.
UNLOCK f ALL RECORDSReleases every lock held on the file.
File-name and path rules. VX/RMS uppercases file names to match authentic VMS behaviour (cust.dat becomes CUST.DAT), and it cannot address a Unix path with a dot in any directory component, so programs need to run from dot-free working directories. Unsupported operations never fail silently: they return a file status and name the operation and file on the error stream.

Compatibility with OpenVMS

Every item below is either fully working today or has a defined status. Where Linux cannot reproduce an OpenVMS mechanism exactly, the difference is deliberate and documented rather than silently approximated.

ItemStatus
Call by descriptor, routine arity padding, 64-bit pointerslive
VMS symbolic constants (11,388 entries) and constant file supplementslive
Pointer initialisation by reference and address-oflive
Success/failure condition handling, GIVING return valueslive
$ in words, hyphen/underscore equivalence, module version stringslive
VSI binary storage model and IEEE float usageslive
OSVS-style PERFORM rangelive
File I/O through VX/RMS, including indexed files and split keyslive
Extended file I/O syntax (REGARDLESS, ALLOWING, VALUE OF ID, APPLY hints)live
RMS status special registersv1 soon
Sharing mode wired through to the file control descriptor on OPEN ALLOWINGv1 soon
Multiple APPLY phrases in a single clausev1 soon
Full partial-spec merge on VALUE OF IDv1 soon
Callee-side PROCEDURE DIVISION USING BY DESCRIPTORv2
19 to 31 digit octaword COMPout of scope
VAX floating-point bit-pattern emulationout of scope
Embedded SQL and repository featuresout of scope, handled separately by SQL$PRE – COBOL

Deliberate differences from OpenVMS

DifferenceReason
VALUE IS EXTERNAL resolves at compile time, not link timeThere is no OpenVMS linker on Linux, so constants come from the built-in table instead.
The word/longword-only restriction on VALUE EXTERNAL is not enforcedAny numeric integer item is accepted, a deliberately permissive superset.
No VAX floating-point emulationVAX-format float data is converted upstream, so the compiler only ever sees IEEE values.
External names encode a hyphen as a single underscore, not twoMatches the VSI link-symbol spelling exactly, and the runtime resolver bridges both spellings automatically.
File names are uppercased and paths cannot contain dotsCarries over authentic VMS RMS file-naming rules.

Quick reference

Flags

FlagEffect
-fdecMaster switch. Turns on every extension above; off, each one is a compile error. Implies OSVS PERFORM range, the word/longword/quadword storage model, native byte order, and RMS file I/O, each individually overridable.
-fdec-constants=<file>Loads additional VALUE IS EXTERNAL constants. Checked before the built-in table. Repeatable.
-fno-perform-osvsTurns off the OSVS PERFORM range implied by -fdec.
-fbinary-size= / -fbinary-byteorder=Overrides the storage model implied by -fdec.
-fcallfh=EXTFHUses the compiler's own file layer instead of VX/RMS.
-Wno-dec-hintSilences the default warnings for accepted-and-ignored RMS tuning clauses.

Interop cheat sheet

CALL "R" USING BY DESCRIPTOR X RETURNING S
01 S PIC S9(9) COMP VALUE EXTERNAL SS$_NORMAL.
01 P USAGE POINTER VALUE REFERENCE ITEM.
SET S TO SUCCESS
IF S IS FAILURE
PROCEDURE DIVISION GIVING RET-STAT.
SET P TO REFERENCE OF ITEM.
PROGRAM-ID. NAME WITH IDENT "V1.0".

File I/O cheat sheet

VALUE OF ID IS "x"
APPLY LOCK-HOLDING ON f
OPEN ... ALLOWING ALL
READ ... REGARDLESS [OF LOCK]
READ ... PRIOR
READ/REWRITE ... ALLOWING NO OTHERS/UPDATERS
UNLOCK f ALL RECORDS

Getting started

# Compile a VSI-style program
cobc -fdec -fformat=terminal prog.cob

# Supply application-specific constants
cobc -fdec -fdec-constants=msgcodes.h prog.cob

Frequently Asked Questions

Curious about how Sector7 can facilitate your application migration? Explore our FAQs for expert insights.

Which platforms and COBOL compilers are supported?

OpenVMS x86-64 (V9.2) with native VSI COBOL, Linux with Fujitsu NetCOBOL or GnuCOBOL, and macOS for development and CI. On every platform the vxsql preprocessor and the runtime are the same, so one code base covers all three.

Our OpenVMS application makes use of multiple System Services. How do you support that?

Sector7 has an extensive library of these services running on Linux to perform the same functions as on OpenVMS.  our language conversion tools will adapt the arguments in the procedure API to work with this library.  For instance, VX/COBOL or VX/FORTRAN etc will transform the argument passed BY DESCRIPTOR to a method that will work on Linux.

When the code is compiled on Linux, the compiled objects are linked with the Sector7 library of system services and the program executes on Linux just as it does on OpenVMS, making full use of the various system services.

The critical point here is that there is no need to touch the original source code, the Sector7 tools do all the work.

Which OpenVMS runtime libraries does VX/RT support?

VX/RT provides call-compatible implementations of the major OpenVMS runtime libraries, including LIB$ (general routines), STR$ (string), MTH$ (math), OTS$ (data conversion), and SYS$ (system interface), along with language runtimes such as BAS$, COB$, FOR$, and PAS$. Each family has its own detailed reference page under /technical/.

Which RMS file organizations does VX/RMS support?

All OpenVMS RMS file organizations: indexed, relative, and sequential, along with their associated access modes and record formats. Sequential and relative files map onto plain host files, and indexed files use a keyed store.

Do I have to change my COBOL source, EXEC SQL, or SQLCODE checks?

No. Existing EXEC SQL blocks, CDD includes, and SQLCODE branches keep working. SQL$PRE – COBOL is a drop-in replacement for Rdb's SQL$PRE, so the migration does not require a hand rewrite of the COBOL source.

What does SQL$PRE – COBOL actually produce from my COBOL source?

The vxsql preprocessor rewrites each EXEC SQL block into ordinary COBOL CALL "S7..." statements and writes a binary .cbsql.map sidecar that captures host-variable types and null indicators. The result is still COBOL: it is compiled by your native COBOL compiler and linked against the VX/SQL$PRE runtime. It is not converted into C or C++.

Transform Your Legacy Software Today!

Get In Touch
Unlock the potential of your legacy software with our expert migration services.