VX/DECFORMS - DECforms IFDL Compiler and FORMS$
Overview
VX/DECFORMS is Sector7's Linux and Windows reimplementation of OpenVMS DECforms, the DEC CODASYL/FIMS forms manager. It has two halves: the IFDL compiler (vxforms), which parses Interactive Forms Definition Language source and lowers it to a C++ subroutine, and the FORMS$ Form Driver runtime (libvxdf), which links against that generated code, drives the terminal, and exposes the original DECforms callable interface.
The migration contract is source-level compatibility: an application keeps its FORMS$ calls unchanged, each form is recompiled with vxforms, and the Form Driver reproduces the original VT screen behaviour by emitting the same ANSI escape sequences DECforms used. The result is a functional emulation in which users cannot tell a migrated screen from the original. VX/DECFORMS supports nearly all DECforms syntax and can also present forms in modern HTML5 browsers, broadening access to legacy applications.
<!-- Webflow embed (min). Source: decforms-page-technical/decforms-tech-body-embed-dark.html → python3 website/embeds/minify_webflow_embed.py … -->
<div class="s7-tech-embed" data-vxdecformsd-body-embed="1" data-technical-mega-embed="1" lang="en"><h2 id="architecture">Architecture and components</h2><p>
VX/DECFORMS is a compiler plus a linked runtime library, not a long-running daemon.
The compiler, <code>vxforms</code>, is a flex and bison front end that parses IFDL and
emits a C++ translation unit. The runtime, <code>libvxdf</code>, is the Form Driver: it
links directly into the migrated application, loads the generated form logic, drives the
terminal, displays panels, validates input, and exposes the DECforms <code>FORMS$</code>
callable interface. The table maps each OpenVMS DECforms concept to its VX/DECFORMS
counterpart.
</p><figure style="max-width:248px;margin:24px auto;"><img src="https://cdn.prod.website-files.com/6654a06b5910e86da45495b0/67a4f4ca6538f1a6a78220c2_Decforms1.svg" alt="VX/DECFORMS IFDL-to-C++ compilation flow" style="width:100%;height:auto;" loading="lazy"></figure><div class="table-wrapper"><table><thead><tr><th>OpenVMS DECforms concept</th><th>VX/DECFORMS counterpart</th><th>Role</th><th>Status</th></tr></thead><tbody><tr><td>DECforms IFDL compiler</td><td>binary <code>vxforms</code> (<code>compiler/</code>)</td><td>Parses IFDL source, emits the generated C++ translation unit.</td><td><span class="ac-live">live</span></td></tr><tr><td>Lexer</td><td><code>decforms.flex</code></td><td>Tokenises IFDL with case-insensitive keywords.</td><td><span class="ac-live">live</span></td></tr><tr><td>Grammar</td><td><code>decforms.bison</code></td><td>Maps IFDL syntax to the code-generator semantic actions.</td><td><span class="ac-live">live</span></td></tr><tr><td>Code generator</td><td><code>CFromIFDL.c</code></td><td>Emits <code>forms_*</code> builder calls and the <code>Form__NAME()</code> entry point.</td><td><span class="ac-live">live</span></td></tr><tr><td>CDD/CDO dictionary forms</td><td><code>--cvt-cdolst-ifdl</code> conversion path</td><td>Converts a CDD/CDO listing into IFDL source for compilation.</td><td><span class="ac-live">live</span></td></tr><tr><td>DECforms shareable image</td><td><code>libvxdf</code> Form Driver runtime (<code>rtl/</code>)</td><td>Loads generated form logic, drives the terminal, executes the callable interface.</td><td><span class="ac-live">live</span></td></tr><tr><td>Screen management</td><td><code>vxdf_screen_smg.cpp</code></td><td>VT terminal driver that emits ANSI/VT sequences directly.</td><td><span class="ac-live">live</span></td></tr><tr><td>User escape / external routine dispatch</td><td><code>vxdf_forms_callpeu.cpp</code>, <code>vxdf_peudispatch.c</code></td><td>Invokes user-supplied PUE/UAR routines linked into the compiled form.</td><td><span class="ac-live">live</span></td></tr><tr><td>Picture / edit fields, fixed-decimal math</td><td><code>vxdf_picturefield.cpp</code>, <code>vxdf_stringmath.cpp</code></td><td>Picture-string validation and DECforms numeric semantics.</td><td><span class="ac-live">live</span></td></tr></tbody></table></div><div class="callout"><strong>No curses, termcap, or terminfo.</strong> The screen driver emits VT and ANSI
sequences directly, with no dependency on external terminal databases or configuration
files. This is what makes the Form Driver portable across Linux and Windows.
</div><h6>Compilation pipeline</h6><p>The build flow runs offline, once per form, and produces C++ that is compiled and linked into the application alongside the Form Driver:</p><style>.s7-tech-embed .decforms-flow {margin: 1.5rem 0;padding: 16px;border: 1px solid var(--s7t-border);border-radius: 10px;background: rgba(255, 255, 255, 0.01);}.s7-tech-embed .decforms-flow-group {display: grid;grid-template-columns: repeat(2, minmax(0, 1fr));gap: 10px;}.s7-tech-embed .decforms-flow-stages {display: grid;grid-template-columns: repeat(3, minmax(0, 1fr));gap: 10px;}.s7-tech-embed .decforms-flow-card {min-width: 0;padding: 15px;border-top: 3px solid var(--s7t-accent);border-radius: 6px;background: var(--s7t-surface2);color: var(--s7t-text);}.s7-tech-embed .decforms-flow-card strong,.s7-tech-embed .decforms-flow-card span:last-child {display: block;}.s7-tech-embed .decforms-flow-card strong {margin-bottom: 4px;}.s7-tech-embed .decforms-flow-card span:last-child {color: var(--s7t-muted);font-size: 0.9em;line-height: 1.45;}.s7-tech-embed .decforms-flow-label {display: block;margin-bottom: 10px;font-family: var(--s7t-mono);color: var(--s7t-accent);font-size: 0.76em;font-weight: 700;letter-spacing: 0.08em;text-transform: uppercase;}.s7-tech-embed .decforms-flow-connector {position: relative;width: 2px;height: 28px;margin: 0 auto;background: var(--s7t-accent);}.s7-tech-embed .decforms-flow-connector::after {content: "";position: absolute;bottom: -1px;left: -4px;width: 8px;height: 8px;border-right: 2px solid var(--s7t-accent);border-bottom: 2px solid var(--s7t-accent);transform: rotate(45deg);}.s7-tech-embed .decforms-flow-output {border: 1px solid var(--s7t-note-bd);border-top: 3px solid var(--s7t-accent);background: var(--s7t-note-bg);}@media (max-width: 800px) {.s7-tech-embed .decforms-flow-group,.s7-tech-embed .decforms-flow-stages {grid-template-columns: 1fr;}}</style><div class="decforms-flow" aria-label="VX/DECFORMS compilation flow"><span class="decforms-flow-label">Inputs converging on IFDL</span><div class="decforms-flow-group"><div class="decforms-flow-card"><strong>IFDL source</strong><span><code>form.ifdl</code> enters the compiler directly.</span></div><div class="decforms-flow-card"><strong>CDD/CDO listing</strong><span><code>ConvertCDOLSTtoIFDL</code>, also exposed as <code>--cvt-cdolst-ifdl</code>, converts <code>.LST</code> input to <code>form.ifdl</code>.</span></div></div><div class="decforms-flow-connector" aria-hidden="true"></div><div class="decforms-flow-stages"><div class="decforms-flow-card"><span class="decforms-flow-label">01</span><strong>Parse IFDL</strong><span><code>vxforms</code> runs <code>decforms.flex</code> and <code>decforms.bison</code> to produce semantic actions.</span></div><div class="decforms-flow-card"><span class="decforms-flow-label">02</span><strong>Generate C++</strong><span><code>CFromIFDL.c</code> turns the semantic actions into <code>form.cpp</code>.</span></div><div class="decforms-flow-card decforms-flow-output"><span class="decforms-flow-label">03 - Output</span><strong>Build the application</strong><span>Compile with <code>c++ -std=c++11</code> and link <code>libvxdf</code> to produce the application plus Form Driver.</span></div></div></div><p>
The generated <code>.cpp</code> defines one <code>extern "C" void Form__<NAME>()</code>
entry point that preserves the original IFDL identifiers in the generated symbol names, so
the form keeps its name and structure across the migration.
</p><h2 id="compiler">The IFDL compiler (vxforms)</h2><p><code>vxforms</code> translates IFDL source descriptions into C++ subroutines. The generated
code calls a library of <code>forms_*</code> runtime functions plus a variadic
<code>forms_Dispatch(__VERB, ...)</code> dispatcher keyed on implementor-key constants,
rather than emitting one class per verb. Each IFDL declaration is buffered into a per-kind
list (function responses, validation responses, panels, and so on) and flushed in a fixed
order, and the generated symbol names preserve the original IFDL identifiers.
</p><h6>Command-line flags</h6><div class="table-wrapper"><table><thead><tr><th>Flag</th><th>Effect</th></tr></thead><tbody><tr><td><code>--main</code></td><td>Also emit <code>Form__Main()</code> aliasing the first form.</td></tr><tr><td><code>--output=<file></code></td><td>Set the output file name.</td></tr><tr><td><code>--include=<dir></code></td><td>Add an IFDL include directory.</td></tr><tr><td><code>--option-file=<file></code></td><td>Read options from a file (for large builds).</td></tr><tr><td><code>--compile</code> / <code>--compile="<line>"</code></td><td>Compile each generated <code>.cpp</code> via <code>vxforms.sh</code> or a given command line.</td></tr><tr><td><code>--cvt-cdolst-ifdl=<CDO.LST>,<out_dir></code></td><td>Convert a CDD/CDO listing into IFDL.</td></tr><tr><td><code>--singleline</code></td><td>Collapse generated output onto a single line.</td></tr><tr><td><code>--force</code></td><td>Force output even on error.</td></tr><tr><td><code>--no-warnings</code> / <code>--quiet</code></td><td>Suppress warnings / run quietly.</td></tr><tr><td><code>--trace=<items></code> / <code>--yydebug</code></td><td>Compiler-internal and grammar-rule tracing.</td></tr></tbody></table></div><h6>Generated C++</h6><p>
The generator emits an include of <code>vxFormsDef.hpp</code>, forward declarations for every
response, group, icon, and field, and a single <code>Form__<NAME>()</code> entry that
initialises the library and calls the <code>forms_*</code> builders:
</p>
<pre><span class="cmt">#include "vxFormsDef.hpp"</span>
<span class="kw">static void</span> FunctionResponse__KEY_F10__8();
<span class="kw">static void</span> Group__ACCOUNT_LIST__1();
...
forms_Dispatch(__FIELD_DEFAULT, __PROTECTED, ...);
forms_GroupDisplayAttributes(__VERTICAL_SPEC, __DISPLAYS, 5, __SCROLL_BY_PAGE, ...);
forms_DeclareFunctionResponse(...);
forms_PictureFieldDeclaration(<span class="str">"BALANCE"</span>, ...);
forms_Literal(__TEXT, ...);
forms_EndGroup();
<span class="kw">extern</span> <span class="str">"C"</span> <span class="kw">void</span> Form__ACCOUNT_INQUIRY()
{
forms_LibraryInitializer((<span class="kw">void</span> **)&FDp, <span class="kw">sizeof</span> (*FDp), main_map_table);
...
}</pre>
<div class="callout"><strong>Reviewable output.</strong> Because the compiler emits ordinary C++ rather than
opaque binary form files, the generated form logic can be compiled with a standard
<code>c++ -std=c++11</code> toolchain and linked into the application like any other object.
</div><h2 id="ifdl">IFDL language reference</h2><p>
IFDL (Interactive Forms Definition Language) is a declarative, keyword-oriented language used
to describe forms: their data, layout, panels, key bindings, display attributes, and the
response logic that runs at each phase of a session. VX/DECFORMS supports nearly all DECforms
IFDL syntax. Keywords are matched case-insensitively by the lexer.
</p><h6>Top-level declarations</h6><div class="table-wrapper"><table><thead><tr><th>Declaration</th><th>Purpose</th></tr></thead><tbody><tr><td><code>Form <name> ... End</code></td><td>Top-level form.</td></tr><tr><td><code>Form Data ... End Data</code></td><td>Working-storage record the responses read and write.</td></tr><tr><td><code>Form Record <name> ... End Record</code></td><td>Send / receive record layout(s).</td></tr><tr><td><code>Layout <name> ... End</code></td><td>A device-specific rendering of the form.</td></tr><tr><td><code>Device ... Terminal Type %VT100 ... End Device</code></td><td>Target device and terminal type.</td></tr><tr><td><code>Size <n> Lines by <m> Columns</code></td><td>Screen geometry.</td></tr><tr><td><code>Viewport <name> ... End Viewport</code></td><td>A named screen region.</td></tr><tr><td><code>Panel <name> ...</code></td><td>A displayable panel of fields and literals.</td></tr><tr><td><code>Function <name> Is %KEY ... End Function</code></td><td>Bind terminal keys to a logical function.</td></tr><tr><td><code>Attribute <name> Is ... End Attribute</code></td><td>A named video-attribute set.</td></tr><tr><td><code><kind> Response ... End Response</code></td><td>Response blocks (send, receive, transceive, internal, function, entry, exit, validation).</td></tr></tbody></table></div><h6>Response steps</h6><div class="table-wrapper"><table><thead><tr><th>IFDL step</th><th>Meaning</th></tr></thead><tbody><tr><td><code>Let <field> = <expr></code></td><td>Assign a form-data field.</td></tr><tr><td><code>Display <panel> On <viewport></code></td><td>Render a panel.</td></tr><tr><td><code>Message <text></code></td><td>Write to the message viewport.</td></tr><tr><td><code>Signal %Bell</code></td><td>Emit a terminal signal.</td></tr><tr><td><code>If <cond> Then ... Else ... End If</code></td><td>Conditional.</td></tr><tr><td><code>Reset</code> / <code>Refresh</code> / <code>Remove</code></td><td>Field and screen management.</td></tr><tr><td><code>Activate</code> / <code>Deactivate</code></td><td>Field and panel focus control.</td></tr><tr><td><code>Send</code> / <code>Receive</code> / <code>Transceive</code> / <code>Return</code></td><td>Data and flow to the application.</td></tr><tr><td><code>Call <routine></code></td><td>Invoke a user escape routine (external response / PUE).</td></tr></tbody></table></div><h6>IFDL example</h6><p>
A teller sign-on form for a banking application: a <code>Form Data</code> block, a
<code>Form Record</code>, a <code>Layout</code> with a viewport, a key-bound function, a named
attribute, and a <code>Transceive Response</code>. Keywords are case-insensitive, and
<code>%VT100</code>, <code>%CARRIAGE_RETURN</code>, and <code>%Bell</code> are implementor keys.
</p>
<pre><span class="kw">Form</span> TELLER_SIGNON
<span class="kw">Form Data</span>
PROGRAM_TITLE <span class="kw">Character</span>(40)
PROGRAM_DATE <span class="kw">Character</span>(14)
TELLER_ID <span class="kw">Character</span>(12) <span class="kw">Value</span> <span class="str">" "</span>
BRANCH_MSG_FLAG <span class="kw">Character</span>(1) <span class="kw">Value</span> <span class="str">" "</span>
BRANCH_MSG_LINE <span class="kw">Character</span>(80) <span class="kw">Value</span> <span class="str">" "</span>
SIGNON_ATTEMPTS <span class="kw">Signed longword</span>
<span class="kw">End Data</span>
<span class="kw">Form Record</span> TELLER_SIGNON_REC
SIGNON_ACTION_FLAG <span class="kw">Character</span>(5)
TELLER_ID <span class="kw">Character</span>(12)
SIGNON_ATTEMPTS <span class="kw">Signed longword</span>
<span class="kw">End Record</span>
<span class="kw">Layout</span> TELLER_SIGNON
<span class="kw">Device Terminal Type</span> %VT100 <span class="kw">End Device</span>
<span class="kw">Size</span> 24 <span class="kw">Lines by</span> 80 <span class="kw">Columns</span>
<span class="kw">Viewport</span> Message_Viewport
<span class="kw">Lines</span> 24 <span class="kw">Through</span> 24
<span class="kw">Columns</span> 1 <span class="kw">Through</span> 80
<span class="kw">End Viewport</span>
<span class="kw">Function</span> Select_Item
<span class="kw">Is</span> %CARRIAGE_RETURN %KP_ENTER %SELECT
<span class="kw">End Function</span>
<span class="kw">Attribute</span> Prompt_Attr
<span class="kw">Is NoBlinking NoBold Reverse NoUnderlined</span>
<span class="kw">End Attribute</span>
<span class="kw">Transceive Response</span> TELLER_SIGNON_REC TELLER_SIGNON_REC
<span class="kw">Let</span> PROGRAM_TITLE = <span class="str">" Teller Sign-On"</span>
<span class="kw">Let</span> PROGRAM_DATE = SCREEN_DATE
<span class="kw">Display</span> Heading_Panel <span class="kw">On</span> Heading_Viewport
<span class="kw">Display</span> Signon_Panel <span class="kw">On</span> Main_Viewport
<span class="kw">If</span> BRANCH_MSG_FLAG <> <span class="str">" "</span>
<span class="kw">Then Message</span> BRANCH_MSG_LINE
<span class="kw">Signal</span> %Bell
<span class="kw">Let</span> BRANCH_MSG_FLAG = <span class="str">" "</span>
<span class="kw">Else Message</span> <span class="str">" "</span>
<span class="kw">End If</span>
<span class="kw">End Response</span></pre>
<h6>Field data types</h6><div class="kw-grid"><div>Character(n)</div><div>Integer</div><div>Signed longword</div><div>Unsigned longword</div><div>Signed word</div><div>Signed byte</div><div>Signed quadword</div><div>Packed</div><div>Float</div><div>DFloat</div><div>Picture (edit mask)</div><div>Picture For Date</div></div><h6>Selected IFDL keywords</h6><div class="kw-grid"><div>ACCEPT</div><div>ACTIVATE</div><div>ATTRIBUTE</div><div>AUTOSKIP</div><div>BLINKING</div><div>BOLD</div><div>CONCEALED</div><div>DATA</div><div>DEVICE</div><div>DISPLAY</div><div>ENABLE</div><div>ENTRY</div><div>EXIT</div><div>FIELD</div><div>FORM</div><div>FUNCTION</div><div>GROUP</div><div>HELP</div><div>ICON</div><div>IF</div><div>LAYOUT</div><div>LET</div><div>LITERAL</div><div>MESSAGE</div><div>PANEL</div><div>PICTURE</div><div>PROTECTED</div><div>RECEIVE</div><div>RECORD</div><div>REFRESH</div><div>REQUIRE</div><div>RESET</div><div>RESPONSE</div><div>REVERSE</div><div>SEND</div><div>SIGNAL</div><div>TRANSCEIVE</div><div>UNDERLINED</div><div>VALIDATION</div><div>VIEWPORT</div></div><p>The lexer recognises 286 single-word keywords in total, plus multi-word and implementor-key tokens.</p><h2 id="runtime-api">The FORMS$ Form Driver runtime</h2><p>
VX/DECFORMS is a library of <strong>FORMS$</strong> APIs that mirror the original DECforms Form
Driver call interface, so a migrated application links and runs its existing <code>FORMS$</code>
calls without modification. Each callable service is defined once internally and exported under
three names: the OpenVMS uppercase form (<code>FORMS$ENABLE</code>), a lowercase-linkage form
(<code>forms$enable</code>), and the internal implementation name, so existing object references
resolve unchanged.
</p><h6>Callable services</h6><div class="table-wrapper"><table><thead><tr><th>Service</th><th>Purpose</th><th>Status</th></tr></thead><tbody><tr><td><code>FORMS$ENABLE</code></td><td>Load a form and start a session on a device.</td><td><span class="ac-live">live</span></td></tr><tr><td><code>FORMS$DISABLE</code></td><td>End a session.</td><td><span class="ac-live">live</span></td></tr><tr><td><code>FORMS$SEND</code></td><td>Output a record to the form.</td><td><span class="ac-live">live</span></td></tr><tr><td><code>FORMS$RECEIVE</code></td><td>Read input from the form into a record.</td><td><span class="ac-live">live</span></td></tr><tr><td><code>FORMS$TRANSCEIVE</code></td><td>Combined send and receive in one call.</td><td><span class="ac-live">live</span></td></tr><tr><td><code>FORMS$CANCEL</code></td><td>Cancel an outstanding request.</td><td><span class="ac-live">live</span></td></tr></tbody></table></div><p>
Arguments are passed as VMS-style string descriptors, which the runtime adapts and converts to
C strings internally. Because the signatures and descriptor conventions match the OpenVMS
DECforms Form Driver, the application code that calls them does not change.
</p><h6>FORMS$ENABLE option keys</h6><div class="kw-grid"><div>FORMS$K_ASTADR</div><div>FORMS$K_ASTPRM</div><div>FORMS$K_EFN</div><div>FORMS$K_END</div><div>FORMS$K_ERROR_ITEMS_NOT_SAVED</div><div>FORMS$K_ERROR_PARAMETER</div><div>FORMS$K_ERROR_ROUTINE</div><div>FORMS$K_IMAGE</div><div>FORMS$K_LANGUAGE</div><div>FORMS$K_NO_TERM_IO</div><div>FORMS$K_PRINTFILE</div><div>FORMS$K_RSB</div><div>FORMS$K_SELECTION_LABEL</div><div>FORMS$K_STACK_SIZE</div><div>FORMS$K_TRACE</div><div>FORMS$K_TRACEFILE</div></div><h6>The forms_ builder library</h6><p>
The generated C++ targets a runtime library of builder and dispatch functions declared in
<code>vxFormsDef.hpp</code>. Representative entry points:
</p>
<pre>S32 forms_DeclareForm ( __CallBack, <span class="kw">const char</span> *szFormName );
S32 forms_DeclareField( __CallBack, <span class="kw">const char</span> *szFieldName );
S32 forms_Dispatch ( U32 Parameter, ... ); <span class="cmt">// variadic, keyed on __VERB</span>
S32 forms_Display ( U32 Parameter, ... );</pre>
<p>
Attribute and option keywords become implementor-key constants (for example
<code>__FIELD_DEFAULT</code>, <code>__PROTECTED</code>, <code>__DISPLAYS</code>,
<code>__SCROLL_BY_PAGE</code>) passed to <code>forms_Dispatch</code> and
<code>forms_GroupDisplayAttributes</code>.
</p><h6>User escapes (PUEs and UARs)</h6><p>
User Escapes, also called PUEs, are custom routines written in any DEC-supported programming
language and linked directly into the compiled form. The Form Driver calls them automatically
in several scenarios: after field processing, before and after help requests, when function keys
are pressed, and during screen refresh. In VX/DECFORMS these behave identically to those in the
original OpenVMS DECforms, with the added flexibility that the IFDL compiler produces
maintainable C++ into which external routines link directly, through
<code>forms_CallPEU()</code>.
</p><h2 id="features">DECforms features preserved</h2><p>
VX/DECFORMS retains the full original OpenVMS DECforms feature set. The goal is a functional
emulation that preserves complex attributes and behaviour rather than altering or enhancing the
core features, so migrated screens behave exactly as before.
</p><div class="table-wrapper"><table><thead><tr><th>Feature</th><th>Description</th></tr></thead><tbody><tr><td>Scrolled areas</td><td>Supports scrolling form sections within DECforms layouts.</td></tr><tr><td>Named data</td><td>Retains structured field naming and referencing.</td></tr><tr><td>Overlapping forms</td><td>Allows multiple forms to be layered on top of each other.</td></tr><tr><td>132-character mode</td><td>Supports wide terminal displays.</td></tr><tr><td>Help forms</td><td>Integrates with <a href="/technical/vx-dcl-vms-dcl">VX/DCL</a> to display user help panels.</td></tr><tr><td>User escape routines (PUEs)</td><td>Supports user-defined event handlers linked into the compiled form.</td></tr></tbody></table></div><figure style="max-width:1199px;margin:24px auto;"><img src="https://cdn.prod.website-files.com/6654a06b5910e86da45495b0/67a4f4f4983997cd0e3c9484_DecForms2.avif" alt="VX/DECFORMS terminal form rendering with VT display attributes" style="width:100%;height:auto;" loading="lazy"></figure><h6>Terminal support</h6><p>
The Form Driver is compatible with all VT terminals from VT100 upward, including DECterm under
DECwindows, and can be extended for non-VTxxx terminals as needed. Its built-in C-based terminal
drivers provide portability across Linux and Windows without relying on curses, termcap, or
external terminal configuration files.
</p><h6>Display attributes</h6><p>VX/DECFORMS reproduces the display capabilities of the DEC VT family:</p><ul><li><strong>Character attributes:</strong> reverse video, bold, blinking, and underlined text.</li><li><strong>Line attributes:</strong> double-width and double-height characters, and scrolled lines.</li><li><strong>Screen-width attributes:</strong> both 80-column and 132-column modes, plus reverse video.</li><li><strong>Alternative character sets:</strong> full support for VT100 special graphics and line-drawing characters.</li></ul><h6>Form Driver capabilities</h6><p>
The Form Driver is the runtime component responsible for terminal input and output, displaying
forms, managing screen manipulation, and performing basic input validation. It supports both
field-based and full-form input and output, allowing values to be specified one field at a time
or across the whole form, and eliminates the need for external terminal configuration files.
</p><div class="callout warn"><strong>One current limitation.</strong> VX/DECFORMS supports nearly all DECforms syntax but
does not currently support right-to-left text formatting. Everything else in the original
feature set is preserved.
</div><h2 id="migration">Migration workflow and compatibility</h2><p>
Originally designed for VMS, DECforms was difficult to migrate because of its complexity,
VMS-specific dependencies, and platform-specific programming constructs. VX/DECFORMS removes those
barriers with a set of language interface utilities that carry DECforms forms to Linux and
Windows. These system-independent routines adapt VMS descriptors and enable smooth linking into
modern environments.
</p><h6>No application code changes</h6><p>
The migration process does not require changes to application programs. Once the form descriptions
are recompiled, the application automatically uses the new forms through the runtime system. The
existing <code>FORMS$</code> calls link and run unchanged, and the Form Driver reproduces the
original screen behaviour, so users cannot distinguish a migrated screen from the original OpenVMS
DECforms.
</p><h6>Supported application languages</h6><p>
The VX/DECFORMS utilities support applications written in multiple programming languages and
provide the procedures needed to adapt VMS descriptors for each. Callable from:
</p><div class="table-wrapper"><table><thead><tr><th>Language</th><th>Sector7 migration path</th></tr></thead><tbody><tr><td>COBOL</td><td><a href="/technical/vx-cobol-vms-cobol-to-ansi-cobol">VX/COBOL</a></td></tr><tr><td>FORTRAN</td><td><a href="/technical/vx-fortran-vms-fortran-to-ansi-fortran">VX/FORTRAN</a></td></tr><tr><td>C</td><td><a href="/technical/vx-c-vms-c-to-ansi-c">VX/C</a></td></tr><tr><td>BASIC</td><td><a href="/technical/vx-basic-vms-basic-to-ansi-c">VX/BASIC</a></td></tr></tbody></table></div><h6>Integration with VX/RT</h6><p>
For applications that require full integration with VMS semantics, VX/DECFORMS works together with
<a href="/technical/vx-rt-apis">VX/RT</a>, Sector7's runtime support libraries for Linux, which
supply the VMS descriptor handling and system-service compatibility the Form Driver builds on.
Migrated forms can also be presented in modern HTML5 browsers alongside VT-terminal output,
broadening access to the legacy applications.
</p><h6>Compatibility status</h6><div class="table-wrapper"><table><thead><tr><th>Capability</th><th>Status</th></tr></thead><tbody><tr><td>IFDL lexer and grammar</td><td><span class="ac-live">live</span></td></tr><tr><td>IFDL to C++ code generation</td><td><span class="ac-live">live</span></td></tr><tr><td>CDD/CDO listing to IFDL conversion</td><td><span class="ac-live">live</span></td></tr><tr><td><code>FORMS$</code> callable runtime (Form Driver)</td><td><span class="ac-live">live</span></td></tr><tr><td>VT100+ terminal driver (no curses or termcap)</td><td><span class="ac-live">live</span></td></tr><tr><td>User escape / external routines (PUEs)</td><td><span class="ac-live">live</span></td></tr><tr><td>Picture fields and fixed-decimal math</td><td><span class="ac-live">live</span></td></tr><tr><td>Right-to-left text formatting</td><td><span class="ac-no">not currently supported</span></td></tr></tbody></table></div><h6>Related tools</h6><p>
VX/DECFORMS is the base DECforms product. The <code>FORMS$</code> callable API it provides is
documented on the <a href="/technical/api-forms-dec-integration">FORMS$ integration</a> page, and
TDMS-compatibility response steps are added by the separate
<a href="/technical/vx-decforms-plus-tdms-compatibility-extensions">VX/DECFORMS+</a> extension.
Related forms and screen-management tools in the same space include
<a href="/technical/vx-tdms-terminal-data-management-system">VX/TDMS</a>,
<a href="/technical/vx-fms-fms">VX/FMS</a>, and
<a href="/technical/vx-smg">VX/SMG</a>.
</p><h2 id="quickref">Quick reference</h2><h6>Compile a form</h6>
<pre>vxforms --output=form.cpp form.ifdl <span class="cmt"># IFDL to C++</span>
vxforms --main --compile form.ifdl <span class="cmt"># emit Form__Main, compile via vxforms.sh</span>
vxforms --cvt-cdolst-ifdl=CDO.LST,out_dir <span class="cmt"># CDD/CDO listing to IFDL</span>
c++ -std=c++11 -c form.cpp <span class="cmt"># then link with libvxdf</span></pre>
<h6>Runtime call skeleton</h6>
<pre>FORMS$ENABLE(&FormPtr, &Device, &Session, &FormFile, &FormName, ..., &Options);
FORMS$TRANSCEIVE(&Session, &SendRec, &SendCnt, &RecvRec, &RecvCnt, ...);
FORMS$DISABLE(&Session, &RcvCtl, ...);</pre>
<h6>IFDL skeleton</h6>
<pre><span class="kw">Form</span> <NAME>
<span class="kw">Form Data</span> ... <span class="kw">End Data</span>
<span class="kw">Form Record</span> <REC> ... <span class="kw">End Record</span>
<span class="kw">Layout</span> <NAME>
<span class="kw">Device Terminal Type</span> %VT100 <span class="kw">End Device</span>
<span class="kw">Size</span> 24 <span class="kw">Lines by</span> 80 <span class="kw">Columns</span>
<span class="kw">Viewport</span> ... <span class="kw">End Viewport</span>
<span class="kw">Function</span> ... <span class="kw">Is</span> %KEY <span class="kw">End Function</span>
<span class="kw">Attribute</span> ... <span class="kw">Is NoBlinking Bold</span> ... <span class="kw">End Attribute</span>
<kind> <span class="kw">Response</span> ... <span class="kw">End Response</span></pre>
<h6>FORMS$ services</h6><div class="kw-grid"><div>FORMS$ENABLE</div><div>FORMS$DISABLE</div><div>FORMS$SEND</div><div>FORMS$RECEIVE</div><div>FORMS$TRANSCEIVE</div><div>FORMS$CANCEL</div></div><h6>Response types</h6><div class="kw-grid"><div>Send</div><div>Receive</div><div>Transceive</div><div>Internal</div><div>Function</div><div>Entry</div><div>Exit</div><div>Validation</div></div></div>