Selaa lähdekoodia

Split executables to FreeOberon and fob; compilation process change; fixed some graphical examples

Arthur Yefimov 3 vuotta sitten
vanhempi
commit
deee39018f

+ 3 - 1
.gitignore

@@ -1,6 +1,8 @@
 /FreeOberon
 /FreeOberon.exe
-/bin/*
+/fob
+/fob.exe
+/_Build/*
 /src/Makefile
 /src/*.o
 /src/*.h

+ 1 - 0
Data/Texts/ru.dat

@@ -240,6 +240,7 @@ menuMemorySizes "&Размеры памяти..."
 menuLinker "&Компоновщик..."
 menuDirectories "&Каталоги..."
 menuEnvironment "Окру&жение"
+menuTools "&Инструменты..."
 menuPreferences "&Предпочтения..."
 menuEditor "&Редактор..."
 menuCodeComplete "&Автозавершение кода..."

+ 22 - 5
Data/bin/compile.sh

@@ -1,18 +1,35 @@
 #!/bin/bash
-#   This script is automatically run by Free Oberon on Windows
+#   This script is automatically run by Free Oberon on Linux
 #   for each compiled module. The initial current directory of
 #   the script is where FreeOberon executable is located.
 #   You are free to edit this file to adjust the process.
 
-cd bin
+# Set DIR = directory of this script
+SOURCE=${BASH_SOURCE[0]}
+while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
+  DIR=$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )
+  SOURCE=$(readlink "$SOURCE")
+  [[ $SOURCE != /* ]] && SOURCE=$DIR/$SOURCE # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
+done
+DIR=$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )
 
-OFRDIR="../Data/bin/OfrontPlus/Target/Linux_amd64"
+FNAME=$1
+
+if [[ "${FNAME:0:1}" != "/" ]]; then
+  FNAME=../$FNAME
+fi
+
+
+mkdir -p _Build
+cd _Build
+
+OFRDIR="$DIR/OfrontPlus/Target/Linux_amd64"
 PATH="$OFRDIR:$PATH"
-export OBERON=".:$PWD/../src:$OFRDIR/Lib/Sym"
+export OBERON=".:$DIR/../../src:$OFRDIR/Lib/Sym"
 OFR="ofront+ -s -88 -7w"
 
 
-$OFR $2 ../Programs/$1
+$OFR $2 $FNAME
 retcode=$?
 cd ..
 exit $retcode

+ 14 - 5
Data/bin/link_console.sh

@@ -4,13 +4,22 @@
 #   When it is being run, the current directory
 #   must be the root directory of Free Oberon.
 
-cd bin
+# Set DIR = directory of this script
+SOURCE=${BASH_SOURCE[0]}
+while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
+  DIR=$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )
+  SOURCE=$(readlink "$SOURCE")
+  [[ $SOURCE != /* ]] && SOURCE=$DIR/$SOURCE # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
+done
+DIR=$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )
+
+cd _Build
 
 THENAME="${1%.*}"
 ONAME="${THENAME##*/}"
 
-FOBDIR=".."
-OFRDIR="../Data/bin/OfrontPlus"
+FOBDIR="$DIR/../.."
+OFRDIR="$DIR/OfrontPlus"
 OFRTAR="$OFRDIR/Target/Linux_amd64"
 PATH="$OFRTAR:$PATH"
 CC="gcc"
@@ -21,8 +30,8 @@ shift
 
 
 
-# These blanks are left to allow Windows and Linux
-# versions of the script to be viewed in parallel.
+
+
 
 
 

+ 21 - 12
Data/bin/link_graph.sh

@@ -4,16 +4,25 @@
 #   When it is being run, the current directory
 #   must be the root directory of Free Oberon.
 
-THENAME="${1%.*}"
-ONAME="${THENAME##*/}"
-OFRDIR="../Data/bin/OfrontPlus/Target/Linux_amd64"
-PATH="$OFRDIR:$PATH"
-CC="gcc"
-
-cd bin
+# Set DIR = directory of this script
+SOURCE=${BASH_SOURCE[0]}
+while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
+  DIR=$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )
+  SOURCE=$(readlink "$SOURCE")
+  [[ $SOURCE != /* ]] && SOURCE=$DIR/$SOURCE # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
+done
+DIR=$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )
 
+cd _Build
 
+THENAME="${1%.*}"
+ONAME="${THENAME##*/}"
 
+FOBDIR="$DIR/../.."
+OFRDIR="$DIR/OfrontPlus"
+OFRTAR="$OFRDIR/Target/Linux_amd64"
+PATH="$OFRTAR:$PATH"
+CC="gcc"
 
 
 shift
@@ -29,13 +38,13 @@ shift
 
 
 $CC -O0 -fno-exceptions \
-  -I ../src \
-  -I $OFRDIR/../../Mod/Lib \
-  -I $OFRDIR/Lib/Obj \
+  -I $FOBDIR/src \
+  -I $OFRDIR/Mod/Lib \
+  -I $OFRTAR/Lib/Obj \
   $ONAME.c -o $ONAME \
   $@ \
-  ../Data/bin/libFreeOberon.a \
-  $OFRDIR/Lib/libOfront.a \
+  $FOBDIR/Data/bin/libFreeOberon.a \
+  $OFRTAR/Lib/libOfront.a \
   $(pkg-config \
     allegro_primitives-5 allegro_image-5 allegro_audio-5 \
     allegro_acodec-5 allegro_font-5 allegro_dialog-5 \

+ 1 - 1
Programs/Book.Mod

@@ -1,5 +1,5 @@
 MODULE Book;
-IMPORT Out, In, G := Graph2;
+IMPORT Out, In, G := Graph;
 VAR c: G.Color;
 BEGIN
   G.Init();

+ 16 - 14
Programs/Life.Mod

@@ -6,11 +6,11 @@ CONST maxW = 60*4; maxH = 33*4;
 TYPE
   Field = ARRAY maxH, maxW OF BOOLEAN;
 VAR
-  S: G.Bitmap;
-  W, H: INTEGER; (* Real width and height of field in cells *)
+  sw, sh: INTEGER; (* Screen size in pixels *)
+  W, H: INTEGER; (* Actual width and height of field in cells *)
   m, m2: Field; (* m2 is a temporary copy of m *)
   x0, y0: INTEGER; (* Field offset on screen in pixels *)
-  red, black, white: INTEGER; (* Color constants: black, red etc. *)
+  red, black, white: G.Color;
 
 PROCEDURE Neighbours(x, y: INTEGER): INTEGER;
 VAR n: INTEGER;
@@ -48,12 +48,13 @@ BEGIN
 END Live;
 
 PROCEDURE DrawCell(x, y: INTEGER);
-VAR xx, yy, c: INTEGER;
+VAR xx, yy: INTEGER;
+  c: G.Color;
 BEGIN
   xx := x0 + x * cellSize;
   yy := y0 + y * cellSize;
   IF m[y, x] THEN c := red ELSE c := black END;
-  G.RectFill(S, xx, yy, xx + cellSize - 1, yy + cellSize - 1, c)
+  G.FillRect(xx, yy, xx + cellSize - 1, yy + cellSize - 1, c)
 END DrawCell;
 
 PROCEDURE Draw;
@@ -78,25 +79,26 @@ END Run;
 PROCEDURE Init;
 VAR x, y: INTEGER;
 BEGIN
-  G.Settings(640, 480, {G.sharpPixels, G.spread, G.fullscreen});
-  S := G.Init();
+  G.Settings(640, 480, {});
+  G.Init;
 
-  W := S.w DIV cellSize;
-  H := S.h DIV cellSize;
+  G.GetScreenSize(sw, sh);
+  W := sw DIV cellSize;
+  H := sh DIV cellSize;
   IF W >= maxW THEN W := maxW - 1 END;
   IF H >= maxH THEN H := maxH - 1 END;
 
-  red := G.MakeCol(240, 0, 0);
-  black := G.MakeCol(10, 10, 10);
-  white := G.MakeCol(230, 230, 230);
+  G.MakeCol(red, 240, 0, 0);
+  G.MakeCol(black, 10, 10, 10);
+  G.MakeCol(white, 230, 230, 230);
 
   FOR y := 0 TO H - 1 DO
     FOR x := 0 TO W - 1 DO
       m[y, x] := Random.Uniform() < initial
     END
   END;
-  x0 := (S.w - cellSize * W) DIV 2;
-  y0 := (S.h - cellSize * H) DIV 2
+  x0 := (sw - cellSize * W) DIV 2;
+  y0 := (sh - cellSize * H) DIV 2
 END Init;
 
 BEGIN

+ 24 - 21
Programs/Life2.Mod

@@ -1,13 +1,13 @@
 MODULE Life2;
-IMPORT G := Graph2, Random;
-CONST maxW = 60*8; maxH = 33*8;
-  cellSize = 2;
+IMPORT G := Graph, Random;
+CONST maxW = 180; maxH = 100;
+  cellSize = 5;
   initial = 0.2;
 TYPE
   Field = ARRAY maxH, maxW OF INTEGER;
 VAR
-  S: G.Bitmap;
-  W, H: INTEGER; (* Real width and height of field in cells *)
+  SW, SH: INTEGER; (* Screen size in pixels *)
+  W, H: INTEGER; (* Actual width and height of field in cells *)
   m, m2: Field; (* m2 is a temporary copy of m *)
   x0, y0: INTEGER; (* Field offset on screen in pixels *)
   colors: ARRAY 9 OF G.Color; (* Color constants: black, red etc. *)
@@ -87,7 +87,8 @@ BEGIN
       DrawCell(x, y)
     END
   END;
-  G.Flip
+  G.Flip;
+  G.Delay(20)
 END Draw;
 
 PROCEDURE Run;
@@ -101,23 +102,25 @@ END Run;
 PROCEDURE Init;
 VAR x, y: INTEGER;
 BEGIN
-  G.Settings(640, 400, {G.sharpPixels, G.spread, G.fullscreen});
-  S := G.Init();
+  G.Settings(640, 400, {});
+  G.Init();
 
-  W := S.w DIV cellSize;
-  H := S.h DIV cellSize;
+  G.GetScreenSize(SW, SH);
+
+  W := SW DIV cellSize;
+  H := SH DIV cellSize;
   IF W >= maxW THEN W := maxW - 1 END;
   IF H >= maxH THEN H := maxH - 1 END;
 
-  colors[0] := G.MakeCol(10, 10, 10);
-  colors[1] := G.MakeCol(240, 0, 0);
-  colors[2] := G.MakeCol(230, 230, 230);
-  colors[3] := G.MakeCol(0, 100, 255);
-  colors[4] := G.MakeCol(0, 230, 0);
-  colors[5] := G.MakeCol(255, 255, 0);
-  colors[6] := G.MakeCol(230, 0, 230);
-  colors[7] := G.MakeCol(150, 80, 0);
-  colors[8] := G.MakeCol(255, 150, 0);
+  G.MakeCol(colors[0], 10, 10, 10);
+  G.MakeCol(colors[1], 240, 0, 0);
+  G.MakeCol(colors[2], 230, 230, 230);
+  G.MakeCol(colors[3], 0, 100, 255);
+  G.MakeCol(colors[4], 0, 230, 0);
+  G.MakeCol(colors[5], 255, 255, 0);
+  G.MakeCol(colors[6], 230, 0, 230);
+  G.MakeCol(colors[7], 150, 80, 0);
+  G.MakeCol(colors[8], 255, 150, 0);
 
   FOR y := 0 TO H - 1 DO
     FOR x := 0 TO W - 1 DO
@@ -128,8 +131,8 @@ BEGIN
       END
     END
   END;
-  x0 := (S.w - cellSize * W) DIV 2;
-  y0 := (S.h - cellSize * H) DIV 2
+  x0 := (SW - cellSize * W) DIV 2;
+  y0 := (SH - cellSize * H) DIV 2
 END Init;
 
 BEGIN

+ 0 - 0
bin/TEXT.DAT → _Build/TEXT.DAT


+ 1 - 0
_Build/fungame.in

@@ -0,0 +1 @@
+21

+ 30 - 19
src/Builder.Mod

@@ -16,7 +16,8 @@ GNU General Public License for more details.
 You should have received a copy of the GNU General Public License
 along with Free Oberon.  If not, see <http://www.gnu.org/licenses/>.
 *)
-IMPORT Term, FoStrings, Files, Utf8, Config, Strings, Int, Out, Kernel;
+IMPORT Term, FoStrings, Files, Utf8, Config, Strings, Int, Out,
+  Env, Dir, Kernel;
 
 TYPE
   StrList* = POINTER TO StrListDesc;
@@ -48,7 +49,7 @@ RETURN exists END ModuleExists;
 
 PROCEDURE SetWorkDir*(IN fname: ARRAY OF CHAR);
 VAR i: INTEGER;
-BEGIN i := Strings.Length(fname);
+BEGIN i := Strings.Length(fname) - 1;
   WHILE (i # -1) & (fname[i] # '/') & (fname[i] # '\') DO DEC(i) END;
   IF i # -1 THEN Strings.Extract(fname, 0, i + 1, workDir)
   ELSE workDir[0] := 0X
@@ -164,6 +165,16 @@ BEGIN i := 0; j := 0;
   modname[j] := 0X
 END GetModuleName;
 
+(* Appends relative or full path of 'Data/bin/' or 'Data\bin\' to s *)
+PROCEDURE AppendDataBin(VAR s: ARRAY OF CHAR);
+VAR dir: ARRAY 1024 OF CHAR;
+BEGIN
+  Env.GetAppDir(s);
+  IF Config.isWindows THEN Strings.Append('Data\bin\', s)
+  ELSE Strings.Append('Data/bin/', s)
+  END
+END AppendDataBin;
+
 PROCEDURE RunCommand(IN fname, mod: ARRAY OF CHAR; link, graph, main: BOOLEAN;
     list: StrList; onError: ErrorHandler): BOOLEAN;
 CONST bufLen = 20480;
@@ -183,23 +194,19 @@ BEGIN ok := TRUE;
   END;
   IF Config.isWindows THEN
     IF Term.SearchPath('cmd.exe', q) # 0 THEN
-      Utf8.Decode(q, cmd);
-      Strings.Insert('"', 0, cmd);
-      Strings.Append('" /C Data\bin\', cmd);
-      Strings.Append(command, cmd);
-      Strings.Append('.bat ', cmd)
+      Utf8.Decode(q, cmd); Strings.Insert('"', 0, cmd);
+      Strings.Append('" /C ', cmd); AppendDataBin(cmd);
+      Strings.Append(command, cmd); Strings.Append('.bat ', cmd)
     ELSE ok := FALSE; onError('', -1, -1, -1, 'Could not find cmd.exe')
     END
   ELSE (* Linux *)
-    cmd := 'Data/bin/'; Strings.Append(command, cmd);
+    cmd := ''; AppendDataBin(cmd);
+    Strings.Append(command, cmd);
     Strings.Append('.sh ', cmd)
   END;
 
   IF ok THEN
-    IF Strings.Pos(Config.stdPath, fname, 0) = 0 THEN
-      Strings.Extract(fname, Strings.Length(Config.stdPath), LEN(s), s)
-    ELSE s := fname$
-    END;
+    s := fname$;
     Strings.Append(s, cmd);
 
     IF main THEN Strings.Append(' -m', cmd)
@@ -226,7 +233,6 @@ BEGIN ok := TRUE;
       ELSIF link THEN FoStrings.GetErrorStr(422, z)
       ELSE FoStrings.GetErrorStr(421, z)
       END;
-      (*IF z[0] = 0X THEN ShowError(s) ELSE ShowError(z) END*)
       IF z[0] = 0X THEN onError('', -1, -1, -1, s)
       ELSE onError('', -1, -1, -1, z)
       END
@@ -241,15 +247,18 @@ END Compile;
 
 PROCEDURE Link(IN fname, mod: ARRAY OF CHAR;
     graph: BOOLEAN; list: StrList; VAR exename: ARRAY OF CHAR;
-    onError: ErrorHandler): BOOLEAN;
+    onError: ErrorHandler; moveToCwd: BOOLEAN): BOOLEAN;
 VAR ok: BOOLEAN;
   s: ARRAY 2048 OF CHAR;
   res: INTEGER;
 BEGIN ok := RunCommand(fname, mod, TRUE, graph, FALSE, list, onError);
   IF ok THEN (* Move executable file if workDir is non-standard *)
     s := mod$; IF Config.isWindows THEN Strings.Append('.exe', s) END;
-    exename := 'bin/'; Strings.Append(s, exename);
-    IF workDir # Config.stdPath THEN
+    exename := '_Build/'; Strings.Append(s, exename);
+    IF moveToCwd THEN
+      Files.Rename(exename, s, res);
+      IF res = 0 THEN exename := s$ END
+    ELSIF workDir # Config.stdPath THEN
       Strings.Insert(workDir, 0, s);
       Files.Rename(exename, s, res);
       IF res = 0 THEN exename := s$ END
@@ -322,7 +331,8 @@ BEGIN
 END GetSym;
 
 PROCEDURE CompileAll*(modules: StrList; graph: BOOLEAN;
-    VAR exename: ARRAY OF CHAR; onError: ErrorHandler): BOOLEAN;
+    VAR exename: ARRAY OF CHAR; moveToCwd: BOOLEAN;
+    onError: ErrorHandler): BOOLEAN;
 VAR p, last: StrList;
   ok: BOOLEAN;
 BEGIN exename[0] := 0X;
@@ -339,7 +349,8 @@ BEGIN exename[0] := 0X;
       IF ModuleExists(p.fname) THEN
         IF ~Compile(p.fname, '', TRUE, onError) THEN ok := FALSE END
       END;
-      ok := ok & Link(p.fname, p.s, graph, modules, exename, onError);
+      ok := ok & Link(p.fname, p.s, graph, modules,
+          exename, onError, moveToCwd);
     END
   ELSE ok := FALSE
   END ;
@@ -434,7 +445,7 @@ BEGIN L := NIL; res := 0(*OK*);
 RETURN L END UsedModuleList;
 
 PROCEDURE ImportsGraph*(p: StrList): BOOLEAN;
-BEGIN WHILE (p # NIL) & (p.s # 'Graph') DO Out.Char('>');Out.String(p.s); Out.Ln; p := p.next END ;
+BEGIN WHILE (p # NIL) & (p.s # 'Graph') DO p := p.next END ;
 RETURN p # NIL END ImportsGraph;
 
 BEGIN

+ 47 - 0
src/Env.Mod

@@ -0,0 +1,47 @@
+MODULE Env;
+IMPORT CmdArgs, Platform, Utf8;
+TYPE SHORTCHAR = Utf8.SHORTCHAR;
+
+VAR count: INTEGER;
+
+PROCEDURE Count*(): INTEGER;
+BEGIN
+  IF count = -1 THEN count := CmdArgs.GetEnvCount() END
+RETURN count END Count;
+
+PROCEDURE Get*(n: INTEGER; VAR s: ARRAY OF CHAR);
+VAR q: ARRAY 10240 OF SHORTCHAR;
+BEGIN
+  IF (0 <= n) & (n < Count()) THEN
+    CmdArgs.GetEnvN(n, q); Utf8.Decode(q, s)
+  ELSE s := ''
+  END
+END Get;
+
+PROCEDURE GetByName*(name: ARRAY OF CHAR; VAR val: ARRAY OF CHAR);
+VAR q: ARRAY 10240 OF SHORTCHAR;
+  z: ARRAY 1024 OF SHORTCHAR;
+BEGIN Utf8.Encode(name, z); CmdArgs.GetEnv(z, q); Utf8.Decode(q, val)
+END GetByName;
+
+PROCEDURE GetAppDir*(VAR s: ARRAY OF CHAR);
+VAR c, delim: CHAR;
+  i: INTEGER;
+BEGIN
+  GetByName('_', s);
+  s[LEN(s) - 1] := 0X;
+
+  i := 0; WHILE s[i] # 0X DO INC(i) END;
+
+  IF Platform.Windows THEN delim := '\' ELSE delim := '/' END;
+
+  c := s[0]; s[0] := delim;
+  REPEAT DEC(i) UNTIL s[i] = delim;
+  s[0] := c;
+
+  s[i + 1] := 0X
+END GetAppDir;
+
+BEGIN
+  count := -1
+END Env.

+ 4 - 3
src/FoStrings.Mod

@@ -1,5 +1,5 @@
 MODULE FoStrings;
-IMPORT Strings, Texts, Int, Dir, Out;
+IMPORT Strings, Texts, Int, Dir, Env, Out;
 
 CONST
   maxErrors* = 500;
@@ -59,8 +59,9 @@ BEGIN
 END Clear;
 
 PROCEDURE GetLangFname(lang: ARRAY OF CHAR; VAR fname: ARRAY OF CHAR);
-BEGIN fname := 'Data/Texts/'; Strings.Append(lang, fname);
-  Strings.Append('.dat', fname)
+BEGIN
+  Env.GetAppDir(fname); Strings.Append('Data/Texts/', fname);
+  Strings.Append(lang, fname); Strings.Append('.dat', fname)
 END GetLangFname;
 
 PROCEDURE LoadStrings;

+ 19 - 4
src/Fob.Mod

@@ -48,21 +48,36 @@ BEGIN
   Out.String(msg); Out.Ln
 END BuildErrorCallback;
 
+PROCEDURE ParseArgs(VAR mainFname, lang: ARRAY OF CHAR);
+VAR i: INTEGER;
+  s: ARRAY 4096 OF CHAR;
+BEGIN i := 1; lang := 'en';
+  WHILE i <= Args.Count DO
+    Args.Get(i, s);
+    IF s = '--lang' THEN Args.Get(i + 1, lang); INC(i)
+    ELSE Strings.Copy(s, mainFname)
+    END;
+    INC(i)
+  END
+END ParseArgs;
+
 PROCEDURE Do;
 VAR modules: Builder.StrList;
-  mainFname, modname, exename, errFname, s: ARRAY 256 OF CHAR;
+  mainFname, modname, exename, errFname, lang, s: ARRAY 256 OF CHAR;
   errLine, errCol, res: INTEGER;
   graph: BOOLEAN;
 BEGIN
-  Args.Get(1, mainFname);
-  FoStrings.SetLang('en');
+  ParseArgs(mainFname, lang);
+  FoStrings.SetLang(lang);
   Builder.SetWorkDir(mainFname);
   Builder.GetModuleName(mainFname, modname);
   modules := Builder.UsedModuleList(modname, mainFname,
     errFname, errLine, errCol, res);
   IF res = 0 THEN
     graph := Builder.ImportsGraph(modules);
-    IF Builder.CompileAll(modules, graph, exename, BuildErrorCallback) THEN END
+    IF Builder.CompileAll(modules, graph, exename,
+        TRUE, BuildErrorCallback) THEN
+    END
   ELSE (*res = 400-file not found or 401-file contains wrong module name*)
     FoStrings.MakeErrorStr(res, s);
     BuildErrorCallback(errFname, 1, 1, 401, s)

+ 3 - 3
src/FreeOberon.Mod

@@ -460,8 +460,9 @@ BEGIN w := c.app.windows;
         errFname, errLine, errCol, res);
       IF res = 0 THEN
         graph := Builder.ImportsGraph(modules);
-        IF Builder.CompileAll(modules, graph, exename, BuildErrorCallback) THEN
-          RunProgram(exename)
+        IF Builder.CompileAll(modules, graph, exename,
+            FALSE, BuildErrorCallback)
+        THEN RunProgram(exename)
         END
       ELSE
         FocusOrOpenFile(errFname);
@@ -851,7 +852,6 @@ PROCEDURE ParseArgs(VAR fs, sw: BOOLEAN; VAR w, h: INTEGER;
     VAR lang: ARRAY OF CHAR; VAR fnames: Fnames);
 VAR i, nofnames: INTEGER;
   s: ARRAY 2048 OF CHAR;
-  q: ARRAY 2048 OF SHORTCHAR;
 BEGIN fs := TRUE; sw := FALSE; i := 1; nofnames := 0; w := defW; h := defH;
   lang := defLang;
   WHILE i <= Args.Count DO Args.Get(i, s);

+ 7 - 2
src/Term.Mod

@@ -24,7 +24,7 @@ PROCEDURE -AAIncludeTermh* '#include "term/term.h"';
 
 PROCEDURE -StartProcess*
   (cmd: ARRAY OF CHAR): BOOLEAN
-  "StartProcess(cmd)";
+  "StartProcessIn(cmd, (char *)0)";
 
 PROCEDURE -StartProcessIn*
   (cmd, dir: ARRAY OF CHAR): BOOLEAN
@@ -44,7 +44,12 @@ PROCEDURE -ReadFromProcess*
 PROCEDURE -RunProcess*
   (cmd: ARRAY OF CHAR; VAR buf: ARRAY OF CHAR;
   limit: INTEGER; VAR len, err: INTEGER): INTEGER
-  "(int)RunProcess((char *)cmd, (char *)buf, limit, len, err)";
+  "(int)RunProcessIn((char *)cmd, (char *)0, (char *)buf, limit, len, err)";
+
+PROCEDURE -RunProcessIn*
+  (cmd, dir: ARRAY OF CHAR; VAR buf: ARRAY OF CHAR;
+  limit: INTEGER; VAR len, err: INTEGER): INTEGER
+  "(int)RunProcessIn((char *)cmd, (char *)dir, (char *)buf, limit, len, err)";
 
 PROCEDURE -SearchPath*
   (filename: ARRAY OF CHAR; VAR result: ARRAY OF CHAR): LONGINT

+ 5 - 2
src/Texts.Mod

@@ -286,10 +286,11 @@ VAR ch, quot: CHAR;
   i, j, h, d, e, n, s: INTEGER;
   x: REAL;
 BEGIN ch := S.nextCh; i := 0;
-  WHILE ch <= ' ' DO
+  WHILE (ch # 0X) & (ch <= ' ') DO
     IF ch = LF THEN INC(S.line) END;
     Read(S, ch)
   END;
+
   IF ('A' <= ch) & (ch <= 'Z') OR ('a' <= ch) & (ch <= 'z') THEN (* Name *)
     REPEAT S.s[i] := ch; INC(i); Read(S, ch)
     UNTIL ((ch < '0') & (ch # '.') OR
@@ -345,7 +346,9 @@ BEGIN ch := S.nextCh; i := 0;
         IF neg THEN S.i := -n ELSE S.i := n END;
         IF hex THEN S.class := Inval ELSE S.class := Int END
       END
-    ELSE (* Spectal character *) S.class := Char;
+    ELSIF ch = 0X THEN
+      S.eot := TRUE
+    ELSE (* Special character *) S.class := Char;
       IF neg THEN S.c := '-' ELSE S.c := ch; Read(S, ch) END
     END
   END;

+ 6 - 1
src/make.bat

@@ -29,6 +29,8 @@ ECHO ON
 @IF ERRORLEVEL 1 GOTO ERR
 %OFR% -7w Args.Mod
 @IF ERRORLEVEL 1 GOTO ERR
+%OFR% -7w Env.Mod
+@IF ERRORLEVEL 1 GOTO ERR
 %OFR% -Cw Files.Mod
 @IF ERRORLEVEL 1 GOTO ERR
 %OFR% -7w Texts.Mod
@@ -74,6 +76,8 @@ windres resources.rc resources.o
 @IF ERRORLEVEL 1 GOTO ERR
 %CCFULL% -c Args.c
 @IF ERRORLEVEL 1 GOTO ERR
+%CCFULL% -c Env.c
+@IF ERRORLEVEL 1 GOTO ERR
 %CCFULL% -c Files.c
 @IF ERRORLEVEL 1 GOTO ERR
 %CCFULL% -c Texts.c
@@ -90,7 +94,8 @@ windres resources.rc resources.o
 @IF ERRORLEVEL 1 GOTO ERR
 
 %AR% -crs ..\Data\bin\FreeOberon.a ^
-  Utf8.o Strings.o Reals.o Int.o In.o Out.o Args.o Files.o Texts.o Random.o ^
+  Utf8.o Strings.o Reals.o Int.o In.o Out.o Args.o Env.o ^
+  Files.o Texts.o Random.o ^
   StrList.o Dir.o Graph.o TermBox.o
 @IF ERRORLEVEL 1 GOTO ERR
 

+ 5 - 1
src/make.sh

@@ -29,6 +29,8 @@ $OFR -Cw Out.Mod &&
 
 $OFR -7w Args.Mod &&
 
+$OFR -7w Env.Mod &&
+
 $OFR -Cw Files.Mod &&
 
 $OFR -7w Texts.Mod &&
@@ -70,6 +72,7 @@ $CCFULL -c Int.c &&
 $CCFULL -c In.c &&
 $CCFULL -c Out.c &&
 $CCFULL -c Args.c &&
+$CCFULL -c Env.c &&
 $CCFULL -c Files.c &&
 $CCFULL -c Texts.c &&
 $CCFULL -c Random.c &&
@@ -79,7 +82,8 @@ $CCFULL -c Graph.c &&
 $CCFULL -c TermBox.c &&
 
 $AR -crs ../Data/bin/libFreeOberon.a \
-  Utf8.o Strings.o Reals.o Int.o In.o Out.o Args.o Files.o Texts.o Random.o \
+  Utf8.o Strings.o Reals.o Int.o In.o Out.o Args.o Env.o \
+  Files.o Texts.o Random.o \
   StrList.o Dir.o Graph.o TermBox.o &&
 
 $CCFULL -o ../$PROG1 \

+ 1 - 2
src/term/term.h

@@ -1,12 +1,11 @@
 #ifndef TERM_H
 #define TERM_H
 
-int StartProcess(char *process);
 int StartProcessIn(char *process, char *dir);
 int ProcessFinished();
 int WriteToProcess(char *buf, int len);
 int ReadFromProcess(char *buf, int *len, int limit);
-int RunProcess(char *cmd, char *buf, int limit, int *len, int *err);
+int RunProcessIn(char *cmd, char *dir, char *buf, int limit, int *len, int *err);
 int MySearchPath(char *filename, char* result, int limit);
 
 #endif

+ 9 - 12
src/term/term_linux.c

@@ -34,17 +34,17 @@ int StartProcessIn(char *process, char *dir) {
   int success = 0;
   int i, j;
 
-      // Ignore SIGPIPE in case of a write to a broken pipe
-      if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
-        puts("Could not ignore SIGPIPE signal.");
-      }
+  // Ignore SIGPIPE in case of a write to a broken pipe
+  if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
+    perror("StartProcessIn: Could not ignore SIGPIPE signal");
+  }
 
   if ((pipe(p) == -1) || (pipe(q) == -1)) {
     perror("StartProcessIn: Could not create pipes");
   } else {
     pid = fork();
     if (pid == -1) { // fork() error
-      perror("StartProcessIn: Could not fork().");
+      perror("StartProcessIn: Could not fork()");
     } else if (pid == 0) { // Child process
       if (dup2(q[0], 0/*stdin*/) == -1) {
         perror("StartProcessIn: Could not dup2(stdin) in child process");
@@ -56,7 +56,7 @@ int StartProcessIn(char *process, char *dir) {
       close(p[0]);
       if (dir && dir[0] != '\0') {
         if (getcwd(cmd, 256) == NULL) {
-          perror("StartProcessIn: Could not getcdw()");
+          perror("StartProcessIn: Could not getcwd()");
         }
         i = 0;
         while (cmd[i]) i++;
@@ -74,7 +74,7 @@ int StartProcessIn(char *process, char *dir) {
         process = &cmd[0];
       }
       if (execl(process, process, (char*)NULL)) {
-        puts("Could not run program.");
+        perror("StartProcess: Could not execl()");
         exit(0);
       }
       /*
@@ -93,10 +93,6 @@ int StartProcessIn(char *process, char *dir) {
   return success;
 }
 
-int StartProcess(char *process) {
-  return StartProcessIn(process, (char *)NULL);
-}
-
 int ProcessFinished(int *err) {
   int status;
   pid_t result = waitpid(pid, &status, WNOHANG|WUNTRACED);
@@ -131,7 +127,8 @@ void ReadFromProcess(char *buf, int *len, int limit) {
   if (*len < 0) *len = 0;
 }
 
-int RunProcess(char *cmd, char *buf, int limit, int *len, int *err) {
+/* !FIXME dir is ignored now*/
+int RunProcessIn(char *cmd, char *dir, char *buf, int limit, int *len, int *err) {
   int success = 0;
   *err = 0;
   FILE *F;

+ 2 - 6
src/term/term_win32.c

@@ -216,10 +216,6 @@ int StartProcessIn(char *process, char *dir) {
   return bSuccess ? 1 : 0;
 }
 
-int StartProcess(char *process) {
-  return StartProcessIn(process, (char *)NULL);
-}
-
 int ProcessFinished(int *err) {
   GetExitCodeProcess(piProcInfo.hProcess, &exit_code);
   int result = exit_code != STILL_ACTIVE;
@@ -350,9 +346,9 @@ void ErrorExit(PTSTR lpszFunction) {
   ExitProcess(1);
 }
 
-int RunProcess(char *cmd, char *buf, int limit, int *len, int *err) {
+int RunProcessIn(char *cmd, char *dir, char *buf, int limit, int *len, int *err) {
   int success = 0;
-  if (StartProcess(cmd)) {
+  if (StartProcessIn(cmd, dir)) {
     int n, i = 0;
     do {
       ReadFromProcess(&buf[i], &n, limit - i); //!FIXME add inner loop