🚨 Oracle not porting Rdb to x86 and EOL on Itanium 12/2027 🚨
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 built into Sector7's GnuCOBOL 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.

<div class="s7-tech-embed" data-gnucoboldec-body-embed="1" data-technical-mega-embed="1" lang="en"><h2 id="architecture">Architecture and components</h2><p> Under <code>-fdec</code>, 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. </p><div class="table-wrapper"><table><thead><tr><th>OpenVMS equivalent</th><th>Linux component</th><th>Role</th></tr></thead><tbody><tr><td>VSI COBOL compiler front end</td><td><code>cobc</code> with <code>-fdec</code></td><td>Parses VSI syntax and applies VSI storage, naming, and status semantics.</td></tr><tr><td>OpenVMS RTL condition macros</td><td>Low-bit <code>IS SUCCESS</code> / <code>IS FAILURE</code> support in the runtime</td><td>Tests the OpenVMS success/failure convention at runtime.</td></tr><tr><td>OpenVMS image linker symbol resolution</td><td>DEC-spelling fallback resolver</td><td>Falls back to the DEC-style symbol spelling so a standard-built caller can still find an <code>-fdec</code>-built routine.</td></tr><tr><td>RMS (Record Management Services)</td><td>External file handler</td><td>Translates COBOL file operations into calls Sector7's VX/RMS understands.</td></tr><tr><td>RMS on OpenVMS</td><td>VX/RMS (Sector7's RMS-on-Linux runtime)</td><td>Performs the actual file opens, reads, writes, and key lookups.</td></tr><tr><td>VMS symbolic status constants</td><td>Built-in constant table, 11,388 entries</td><td>Resolves <code>VALUE IS EXTERNAL name</code> constants at compile time instead of at link time.</td></tr><tr><td>VMS RTL / system-service call signatures</td><td>Built-in routine table, 565 routines</td><td>Pads call arguments to each routine's expected count and remaps a handful of item-list services.</td></tr></tbody></table></div><h6>How a routine call resolves</h6><p> For a program calling an OpenVMS RTL routine, for example <code>CALL "LIB$PUT_OUTPUT" USING BY DESCRIPTOR MSG RETURNING ST</code>, the compiler works through the call in a fixed sequence: </p><ol><li>Accepts the VMS-style routine name, the <code>BY DESCRIPTOR</code> call mode, and a <code>RETURNING</code> target.</li><li>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.</li><li>Emits each <code>BY DESCRIPTOR</code> argument as a 64-bit OpenVMS string descriptor.</li><li>Maps the routine's return value into the <code>RETURNING</code> / <code>GIVING</code> item if present, otherwise into <code>RETURN-CODE</code>.</li><li>Compiles <code>IS SUCCESS</code> / <code>IS FAILURE</code> tests against that status using the OpenVMS low-bit convention: bit 0 set means success.</li><li>If the routine being called was itself built with <code>-fdec</code>, 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.</li></ol><h6>How file I/O routes through RMS</h6><p>Any program that has files defaults to routing file I/O through VX/RMS:</p><ol><li>Every <code>OPEN</code>, <code>READ</code>, <code>WRITE</code>, <code>REWRITE</code>, <code>DELETE</code>, <code>START</code>, and <code>CLOSE</code> is handed to the external file handler.</li><li>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.</li><li>Each file's last RMS status is kept per file, ready to support the RMS status special registers.</li><li>Setting an explicit file-handler flag overrides the RMS default and switches file I/O back to the compiler's built-in file layer.</li></ol><h2 id="example">Example: calling an OpenVMS routine</h2><p> 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 <code>CALL</code> needs: </p> <pre><span class="kw">IDENTIFICATION DIVISION.</span> <span class="kw">PROGRAM-ID.</span> LIB-PUT-OUTPUT-DEMO. <span class="kw">DATA DIVISION.</span> <span class="kw">WORKING-STORAGE SECTION.</span> 01 MESSAGE-TEXT PIC X(42) VALUE <span class="str">"Hello from COBOL via LIB$PUT_OUTPUT"</span>. 01 RETURN-STATUS PIC S9(9) COMP VALUE ZERO. <span class="kw">PROCEDURE DIVISION.</span> <span class="kw">CALL</span> <span class="str">"LIB$PUT_OUTPUT"</span> <span class="kw">USING BY DESCRIPTOR</span> MESSAGE-TEXT <span class="kw">RETURNING</span> RETURN-STATUS <span class="kw">END-CALL</span>. <span class="kw">IF</span> RETURN-STATUS <span class="kw">IS FAILURE</span> <span class="kw">DISPLAY</span> <span class="str">"LIB$PUT_OUTPUT failed, status "</span> RETURN-STATUS <span class="kw">END-IF</span>. <span class="kw">GOBACK</span>.</pre> <p>Compiled with:</p> <pre>cobc -fdec prog.cob</pre> <h2 id="language-extensions">Language extensions</h2><p><code>-fdec</code> 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. </p><div class="table-wrapper"><table><thead><tr><th>Keyword</th><th>Meaning under -fdec</th></tr></thead><tbody><tr><td><code>DESCRIPTOR</code></td><td><code>CALL ... USING BY DESCRIPTOR</code> call mode.</td></tr><tr><td><code>POINTER-64</code></td><td><code>USAGE POINTER-64</code> on 64-bit-pointer builds.</td></tr><tr><td><code>SUCCESS</code> / <code>FAILURE</code></td><td><code>SET ... TO SUCCESS/FAILURE</code>, <code>... IS SUCCESS/FAILURE</code>.</td></tr><tr><td><code>IDENT</code></td><td><code>PROGRAM-ID. name WITH IDENT "literal"</code>, a module version string.</td></tr><tr><td><code>REGARDLESS</code></td><td><code>READ</code> / <code>START ... REGARDLESS [OF LOCK]</code>.</td></tr><tr><td><code>PRIOR</code></td><td><code>READ ... PRIOR</code>, equivalent to <code>READ PREVIOUS</code>.</td></tr><tr><td><code>LOCK-HOLDING</code>, <code>DEFERRED-WRITE</code>, <code>EXTENSION</code>, <code>FILL-SIZE</code>, <code>MASS-INSERT</code>, <code>PREALLOCATION</code>, <code>PRINT-CONTROL</code>, <code>WINDOW</code></td><td><code>APPLY</code> clauses carrying RMS tuning hints.</td></tr><tr><td><code>ALLOWING</code>, <code>OTHERS</code>, <code>READERS</code>, <code>UPDATERS</code>, <code>WRITERS</code></td><td>Sharing and locking modifiers on <code>OPEN</code> / <code>READ</code> / <code>WRITE</code> / <code>REWRITE</code> / <code>START</code>.</td></tr></tbody></table></div><p> Also recognised, without adding new reserved words: <code>$</code> inside a user-defined word (not as the first character), <code>REFERENCE OF</code> as an equivalent to <code>ADDRESS OF</code>, <code>VALUE IS EXTERNAL name</code>, <code>VALUE IS REFERENCE data-name</code> or a literal, <code>GIVING</code> on <code>PROCEDURE DIVISION</code>, and logical-name mnemonics in <code>SPECIAL-NAMES</code> bound to environment name, environment value, and argument number or value. </p><h2 id="feature-reference">Feature reference</h2><h6>Routine and call interop</h6><div class="table-wrapper"><table><thead><tr><th>Feature</th><th>Behaviour under -fdec</th></tr></thead><tbody><tr><td><code>CALL ... USING BY DESCRIPTOR</code></td><td>Emits a 64-bit OpenVMS string descriptor per argument. Arguments must be alphanumeric. Caller-side only.</td></tr><tr><td>Routine arity padding</td><td>Pads 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.</td></tr><tr><td><code>USAGE POINTER-64</code></td><td>Accepted on 64-bit-pointer builds, a hard error otherwise.</td></tr><tr><td><code>PROCEDURE DIVISION GIVING item</code></td><td>VSI return-value semantics: the named item holds the routine's return value on exit. The item can live in working storage or linkage.</td></tr><tr><td><code>CALL GIVING</code> / <code>RETURN-CODE</code> mapping</td><td>The called routine's return value lands in the <code>GIVING</code> item if present, otherwise in <code>RETURN-CODE</code>; interoperates with <code>IS SUCCESS</code> / <code>IS FAILURE</code>.</td></tr></tbody></table></div><h6>Status conditions</h6><div class="table-wrapper"><table><thead><tr><th>Feature</th><th>Behaviour under -fdec</th></tr></thead><tbody><tr><td><code>SET status TO SUCCESS</code> / <code>TO FAILURE</code></td><td>Sets the OpenVMS low-bit condition state (bit 0 set means success). Targets are validated as word or longword numeric items.</td></tr><tr><td><code>status IS SUCCESS</code> / <code>IS FAILURE</code></td><td>Compiles to a runtime low-bit test on the status item.</td></tr></tbody></table></div><h6>Data initialisation</h6><div class="table-wrapper"><table><thead><tr><th>Feature</th><th>Behaviour under -fdec</th></tr></thead><tbody><tr><td><code>VALUE IS EXTERNAL name</code></td><td>Initialises an integer item from a VMS symbolic constant. Hyphens and underscores are treated as equivalent, so <code>SS$-NORMAL</code> and <code>SS$_NORMAL</code> 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.</td></tr><tr><td><code>-fdec-constants=&lt;file&gt;</code></td><td>Supplies additional application-level constants not in the built-in table. Accepts simple <code>NAME = value</code> lines. Checked before the built-in table, and can be repeated.</td></tr><tr><td><code>VALUE IS REFERENCE data-name</code></td><td>Initialises a pointer to the address of static data. The target may be declared later in the program.</td></tr><tr><td><code>VALUE IS REFERENCE numeric-literal</code></td><td>Initialises a pointer to a literal integer address.</td></tr><tr><td><code>SET pointer TO REFERENCE OF item</code></td><td>The VSI address-of spelling, equivalent to <code>ADDRESS OF</code>.</td></tr></tbody></table></div><h6>Storage and numeric model</h6><div class="table-wrapper"><table><thead><tr><th>Feature</th><th>Behaviour under -fdec</th></tr></thead><tbody><tr><td>Binary storage model</td><td><code>-fdec</code> implies word-sized <code>COMP</code> 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.</td></tr><tr><td>Floating-point usages</td><td><code>COMP-1</code> is IEEE single precision, <code>COMP-2</code> is IEEE double precision, and <code>FLOAT-EXTENDED</code> is treated as an 8-byte synonym for <code>COMP-2</code>, matching the VSI usage rule.</td></tr></tbody></table></div><h6>Names and symbols</h6><div class="table-wrapper"><table><thead><tr><th>Feature</th><th>Behaviour under -fdec</th></tr></thead><tbody><tr><td><code>$</code> in user-defined words</td><td>Allowed anywhere except as the first character, so names like <code>SYS$TRNLNM</code> are valid.</td></tr><tr><td>Hyphen and underscore equivalence</td><td>In user-defined words, <code>_</code> and <code>-</code> fold together, so <code>C_NINE</code> and <code>C-NINE</code> are the same word. External names (<code>PROGRAM-ID</code>, and constant <code>CALL</code> / <code>ENTRY</code> / <code>CANCEL</code> names) encode a hyphen as an underscore in the exported symbol, matching VSI's own link-symbol spelling.</td></tr><tr><td><code>PROGRAM-ID. name WITH IDENT "literal"</code></td><td>A VSI module version string, validated as non-numeric text between 1 and 31 characters.</td></tr><tr><td>Logical-name mnemonics in <code>SPECIAL-NAMES</code></td><td>Lets <code>DISPLAY ... UPON</code> and <code>ACCEPT ... FROM</code> target environment name, environment value, and argument mnemonics. Off OpenVMS, logical names map to environment variables.</td></tr></tbody></table></div><h6>Control flow</h6><p><code>-fdec</code> turns on OSVS-style <code>PERFORM</code> range semantics by default, matching the dynamic range behaviour described in the VSI reference material: a <code>GO TO</code> 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 <code>PERFORM</code> semantics instead. </p><h2 id="file-io">File I/O through RMS</h2><p> 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. </p><h6>Extended file I/O syntax</h6><p>Every clause below is a hard compile error without <code>-fdec</code>:</p> <pre><span class="kw">INPUT-OUTPUT SECTION.</span> <span class="kw">FILE-CONTROL.</span> <span class="kw">SELECT</span> F1 <span class="kw">ASSIGN TO</span> <span class="str">"f1.dat"</span> <span class="kw">ORGANIZATION INDEXED ACCESS DYNAMIC</span> <span class="kw">RECORD KEY IS</span> SK = R1-A R1-B <span class="kw">ALTERNATE RECORD KEY IS</span> R1-C <span class="kw">WITH DUPLICATES</span>. <span class="kw">I-O-CONTROL.</span> <span class="kw">APPLY LOCK-HOLDING ON</span> F1. <span class="kw">APPLY DEFERRED-WRITE ON</span> F1. <span class="kw">APPLY EXTENSION</span> 100 <span class="kw">ON</span> F1. <span class="kw">APPLY PREALLOCATION</span> 500 <span class="kw">ON</span> F1. <span class="kw">APPLY WINDOW</span> 7 <span class="kw">ON</span> F1. <span class="kw">PROCEDURE DIVISION.</span> <span class="kw">OPEN I-O</span> F1 <span class="kw">ALLOWING ALL</span> <span class="kw">START</span> F1 <span class="kw">KEY IS</span> &gt;= SK <span class="kw">REGARDLESS</span> <span class="kw">READ</span> F1 <span class="kw">ALLOWING NO OTHERS KEY IS</span> SK <span class="kw">END-READ</span> <span class="kw">READ</span> F1 <span class="kw">NEXT REGARDLESS OF LOCK END-READ</span> <span class="kw">READ</span> F1 <span class="kw">PRIOR END-READ</span> <span class="kw">REWRITE</span> R1 <span class="kw">ALLOWING UPDATERS END-REWRITE</span> <span class="kw">UNLOCK</span> F1 <span class="kw">ALL RECORDS</span> <span class="kw">CLOSE</span> F1 <span class="kw">STOP RUN.</span></pre> <h6>Clause reference</h6><div class="table-wrapper"><table><thead><tr><th>Clause</th><th>Behaviour</th></tr></thead><tbody><tr><td><code>VALUE OF ID IS "x"</code> (FD)</td><td>Overrides the file spec given on <code>ASSIGN</code>.</td></tr><tr><td><code>APPLY LOCK-HOLDING ON f</code></td><td>Switches the file to manual lock mode, normally paired with <code>OPEN ALLOWING</code> / <code>READ REGARDLESS</code>.</td></tr><tr><td><code>APPLY DEFERRED-WRITE / EXTENSION n / FILL-SIZE / MASS-INSERT / PREALLOCATION n / WINDOW n / PRINT-CONTROL</code></td><td>Accepted as RMS tuning hints with a default-on warning; they have no effect on this build and can be silenced with a compiler flag.</td></tr><tr><td><code>READ f [NEXT/PRIOR] ... REGARDLESS [OF LOCK]</code></td><td>Reads while ignoring locks. <code>READ PRIOR</code> is equivalent to <code>READ PREVIOUS</code>.</td></tr><tr><td><code>READ/WRITE/REWRITE ... ALLOWING NO OTHERS / READERS / UPDATERS / WRITERS / ALL</code></td><td><code>NO OTHERS</code> takes a lock; <code>UPDATERS</code>, <code>WRITERS</code>, and <code>ALL</code> take no lock; <code>READERS</code> is treated as <code>NO OTHERS</code> with a warning.</td></tr><tr><td><code>UNLOCK f ALL RECORDS</code></td><td>Releases every lock held on the file.</td></tr></tbody></table></div><div class="callout"><strong>File-name and path rules.</strong> VX/RMS uppercases file names to match authentic VMS behaviour (<code>cust.dat</code> becomes <code>CUST.DAT</code>), 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. </div><h2 id="compatibility">Compatibility with OpenVMS</h2><p> 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. </p><div class="table-wrapper"><table><thead><tr><th>Item</th><th>Status</th></tr></thead><tbody><tr><td>Call by descriptor, routine arity padding, 64-bit pointers</td><td><span class="ac-live">live</span></td></tr><tr><td>VMS symbolic constants (11,388 entries) and constant file supplements</td><td><span class="ac-live">live</span></td></tr><tr><td>Pointer initialisation by reference and address-of</td><td><span class="ac-live">live</span></td></tr><tr><td>Success/failure condition handling, GIVING return values</td><td><span class="ac-live">live</span></td></tr><tr><td><code>$</code> in words, hyphen/underscore equivalence, module version strings</td><td><span class="ac-live">live</span></td></tr><tr><td>VSI binary storage model and IEEE float usages</td><td><span class="ac-live">live</span></td></tr><tr><td>OSVS-style <code>PERFORM</code> range</td><td><span class="ac-live">live</span></td></tr><tr><td>File I/O through VX/RMS, including indexed files and split keys</td><td><span class="ac-live">live</span></td></tr><tr><td>Extended file I/O syntax (<code>REGARDLESS</code>, <code>ALLOWING</code>, <code>VALUE OF ID</code>, <code>APPLY</code> hints)</td><td><span class="ac-live">live</span></td></tr><tr><td>RMS status special registers</td><td><span class="ac-v1">v1 soon</span></td></tr><tr><td>Sharing mode wired through to the file control descriptor on <code>OPEN ALLOWING</code></td><td><span class="ac-v1">v1 soon</span></td></tr><tr><td>Multiple <code>APPLY</code> phrases in a single clause</td><td><span class="ac-v1">v1 soon</span></td></tr><tr><td>Full partial-spec merge on <code>VALUE OF ID</code></td><td><span class="ac-v1">v1 soon</span></td></tr><tr><td>Callee-side <code>PROCEDURE DIVISION USING BY DESCRIPTOR</code></td><td><span class="ac-v2">v2</span></td></tr><tr><td>19 to 31 digit octaword <code>COMP</code></td><td><span class="ac-no">out of scope</span></td></tr><tr><td>VAX floating-point bit-pattern emulation</td><td><span class="ac-no">out of scope</span></td></tr><tr><td>Embedded SQL and repository features</td><td><span class="ac-no">out of scope, handled separately by VX/SQL-COBOL</span></td></tr></tbody></table></div><h6>Deliberate differences from OpenVMS</h6><div class="table-wrapper"><table><thead><tr><th>Difference</th><th>Reason</th></tr></thead><tbody><tr><td><code>VALUE IS EXTERNAL</code> resolves at compile time, not link time</td><td>There is no OpenVMS linker on Linux, so constants come from the built-in table instead.</td></tr><tr><td>The word/longword-only restriction on <code>VALUE EXTERNAL</code> is not enforced</td><td>Any numeric integer item is accepted, a deliberately permissive superset.</td></tr><tr><td>No VAX floating-point emulation</td><td>VAX-format float data is converted upstream, so the compiler only ever sees IEEE values.</td></tr><tr><td>External names encode a hyphen as a single underscore, not two</td><td>Matches the VSI link-symbol spelling exactly, and the runtime resolver bridges both spellings automatically.</td></tr><tr><td>File names are uppercased and paths cannot contain dots</td><td>Carries over authentic VMS RMS file-naming rules.</td></tr></tbody></table></div><h2 id="quick-reference">Quick reference</h2><h6>Flags</h6><div class="table-wrapper"><table><thead><tr><th>Flag</th><th>Effect</th></tr></thead><tbody><tr><td><code>-fdec</code></td><td>Master switch. Turns on every extension above; off, each one is a compile error. Implies OSVS <code>PERFORM</code> range, the word/longword/quadword storage model, native byte order, and RMS file I/O, each individually overridable.</td></tr><tr><td><code>-fdec-constants=&lt;file&gt;</code></td><td>Loads additional <code>VALUE IS EXTERNAL</code> constants. Checked before the built-in table. Repeatable.</td></tr><tr><td><code>-fno-perform-osvs</code></td><td>Turns off the OSVS <code>PERFORM</code> range implied by <code>-fdec</code>.</td></tr><tr><td><code>-fbinary-size=</code> / <code>-fbinary-byteorder=</code></td><td>Overrides the storage model implied by <code>-fdec</code>.</td></tr><tr><td><code>-fcallfh=EXTFH</code></td><td>Uses the compiler's own file layer instead of VX/RMS.</td></tr><tr><td><code>-Wno-dec-hint</code></td><td>Silences the default warnings for accepted-and-ignored RMS tuning clauses.</td></tr></tbody></table></div><h6>Interop cheat sheet</h6><div class="kw-grid"><div>CALL "R" USING BY DESCRIPTOR X RETURNING S</div><div>01 S PIC S9(9) COMP VALUE EXTERNAL SS$_NORMAL.</div><div>01 P USAGE POINTER VALUE REFERENCE ITEM.</div><div>SET S TO SUCCESS</div><div>IF S IS FAILURE</div><div>PROCEDURE DIVISION GIVING RET-STAT.</div><div>SET P TO REFERENCE OF ITEM.</div><div>PROGRAM-ID. NAME WITH IDENT "V1.0".</div></div><h6>File I/O cheat sheet</h6><div class="kw-grid"><div>VALUE OF ID IS "x"</div><div>APPLY LOCK-HOLDING ON f</div><div>OPEN ... ALLOWING ALL</div><div>READ ... REGARDLESS [OF LOCK]</div><div>READ ... PRIOR</div><div>READ/REWRITE ... ALLOWING NO OTHERS/UPDATERS</div><div>UNLOCK f ALL RECORDS</div></div><h6>Getting started</h6> <pre><span class="cmt"># Compile a VSI-style program</span> cobc -fdec -fformat=terminal prog.cob <span class="cmt"># Supply application-specific constants</span> cobc -fdec -fdec-constants=msgcodes.h prog.cob</pre> </div>

Frequently Asked Questions

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

No items found.

Transform Your Legacy Software Today!

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