Bladeren bron

v3 step 7.1 — self-hosted syslib: SysShim + FileIO (103/103 tests green)

Eric Streit 2 weken geleden
bovenliggende
commit
7e76697b00

+ 1 - 0
compiler/run_tests.sh

@@ -210,6 +210,7 @@ expect_run_files DBasicProg 49 d_basic.def d_basic.mod d_basic_prog.mod
 expect_run_files DQualProg 46 d_basic.def d_basic.mod d_qual_prog.mod
 expect_run_files DTypesProg 36 d_types.def d_types.mod d_types_prog.mod
 expect_run_files DOpaqueProg 55 d_opaque.def d_opaque.mod d_opaque_prog.mod
+expect_run_files FioProg 42 ../runtime/syslib/SysShim.def ../runtime/syslib/SysShim.mod ../runtime/syslib/FileIO.def ../runtime/syslib/FileIO.mod fio_prog.mod
 expect_run_files StorageProg 42 ../stdlib/storage.def ../stdlib/storage.mod storage_prog.mod
 expect_run_files ClashProg 60 d_clash_a.def d_clash_a.mod d_clash_b.def d_clash_b.mod d_clash_prog.mod
 expect_run_files_out Hello 0 "Hello, Modula-2!" ../stdlib/sysio.def ../stdlib/sysio.mod hello.mod

+ 21 - 0
compiler/tests/fio_prog.mod

@@ -0,0 +1,21 @@
+MODULE FioProg;
+(* Self-hosted FileIO (runtime/syslib): write, read back, verify. *)
+IMPORT FileIO;
+FROM SYSTEM IMPORT ADDRESS;
+VAR ExitCode : INTEGER;
+VAR f : ADDRESS;
+VAR buf : ARRAY [0..31] OF CHAR;
+VAR n : CARDINAL;
+BEGIN
+  FileIO.Open(f, "gen_ssa/_fio_tmp.txt", TRUE);
+  FileIO.WriteString(f, "hello");
+  FileIO.WriteLn(f);
+  FileIO.Close(f);
+
+  FileIO.Open(f, "gen_ssa/_fio_tmp.txt", FALSE);
+  n := LEN(buf);
+  FileIO.ReadBytes(f, buf, n);
+  FileIO.Close(f);
+
+  IF (buf[0] = 'h') AND (n = 6) THEN ExitCode := n * 7 ELSE ExitCode := 0 END
+END FioProg.

+ 49 - 0
docs/summary_step7.1.md

@@ -0,0 +1,49 @@
+# V3 step 7.1 — self-hosted syslib: SysShim + FileIO (done 2026-09-22)
+
+Follows the step-7 analysis. Rather than force one `FileIO` under
+two ABIs (host gm2 NUL-terminated strings vs V3 length-prefixed
+descriptors), this lands the **self-hosted syslib** the stage-2
+compiler will link: `runtime/syslib/SysShim` + `runtime/syslib/FileIO`
+— V3-only, descriptor-aware, over the existing C shim. Suite 103/103.
+
+## `runtime/syslib/SysShim`
+
+Descriptor-aware externals over `shim.c`: `fopenread`/`fopenwrite`
+(→ ADDRESS), `fclose`, `fread` (bulk, sets the buffer's length),
+`fputc`, `fputs`, `fwriteln`, `fwriteintw`, `stdout`/`stderr`
+(→ ADDRESS), `arg` (argv via `/proc/self/cmdline`). Statement-like
+operations are proper procedures (V3's 233 forbids
+function-as-statement); value-returning ones are functions.
+
+## `runtime/syslib/FileIO`
+
+The compiler's FileIO subset, reimplemented over `SysShim` only:
+`File` = `ADDRESS`; `Open`/`Close`/`ReadBytes`/`Write`/`WriteLn`/
+`WriteString`/`WriteInt`/`WriteCard`/`NextParameter`, plus
+`SLENGTH`/`Assign`/`Extract`/`Concat`/`Compare` and the classic
+constants. This is the stage-2 counterpart of the host `FileIO`
+used to bootstrap; the stage-1 gm2 build keeps the host library
+(the standard bootstrap split, as Blaise does with FPC).
+
+## Test
+
+`FioProg` → 42: writes `"hello\n"` via the self-hosted FileIO, opens
+it for read, `ReadBytes` (which sets the buffer's length), and checks
+`buf[0] = 'h'` and length 6. Harness links `shim.c`.
+
+## Stage-2 port items found (Redux / ABI)
+
+Compiling the compiler's own sources with V3 will also need:
+- Redux cleanups in those sources: `0C`/`15C`/`177C` octal char-code
+  literals → `CHR(n)` (V3 has no `C` suffix), and `&`/`~`/`<>` →
+  `AND`/`NOT`/`#`.
+- A `DEFINITION MODULE FOR "C"` + `EXPORT UNQUALIFIED` V3 dialect
+  only if a single FFI definition must also compile under gm2
+  (not needed for the current split).
+
+## Files
+
+`runtime/syslib/SysShim.def|.mod`, `runtime/syslib/FileIO.def|.mod`,
+`compiler/tests/fio_prog.mod`, `compiler/run_tests.sh`.
+Step 7 remains "in progress": the compiler-source Redux sweep and
+the `FileIO` selection between stages are the remaining tasks.

+ 137 - 0
runtime/syslib/FileIO.LST

@@ -0,0 +1,137 @@
+Listing:
+
+    1  IMPLEMENTATION MODULE FileIO;
+    2  (* Self-hosted file I/O: SysShim only. *)
+    3  
+    4  IMPORT SysShim;
+    5  
+    6  VAR
+    7    argIdx: CARDINAL;
+    8  
+    9  PROCEDURE NextParameter (VAR s: ARRAY OF CHAR);
+   10  BEGIN
+   11    IF SysShim.arg(argIdx, s, LEN(s)) THEN
+   12      INC(argIdx)
+   13    ELSE
+   14      s[0] := CHR(0)
+   15    END
+   16  END NextParameter;
+   17  
+   18  PROCEDURE Open (VAR f: File; fileName: ARRAY OF CHAR; newFile: BOOLEAN);
+   19  BEGIN
+   20    IF newFile THEN f := SysShim.fopenwrite(fileName)
+   21    ELSE f := SysShim.fopenread(fileName)
+   22    END;
+   23    Okay := f # NIL
+   24  END Open;
+   25  
+   26  PROCEDURE Close (VAR f: File);
+   27  BEGIN
+   28    SysShim.fclose(f);
+   29    f := NIL
+   30  END Close;
+   31  
+   32  PROCEDURE ReadBytes (f: File; VAR buf: ARRAY OF CHAR; VAR len: CARDINAL);
+   33  BEGIN
+   34    len := SysShim.fread(f, buf, len)
+   35  END ReadBytes;
+   36  
+   37  PROCEDURE Write (f: File; ch: CHAR);
+   38  BEGIN
+   39    IF ch = EOL THEN SysShim.fwriteln(f) ELSE SysShim.fputc(f, ch) END
+   40  END Write;
+   41  
+   42  PROCEDURE WriteLn (f: File);
+   43  BEGIN
+   44    SysShim.fwriteln(f)
+   45  END WriteLn;
+   46  
+   47  PROCEDURE WriteString (f: File; str: ARRAY OF CHAR);
+   48  BEGIN
+   49    SysShim.fputs(f, str)
+   50  END WriteString;
+   51  
+   52  PROCEDURE WriteInt (f: File; int: INTEGER; wid: CARDINAL);
+   53  BEGIN
+   54    SysShim.fwriteintw(f, int, wid)
+   55  END WriteInt;
+   56  
+   57  PROCEDURE WriteCard (f: File; card, wid: CARDINAL);
+   58  BEGIN
+   59    SysShim.fwriteintw(f, card, wid)
+   60  END WriteCard;
+   61  
+   62  PROCEDURE SLENGTH (stringVal: ARRAY OF CHAR): CARDINAL;
+   63  BEGIN
+   64    RETURN LEN(stringVal)
+   65  END SLENGTH;
+   66  
+   67  PROCEDURE Assign (source: ARRAY OF CHAR; VAR destination: ARRAY OF CHAR);
+   68    VAR i, n: CARDINAL;
+   69  BEGIN
+   70    n := LEN(source);
+   71    IF n > LEN(destination) THEN n := LEN(destination) END;
+   72    i := 0;
+   73    WHILE i < n DO
+   74      destination[i] := source[i];
+   75      INC(i)
+   76    END
+   77  END Assign;
+   78  
+   79  PROCEDURE Extract (source: ARRAY OF CHAR;
+   80                     startIndex, numberToExtract: CARDINAL;
+   81                     VAR destination: ARRAY OF CHAR);
+   82    VAR i, n, k: CARDINAL;
+   83  BEGIN
+   84    n := LEN(source);
+   85    k := 0;
+   86    i := startIndex;
+   87    WHILE (i < n) AND (k < numberToExtract) AND (k < LEN(destination)) DO
+   88      destination[k] := source[i];
+   89      INC(k); INC(i)
+   90    END
+   91  END Extract;
+   92  
+   93  PROCEDURE Concat (stringVal1, stringVal2: ARRAY OF CHAR;
+   94                    VAR destination: ARRAY OF CHAR);
+   95    VAR i, k: CARDINAL;
+   96  BEGIN
+   97    k := 0; i := 0;
+   98    WHILE (i < LEN(stringVal1)) AND (k < LEN(destination)) DO
+   99      destination[k] := stringVal1[i]; INC(k); INC(i)
+  100    END;
+  101    i := 0;
+  102    WHILE (i < LEN(stringVal2)) AND (k < LEN(destination)) DO
+  103      destination[k] := stringVal2[i]; INC(k); INC(i)
+  104    END
+  105  END Concat;
+  106  
+  107  PROCEDURE Compare (stringVal1, stringVal2: ARRAY OF CHAR): INTEGER;
+  108    VAR i, n, m: CARDINAL;
+  109  BEGIN
+  110    n := LEN(stringVal1); m := LEN(stringVal2);
+  111    i := 0;
+  112    WHILE (i < n) AND (i < m) DO
+  113      IF stringVal1[i] < stringVal2[i] THEN RETURN -1
+  114      ELSIF stringVal1[i] > stringVal2[i] THEN RETURN 1
+  115      END;
+  116      INC(i)
+  117    END;
+  118    IF n < m THEN RETURN -1
+  119    ELSIF n > m THEN RETURN 1
+  120    END;
+  121    RETURN 0
+  122  END Compare;
+  123  
+  124  BEGIN
+  125    argIdx := 0;
+  126    Okay := TRUE;
+  127    StdOut := SysShim.stdout();
+  128    con := StdOut;
+  129    StdIn := NIL;
+  130    err := SysShim.stderr()
+  131  END FileIO.
+
+    0 errors
+
+

+ 52 - 0
runtime/syslib/FileIO.def

@@ -0,0 +1,52 @@
+DEFINITION MODULE FileIO;
+(* Self-hosted V3 FileIO over the runtime shim (SysShim). Provides
+   the subset used by the Coco/R-generated scanner/parser/driver,
+   plus the classic string helpers. Stage-2 counterpart of the
+   host-supplied FileIO used to bootstrap. *)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+TYPE
+  File = ADDRESS;
+  INT32 = INTEGER;
+
+CONST
+  EOF = CHR(0);
+  EOL = CHR(10);
+  ESC = CHR(27);
+  CR  = CHR(13);
+  LF  = CHR(10);
+  BS  = CHR(8);
+  DEL = CHR(127);
+  BitSetSize = 16;
+  Long0 = 0;
+  Long1 = 1;
+  Long2 = 2;
+  PathSep = ":";
+  DirSep  = "/";
+
+VAR
+  Okay: BOOLEAN;
+  con, err: File;
+  StdIn, StdOut: File;
+
+PROCEDURE NextParameter (VAR s: ARRAY OF CHAR);
+PROCEDURE Open (VAR f: File; fileName: ARRAY OF CHAR; newFile: BOOLEAN);
+PROCEDURE Close (VAR f: File);
+PROCEDURE ReadBytes (f: File; VAR buf: ARRAY OF CHAR; VAR len: CARDINAL);
+PROCEDURE Write (f: File; ch: CHAR);
+PROCEDURE WriteLn (f: File);
+PROCEDURE WriteString (f: File; str: ARRAY OF CHAR);
+PROCEDURE WriteInt (f: File; int: INTEGER; wid: CARDINAL);
+PROCEDURE WriteCard (f: File; card, wid: CARDINAL);
+
+PROCEDURE SLENGTH (stringVal: ARRAY OF CHAR): CARDINAL;
+PROCEDURE Assign (source: ARRAY OF CHAR; VAR destination: ARRAY OF CHAR);
+PROCEDURE Extract (source: ARRAY OF CHAR;
+                   startIndex, numberToExtract: CARDINAL;
+                   VAR destination: ARRAY OF CHAR);
+PROCEDURE Concat (stringVal1, stringVal2: ARRAY OF CHAR;
+                  VAR destination: ARRAY OF CHAR);
+PROCEDURE Compare (stringVal1, stringVal2: ARRAY OF CHAR): INTEGER;
+
+END FileIO.

+ 131 - 0
runtime/syslib/FileIO.mod

@@ -0,0 +1,131 @@
+IMPLEMENTATION MODULE FileIO;
+(* Self-hosted file I/O: SysShim only. *)
+
+IMPORT SysShim;
+
+VAR
+  argIdx: CARDINAL;
+
+PROCEDURE NextParameter (VAR s: ARRAY OF CHAR);
+BEGIN
+  IF SysShim.arg(argIdx, s, LEN(s)) THEN
+    INC(argIdx)
+  ELSE
+    s[0] := CHR(0)
+  END
+END NextParameter;
+
+PROCEDURE Open (VAR f: File; fileName: ARRAY OF CHAR; newFile: BOOLEAN);
+BEGIN
+  IF newFile THEN f := SysShim.fopenwrite(fileName)
+  ELSE f := SysShim.fopenread(fileName)
+  END;
+  Okay := f # NIL
+END Open;
+
+PROCEDURE Close (VAR f: File);
+BEGIN
+  SysShim.fclose(f);
+  f := NIL
+END Close;
+
+PROCEDURE ReadBytes (f: File; VAR buf: ARRAY OF CHAR; VAR len: CARDINAL);
+BEGIN
+  len := SysShim.fread(f, buf, len)
+END ReadBytes;
+
+PROCEDURE Write (f: File; ch: CHAR);
+BEGIN
+  IF ch = EOL THEN SysShim.fwriteln(f) ELSE SysShim.fputc(f, ch) END
+END Write;
+
+PROCEDURE WriteLn (f: File);
+BEGIN
+  SysShim.fwriteln(f)
+END WriteLn;
+
+PROCEDURE WriteString (f: File; str: ARRAY OF CHAR);
+BEGIN
+  SysShim.fputs(f, str)
+END WriteString;
+
+PROCEDURE WriteInt (f: File; int: INTEGER; wid: CARDINAL);
+BEGIN
+  SysShim.fwriteintw(f, int, wid)
+END WriteInt;
+
+PROCEDURE WriteCard (f: File; card, wid: CARDINAL);
+BEGIN
+  SysShim.fwriteintw(f, card, wid)
+END WriteCard;
+
+PROCEDURE SLENGTH (stringVal: ARRAY OF CHAR): CARDINAL;
+BEGIN
+  RETURN LEN(stringVal)
+END SLENGTH;
+
+PROCEDURE Assign (source: ARRAY OF CHAR; VAR destination: ARRAY OF CHAR);
+  VAR i, n: CARDINAL;
+BEGIN
+  n := LEN(source);
+  IF n > LEN(destination) THEN n := LEN(destination) END;
+  i := 0;
+  WHILE i < n DO
+    destination[i] := source[i];
+    INC(i)
+  END
+END Assign;
+
+PROCEDURE Extract (source: ARRAY OF CHAR;
+                   startIndex, numberToExtract: CARDINAL;
+                   VAR destination: ARRAY OF CHAR);
+  VAR i, n, k: CARDINAL;
+BEGIN
+  n := LEN(source);
+  k := 0;
+  i := startIndex;
+  WHILE (i < n) AND (k < numberToExtract) AND (k < LEN(destination)) DO
+    destination[k] := source[i];
+    INC(k); INC(i)
+  END
+END Extract;
+
+PROCEDURE Concat (stringVal1, stringVal2: ARRAY OF CHAR;
+                  VAR destination: ARRAY OF CHAR);
+  VAR i, k: CARDINAL;
+BEGIN
+  k := 0; i := 0;
+  WHILE (i < LEN(stringVal1)) AND (k < LEN(destination)) DO
+    destination[k] := stringVal1[i]; INC(k); INC(i)
+  END;
+  i := 0;
+  WHILE (i < LEN(stringVal2)) AND (k < LEN(destination)) DO
+    destination[k] := stringVal2[i]; INC(k); INC(i)
+  END
+END Concat;
+
+PROCEDURE Compare (stringVal1, stringVal2: ARRAY OF CHAR): INTEGER;
+  VAR i, n, m: CARDINAL;
+BEGIN
+  n := LEN(stringVal1); m := LEN(stringVal2);
+  i := 0;
+  WHILE (i < n) AND (i < m) DO
+    IF stringVal1[i] < stringVal2[i] THEN RETURN -1
+    ELSIF stringVal1[i] > stringVal2[i] THEN RETURN 1
+    END;
+    INC(i)
+  END;
+  IF n < m THEN RETURN -1
+  ELSIF n > m THEN RETURN 1
+  END;
+  RETURN 0
+END Compare;
+
+BEGIN
+  argIdx := 0;
+  Okay := TRUE;
+  StdOut := SysShim.stdout();
+  con := StdOut;
+  StdIn := NIL;
+  err := SysShim.stderr()
+END FileIO.

+ 94 - 0
runtime/syslib/SysShim.LST

@@ -0,0 +1,94 @@
+Listing:
+
+    1  IMPLEMENTATION MODULE SysShim;
+    2  (* Binds the C shim (shim.c) directly. *)
+    3  
+    4  FROM SYSTEM IMPORT ADDRESS;
+    5  
+    6  PROCEDURE m2fopenread (VAR name : ARRAY OF CHAR) : ADDRESS;
+    7    EXTERNAL;
+    8  PROCEDURE m2fopenwrite (VAR name : ARRAY OF CHAR) : ADDRESS;
+    9    EXTERNAL;
+   10  PROCEDURE m2fclose (h : ADDRESS);
+   11    EXTERNAL;
+   12  PROCEDURE m2fread (h : ADDRESS; VAR buf : ARRAY OF CHAR;
+   13                     max : CARDINAL) : CARDINAL;
+   14    EXTERNAL;
+   15  PROCEDURE m2fputc (h : ADDRESS; c : CHAR);
+   16    EXTERNAL;
+   17  PROCEDURE m2fputs (h : ADDRESS; VAR s : ARRAY OF CHAR);
+   18    EXTERNAL;
+   19  PROCEDURE m2fwriteln (h : ADDRESS);
+   20    EXTERNAL;
+   21  PROCEDURE m2fwriteintw (h : ADDRESS; v : INTEGER; wid : CARDINAL);
+   22    EXTERNAL;
+   23  PROCEDURE m2stdout () : ADDRESS;
+   24    EXTERNAL;
+   25  PROCEDURE m2stderr () : ADDRESS;
+   26    EXTERNAL;
+   27  PROCEDURE m2arg (i : CARDINAL; VAR s : ARRAY OF CHAR;
+   28                   cap : CARDINAL) : BOOLEAN;
+   29    EXTERNAL;
+   30  
+   31  PROCEDURE fopenread (VAR name : ARRAY OF CHAR) : ADDRESS;
+   32  BEGIN
+   33    RETURN m2fopenread(name)
+   34  END fopenread;
+   35  
+   36  PROCEDURE fopenwrite (VAR name : ARRAY OF CHAR) : ADDRESS;
+   37  BEGIN
+   38    RETURN m2fopenwrite(name)
+   39  END fopenwrite;
+   40  
+   41  PROCEDURE fclose (h : ADDRESS);
+   42  BEGIN
+   43    m2fclose(h)
+   44  END fclose;
+   45  
+   46  PROCEDURE fread (h : ADDRESS; VAR buf : ARRAY OF CHAR;
+   47                   max : CARDINAL) : CARDINAL;
+   48  BEGIN
+   49    RETURN m2fread(h, buf, max)
+   50  END fread;
+   51  
+   52  PROCEDURE fputc (h : ADDRESS; c : CHAR);
+   53  BEGIN
+   54    m2fputc(h, c)
+   55  END fputc;
+   56  
+   57  PROCEDURE fputs (h : ADDRESS; VAR s : ARRAY OF CHAR);
+   58  BEGIN
+   59    m2fputs(h, s)
+   60  END fputs;
+   61  
+   62  PROCEDURE fwriteln (h : ADDRESS);
+   63  BEGIN
+   64    m2fwriteln(h)
+   65  END fwriteln;
+   66  
+   67  PROCEDURE fwriteintw (h : ADDRESS; v : INTEGER; wid : CARDINAL);
+   68  BEGIN
+   69    m2fwriteintw(h, v, wid)
+   70  END fwriteintw;
+   71  
+   72  PROCEDURE stdout () : ADDRESS;
+   73  BEGIN
+   74    RETURN m2stdout()
+   75  END stdout;
+   76  
+   77  PROCEDURE stderr () : ADDRESS;
+   78  BEGIN
+   79    RETURN m2stderr()
+   80  END stderr;
+   81  
+   82  PROCEDURE arg (i : CARDINAL; VAR s : ARRAY OF CHAR;
+   83                 cap : CARDINAL) : BOOLEAN;
+   84  BEGIN
+   85    RETURN m2arg(i, s, cap)
+   86  END arg;
+   87  
+   88  END SysShim.
+
+    0 errors
+
+

+ 32 - 0
runtime/syslib/SysShim.def

@@ -0,0 +1,32 @@
+DEFINITION MODULE SysShim;
+(* Low-level bridge from V3 Modula-2 to the C runtime shim
+   (runtime/syslib/shim.c). Descriptor-aware: ARRAY OF CHAR is
+   passed as its descriptor address, matching V3's string layout.
+   This is the self-hosted counterpart of the host FileIO. *)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+PROCEDURE fopenread (VAR name : ARRAY OF CHAR) : ADDRESS;
+(* Opens name for reading; NIL on failure. *)
+PROCEDURE fopenwrite (VAR name : ARRAY OF CHAR) : ADDRESS;
+(* Creates/truncates name for writing; NIL on failure. *)
+PROCEDURE fclose (h : ADDRESS);
+
+PROCEDURE fread (h : ADDRESS; VAR buf : ARRAY OF CHAR;
+                 max : CARDINAL) : CARDINAL;
+(* Reads up to max bytes into buf; buf's length is set to the
+   number read, which is also returned. *)
+PROCEDURE fputc (h : ADDRESS; c : CHAR);
+PROCEDURE fputs (h : ADDRESS; VAR s : ARRAY OF CHAR);
+PROCEDURE fwriteln (h : ADDRESS);
+PROCEDURE fwriteintw (h : ADDRESS; v : INTEGER; wid : CARDINAL);
+
+PROCEDURE stdout () : ADDRESS;
+PROCEDURE stderr () : ADDRESS;
+
+PROCEDURE arg (i : CARDINAL; VAR s : ARRAY OF CHAR;
+               cap : CARDINAL) : BOOLEAN;
+(* Copies command-line argument i into s (capacity cap); FALSE when
+   no such argument. *)
+
+END SysShim.

+ 88 - 0
runtime/syslib/SysShim.mod

@@ -0,0 +1,88 @@
+IMPLEMENTATION MODULE SysShim;
+(* Binds the C shim (shim.c) directly. *)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+PROCEDURE m2fopenread (VAR name : ARRAY OF CHAR) : ADDRESS;
+  EXTERNAL;
+PROCEDURE m2fopenwrite (VAR name : ARRAY OF CHAR) : ADDRESS;
+  EXTERNAL;
+PROCEDURE m2fclose (h : ADDRESS);
+  EXTERNAL;
+PROCEDURE m2fread (h : ADDRESS; VAR buf : ARRAY OF CHAR;
+                   max : CARDINAL) : CARDINAL;
+  EXTERNAL;
+PROCEDURE m2fputc (h : ADDRESS; c : CHAR);
+  EXTERNAL;
+PROCEDURE m2fputs (h : ADDRESS; VAR s : ARRAY OF CHAR);
+  EXTERNAL;
+PROCEDURE m2fwriteln (h : ADDRESS);
+  EXTERNAL;
+PROCEDURE m2fwriteintw (h : ADDRESS; v : INTEGER; wid : CARDINAL);
+  EXTERNAL;
+PROCEDURE m2stdout () : ADDRESS;
+  EXTERNAL;
+PROCEDURE m2stderr () : ADDRESS;
+  EXTERNAL;
+PROCEDURE m2arg (i : CARDINAL; VAR s : ARRAY OF CHAR;
+                 cap : CARDINAL) : BOOLEAN;
+  EXTERNAL;
+
+PROCEDURE fopenread (VAR name : ARRAY OF CHAR) : ADDRESS;
+BEGIN
+  RETURN m2fopenread(name)
+END fopenread;
+
+PROCEDURE fopenwrite (VAR name : ARRAY OF CHAR) : ADDRESS;
+BEGIN
+  RETURN m2fopenwrite(name)
+END fopenwrite;
+
+PROCEDURE fclose (h : ADDRESS);
+BEGIN
+  m2fclose(h)
+END fclose;
+
+PROCEDURE fread (h : ADDRESS; VAR buf : ARRAY OF CHAR;
+                 max : CARDINAL) : CARDINAL;
+BEGIN
+  RETURN m2fread(h, buf, max)
+END fread;
+
+PROCEDURE fputc (h : ADDRESS; c : CHAR);
+BEGIN
+  m2fputc(h, c)
+END fputc;
+
+PROCEDURE fputs (h : ADDRESS; VAR s : ARRAY OF CHAR);
+BEGIN
+  m2fputs(h, s)
+END fputs;
+
+PROCEDURE fwriteln (h : ADDRESS);
+BEGIN
+  m2fwriteln(h)
+END fwriteln;
+
+PROCEDURE fwriteintw (h : ADDRESS; v : INTEGER; wid : CARDINAL);
+BEGIN
+  m2fwriteintw(h, v, wid)
+END fwriteintw;
+
+PROCEDURE stdout () : ADDRESS;
+BEGIN
+  RETURN m2stdout()
+END stdout;
+
+PROCEDURE stderr () : ADDRESS;
+BEGIN
+  RETURN m2stderr()
+END stderr;
+
+PROCEDURE arg (i : CARDINAL; VAR s : ARRAY OF CHAR;
+               cap : CARDINAL) : BOOLEAN;
+BEGIN
+  RETURN m2arg(i, s, cap)
+END arg;
+
+END SysShim.