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&)</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&)</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&)</code>, <code>int32_t Time(_String&)</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&)</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 &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( &len, &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 & 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&)</code>
and <code>PAS$RAB(File_t&)</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 & 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>