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/MSG – OpenVMS Message Compiler

Overview

VX/MSG is a native reimplementation of the OpenVMS message compiler for Linux. It reads OpenVMS message-definition files (.msg) and compiles each message into an indexed message database that the runtime reads through SYS$GETMSG, so migrated applications keep the same OpenVMS message calls and message codes without source changes.

The compiler preserves the OpenVMS message-code layout (facility, message number, and severity) and reproduces the SYS$MESSAGE:MESSAGES.SYS file structure that VMS applications expect. It can also emit 3GL constant sources, so application code continues to reference message symbols by name exactly as it did on OpenVMS. Full compatibility with SYS$GETMSG, SYS$FAO, and SYS$FAOL means messages are retrieved and formatted at runtime with no changes to calling code.

Architecture and compilation pipeline

VX/MSG is a small, single-pass compiler, not a long-running service. It reads an OpenVMS-style message-definition file (.msg) and, in its default mode, writes each message as a fixed-size record into an indexed database that the VX/RT runtime reads back through SYS$GETMSG. There is no server process to administer: compilation happens once per build, and lookups happen inside the migrated application. The table maps each OpenVMS message-system component to its VX/MSG counterpart.

OpenVMS componentVX/MSG counterpartRoleStatus
MESSAGE (message compiler)msgParses .msg facilities, symbols, text, and qualifiers and compiles them into the indexed message database.live
SYS$MESSAGE:MESSAGES.SYSIndexed (ISAM) database via VX/RMSThe on-disk message store, keyed by message code, that the runtime reads at lookup time.live
SYS$GETMSGVX/RT SYS$GETMSGLooks a message up by its 32-bit code at run time and returns the text plus argument metadata.live
SYS$FAO / SYS$FAOLVX/RT formatting servicesSubstitute FAO directives (for example !UL, !AS) in the retrieved text at run time.live
Shared message imagemsgsecFlattens the indexed database into a memory-mappable image (messages.shr) for a fast lookup path.live
3GL message constantsmsg -c / -h / -fEmit C, C header, or FORTRAN constant sources so application code references message symbols by name.live

Data flow

The compile-time flow runs offline, once per build:

Compile 01messages.msgMessage definitions enter the compiler on standard input.
Compile 02msg compilerParses facilities, symbols, severities, text, and qualifiers.
Compile 03Select output modeThe default database path and optional source-generation path remain separate.
Default outputSYS$MESSAGE:MESSAGES.SYSWrites the indexed message database as .dat and .idx files.
-c, -h, or -f outputLanguage constantsWrites C, C header, or FORTRAN constant source to standard output.

The run-time flow happens inside the migrated application:

Runtime 01MESSAGES.SYSThe compiled indexed database is the runtime message source.
Runtime 02msgsec -fFlattens the indexed records into messages.shr.
Runtime 03Memory mapThe runtime maps messages.shr for fast indexed access.
Runtime 04SYS$GETMSG(code)Looks up the code and returns the matching message text and metadata.
Runtime 05SYS$FAO or SYS$FAOLSubstitutes directives such as !UL and !AS.
Runtime 06Formatted lineThe migrated application receives the final display text.
No runtime rebuild step. The runtime reads the message database fresh at lookup time, so a recompiled MESSAGES.SYS takes effect on the next run with no relink of the calling application.

The .msg message-definition format

A .msg file is line-oriented and uses the same syntax as the OpenVMS message source it replaces. The scanner recognises four line shapes: comments, control words (leading .), symbol names, and message text with optional per-message qualifiers. Existing OpenVMS message sources compile through VX/MSG without editing.

Control words

Control wordEffect
.FACILITY name, num [/SYSTEM] [/PREFIX=xxx]Starts a facility and resets numbering. A user facility number is OR'd with the user-supplied bit unless /SYSTEM is given; /PREFIX sets the symbol prefix.
.BASE n (or .BASE ^Xhhh)Sets the next message number. A user facility adds the user base offset; /SYSTEM facilities use the number exactly. The hex form uses a ^X prefix.
.SEVERITY nameSets the default severity for following messages: SUCCESS, INFORMATIONAL, WARNING, ERROR, or FATAL / SEVERE.
.IDENT textStores an ident string for the module.
.TITLE textStores a title string for the module.
.PAGEPage break. No effect on the compiled output.
.ENDEnd-of-file marker.

Symbols, message text, and qualifiers

A symbol name at the start of a line names the message. Message text follows in one of two delimiter styles: double quotes ("...text...") or angle brackets (<...text...>), with angle brackets supporting nesting. A trailing - continues a definition onto the next line, so a symbol, its qualifiers, and its text can span several lines. Per-message qualifiers refine a single message:

QualifierMeaning
/FAO_COUNT=nNumber of FAO substitution arguments the message text expects.
/USER=nA user-supplied value stored alongside the message.
/IDENTIFICATION=xAccepted for source compatibility.
/SUCCESS /INFORMATIONAL /WARNING /ERROR /FATAL /SEVEREOverride the default severity for this one message.

Example

A user facility for a funds-transfer service, with FAO directives left in the text for the runtime to substitute through SYS$FAO:

.facility BANKING, 2048 /PREFIX=BANK$_
.base 0
.severity ERROR

INSUFFUNDS   <insufficient funds in account !UL> /FAO_COUNT=1
ACCTLOCKED   <account !AS is locked> /FAO_COUNT=1
XFERDONE     <transfer of !UL cents completed> /FAO_COUNT=1 /SUCCESS

Here !UL (unsigned longword) and !AS (counted ASCII string) are VMS FAO directives. VX/MSG stores the message text verbatim and records the argument count from /FAO_COUNT, leaving the substitution itself to SYS$FAO and SYS$GETMSG at run time.

Message codes and the output record

VX/MSG reproduces the OpenVMS 32-bit message-code layout exactly, so codes compiled on Linux match the values applications and callers already expect. Each code is assembled from the facility number, the message index (base plus sequence within the facility), and the severity:

code = (facility << 16) | ((base + sequence) << 3) | severity

Bits 0 to 2 hold the severity, bits 3 to 15 hold the message index, and bits 16 to 27 hold the facility number. A user facility (one declared without /SYSTEM) carries the user-supplied bit in its facility word. The severity encoding matches OpenVMS:

SeverityValue
WARNING0
SUCCESS1
ERROR2
INFORMATIONAL3
FATAL / SEVERE4

The message record

Each message is written to the database as a fixed-size record holding the code, the facility number, argument metadata, and the facility, symbol, and message-text strings:

typedef struct {
    U32    msgnum;            /* code with severity masked off */
    U32    facnum;
    unsigned char optinfo[4]; /* [0]=severity [1]=FAO count [2]=user [3]=reserved */
    char   facnam[32];
    char   msgnam[64];
    char   message[256];
} MESSAGE_RECORD;
Severity is masked out of the key. The ISAM key is the message code with the low three severity bits cleared, and the actual severity is preserved in optinfo[0]. A lookup by code therefore matches regardless of the severity a caller passes, matching OpenVMS behaviour. Duplicate keys update the existing record rather than failing the build.

Command-line interface

The compiler reads a .msg file from standard input (or from a filename argument) and selects one of two behaviours. With no source-generation flag it populates the indexed message database. With a source-generation flag it writes a 3GL constant source to standard output and does not touch the database; the two modes are mutually exclusive.

FlagEffect
-q / --quietSuppress the startup banner.
-cEmit a C source file with a linkable constant per message.
-hEmit a C header file with a #define per message.
-fEmit a FORTRAN source file with a PARAMETER constant per message.
-nEmit a C table of {code, FAO_COUNT} pairs for messages that take arguments.
-pPreserve the original case of symbol names.
-lLowercase symbol names.
-sEmit GNU-ld --defsym linker constants (used with the FORTRAN path).

Flags can be bundled, so msg -qc is a quiet C-source generation run.

Generated constant shapes

The source-generation modes emit one constant per message symbol:

ModeOutput form
C source (-c)int NAME = 0x<code>;, guarded for VMS globalvalue linkage.
C header (-h)#define NAME 0x<code>, with a comment naming the facility and severity.
FORTRAN (-f)PARAMETER NAME = '<code>'x, plus a matching PARAMETER per facility.

Worked example

# compile the message source into the indexed database
msg -q banking.msg
#   populates SYS$MESSAGE:MESSAGES.SYS (.dat + .idx)

# generate a C header of message constants for the application build
msg -h < banking.msg > bank_messages.h

# generate FORTRAN constants
msg -f < banking.msg > bank_messages.for

Runtime lookup and files on disk

At run time the migrated application calls SYS$GETMSG with a message code, and VX/RT resolves it against the compiled database. The default database is SYS$MESSAGE:MESSAGES.SYS, where the logical name SYS$MESSAGE resolves to the message directory under the VX/RT release. The indexed store is two files:

FileContents
MESSAGES.SYS.datThe message records: codes, facility and symbol names, argument metadata, and message text.
MESSAGES.SYS.idxThe index over message codes used for fast lookup.
messages.shrOptional memory-mappable image built by msgsec -f for a faster lookup path.

Lookup path

SYS$GETMSG prefers the memory-mapped messages.shr image when it is present and falls back to the indexed database otherwise. If neither is available it returns default placeholder text, and an unknown code returns the standard SS$_MSGNOTFND status, so callers see well-defined behaviour rather than a crash. The argument metadata returned to the caller matches what the compiler wrote: the FAO argument count and the user value travel with the message text.

Viewing the database

Because the store mirrors the OpenVMS SYS$MESSAGE layout, compiled messages can be inspected from VX/DCL just as on OpenVMS, which is useful for verifying a message-source compile during a migration:

$ TYPE/PAGE SYS$MESSAGE:MESSAGES.SYS

Compatibility and language support

VX/MSG targets source-level compatibility with the OpenVMS message system: existing .msg sources compile unchanged, message codes keep their original layout, and the runtime message calls behave as they did on OpenVMS. The matrix below summarises what is supported today.

CapabilityStatus
Compile .msg to indexed MESSAGES.SYS (.dat / .idx)live
SYS$GETMSG, SYS$FAO, SYS$FAOL retrieval and formattinglive
C source constants (-c)live
C header #defines (-h)live
FORTRAN constants (-f)live
FAO-count table (-n) and FORTRAN linker constants (-s)live
Symbol-case control (-p / -l)live
Memory-mapped shared image (msgsec)live
View compiled messages from VX/DCLlive

Message constants for application code

Applications that referenced message symbols by name on OpenVMS continue to do so on Linux. VX/MSG generates constant sources for C, C headers, and FORTRAN, so C and C++ callers include the generated header and FORTRAN callers include the generated PARAMETER definitions. Each constant carries the same message code the runtime resolves, keeping the compile-time symbol and the run-time lookup in step.

Migration posture. VX/MSG preserves the message-code layout, the SYS$MESSAGE file structure, and the SYS$ retrieval calls, so message handling migrates with minimal changes to application code.

Quick reference

Control words

.FACILITY
.BASE
.SEVERITY
.IDENT
.TITLE
.PAGE
.END

Qualifiers

/SYSTEM
/PREFIX=
/FAO_COUNT=n
/USER=n
/IDENTIFICATION=
/SUCCESS
/INFORMATIONAL
/WARNING
/ERROR
/FATAL
/SEVERE

Severity values

WARNING = 0
SUCCESS = 1
ERROR = 2
INFORMATIONAL = 3
FATAL / SEVERE = 4

Compiler flags

-q / --quiet
-c
-h
-f
-n
-p
-l
-s

Runtime services

SYS$GETMSG
SYS$FAO
SYS$FAOL

Common commands

# compile to the indexed message database
msg -q messages.msg

# generate constants
msg -c < messages.msg > constants.c
msg -h < messages.msg > constants.h
msg -f < messages.msg > constants.for

# view compiled messages via VX/DCL
$ TYPE/PAGE SYS$MESSAGE:MESSAGES.SYS

Frequently Asked Questions

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

What is VX/MSG and how does it help with VMS message migration?

VX/MSG is a VMS/OpenVMS message file compiler that translates message definitions (.msg) into indexed memory files on Linux, ensuring full compatibility with SYS$ API calls. It enables seamless application migration while preserving original messaging functionality and generates 3GL message constants for multiple programming languages including C, C++, BASIC, Fortran, COBOL, and PASCAL.

This tool simplifies VMS modernization by maintaining message-handling capabilities without requiring code modifications. Contact us to discuss your VMS message migration requirements.

Which programming languages does VX/MSG support for message constants?

VX/MSG generates message constants for C, C++, Fortran, COBOL, BASIC, and Pascal programming languages.

What SYS$ API calls are supported by VX/MSG?

VX/MSG provides full compatibility with VMS SYS$ API calls including SYS$GETMSG, SYS$FAO, and SYS$FAOL for message retrieval and formatting.

How does VX/MSG compile message files?

VX/MSG compiles VMS/OpenVMS message files (.msg) into indexed binary files (.dat and .idx), creating an efficient storage and retrieval system that mirrors the VMS SYS$MESSAGE system.

Does VX/MSG support message display and viewing?

VX/MSG supports message display via VX/DCL, allowing messages to be viewed and retrieved similarly to VMS environments.

What file formats does VX/MSG create for message storage?

VX/MSG creates an indexed file format consisting of .dat and .idx files that contain binary message data along with indexing information for fast retrieval, ensuring efficient message storage and access.

What is VX/MSG?

VX/MSG is a reimplementation of the OpenVMS message compiler for Linux. It translates OpenVMS message-definition files (.msg) into an indexed message database, preserving the original OpenVMS message-handling behaviour so migrated applications keep their messaging without a rewrite.

Does VX/MSG require rewriting application code?

No. VX/MSG preserves the OpenVMS message-code layout, reproduces the SYS$MESSAGE file structure, and keeps the SYS$GETMSG, SYS$FAO, and SYS$FAOL calls compatible, so message handling migrates with minimal changes to application code.

Which OpenVMS message calls does VX/MSG stay compatible with?

VX/MSG works with the OpenVMS SYS$ message services used for retrieval and formatting, specifically SYS$GETMSG, SYS$FAO, and SYS$FAOL, so code that calls them keeps working after migration.

What files does the VX/MSG compiler produce?

In its default mode VX/MSG compiles a .msg source into an indexed message database made up of a data file (.dat) and an index file (.idx), stored as SYS$MESSAGE:MESSAGES.SYS, matching the way OpenVMS stores messages.

Which languages can VX/MSG generate message constants for?

VX/MSG can generate message-constant sources so application code references messages by name: a C source file (-c), a C header of #define constants (-h), and FORTRAN PARAMETER constants (-f).

How does VX/MSG fit into a build process?

VX/MSG runs as a normal build step on Linux. A makefile rule invokes the compiler to turn the .msg definitions into the indexed messages file, and it can generate language constant headers for the application build at the same time.

Can compiled messages be viewed after migration?

Yes. Because the database mirrors the OpenVMS SYS$MESSAGE layout, compiled messages can be inspected from VX/DCL (for example TYPE/PAGE SYS$MESSAGE:MESSAGES.SYS), which is useful for verifying a message compile during a migration.

What happens when a message code is not found at runtime?

VX/MSG returns well-defined behaviour rather than failing. An unknown message code returns the standard SS$_MSGNOTFND status along with default placeholder text, so applications handle a missing message the same way they did on OpenVMS.

Transform Your Legacy Software Today!

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