VX/FMS - OpenVMS Forms Management
Overview
VX/FMS is a native reimplementation of DEC's OpenVMS Forms Management System (FMS) for Linux. It delivers the FDV$ Form Driver API, the FMS form language compiler, and the supporting form utilities as a linked C runtime, so migrated OpenVMS applications keep their existing FDV$ calls, .flg form sources, and character-cell terminal behaviour without source changes.
The runtime library links directly into the migrated program: its FDV$ calls resolve to Sector7's implementations with the same calling sequence and VMS status conventions as OpenVMS. Forms compile from .flg source to .fbn binary through the VX/FMS compiler, User Action Routines bind by name at link time, and screens render through direct VT and ANSI terminal control with no dependency on curses, termcap, or terminfo.
<!-- Webflow embed (min). Source: fms-page-technical/fms-tech-body-embed-dark.html → python3 website/embeds/minify_webflow_embed.py … -->
<div class="s7-tech-embed" data-vxfmsd-body-embed="1" data-technical-mega-embed="1" lang="en"><h2 id="architecture">Architecture and components</h2><p>
VX/FMS is a linked runtime library plus a small set of command-line utilities, not a
long-running server. The runtime is a C library that the migrated application links
against directly, so the program's existing <code>FDV$</code> calls resolve to Sector7's
implementations with no server process to administer. The table maps each OpenVMS FMS
component to its VX/FMS counterpart.
</p><div class="table-wrapper"><table><thead><tr><th>OpenVMS FMS component</th><th>VX/FMS artifact</th><th>Role</th><th>Status</th></tr></thead><tbody><tr><td>FMS Form Driver (<code>FDV$</code> shareable image)</td><td><code>libfms.a</code> / <code>libfms.so</code></td><td>Runtime the migrated application links; exposes the full <code>FDV$</code> call surface.</td><td><span class="ac-live">live</span></td></tr><tr><td>Form Language Translator (<code>FMS$FLTR</code>)</td><td><code>fms_form</code></td><td>Compiles <code>.flg</code> ASCII form source into <code>.fbn</code> binary form files.</td><td><span class="ac-live">live</span></td></tr><tr><td>Screen-oriented form editor (<code>FMS$FORM</code>)</td><td><code>fmsedit</code></td><td>Interactive <code>.flg</code> editor for VT and ANSI terminals.</td><td><span class="ac-live">live</span></td></tr><tr><td>UAR binding (VMS image activator)</td><td><code>fms_uar</code></td><td>Generates the User Action Routine name-to-function binding table to link into the application.</td><td><span class="ac-live">live</span></td></tr><tr><td>Diagnostics and regression tooling</td><td><code>fms_display</code> / <code>fms_dump</code> / <code>fms_compare</code></td><td>Headless render of a compiled form, escape-sequence dump, and render comparison against a captured reference.</td><td><span class="ac-live">live</span></td></tr></tbody></table></div><div class="callout"><strong>No runtime daemon.</strong> There is no forms server and no IPC substrate to
configure. The compiled <code>.fbn</code> form library is opened on disk by the linked
runtime at <code>FDV$LOPEN</code> time, and forms are pulled into memory individually
with <code>FDV$LOAD</code>.
</div><h6>Call dispatch chain</h6><p>
Each public API name is a thin dispatcher. A call to <code>FDV$DISP</code> resolves through
a link-time alias to an internal dispatcher, which wraps the call in the VX runtime
trace/return convention and hands off to the routine implementation:
</p><style>.s7-tech-embed .fms-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 .fms-flow-stages {display: grid;grid-template-columns: repeat(4, minmax(0, 1fr));gap: 10px;}.s7-tech-embed .fms-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 .fms-flow-card strong,.s7-tech-embed .fms-flow-card span:last-child {display: block;}.s7-tech-embed .fms-flow-card strong {margin-bottom: 4px;}.s7-tech-embed .fms-flow-card span:last-child {color: var(--s7t-muted);font-size: 0.9em;line-height: 1.45;}.s7-tech-embed .fms-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 .fms-flow-output {border: 1px solid var(--s7t-note-bd);border-top: 3px solid var(--s7t-accent);background: var(--s7t-note-bg);}@media (max-width: 960px) {.s7-tech-embed .fms-flow-stages {grid-template-columns: repeat(2, minmax(0, 1fr));}}@media (max-width: 600px) {.s7-tech-embed .fms-flow-stages {grid-template-columns: 1fr;}}</style><div class="fms-flow" aria-label="VX/FMS call dispatch chain"><div class="fms-flow-stages"><div class="fms-flow-card"><span class="fms-flow-label">01 - Aliases</span><strong>Portable caller symbols</strong><span><code>FDV$DISP</code>, <code>fdv$disp</code>, and <code>fdv$disp_</code> expose C upper-case, C lower-case, and Fortran trailing-underscore names for unchanged C, COBOL, and Fortran callers.</span></div><div class="fms-flow-card"><span class="fms-flow-label">02 - Public dispatcher</span><strong><code>FDV_D_DISP</code></strong><span>All three link-time aliases resolve to this single portable symbol.</span></div><div class="fms-flow-card"><span class="fms-flow-label">03 - Runtime wrapper</span><strong>Begin, call, end</strong><span>The wrappers apply tracing and the VMS return convention around the implementation call.</span></div><div class="fms-flow-card fms-flow-output"><span class="fms-flow-label">04 - Implementation</span><strong><code>FCC_DISP()</code></strong><span>The display implementation performs the routine's actual work.</span></div></div></div><p>
On an OpenVMS host, the dispatcher reads the caller's argument count and nulls out omitted
optional parameters, preserving FMS's "optional trailing argument" semantics. On Linux the
fixed prototype is used. The real work lives in the per-routine implementation files, which
are complete implementations rather than stubs.
</p><h2 id="fdv-api">The FDV$ Form Driver API</h2><p>
VX/FMS implements the full FMS Form Driver call surface: <strong>66 public <code>FDV$</code>
routines</strong>, each exported under the VMS dollar-sign name plus C lower-case and
Fortran trailing-underscore aliases so existing object references resolve at link time. A
migrated application links against <code>libfms</code> and its <code>FDV$</code> calls run
unchanged.
</p><h6>VMS calling convention</h6><p>
Every routine returns a VMS condition value <strong>by value</strong>: odd means success,
even means failure. Arguments are passed by reference as VMS descriptors (32-bit, or 64-bit
descriptors under an LP64 build), matching the original VMS calling convention. This is what
lets unmodified VMS source relink against VX/FMS. The canonical success status is
<code>FDV$_SUC</code>; callers test the low bit of the return value exactly as they did on
OpenVMS.
</p><h6>Routine reference</h6><p>
The table below groups the most frequently called routines by role. It is a representative
selection of the 66-routine <code>FDV$</code> API; every routine listed is implemented in
the runtime.
</p><div class="table-wrapper"><table><thead><tr><th>Group</th><th>Routines</th><th>Purpose</th><th>Status</th></tr></thead><tbody><tr><td>Terminal session</td><td><code>FDV$ATERM</code>, <code>FDV$DTERM</code>, <code>FDV$STERM</code>, <code>FDV$FIX_SCREEN</code></td><td>Attach and detach the Form Driver session, set terminal characteristics, and re-sync the physical screen.</td><td><span class="ac-live">live</span></td></tr><tr><td>Workspace</td><td><code>FDV$AWKSP</code>, <code>FDV$SWKSP</code>, <code>FDV$DWKSP</code></td><td>Allocate, select, and free a Form Driver workspace.</td><td><span class="ac-live">live</span></td></tr><tr><td>Form library</td><td><code>FDV$LOPEN</code>, <code>FDV$LOAD</code>, <code>FDV$LCLOS</code></td><td>Open a compiled form library, load a named form into memory, and close the library.</td><td><span class="ac-live">live</span></td></tr><tr><td>Display</td><td><code>FDV$DISP</code>, <code>FDV$DISPW</code>, <code>FDV$CDISP</code>, <code>FDV$CLEAR</code>, <code>FDV$RFRSH</code></td><td>Display a form on the terminal, display at a workspace offset, clear, and refresh.</td><td><span class="ac-live">live</span></td></tr><tr><td>Field input / output</td><td><code>FDV$GET</code>, <code>FDV$GETAL</code>, <code>FDV$PUT</code>, <code>FDV$PUTAL</code>, <code>FDV$PUTL</code>, <code>FDV$RET</code>, <code>FDV$RETAL</code></td><td>Read a single field or the whole form, write values into fields, and return field values with their terminators.</td><td><span class="ac-live">live</span></td></tr><tr><td>Scrolled areas</td><td><code>FDV$GETSC</code>, <code>FDV$PUTSC</code></td><td>Read from and write to a scrolled (scrolling) region within a form.</td><td><span class="ac-live">live</span></td></tr><tr><td>Named data</td><td><code>FDV$RETDN</code>, <code>FDV$RETDI</code>, <code>FDV$NDISP</code></td><td>Retrieve named-data items by name or index, attached to a compiled form.</td><td><span class="ac-live">live</span></td></tr><tr><td>Status and operator</td><td><code>FDV$STAT</code>, <code>FDV$SIGOP</code>, <code>FDV$BELL</code>, <code>FDV$RETLE</code>, <code>FDV$RETFN</code></td><td>Return Form Driver status and field metadata, signal the operator, and sound the terminal bell.</td><td><span class="ac-live">live</span></td></tr><tr><td>Keyboard</td><td><code>FDV$DFKBD</code>, <code>FDV$LEDON</code>, <code>FDV$LEDOF</code></td><td>Configure the keyboard and toggle keyboard LEDs.</td><td><span class="ac-live">live</span></td></tr></tbody></table></div><h6>Real call path</h6><p>
A migrated program links this session sequence unchanged against <code>libfms</code>. The
example uses a banking demo library and tests each status with the VMS success convention:
</p>
<pre><span class="cmt">/* 1. Attach the terminal (open the Form Driver session) */</span>
rc = fdv$aterm(&_tca, &val0, &val1, 0, 0, 0);
if (rc != FDV$_SUC) { <span class="cmt">/* report status text and exit */</span> }
<span class="cmt">/* 2. Allocate and select a workspace */</span>
val0 = 2000;
rc = fdv$awksp(&_wksp1, &val0);
rc = fdv$swksp(&_wksp1);
<span class="cmt">/* 3. Open the compiled form library and load a form */</span>
rc = fdv$lopen(_DESCR1(<span class="str">"BANKING_FORMS"</span>), &val0);
rc = fdv$load (_DESCR1(<span class="str">"ACCOUNT_INQUIRY"</span>));
<span class="cmt">/* 4. Display the form and read all fields (trm receives the terminator) */</span>
rc = fdv$dispw(0);
rc = fdv$getal(&_val, &trm, 0, 0);
<span class="cmt">/* 5. Tear down */</span>
fdv$dwksp(&_wksp1);
fdv$dterm(&_tca);</pre>
<p>
The equivalent portable C entry point is declared as
<code>extern "C" int fdv$get(...);</code> and returns the condition value by value. The same
routines are the ones the callable <a href="/technical/api-fms-forms-management-system">FMS$ Forms Management System API</a>
page documents in full detail.
</p><h2 id="form-language">The FMS form language</h2><p><code>.flg</code> is the ASCII form-description source the compiler reads. The VX/FMS
compiler emits a binary form file with the <code>.fbn</code> extension, byte-compatible with
the compiled forms FMS produced on OpenVMS. A library of compiled forms is opened at runtime
with <code>FDV$LOPEN</code>, and individual forms are pulled with <code>FDV$LOAD</code>.
</p><h6>Statement keywords</h6><p>The form language has ten top-level statement types:</p><div class="table-wrapper"><table><thead><tr><th>Statement</th><th>Purpose</th></tr></thead><tbody><tr><td><code>FORM</code></td><td>Opens a form definition (takes <code>NAME=</code>).</td></tr><tr><td><code>END_OF_FORM</code></td><td>Closes a form definition (takes <code>NAME=</code>).</td></tr><tr><td><code>FIELD</code></td><td>Defines an input or output field at a row and column.</td></tr><tr><td><code>TEXT</code></td><td>Places literal text at a <code>(row,col)</code> position.</td></tr><tr><td><code>ATTRIBUTE_DEFAULTS</code></td><td>Sets default field and attribute values for the form.</td></tr><tr><td><code>NAMED_DATA</code></td><td>Attaches named constant data to the form.</td></tr><tr><td><code>ORDER</code></td><td>Defines the field navigation order.</td></tr><tr><td><code>SCROLL</code></td><td>Declares a scrolled region by line range.</td></tr><tr><td><code>DRAW</code></td><td>Line-draw or ruling directive.</td></tr><tr><td><code>VIDEO</code></td><td>Video and display-attribute directive.</td></tr></tbody></table></div><h6>Statement items and attribute flags</h6><p>
Statement items take a <code>=value</code>; attribute flags are bare keywords, most with a
<code>NO...</code> negation. The compiler recognises the full FMS keyword set:
</p><div class="kw-grid"><div>NAME=</div><div>PICTURE=</div><div>DEFAULT=</div><div>HELP=</div><div>HELP_FORM=</div><div>WIDTH=</div><div>INDEX=</div><div>CHARACTER_SET=</div><div>CLEAR_CHARACTER=</div><div>BACKGROUND=</div><div>HIGHLIGHT=</div><div>DATA=</div><div>AREA_TO_CLEAR=</div><div>BEGIN_WITH= / END_WITH=</div><div>DATE_FIELD= / TIME_FIELD=</div><div>ACTION_ROUTINE=</div><div>FUNCTION_KEY_ACTION_ROUTINE=</div><div>PRE_HELP_ACTION_ROUTINE=</div><div>POST_HELP_ACTION_ROUTINE=</div><div>AUTOTAB / NOAUTOTAB</div><div>BOLD / NOBOLD</div><div>BLINKING / NOBLINKING</div><div>REVERSE / NOREVERSE</div><div>UNDERLINE / NOUNDERLINE</div><div>DISPLAY_ONLY / ECHO / NOECHO</div><div>MUST_FILL / RESPONSE_REQUIRED</div><div>LEFT_JUSTIFIED / RIGHT_JUSTIFIED</div><div>UPPERCASE / BLANK_FILL / ZERO_FILL</div><div>SUPERVISOR_ONLY / SUPPRESS</div></div><p>
Date fields support <code>MDY</code>, <code>DDMMMYY</code>, <code>MMDDYY</code>, and
<code>DDMMYY</code> pictures; time fields support <code>HHMMSS</code> and
<code>HHMMAMPM</code>. <code>PICTURE</code> accepts either a literal mask
(<code>PICTURE='XXXXX-XXXX'</code>) or a count-prefixed form (<code>PICTURE=40'X'</code>).
</p><h6>Example form source</h6><p>
A field with attribute defaults, a bound User Action Routine, a navigation order, and a
help string. Comments begin with <code>!</code>; a statement ends with <code>;</code>:
</p>
<pre><span class="kw">FORM</span> NAME=<span class="str">'ACCOUNT_INQUIRY'</span>
AREA_TO_CLEAR=1:23
WIDTH=80
BACKGROUND=CURRENT
HIGHLIGHT=BOLD:UNDERLINE
FUNCTION_KEY_ACTION_ROUTINE=<span class="str">'FILTER_UAR'</span>
;
<span class="kw">TEXT</span> (2,30) <span class="str">'ACCOUNT INQUIRY'</span> ;
<span class="kw">ATTRIBUTE_DEFAULTS</span> FIELD
CLEAR_CHARACTER=<span class="str">' '</span>
NOAUTOTAB BLANK_FILL NOBOLD NOREVERSE ECHO
LEFT_JUSTIFIED NOSUPERVISOR_ONLY NOUPPERCASE
;
<span class="kw">FIELD</span> NAME=<span class="str">'POST_IT'</span> (22,64)
PICTURE=<span class="str">'X'</span>
HELP=<span class="str">'Enter "Y" to post this transaction, "N" to abort'</span>
UPPERCASE
ACTION_ROUTINE=<span class="str">'POST_IT_UAR'</span>
RESPONSE_REQUIRED
;
<span class="kw">ORDER</span> BEGIN_WITH = 1
NAME=<span class="str">'ACCOUNT_NUMBER'</span>
NAME=<span class="str">'POST_IT'</span>
;
<span class="kw">END_OF_FORM</span> NAME=<span class="str">'ACCOUNT_INQUIRY'</span> ;</pre>
<p>
Scrolled regions are declared by line range, and a help form is linked with
<code>HELP_FORM='HELPTOPIC'</code>. The <code>RULE</code> character set selects the VT
line-drawing glyphs used for box borders:
</p>
<pre><span class="kw">SCROLL</span> BEGIN_WITH=9 END_WITH=13 ;
<span class="kw">SCROLL</span> BEGIN_WITH=18 END_WITH=20 ;</pre>
<h2 id="uars">User Action Routines</h2><p>
A User Action Routine (UAR) is a user-supplied C or C++ function bound to a form or field
<strong>by name</strong> in the <code>.flg</code> source. VX/FMS supports all UAR scenarios
that OpenVMS FMS does:
</p><ul><li>Field completion events, when the operator finishes entering a field.</li><li>Help requests raised by the terminal operator.</li><li>Function-key interactions, bound with <code>FUNCTION_KEY_ACTION_ROUTINE=</code>.</li><li>Pre-help and post-help hooks, bound with <code>PRE_HELP_ACTION_ROUTINE=</code> and <code>POST_HELP_ACTION_ROUTINE=</code>.</li><li>Screen refresh operations.</li></ul><h6>Binding and dispatch</h6><p>
A form binds a UAR by string name, for example
<code>ACTION_ROUTINE='POST_IT_UAR'</code> or
<code>FUNCTION_KEY_ACTION_ROUTINE='FILTER_UAR'</code>. At run time the Form Driver dispatches
by name through a generated lookup table that pairs each UAR name with its function pointer:
</p>
<pre><span class="cmt">/* generated binding table, linked into the application */</span>
extern char *FMS_name_field[]; <span class="cmt">/* UAR names */</span>
extern int (*FMS_ptr_field[])(void); <span class="cmt">/* parallel function pointers */</span>
int FMS_find_call_uar(char *name) {
<span class="cmt">/* locate name in FMS_name_field[], then call the paired pointer */</span>
for (i = 0; strcmp(name, FMS_name_field[i]) && ... ; i++) ;
return (*FMS_ptr_field[i])(); <span class="cmt">/* invoke the UAR */</span>
}</pre>
<p>
The name-to-pointer table is produced by the <code>fms_uar</code> generator, which scans the
application's UAR source and emits the binding table to link in. On OpenVMS the image
activator resolved UARs by name at run time; on Linux there is no image activator, so the
generator materialises the equivalent table at link time. This is also how VX/FMS extends
the original FMS capability by allowing <strong>dynamic linking of external C++ functions</strong>
as UARs, giving migrated forms more flexibility than the OpenVMS original.
</p><div class="callout"><strong>No source rewrite for UAR logic.</strong> Existing UAR functions keep their names
and signatures. The only new build step is running <code>fms_uar</code> to generate the
binding table, which replaces the OpenVMS run-time name resolution.
</div><h2 id="terminal">Terminal handling</h2><p>
VX/FMS drives the terminal directly and emits raw VT and ANSI escape sequences. It does
<strong>not</strong> depend on curses, termcap, or terminfo. This is a deliberate design
choice: rendering the screen the same way OpenVMS FMS did preserves exact character-cell
behaviour, cursor addressing, and video attributes, rather than approximating them through a
Unix TUI layer.
</p><h6>Supported terminals</h6><ul><li>VT100, VT220, and all compatible VT-series terminals.</li><li>DECterm under DECwindows.</li><li>ANSI-compatible terminal emulators on Linux.</li></ul><h6>Display features preserved</h6><div class="table-wrapper"><table><thead><tr><th>Feature</th><th>Behaviour</th></tr></thead><tbody><tr><td>132-character mode</td><td>Wide-screen (132-column) display, switched at runtime through the screen-width routine.</td></tr><tr><td>Double-size and double-width</td><td>The <code>DBLSIZ</code> and <code>DBLWID</code> form attributes render as on VT terminals.</td></tr><tr><td>Line drawing</td><td>The <code>RULE</code> character set drives VT line-drawing glyphs for box borders and rules.</td></tr><tr><td>Video attributes</td><td><code>BOLD</code>, <code>REVERSE</code>, <code>UNDERLINE</code>, and <code>BLINKING</code> map to their SGR equivalents.</td></tr><tr><td>Scrolled regions</td><td>Scrolling areas declared by line range in the form scroll and refresh correctly.</td></tr></tbody></table></div><p>
Because the runtime owns terminal I/O end to end, the diagnostic tools can capture and
replay the exact escape stream: <code>fms_dump</code> writes a form render to an
escape-sequence file, and <code>fms_compare</code> parses those escapes back to compare a
Linux render against a captured reference render for regression testing.
</p><h2 id="build-pipeline">Build and compile pipeline</h2><p>
The build produces the runtime library and the form utilities. Applications then compile
their forms and generate the UAR binding table before linking against the library.
</p><div class="table-wrapper"><table><thead><tr><th>Step</th><th>Command</th><th>Input</th><th>Output</th></tr></thead><tbody><tr><td>Build the runtime library</td><td><code>make</code></td><td>runtime C sources</td><td><code>libfms.a</code> / <code>libfms.so</code></td></tr><tr><td>Build the utilities</td><td><code>make</code> (utilities target)</td><td>utility C sources</td><td><code>fms_form</code>, <code>fms_uar</code>, <code>fms_display</code>, <code>fms_compare</code></td></tr><tr><td>Standalone variant</td><td><code>make standalone</code></td><td>same sources</td><td>self-contained library and tools, independent of the wider VX/RT runtime</td></tr><tr><td>Compile a form</td><td><code>fms_form <name></code></td><td><code>name.flg</code></td><td><code>name.fbn</code></td></tr><tr><td>Edit a form</td><td><code>fmsedit name.flg</code></td><td><code>.flg</code></td><td><code>.flg</code></td></tr><tr><td>Generate the UAR table</td><td><code>fms_uar</code></td><td>application UAR sources</td><td>name-to-pointer binding table to link in</td></tr></tbody></table></div><div class="callout"><strong>Standalone or integrated.</strong> VX/FMS builds either as a self-contained
library and toolset, or against the wider Sector7 runtime so it interoperates with
<a href="/technical/vx-rt-apis">VX/RT</a> and other Sector7 migration components in the
same estate.
</div><p>
The form compiler is a hand-written recursive-descent parser: it reads the <code>.flg</code>
statement stream, keys on the statement keywords against the token table, and serialises the
compiled form to the <code>.fbn</code> binary. Because the output format matches the OpenVMS
compiled form, existing tooling that consumes <code>.fbn</code> libraries continues to work.
</p><h2 id="compatibility">Feature and platform compatibility</h2><p>
VX/FMS retains the core capabilities of OpenVMS FMS so migrated applications keep their
form behaviour, layout, and interactions. The matrix below lists each capability and its
status in the runtime.
</p><div class="table-wrapper"><table><thead><tr><th>Capability</th><th>Status</th></tr></thead><tbody><tr><td>FDV$ Form Driver API (66 routines)</td><td><span class="ac-live">live</span></td></tr><tr><td><code>.flg</code> to <code>.fbn</code> form compiler</td><td><span class="ac-live">live</span></td></tr><tr><td>User Action Routine name-to-pointer dispatch and generator</td><td><span class="ac-live">live</span></td></tr><tr><td>Scrolled areas, named data, and overlapping forms</td><td><span class="ac-live">live</span></td></tr><tr><td>132-column, double-size, and double-width display</td><td><span class="ac-live">live</span></td></tr><tr><td>HELP forms with pre-help and post-help action routines</td><td><span class="ac-live">live</span></td></tr><tr><td>Direct VT and ANSI terminal I/O (no curses, termcap, or terminfo)</td><td><span class="ac-live">live</span></td></tr><tr><td><code>fmsedit</code> interactive form editor</td><td><span class="ac-live">live</span></td></tr><tr><td>Diagnostic and regression tooling (dump, display, compare)</td><td><span class="ac-live">live</span></td></tr></tbody></table></div><h6>Platforms</h6><p>
The VX/FMS runtime is native on Linux, and the same sources build for other Unix platforms
(macOS, HP-UX, and SCO) through build-time configuration. The library links directly into
the migrated application, so the target platform is whatever the recompiled application
targets.
</p><div class="callout"><strong>100 percent FDV$ API compatibility.</strong> Every FDV$ routine an existing
forms application calls is implemented with the same arguments and status conventions, so
migration is a relink rather than a rewrite. This makes VX/FMS a drop-in path for OpenVMS
FMS forms applications moving to Linux.
</div><h2 id="quickref">Quick reference</h2><h6>Session skeleton</h6><p>The canonical Form Driver session lifecycle:</p><div class="fms-flow" aria-label="VX/FMS Form Driver session lifecycle"><div class="fms-flow-stages"><div class="fms-flow-card"><span class="fms-flow-label">01</span><strong>Attach terminal</strong><span><code>FDV$ATERM</code></span></div><div class="fms-flow-card"><span class="fms-flow-label">02</span><strong>Attach or select workspace</strong><span><code>FDV$AWKSP</code> or <code>FDV$SWKSP</code></span></div><div class="fms-flow-card"><span class="fms-flow-label">03</span><strong>Open library</strong><span><code>FDV$LOPEN</code></span></div><div class="fms-flow-card"><span class="fms-flow-label">04</span><strong>Load form</strong><span><code>FDV$LOAD</code></span></div><div class="fms-flow-card"><span class="fms-flow-label">05</span><strong>Display</strong><span><code>FDV$DISP</code> or <code>FDV$DISPW</code></span></div><div class="fms-flow-card"><span class="fms-flow-label">06</span><strong>Read fields</strong><span><code>FDV$GET</code> or <code>FDV$GETAL</code></span></div><div class="fms-flow-card"><span class="fms-flow-label">07</span><strong>Detach workspace</strong><span><code>FDV$DWKSP</code></span></div><div class="fms-flow-card fms-flow-output"><span class="fms-flow-label">08</span><strong>Detach terminal</strong><span><code>FDV$DTERM</code></span></div></div></div><h6>At a glance</h6><div class="table-wrapper"><table><thead><tr><th>Item</th><th>Value</th></tr></thead><tbody><tr><td>Runtime library</td><td><code>libfms.a</code> / <code>libfms.so</code>, linked into the migrated application.</td></tr><tr><td>Public API</td><td>66 <code>FDV$</code> routines, dispatched to per-routine implementations.</td></tr><tr><td>Form language</td><td>Source <code>.flg</code> compiled to <code>.fbn</code> by <code>fms_form</code>.</td></tr><tr><td>Return convention</td><td>VMS condition value by value; odd is success, <code>FDV$_SUC</code> is success.</td></tr><tr><td>UARs</td><td>Bound by name in the <code>.flg</code>; dispatched through a table generated by <code>fms_uar</code>.</td></tr><tr><td>Terminals</td><td>VT100, VT220, DECterm, and ANSI emulators, driven by direct VT and ANSI escapes.</td></tr><tr><td>Utilities</td><td><code>fms_form</code>, <code>fmsedit</code>, <code>fms_uar</code>, <code>fms_display</code>, <code>fms_dump</code>, <code>fms_compare</code>.</td></tr></tbody></table></div><h6>Status codes</h6><p>
Form Driver routines return VMS-format 32-bit condition values, where odd values indicate
success. Field-level input conditions (for example full field, no previous field, numeric
required, or help available) are reported through the same status interface, and a
workspace-item form of the status is available through <code>FDV$STAT</code> for programs
that inspect completion detail.
</p><h6>Related Sector7 tools</h6><ul><li><a href="/technical/api-fms-forms-management-system">FMS$ - Forms Management System</a>: the callable FDV$ API companion, documented routine by routine.</li><li><a href="/technical/vx-rt-apis">VX/RT APIs</a>: the OpenVMS runtime environment VX/FMS integrates with on Linux.</li><li><a href="/technical/vx-rms-sys-routines-for-rms">VX/RMS</a>: RMS file access for the same migrated applications.</li><li><a href="/technical/vx-tdms-terminal-data-management-system">VX/TDMS</a> and <a href="/technical/vx-decforms---decforms-ifdl-compiler-and-forms">VX/DECFORMS</a>: sibling forms and screen-management tools in the same family.</li></ul></div>