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.

How VX/C works

VX/C is a source-to-source translator, not a compiler back-end: it produces C text, not object files. The binary, vxcpp, behaves like a C front-end. It runs its own lexer, a full C grammar with rewrite actions, a macro and #include 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 variant_union, variant_struct, globalref, and MAIN_PROGRAM.

Processing model

Input
OpenVMS C sourceVAX-C, DEC C, and VMS-C language extensions
01LexerTokenises the source and recognises VMS-C extensions.
02GrammarParses C syntax and selects the required rewrite actions.
03Edit bufferRewrites the token stream and records each applied fix.
Output
Portable POSIX ANSI CTransformed source plus diagnostics on standard error

Run lifecycle

  1. Install a watchdog timer and exit handlers to bound each run.
  2. Read trace controls from the environment (VXCPP_DEBUG / VXCPP_TRACE).
  3. Parse the command-line switches.
  4. Load the target platform personality (Linux or macOS) predefined macros; if none is selected, abort.
  5. Parse the source, applying edits into the edit buffer.
  6. If any parse errors occurred, suppress output and abort; otherwise write the transformed source to --output= or standard output.
Fail-fast output. 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.

Components

ComponentRole
vxcppThe translator: lexer, C grammar with rewrite actions, preprocessor, and output writer.
vxaddargsCompanion scanner that discovers variadic call sites and maintains the --vararg_file fixed-argument-count database.
Platform personalitiesPredefined-macro tables, one per target host: Linux (GCC macros) and macOS (Apple LLVM/clang macros).
Fix-tag catalogueThe /*S7-nnn*/ code set that annotates every applied edit in the output.

Source coverage and target platforms

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.

VMS-C constructs handled

The extensions and non-ANSI constructs VX/C rewrites into portable form include:

VMS / OpenVMS C constructANSI C result
variant_unionunion
variant_structstruct
globalrefextern
MAIN_PROGRAM()Synthesised int main(int argc, char **argv).
K&R variadics (<varargs.h>, va_dcl, va_alist)<stdarg.h> form with a generated argument counter.
Old-style function definitionsANSI prototypes with inserted return types and parameter types.
Address-of a constant or string (&123, &"HELLO")i_constant() / f_constant() or the literal itself.

Target personalities

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.

Transformations and fix tags

Every edit VX/C makes is annotated in the output with a /*S7-nnn*/ comment, so a reviewer can see exactly what changed and why. Annotations can be suppressed with --no-s7-tags. VX/C identifies and resolves the following categories of VMS / OpenVMS C issue.

Feature codeIssue identified
01.01Addressing constants (numbers)
01.02Addressing strings
03.01Variant struct/union usage
04.01Assigning unions to unions
05.01#include from a text library without quotes or angle brackets
05.02Logical-name #include references
05.04Case sensitivity in #include paths
06.01Missing function arguments
08.02Type mismatches
09.01Inconsistent function naming cases
10.02Use of VMS-specific compiler calls (e.g. vax$errno)
10.04Incompatible POSIX type usage (stderr, etc.)
16.01Undefined return types
19.01Typecasting on the left-hand side of assignments

The tool's inline replacement tags (/*S7-nnn*/) map back to these 14 categories.

Example: missing return type and terminal return

An old-style function with no return type and no return statement is legal in VMS C but not in ANSI C. VX/C inserts int and a terminating return.

/* VMS / OpenVMS C */
static ACCT_INIT (void)
{
}

/* Migrated ANSI C */
static int /*S7-100*/ ACCT_INIT (void)
{
    return ( int)0; /*S7-102*/
}

Example: missing arguments to a VMS system service

VX/C pads system-service calls (SYS$, LIB$, STR$, and similar) that were written with fewer than the required arguments.

/* VMS / OpenVMS C */
int t = SYS$QIO(0);

/* Migrated ANSI C */
int t = SYS$QIO(0/*S7-041*/,0,0,0,0,0,0,0,0,0,0,0);

Example: buffered I/O retargeting and argument padding

Buffered-I/O calls are retargeted to the vms_* runtime wrappers (S7-040), short argument lists are padded (S7-041), and fopen gets a trailing NULL (S7-042).

/* VMS / OpenVMS C */
cp = strerror(12);
fp = fopen("account.dat", "r+", "shr=nil");
i  = fclose(fp);

/* Migrated ANSI C */
cp = /*S7-040*/vms_strerror(12/*S7-041*/,0);
fp = /*S7-040*/vms_fopen("account.dat", "r+", "shr=nil", NULL /*S7-042*/);
i  = /*S7-040*/vms_fclose(fp);

Example: address-of-constant rewrites

Taking the address of a numeric constant, a float, or a string literal is rewritten to a portable equivalent.

/* VMS / OpenVMS C */
i  = & 1234;
i  = & 133.23;
cp = &"HELLO";

/* Migrated ANSI C */
i  = i_constant(1234)/*S7-008*/;
i  = f_constant(133.23)/*S7-010*/;
cp = "HELLO"/*S7-012*/;

Example: K&R varargs to stdarg

Old K&R variadic prototypes are converted to <stdarg.h> form: #include <varargs.h> becomes #include <stdarg.h>, the va_alist / va_dcl parameter list is rewritten with a generated argument counter, and va_start / va_count are adjusted to match. The vxaddargs companion tool supplies the correct fixed argument count for each function through the --vararg_file database.

Traceability. Because each transformation carries its own /*S7-nnn*/ tag, a reviewer can diff the migrated source against the original and account for every change the tool made.

Command-line interface

VX/C follows a standard compilation-like invocation. You run vxcpp with a list of switches and one or more C source files; transformed source is written to --output= or standard output, and diagnostics go to standard error.

vxcpp --vararg_file=/opt/vxrt/varargs_file \
      --include=./include \
      --vmsinclude=./vms_include \
      --output=account_posix.c \
      account.c

Core switches

SwitchEffect
--vms-api=lower|upperForce VMS API identifiers to lower or upper case.
--vmsinclude=<dir>Directory of VMS system include files that should not be translated.
--include=<dir>Search <dir> for header files.
--include-recursive=<dir>Recursively search <dir> for headers.
--hmap=<in.h>,<out.h>Single header remap. Repeatable.
--hmapdir=<dir>Use any .h in <dir> as a suffix-match replacement. Repeatable.
--hmapfile=<file>Read input-header to output-header mappings from a file.
--vararg_file=<file>Path to the variadic-function fixed-argument-count database.
--copy=<in_dir>,<out_dir>Directory-tree mode: mirror all output under <out_dir>.
--output=<file>Write transformed source to a file instead of standard output.
--no-s7-tagsSuppress the /*S7-nnn*/ annotations in the output.
--vms-guard-macrosWrap certain changes in #if defined guards.
-t[fimpstc]Trace: Files, Input, Macro, Pre-processor, Symbols, Tokens, Comments. Combinable.
--version / -hPrint the version banner or help, then exit.

Configuration and mapping files

Common option sets and header remaps do not have to be retyped on every run. --hmapfile= reads input-header to output-header mappings, --vararg_file= supplies fixed argument counts for variadic functions, and --copy= 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.

Trace controls

Tracing is available through the -t switch or the VXCPP_DEBUG / VXCPP_TRACE environment variables, which accept a comma-separated option string (pre-processor, tokens, symbols, files, macros, and more) plus an optional output=<file> redirect. YYDEBUG=n enables parser debug output.

Header and include handling

VX/C normalises #include 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.

#include fixes

SituationResult
#include from a text library without delimitersQuoted #include.
#include via a VMS logical nameResolved to a portable path.
Case mismatch in an #include pathCorrected to the actual filename case.
System header in quotesSwitched to angle brackets.
User header in angle bracketsSwitched to quotes.
#pragma dictionary "file" (CDD)#include "file.h".
#include <varargs.h>#include <stdarg.h>.

Built-in VMS to POSIX header map

Beyond user-supplied --hmap* maps, VX/C ships a fixed VMS to POSIX header-name table. The built-in pairs are:

VMS headerPOSIX header
inet.harpa/inet.h
nameser.harpa/nameser.h
nameser_compat.harpa/nameser_compat.h
if.hnet/if.h
if_arp.hnet/if_arp.h
if_types.hnet/if_types.h
netdb.hnetdb.h
in.hnetinet/in.h
tcp.hnetinet/tcp.h
in6.hnetinet6/in6.h
file.hsys/file.h
ioctl.hsys/ioctl.h
ipc.hsys/ipc.h
mman.hsys/mman.h
resource.hsys/resource.h
sem.hsys/sem.h
signal.hsys/signal.h
socket.hsys/socket.h
stat.hsys/stat.h
statvfs.hsys/statvfs.h
timeb.hsys/timeb.h
times.hsys/times.h
types.hsys/types.h
uio.hsys/uio.h
unistd.hsys/unistd.h
utsname.hsys/utsname.h
wait.hsys/wait.h
ints.hstdint.h
perror.hstdio.h

Example: #pragma dictionary to #include

Migrated code that pulled records from the OpenVMS Common Data Dictionary through #pragma dictionary is rewritten to a portable #include of the dictionary-derived header.

/* VMS / OpenVMS C */
typedef
#pragma dictionary "account_cmn.def"

/* Migrated ANSI C */
typedef
#include "account_cmn.def.h" /*S7-084 DICTIONARY */

Compatibility status

The table below summarises what VX/C transforms today and which targets it supports.

CapabilityStatus
K&R to ANSI prototype conversion, inserted return types and parameter typeslive
Missing-argument padding for SYS$, LIB$, STR$ callslive
Trailing-NULL insertion (fopen, LIB$SIGNAL, and similar)live
Buffered-I/O retargeting to vms_* runtime wrapperslive
Address-of-constant rewrites (i_constant / f_constant)live
#pragma dictionary to #include (CDD)live
<varargs.h> to <stdarg.h> conversionlive
#include delimiter, case, and logical-name fixeslive
Built-in and user-supplied header name remappinglive
Missing switch default insertionlive
Header guard-macro insertionlive
Linux target personalitylive
macOS target personalitylive
Windows targetout of scope

Diagnostics and exit codes

All operator messages are written to standard error; transformed source goes to --output= or standard output. VX/C returns a distinct exit code per failure class so a build script can react appropriately.

CodeMeaning
1File error
2Internal error
3Syntax error
4Missing include
5Option error
6No output (errors suppressed output)
7Identifier error

Quick reference

Invocation

vxcpp [switches] file.c        # transformed source to stdout or --output=
vxcpp --copy=<in>,<out> ...     # directory-tree mode

Core switches

--vms-api=lower|upper
--vmsinclude=<dir>
--include=<dir>
--include-recursive=<dir>
--hmap=<in>,<out>
--hmapdir=<dir>
--hmapfile=<file>
--vararg_file=<file>
--copy=<in>,<out>
--output=<file>
--no-s7-tags
--vms-guard-macros
-t[fimpstc]
--version
-h

Environment variables

VXCPP_DEBUG
VXCPP_TRACE
YYDEBUG

Exit codes

1 FILE
2 INTERNAL
3 SYNTAX
4 MISSING_INCLUDE
5 OPTION
6 NO_OUTPUT
7 IDENTIFIER

At a glance

  • Binary: vxcpp (product VX/C).
  • Input: OpenVMS/VAX-C and DEC C, including VMS-C extensions.
  • Output: portable, POSIX-compliant ANSI C.
  • Change markers: inline /*S7-nnn*/ tags across 14 feature-coded categories.
  • Header remaps: 29 built-in VMS to POSIX pairs, plus user --hmap* maps.
  • Targets: Linux and other POSIX/UNIX platforms (e.g. macOS). No Windows.

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 14 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.

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 is an automated source-to-source translator that reduces manual effort and gives consistent code output across large codebases. Every machine-applied edit is annotated inline with a /*S7-nnn*/ comment, so each change stays traceable and reviewable, and it works with existing Makefiles and build systems and fits continuous-integration workflows.

The result is portable, POSIX-compliant ANSI C that compiles cleanly off OpenVMS on Linux and macOS. 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.