🚨 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

VX/C - OpenVMS C to ANSI C

Overview

VX/C is Sector7's automated source-to-source translator for C. It reads OpenVMS/VAX-C and DEC C source and emits portable, POSIX-compliant ANSI C, optimized for Linux and other POSIX/UNIX platforms (e.g. macOS). It identifies, flags, and corrects VMS-specific syntax and dependencies so migrated code compiles cleanly off OpenVMS.

Every machine-applied edit is annotated inline with a /*S7-nnn*/ comment, so each change stays traceable and reviewable. VX/C behaves like a C front-end: it runs its own lexer, a full C grammar, a macro and #include preprocessor, and an edit buffer that rewrites the original source in place. It works with existing Makefiles and build systems and fits continuous-integration workflows. The command-line binary is vxcpp.

<!-- Webflow embed (min). Source: c-page-technical/c-tech-body-embed-dark.html → python3 website/embeds/minify_webflow_embed.py … --> <div class="s7-tech-embed" data-vxcd-body-embed="1" data-technical-mega-embed="1" lang="en"><h2 id="architecture">How VX/C works</h2><p> VX/C is a source-to-source translator, not a compiler back-end: it produces C text, not object files. The binary, <code>vxcpp</code>, behaves like a C front-end. It runs its own lexer, a full C grammar with rewrite actions, a macro and <code>#include</code> preprocessor, a symbol-table and scope engine, and an edit buffer that rewrites the original token stream in place. Recognised input includes OpenVMS/VAX-C and DEC C, along with VMS-C language extensions such as <code>variant_union</code>, <code>variant_struct</code>, <code>globalref</code>, and <code>MAIN_PROGRAM</code>. </p><h6>Processing model</h6><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-endpoint {display: grid;grid-template-columns: 72px minmax(0, 1fr);gap: 14px;align-items: center;padding: 14px 16px;border-radius: 8px;background: var(--s7t-surface);color: var(--s7t-text);}.s7-tech-embed .process-output {border: 1px solid var(--s7t-note-bd);background: var(--s7t-note-bg);}.s7-tech-embed .process-label,.s7-tech-embed .process-number {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-endpoint div,.s7-tech-embed .process-stage {min-width: 0;}.s7-tech-embed .process-endpoint strong,.s7-tech-embed .process-endpoint span:last-child,.s7-tech-embed .process-stage strong,.s7-tech-embed .process-stage span:last-child {display: block;}.s7-tech-embed .process-endpoint strong,.s7-tech-embed .process-stage strong {margin-bottom: 4px;color: var(--s7t-text);}.s7-tech-embed .process-endpoint span:last-child,.s7-tech-embed .process-stage span:last-child {color: var(--s7t-muted);font-size: 0.9em;line-height: 1.45;}.s7-tech-embed .process-stages {display: grid;grid-template-columns: repeat(3, minmax(0, 1fr));gap: 10px;margin: 10px 0;}.s7-tech-embed .process-stage {padding: 15px;border-top: 3px solid var(--s7t-accent);border-radius: 6px;background: var(--s7t-surface2);color: var(--s7t-text);}.s7-tech-embed .process-stage .process-number {margin-bottom: 10px;}@media (max-width: 800px) {.s7-tech-embed .process-stages {grid-template-columns: 1fr;}.s7-tech-embed .process-endpoint {grid-template-columns: 1fr;gap: 5px;}}</style><div class="process-flow" aria-label="VX/C source transformation stages"><div class="process-endpoint"><span class="process-label">Input</span><div><strong>OpenVMS C source</strong><span>VAX-C, DEC C, and VMS-C language extensions</span></div></div><div class="process-stages"><div class="process-stage"><span class="process-number">01</span><strong>Lexer</strong><span>Tokenises the source and recognises VMS-C extensions.</span></div><div class="process-stage"><span class="process-number">02</span><strong>Grammar</strong><span>Parses C syntax and selects the required rewrite actions.</span></div><div class="process-stage"><span class="process-number">03</span><strong>Edit buffer</strong><span>Rewrites the token stream and records each applied fix.</span></div></div><div class="process-endpoint process-output"><span class="process-label">Output</span><div><strong>Portable POSIX ANSI C</strong><span>Transformed source plus diagnostics on standard error</span></div></div></div><h6>Run lifecycle</h6><ol><li>Install a watchdog timer and exit handlers to bound each run.</li><li>Read trace controls from the environment (<code>VXCPP_DEBUG</code> / <code>VXCPP_TRACE</code>).</li><li>Parse the command-line switches.</li><li>Load the target platform personality (Linux or macOS) predefined macros; if none is selected, abort.</li><li>Parse the source, applying edits into the edit buffer.</li><li>If any parse errors occurred, suppress output and abort; otherwise write the transformed source to <code>--output=</code> or standard output.</li></ol><div class="callout"><strong>Fail-fast output.</strong> If the parse accumulates any errors, VX/C does not write partial output. It aborts and reports how many errors were seen, so a broken translation is never emitted silently. </div><h6>Components</h6><div class="table-wrapper"><table><thead><tr><th>Component</th><th>Role</th></tr></thead><tbody><tr><td><code>vxcpp</code></td><td>The translator: lexer, C grammar with rewrite actions, preprocessor, and output writer.</td></tr><tr><td><code>vxaddargs</code></td><td>Companion scanner that discovers variadic call sites and maintains the <code>--vararg_file</code> fixed-argument-count database.</td></tr><tr><td>Platform personalities</td><td>Predefined-macro tables, one per target host: Linux (GCC macros) and macOS (Apple LLVM/clang macros).</td></tr><tr><td>Fix-tag catalogue</td><td>The <code>/*S7-nnn*/</code> code set that annotates every applied edit in the output.</td></tr></tbody></table></div><h2 id="dialects">Source coverage and target platforms</h2><p> VX/C accepts OpenVMS C written for VAX-C and DEC C, including the VMS-C language extensions, and rewrites it into portable ANSI C. Output targets Linux and other POSIX/UNIX platforms (e.g. macOS). There is no Windows target. </p><h6>VMS-C constructs handled</h6><p>The extensions and non-ANSI constructs VX/C rewrites into portable form include:</p><div class="table-wrapper"><table><thead><tr><th>VMS / OpenVMS C construct</th><th>ANSI C result</th></tr></thead><tbody><tr><td><code>variant_union</code></td><td><code>union</code></td></tr><tr><td><code>variant_struct</code></td><td><code>struct</code></td></tr><tr><td><code>globalref</code></td><td><code>extern</code></td></tr><tr><td><code>MAIN_PROGRAM()</code></td><td>Synthesised <code>int main(int argc, char **argv)</code>.</td></tr><tr><td>K&amp;R variadics (<code>&lt;varargs.h&gt;</code>, <code>va_dcl</code>, <code>va_alist</code>)</td><td><code>&lt;stdarg.h&gt;</code> form with a generated argument counter.</td></tr><tr><td>Old-style function definitions</td><td>ANSI prototypes with inserted return types and parameter types.</td></tr><tr><td>Address-of a constant or string (<code>&amp;123</code>, <code>&amp;"HELLO"</code>)</td><td><code>i_constant()</code> / <code>f_constant()</code> or the literal itself.</td></tr></tbody></table></div><h6>Target personalities</h6><p> VX/C selects a target personality at run time and loads that host's predefined macros so preprocessor conditionals resolve the same way the native compiler would. Two personalities ship today: Linux, using GCC predefined macros, and macOS, using Apple LLVM/clang predefined macros. If no personality is selected, VX/C aborts rather than guessing. </p><h2 id="transformations">Transformations and fix tags</h2><p> Every edit VX/C makes is annotated in the output with a <code>/*S7-nnn*/</code> comment, so a reviewer can see exactly what changed and why. Annotations can be suppressed with <code>--no-s7-tags</code>. VX/C identifies and resolves the following categories of VMS / OpenVMS C issue. </p><div class="table-wrapper"><table><thead><tr><th>Feature code</th><th>Issue identified</th></tr></thead><tbody><tr><td><strong>01.01</strong></td><td>Addressing constants (numbers)</td></tr><tr><td><strong>01.02</strong></td><td>Addressing strings</td></tr><tr><td><strong>03.01</strong></td><td>Variant struct/union usage</td></tr><tr><td><strong>04.01</strong></td><td>Assigning unions to unions</td></tr><tr><td><strong>05.01</strong></td><td><code>#include</code> from a text library without quotes or angle brackets</td></tr><tr><td><strong>05.02</strong></td><td>Logical-name <code>#include</code> references</td></tr><tr><td><strong>05.04</strong></td><td>Case sensitivity in <code>#include</code> paths</td></tr><tr><td><strong>06.01</strong></td><td>Missing function arguments</td></tr><tr><td><strong>08.02</strong></td><td>Type mismatches</td></tr><tr><td><strong>09.01</strong></td><td>Inconsistent function naming cases</td></tr><tr><td><strong>10.02</strong></td><td>Use of VMS-specific compiler calls (e.g. <code>vax$errno</code>)</td></tr><tr><td><strong>10.04</strong></td><td>Incompatible POSIX type usage (<code>stderr</code>, etc.)</td></tr><tr><td><strong>16.01</strong></td><td>Undefined return types</td></tr><tr><td><strong>19.01</strong></td><td>Typecasting on the left-hand side of assignments</td></tr></tbody></table></div><p>The tool's inline replacement tags (<code>/*S7-nnn*/</code>) map back to these 14 categories.</p><h6>Example: missing return type and terminal return</h6><p> An old-style function with no return type and no <code>return</code> statement is legal in VMS C but not in ANSI C. VX/C inserts <code>int</code> and a terminating return. </p> <pre><span class="cmt">/* VMS / OpenVMS C */</span> static ACCT_INIT (void) { } <span class="cmt">/* Migrated ANSI C */</span> static int <span class="cmt">/*S7-100*/</span> ACCT_INIT (void) { return ( int)0; <span class="cmt">/*S7-102*/</span> }</pre> <h6>Example: missing arguments to a VMS system service</h6><p> VX/C pads system-service calls (<code>SYS$</code>, <code>LIB$</code>, <code>STR$</code>, and similar) that were written with fewer than the required arguments. </p> <pre><span class="cmt">/* VMS / OpenVMS C */</span> int t = SYS$QIO(0); <span class="cmt">/* Migrated ANSI C */</span> int t = SYS$QIO(0<span class="cmt">/*S7-041*/</span>,0,0,0,0,0,0,0,0,0,0,0);</pre> <h6>Example: buffered I/O retargeting and argument padding</h6><p> Buffered-I/O calls are retargeted to the <code>vms_*</code> runtime wrappers (<code>S7-040</code>), short argument lists are padded (<code>S7-041</code>), and <code>fopen</code> gets a trailing <code>NULL</code> (<code>S7-042</code>). </p> <pre><span class="cmt">/* VMS / OpenVMS C */</span> cp = strerror(12); fp = fopen("account.dat", "r+", "shr=nil"); i = fclose(fp); <span class="cmt">/* Migrated ANSI C */</span> cp = <span class="cmt">/*S7-040*/</span>vms_strerror(12<span class="cmt">/*S7-041*/</span>,0); fp = <span class="cmt">/*S7-040*/</span>vms_fopen("account.dat", "r+", "shr=nil", NULL <span class="cmt">/*S7-042*/</span>); i = <span class="cmt">/*S7-040*/</span>vms_fclose(fp);</pre> <h6>Example: address-of-constant rewrites</h6><p> Taking the address of a numeric constant, a float, or a string literal is rewritten to a portable equivalent. </p> <pre><span class="cmt">/* VMS / OpenVMS C */</span> i = &amp; 1234; i = &amp; 133.23; cp = &amp;"HELLO"; <span class="cmt">/* Migrated ANSI C */</span> i = i_constant(1234)<span class="cmt">/*S7-008*/</span>; i = f_constant(133.23)<span class="cmt">/*S7-010*/</span>; cp = "HELLO"<span class="cmt">/*S7-012*/</span>;</pre> <h6>Example: K&amp;R varargs to stdarg</h6><p> Old K&amp;R variadic prototypes are converted to <code>&lt;stdarg.h&gt;</code> form: <code>#include &lt;varargs.h&gt;</code> becomes <code>#include &lt;stdarg.h&gt;</code>, the <code>va_alist</code> / <code>va_dcl</code> parameter list is rewritten with a generated argument counter, and <code>va_start</code> / <code>va_count</code> are adjusted to match. The <code>vxaddargs</code> companion tool supplies the correct fixed argument count for each function through the <code>--vararg_file</code> database. </p><div class="callout"><strong>Traceability.</strong> Because each transformation carries its own <code>/*S7-nnn*/</code> tag, a reviewer can diff the migrated source against the original and account for every change the tool made. </div><h2 id="cli">Command-line interface</h2><p> VX/C follows a standard compilation-like invocation. You run <code>vxcpp</code> with a list of switches and one or more C source files; transformed source is written to <code>--output=</code> or standard output, and diagnostics go to standard error. </p> <pre>vxcpp --vararg_file=/opt/vxrt/varargs_file \ --include=./include \ --vmsinclude=./vms_include \ --output=account_posix.c \ account.c</pre> <h6>Core switches</h6><div class="table-wrapper"><table><thead><tr><th>Switch</th><th>Effect</th></tr></thead><tbody><tr><td><code>--vms-api=lower|upper</code></td><td>Force VMS API identifiers to lower or upper case.</td></tr><tr><td><code>--vmsinclude=&lt;dir&gt;</code></td><td>Directory of VMS system include files that should not be translated.</td></tr><tr><td><code>--include=&lt;dir&gt;</code></td><td>Search <code>&lt;dir&gt;</code> for header files.</td></tr><tr><td><code>--include-recursive=&lt;dir&gt;</code></td><td>Recursively search <code>&lt;dir&gt;</code> for headers.</td></tr><tr><td><code>--hmap=&lt;in.h&gt;,&lt;out.h&gt;</code></td><td>Single header remap. Repeatable.</td></tr><tr><td><code>--hmapdir=&lt;dir&gt;</code></td><td>Use any <code>.h</code> in <code>&lt;dir&gt;</code> as a suffix-match replacement. Repeatable.</td></tr><tr><td><code>--hmapfile=&lt;file&gt;</code></td><td>Read input-header to output-header mappings from a file.</td></tr><tr><td><code>--vararg_file=&lt;file&gt;</code></td><td>Path to the variadic-function fixed-argument-count database.</td></tr><tr><td><code>--copy=&lt;in_dir&gt;,&lt;out_dir&gt;</code></td><td>Directory-tree mode: mirror all output under <code>&lt;out_dir&gt;</code>.</td></tr><tr><td><code>--output=&lt;file&gt;</code></td><td>Write transformed source to a file instead of standard output.</td></tr><tr><td><code>--no-s7-tags</code></td><td>Suppress the <code>/*S7-nnn*/</code> annotations in the output.</td></tr><tr><td><code>--vms-guard-macros</code></td><td>Wrap certain changes in <code>#if defined</code> guards.</td></tr><tr><td><code>-t[fimpstc]</code></td><td>Trace: Files, Input, Macro, Pre-processor, Symbols, Tokens, Comments. Combinable.</td></tr><tr><td><code>--version</code> / <code>-h</code></td><td>Print the version banner or help, then exit.</td></tr></tbody></table></div><h6>Configuration and mapping files</h6><p> Common option sets and header remaps do not have to be retyped on every run. <code>--hmapfile=</code> reads input-header to output-header mappings, <code>--vararg_file=</code> supplies fixed argument counts for variadic functions, and <code>--copy=</code> processes a whole directory tree, mirroring its subdirectories into an output tree. This makes VX/C easy to drive from a batch script over a source estate and then compile the transformed output. </p><h6>Trace controls</h6><p> Tracing is available through the <code>-t</code> switch or the <code>VXCPP_DEBUG</code> / <code>VXCPP_TRACE</code> environment variables, which accept a comma-separated option string (pre-processor, tokens, symbols, files, macros, and more) plus an optional <code>output=&lt;file&gt;</code> redirect. <code>YYDEBUG=n</code> enables parser debug output. </p><h2 id="headers">Header and include handling</h2><p> VX/C normalises <code>#include</code> directives and remaps VMS header names to their POSIX equivalents. System includes are forced to angle-bracket delimiters and user includes to quoted form, filename case is corrected to match the file on a case-sensitive POSIX filesystem, and VMS text-library or logical-name includes are rewritten to portable paths. </p><h6>#include fixes</h6><div class="table-wrapper"><table><thead><tr><th>Situation</th><th>Result</th></tr></thead><tbody><tr><td><code>#include</code> from a text library without delimiters</td><td>Quoted <code>#include</code>.</td></tr><tr><td><code>#include</code> via a VMS logical name</td><td>Resolved to a portable path.</td></tr><tr><td>Case mismatch in an <code>#include</code> path</td><td>Corrected to the actual filename case.</td></tr><tr><td>System header in quotes</td><td>Switched to angle brackets.</td></tr><tr><td>User header in angle brackets</td><td>Switched to quotes.</td></tr><tr><td><code>#pragma dictionary "file"</code> (CDD)</td><td><code>#include "file.h"</code>.</td></tr><tr><td><code>#include &lt;varargs.h&gt;</code></td><td><code>#include &lt;stdarg.h&gt;</code>.</td></tr></tbody></table></div><h6>Built-in VMS to POSIX header map</h6><p> Beyond user-supplied <code>--hmap*</code> maps, VX/C ships a fixed VMS to POSIX header-name table. The built-in pairs are: </p><div class="table-wrapper"><table><thead><tr><th>VMS header</th><th>POSIX header</th></tr></thead><tbody><tr><td><code>inet.h</code></td><td><code>arpa/inet.h</code></td></tr><tr><td><code>nameser.h</code></td><td><code>arpa/nameser.h</code></td></tr><tr><td><code>nameser_compat.h</code></td><td><code>arpa/nameser_compat.h</code></td></tr><tr><td><code>if.h</code></td><td><code>net/if.h</code></td></tr><tr><td><code>if_arp.h</code></td><td><code>net/if_arp.h</code></td></tr><tr><td><code>if_types.h</code></td><td><code>net/if_types.h</code></td></tr><tr><td><code>netdb.h</code></td><td><code>netdb.h</code></td></tr><tr><td><code>in.h</code></td><td><code>netinet/in.h</code></td></tr><tr><td><code>tcp.h</code></td><td><code>netinet/tcp.h</code></td></tr><tr><td><code>in6.h</code></td><td><code>netinet6/in6.h</code></td></tr><tr><td><code>file.h</code></td><td><code>sys/file.h</code></td></tr><tr><td><code>ioctl.h</code></td><td><code>sys/ioctl.h</code></td></tr><tr><td><code>ipc.h</code></td><td><code>sys/ipc.h</code></td></tr><tr><td><code>mman.h</code></td><td><code>sys/mman.h</code></td></tr><tr><td><code>resource.h</code></td><td><code>sys/resource.h</code></td></tr><tr><td><code>sem.h</code></td><td><code>sys/sem.h</code></td></tr><tr><td><code>signal.h</code></td><td><code>sys/signal.h</code></td></tr><tr><td><code>socket.h</code></td><td><code>sys/socket.h</code></td></tr><tr><td><code>stat.h</code></td><td><code>sys/stat.h</code></td></tr><tr><td><code>statvfs.h</code></td><td><code>sys/statvfs.h</code></td></tr><tr><td><code>timeb.h</code></td><td><code>sys/timeb.h</code></td></tr><tr><td><code>times.h</code></td><td><code>sys/times.h</code></td></tr><tr><td><code>types.h</code></td><td><code>sys/types.h</code></td></tr><tr><td><code>uio.h</code></td><td><code>sys/uio.h</code></td></tr><tr><td><code>unistd.h</code></td><td><code>sys/unistd.h</code></td></tr><tr><td><code>utsname.h</code></td><td><code>sys/utsname.h</code></td></tr><tr><td><code>wait.h</code></td><td><code>sys/wait.h</code></td></tr><tr><td><code>ints.h</code></td><td><code>stdint.h</code></td></tr><tr><td><code>perror.h</code></td><td><code>stdio.h</code></td></tr></tbody></table></div><h6>Example: #pragma dictionary to #include</h6><p> Migrated code that pulled records from the OpenVMS Common Data Dictionary through <code>#pragma dictionary</code> is rewritten to a portable <code>#include</code> of the dictionary-derived header. </p> <pre><span class="cmt">/* VMS / OpenVMS C */</span> typedef #pragma dictionary "account_cmn.def" <span class="cmt">/* Migrated ANSI C */</span> typedef #include "account_cmn.def.h" <span class="cmt">/*S7-084 DICTIONARY */</span></pre> <h2 id="compatibility">Compatibility status</h2><p>The table below summarises what VX/C transforms today and which targets it supports.</p><div class="table-wrapper"><table><thead><tr><th>Capability</th><th>Status</th></tr></thead><tbody><tr><td>K&amp;R to ANSI prototype conversion, inserted return types and parameter types</td><td><span class="ac-live">live</span></td></tr><tr><td>Missing-argument padding for <code>SYS$</code>, <code>LIB$</code>, <code>STR$</code> calls</td><td><span class="ac-live">live</span></td></tr><tr><td>Trailing-<code>NULL</code> insertion (<code>fopen</code>, <code>LIB$SIGNAL</code>, and similar)</td><td><span class="ac-live">live</span></td></tr><tr><td>Buffered-I/O retargeting to <code>vms_*</code> runtime wrappers</td><td><span class="ac-live">live</span></td></tr><tr><td>Address-of-constant rewrites (<code>i_constant</code> / <code>f_constant</code>)</td><td><span class="ac-live">live</span></td></tr><tr><td><code>#pragma dictionary</code> to <code>#include</code> (CDD)</td><td><span class="ac-live">live</span></td></tr><tr><td><code>&lt;varargs.h&gt;</code> to <code>&lt;stdarg.h&gt;</code> conversion</td><td><span class="ac-live">live</span></td></tr><tr><td><code>#include</code> delimiter, case, and logical-name fixes</td><td><span class="ac-live">live</span></td></tr><tr><td>Built-in and user-supplied header name remapping</td><td><span class="ac-live">live</span></td></tr><tr><td>Missing <code>switch</code> default insertion</td><td><span class="ac-live">live</span></td></tr><tr><td>Header guard-macro insertion</td><td><span class="ac-live">live</span></td></tr><tr><td>Linux target personality</td><td><span class="ac-live">live</span></td></tr><tr><td>macOS target personality</td><td><span class="ac-live">live</span></td></tr><tr><td>Windows target</td><td><span class="ac-no">out of scope</span></td></tr></tbody></table></div><h6>Diagnostics and exit codes</h6><p> All operator messages are written to standard error; transformed source goes to <code>--output=</code> or standard output. VX/C returns a distinct exit code per failure class so a build script can react appropriately. </p><div class="table-wrapper"><table><thead><tr><th>Code</th><th>Meaning</th></tr></thead><tbody><tr><td><code>1</code></td><td>File error</td></tr><tr><td><code>2</code></td><td>Internal error</td></tr><tr><td><code>3</code></td><td>Syntax error</td></tr><tr><td><code>4</code></td><td>Missing include</td></tr><tr><td><code>5</code></td><td>Option error</td></tr><tr><td><code>6</code></td><td>No output (errors suppressed output)</td></tr><tr><td><code>7</code></td><td>Identifier error</td></tr></tbody></table></div><h2 id="quickref">Quick reference</h2><h6>Invocation</h6> <pre>vxcpp [switches] file.c <span class="cmt"># transformed source to stdout or --output=</span> vxcpp --copy=&lt;in&gt;,&lt;out&gt; ... <span class="cmt"># directory-tree mode</span></pre> <h6>Core switches</h6><div class="kw-grid"><div>--vms-api=lower|upper</div><div>--vmsinclude=&lt;dir&gt;</div><div>--include=&lt;dir&gt;</div><div>--include-recursive=&lt;dir&gt;</div><div>--hmap=&lt;in&gt;,&lt;out&gt;</div><div>--hmapdir=&lt;dir&gt;</div><div>--hmapfile=&lt;file&gt;</div><div>--vararg_file=&lt;file&gt;</div><div>--copy=&lt;in&gt;,&lt;out&gt;</div><div>--output=&lt;file&gt;</div><div>--no-s7-tags</div><div>--vms-guard-macros</div><div>-t[fimpstc]</div><div>--version</div><div>-h</div></div><h6>Environment variables</h6><div class="kw-grid"><div>VXCPP_DEBUG</div><div>VXCPP_TRACE</div><div>YYDEBUG</div></div><h6>Exit codes</h6><div class="kw-grid"><div>1 FILE</div><div>2 INTERNAL</div><div>3 SYNTAX</div><div>4 MISSING_INCLUDE</div><div>5 OPTION</div><div>6 NO_OUTPUT</div><div>7 IDENTIFIER</div></div><h6>At a glance</h6><ul><li><strong>Binary:</strong> <code>vxcpp</code> (product VX/C).</li><li><strong>Input:</strong> OpenVMS/VAX-C and DEC C, including VMS-C extensions.</li><li><strong>Output:</strong> portable, POSIX-compliant ANSI C.</li><li><strong>Change markers:</strong> inline <code>/*S7-nnn*/</code> tags across 14 feature-coded categories.</li><li><strong>Header remaps:</strong> 29 built-in VMS to POSIX pairs, plus user <code>--hmap*</code> maps.</li><li><strong>Targets:</strong> Linux and other POSIX/UNIX platforms (e.g. macOS). No Windows.</li></ul></div>

Frequently Asked Questions

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

What is VX/C and how does it help with OpenVMS C migration?

VX/C is Sector7's automated tool that converts VMS/OpenVMS C source code into portable, POSIX-compliant ANSI C. It identifies, flags, and corrects VMS-specific issues to ensure your code runs seamlessly on Linux environments.

The tool provides fully automated source code conversion, works with existing Makefiles and build systems, and handles VMS-specific syntax and dependencies. For organizations looking to modernize their legacy systems, contact us to discuss your migration requirements.

What VMS-specific issues does VX/C automatically detect and fix?

VX/C identifies and resolves over 15 categories of VMS-specific issues including addressing constants, variant struct/union usage, missing function arguments, VMS-specific compiler calls, and POSIX type incompatibilities.

How does VX/C handle VMS include files and logical names?

VX/C automatically handles VMS-specific include file references, logical name includes, and case sensitivity issues in include paths, ensuring proper POSIX compliance in the migrated code.

What is the typical workflow for using VX/C?

VX/C functions like a C compiler, parsing source files and generating formatted reports, fix scripts, and POSIX-compliant source code through a simple command-line interface.

How does VX/C integrate with existing development environments?

VX/C seamlessly integrates with existing Makefiles and build systems, providing configuration file support for default options. It generates SED scripts for automated code fixes that can be easily applied to your source code.

Companies like DuPont have successfully used similar migration tools to modernize their legacy C applications while maintaining their existing development workflows.

What types of output does VX/C provide?

VX/C provides three types of output: formatted reports for issue identification, database files with tab-separated logs for tracking, and SED scripts for automated code fixes.

Can VX/C fix function prototype issues automatically?

Yes, VX/C automatically corrects missing function arguments, undefined return types, and inconsistent function naming cases. It converts VMS-specific function calls to their POSIX-compliant equivalents and fixes typecasting issues on assignment operations.

What are the main benefits of using VX/C for legacy migration projects?

VX/C delivers fully automated migration that reduces manual effort and ensures consistent code output across large codebases. It supports continuous integration workflows and has been proven effective in high-complexity migrations.

Organizations achieve seamless portability from VMS/OpenVMS to Linux environments while maintaining code functionality. Companies like Honeywell have leveraged similar automated tools for successful large-scale migrations.

To learn more about how VX/C can accelerate your migration project, contact our migration experts.

What does VX/C convert, and what does it produce?

VX/C takes OpenVMS/VAX-C and DEC C source and produces portable, POSIX-compliant ANSI C. It identifies, flags, and corrects VMS-specific issues so the generated code targets Linux and other POSIX/UNIX platforms such as macOS.

How is VX/C invoked?

VX/C works like a C compiler. You run the vxcpp command with a list of switches (for example --include=, --vms-api=lower, --output=) and one or more C source files. It also reads mapping files (--hmapfile=, --vararg_file=) so common option sets and header remaps do not have to be retyped on every run.

What kinds of VMS-specific C issues does VX/C detect?

VX/C covers 14 feature-coded categories, including addressing constants and strings, variant struct and union usage, union-to-union assignment, several #include problems (text-library includes, logical-name references, case sensitivity), missing function arguments, type mismatches, inconsistent function-naming cases, VMS-specific compiler calls such as vax$errno, incompatible POSIX type usage, undefined return types, and left-hand-side typecasting.

Does VX/C change my code automatically, or just report problems?

Both. It rewrites the source into POSIX-compliant ANSI C and marks every edit inline with a traceable /*S7-nnn*/ annotation (for example /*S7-041*/ where it padded a system-service call's arguments), and it writes diagnostics for anything it cannot handle to standard error.

How does VX/C make its changes traceable?

Every transformation is tagged in the output with a /*S7-nnn*/ comment that identifies the rule applied, so a reviewer can diff the migrated source against the original and see exactly what the tool did and why. The annotations can be suppressed with --no-s7-tags when they are no longer needed.

How does VX/C handle VMS #include and logical-name references?

It addresses #include directives that pull from a text library without delimiters, #include references via VMS logical names, and case-sensitivity differences in #include paths. It also remaps VMS header names to their POSIX equivalents (for example stat.h to sys/stat.h, in.h to netinet/in.h) using a built-in table plus any user-supplied maps.

Does VX/C fit into an existing build and CI setup?

Yes. It works with existing Makefiles and build systems and supports continuous-integration workflows. It is typically driven by a batch script that runs vxcpp over a source tree, using --copy= for directory-tree mode, and then compiles the transformed output.

Which platforms does VX/C target?

VX/C produces code for Linux and other POSIX/UNIX platforms such as macOS. It ships target personalities that load the correct predefined macros for each host (GCC on Linux, Apple LLVM/clang on macOS). There is no Windows target.

Transform Your Legacy Software Today!

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