VX/DCL - OpenVMS DCL
Overview
VX/DCL is a from-scratch reimplementation of the OpenVMS DIGITAL Command Language (DCL) that runs natively on Linux and Windows. It is a full command-line interpreter, not a shell wrapper: it has its own lexer, expression parser, symbol and logical-name machinery, and .COM command-file engine, so existing procedures and DCL-based automation run without modification. Interactive login runs SYLOGIN.COM and the user's LOGIN.COM in the same order as VMS.
The interpreter ships more than 120 built-in verb handlers and 43 F$ lexical functions, and reproduces VMS file-spec handling through the VX/RT runtime, including automatic VMS-to-Unix and VMS-to-UNC path translation. VX/DCL runs on the shared VX/RT runtime and calls sibling tools directly: VX/SORT for SORT and MERGE, VX/JSP for print and batch queues, and VX/RMS for file operations. It can also replace a user's login shell to give migrated operators a familiar captive DCL environment.
<!-- Webflow embed (min). Source: dcl-page-technical/dcl-tech-body-embed-dark.html → python3 website/embeds/minify_webflow_embed.py … -->
<div class="s7-tech-embed" data-vxdcld-body-embed="1" data-technical-mega-embed="1" lang="en"><h2 id="architecture">Architecture and components</h2><p>
VX/DCL is a full DCL command-line interpreter, not a wrapper around a Unix shell. It is
split into two source subsystems: the interpreter and verb handlers, and the CLI parsing
and lexical subsystem. Utilities that OpenVMS also ships as separate images (SORT, DIFF,
SEARCH, BACKUP and more) are built as standalone executables and dispatched as DCL verbs.
The table maps each major piece to its role.
</p><div class="table-wrapper"><table><thead><tr><th>Component</th><th>Subsystem</th><th>Role</th><th>Status</th></tr></thead><tbody><tr><td>DCL interpreter / CLI driver</td><td><code>dcl</code></td><td>Main read-eval loop, login and captive-account handling, <code>LOGIN.COM</code> / <code>SYLOGIN.COM</code> processing, banner, and dispatch entry.</td><td><span class="ac-live">live</span></td></tr><tr><td>Built-in verb handlers</td><td><code>dcl</code></td><td>121 distinct <code>DO_*</code> routines behind a 195-entry dispatch table.</td><td><span class="ac-live">live</span></td></tr><tr><td>Expression / lexical parser</td><td><code>cli</code></td><td>Operator and <code>F$</code> name table, expression-tree build, and path-translation resolution.</td><td><span class="ac-live">live</span></td></tr><tr><td>Lexical function bodies</td><td><code>cli</code></td><td>Implementations of <code>F$CVTIME</code>, <code>F$GETSYI</code>, <code>F$FILE_ATTRIBUTES</code>, <code>F$FAO</code> and the rest.</td><td><span class="ac-live">live</span></td></tr><tr><td>Command grammar parser</td><td><code>cli</code></td><td>Parses verb, qualifier and parameter syntax against the loaded CLD tables.</td><td><span class="ac-live">live</span></td></tr><tr><td>CLD table loader</td><td><code>cli</code></td><td>Loads Command Language Dictionary tables via <code>SET COMMAND</code>; default <code>sys$library:dcltables64.exe</code>.</td><td><span class="ac-live">live</span></td></tr><tr><td>Process control block</td><td><code>dcl</code></td><td>Per-process DCL state: symbols, logical names, and ON / control-Y state.</td><td><span class="ac-live">live</span></td></tr><tr><td>File-spec name parser</td><td><code>dcl</code></td><td>VMS file-spec parse through RMS extended attribute blocks.</td><td><span class="ac-live">live</span></td></tr><tr><td>Web / X front ends</td><td><code>dcl</code></td><td>Browser-hosted and X-hosted DCL sessions.</td><td><span class="ac-v1">partial: terminal CLI is the primary surface</span></td></tr></tbody></table></div><div class="callout"><strong>One interpreter, many verbs.</strong> VMS ships DCL alongside dozens of separate
utility images. VX/DCL can either spawn those utilities as external executables or link
them into a single interpreter image, so a deployment trades image size against
process-spawn cost without changing script behaviour.
</div><h6>Dispatch model</h6><p>
Every command line resolves to a verb handler through <code>dcl_dispatch()</code>. It first
consults small state-specific tables (for <code>IF</code> / <code>THEN</code> /
<code>ELSE</code> and <code>SUBROUTINE</code> handling while in a GOTO or CALL branch),
then the master verb table, and finally falls back to loading a routine from a dynamic
shared image. Every handler shares the signature <code>U32 DO_xxx(U32)</code> and returns
a VMS-style status code, so success is tested the VMS way: odd status is success.
</p><style>.s7-tech-embed .process-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 .process-stages,.s7-tech-embed .process-routes {display: grid;gap: 10px;}.s7-tech-embed .process-stages {grid-template-columns: repeat(3, minmax(0, 1fr));}.s7-tech-embed .process-routes {grid-template-columns: repeat(3, minmax(0, 1fr));margin: 10px 0;}.s7-tech-embed .process-stage {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 .process-route {border: 1px solid var(--s7t-note-bd);border-top-width: 3px;background: var(--s7t-note-bg);}.s7-tech-embed .process-number,.s7-tech-embed .process-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 .process-stage strong,.s7-tech-embed .process-stage span:last-child {display: block;}.s7-tech-embed .process-stage strong {margin-bottom: 4px;color: var(--s7t-text);}.s7-tech-embed .process-stage span:last-child {color: var(--s7t-muted);font-size: 0.9em;line-height: 1.45;}@media (max-width: 800px) {.s7-tech-embed .process-stages,.s7-tech-embed .process-routes {grid-template-columns: 1fr;}}</style><div class="process-flow" aria-label="VX/DCL command dispatch flow"><div class="process-stages"><div class="process-stage"><span class="process-number">01</span><strong>Command line</strong><span>The interpreter receives the DCL verb and its arguments.</span></div><div class="process-stage"><span class="process-number">02</span><strong>DCL_PARSE</strong><span>Matches the verb, qualifiers, and parameters against loaded CLD tables.</span></div><div class="process-stage"><span class="process-number">03</span><strong>dcl_dispatch()</strong><span>Resolves a handler name such as <code>DO_COPY</code> through ordered dispatch routes.</span></div></div><div class="process-routes" aria-label="Ordered dispatch routes"><div class="process-stage process-route"><span class="process-label">First</span><strong>State tables</strong><span>Handle <code>IF</code>, <code>THEN</code>, <code>ELSE</code>, <code>SUBROUTINE</code>, and false-branch state.</span></div><div class="process-stage process-route"><span class="process-label">Then</span><strong>doroutines[]</strong><span>Search 195 dispatch entries that resolve to 121 built-in <code>DO_*</code> handlers.</span></div><div class="process-stage process-route"><span class="process-label">Fallback</span><strong>Dynamic .so image</strong><span>Load an external utility routine when no internal route matches.</span></div></div><div class="process-stages"><div class="process-stage"><span class="process-number">04</span><strong>DO_xxx(U32)</strong><span>The selected built-in or loaded routine executes with the shared handler signature.</span></div><div class="process-stage"><span class="process-number">05</span><strong>VMS status</strong><span>The handler returns a code such as <code>SS$_NORMAL</code>.</span></div><div class="process-stage"><span class="process-number">06</span><strong>Success test</strong><span>An odd status value is treated as success.</span></div></div></div><h6>External utility images</h6><p>
File and data utilities are built as standalone executables and also compile into the
interpreter when a smaller footprint is wanted. The standalone image set includes:
</p><div class="kw-grid"><div>ANALYZE</div><div>CONVERT</div><div>DUMP</div><div>EDIT</div><div>MERGE</div><div>FTP</div><div>SORT</div><div>CC</div><div>CXX</div><div>CXXLINK</div><div>BASIC</div><div>FORTRAN</div><div>PASCAL</div><div>MONITOR</div><div>LIBRARY</div><div>TCPIP</div><div>ZIP</div><div>DIFF</div><div>HELP</div><div>SEARCH</div><div>SHOW</div><div>START</div><div>STOP</div></div><h2 id="command-language">The DCL command language</h2><p>
VX/DCL executes standard VMS <code>.COM</code> command procedures unchanged. Lines begin
with <code>$</code>; control constructs, symbol assignment (<code>=</code> and
<code>:=</code>), and lexical substitution (<code>'symbol'</code>,
<code>''lexical()'</code>) are all handled by the interpreter. At interactive login it runs
the system login procedure (<code>SYS$SYLOGIN</code>, resolving to
<code>SYS$MANAGER:SYLOGIN.COM</code>) and then the user's
<code>SYS$LOGIN:LOGIN.COM</code>, matching VMS ordering, so captive and menu-driven login
environments behave the way operators expect.
</p><h6>Symbols, logical names and substitution</h6><p>
Local and global symbols, logical-name tables, and the full VMS substitution rules are
implemented in the interpreter's per-process control block. The procedure below is a
representative end-of-day batch job for a funds-transfer system: it sets a symbol and a
logical name, tests for a file with the <code>F$SEARCH</code> lexical, sorts a ledger
through VX/SORT, and queues a follow-on procedure through VX/JSP.
</p>
<pre><span class="cmt">$! nightly_close.com - end-of-day batch for the funds-transfer system</span>
$
$ <span class="kw">SET</span> NOON
$ ACCT_DIR <span class="kw">:==</span> SYS$LOGIN:[BANKING.ACCOUNTS]
$ <span class="kw">DEFINE</span> ACCT$DATA DUA0:[BANKING.DATA]
$
$ start_time = <span class="kw">F$TIME</span>()
$ <span class="kw">WRITE</span> SYS$OUTPUT <span class="str">"Close started at ''start_time'"</span>
$
$ <span class="kw">IF</span> <span class="kw">F$SEARCH</span>(<span class="str">"ACCT$DATA:LEDGER.DAT"</span>) .EQS. <span class="str">""</span>
$ <span class="kw">THEN</span>
$ <span class="kw">WRITE</span> SYS$OUTPUT <span class="str">"No ledger to process - exiting"</span>
$ <span class="kw">EXIT</span>
$ <span class="kw">ENDIF</span>
$
$ <span class="kw">SORT</span>/KEY=(POSITION:1,SIZE:12) ACCT$DATA:LEDGER.DAT LEDGER_SORTED.DAT
$ <span class="kw">SUBMIT</span>/QUEUE=SYS$BATCH ACCT_DIR:POST_STATEMENTS.COM
$ <span class="kw">EXIT</span></pre>
<p>
Nested single and double quotes substitute symbols and lexical results into the command
line before it is parsed, exactly as on VMS. Foreign commands (a symbol assigned to an
image plus arguments) dispatch through the same path, so tools invoked by name from a
procedure continue to work.
</p><h6>Built-in verbs by category</h6><p>
VX/DCL implements more than 120 distinct built-in verbs (195 dispatch entries once the
<code>SET</code>, <code>SHOW</code> and <code>TCPIP</code> sub-verbs are counted). They
group into the same families as native DCL.
</p><div class="table-wrapper"><table><thead><tr><th>Category</th><th>Representative verbs</th></tr></thead><tbody><tr><td>Flow and procedure control</td><td><code>IF</code>, <code>THEN</code>, <code>ELSE</code>, <code>GOTO</code>, <code>GOSUB</code>, <code>CALL</code>, <code>SUBROUTINE</code>, <code>ON</code>, <code>EXIT</code>, <code>INQUIRE</code>, <code>WAIT</code></td></tr><tr><td>Symbols and logical names</td><td><code>ASSIGN</code>, <code>DEASSIGN</code>, <code>DEFINE</code>, <code>DEFINE/KEY</code>, <code>SET SYMBOL</code>, <code>DELETE/SYMBOL</code>, <code>SET UIC</code></td></tr><tr><td>File and data utilities</td><td><code>COPY</code>, <code>CREATE</code>, <code>DELETE</code>, <code>APPEND</code>, <code>RENAME</code>, <code>PURGE</code>, <code>TYPE</code>, <code>DIRECTORY</code>, <code>BACKUP</code>, <code>CONVERT</code>, <code>DUMP</code>, <code>SEARCH</code>, <code>DIFFERENCES</code>, <code>SORT</code>, <code>MERGE</code></td></tr><tr><td>Process and image execution</td><td><code>RUN</code>, <code>SPAWN</code>, <code>ATTACH</code>, <code>MCR</code>, <code>PIPE</code>, <code>RECALL</code>, <code>ALLOCATE</code>, <code>DEALLOCATE</code></td></tr><tr><td>Queues, batch and print</td><td><code>PRINT</code>, <code>SUBMIT</code>, <code>START/QUEUE</code>, <code>STOP/QUEUE</code>, <code>INITIALIZE/QUEUE</code>, <code>SET QUEUE</code>, <code>SHOW QUEUE</code>, <code>SET ENTRY</code></td></tr><tr><td>Networking and remote</td><td><code>FTP</code>, <code>SSH</code>, <code>SCP</code>, <code>SFTP</code>, <code>SET HOST/SSH</code>, <code>TCPIP</code></td></tr><tr><td>Environment and operator</td><td><code>SET</code> (27 sub-verbs), <code>SHOW</code> (27 sub-verbs), <code>REPLY</code>, <code>REQUEST</code>, <code>MAIL</code>, <code>MONITOR</code></td></tr></tbody></table></div><h6>Essential commands</h6><p>These commonly-migrated commands are implemented so command procedures and interactive use continue without modification.</p><div class="table-wrapper"><table><thead><tr><th>Command</th><th>Function</th></tr></thead><tbody><tr><td><code>ALLOCATE</code></td><td>Assigns a device to a process.</td></tr><tr><td><code>ASSIGN</code></td><td>Creates a logical name.</td></tr><tr><td><code>COPY</code></td><td>Copies files from one location to another.</td></tr><tr><td><code>CREATE</code></td><td>Creates new files or directories.</td></tr><tr><td><code>DELETE</code></td><td>Removes files or directories.</td></tr><tr><td><code>PRINT</code></td><td>Submits print jobs through VX/JSP.</td></tr><tr><td><code>SUBMIT</code></td><td>Submits batch jobs through VX/JSP.</td></tr><tr><td><code>SHOW QUEUE</code></td><td>Displays job queue status.</td></tr><tr><td><code>SET DEFAULT</code></td><td>Changes the current working directory.</td></tr></tbody></table></div><h2 id="lexicals">Lexical functions</h2><p>
VX/DCL implements 43 DCL lexical functions. They are registered by name in the expression
parser and evaluated by dedicated bodies that balance parentheses, resolve the expression,
and substitute the result back into the command line. The table lists the functions
scripts reach for most often; the full set is in the quick reference.
</p><div class="table-wrapper"><table><thead><tr><th>Lexical</th><th>Purpose</th></tr></thead><tbody><tr><td><code>F$SEARCH</code></td><td>Search a directory for a file spec; returns the full spec or an empty string.</td></tr><tr><td><code>F$PARSE</code></td><td>Parse a file spec through RMS and return a named component.</td></tr><tr><td><code>F$FILE_ATTRIBUTES</code></td><td>Return an RMS file attribute item such as record format or size.</td></tr><tr><td><code>F$CVTIME</code></td><td>Convert or decompose a date-time into fields like YEAR, MONTH or DAYOFYEAR.</td></tr><tr><td><code>F$TIME</code></td><td>Return the current date-time string.</td></tr><tr><td><code>F$EXTRACT</code> / <code>F$ELEMENT</code></td><td>Substring by start and length; extract a delimited element.</td></tr><tr><td><code>F$EDIT</code></td><td>Edit a string: UPCASE, TRIM, COMPRESS and related operations.</td></tr><tr><td><code>F$LENGTH</code> / <code>F$LOCATE</code></td><td>String length; offset of a substring.</td></tr><tr><td><code>F$INTEGER</code> / <code>F$STRING</code></td><td>Convert an expression to an integer or to a string.</td></tr><tr><td><code>F$GETDVI</code></td><td>Get a device or volume information item.</td></tr><tr><td><code>F$GETJPI</code></td><td>Get a job or process information item.</td></tr><tr><td><code>F$GETQUI</code></td><td>Get a queue information item.</td></tr><tr><td><code>F$GETSYI</code></td><td>Get a system information item.</td></tr><tr><td><code>F$TRNLNM</code></td><td>Translate a logical name.</td></tr><tr><td><code>F$MODE</code></td><td>Return the process mode (INTERACTIVE, BATCH and so on).</td></tr><tr><td><code>F$MESSAGE</code></td><td>Return the message text for a status code.</td></tr><tr><td><code>F$FAO</code></td><td>Formatted ASCII output for building formatted strings.</td></tr></tbody></table></div><div class="callout"><strong>Selectable item keywords are supported.</strong> The <code>F$GETxxx</code>
lexicals resolve item keywords through per-facility tables, so
<code>F$GETDVI</code> device items (such as <code>FREEBLOCKS</code>),
<code>F$GETJPI</code> process items, <code>F$GETQUI</code> queue items and
<code>F$FILE_ATTRIBUTES</code> record formats (<code>FIX</code>, <code>VAR</code>,
<code>VFC</code>, <code>STM</code>) all behave as they do on VMS.
</div><h6>Example: F$CVTIME and nested substitution</h6><p>
The procedure below exercises <code>F$CVTIME</code> and the nested double-quote
substitution rules. It is representative of date-driven batch logic that migrates
unchanged.
</p>
<pre>$ <span class="kw">WRITE</span> SYS$OUTPUT <span class="str">" DATETIME ''F$CVTIME (,,""DATETIME"")'"</span>
$ <span class="kw">WRITE</span> SYS$OUTPUT <span class="str">" DATE ''F$CVTIME (,,""DATE"")'"</span>
$ <span class="kw">WRITE</span> SYS$OUTPUT <span class="str">" YEAR ''F$CVTIME (,,""YEAR"")'"</span>
$ <span class="kw">WRITE</span> SYS$OUTPUT <span class="str">" WEEKDAY ''F$CVTIME (,,""WEEKDAY"")'"</span>
$ <span class="kw">WRITE</span> SYS$OUTPUT <span class="str">" DAYOFYEAR ''F$CVTIME (,,""DAYOFYEAR"")'"</span>
$ <span class="kw">WRITE</span> SYS$OUTPUT <span class="str">" Yesterday ''F$CVTIME (""YESTERDAY"",""ABSOLUTE"",""DAYOFYEAR"")'"</span>
$ <span class="kw">EXIT</span></pre>
<p><code>F$CVTIME</code> supports the full VMS output field set (<code>DATETIME</code>,
<code>DATE</code>, <code>TIME</code>, <code>YEAR</code>, <code>MONTH</code>,
<code>DAY</code>, <code>WEEKDAY</code>, <code>HOUR</code>, <code>MINUTE</code>,
<code>SECOND</code>, <code>DAYOFYEAR</code> and more) and the input keywords
<code>YESTERDAY</code>, <code>TODAY</code>, <code>TOMORROW</code> and
<code>ABSOLUTE</code>.
</p><h2 id="path-translation">File system and path translation</h2><p>
VX/DCL retains full compatibility with VMS file specifications and translates them to and
from host paths automatically. Conversion is done through the VX/RT runtime rather than
inside the interpreter, so the same path mapper serves every file verb, lexical function,
and RMS operation. Scripts that pass VMS file specs keep working, and the interpreter
handles logical-name mapping, device-table management, and automatic case conversion for
file specifications.
</p><div class="table-wrapper"><table><thead><tr><th>VMS path</th><th>Linux equivalent</th></tr></thead><tbody><tr><td><code>DUA0:[A.B.C]FILE.TXT</code></td><td><code>/vms_disk/A/B/C/FILE.TXT</code></td></tr><tr><td><code>SYS$LOGIN:LOGIN.COM</code></td><td><code>/home/user/LOGIN.COM</code></td></tr></tbody></table></div><h6>Path-translation lexicals</h6><p>
Four path-translation lexicals expose the runtime's path mapper directly to scripts. They
are VX/DCL extensions, not present in native VMS DCL, and are the recommended way for a
procedure to move between VMS and host path conventions when it needs an explicit
conversion.
</p><div class="table-wrapper"><table><thead><tr><th>Lexical</th><th>Conversion</th></tr></thead><tbody><tr><td><code>F$VMS_TO_UNIX</code></td><td>VMS file spec to a Unix path.</td></tr><tr><td><code>F$UNIX_TO_VMS</code></td><td>Unix path to a VMS file spec.</td></tr><tr><td><code>F$VMS_TO_UNC</code></td><td>VMS file spec to a Windows or UNC path.</td></tr><tr><td><code>F$UNC_TO_VMS</code></td><td>Windows or UNC path to a VMS file spec.</td></tr></tbody></table></div><div class="callout"><strong>Case handling is a build-time choice.</strong> Linux is case-sensitive while VMS
is case-insensitive and upcasing. On a case-preserving deployment, uppercase symlinks are
created alongside their lowercase targets so that VMS-style uppercase file references
resolve correctly.
</div><h6>RMS file-spec parsing</h6><p>
VMS file specs are parsed through RMS extended attribute blocks, so device, directory,
name, type, and version decomposition matches RMS behaviour. This is the same machinery
that resolves <code>LOGIN.COM</code> at login and that backs the
<code>DUA0:[A.B.C]FILE.TXT</code> mapping above, which keeps file handling in the file
verbs (<code>COPY</code>, <code>CREATE</code>, <code>APPEND</code>, <code>BACKUP</code>,
<code>CONVERT</code>, <code>DIRECTORY</code>) consistent with the rest of the runtime.
</p><h2 id="integrations">Sector7 tool integrations</h2><p>
VX/DCL runs on the shared VX/RT runtime and calls its sibling tools directly through their
native APIs. These are real link-time dependencies, not marketing adjacency: DCL verbs
hand work to the same libraries a migrated application would use, so behaviour matches
end to end.
</p><div class="table-wrapper"><table><thead><tr><th>Tool</th><th>How VX/DCL uses it</th></tr></thead><tbody><tr><td><a href="/technical/vx-rt-apis">VX/RT</a></td><td>Runtime foundation: descriptors, configuration, path mapping, process and spawn control, captive and batch mode, and terminal control. VX/DCL reports the shared VX/RT version in its banner.</td></tr><tr><td><a href="/technical/vx-sort-vms-sor-merge">VX/SORT</a></td><td>The <code>SORT</code> and <code>MERGE</code> verbs call the VX/SORT API directly, mapping the VMS qualifier surface (<code>/KEY</code>, <code>/NODUPLICATES</code>, <code>/STABLE</code>) onto its sort options.</td></tr><tr><td><a href="/technical/vx-jsp-vms-print-batch">VX/JSP</a></td><td><code>PRINT</code>, <code>SUBMIT</code> and the queue verbs create jobs through VX/JSP against <code>SYS$PRINT</code> and <code>SYS$BATCH</code>.</td></tr><tr><td><a href="/technical/vx-rms-sys-routines-for-rms">VX/RMS</a></td><td>File-spec parsing and the file verbs (<code>COPY</code>, <code>CREATE</code>, <code>APPEND</code>, <code>BACKUP</code>, <code>CONVERT</code>, <code>DELETE</code>, <code>DIRECTORY</code>) operate over RMS extended attribute blocks.</td></tr><tr><td>VX/CLD</td><td>Command and verb grammar is driven by CLD tables loaded at startup (default <code>sys$library:dcltables64.exe</code>), so <code>SET COMMAND</code> and custom verb definitions work as on VMS.</td></tr></tbody></table></div><h6>Example: the SORT verb calling VX/SORT</h6><p>
The <code>DO_SORT</code> handler shows the full VX/SORT lifecycle: feed each input file,
begin the sort, run it, then always release the sort context. Every call is checked with
the VMS convention that odd status is success.
</p>
<pre><span class="kw">while</span> (nn < num_files) {
vxrt_dsc64t(&d_infile, (U16)strlen(infile[nn]), infile[nn]); nn++;
rc = SOR_D_PASS_FILES(&d_infile, &d_outfile, org); <span class="cmt">// feed each input file</span>
<span class="kw">if</span> ((rc & 1) == 0) {
fprintf(sysout, <span class="str">"DCL$SORT: SOR$PASS_FILES Error\r\n"</span>);
VX_RETURNS(rc);
}
vxrt_dsc64t(&d_outfile, 0, NULL); <span class="cmt">// clear output for next pass</span>
}
rc = SOR_D_BEGIN_SORT(key_info, &key_mrs, &key_options); <span class="cmt">// start the sort</span>
rc = SOR_D_SORT_MERGE(); <span class="cmt">// run it</span>
SORT_END:;
rc = SOR_D_END_SORT(); <span class="cmt">// always release the sort context</span></pre>
<h2 id="compatibility">Compatibility and divergences</h2><p>
The goal is source-level compatibility: existing <code>.COM</code> files, logical names,
symbols and lexicals run without modification. The matrix summarises what is present and
wired in the runtime today.
</p><div class="table-wrapper"><table><thead><tr><th>Capability</th><th>Status</th></tr></thead><tbody><tr><td><code>.COM</code> procedure execution plus <code>LOGIN.COM</code> / <code>SYLOGIN.COM</code></td><td><span class="ac-live">live</span></td></tr><tr><td>121 built-in verb handlers across a 195-entry dispatch table</td><td><span class="ac-live">live</span></td></tr><tr><td>43 <code>F$</code> lexical functions</td><td><span class="ac-live">live</span></td></tr><tr><td>VMS-to-Unix and VMS-to-UNC path translation</td><td><span class="ac-live">live</span></td></tr><tr><td>Logical names, symbols, <code>DEFINE</code> and <code>ASSIGN</code></td><td><span class="ac-live">live</span></td></tr><tr><td>SORT and MERGE through VX/SORT</td><td><span class="ac-live">live</span></td></tr><tr><td>PRINT, SUBMIT and queues through VX/JSP</td><td><span class="ac-live">live</span></td></tr><tr><td>File utilities (COPY, BACKUP, CONVERT, DIRECTORY, DIFF, SEARCH, DUMP)</td><td><span class="ac-live">live</span></td></tr><tr><td>Captive accounts and login-shell replacement</td><td><span class="ac-live">live</span></td></tr><tr><td>Networking verbs (FTP, SSH, SCP, SFTP, TCPIP)</td><td><span class="ac-live">live</span></td></tr><tr><td>Compiler front-end verbs (CC, CXX, FORTRAN, PASCAL, BASIC, LINK, MMS)</td><td><span class="ac-live">live</span></td></tr><tr><td>Web-hosted and X-hosted DCL sessions</td><td><span class="ac-v1">partial: terminal CLI is the primary surface</span></td></tr></tbody></table></div><h6>Intentional divergences from native VMS DCL</h6><p>
A handful of behaviours differ from native DCL by design, so scripts can interoperate with
a Linux or Windows host. Each divergence is additive: VMS syntax still behaves the VMS way.
</p><div class="table-wrapper"><table><thead><tr><th>Divergence</th><th>Reason</th></tr></thead><tbody><tr><td>Adds <code>F$VMS_TO_UNIX</code>, <code>F$UNIX_TO_VMS</code>, <code>F$VMS_TO_UNC</code>, <code>F$UNC_TO_VMS</code></td><td>The host filesystem is POSIX or Windows, so scripts need explicit access to the path mapper.</td></tr><tr><td>Adds <code>F$SHELLVAR</code>, <code>DO_UNIX</code>, <code>SETENV</code></td><td>Lets procedures read host environment variables and run Linux commands from the <code>$</code> prompt.</td></tr><tr><td>Adds SSH, SCP and SFTP verbs</td><td>DECnet and LAT transports are replaced by TCP/IP and OpenSSH on the host.</td></tr><tr><td>Utilities can be external images or linked into the interpreter</td><td>Lets a deployment trade image size against process-spawn cost.</td></tr><tr><td>Case handling gated by a build-time switch</td><td>Linux is case-sensitive; VMS is case-insensitive and upcasing, so a build option reconciles the two.</td></tr></tbody></table></div><h2 id="quickref">Quick reference</h2><h6>Lexical functions (43)</h6><div class="kw-grid"><div>F$ADDTIME</div><div>F$CONTEXT</div><div>F$CSID</div><div>F$CVSI</div><div>F$CVTIME</div><div>F$CVUI</div><div>F$DEVICE</div><div>F$DIRECTORY</div><div>F$EDIT</div><div>F$ELEMENT</div><div>F$ENVIRONMENT</div><div>F$EXTRACT</div><div>F$FAO</div><div>F$FILE_ATTRIBUTES</div><div>F$GETDVI</div><div>F$GETJPI</div><div>F$GETQUI</div><div>F$GETSYI</div><div>F$IDENTIFIER</div><div>F$INTEGER</div><div>F$LENGTH</div><div>F$LOCATE</div><div>F$LOGICAL</div><div>F$MESSAGE</div><div>F$MODE</div><div>F$PARSE</div><div>F$PID</div><div>F$PRIVILEGE</div><div>F$PROCESS</div><div>F$SEARCH</div><div>F$SETPRV</div><div>F$SHELLVAR</div><div>F$STRING</div><div>F$TIME</div><div>F$TRNLNM</div><div>F$TYPE</div><div>F$UNIQUE</div><div>F$USER</div><div>F$VERIFY</div><div>F$VMS_TO_UNIX</div><div>F$UNIX_TO_VMS</div><div>F$VMS_TO_UNC</div><div>F$UNC_TO_VMS</div></div><h6>Path-translation extensions</h6><div class="kw-grid"><div>F$VMS_TO_UNIX</div><div>F$UNIX_TO_VMS</div><div>F$VMS_TO_UNC</div><div>F$UNC_TO_VMS</div><div>F$SHELLVAR</div></div><h6>Verb categories</h6><div class="kw-grid"><div>Flow control</div><div>Symbols and logicals</div><div>File utilities</div><div>Process and image</div><div>Queues and batch</div><div>Networking</div><div>SET (27 sub-verbs)</div><div>SHOW (27 sub-verbs)</div><div>System and operator</div></div><h6>Key facts</h6><div class="table-wrapper"><table><thead><tr><th>Item</th><th>Value</th></tr></thead><tbody><tr><td>Built-in verbs</td><td>121 <code>DO_*</code> handlers behind a 195-entry dispatch table.</td></tr><tr><td>Lexical functions</td><td>43 <code>F$</code> functions.</td></tr><tr><td>Help topics</td><td>104 top-level topics in the DCL help database.</td></tr><tr><td>Command tables</td><td>Loaded from <code>sys$library:dcltables64.exe</code> (or <code>dcltables32.exe</code>), up to 32 tables.</td></tr><tr><td>Runtime</td><td>Shared VX/RT runtime, reported in the VX/DCL banner.</td></tr><tr><td>Platforms</td><td>x86 and ARM Linux, and Windows.</td></tr></tbody></table></div></div>