🚨 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

PAS$ - PASCAL Support Routines

Overview

PAS$ is a call-compatible re-implementation of the OpenVMS Pascal runtime support routines for x86 and ARM Linux. It provides the PAS$ facility entry points and the Pascal built-in support that DEC and VSI Pascal object code calls at run time, so migrated Pascal applications link and execute while preserving language semantics, value string handling, and VMS system interactions. It is the runtime the recompiled or translated Pascal links against, not the compiler and not the source translator.

The library is delivered as libvxpas and integrates with VX/RT. It unifies every Pascal string flavour into one dynamic string type so natural Pascal operators survive translation, exposes the Pascal file I/O verbs over Sector7's RMS layer, and carries the PAS$ and SYS$ service shims that OpenVMS Pascal programs depend on. Applications that link against PAS$ port directly and keep their original behaviour.

<!-- Webflow embed (min). Source: pas-page-technical/pas-tech-body-embed-dark.html → python3 website/embeds/minify_webflow_embed.py … --> <div class="s7-tech-embed" data-vxpasd-body-embed="1" data-technical-mega-embed="1" lang="en"><h2 id="architecture">Architecture and components</h2><p> On OpenVMS, <code>PAS$</code> is the facility prefix of the DEC and VSI Pascal Run-Time Library: the routines the Pascal compiler emits calls to for I/O, string handling, math built-ins, condition handling, and RMS file operations. PAS$ re-implements that runtime for Linux as a linkable C++ library so recompiled or translated Pascal links and runs unchanged. It is not a server process and there is nothing to administer. </p><p>Two layers live behind the runtime:</p><ul><li><strong>Pascal built-in support.</strong> Functions that stand in for Pascal predeclared functions and I/O verbs (<code>Present</code>, <code>Index</code>, <code>Substr</code>, <code>Hex</code>, <code>Date</code>, and the file verbs), the bulk of the library.</li><li><strong>PAS$ facility shims.</strong> The lower-level <code>pas$</code> entry points that mirror the OpenVMS <code>PAS$</code> and system-service calls (<code>pas$assign</code>, <code>pas$trnlnm</code>, <code>pas$getjpi</code>, and the rest), plus the RMS block accessors <code>PAS$FAB</code> and <code>PAS$RAB</code>.</li></ul><div class="table-wrapper"><table><thead><tr><th>OpenVMS Pascal concern</th><th>PAS$ implementation</th><th>Role</th><th>Status</th></tr></thead><tbody><tr><td>Pascal <code>STRING</code> / <code>VARYING OF CHAR</code></td><td>The <code>_String</code> dynamic string type</td><td>One value-semantic string type behind fixed and varying Pascal strings and literals.</td><td><span class="ac-live">live</span></td></tr><tr><td>String descriptors (<code>dsc$descriptor</code>)</td><td>Descriptor bridging</td><td>Converts strings to and from VMS descriptors so descriptor-based calls resolve.</td><td><span class="ac-live">live</span></td></tr><tr><td>File and RMS I/O</td><td><code>File_t</code> plus the Pascal I/O verbs</td><td>Pascal <code>Open</code>, <code>Get</code>, <code>Put</code>, <code>Read</code>, and <code>Write</code> over the RMS layer; <code>PAS$FAB</code> and <code>PAS$RAB</code> expose the RMS blocks.</td><td><span class="ac-live">live</span></td></tr><tr><td>Radix and formatting built-ins</td><td><code>Hex</code>, <code>Oct</code>, <code>Bin</code>, <code>Dec</code>, <code>Udec</code></td><td>Convert numeric values to formatted strings.</td><td><span class="ac-live">live</span></td></tr><tr><td>Date and time built-ins</td><td><code>Date</code>, <code>Fdate</code>, <code>Time</code>, <code>Ftime</code>, <code>Gettimestamp</code></td><td>Current date and time, plus binary-time formatting.</td><td><span class="ac-live">live</span></td></tr><tr><td>Math intrinsics</td><td><code>Max</code>, <code>Min</code>, <code>Mod</code>, <code>Rem</code>, <code>Sqrt</code>, <code>Fabs</code>, <code>Labs</code></td><td>Pascal predeclared math functions.</td><td><span class="ac-live">live</span></td></tr><tr><td>Argument presence (VMS stack)</td><td><code>Present</code></td><td>Reproduces VMS stack argument counting for <code>PRESENT</code> and <code>NOT PRESENT</code>.</td><td><span class="ac-live">live</span></td></tr><tr><td>Condition handling</td><td><code>Establish</code>, <code>Halt</code>, <code>Status</code>, <code>Statusv</code></td><td>Install VMS condition handlers and read run-time status.</td><td><span class="ac-live">live</span></td></tr><tr><td>Sets and membership</td><td><code>_Set</code> and membership lists</td><td>Pascal set types and set-membership tests.</td><td><span class="ac-live">live</span></td></tr><tr><td>Heap management (<code>NEW</code> / <code>DISPOSE</code>)</td><td>Allocator with optional debug tracking</td><td>Pascal heap allocation and disposal.</td><td><span class="ac-live">live</span></td></tr><tr><td><code>PAS$</code> and <code>SYS$</code> shims</td><td><code>pas$assign</code>, <code>pas$crelnm</code>, <code>pas$trnlnm</code>, and others</td><td>System-service call shims the Pascal RTL depends on.</td><td><span class="ac-live">live</span></td></tr></tbody></table></div><div class="callout"><strong>No daemon to run.</strong> PAS$ is delivered as the linkable <code>libvxpas</code> library. The migrated application links it directly, so there is no separate runtime service to install or manage on the Linux host. </div><h6>Where PAS$ sits at link time</h6><p> Translated Pascal object code links against <code>libvxpas</code>, which provides the string type, the file runtime, the built-ins, and the service shims. File and record work is delegated to the RMS layer, and the system-service shims resolve against VX/RT: </p><style>.s7-tech-embed .pas-runtime-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 .pas-card {min-width: 0;padding: 14px 16px;border-radius: 8px;background: var(--s7t-surface);color: var(--s7t-text);}.s7-tech-embed .pas-card strong,.s7-tech-embed .pas-card span:last-child {display: block;}.s7-tech-embed .pas-card strong {margin-bottom: 4px;}.s7-tech-embed .pas-card span:last-child {color: var(--s7t-muted);font-size: 0.9em;line-height: 1.45;}.s7-tech-embed .pas-label,.s7-tech-embed .pas-connector {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 .pas-label {margin-bottom: 8px;}.s7-tech-embed .pas-connector {padding: 10px;text-align: center;}.s7-tech-embed .pas-runtime {border: 1px solid var(--s7t-note-bd);background: var(--s7t-note-bg);}.s7-tech-embed .pas-fanout {display: grid;grid-template-columns: repeat(4, minmax(0, 1fr));gap: 10px;}.s7-tech-embed .pas-branch {border-top: 3px solid var(--s7t-accent);background: var(--s7t-surface2);}.s7-tech-embed .pas-delegate {margin-top: 10px;padding-top: 10px;border-top: 1px solid var(--s7t-border);}.s7-tech-embed .pas-delegate .pas-label {display: block;margin-bottom: 4px;}@media (max-width: 800px) {.s7-tech-embed .pas-fanout {grid-template-columns: 1fr;}}</style><div class="pas-runtime-flow" aria-label="Translated Pascal links to the PAS runtime and fans out to runtime services"><div class="pas-card"><span class="pas-label">Input</span><strong>Translated Pascal C++</strong><span>Application object code ready to link</span></div><div class="pas-connector">Links to</div><div class="pas-card pas-runtime"><span class="pas-label">Runtime</span><strong><code>libvxpas</code> (PAS$ runtime)</strong><span>Provides Pascal-compatible language and platform services.</span></div><div class="pas-connector">Runtime fan-out</div><div class="pas-fanout"><div class="pas-card pas-branch"><strong><code>_String</code></strong><span>Value-semantic strings</span></div><div class="pas-card pas-branch"><strong><code>File_t</code> and Pascal I/O verbs</strong><span>File and record operations</span><div class="pas-delegate"><span class="pas-label">Delegates to</span><strong>VX/RMS layer</strong></div></div><div class="pas-card pas-branch"><strong>Built-ins</strong><span><code>Present</code>, <code>Hex</code>, <code>Date</code>, <code>Max</code>, and others</span></div><div class="pas-card pas-branch"><strong>PAS$ / SYS$ service shims</strong><span>Compatible system-service entry points</span><div class="pas-delegate"><span class="pas-label">Resolves against</span><strong>VX/RT runtime</strong></div></div></div></div><h2 id="strings">The _String runtime type</h2><p> The heart of PAS$ string handling is a single dynamic string type, <code>_String</code>, onto which the translator maps every Pascal string flavour: fixed <code>PACKED ARRAY OF CHAR</code>, <code>VARYING [n] OF CHAR</code>, and string literals. It carries both a fixed and a varying organisation with a discriminator for which is live, plus declared lower and upper bounds, and a flag for whether it owns its buffer or is a view over caller memory. That design lets emitted C++ keep Pascal value semantics and Pascal's natural operators. </p><h6>Operator surface</h6><p><code>_String</code> overloads the operators Pascal code relies on, so the translated C++ reads almost the same as the source: </p><div class="table-wrapper"><table><thead><tr><th>Group</th><th>Operators</th><th>Purpose</th></tr></thead><tbody><tr><td>Concatenate</td><td><code>operator+</code> (string, char, and <code>const char*</code> forms)</td><td>Join strings with the same <code>+</code> Pascal uses.</td></tr><tr><td>Append</td><td><code>operator+=</code></td><td>Append a char, C string, or another string in place.</td></tr><tr><td>Assign</td><td><code>operator=</code></td><td>Assign from a char, C string, string, or array with a value copy.</td></tr><tr><td>Compare</td><td><code>operator==</code> / <code>operator!=</code></td><td>Value comparison against chars, C strings, and strings.</td></tr><tr><td>Index</td><td><code>operator[]</code></td><td>Read or write a single character by position.</td></tr><tr><td>Test</td><td><code>operator!</code> / <code>operator bool</code></td><td>Empty or non-empty tests.</td></tr><tr><td>Descriptor bridging</td><td><code>operator DXX*</code>, <code>operator const char*</code></td><td>Pass a string where a VMS descriptor or C string is expected.</td></tr></tbody></table></div><p> Member helpers cover the common Pascal string operations: <code>substr</code>, <code>subset</code>, <code>pad</code>, length, and reference counting, alongside free helpers such as <code>Length</code>, <code>Substr</code>, <code>Present</code>, and the <code>Pas_str</code> constructor macro that backs the <code>PAS_STR</code> built-in. </p><h6>Why it matters for migration</h6><p> Because <code>_String</code> preserves <code>+</code> concatenation, string logic reads the same after migration. Where a Pascal statement concatenates with <code>+</code>, the emitted C++ keeps <code>+</code> rather than falling back to descriptor juggling or explicit copy routines: </p> <pre><span class="cmt">{ Pascal source }</span> A := Me + <span class="str">'You'</span> + Them; <span class="cmt">/* emitted C++ (unchanged operator, value semantics preserved) */</span> A = Me + <span class="str">"You"</span> + Them;</pre> <p> The same technique is applied throughout the runtime, so migrated code that builds, compares, and slices strings keeps its original shape and behaviour without manual rewriting. </p><h2 id="builtins">Intrinsic runtime routines</h2><p> PAS$ provides the Pascal predeclared functions and I/O helpers the compiler emits calls to. Each is a call-compatible entry point, so translated code invokes them exactly as the original Pascal did. The table lists the most commonly used routines and their behaviour. </p><div class="table-wrapper"><table><thead><tr><th>Routine</th><th>Signature (as declared)</th><th>Purpose</th><th>Status</th></tr></thead><tbody><tr><td><code>Present</code></td><td><code>bool Present(const T&amp;)</code></td><td>VMS argument-presence test; safe on a null reference, returning false when an argument was not passed.</td><td><span class="ac-live">live</span></td></tr><tr><td><code>Index</code></td><td><code>int32_t Index(_String, _String)</code></td><td>Substring position; returns 0 when not found and -1 for a null pattern.</td><td><span class="ac-live">live</span></td></tr><tr><td><code>Substr</code></td><td><code>_String Substr(_String, int32_t start, int32_t size)</code></td><td>Substring extraction.</td><td><span class="ac-live">live</span></td></tr><tr><td><code>Pad</code></td><td><code>_String Pad(_String, char fill, uint32_t size)</code></td><td>Blank or character pad to a length.</td><td><span class="ac-live">live</span></td></tr><tr><td><code>Length</code></td><td><code>uint32_t Length(const _String&amp;)</code></td><td>String length.</td><td><span class="ac-live">live</span></td></tr><tr><td><code>Hex</code> / <code>Oct</code> / <code>Bin</code></td><td><code>_String Hex(int64_t, int32_t length, int32_t min_digits)</code></td><td>Radix conversion of a numeric value to a formatted string.</td><td><span class="ac-live">live</span></td></tr><tr><td><code>Dec</code> / <code>Udec</code></td><td><code>_String Dec(int64_t, int32_t, int32_t)</code></td><td>Signed and unsigned decimal conversion to string.</td><td><span class="ac-live">live</span></td></tr><tr><td><code>Chr</code> / <code>Ord</code></td><td><code>_String Chr(int32_t)</code>, <code>int32_t Ord(int32_t)</code></td><td>Ordinal to character and character to ordinal.</td><td><span class="ac-live">live</span></td></tr><tr><td><code>Date</code> / <code>Time</code></td><td><code>int32_t Date(_String&amp;)</code>, <code>int32_t Time(_String&amp;)</code></td><td>Current date and time text.</td><td><span class="ac-live">live</span></td></tr><tr><td><code>Fdate</code> / <code>Ftime</code></td><td><code>_String Fdate(Time_t)</code>, <code>_String Ftime(Time_t)</code></td><td>Format a binary time value to text.</td><td><span class="ac-live">live</span></td></tr><tr><td><code>Max</code> / <code>Min</code></td><td><code>double Max(uint32_t nargs, ...)</code></td><td>Variadic maximum and minimum.</td><td><span class="ac-live">live</span></td></tr><tr><td><code>Mod</code> / <code>Rem</code></td><td><code>uint32_t Mod(int32_t, int32_t)</code></td><td>Modulo and remainder.</td><td><span class="ac-live">live</span></td></tr><tr><td><code>Sqrt</code> / <code>Fabs</code> / <code>Labs</code></td><td><code>double Sqrt(double)</code></td><td>Square root and absolute value.</td><td><span class="ac-live">live</span></td></tr><tr><td><code>Status</code> / <code>Statusv</code></td><td><code>int32_t Status(File_t&amp;)</code></td><td>File status code and global status value.</td><td><span class="ac-live">live</span></td></tr><tr><td><code>Halt</code> / <code>Establish</code></td><td><code>void Halt()</code></td><td>Terminate the program, or install a VMS condition handler.</td><td><span class="ac-live">live</span></td></tr></tbody></table></div><h6>A built-in end to end</h6><p> Every intrinsic follows the same pattern: set up a VMS-style descriptor, call the runtime's system-service implementation, and marshal the result into a <code>_String</code>. The <code>Date</code> built-in shows the shape, including the OpenVMS status convention where the low bit of the return value marks success: </p> <pre>extern <span class="str">"C"</span> uint32_t SYS_D_ASCTIM(U16 *, void *, void *pqtime, uint32_t flag); int32_t Date( _String &amp;v ) { char buffer[64]; <span class="cmt">// buffer to hold the date string</span> $DESCRIPTOR64( d, buffer ); <span class="cmt">// VMS-style descriptor for the buffer</span> int32_t rc; U16 len = 0; rc = SYS_D_ASCTIM( &amp;len, &amp;d ); <span class="cmt">// system call fills the buffer</span> buffer[len] = 0; <span class="cmt">// null-terminate</span> v = buffer; <span class="cmt">// _String::operator= copies it in</span> return rc; <span class="cmt">// VMS status (bit 0 = success)</span> }</pre> <p> Two migration-relevant details are visible here. The <code>rc &amp; 1</code> style success test is the OpenVMS convention preserved verbatim, and assigning a C string into a <code>_String</code> uses the value-copy assignment operator so the result keeps Pascal string semantics. </p><h6>Pascal built-ins provided</h6><div class="kw-grid"><div>ABS</div><div>ADDRESS</div><div>ARCTAN</div><div>ASSERT</div><div>BIN</div><div>CHR</div><div>COS</div><div>DATE</div><div>DEC</div><div>DISPOSE</div><div>EOF</div><div>EOLN</div><div>EXP</div><div>HALT</div><div>HEX</div><div>INDEX</div><div>LENGTH</div><div>LOWER</div><div>MALLOC</div><div>MAX</div><div>MIN</div><div>NEW</div><div>OCT</div><div>ODD</div><div>ORD</div><div>PAD</div><div>PAS_STR</div><div>PRED</div><div>PRESENT</div><div>ROUND</div><div>SIN</div><div>SIZE</div><div>SQRT</div><div>STATUS</div><div>SUBSTR</div><div>SUCC</div><div>TIME</div><div>TRUNC</div><div>UDEC</div><div>UPPER</div></div><h2 id="file-io">File I/O and RMS support</h2><p> PAS$ implements the Pascal file I/O verbs over Sector7's RMS layer through a <code>File_t</code> object per open file. All RMS file organizations, record formats, and access modes from VMS Pascal are supported, so record-oriented programs keep their file semantics on Linux. Each verb accepts an error-processing option and defaults to continuing, matching the Pascal runtime. </p><div class="table-wrapper"><table><thead><tr><th>Verb</th><th>Role</th><th>Status</th></tr></thead><tbody><tr><td><code>Open</code> / <code>Fclose</code></td><td>Open and close a file, building the RMS control blocks.</td><td><span class="ac-live">live</span></td></tr><tr><td><code>Get</code> / <code>Put</code></td><td>Read the current record, or write the record buffer.</td><td><span class="ac-live">live</span></td></tr><tr><td><code>Read</code> / <code>Readv</code></td><td>Record read, including the formatted-read helper.</td><td><span class="ac-live">live</span></td></tr><tr><td><code>Write</code></td><td>Record write, including formatted write.</td><td><span class="ac-live">live</span></td></tr><tr><td><code>Update</code></td><td>Update a record in place.</td><td><span class="ac-live">live</span></td></tr><tr><td><code>Reset</code> / <code>Resetk</code></td><td>Reposition to the start, or reset by key for keyed access.</td><td><span class="ac-live">live</span></td></tr><tr><td><code>Rewrite</code> / <code>Find</code></td><td>Rewrite the file, or locate a record without reading it.</td><td><span class="ac-live">live</span></td></tr><tr><td><code>Extend</code> / <code>Truncate</code></td><td>Extend or truncate the file.</td><td><span class="ac-live">live</span></td></tr><tr><td><code>Delete_file</code> / <code>Create_directory</code></td><td>Delete a file, or create a directory.</td><td><span class="ac-live">live</span></td></tr><tr><td><code>Eof</code> / <code>Eoln</code></td><td>End-of-file and end-of-line tests.</td><td><span class="ac-live">live</span></td></tr></tbody></table></div><h6>The file option model</h6><p> File behaviour is driven by an option model. Each family is a distinct set of values, and the families that carry the RMS claims map directly onto OpenVMS RMS concepts: </p><div class="table-wrapper"><table><thead><tr><th>Option family</th><th>Members</th><th>Covers</th></tr></thead><tbody><tr><td>Organization</td><td><code>SEQUENTIAL</code>, <code>RELATIVE</code>, <code>INDEXED</code></td><td>RMS file organizations.</td></tr><tr><td>Record type</td><td><code>FIXED</code>, <code>VARIABLE</code>, stream forms</td><td>RMS record formats.</td></tr><tr><td>Access method</td><td><code>SEQUENTIAL</code>, <code>DIRECT</code>, <code>KEYED</code></td><td>RMS access modes.</td></tr><tr><td>History</td><td>new, readonly, old, unknown</td><td>Open disposition on existing files.</td></tr><tr><td>Sharing</td><td>none, readonly, readwrite</td><td>File sharing mode.</td></tr><tr><td>Disposition</td><td>save, delete, print, submit</td><td>Close-time disposition, including print and submit.</td></tr><tr><td>Carriage control</td><td>none, list, carriage, fortran</td><td>Carriage-control handling on output.</td></tr></tbody></table></div><h6>RMS block access</h6><div class="callout"><strong>PAS$FAB and PAS$RAB.</strong> The uppercase accessors <code>PAS$FAB(File_t&amp;)</code> and <code>PAS$RAB(File_t&amp;)</code> return pointers to the File Access Block and Record Access Block for an open file. This is the seam that lets migrated code which poked FAB or RAB fields directly keep working against the RMS layer. </div><h6>Real call path (banking example)</h6><p> A migrated Pascal program opens a keyed account file and reads a record by key. The file option values and I/O verbs are the same ones the original ran on OpenVMS: </p> <pre><span class="cmt">{ open an indexed account master for keyed access }</span> Open( ACCOUNT_FILE, FILE_NAME := <span class="str">'BANKING$DATA:ACCOUNT_MASTER.DAT'</span>, ORGANIZATION := INDEXED, ACCESS_METHOD := KEYED, HISTORY := OLD ); <span class="cmt">{ position by customer id, then read the record buffer }</span> Resetk( ACCOUNT_FILE, KEY := 0, RELATION := EQL, KEY_VALUE := CUST_ID ); Get( ACCOUNT_FILE ); ACCT_RECORD := ACCOUNT_FILE^; <span class="cmt">{ ... update fields, then write the record back in place ... }</span> ACCOUNT_FILE^ := ACCT_RECORD; Update( ACCOUNT_FILE ); Fclose( ACCOUNT_FILE );</pre> <h2 id="shims">PAS$ and SYS$ service shims</h2><p> Some routines carry the literal <code>PAS$</code> facility name on OpenVMS: the shims the Pascal RTL uses to reach system services. PAS$ declares these with C linkage and the VMS-style return convention, where the low bit of the returned condition value marks success. Each maps onto a familiar OpenVMS system service or library routine. </p><div class="table-wrapper"><table><thead><tr><th>Routine</th><th>OpenVMS analogue</th><th>Purpose</th></tr></thead><tbody><tr><td><code>pas$assign</code></td><td><code>SYS$ASSIGN</code></td><td>Assign an I/O channel to a device or mailbox.</td></tr><tr><td><code>pas$crelnm</code></td><td><code>SYS$CRELNM</code></td><td>Create a logical name.</td></tr><tr><td><code>pas$dellnm</code></td><td><code>SYS$DELLNM</code></td><td>Delete a logical name.</td></tr><tr><td><code>pas$trnlnm</code></td><td><code>SYS$TRNLNM</code></td><td>Translate a logical name.</td></tr><tr><td><code>pas$getjpi</code> / <code>pas$getjpiw</code></td><td><code>SYS$GETJPI</code> / <code>SYS$GETJPIW</code></td><td>Get job and process information.</td></tr><tr><td><code>pas$setprv</code></td><td><code>SYS$SETPRV</code></td><td>Set process privileges.</td></tr><tr><td><code>pas$sndjbc</code> / <code>pas$sndjbcw</code></td><td><code>SYS$SNDJBC</code> / <code>SYS$SNDJBCW</code></td><td>Send a request to the job controller.</td></tr><tr><td><code>pas$cvt_vectim</code></td><td><code>LIB$CVT_VECTIM</code></td><td>Convert a seven-word time vector to a binary time.</td></tr><tr><td><code>pas$set_logical</code></td><td><code>LIB$SET_LOGICAL</code></td><td>Set a logical name from Pascal.</td></tr></tbody></table></div><div class="callout"><strong>Return convention preserved.</strong> These shims return a VMS condition value by value, so migrated code that tests the low bit of the status (success when odd) behaves the same on Linux as it did on OpenVMS. </div><h2 id="compatibility">Compatibility and divergences</h2><p> PAS$ is built to let OpenVMS Pascal applications run on Linux without source changes. A few behaviours differ from the original VMS runtime by design, because the host platform differs. Each divergence keeps application-visible behaviour intact while adapting to Linux. </p><div class="table-wrapper"><table><thead><tr><th>Divergence</th><th>Reason</th></tr></thead><tbody><tr><td>The runtime is a linkable C++ library (<code>libvxpas</code>) rather than a shareable image such as <code>PASRTL.EXE</code>.</td><td>The host is Linux, which has no VMS image activator.</td></tr><tr><td>System services are re-implemented as <code>SYS_</code> and <code>pas$</code> functions that call the VX/RT runtime.</td><td>There is no VMS executive on Linux, so each service is provided by the Sector7 runtime.</td></tr><tr><td>Every Pascal string flavour is unified into one <code>_String</code> type with an organisation discriminator.</td><td>C++ has no native <code>VARYING OF CHAR</code>; one type keeps value semantics and <code>+</code> concatenation.</td></tr><tr><td>The VMS success test is kept as <code>status &amp; 1</code> in emitted code.</td><td>This preserves the behaviour of code that inspects RTL status directly.</td></tr><tr><td><code>Present</code> returns false on a null reference.</td><td>Linux has no VMS register argument-count, so a not-passed argument is emulated this way.</td></tr><tr><td>Optional C-string caching and standard-library string interop are off by default.</td><td>Defaults match the VMS memory layout; the extra behaviours are opt-in at build time.</td></tr></tbody></table></div><div class="callout"><strong>Integrates with VX/RT.</strong> PAS$ works alongside the rest of the OpenVMS run-time services on Linux, so a Pascal application picks up string handling, file I/O, built-ins, and service shims together with the wider VX/RT surface. </div><h2 id="quickref">Quick reference</h2><h6>Library and core types</h6><div class="table-wrapper"><table><thead><tr><th>Item</th><th>Value</th></tr></thead><tbody><tr><td>Library</td><td><code>libvxpas</code>, linked directly into the migrated Pascal application.</td></tr><tr><td>Core string type</td><td><code>_String</code> (dynamic Pascal string with value semantics).</td></tr><tr><td>File object</td><td><code>File_t</code>, one per open file over the RMS layer.</td></tr><tr><td>Descriptors</td><td>VMS string descriptor bridging to and from <code>_String</code>.</td></tr><tr><td>Sets</td><td><code>_Set</code> and membership lists.</td></tr><tr><td>Delivered with</td><td>VX/RT run-time services on Linux.</td></tr><tr><td>Target platforms</td><td>x86 and ARM Linux.</td></tr></tbody></table></div><h6>Built-ins</h6><div class="kw-grid"><div>Present</div><div>Index</div><div>Substr</div><div>Pad</div><div>Length</div><div>Hex</div><div>Oct</div><div>Bin</div><div>Dec</div><div>Udec</div><div>Chr</div><div>Ord</div><div>Date</div><div>Fdate</div><div>Time</div><div>Ftime</div><div>Gettimestamp</div><div>Max</div><div>Min</div><div>Mod</div><div>Rem</div><div>Sqrt</div><div>Fabs</div><div>Labs</div><div>Eof</div><div>Eoln</div><div>Status</div><div>Statusv</div><div>Halt</div><div>Establish</div></div><h6>File I/O verbs</h6><div class="kw-grid"><div>Open</div><div>Fclose</div><div>Get</div><div>Put</div><div>Read</div><div>Readv</div><div>Write</div><div>Update</div><div>Reset</div><div>Resetk</div><div>Rewrite</div><div>Find</div><div>Extend</div><div>Truncate</div><div>Delete_file</div><div>Create_directory</div></div><h6>RMS file model</h6><div class="table-wrapper"><table><thead><tr><th>Family</th><th>Members</th></tr></thead><tbody><tr><td>Organization</td><td>sequential, relative, indexed</td></tr><tr><td>Record type</td><td>fixed, variable, stream</td></tr><tr><td>Access method</td><td>sequential, direct, keyed</td></tr></tbody></table></div><h6>PAS$ and SYS$ shims</h6><div class="kw-grid"><div>pas$assign</div><div>pas$crelnm</div><div>pas$dellnm</div><div>pas$trnlnm</div><div>pas$getjpi</div><div>pas$getjpiw</div><div>pas$setprv</div><div>pas$sndjbc</div><div>pas$sndjbcw</div><div>pas$cvt_vectim</div><div>pas$set_logical</div><div>PAS$FAB</div><div>PAS$RAB</div></div></div>

Frequently Asked Questions

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

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

VX/PASCAL is an automated transpiler that converts OpenVMS Pascal to ANSI-compliant C++ for execution on Linux. It fully supports VMS-specific extensions, CDD data structures, and RMS file handling ensuring 100% compatibility. To explore VX/PASCAL for your migration, contact us.

What specific VMS Pascal features does VX/PASCAL support during conversion?

VX/PASCAL supports VMS stack operations, Common Data Dictionary (CDD) integration, RMS file handling, VMS API mapping, and optimized string operations using STR$CONCAT and STR$COPY.

How does the VX/PASCAL migration process work technically?

VX/PASCAL automates migration in four steps: source code analysis, transpile to C++, compile with GNU C++, and validate with automated testing to ensure identical behavior.

Can you continue developing Pascal code while using VX/PASCAL for migration?

Yes, VX/PASCAL allows continuous development without code freeze. Teams can continue enhancing VMS Pascal applications while changes remain synchronized between Pascal and C++ versions.

What customization options are available in VX/PASCAL?

VX/PASCAL provides 500+ customizable options including VMS API mapping, variable naming conventions, code formatting, and error code translation to meet enterprise standards.

How does VX/PASCAL handle VMS stack argument tracking on Linux?

VX/PASCAL automatically handles VMS stack argument tracking (PRESENT/NOT PRESENT) that Linux doesn't support, preventing stack corruption by generating equivalent C++ code that maintains identical behavior.

What are the key benefits and proven results of using VX/PASCAL?

VX/PASCAL has successfully translated over 3 million lines of Pascal code with 100% automation, bug-for-bug compatibility, and zero code freeze. Organizations eliminate vendor lock-in and reduce infrastructure costs. Contact us to discuss your requirements.

What makes VX/PASCAL different from other migration tools?

VX/PASCAL converts OpenVMS PASCAL to beautiful, maintainable C++ code, allowing programs to compile, link, and run on Linux with no manual intervention. Our PASCAL Process Control bundle ensures complete functionality preservation.

What is PAS$?

PAS$ is Sector7's call-compatible re-implementation of the OpenVMS Pascal runtime support routines for x86 and ARM Linux. It provides the PAS$ entry points and Pascal built-in support that DEC and VSI Pascal object code calls at run time, delivered as the libvxpas library. It is the runtime your migrated Pascal links against, not the compiler and not the source translator.

Do I have to rewrite my Pascal application to use PAS$?

No. PAS$ is call-compatible, so recompiled or translated Pascal links against it and runs without source changes. Pascal string handling, file I/O, built-in functions, and VMS system-service calls keep their original behaviour on Linux.

How does PAS$ relate to VX/PASCAL and VX/RT?

VX/PASCAL translates OpenVMS Pascal source to C++. PAS$ is the runtime library that the translated code links against so it behaves as it did on OpenVMS. PAS$ integrates with VX/RT, so a Pascal application picks up the runtime support routines alongside the wider OpenVMS runtime services on Linux.

How does PAS$ handle Pascal string handling in C++?

PAS$ unifies every Pascal string flavour into one dynamic string type that preserves value semantics and operators. A Pascal concatenation written with + stays a + in the emitted C++, so string logic reads the same after migration and does not need manual rewriting.

Which file and RMS operations does PAS$ support?

PAS$ implements the Pascal file I/O verbs over Sector7's RMS layer. It supports the RMS file organizations (sequential, relative, indexed), record formats (fixed, variable, stream), and access methods (sequential, direct, keyed), and exposes the RMS File and Record Access Blocks through PAS$FAB and PAS$RAB.

Does PAS$ support the VMS PRESENT and NOT PRESENT keywords on Linux?

Yes. VMS argument presence relies on stack argument counting, which Linux does not provide natively. PAS$ reproduces this through its Present routine, which returns false when an argument was not passed, so code that checks PRESENT and NOT PRESENT behaves the same on Linux.

Which VMS system services can Pascal code still call through PAS$?

PAS$ carries the PAS$ facility shims that mirror common OpenVMS system services and library routines, including channel assignment, logical name creation and translation, process information, privilege setting, and job controller requests. They keep the VMS status return convention, so existing status checks continue to work.

Which platforms does PAS$ run on?

PAS$ runs on x86 and ARM Linux and is delivered as the libvxpas runtime library alongside VX/RT.

Transform Your Legacy Software Today!

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