Prechádzať zdrojové kódy

SVI Изменение форматирования

SVI 3 rokov pred
rodič
commit
0ac03f9f44
14 zmenil súbory, kde vykonal 3125 pridanie a 3217 odobranie
  1. 529 536
      source/ARITH.ob07
  2. 111 118
      source/AVLTREES.ob07
  3. 210 217
      source/BIN.ob07
  4. 143 151
      source/CHUNKLISTS.ob07
  5. 21 28
      source/COLLECTIONS.ob07
  6. 40 47
      source/CONSOLE.ob07
  7. 290 290
      source/Compiler.ob07
  8. 432 439
      source/ELF.ob07
  9. 180 187
      source/ERRORS.ob07
  10. 124 131
      source/FILES.ob07
  11. 76 83
      source/HEX.ob07
  12. 699 706
      source/IL.ob07
  13. 141 148
      source/KOS.ob07
  14. 129 136
      source/LISTS.ob07

+ 529 - 536
source/ARITH.ob07

@@ -1,11 +1,4 @@
-(*
-    BSD 2-Clause License
-
-    Copyright (c) 2018-2022, Anton Krotov
-    All rights reserved.
-*)
-
-MODULE ARITH;
+MODULE ARITH;
 
 IMPORT STRINGS, UTILS, LISTS;
 
@@ -42,754 +35,754 @@ VAR
 
 
 PROCEDURE Int* (v: VALUE): INTEGER;
-VAR
-    res: INTEGER;
+    VAR
+        res: INTEGER;
 
-BEGIN
+    BEGIN
 
-    CASE v.typ OF
-    |tINTEGER, tCHAR, tWCHAR:
-        res := v.int
-    |tSET:
-        res := UTILS.Long(ORD(v.set))
-    |tBOOLEAN:
-        res := ORD(v.bool)
-    END
+        CASE v.typ OF
+        |tINTEGER, tCHAR, tWCHAR:
+            res := v.int
+        |tSET:
+            res := UTILS.Long(ORD(v.set))
+        |tBOOLEAN:
+            res := ORD(v.bool)
+        END
 
-    RETURN res
-END Int;
+        RETURN res
+    END Int;
 
 
 PROCEDURE getBool* (v: VALUE): BOOLEAN;
-BEGIN
-    ASSERT(v.typ = tBOOLEAN);
+    BEGIN
+        ASSERT(v.typ = tBOOLEAN);
 
-    RETURN v.bool
-END getBool;
+        RETURN v.bool
+    END getBool;
 
 
 PROCEDURE Float* (v: VALUE): REAL;
-BEGIN
-    ASSERT(v.typ = tREAL);
+    BEGIN
+        ASSERT(v.typ = tREAL);
 
-    RETURN v.float
-END Float;
+        RETURN v.float
+    END Float;
 
 
 PROCEDURE range* (i: VALUE; a, b: INTEGER): BOOLEAN;
-    RETURN (a <= i.int) & (i.int <= b)
-END range;
+        RETURN (a <= i.int) & (i.int <= b)
+    END range;
 
 
 PROCEDURE check* (v: VALUE): BOOLEAN;
-VAR
-    res: BOOLEAN;
+    VAR
+        res: BOOLEAN;
 
-BEGIN
-    CASE v.typ OF
-    |tINTEGER: res := range(v, UTILS.target.minInt, UTILS.target.maxInt)
-    |tCHAR:    res := range(v, 0, 255)
-    |tWCHAR:   res := range(v, 0, 65535)
-    |tREAL:    res := (-UTILS.target.maxReal <= v.float) & (v.float <= UTILS.target.maxReal)
-    END
+    BEGIN
+        CASE v.typ OF
+        |tINTEGER: res := range(v, UTILS.target.minInt, UTILS.target.maxInt)
+        |tCHAR:    res := range(v, 0, 255)
+        |tWCHAR:   res := range(v, 0, 65535)
+        |tREAL:    res := (-UTILS.target.maxReal <= v.float) & (v.float <= UTILS.target.maxReal)
+        END
 
-    RETURN res
-END check;
+        RETURN res
+    END check;
 
 
 PROCEDURE isZero* (v: VALUE): BOOLEAN;
-VAR
-    res: BOOLEAN;
+    VAR
+        res: BOOLEAN;
 
-BEGIN
-    CASE v.typ OF
-    |tINTEGER: res := v.int = 0
-    |tREAL:    res := v.float = 0.0
-    END
+    BEGIN
+        CASE v.typ OF
+        |tINTEGER: res := v.int = 0
+        |tREAL:    res := v.float = 0.0
+        END
 
-    RETURN res
-END isZero;
+        RETURN res
+    END isZero;
 
 
 PROCEDURE iconv* (s: ARRAY OF CHAR; VAR v: VALUE; VAR error: INTEGER);
-VAR
-    value: INTEGER;
-    i:     INTEGER;
-    d:     INTEGER;
-
-BEGIN
-    error := 0;
-    value := 0;
-
-    i := 0;
-    WHILE STRINGS.digit(s[i]) & (error = 0) DO
-        d := digit[ORD(s[i])];
-        IF value <= (UTILS.maxint - d) DIV 10 THEN
-            value := value * 10 + d;
-            INC(i)
-        ELSE
-            error := 1
-        END
-    END;
+    VAR
+        value: INTEGER;
+        i:     INTEGER;
+        d:     INTEGER;
+
+    BEGIN
+        error := 0;
+        value := 0;
+
+        i := 0;
+        WHILE STRINGS.digit(s[i]) & (error = 0) DO
+            d := digit[ORD(s[i])];
+            IF value <= (UTILS.maxint - d) DIV 10 THEN
+                value := value * 10 + d;
+                INC(i)
+            ELSE
+                error := 1
+            END
+        END;
 
-    IF error = 0 THEN
-        v.int := value;
-        v.typ := tINTEGER;
-        IF ~check(v) THEN
-            error := 1
+        IF error = 0 THEN
+            v.int := value;
+            v.typ := tINTEGER;
+            IF ~check(v) THEN
+                error := 1
+            END
         END
-    END
 
-END iconv;
+    END iconv;
 
 
 PROCEDURE hconv* (s: ARRAY OF CHAR; VAR v: VALUE; VAR error: INTEGER);
-VAR
-    value: INTEGER;
-    i:     INTEGER;
-    n:     INTEGER;
-    d:     INTEGER;
+    VAR
+        value: INTEGER;
+        i:     INTEGER;
+        n:     INTEGER;
+        d:     INTEGER;
 
-BEGIN
-    ASSERT(STRINGS.digit(s[0]));
+    BEGIN
+        ASSERT(STRINGS.digit(s[0]));
 
-    error := 0;
-    value := 0;
+        error := 0;
+        value := 0;
 
-    n := -1;
-    i := 0;
-    WHILE (s[i] # "H") & (s[i] # "X") & (s[i] # "h") & (s[i] # "x") & (error = 0) DO
+        n := -1;
+        i := 0;
+        WHILE (s[i] # "H") & (s[i] # "X") & (s[i] # "h") & (s[i] # "x") & (error = 0) DO
 
-        d := digit[ORD(s[i])];
-        IF (n = -1) & (d # 0) THEN
-            n := i
-        END;
+            d := digit[ORD(s[i])];
+            IF (n = -1) & (d # 0) THEN
+                n := i
+            END;
 
-        IF (n # -1) & (i - n + 1 > UTILS.target.maxHex) THEN
-            error := 2
-        ELSE
-            value := value * 16 + d;
-            INC(i)
-        END
+            IF (n # -1) & (i - n + 1 > UTILS.target.maxHex) THEN
+                error := 2
+            ELSE
+                value := value * 16 + d;
+                INC(i)
+            END
 
-    END;
+        END;
 
-    value := UTILS.Long(value);
+        value := UTILS.Long(value);
 
-    IF ((s[i] = "X") OR (s[i] = "x")) & (n # -1) & (i - n > 4) THEN
-        error := 3
-    END;
+        IF ((s[i] = "X") OR (s[i] = "x")) & (n # -1) & (i - n > 4) THEN
+            error := 3
+        END;
 
-    IF error = 0 THEN
-        v.int := value;
-        IF (s[i] = "X") OR (s[i] = "x") THEN
-            v.typ := tCHAR;
-            IF ~check(v) THEN
-                v.typ := tWCHAR;
+        IF error = 0 THEN
+            v.int := value;
+            IF (s[i] = "X") OR (s[i] = "x") THEN
+                v.typ := tCHAR;
                 IF ~check(v) THEN
-                    error := 3
+                    v.typ := tWCHAR;
+                    IF ~check(v) THEN
+                        error := 3
+                    END
+                END
+            ELSE
+                v.typ := tINTEGER;
+                IF ~check(v) THEN
+                    error := 2
                 END
-            END
-        ELSE
-            v.typ := tINTEGER;
-            IF ~check(v) THEN
-                error := 2
             END
         END
-    END
 
-END hconv;
+    END hconv;
 
 
 PROCEDURE opFloat2 (VAR a: REAL; b: REAL; op: CHAR): BOOLEAN;
-BEGIN
-    CASE op OF
-    |"+": a := a + b
-    |"-": a := a - b
-    |"*": a := a * b
-    |"/": a := a / b
-    END
+    BEGIN
+        CASE op OF
+        |"+": a := a + b
+        |"-": a := a - b
+        |"*": a := a * b
+        |"/": a := a / b
+        END
 
-    RETURN (-UTILS.maxreal <= a) & (a <= UTILS.maxreal) (* +inf > UTILS.maxreal *)
-END opFloat2;
+        RETURN (-UTILS.maxreal <= a) & (a <= UTILS.maxreal) (* +inf > UTILS.maxreal *)
+    END opFloat2;
 
 
 PROCEDURE fconv* (s: ARRAY OF CHAR; VAR v: VALUE; VAR error: INTEGER);
-VAR
-    value:    REAL;
-    exp10:    REAL;
-    i, n, d:  INTEGER;
-    minus:    BOOLEAN;
-
-BEGIN
-    error := 0;
-    value := 0.0;
-    minus := FALSE;
-    n := 0;
-
-    exp10 := 0.0;
-    WHILE (error = 0) & (STRINGS.digit(s[i]) OR (s[i] = ".")) DO
-        IF s[i] = "." THEN
-            exp10 := 1.0;
-            INC(i)
-        ELSE
-            IF opFloat2(value, 10.0, "*") & opFloat2(value, FLT(digit[ORD(s[i])]), "+") & opFloat2(exp10, 10.0, "*") THEN
+    VAR
+        value:    REAL;
+        exp10:    REAL;
+        i, n, d:  INTEGER;
+        minus:    BOOLEAN;
+
+    BEGIN
+        error := 0;
+        value := 0.0;
+        minus := FALSE;
+        n := 0;
+
+        exp10 := 0.0;
+        WHILE (error = 0) & (STRINGS.digit(s[i]) OR (s[i] = ".")) DO
+            IF s[i] = "." THEN
+                exp10 := 1.0;
                 INC(i)
             ELSE
-                error := 4
+                IF opFloat2(value, 10.0, "*") & opFloat2(value, FLT(digit[ORD(s[i])]), "+") & opFloat2(exp10, 10.0, "*") THEN
+                    INC(i)
+                ELSE
+                    error := 4
+                END
             END
-        END
-    END;
-
-    IF ~opFloat2(value, exp10, "/") THEN
-        error := 4
-    END;
+        END;
 
-    IF (s[i] = "E") OR (s[i] = "e") THEN
-        INC(i)
-    END;
+        IF ~opFloat2(value, exp10, "/") THEN
+            error := 4
+        END;
 
-    IF (s[i] = "-") OR (s[i] = "+") THEN
-        minus := s[i] = "-";
-        INC(i)
-    END;
+        IF (s[i] = "E") OR (s[i] = "e") THEN
+            INC(i)
+        END;
 
-    WHILE (error = 0) & STRINGS.digit(s[i]) DO
-        d := digit[ORD(s[i])];
-        IF n <= (UTILS.maxint - d) DIV 10 THEN
-            n := n * 10 + d;
+        IF (s[i] = "-") OR (s[i] = "+") THEN
+            minus := s[i] = "-";
             INC(i)
-        ELSE
-            error := 5
-        END
-    END;
+        END;
 
-    exp10 := 1.0;
-    WHILE (error = 0) & (n > 0) DO
-        IF opFloat2(exp10, 10.0, "*") THEN
-            DEC(n)
-        ELSE
-            error := 4
-        END
-    END;
+        WHILE (error = 0) & STRINGS.digit(s[i]) DO
+            d := digit[ORD(s[i])];
+            IF n <= (UTILS.maxint - d) DIV 10 THEN
+                n := n * 10 + d;
+                INC(i)
+            ELSE
+                error := 5
+            END
+        END;
 
-    IF error = 0 THEN
-        IF minus THEN
-            IF ~opFloat2(value, exp10, "/") THEN
+        exp10 := 1.0;
+        WHILE (error = 0) & (n > 0) DO
+            IF opFloat2(exp10, 10.0, "*") THEN
+                DEC(n)
+            ELSE
                 error := 4
             END
-        ELSE
-            IF ~opFloat2(value, exp10, "*") THEN
-                error := 4
+        END;
+
+        IF error = 0 THEN
+            IF minus THEN
+                IF ~opFloat2(value, exp10, "/") THEN
+                    error := 4
+                END
+            ELSE
+                IF ~opFloat2(value, exp10, "*") THEN
+                    error := 4
+                END
             END
-        END
-    END;
+        END;
 
-    IF error = 0 THEN
-        v.float := value;
-        v.typ := tREAL;
-        IF ~check(v) THEN
-            error := 4
+        IF error = 0 THEN
+            v.float := value;
+            v.typ := tREAL;
+            IF ~check(v) THEN
+                error := 4
+            END
         END
-    END
 
-END fconv;
+    END fconv;
 
 
 PROCEDURE setChar* (VAR v: VALUE; ord: INTEGER);
-BEGIN
-    v.typ := tCHAR;
-    v.int := ord
-END setChar;
+    BEGIN
+        v.typ := tCHAR;
+        v.int := ord
+    END setChar;
 
 
 PROCEDURE setWChar* (VAR v: VALUE; ord: INTEGER);
-BEGIN
-    v.typ := tWCHAR;
-    v.int := ord
-END setWChar;
+    BEGIN
+        v.typ := tWCHAR;
+        v.int := ord
+    END setWChar;
 
 
 PROCEDURE addInt (VAR a: INTEGER; b: INTEGER): BOOLEAN;
-VAR
-    error: BOOLEAN;
-
-BEGIN
-    IF (a > 0) & (b > 0) THEN
-        error := a > UTILS.maxint - b
-    ELSIF (a < 0) & (b < 0) THEN
-        error := a < UTILS.minint - b
-    ELSE
-        error := FALSE
-    END;
+    VAR
+        error: BOOLEAN;
+
+    BEGIN
+        IF (a > 0) & (b > 0) THEN
+            error := a > UTILS.maxint - b
+        ELSIF (a < 0) & (b < 0) THEN
+            error := a < UTILS.minint - b
+        ELSE
+            error := FALSE
+        END;
 
-    IF ~error THEN
-        a := a + b
-    ELSE
-        a := 0
-    END
+        IF ~error THEN
+            a := a + b
+        ELSE
+            a := 0
+        END
 
-    RETURN ~error
-END addInt;
+        RETURN ~error
+    END addInt;
 
 
 PROCEDURE subInt (VAR a: INTEGER; b: INTEGER): BOOLEAN;
-VAR
-    error: BOOLEAN;
-
-BEGIN
-    IF (a > 0) & (b < 0) THEN
-        error := a > UTILS.maxint + b
-    ELSIF (a < 0) & (b > 0) THEN
-        error := a < UTILS.minint + b
-    ELSIF (a = 0) & (b < 0) THEN
-        error := b = UTILS.minint
-    ELSE
-        error := FALSE
-    END;
+    VAR
+        error: BOOLEAN;
+
+    BEGIN
+        IF (a > 0) & (b < 0) THEN
+            error := a > UTILS.maxint + b
+        ELSIF (a < 0) & (b > 0) THEN
+            error := a < UTILS.minint + b
+        ELSIF (a = 0) & (b < 0) THEN
+            error := b = UTILS.minint
+        ELSE
+            error := FALSE
+        END;
 
-    IF ~error THEN
-        a := a - b
-    ELSE
-        a := 0
-    END
+        IF ~error THEN
+            a := a - b
+        ELSE
+            a := 0
+        END
 
-    RETURN ~error
-END subInt;
+        RETURN ~error
+    END subInt;
 
 
 PROCEDURE lg2 (x: INTEGER): INTEGER;
-VAR
-    n: INTEGER;
+    VAR
+        n: INTEGER;
 
-BEGIN
-    ASSERT(x > 0);
+    BEGIN
+        ASSERT(x > 0);
 
-    n := UTILS.Log2(x);
-    IF n = -1 THEN
-        n := 255
-    END
+        n := UTILS.Log2(x);
+        IF n = -1 THEN
+            n := 255
+        END
 
-    RETURN n
-END lg2;
+        RETURN n
+    END lg2;
 
 
 PROCEDURE mulInt* (VAR a: INTEGER; b: INTEGER): BOOLEAN;
-VAR
-    error:    BOOLEAN;
-    min, max: INTEGER;
-
-BEGIN
-    min := UTILS.minint;
-    max := UTILS.maxint;
+    VAR
+        error:    BOOLEAN;
+        min, max: INTEGER;
+
+    BEGIN
+        min := UTILS.minint;
+        max := UTILS.maxint;
+
+        IF ((a > 1) & (b > 1)) OR ((a < 0) & (b < 0)) THEN
+            error := (a = min) OR (b = min) OR (ABS(a) > max DIV ABS(b))
+
+        ELSIF ((a > 1) & (b < 0)) OR ((a < 0) & (b > 1)) THEN
+            error := (a = min) OR (b = min);
+            IF ~error THEN
+                IF lg2(ABS(a)) + lg2(ABS(b)) >= UTILS.bit_depth THEN
+                    error := ABS(a) > max DIV ABS(b)
+                END
+            END
 
-    IF ((a > 1) & (b > 1)) OR ((a < 0) & (b < 0)) THEN
-        error := (a = min) OR (b = min) OR (ABS(a) > max DIV ABS(b))
+        ELSE
+            error := FALSE
+        END;
 
-    ELSIF ((a > 1) & (b < 0)) OR ((a < 0) & (b > 1)) THEN
-        error := (a = min) OR (b = min);
         IF ~error THEN
-            IF lg2(ABS(a)) + lg2(ABS(b)) >= UTILS.bit_depth THEN
-                error := ABS(a) > max DIV ABS(b)
-            END
+            a := a * b
+        ELSE
+            a := 0
         END
 
-    ELSE
-        error := FALSE
-    END;
-
-    IF ~error THEN
-        a := a * b
-    ELSE
-        a := 0
-    END
-
-    RETURN ~error
-END mulInt;
+        RETURN ~error
+    END mulInt;
 
 
 PROCEDURE _ASR (x, n: INTEGER): INTEGER;
-    RETURN ASR(UTILS.Long(x), n)
-END _ASR;
+        RETURN ASR(UTILS.Long(x), n)
+    END _ASR;
 
 
 PROCEDURE _LSR (x, n: INTEGER): INTEGER;
-    RETURN UTILS.Long(LSR(UTILS.Short(x), n))
-END _LSR;
+        RETURN UTILS.Long(LSR(UTILS.Short(x), n))
+    END _LSR;
 
 
 PROCEDURE _LSL (x, n: INTEGER): INTEGER;
-    RETURN UTILS.Long(LSL(x, n))
-END _LSL;
+        RETURN UTILS.Long(LSL(x, n))
+    END _LSL;
 
 
 PROCEDURE _ROR1_32 (x: INTEGER): INTEGER;
-BEGIN
-    x := UTILS.Short(x);
-    x := ORD(BITS(LSR(x, 1)) + BITS(LSL(x, 31)))
-    RETURN UTILS.Long(x)
-END _ROR1_32;
+    BEGIN
+        x := UTILS.Short(x);
+        x := ORD(BITS(LSR(x, 1)) + BITS(LSL(x, 31)))
+        RETURN UTILS.Long(x)
+    END _ROR1_32;
 
 
 PROCEDURE _ROR1_16 (x: INTEGER): INTEGER;
-BEGIN
-    x := x MOD 65536;
-    x := ORD(BITS(LSR(x, 1)) + BITS(LSL(x, 15)))
-    RETURN UTILS.Long(x)
-END _ROR1_16;
+    BEGIN
+        x := x MOD 65536;
+        x := ORD(BITS(LSR(x, 1)) + BITS(LSL(x, 15)))
+        RETURN UTILS.Long(x)
+    END _ROR1_16;
 
 
 PROCEDURE _ROR (x, n: INTEGER): INTEGER;
-BEGIN
-
-    CASE UTILS.bit_diff OF
-    |0: x := ROR(x, n)
-    |16, 48:
-        n := n MOD 16;
-        WHILE n > 0 DO
-            x := _ROR1_16(x);
-            DEC(n)
-        END
-    |32:
-        n := n MOD 32;
-        WHILE n > 0 DO
-            x := _ROR1_32(x);
-            DEC(n)
+    BEGIN
+
+        CASE UTILS.bit_diff OF
+        |0: x := ROR(x, n)
+        |16, 48:
+            n := n MOD 16;
+            WHILE n > 0 DO
+                x := _ROR1_16(x);
+                DEC(n)
+            END
+        |32:
+            n := n MOD 32;
+            WHILE n > 0 DO
+                x := _ROR1_32(x);
+                DEC(n)
+            END
         END
-    END
 
-    RETURN x
-END _ROR;
+        RETURN x
+    END _ROR;
 
 
 PROCEDURE opInt* (VAR a: VALUE; b: VALUE; op: CHAR): BOOLEAN;
-VAR
-    success: BOOLEAN;
-
-BEGIN
-    success := TRUE;
-
-    CASE op OF
-    |"+": success := addInt(a.int, b.int)
-    |"-": success := subInt(a.int, b.int)
-    |"*": success := mulInt(a.int, b.int)
-    |"/": success := FALSE
-    |"D": a.int := a.int DIV b.int
-    |"M": a.int := a.int MOD b.int
-    |"L": a.int := _LSL(a.int, b.int)
-    |"A": a.int := _ASR(a.int, b.int)
-    |"O": a.int := _ROR(a.int, b.int)
-    |"R": a.int := _LSR(a.int, b.int)
-    |"m": a.int := MIN(a.int, b.int)
-    |"x": a.int := MAX(a.int, b.int)
-    END;
-    a.typ := tINTEGER
+    VAR
+        success: BOOLEAN;
+
+    BEGIN
+        success := TRUE;
+
+        CASE op OF
+        |"+": success := addInt(a.int, b.int)
+        |"-": success := subInt(a.int, b.int)
+        |"*": success := mulInt(a.int, b.int)
+        |"/": success := FALSE
+        |"D": a.int := a.int DIV b.int
+        |"M": a.int := a.int MOD b.int
+        |"L": a.int := _LSL(a.int, b.int)
+        |"A": a.int := _ASR(a.int, b.int)
+        |"O": a.int := _ROR(a.int, b.int)
+        |"R": a.int := _LSR(a.int, b.int)
+        |"m": a.int := MIN(a.int, b.int)
+        |"x": a.int := MAX(a.int, b.int)
+        END;
+        a.typ := tINTEGER
 
-    RETURN success & check(a)
-END opInt;
+        RETURN success & check(a)
+    END opInt;
 
 
 PROCEDURE charToStr* (c: VALUE; VAR s: ARRAY OF CHAR);
-BEGIN
-    s[0] := CHR(c.int);
-    s[1] := 0X
-END charToStr;
+    BEGIN
+        s[0] := CHR(c.int);
+        s[1] := 0X
+    END charToStr;
 
 
 PROCEDURE opSet* (VAR a: VALUE; b: VALUE; op: CHAR);
-BEGIN
-    CASE op OF
-    |"+": a.set := a.set + b.set
-    |"-": a.set := a.set - b.set
-    |"*": a.set := a.set * b.set
-    |"/": a.set := a.set / b.set
-    END;
-    a.typ := tSET
-END opSet;
+    BEGIN
+        CASE op OF
+        |"+": a.set := a.set + b.set
+        |"-": a.set := a.set - b.set
+        |"*": a.set := a.set * b.set
+        |"/": a.set := a.set / b.set
+        END;
+        a.typ := tSET
+    END opSet;
 
 
 PROCEDURE opFloat* (VAR a: VALUE; b: VALUE; op: CHAR): BOOLEAN;
-BEGIN
-    a.typ := tREAL
-    RETURN opFloat2(a.float, b.float, op) & check(a)
-END opFloat;
+    BEGIN
+        a.typ := tREAL
+        RETURN opFloat2(a.float, b.float, op) & check(a)
+    END opFloat;
 
 
 PROCEDURE ord* (VAR v: VALUE);
-BEGIN
-    CASE v.typ OF
-    |tCHAR, tWCHAR:
-    |tBOOLEAN: v.int := ORD(v.bool)
-    |tSET:     v.int := UTILS.Long(ORD(v.set))
-    END;
-    v.typ := tINTEGER
-END ord;
+    BEGIN
+        CASE v.typ OF
+        |tCHAR, tWCHAR:
+        |tBOOLEAN: v.int := ORD(v.bool)
+        |tSET:     v.int := UTILS.Long(ORD(v.set))
+        END;
+        v.typ := tINTEGER
+    END ord;
 
 
 PROCEDURE odd* (VAR v: VALUE);
-BEGIN
-    v.typ := tBOOLEAN;
-    v.bool := ODD(v.int)
-END odd;
+    BEGIN
+        v.typ := tBOOLEAN;
+        v.bool := ODD(v.int)
+    END odd;
 
 
 PROCEDURE bits* (VAR v: VALUE);
-BEGIN
-    v.typ := tSET;
-    v.set := BITS(v.int)
-END bits;
+    BEGIN
+        v.typ := tSET;
+        v.set := BITS(v.int)
+    END bits;
 
 
 PROCEDURE abs* (VAR v: VALUE): BOOLEAN;
-VAR
-    res: BOOLEAN;
+    VAR
+        res: BOOLEAN;
 
-BEGIN
-    res := FALSE;
-
-    CASE v.typ OF
-    |tREAL:
-        v.float := ABS(v.float);
-        res := TRUE
-    |tINTEGER:
-        IF v.int # UTILS.minint THEN
-            v.int := ABS(v.int);
+    BEGIN
+        res := FALSE;
+
+        CASE v.typ OF
+        |tREAL:
+            v.float := ABS(v.float);
             res := TRUE
+        |tINTEGER:
+            IF v.int # UTILS.minint THEN
+                v.int := ABS(v.int);
+                res := TRUE
+            END
         END
-    END
 
-    RETURN res
-END abs;
+        RETURN res
+    END abs;
 
 
 PROCEDURE floor* (VAR v: VALUE): BOOLEAN;
-VAR
-    res: BOOLEAN;
+    VAR
+        res: BOOLEAN;
 
-BEGIN
-    v.typ := tINTEGER;
-    res := (FLT(UTILS.minint) <= v.float) & (v.float <= FLT(UTILS.maxint));
-    IF res THEN
-        v.int := FLOOR(v.float)
-    END
+    BEGIN
+        v.typ := tINTEGER;
+        res := (FLT(UTILS.minint) <= v.float) & (v.float <= FLT(UTILS.maxint));
+        IF res THEN
+            v.int := FLOOR(v.float)
+        END
 
-    RETURN res
-END floor;
+        RETURN res
+    END floor;
 
 
 PROCEDURE flt* (VAR v: VALUE);
-BEGIN
-    v.typ := tREAL;
-    v.float := FLT(v.int)
-END flt;
+    BEGIN
+        v.typ := tREAL;
+        v.float := FLT(v.int)
+    END flt;
 
 
 PROCEDURE neg* (VAR v: VALUE): BOOLEAN;
-VAR
-    z: VALUE;
-    res: BOOLEAN;
+    VAR
+        z: VALUE;
+        res: BOOLEAN;
 
-BEGIN
-    res := TRUE;
+    BEGIN
+        res := TRUE;
 
-    z.typ := tINTEGER;
-    z.int := 0;
+        z.typ := tINTEGER;
+        z.int := 0;
 
-    CASE v.typ OF
-    |tREAL:     v.float := -v.float
-    |tSET:      v.set := -v.set
-    |tINTEGER:  res := opInt(z, v, "-"); v := z
-    |tBOOLEAN:  v.bool := ~v.bool
-    END
+        CASE v.typ OF
+        |tREAL:     v.float := -v.float
+        |tSET:      v.set := -v.set
+        |tINTEGER:  res := opInt(z, v, "-"); v := z
+        |tBOOLEAN:  v.bool := ~v.bool
+        END
 
-    RETURN res
-END neg;
+        RETURN res
+    END neg;
 
 
 PROCEDURE setbool* (VAR v: VALUE; b: BOOLEAN);
-BEGIN
-    v.bool := b;
-    v.typ := tBOOLEAN
-END setbool;
+    BEGIN
+        v.bool := b;
+        v.typ := tBOOLEAN
+    END setbool;
 
 
 PROCEDURE opBoolean* (VAR a: VALUE; b: VALUE; op: CHAR);
-BEGIN
-    CASE op OF
-    |"&": a.bool := a.bool & b.bool
-    |"|": a.bool := a.bool OR b.bool
-    END;
-    a.typ := tBOOLEAN
-END opBoolean;
+    BEGIN
+        CASE op OF
+        |"&": a.bool := a.bool & b.bool
+        |"|": a.bool := a.bool OR b.bool
+        END;
+        a.typ := tBOOLEAN
+    END opBoolean;
 
 
 PROCEDURE less (v, v2: VALUE; VAR error: INTEGER): BOOLEAN;
-VAR
-    res: BOOLEAN;
-
-BEGIN
-    res := FALSE;
-
-    IF (v.typ = v2.typ) OR (v.typ IN {tCHAR, tWCHAR}) & (v2.typ IN {tCHAR, tWCHAR}) THEN
-        CASE v.typ OF
-        |tINTEGER,
-         tWCHAR,
-         tCHAR:     res := v.int < v2.int
-        |tREAL:     res := v.float < v2.float
-        |tBOOLEAN,
-         tSET:      error := 1
+    VAR
+        res: BOOLEAN;
+
+    BEGIN
+        res := FALSE;
+
+        IF (v.typ = v2.typ) OR (v.typ IN {tCHAR, tWCHAR}) & (v2.typ IN {tCHAR, tWCHAR}) THEN
+            CASE v.typ OF
+            |tINTEGER,
+            tWCHAR,
+            tCHAR:     res := v.int < v2.int
+            |tREAL:     res := v.float < v2.float
+            |tBOOLEAN,
+            tSET:      error := 1
+            END
+        ELSE
+            error := 1
         END
-    ELSE
-        error := 1
-    END
 
-    RETURN res
-END less;
+        RETURN res
+    END less;
 
 
 PROCEDURE equal (v, v2: VALUE; VAR error: INTEGER): BOOLEAN;
-VAR
-    res: BOOLEAN;
-
-BEGIN
-    res := FALSE;
-
-    IF (v.typ = v2.typ) OR (v.typ IN {tCHAR, tWCHAR}) & (v2.typ IN {tCHAR, tWCHAR}) THEN
-        CASE v.typ OF
-        |tINTEGER,
-         tWCHAR,
-         tCHAR:     res := v.int = v2.int
-        |tREAL:     res := v.float = v2.float
-        |tBOOLEAN:  res := v.bool = v2.bool
-        |tSET:      res := v.set = v2.set
+    VAR
+        res: BOOLEAN;
+
+    BEGIN
+        res := FALSE;
+
+        IF (v.typ = v2.typ) OR (v.typ IN {tCHAR, tWCHAR}) & (v2.typ IN {tCHAR, tWCHAR}) THEN
+            CASE v.typ OF
+            |tINTEGER,
+            tWCHAR,
+            tCHAR:     res := v.int = v2.int
+            |tREAL:     res := v.float = v2.float
+            |tBOOLEAN:  res := v.bool = v2.bool
+            |tSET:      res := v.set = v2.set
+            END
+        ELSE
+            error := 1
         END
-    ELSE
-        error := 1
-    END
 
-    RETURN res
-END equal;
+        RETURN res
+    END equal;
 
 
 PROCEDURE relation* (VAR v: VALUE; v2: VALUE; op: INTEGER; VAR error: INTEGER);
-VAR
-    res: BOOLEAN;
-
-BEGIN
-    error := 0;
+    VAR
+        res: BOOLEAN;
 
-    res := FALSE;
+    BEGIN
+        error := 0;
 
-    CASE op OF
+        res := FALSE;
 
-    |opEQ:
-        res := equal(v, v2, error)
+        CASE op OF
 
-    |opNE:
-        res := ~equal(v, v2, error)
+        |opEQ:
+            res := equal(v, v2, error)
 
-    |opLT:
-        res := less(v, v2, error)
+        |opNE:
+            res := ~equal(v, v2, error)
 
-    |opLE:
-        res := less(v, v2, error);
-        IF error = 0 THEN
-            res := equal(v, v2, error) OR res
-        END
+        |opLT:
+            res := less(v, v2, error)
 
-    |opGE:
-        res := ~less(v, v2, error)
-
-    |opGT:
-        res := less(v, v2, error);
-        IF error = 0 THEN
-            res := equal(v, v2, error) OR res
-        END;
-        res := ~res
+        |opLE:
+            res := less(v, v2, error);
+            IF error = 0 THEN
+                res := equal(v, v2, error) OR res
+            END
 
-    |opIN:
-        IF (v.typ = tINTEGER) & (v2.typ = tSET) THEN
-            IF range(v, 0, UTILS.target.maxSet) THEN
-                res := v.int IN v2.set
+        |opGE:
+            res := ~less(v, v2, error)
+
+        |opGT:
+            res := less(v, v2, error);
+            IF error = 0 THEN
+                res := equal(v, v2, error) OR res
+            END;
+            res := ~res
+
+        |opIN:
+            IF (v.typ = tINTEGER) & (v2.typ = tSET) THEN
+                IF range(v, 0, UTILS.target.maxSet) THEN
+                    res := v.int IN v2.set
+                ELSE
+                    error := 2
+                END
             ELSE
-                error := 2
+                error := 1
             END
-        ELSE
-            error := 1
-        END
 
-    END;
+        END;
 
-    IF error = 0 THEN
-        v.bool := res;
-        v.typ  := tBOOLEAN
-    END
+        IF error = 0 THEN
+            v.bool := res;
+            v.typ  := tBOOLEAN
+        END
 
-END relation;
+    END relation;
 
 
 PROCEDURE emptySet* (VAR v: VALUE);
-BEGIN
-    v.typ := tSET;
-    v.set := {}
-END emptySet;
+    BEGIN
+        v.typ := tSET;
+        v.set := {}
+    END emptySet;
 
 
 PROCEDURE constrSet* (VAR v: VALUE; a, b: VALUE);
-BEGIN
-    v.typ := tSET;
-    v.set := {a.int .. b.int}
-END constrSet;
+    BEGIN
+        v.typ := tSET;
+        v.set := {a.int .. b.int}
+    END constrSet;
 
 
 PROCEDURE getInt* (v: VALUE): INTEGER;
-BEGIN
-    ASSERT(check(v))
+    BEGIN
+        ASSERT(check(v))
 
-    RETURN v.int
-END getInt;
+        RETURN v.int
+    END getInt;
 
 
 PROCEDURE setInt* (VAR v: VALUE; i: INTEGER): BOOLEAN;
-BEGIN
-    v.int := i;
-    v.typ := tINTEGER
+    BEGIN
+        v.int := i;
+        v.typ := tINTEGER
 
-    RETURN check(v)
-END setInt;
+        RETURN check(v)
+    END setInt;
 
 
 PROCEDURE concat* (VAR s: ARRAY OF CHAR; s1: ARRAY OF CHAR): BOOLEAN;
-VAR
-    res: BOOLEAN;
+    VAR
+        res: BOOLEAN;
 
-BEGIN
-    res := LENGTH(s) + LENGTH(s1) < LEN(s);
-    IF res THEN
-        STRINGS.append(s, s1)
-    END
+    BEGIN
+        res := LENGTH(s) + LENGTH(s1) < LEN(s);
+        IF res THEN
+            STRINGS.append(s, s1)
+        END
 
-    RETURN res
-END concat;
+        RETURN res
+    END concat;
 
 
 PROCEDURE init;
-VAR
-    i: INTEGER;
+    VAR
+        i: INTEGER;
 
-BEGIN
-    FOR i := 0 TO LEN(digit) - 1 DO
-        digit[i] := -1
-    END;
+    BEGIN
+        FOR i := 0 TO LEN(digit) - 1 DO
+            digit[i] := -1
+        END;
 
-    FOR i := ORD("0") TO ORD("9") DO
-        digit[i] := i - ORD("0")
-    END;
+        FOR i := ORD("0") TO ORD("9") DO
+            digit[i] := i - ORD("0")
+        END;
 
-    FOR i := ORD("A") TO ORD("F") DO
-        digit[i] := i - ORD("A") + 10
-    END
-END init;
+        FOR i := ORD("A") TO ORD("F") DO
+            digit[i] := i - ORD("A") + 10
+        END
+    END init;
 
 
 BEGIN

+ 111 - 118
source/AVLTREES.ob07

@@ -1,11 +1,4 @@
-(*
-    BSD 2-Clause License
-
-    Copyright (c) 2018-2019, Anton Krotov
-    All rights reserved.
-*)
-
-MODULE AVLTREES;
+MODULE AVLTREES;
 
 IMPORT C := COLLECTIONS;
 
@@ -35,161 +28,161 @@ VAR
 
 
 PROCEDURE NewNode (data: DATA): NODE;
-VAR
-    node:  NODE;
-    citem: C.ITEM;
-
-BEGIN
-    citem := C.pop(nodes);
-    IF citem = NIL THEN
-        NEW(node)
-    ELSE
-        node := citem(NODE)
-    END;
+    VAR
+        node:  NODE;
+        citem: C.ITEM;
+
+    BEGIN
+        citem := C.pop(nodes);
+        IF citem = NIL THEN
+            NEW(node)
+        ELSE
+            node := citem(NODE)
+        END;
 
-    node.data := data;
-    node.left := NIL;
-    node.right := NIL;
-    node.height := 1
+        node.data := data;
+        node.left := NIL;
+        node.right := NIL;
+        node.height := 1
 
-    RETURN node
-END NewNode;
+        RETURN node
+    END NewNode;
 
 
 PROCEDURE height (p: NODE): INTEGER;
-VAR
-    res: INTEGER;
+    VAR
+        res: INTEGER;
 
-BEGIN
-    IF p = NIL THEN
-        res := 0
-    ELSE
-        res := p.height
-    END
+    BEGIN
+        IF p = NIL THEN
+            res := 0
+        ELSE
+            res := p.height
+        END
 
-    RETURN res
-END height;
+        RETURN res
+    END height;
 
 
 PROCEDURE bfactor (p: NODE): INTEGER;
-    RETURN height(p.right) - height(p.left)
-END bfactor;
+        RETURN height(p.right) - height(p.left)
+    END bfactor;
 
 
 PROCEDURE fixheight (p: NODE);
-BEGIN
-    p.height := MAX(height(p.left), height(p.right)) + 1
-END fixheight;
+    BEGIN
+        p.height := MAX(height(p.left), height(p.right)) + 1
+    END fixheight;
 
 
 PROCEDURE rotateright (p: NODE): NODE;
-VAR
-    q: NODE;
+    VAR
+        q: NODE;
 
-BEGIN
-    q := p.left;
-    p.left := q.right;
-    q.right := p;
-    fixheight(p);
-    fixheight(q)
+    BEGIN
+        q := p.left;
+        p.left := q.right;
+        q.right := p;
+        fixheight(p);
+        fixheight(q)
 
-    RETURN q
-END rotateright;
+        RETURN q
+    END rotateright;
 
 
 PROCEDURE rotateleft (q: NODE): NODE;
-VAR
-    p: NODE;
+    VAR
+        p: NODE;
 
-BEGIN
-    p := q.right;
-    q.right := p.left;
-    p.left := q;
-    fixheight(q);
-    fixheight(p)
+    BEGIN
+        p := q.right;
+        q.right := p.left;
+        p.left := q;
+        fixheight(q);
+        fixheight(p)
 
-    RETURN p
-END rotateleft;
+        RETURN p
+    END rotateleft;
 
 
 PROCEDURE balance (p: NODE): NODE;
-VAR
-    res: NODE;
+    VAR
+        res: NODE;
 
-BEGIN
-    fixheight(p);
+    BEGIN
+        fixheight(p);
 
-    IF bfactor(p) = 2 THEN
-        IF bfactor(p.right) < 0 THEN
-            p.right := rotateright(p.right)
-        END;
-        res := rotateleft(p)
+        IF bfactor(p) = 2 THEN
+            IF bfactor(p.right) < 0 THEN
+                p.right := rotateright(p.right)
+            END;
+            res := rotateleft(p)
 
-    ELSIF bfactor(p) = -2 THEN
-        IF bfactor(p.left) > 0 THEN
-            p.left := rotateleft(p.left)
-        END;
-        res := rotateright(p)
+        ELSIF bfactor(p) = -2 THEN
+            IF bfactor(p.left) > 0 THEN
+                p.left := rotateleft(p.left)
+            END;
+            res := rotateright(p)
 
-    ELSE
-        res := p
-    END
+        ELSE
+            res := p
+        END
 
-    RETURN res
-END balance;
+        RETURN res
+    END balance;
 
 
 PROCEDURE insert* (p: NODE; data: DATA; cmp: CMP; VAR newnode: BOOLEAN; VAR node: NODE): NODE;
-VAR
-    res: NODE;
-    rescmp: INTEGER;
+    VAR
+        res: NODE;
+        rescmp: INTEGER;
 
-BEGIN
-    IF p = NIL THEN
-        res := NewNode(data);
-        node := res;
-        newnode := TRUE
-    ELSE
-
-        rescmp := cmp(data, p.data);
-        IF rescmp < 0 THEN
-            p.left := insert(p.left, data, cmp, newnode, node);
-            res := balance(p)
-        ELSIF rescmp > 0 THEN
-            p.right := insert(p.right, data, cmp, newnode, node);
-            res := balance(p)
-        ELSE
-            res := p;
+    BEGIN
+        IF p = NIL THEN
+            res := NewNode(data);
             node := res;
-            newnode := FALSE
-        END
+            newnode := TRUE
+        ELSE
 
-    END
+            rescmp := cmp(data, p.data);
+            IF rescmp < 0 THEN
+                p.left := insert(p.left, data, cmp, newnode, node);
+                res := balance(p)
+            ELSIF rescmp > 0 THEN
+                p.right := insert(p.right, data, cmp, newnode, node);
+                res := balance(p)
+            ELSE
+                res := p;
+                node := res;
+                newnode := FALSE
+            END
+
+        END
 
-    RETURN res
-END insert;
+        RETURN res
+    END insert;
 
 
 PROCEDURE destroy* (VAR node: NODE; destructor: DESTRUCTOR);
-VAR
-    left, right: NODE;
+    VAR
+        left, right: NODE;
 
-BEGIN
-    IF node # NIL THEN
-        left  := node.left;
-        right := node.right;
+    BEGIN
+        IF node # NIL THEN
+            left  := node.left;
+            right := node.right;
 
-        IF destructor # NIL THEN
-            destructor(node.data)
-        END;
+            IF destructor # NIL THEN
+                destructor(node.data)
+            END;
 
-        C.push(nodes, node);
-        node := NIL;
+            C.push(nodes, node);
+            node := NIL;
 
-        destroy(left, destructor);
-        destroy(right, destructor)
-    END
-END destroy;
+            destroy(left, destructor);
+            destroy(right, destructor)
+        END
+    END destroy;
 
 
 BEGIN

+ 210 - 217
source/BIN.ob07

@@ -1,11 +1,4 @@
-(*
-    BSD 2-Clause License
-
-    Copyright (c) 2018-2020, Anton Krotov
-    All rights reserved.
-*)
-
-MODULE BIN;
+MODULE BIN;
 
 IMPORT LISTS, CHL := CHUNKLISTS, ARITH, UTILS;
 
@@ -66,319 +59,319 @@ TYPE
 
 
 PROCEDURE create* (NumberOfLabels: INTEGER): PROGRAM;
-VAR
-    program:  PROGRAM;
-    i:        INTEGER;
+    VAR
+        program:  PROGRAM;
+        i:        INTEGER;
 
-BEGIN
-    NEW(program);
+    BEGIN
+        NEW(program);
 
-    program.bss := 0;
+        program.bss := 0;
 
-    program.labels := CHL.CreateIntList();
-    FOR i := 0 TO NumberOfLabels - 1 DO
-        CHL.PushInt(program.labels, 0)
-    END;
+        program.labels := CHL.CreateIntList();
+        FOR i := 0 TO NumberOfLabels - 1 DO
+            CHL.PushInt(program.labels, 0)
+        END;
 
-    program.rel_list := LISTS.create(NIL);
-    program.imp_list := LISTS.create(NIL);
-    program.exp_list := LISTS.create(NIL);
+        program.rel_list := LISTS.create(NIL);
+        program.imp_list := LISTS.create(NIL);
+        program.exp_list := LISTS.create(NIL);
 
-    program.data    := CHL.CreateByteList();
-    program.code    := CHL.CreateByteList();
-    program._import := CHL.CreateByteList();
-    program.export  := CHL.CreateByteList()
+        program.data    := CHL.CreateByteList();
+        program.code    := CHL.CreateByteList();
+        program._import := CHL.CreateByteList();
+        program.export  := CHL.CreateByteList()
 
-    RETURN program
-END create;
+        RETURN program
+    END create;
 
 
 PROCEDURE SetParams* (program: PROGRAM; bss, stack: INTEGER; vmajor, vminor: WCHAR);
-BEGIN
-    program.bss    := bss;
-    program.stack  := stack;
-    program.vmajor := vmajor;
-    program.vminor := vminor
-END SetParams;
+    BEGIN
+        program.bss    := bss;
+        program.stack  := stack;
+        program.vmajor := vmajor;
+        program.vminor := vminor
+    END SetParams;
 
 
 PROCEDURE PutReloc* (program: PROGRAM; opcode: INTEGER);
-VAR
-    cmd: RELOC;
+    VAR
+        cmd: RELOC;
 
-BEGIN
-    NEW(cmd);
-    cmd.opcode := opcode;
-    cmd.offset := CHL.Length(program.code);
-    LISTS.push(program.rel_list, cmd)
-END PutReloc;
+    BEGIN
+        NEW(cmd);
+        cmd.opcode := opcode;
+        cmd.offset := CHL.Length(program.code);
+        LISTS.push(program.rel_list, cmd)
+    END PutReloc;
 
 
 PROCEDURE PutData* (program: PROGRAM; b: BYTE);
-BEGIN
-    CHL.PushByte(program.data, b)
-END PutData;
+    BEGIN
+        CHL.PushByte(program.data, b)
+    END PutData;
 
 
 PROCEDURE get32le* (_array: CHL.BYTELIST; idx: INTEGER): INTEGER;
-VAR
-    i: INTEGER;
-    x: INTEGER;
+    VAR
+        i: INTEGER;
+        x: INTEGER;
 
-BEGIN
-    x := 0;
+    BEGIN
+        x := 0;
 
-    FOR i := 3 TO 0 BY -1 DO
-        x := LSL(x, 8) + CHL.GetByte(_array, idx + i)
-    END;
+        FOR i := 3 TO 0 BY -1 DO
+            x := LSL(x, 8) + CHL.GetByte(_array, idx + i)
+        END;
 
-    IF UTILS.bit_depth = 64 THEN
-        x := LSL(x, 16);
-        x := LSL(x, 16);
-        x := ASR(x, 16);
-        x := ASR(x, 16)
-    END
+        IF UTILS.bit_depth = 64 THEN
+            x := LSL(x, 16);
+            x := LSL(x, 16);
+            x := ASR(x, 16);
+            x := ASR(x, 16)
+        END
 
-    RETURN x
-END get32le;
+        RETURN x
+    END get32le;
 
 
 PROCEDURE put32le* (_array: CHL.BYTELIST; idx: INTEGER; x: INTEGER);
-VAR
-    i: INTEGER;
+    VAR
+        i: INTEGER;
 
-BEGIN
-    FOR i := 0 TO 3 DO
-        CHL.SetByte(_array, idx + i, UTILS.Byte(x, i))
-    END
-END put32le;
+    BEGIN
+        FOR i := 0 TO 3 DO
+            CHL.SetByte(_array, idx + i, UTILS.Byte(x, i))
+        END
+    END put32le;
 
 
 PROCEDURE PutData32LE* (program: PROGRAM; x: INTEGER);
-VAR
-    i: INTEGER;
+    VAR
+        i: INTEGER;
 
-BEGIN
-    FOR i := 0 TO 3 DO
-        CHL.PushByte(program.data, UTILS.Byte(x, i))
-    END
-END PutData32LE;
+    BEGIN
+        FOR i := 0 TO 3 DO
+            CHL.PushByte(program.data, UTILS.Byte(x, i))
+        END
+    END PutData32LE;
 
 
 PROCEDURE PutData64LE* (program: PROGRAM; x: INTEGER);
-VAR
-    i: INTEGER;
+    VAR
+        i: INTEGER;
 
-BEGIN
-    FOR i := 0 TO 7 DO
-        CHL.PushByte(program.data, UTILS.Byte(x, i))
-    END
-END PutData64LE;
+    BEGIN
+        FOR i := 0 TO 7 DO
+            CHL.PushByte(program.data, UTILS.Byte(x, i))
+        END
+    END PutData64LE;
 
 
 PROCEDURE PutDataStr* (program: PROGRAM; s: ARRAY OF CHAR);
-VAR
-    i: INTEGER;
+    VAR
+        i: INTEGER;
 
-BEGIN
-    i := 0;
-    WHILE s[i] # 0X DO
-        PutData(program, ORD(s[i]));
-        INC(i)
-    END
-END PutDataStr;
+    BEGIN
+        i := 0;
+        WHILE s[i] # 0X DO
+            PutData(program, ORD(s[i]));
+            INC(i)
+        END
+    END PutDataStr;
 
 
 PROCEDURE PutCode* (program: PROGRAM; b: BYTE);
-BEGIN
-    CHL.PushByte(program.code, b)
-END PutCode;
+    BEGIN
+        CHL.PushByte(program.code, b)
+    END PutCode;
 
 
 PROCEDURE PutCode32LE* (program: PROGRAM; x: INTEGER);
-VAR
-    i: INTEGER;
+    VAR
+        i: INTEGER;
 
-BEGIN
-    FOR i := 0 TO 3 DO
-        CHL.PushByte(program.code, UTILS.Byte(x, i))
-    END
-END PutCode32LE;
+    BEGIN
+        FOR i := 0 TO 3 DO
+            CHL.PushByte(program.code, UTILS.Byte(x, i))
+        END
+    END PutCode32LE;
 
 
 PROCEDURE PutCode16LE* (program: PROGRAM; x: INTEGER);
-BEGIN
-    CHL.PushByte(program.code, UTILS.Byte(x, 0));
-    CHL.PushByte(program.code, UTILS.Byte(x, 1))
-END PutCode16LE;
+    BEGIN
+        CHL.PushByte(program.code, UTILS.Byte(x, 0));
+        CHL.PushByte(program.code, UTILS.Byte(x, 1))
+    END PutCode16LE;
 
 
 PROCEDURE SetLabel* (program: PROGRAM; label, offset: INTEGER);
-BEGIN
-    CHL.SetInt(program.labels, label, offset)
-END SetLabel;
+    BEGIN
+        CHL.SetInt(program.labels, label, offset)
+    END SetLabel;
 
 
 PROCEDURE Import* (program: PROGRAM; name: ARRAY OF CHAR; label: INTEGER);
-VAR
-    imp: IMPRT;
+    VAR
+        imp: IMPRT;
 
-BEGIN
-    CHL.PushByte(program._import, 0);
-    CHL.PushByte(program._import, 0);
+    BEGIN
+        CHL.PushByte(program._import, 0);
+        CHL.PushByte(program._import, 0);
 
-    IF ODD(CHL.Length(program._import)) THEN
-        CHL.PushByte(program._import, 0)
-    END;
+        IF ODD(CHL.Length(program._import)) THEN
+            CHL.PushByte(program._import, 0)
+        END;
 
-    NEW(imp);
-    imp.nameoffs := CHL.PushStr(program._import, name);
-    imp.label := label;
-    LISTS.push(program.imp_list, imp)
-END Import;
+        NEW(imp);
+        imp.nameoffs := CHL.PushStr(program._import, name);
+        imp.label := label;
+        LISTS.push(program.imp_list, imp)
+    END Import;
 
 
 PROCEDURE less (bytes: CHL.BYTELIST; a, b: EXPRT): BOOLEAN;
-VAR
-    i, j: INTEGER;
+    VAR
+        i, j: INTEGER;
 
-BEGIN
-    i := a.nameoffs;
-    j := b.nameoffs;
+    BEGIN
+        i := a.nameoffs;
+        j := b.nameoffs;
 
-    WHILE (CHL.GetByte(bytes, i) # 0) & (CHL.GetByte(bytes, j) # 0) &
-          (CHL.GetByte(bytes, i) = CHL.GetByte(bytes, j)) DO
-        INC(i);
-        INC(j)
-    END
+        WHILE (CHL.GetByte(bytes, i) # 0) & (CHL.GetByte(bytes, j) # 0) &
+            (CHL.GetByte(bytes, i) = CHL.GetByte(bytes, j)) DO
+            INC(i);
+            INC(j)
+        END
 
-    RETURN CHL.GetByte(bytes, i) < CHL.GetByte(bytes, j)
-END less;
+        RETURN CHL.GetByte(bytes, i) < CHL.GetByte(bytes, j)
+    END less;
 
 
 PROCEDURE Export* (program: PROGRAM; name: ARRAY OF CHAR; label: INTEGER);
-VAR
-    exp, cur: EXPRT;
+    VAR
+        exp, cur: EXPRT;
 
-BEGIN
-    NEW(exp);
-    exp.label := CHL.GetInt(program.labels, label);
-    exp.nameoffs := CHL.PushStr(program.export, name);
+    BEGIN
+        NEW(exp);
+        exp.label := CHL.GetInt(program.labels, label);
+        exp.nameoffs := CHL.PushStr(program.export, name);
 
-    cur := program.exp_list.first(EXPRT);
-    WHILE (cur # NIL) & less(program.export, cur, exp) DO
-        cur := cur.next(EXPRT)
-    END;
+        cur := program.exp_list.first(EXPRT);
+        WHILE (cur # NIL) & less(program.export, cur, exp) DO
+            cur := cur.next(EXPRT)
+        END;
 
-    IF cur # NIL THEN
-        IF cur.prev # NIL THEN
-            LISTS.insert(program.exp_list, cur.prev, exp)
+        IF cur # NIL THEN
+            IF cur.prev # NIL THEN
+                LISTS.insert(program.exp_list, cur.prev, exp)
+            ELSE
+                LISTS.insertL(program.exp_list, cur, exp)
+            END
         ELSE
-            LISTS.insertL(program.exp_list, cur, exp)
+            LISTS.push(program.exp_list, exp)
         END
-    ELSE
-        LISTS.push(program.exp_list, exp)
-    END
 
-END Export;
+    END Export;
 
 
 PROCEDURE GetIProc* (program: PROGRAM; n: INTEGER): IMPRT;
-VAR
-    _import, res: IMPRT;
-
-BEGIN
-    _import  := program.imp_list.first(IMPRT);
+    VAR
+        _import, res: IMPRT;
 
-    res := NIL;
-    WHILE (_import # NIL) & (n >= 0) DO
-        IF _import.label # 0 THEN
-            res := _import;
-            DEC(n)
+    BEGIN
+        _import  := program.imp_list.first(IMPRT);
+
+        res := NIL;
+        WHILE (_import # NIL) & (n >= 0) DO
+            IF _import.label # 0 THEN
+                res := _import;
+                DEC(n)
+            END;
+            _import := _import.next(IMPRT)
         END;
-        _import := _import.next(IMPRT)
-    END;
 
-    ASSERT(n = -1)
-    RETURN res
-END GetIProc;
+        ASSERT(n = -1)
+        RETURN res
+    END GetIProc;
 
 
 PROCEDURE GetLabel* (program: PROGRAM; label: INTEGER): INTEGER;
-    RETURN CHL.GetInt(program.labels, label)
-END GetLabel;
+        RETURN CHL.GetInt(program.labels, label)
+    END GetLabel;
 
 
 PROCEDURE NewLabel* (program: PROGRAM);
-BEGIN
-    CHL.PushInt(program.labels, 0)
-END NewLabel;
+    BEGIN
+        CHL.PushInt(program.labels, 0)
+    END NewLabel;
 
 
 PROCEDURE fixup* (program: PROGRAM);
-VAR
-    rel:    RELOC;
-    imp:    IMPRT;
-    nproc:  INTEGER;
-    L:      INTEGER;
-
-BEGIN
-
-    nproc := 0;
-    imp := program.imp_list.first(IMPRT);
-    WHILE imp # NIL DO
-        IF imp.label # 0 THEN
-            CHL.SetInt(program.labels, imp.label, nproc);
-            INC(nproc)
-        END;
-        imp := imp.next(IMPRT)
-    END;
+    VAR
+        rel:    RELOC;
+        imp:    IMPRT;
+        nproc:  INTEGER;
+        L:      INTEGER;
 
-    rel := program.rel_list.first(RELOC);
-    WHILE rel # NIL DO
+    BEGIN
 
-        IF rel.opcode IN {RIMP, PICIMP} THEN
-            L := get32le(program.code, rel.offset);
-            put32le(program.code, rel.offset, GetLabel(program, L))
+        nproc := 0;
+        imp := program.imp_list.first(IMPRT);
+        WHILE imp # NIL DO
+            IF imp.label # 0 THEN
+                CHL.SetInt(program.labels, imp.label, nproc);
+                INC(nproc)
+            END;
+            imp := imp.next(IMPRT)
         END;
 
-        rel := rel.next(RELOC)
-    END
+        rel := program.rel_list.first(RELOC);
+        WHILE rel # NIL DO
 
-END fixup;
+            IF rel.opcode IN {RIMP, PICIMP} THEN
+                L := get32le(program.code, rel.offset);
+                put32le(program.code, rel.offset, GetLabel(program, L))
+            END;
 
+            rel := rel.next(RELOC)
+        END
 
-PROCEDURE InitArray* (VAR _array: ARRAY OF BYTE; VAR idx: INTEGER; hex: ARRAY OF CHAR);
-VAR
-    i, k: INTEGER;
+    END fixup;
 
 
-    PROCEDURE hexdgt (dgt: CHAR): INTEGER;
+PROCEDURE InitArray* (VAR _array: ARRAY OF BYTE; VAR idx: INTEGER; hex: ARRAY OF CHAR);
     VAR
-        res: INTEGER;
+        i, k: INTEGER;
 
-    BEGIN
-        IF dgt < "A" THEN
-            res := ORD(dgt) - ORD("0")
-        ELSE
-            res := ORD(dgt) - ORD("A") + 10
-        END
 
-        RETURN res
-    END hexdgt;
+        PROCEDURE hexdgt (dgt: CHAR): INTEGER;
+        VAR
+            res: INTEGER;
 
+        BEGIN
+            IF dgt < "A" THEN
+                res := ORD(dgt) - ORD("0")
+            ELSE
+                res := ORD(dgt) - ORD("A") + 10
+            END
 
-BEGIN
-    k := LENGTH(hex);
-    ASSERT(~ODD(k));
-    k := k DIV 2;
+            RETURN res
+        END hexdgt;
 
-    FOR i := 0 TO k - 1 DO
-        _array[i + idx] := hexdgt(hex[2 * i]) * 16 + hexdgt(hex[2 * i + 1])
-    END;
 
-    INC(idx, k)
-END InitArray;
+    BEGIN
+        k := LENGTH(hex);
+        ASSERT(~ODD(k));
+        k := k DIV 2;
+
+        FOR i := 0 TO k - 1 DO
+            _array[i + idx] := hexdgt(hex[2 * i]) * 16 + hexdgt(hex[2 * i + 1])
+        END;
+
+        INC(idx, k)
+    END InitArray;
 
 
 END BIN.

+ 143 - 151
source/CHUNKLISTS.ob07

@@ -1,11 +1,4 @@
-(*
-    BSD 2-Clause License
-
-    Copyright (c) 2018-2021, Anton Krotov
-    All rights reserved.
-*)
-
-MODULE CHUNKLISTS;
+MODULE CHUNKLISTS;
 
 IMPORT LISTS, WR := WRITER;
 
@@ -45,211 +38,210 @@ TYPE
 
 
 PROCEDURE SetByte* (list: BYTELIST; idx: INTEGER; byte: BYTE);
-VAR
-    chunk: BYTECHUNK;
-    item:  LISTS.ITEM;
+    VAR
+        chunk: BYTECHUNK;
+        item:  LISTS.ITEM;
 
-BEGIN
-    ASSERT(idx >= 0);
-    ASSERT(list # NIL);
+    BEGIN
+        ASSERT(idx >= 0);
+        ASSERT(list # NIL);
 
-    item := LISTS.getidx(list, idx DIV LENOFBYTECHUNK);
-    ASSERT(item # NIL);
-    chunk := item(BYTECHUNK);
-    idx := idx MOD LENOFBYTECHUNK;
-    ASSERT(idx < chunk.count);
-    chunk.data[idx] := byte
-END SetByte;
+        item := LISTS.getidx(list, idx DIV LENOFBYTECHUNK);
+        ASSERT(item # NIL);
+        chunk := item(BYTECHUNK);
+        idx := idx MOD LENOFBYTECHUNK;
+        ASSERT(idx < chunk.count);
+        chunk.data[idx] := byte
+    END SetByte;
 
 
 PROCEDURE GetByte* (list: BYTELIST; idx: INTEGER): BYTE;
-VAR
-    chunk: BYTECHUNK;
-    item:  LISTS.ITEM;
+    VAR
+        chunk: BYTECHUNK;
+        item:  LISTS.ITEM;
 
-BEGIN
-    ASSERT(idx >= 0);
-    ASSERT(list # NIL);
+    BEGIN
+        ASSERT(idx >= 0);
+        ASSERT(list # NIL);
 
-    item := LISTS.getidx(list, idx DIV LENOFBYTECHUNK);
-    ASSERT(item # NIL);
-    chunk := item(BYTECHUNK);
-    idx := idx MOD LENOFBYTECHUNK;
-    ASSERT(idx < chunk.count)
-    RETURN chunk.data[idx]
-END GetByte;
+        item := LISTS.getidx(list, idx DIV LENOFBYTECHUNK);
+        ASSERT(item # NIL);
+        chunk := item(BYTECHUNK);
+        idx := idx MOD LENOFBYTECHUNK;
+        ASSERT(idx < chunk.count)
+        RETURN chunk.data[idx]
+    END GetByte;
 
 
 PROCEDURE PushByte* (list: BYTELIST; byte: BYTE);
-VAR
-    chunk: BYTECHUNK;
+    VAR
+        chunk: BYTECHUNK;
 
-BEGIN
-    ASSERT(list # NIL);
+    BEGIN
+        ASSERT(list # NIL);
 
-    chunk := list.last(BYTECHUNK);
+        chunk := list.last(BYTECHUNK);
 
-    IF chunk.count = LENOFBYTECHUNK THEN
-        NEW(chunk);
-        chunk.count := 0;
-        LISTS.push(list, chunk)
-    END;
+        IF chunk.count = LENOFBYTECHUNK THEN
+            NEW(chunk);
+            chunk.count := 0;
+            LISTS.push(list, chunk)
+        END;
 
-    chunk.data[chunk.count] := byte;
-    INC(chunk.count);
+        chunk.data[chunk.count] := byte;
+        INC(chunk.count);
 
-    INC(list.length)
-END PushByte;
+        INC(list.length)
+    END PushByte;
 
 
 PROCEDURE PushStr* (list: BYTELIST; str: ARRAY OF CHAR): INTEGER;
-VAR
-    i, res: INTEGER;
+    VAR
+        i, res: INTEGER;
 
-BEGIN
-    res := list.length;
-    i := 0;
-    REPEAT
-        PushByte(list, ORD(str[i]));
-        INC(i)
-    UNTIL str[i - 1] = 0X
+    BEGIN
+        res := list.length;
+        i := 0;
+        REPEAT
+            PushByte(list, ORD(str[i]));
+            INC(i)
+        UNTIL str[i - 1] = 0X
 
-    RETURN res
-END PushStr;
+        RETURN res
+    END PushStr;
 
 
 PROCEDURE GetStr* (list: BYTELIST; pos: INTEGER; VAR str: ARRAY OF CHAR): BOOLEAN;
-VAR
-    i:   INTEGER;
-    res: BOOLEAN;
+    VAR
+        i:   INTEGER;
+        res: BOOLEAN;
 
-BEGIN
-    res := FALSE;
-    i := 0;
-    WHILE (pos < list.length) & (i < LEN(str)) & ~res DO
-        str[i] := CHR(GetByte(list, pos));
-        res := str[i] = 0X;
-        INC(pos);
-        INC(i)
-    END
+    BEGIN
+        res := FALSE;
+        i := 0;
+        WHILE (pos < list.length) & (i < LEN(str)) & ~res DO
+            str[i] := CHR(GetByte(list, pos));
+            res := str[i] = 0X;
+            INC(pos);
+            INC(i)
+        END
 
-    RETURN res
-END GetStr;
+        RETURN res
+    END GetStr;
 
 
 PROCEDURE WriteToFile* (list: BYTELIST);
-VAR
-    chunk: BYTECHUNK;
+    VAR
+        chunk: BYTECHUNK;
 
-BEGIN
-    chunk := list.first(BYTECHUNK);
-    WHILE chunk # NIL DO
-        WR.Write(chunk.data, chunk.count);
-        chunk := chunk.next(BYTECHUNK)
-    END
-END WriteToFile;
+    BEGIN
+        chunk := list.first(BYTECHUNK);
+        WHILE chunk # NIL DO
+            WR.Write(chunk.data, chunk.count);
+            chunk := chunk.next(BYTECHUNK)
+        END
+    END WriteToFile;
 
 
 PROCEDURE CreateByteList* (): BYTELIST;
-VAR
-    bytelist: BYTELIST;
-    list:     LISTS.LIST;
-    chunk:    BYTECHUNK;
+    VAR
+        bytelist: BYTELIST;
+        list:     LISTS.LIST;
+        chunk:    BYTECHUNK;
 
-BEGIN
-    NEW(bytelist);
-    list := LISTS.create(bytelist);
-    bytelist.length := 0;
+    BEGIN
+        NEW(bytelist);
+        list := LISTS.create(bytelist);
+        bytelist.length := 0;
 
-    NEW(chunk);
-    chunk.count := 0;
-    LISTS.push(list, chunk)
+        NEW(chunk);
+        chunk.count := 0;
+        LISTS.push(list, chunk)
 
-    RETURN list(BYTELIST)
-END CreateByteList;
+        RETURN list(BYTELIST)
+    END CreateByteList;
 
 
 PROCEDURE SetInt* (list: INTLIST; idx: INTEGER; int: INTEGER);
-VAR
-    chunk: INTCHUNK;
-    item:  LISTS.ITEM;
+    VAR
+        chunk: INTCHUNK;
+        item:  LISTS.ITEM;
 
-BEGIN
-    ASSERT(idx >= 0);
-    ASSERT(list # NIL);
+    BEGIN
+        ASSERT(idx >= 0);
+        ASSERT(list # NIL);
 
-    item := LISTS.getidx(list, idx DIV LENOFINTCHUNK);
-    ASSERT(item # NIL);
-    chunk := item(INTCHUNK);
-    idx := idx MOD LENOFINTCHUNK;
-    ASSERT(idx < chunk.count);
-    chunk.data[idx] := int
-END SetInt;
+        item := LISTS.getidx(list, idx DIV LENOFINTCHUNK);
+        ASSERT(item # NIL);
+        chunk := item(INTCHUNK);
+        idx := idx MOD LENOFINTCHUNK;
+        ASSERT(idx < chunk.count);
+        chunk.data[idx] := int
+    END SetInt;
 
 
 PROCEDURE GetInt* (list: INTLIST; idx: INTEGER): INTEGER;
+    VAR
+        chunk: INTCHUNK;
+        item:  LISTS.ITEM;
 
-VAR
-    chunk: INTCHUNK;
-    item:  LISTS.ITEM;
+    BEGIN
+        ASSERT(idx >= 0);
+        ASSERT(list # NIL);
 
-BEGIN
-    ASSERT(idx >= 0);
-    ASSERT(list # NIL);
-
-    item := LISTS.getidx(list, idx DIV LENOFINTCHUNK);
-    ASSERT(item # NIL);
-    chunk := item(INTCHUNK);
-    idx := idx MOD LENOFINTCHUNK;
-    ASSERT(idx < chunk.count)
-    RETURN chunk.data[idx]
-END GetInt;
+        item := LISTS.getidx(list, idx DIV LENOFINTCHUNK);
+        ASSERT(item # NIL);
+        chunk := item(INTCHUNK);
+        idx := idx MOD LENOFINTCHUNK;
+        ASSERT(idx < chunk.count)
+        RETURN chunk.data[idx]
+    END GetInt;
 
 
 PROCEDURE PushInt* (list: INTLIST; int: INTEGER);
-VAR
-    chunk: INTCHUNK;
+    VAR
+        chunk: INTCHUNK;
 
-BEGIN
-    ASSERT(list # NIL);
+    BEGIN
+        ASSERT(list # NIL);
 
-    chunk := list.last(INTCHUNK);
+        chunk := list.last(INTCHUNK);
 
-    IF chunk.count = LENOFINTCHUNK THEN
-        NEW(chunk);
-        chunk.count := 0;
-        LISTS.push(list, chunk)
-    END;
+        IF chunk.count = LENOFINTCHUNK THEN
+            NEW(chunk);
+            chunk.count := 0;
+            LISTS.push(list, chunk)
+        END;
 
-    chunk.data[chunk.count] := int;
-    INC(chunk.count);
+        chunk.data[chunk.count] := int;
+        INC(chunk.count);
 
-    INC(list.length)
-END PushInt;
+        INC(list.length)
+    END PushInt;
 
 
 PROCEDURE CreateIntList* (): INTLIST;
-VAR
-    intlist:  INTLIST;
-    list:     LISTS.LIST;
-    chunk:    INTCHUNK;
+    VAR
+        intlist:  INTLIST;
+        list:     LISTS.LIST;
+        chunk:    INTCHUNK;
 
-BEGIN
-    NEW(intlist);
-    list := LISTS.create(intlist);
-    intlist.length := 0;
+    BEGIN
+        NEW(intlist);
+        list := LISTS.create(intlist);
+        intlist.length := 0;
 
-    NEW(chunk);
-    chunk.count := 0;
-    LISTS.push(list, chunk)
+        NEW(chunk);
+        chunk.count := 0;
+        LISTS.push(list, chunk)
 
-    RETURN list(INTLIST)
-END CreateIntList;
+        RETURN list(INTLIST)
+    END CreateIntList;
 
 
 PROCEDURE Length* (list: ANYLIST): INTEGER;
-    RETURN list.length
-END Length;
+        RETURN list.length
+    END Length;
 
 
 END CHUNKLISTS.

+ 21 - 28
source/COLLECTIONS.ob07

@@ -1,11 +1,4 @@
-(*
-    BSD 2-Clause License
-
-    Copyright (c) 2018-2019, Anton Krotov
-    All rights reserved.
-*)
-
-MODULE COLLECTIONS;
+MODULE COLLECTIONS;
 
 
 TYPE
@@ -24,36 +17,36 @@ TYPE
 
 
 PROCEDURE push* (collection: COLLECTION; item: ITEM);
-BEGIN
-    item.link := collection.last;
-    collection.last := item
-END push;
+    BEGIN
+        item.link := collection.last;
+        collection.last := item
+    END push;
 
 
 PROCEDURE pop* (collection: COLLECTION): ITEM;
-VAR
-    item: ITEM;
+    VAR
+        item: ITEM;
 
-BEGIN
-    item := collection.last;
-    IF item # NIL THEN
-        collection.last := item.link
-    END
+    BEGIN
+        item := collection.last;
+        IF item # NIL THEN
+            collection.last := item.link
+        END
 
-    RETURN item
-END pop;
+        RETURN item
+    END pop;
 
 
 PROCEDURE create* (): COLLECTION;
-VAR
-    collection: COLLECTION;
+    VAR
+        collection: COLLECTION;
 
-BEGIN
-    NEW(collection);
-    collection.last := NIL
+    BEGIN
+        NEW(collection);
+        collection.last := NIL
 
-    RETURN collection
-END create;
+        RETURN collection
+    END create;
 
 
 END COLLECTIONS.

+ 40 - 47
source/CONSOLE.ob07

@@ -1,78 +1,71 @@
-(*
-    BSD 2-Clause License
-
-    Copyright (c) 2018-2021, Anton Krotov
-    All rights reserved.
-*)
-
-MODULE CONSOLE;
+MODULE CONSOLE;
 
 IMPORT UTILS, STRINGS;
 
 
 PROCEDURE String* (s: ARRAY OF CHAR);
-VAR
-    i: INTEGER;
+    VAR
+        i: INTEGER;
 
-BEGIN
-    i := 0;
-    WHILE (i < LEN(s)) & (s[i] # 0X) DO
-        UTILS.OutChar(s[i]);
-        INC(i)
-    END
-END String;
+    BEGIN
+        i := 0;
+        WHILE (i < LEN(s)) & (s[i] # 0X) DO
+            UTILS.OutChar(s[i]);
+            INC(i)
+        END
+    END String;
 
 
 PROCEDURE Int* (x: INTEGER);
-VAR
-    s: ARRAY 24 OF CHAR;
+    VAR
+        s: ARRAY 24 OF CHAR;
 
-BEGIN
-    STRINGS.IntToStr(x, s);
-    String(s)
-END Int;
+    BEGIN
+        STRINGS.IntToStr(x, s);
+        String(s)
+    END Int;
 
 
 PROCEDURE Int2* (x: INTEGER);
-BEGIN
-    IF x < 10 THEN
-        String("0")
-    END;
-    Int(x)
-END Int2;
+    BEGIN
+        IF x < 10 THEN
+            String("0")
+        END;
+        Int(x)
+    END Int2;
 
 
 PROCEDURE Ln*;
-BEGIN
-    String(UTILS.eol)
-END Ln;
+    BEGIN
+        String(UTILS.eol)
+    END Ln;
 
 
 PROCEDURE StringLn* (s: ARRAY OF CHAR);
-BEGIN
-    String(s);
-    Ln
-END StringLn;
+    BEGIN
+        String(s);
+        Ln
+    END StringLn;
 
 
 PROCEDURE IntLn* (x: INTEGER);
-BEGIN
-    Int(x);
-    Ln
-END IntLn;
+    BEGIN
+        Int(x);
+        Ln
+    END IntLn;
 
 
 PROCEDURE Int2Ln* (x: INTEGER);
-BEGIN
-    Int2(x);
-    Ln
-END Int2Ln;
+    BEGIN
+        Int2(x);
+        Ln
+    END Int2Ln;
 
 
 PROCEDURE Dashes*;
-BEGIN
-    StringLn("------------------------------------------------")
-END Dashes;
+    BEGIN
+        StringLn("------------------------------------------------")
+    END Dashes;
 
 
 END CONSOLE.

+ 290 - 290
source/Compiler.ob07

@@ -14,334 +14,334 @@ CONST
 
 
 PROCEDURE keys (VAR options: PROG.OPTIONS; VAR out: PARS.PATH);
-VAR
-    param: PARS.PATH;
-    i, j:  INTEGER;
-    _end:  BOOLEAN;
-    value: INTEGER;
-    minor,
-    major: INTEGER;
-    checking: SET;
-
-
-    PROCEDURE getVal (VAR i: INTEGER; VAR value: INTEGER);
     VAR
         param: PARS.PATH;
-        val: INTEGER;
-    BEGIN
-        INC(i);
-        UTILS.GetArg(i, param);
-        IF STRINGS.StrToInt(param, val) THEN
-            value := val
-        END;
-        IF param[0] = "-" THEN
-            DEC(i)
-        END
-    END getVal;
-
-
-BEGIN
-    options.lower := TRUE;
-    out := "";
-    checking := options.checking;
-    _end := FALSE;
-    i := 3;
-    REPEAT
-        UTILS.GetArg(i, param);
-
-        IF param = "-stk" THEN
+        i, j:  INTEGER;
+        _end:  BOOLEAN;
+        value: INTEGER;
+        minor,
+        major: INTEGER;
+        checking: SET;
+
+
+        PROCEDURE getVal (VAR i: INTEGER; VAR value: INTEGER);
+        VAR
+            param: PARS.PATH;
+            val: INTEGER;
+        BEGIN
             INC(i);
             UTILS.GetArg(i, param);
-            IF STRINGS.StrToInt(param, value) & (1 <= value) & (value <= 32) THEN
-                options.stack := value
+            IF STRINGS.StrToInt(param, val) THEN
+                value := val
             END;
             IF param[0] = "-" THEN
                 DEC(i)
             END
+        END getVal;
 
-        ELSIF param = "-fa" THEN
-            getVal(i, options.PE32FileAlignment)
 
-        ELSIF param = "-out" THEN
-            INC(i);
+    BEGIN
+        options.lower := TRUE;
+        out := "";
+        checking := options.checking;
+        _end := FALSE;
+        i := 3;
+        REPEAT
             UTILS.GetArg(i, param);
-            IF param[0] = "-" THEN
-                DEC(i)
-            ELSE
-                out := param
-            END
 
-        ELSIF param = "-tab" THEN
-            getVal(i, options.tab)
+            IF param = "-stk" THEN
+                INC(i);
+                UTILS.GetArg(i, param);
+                IF STRINGS.StrToInt(param, value) & (1 <= value) & (value <= 32) THEN
+                    options.stack := value
+                END;
+                IF param[0] = "-" THEN
+                    DEC(i)
+                END
+
+            ELSIF param = "-fa" THEN
+                getVal(i, options.PE32FileAlignment)
+
+            ELSIF param = "-out" THEN
+                INC(i);
+                UTILS.GetArg(i, param);
+                IF param[0] = "-" THEN
+                    DEC(i)
+                ELSE
+                    out := param
+                END
+
+            ELSIF param = "-tab" THEN
+                getVal(i, options.tab)
+
+            ELSIF param = "-ram" THEN
+                getVal(i, options.ram)
+
+            ELSIF param = "-rom" THEN
+                getVal(i, options.rom)
+
+            ELSIF param = "-nochk" THEN
+                INC(i);
+                UTILS.GetArg(i, param);
+
+                IF param[0] = "-" THEN
+                    DEC(i)
+                ELSE
+                    j := 0;
+                    WHILE param[j] # 0X DO
+
+                        IF    param[j] = "p" THEN
+                            EXCL(checking, ST.chkPTR)
+                        ELSIF param[j] = "t" THEN
+                            EXCL(checking, ST.chkGUARD)
+                        ELSIF param[j] = "i" THEN
+                            EXCL(checking, ST.chkIDX)
+                        ELSIF param[j] = "b" THEN
+                            EXCL(checking, ST.chkBYTE)
+                        ELSIF param[j] = "c" THEN
+                            EXCL(checking, ST.chkCHR)
+                        ELSIF param[j] = "w" THEN
+                            EXCL(checking, ST.chkWCHR)
+                        ELSIF param[j] = "r" THEN
+                            EXCL(checking, ST.chkCHR);
+                            EXCL(checking, ST.chkWCHR);
+                            EXCL(checking, ST.chkBYTE)
+                        ELSIF param[j] = "s" THEN
+                            EXCL(checking, ST.chkSTK)
+                        ELSIF param[j] = "a" THEN
+                            checking := {}
+                        END;
+
+                        INC(j)
+                    END;
 
-        ELSIF param = "-ram" THEN
-            getVal(i, options.ram)
+                END
 
-        ELSIF param = "-rom" THEN
-            getVal(i, options.rom)
+            ELSIF param = "-ver" THEN
+                INC(i);
+                UTILS.GetArg(i, param);
+                IF STRINGS.StrToVer(param, major, minor) THEN
+                    options.version := major * 65536 + minor
+                END;
+                IF param[0] = "-" THEN
+                    DEC(i)
+                END
 
-        ELSIF param = "-nochk" THEN
-            INC(i);
-            UTILS.GetArg(i, param);
+            ELSIF param = "-lower" THEN
+                options.lower := TRUE
 
-            IF param[0] = "-" THEN
-                DEC(i)
-            ELSE
-                j := 0;
-                WHILE param[j] # 0X DO
-
-                    IF    param[j] = "p" THEN
-                        EXCL(checking, ST.chkPTR)
-                    ELSIF param[j] = "t" THEN
-                        EXCL(checking, ST.chkGUARD)
-                    ELSIF param[j] = "i" THEN
-                        EXCL(checking, ST.chkIDX)
-                    ELSIF param[j] = "b" THEN
-                        EXCL(checking, ST.chkBYTE)
-                    ELSIF param[j] = "c" THEN
-                        EXCL(checking, ST.chkCHR)
-                    ELSIF param[j] = "w" THEN
-                        EXCL(checking, ST.chkWCHR)
-                    ELSIF param[j] = "r" THEN
-                        EXCL(checking, ST.chkCHR);
-                        EXCL(checking, ST.chkWCHR);
-                        EXCL(checking, ST.chkBYTE)
-                    ELSIF param[j] = "s" THEN
-                        EXCL(checking, ST.chkSTK)
-                    ELSIF param[j] = "a" THEN
-                        checking := {}
-                    END;
+            ELSIF param = "-upper" THEN
+                options.lower := FALSE
 
-                    INC(j)
-                END;
+            ELSIF param = "-pic" THEN
+                options.pic := TRUE
 
-            END
+            ELSIF param = "-uses" THEN
+                options.uses := TRUE
 
-        ELSIF param = "-ver" THEN
-            INC(i);
-            UTILS.GetArg(i, param);
-            IF STRINGS.StrToVer(param, major, minor) THEN
-                options.version := major * 65536 + minor
+            ELSIF param = "-def" THEN
+                INC(i);
+                UTILS.GetArg(i, param);
+                SCAN.NewDef(param)
+
+            ELSIF param = "" THEN
+                _end := TRUE
+
+            ELSE
+                ERRORS.BadParam(param)
             END;
-            IF param[0] = "-" THEN
-                DEC(i)
-            END
 
-        ELSIF param = "-lower" THEN
-            options.lower := TRUE
+            INC(i)
+        UNTIL _end;
 
-        ELSIF param = "-upper" THEN
-            options.lower := FALSE
+        options.checking := checking
+    END keys;
 
-        ELSIF param = "-pic" THEN
-            options.pic := TRUE
 
-        ELSIF param = "-uses" THEN
-            options.uses := TRUE
+PROCEDURE OutTargetItem (target: INTEGER; text: ARRAY OF CHAR);
+    VAR
+        width: INTEGER;
 
-        ELSIF param = "-def" THEN
-            INC(i);
-            UTILS.GetArg(i, param);
-            SCAN.NewDef(param)
+    BEGIN
+        width := 15;
+        width := width - LENGTH(TARGETS.Targets[target].ComLinePar) - 4;
+        C.String("  '"); C.String(TARGETS.Targets[target].ComLinePar); C.String("'");
+        WHILE width > 0 DO
+            C.String(20X);
+            DEC(width)
+        END;
+        C.StringLn(text)
+    END OutTargetItem;
 
-        ELSIF param = "" THEN
-            _end := TRUE
 
-        ELSE
-            ERRORS.BadParam(param)
+PROCEDURE main;
+    VAR
+        path:       PARS.PATH;
+        inname:     PARS.PATH;
+        ext:        PARS.PATH;
+        app_path:   PARS.PATH;
+        lib_path:   PARS.PATH;
+        modname:    PARS.PATH;
+        outname:    PARS.PATH;
+        param:      PARS.PATH;
+        temp:       PARS.PATH;
+        target:     INTEGER;
+        time:       INTEGER;
+        options:    PROG.OPTIONS;
+
+    BEGIN
+        options.stack := 2;
+        options.tab := TEXTDRV.defTabSize;
+        options.version := 65536;
+        options.pic := FALSE;
+        options.lower := FALSE;
+        options.uses := FALSE;
+        options.checking := ST.chkALL;
+
+        PATHS.GetCurrentDirectory(app_path);
+
+        UTILS.GetArg(0, temp);
+        PATHS.split(temp, path, modname, ext);
+        IF PATHS.isRelative(path) THEN
+            PATHS.RelPath(app_path, path, temp);
+            path := temp
         END;
+        lib_path := path;
 
-        INC(i)
-    UNTIL _end;
+        UTILS.GetArg(1, inname);
+        STRINGS.replace(inname, "\", UTILS.slash);
+        STRINGS.replace(inname, "/", UTILS.slash);
 
-    options.checking := checking
-END keys;
+        C.Ln;
+        C.String("Akron Oberon Compiler v"); C.Int(UTILS.vMajor); C.String("."); C.Int2(UTILS.vMinor);
+            C.String(" ("); C.Int(UTILS.bit_depth); C.StringLn("-bit) " + UTILS.Date);
+        C.StringLn("Copyright (c) 2018-2023, Anton Krotov");
+
+        IF inname = "" THEN
+            C.Ln;
+            C.StringLn("Usage: Compiler <main module> <target> [optional settings]"); C.Ln;
+            C.StringLn("target =");
+            IF UTILS.bit_depth = 64 THEN
+                OutTargetItem(TARGETS.Win64C, "Windows64 Console");
+                OutTargetItem(TARGETS.Win64GUI, "Windows64 GUI");
+                OutTargetItem(TARGETS.Win64DLL, "Windows64 DLL");
+                OutTargetItem(TARGETS.Linux64, "Linux64 Exec");
+                OutTargetItem(TARGETS.Linux64SO, "Linux64 SO")
+            END;
+            OutTargetItem(TARGETS.Win32C, "Windows32 Console");
+            OutTargetItem(TARGETS.Win32GUI, "Windows32 GUI");
+            OutTargetItem(TARGETS.Win32DLL, "Windows32 DLL");
+            OutTargetItem(TARGETS.Linux32, "Linux32 Exec");
+            OutTargetItem(TARGETS.Linux32SO, "Linux32 SO");
+            OutTargetItem(TARGETS.KolibriOS, "KolibriOS Exec");
+            OutTargetItem(TARGETS.KolibriOSDLL, "KolibriOS DLL");
+            OutTargetItem(TARGETS.MSP430, "MSP430x{1,2}xx microcontrollers");
+            OutTargetItem(TARGETS.STM32CM3, "STM32 Cortex-M3 microcontrollers");
+            C.Ln;
+            C.StringLn("optional settings:"); C.Ln;
+            C.StringLn("  -out <file name>      output"); C.Ln;
+            C.StringLn("  -stk <size>           set size of stack in Mbytes (Windows, Linux, KolibriOS)"); C.Ln;
+            C.StringLn("  -nochk <'ptibcwra'>   disable runtime checking (pointers, types, indexes,");
+            C.StringLn("                        BYTE, CHR, WCHR)"); C.Ln;
+            C.StringLn("  -lower                allow lower case for keywords (default)"); C.Ln;
+            C.StringLn("  -upper                only upper case for keywords"); C.Ln;
+            C.StringLn("  -def <identifier>     define conditional compilation symbol"); C.Ln;
+            C.StringLn("  -ver <major.minor>    set version of program (KolibriOS DLL)"); C.Ln;
+            C.StringLn("  -ram <size>           set size of RAM in bytes (MSP430) or Kbytes (STM32)"); C.Ln;
+            C.StringLn("  -rom <size>           set size of ROM in bytes (MSP430) or Kbytes (STM32)"); C.Ln;
+            C.StringLn("  -tab <width>          set width for tabs"); C.Ln;
+            C.StringLn("  -uses                 list imported modules"); C.Ln;
+            C.StringLn("  -fa <size>            set PE32 file alignment {512 (def.), 1024, 2048, 4096}"); C.Ln;
+            UTILS.Exit(0)
+        END;
 
+        C.Dashes;
+        PATHS.split(inname, path, modname, ext);
 
-PROCEDURE OutTargetItem (target: INTEGER; text: ARRAY OF CHAR);
-VAR
-    width: INTEGER;
+        IF ext # UTILS.FILE_EXT THEN
+            ERRORS.Error(207)
+        END;
 
-BEGIN
-    width := 15;
-    width := width - LENGTH(TARGETS.Targets[target].ComLinePar) - 4;
-    C.String("  '"); C.String(TARGETS.Targets[target].ComLinePar); C.String("'");
-    WHILE width > 0 DO
-        C.String(20X);
-        DEC(width)
-    END;
-    C.StringLn(text)
-END OutTargetItem;
+        IF PATHS.isRelative(path) THEN
+            PATHS.RelPath(app_path, path, temp);
+            path := temp
+        END;
 
+        UTILS.GetArg(2, param);
+        IF param = "" THEN
+            ERRORS.Error(205)
+        END;
 
-PROCEDURE main;
-VAR
-    path:       PARS.PATH;
-    inname:     PARS.PATH;
-    ext:        PARS.PATH;
-    app_path:   PARS.PATH;
-    lib_path:   PARS.PATH;
-    modname:    PARS.PATH;
-    outname:    PARS.PATH;
-    param:      PARS.PATH;
-    temp:       PARS.PATH;
-    target:     INTEGER;
-    time:       INTEGER;
-    options:    PROG.OPTIONS;
+        SCAN.NewDef(param);
 
-BEGIN
-    options.stack := 2;
-    options.tab := TEXTDRV.defTabSize;
-    options.version := 65536;
-    options.pic := FALSE;
-    options.lower := FALSE;
-    options.uses := FALSE;
-    options.checking := ST.chkALL;
-
-    PATHS.GetCurrentDirectory(app_path);
-
-    UTILS.GetArg(0, temp);
-    PATHS.split(temp, path, modname, ext);
-    IF PATHS.isRelative(path) THEN
-        PATHS.RelPath(app_path, path, temp);
-        path := temp
-    END;
-    lib_path := path;
-
-    UTILS.GetArg(1, inname);
-    STRINGS.replace(inname, "\", UTILS.slash);
-    STRINGS.replace(inname, "/", UTILS.slash);
-
-    C.Ln;
-    C.String("Akron Oberon Compiler v"); C.Int(UTILS.vMajor); C.String("."); C.Int2(UTILS.vMinor);
-        C.String(" ("); C.Int(UTILS.bit_depth); C.StringLn("-bit) " + UTILS.Date);
-    C.StringLn("Copyright (c) 2018-2023, Anton Krotov");
-
-    IF inname = "" THEN
-        C.Ln;
-        C.StringLn("Usage: Compiler <main module> <target> [optional settings]"); C.Ln;
-        C.StringLn("target =");
-        IF UTILS.bit_depth = 64 THEN
-            OutTargetItem(TARGETS.Win64C, "Windows64 Console");
-            OutTargetItem(TARGETS.Win64GUI, "Windows64 GUI");
-            OutTargetItem(TARGETS.Win64DLL, "Windows64 DLL");
-            OutTargetItem(TARGETS.Linux64, "Linux64 Exec");
-            OutTargetItem(TARGETS.Linux64SO, "Linux64 SO")
+        IF TARGETS.Select(param) THEN
+            target := TARGETS.target
+        ELSE
+            ERRORS.Error(206)
         END;
-        OutTargetItem(TARGETS.Win32C, "Windows32 Console");
-        OutTargetItem(TARGETS.Win32GUI, "Windows32 GUI");
-        OutTargetItem(TARGETS.Win32DLL, "Windows32 DLL");
-        OutTargetItem(TARGETS.Linux32, "Linux32 Exec");
-        OutTargetItem(TARGETS.Linux32SO, "Linux32 SO");
-        OutTargetItem(TARGETS.KolibriOS, "KolibriOS Exec");
-        OutTargetItem(TARGETS.KolibriOSDLL, "KolibriOS DLL");
-        OutTargetItem(TARGETS.MSP430, "MSP430x{1,2}xx microcontrollers");
-        OutTargetItem(TARGETS.STM32CM3, "STM32 Cortex-M3 microcontrollers");
-        C.Ln;
-        C.StringLn("optional settings:"); C.Ln;
-        C.StringLn("  -out <file name>      output"); C.Ln;
-        C.StringLn("  -stk <size>           set size of stack in Mbytes (Windows, Linux, KolibriOS)"); C.Ln;
-        C.StringLn("  -nochk <'ptibcwra'>   disable runtime checking (pointers, types, indexes,");
-        C.StringLn("                        BYTE, CHR, WCHR)"); C.Ln;
-        C.StringLn("  -lower                allow lower case for keywords (default)"); C.Ln;
-        C.StringLn("  -upper                only upper case for keywords"); C.Ln;
-        C.StringLn("  -def <identifier>     define conditional compilation symbol"); C.Ln;
-        C.StringLn("  -ver <major.minor>    set version of program (KolibriOS DLL)"); C.Ln;
-        C.StringLn("  -ram <size>           set size of RAM in bytes (MSP430) or Kbytes (STM32)"); C.Ln;
-        C.StringLn("  -rom <size>           set size of ROM in bytes (MSP430) or Kbytes (STM32)"); C.Ln;
-        C.StringLn("  -tab <width>          set width for tabs"); C.Ln;
-        C.StringLn("  -uses                 list imported modules"); C.Ln;
-        C.StringLn("  -fa <size>            set PE32 file alignment {512 (def.), 1024, 2048, 4096}"); C.Ln;
+
+        IF TARGETS.CPU = TARGETS.cpuMSP430 THEN
+            options.ram := MSP430.minRAM;
+            options.rom := MSP430.minROM
+        END;
+
+        IF (TARGETS.CPU = TARGETS.cpuTHUMB) & (TARGETS.OS = TARGETS.osNONE) THEN
+            options.ram := THUMB.minRAM;
+            options.rom := THUMB.minROM
+        END;
+
+        IF UTILS.bit_depth < TARGETS.BitDepth THEN
+            ERRORS.Error(206)
+        END;
+
+        STRINGS.append(lib_path, "lib");
+        STRINGS.append(lib_path, UTILS.slash);
+        STRINGS.append(lib_path, TARGETS.LibDir);
+        STRINGS.append(lib_path, UTILS.slash);
+
+        keys(options, outname);
+        TEXTDRV.setTabSize(options.tab);
+        IF outname = "" THEN
+            outname := path;
+            STRINGS.append(outname, modname);
+            STRINGS.append(outname, TARGETS.FileExt)
+        ELSE
+            IF PATHS.isRelative(outname) THEN
+                PATHS.RelPath(app_path, outname, temp);
+                outname := temp
+            END
+        END;
+
+        PARS.init(options);
+
+        CASE TARGETS.OS OF
+        |TARGETS.osNONE:
+        |TARGETS.osWIN32,
+        TARGETS.osWIN64:   SCAN.NewDef(DEF_WINDOWS)
+        |TARGETS.osLINUX32,
+        TARGETS.osLINUX64: SCAN.NewDef(DEF_LINUX)
+        |TARGETS.osKOS:     SCAN.NewDef(DEF_KOLIBRIOS)
+        END;
+
+        CASE TARGETS.CPU OF
+        |TARGETS.cpuX86:    SCAN.NewDef(DEF_CPU_X86)
+        |TARGETS.cpuAMD64:  SCAN.NewDef(DEF_CPU_X8664)
+        |TARGETS.cpuMSP430:
+        |TARGETS.cpuTHUMB:
+        |TARGETS.cpuRVM32I:
+        |TARGETS.cpuRVM64I:
+        END;
+
+        ST.compile(path, lib_path, modname, outname, target, options);
+
+        time := UTILS.GetTickCount() - UTILS.time;
+        C.Dashes;
+        C.Int(PARS.lines); C.String(" lines, ");
+        C.Int(time DIV 100); C.String("."); C.Int2(time MOD 100); C.String(" sec, ");
+        C.Int(WRITER.counter); C.StringLn(" bytes");
+
         UTILS.Exit(0)
-    END;
-
-    C.Dashes;
-    PATHS.split(inname, path, modname, ext);
-
-    IF ext # UTILS.FILE_EXT THEN
-        ERRORS.Error(207)
-    END;
-
-    IF PATHS.isRelative(path) THEN
-        PATHS.RelPath(app_path, path, temp);
-        path := temp
-    END;
-
-    UTILS.GetArg(2, param);
-    IF param = "" THEN
-        ERRORS.Error(205)
-    END;
-
-    SCAN.NewDef(param);
-
-    IF TARGETS.Select(param) THEN
-        target := TARGETS.target
-    ELSE
-        ERRORS.Error(206)
-    END;
-
-    IF TARGETS.CPU = TARGETS.cpuMSP430 THEN
-        options.ram := MSP430.minRAM;
-        options.rom := MSP430.minROM
-    END;
-
-    IF (TARGETS.CPU = TARGETS.cpuTHUMB) & (TARGETS.OS = TARGETS.osNONE) THEN
-        options.ram := THUMB.minRAM;
-        options.rom := THUMB.minROM
-    END;
-
-    IF UTILS.bit_depth < TARGETS.BitDepth THEN
-        ERRORS.Error(206)
-    END;
-
-    STRINGS.append(lib_path, "lib");
-    STRINGS.append(lib_path, UTILS.slash);
-    STRINGS.append(lib_path, TARGETS.LibDir);
-    STRINGS.append(lib_path, UTILS.slash);
-
-    keys(options, outname);
-    TEXTDRV.setTabSize(options.tab);
-    IF outname = "" THEN
-        outname := path;
-        STRINGS.append(outname, modname);
-        STRINGS.append(outname, TARGETS.FileExt)
-    ELSE
-        IF PATHS.isRelative(outname) THEN
-            PATHS.RelPath(app_path, outname, temp);
-            outname := temp
-        END
-    END;
-
-    PARS.init(options);
-
-    CASE TARGETS.OS OF
-    |TARGETS.osNONE:
-    |TARGETS.osWIN32,
-     TARGETS.osWIN64:   SCAN.NewDef(DEF_WINDOWS)
-    |TARGETS.osLINUX32,
-     TARGETS.osLINUX64: SCAN.NewDef(DEF_LINUX)
-    |TARGETS.osKOS:     SCAN.NewDef(DEF_KOLIBRIOS)
-    END;
-
-    CASE TARGETS.CPU OF
-    |TARGETS.cpuX86:    SCAN.NewDef(DEF_CPU_X86)
-    |TARGETS.cpuAMD64:  SCAN.NewDef(DEF_CPU_X8664)
-    |TARGETS.cpuMSP430:
-    |TARGETS.cpuTHUMB:
-    |TARGETS.cpuRVM32I:
-    |TARGETS.cpuRVM64I:
-    END;
-
-    ST.compile(path, lib_path, modname, outname, target, options);
-
-    time := UTILS.GetTickCount() - UTILS.time;
-    C.Dashes;
-    C.Int(PARS.lines); C.String(" lines, ");
-    C.Int(time DIV 100); C.String("."); C.Int2(time MOD 100); C.String(" sec, ");
-    C.Int(WRITER.counter); C.StringLn(" bytes");
-
-    UTILS.Exit(0)
-END main;
+    END main;
 
 
 BEGIN

+ 432 - 439
source/ELF.ob07

@@ -1,11 +1,4 @@
-(*
-    BSD 2-Clause License
-
-    Copyright (c) 2019-2021, Anton Krotov
-    All rights reserved.
-*)
-
-MODULE ELF;
+MODULE ELF;
 
 IMPORT BIN, WR := WRITER, CHL := CHUNKLISTS, LISTS, PE32, UTILS, STRINGS;
 
@@ -95,498 +88,498 @@ VAR
 
 
 PROCEDURE Write16 (w: WCHAR);
-BEGIN
-    WR.Write16LE(ORD(w))
-END Write16;
+    BEGIN
+        WR.Write16LE(ORD(w))
+    END Write16;
 
 
 PROCEDURE WritePH (ph: Elf32_Phdr);
-BEGIN
-    WR.Write32LE(ph.p_type);
-    WR.Write32LE(ph.p_offset);
-    WR.Write32LE(ph.p_vaddr);
-    WR.Write32LE(ph.p_paddr);
-    WR.Write32LE(ph.p_filesz);
-    WR.Write32LE(ph.p_memsz);
-    WR.Write32LE(ph.p_flags);
-    WR.Write32LE(ph.p_align)
-END WritePH;
+    BEGIN
+        WR.Write32LE(ph.p_type);
+        WR.Write32LE(ph.p_offset);
+        WR.Write32LE(ph.p_vaddr);
+        WR.Write32LE(ph.p_paddr);
+        WR.Write32LE(ph.p_filesz);
+        WR.Write32LE(ph.p_memsz);
+        WR.Write32LE(ph.p_flags);
+        WR.Write32LE(ph.p_align)
+    END WritePH;
 
 
 PROCEDURE WritePH64 (ph: Elf32_Phdr);
-BEGIN
-    WR.Write32LE(ph.p_type);
-    WR.Write32LE(ph.p_flags);
-    WR.Write64LE(ph.p_offset);
-    WR.Write64LE(ph.p_vaddr);
-    WR.Write64LE(ph.p_paddr);
-    WR.Write64LE(ph.p_filesz);
-    WR.Write64LE(ph.p_memsz);
-    WR.Write64LE(ph.p_align)
-END WritePH64;
+    BEGIN
+        WR.Write32LE(ph.p_type);
+        WR.Write32LE(ph.p_flags);
+        WR.Write64LE(ph.p_offset);
+        WR.Write64LE(ph.p_vaddr);
+        WR.Write64LE(ph.p_paddr);
+        WR.Write64LE(ph.p_filesz);
+        WR.Write64LE(ph.p_memsz);
+        WR.Write64LE(ph.p_align)
+    END WritePH64;
 
 
 PROCEDURE NewDyn (tag, val: INTEGER);
-VAR
-    dyn: Elf32_Dyn;
+    VAR
+        dyn: Elf32_Dyn;
 
-BEGIN
-    NEW(dyn);
-    dyn.d_tag := tag;
-    dyn.d_val := val;
-    LISTS.push(dynamic, dyn)
-END NewDyn;
+    BEGIN
+        NEW(dyn);
+        dyn.d_tag := tag;
+        dyn.d_val := val;
+        LISTS.push(dynamic, dyn)
+    END NewDyn;
 
 
 PROCEDURE NewSym (name, value, size: INTEGER; info, other: CHAR; shndx: WCHAR);
-VAR
-    sym: Elf32_Sym;
+    VAR
+        sym: Elf32_Sym;
 
-BEGIN
-    NEW(sym);
-    sym.name := name;
-    sym.value := value;
-    sym.size := size;
-    sym.info := info;
-    sym.other := other;
-    sym.shndx := shndx;
+    BEGIN
+        NEW(sym);
+        sym.name := name;
+        sym.value := value;
+        sym.size := size;
+        sym.info := info;
+        sym.other := other;
+        sym.shndx := shndx;
 
-    LISTS.push(symtab, sym)
-END NewSym;
+        LISTS.push(symtab, sym)
+    END NewSym;
 
 
 PROCEDURE MakeHash (bucket, chain: CHL.INTLIST; symCount: INTEGER);
-VAR
-    symi, hi, k: INTEGER;
-
-BEGIN
-    FOR symi := 0 TO symCount - 1 DO
-        CHL.SetInt(chain, symi, 0);
-        hi := CHL.GetInt(hashtab, symi) MOD symCount;
-        IF CHL.GetInt(bucket, hi) # 0 THEN
-            k := symi;
-            WHILE CHL.GetInt(chain, k) # 0 DO
-                k := CHL.GetInt(chain, k)
+    VAR
+        symi, hi, k: INTEGER;
+
+    BEGIN
+        FOR symi := 0 TO symCount - 1 DO
+            CHL.SetInt(chain, symi, 0);
+            hi := CHL.GetInt(hashtab, symi) MOD symCount;
+            IF CHL.GetInt(bucket, hi) # 0 THEN
+                k := symi;
+                WHILE CHL.GetInt(chain, k) # 0 DO
+                    k := CHL.GetInt(chain, k)
+                END;
+                CHL.SetInt(chain, k, CHL.GetInt(bucket, hi))
             END;
-            CHL.SetInt(chain, k, CHL.GetInt(bucket, hi))
-        END;
-        CHL.SetInt(bucket, hi, symi)
-    END
-END MakeHash;
+            CHL.SetInt(bucket, hi, symi)
+        END
+    END MakeHash;
 
 
 PROCEDURE write* (program: BIN.PROGRAM; FileName: ARRAY OF CHAR; fini: INTEGER; so, amd64: BOOLEAN);
-CONST
-    interp  =  0;
-    dyn     =  1;
-    header  =  2;
-    text    =  3;
-    data    =  4;
-    bss     =  5;
-
-    linuxInterpreter64 = "/lib64/ld-linux-x86-64.so.2";
-    linuxInterpreter32 = "/lib/ld-linux.so.2";
-
-    exeBaseAddress32 = 8048000H;
-    exeBaseAddress64 = 400000H;
-    dllBaseAddress = 0;
-
-    DT_NULL = 0;
-    DT_NEEDED = 1;
-    DT_HASH = 4;
-    DT_STRTAB = 5;
-    DT_SYMTAB = 6;
-    DT_RELA = 7;
-    DT_RELASZ = 8;
-    DT_RELAENT = 9;
-    DT_STRSZ = 10;
-    DT_SYMENT = 11;
-    DT_INIT = 12;
-    DT_FINI = 13;
-    DT_SONAME = 14;
-    DT_REL = 17;
-    DT_RELSZ = 18;
-    DT_RELENT = 19;
-
-VAR
-    ehdr: Elf32_Ehdr;
-    phdr: ARRAY 16 OF Elf32_Phdr;
-
-    i, BaseAdr, DynAdr, offset, pad, VA, symCount: INTEGER;
+    CONST
+        interp  =  0;
+        dyn     =  1;
+        header  =  2;
+        text    =  3;
+        data    =  4;
+        bss     =  5;
+
+        linuxInterpreter64 = "/lib64/ld-linux-x86-64.so.2";
+        linuxInterpreter32 = "/lib/ld-linux.so.2";
+
+        exeBaseAddress32 = 8048000H;
+        exeBaseAddress64 = 400000H;
+        dllBaseAddress = 0;
+
+        DT_NULL = 0;
+        DT_NEEDED = 1;
+        DT_HASH = 4;
+        DT_STRTAB = 5;
+        DT_SYMTAB = 6;
+        DT_RELA = 7;
+        DT_RELASZ = 8;
+        DT_RELAENT = 9;
+        DT_STRSZ = 10;
+        DT_SYMENT = 11;
+        DT_INIT = 12;
+        DT_FINI = 13;
+        DT_SONAME = 14;
+        DT_REL = 17;
+        DT_RELSZ = 18;
+        DT_RELENT = 19;
+
+    VAR
+        ehdr: Elf32_Ehdr;
+        phdr: ARRAY 16 OF Elf32_Phdr;
+
+        i, BaseAdr, DynAdr, offset, pad, VA, symCount: INTEGER;
+
+        SizeOf: RECORD header, code, data, bss: INTEGER END;
+
+        Offset: RECORD symtab, reltab, hash, strtab: INTEGER END;
+
+        Interpreter: ARRAY 40 OF CHAR; lenInterpreter: INTEGER;
+
+        item: LISTS.ITEM;
+
+        Name: ARRAY 2048 OF CHAR;
+
+        Address: PE32.VIRTUAL_ADDR;
+
+    BEGIN
+        dynamic := LISTS.create(NIL);
+        symtab  := LISTS.create(NIL);
+        strtab  := CHL.CreateByteList();
+
+        IF amd64 THEN
+            BaseAdr := exeBaseAddress64;
+            Interpreter := linuxInterpreter64
+        ELSE
+            BaseAdr := exeBaseAddress32;
+            Interpreter := linuxInterpreter32
+        END;
 
-    SizeOf: RECORD header, code, data, bss: INTEGER END;
+        IF so THEN
+            BaseAdr := dllBaseAddress
+        END;
 
-    Offset: RECORD symtab, reltab, hash, strtab: INTEGER END;
+        lenInterpreter := LENGTH(Interpreter) + 1;
 
-    Interpreter: ARRAY 40 OF CHAR; lenInterpreter: INTEGER;
+        SizeOf.code := CHL.Length(program.code);
+        SizeOf.data := CHL.Length(program.data);
+        SizeOf.bss  := program.bss;
 
-    item: LISTS.ITEM;
+        ehdr.e_ident[0] := 7FH;
+        ehdr.e_ident[1] := ORD("E");
+        ehdr.e_ident[2] := ORD("L");
+        ehdr.e_ident[3] := ORD("F");
+        IF amd64 THEN
+            ehdr.e_ident[4] := ELFCLASS64
+        ELSE
+            ehdr.e_ident[4] := ELFCLASS32
+        END;
+        ehdr.e_ident[5] := ELFDATA2LSB;
+        ehdr.e_ident[6] := 1;
+        ehdr.e_ident[7] := 3;
+        FOR i := 8 TO EI_NIDENT - 1 DO
+            ehdr.e_ident[i] := 0
+        END;
 
-    Name: ARRAY 2048 OF CHAR;
+        IF so THEN
+            ehdr.e_type := WCHR(ET_DYN)
+        ELSE
+            ehdr.e_type := WCHR(ET_EXEC)
+        END;
 
-    Address: PE32.VIRTUAL_ADDR;
+        ehdr.e_version := 1;
+        ehdr.e_shoff := 0;
+        ehdr.e_flags := 0;
+        ehdr.e_shnum := WCHR(0);
+        ehdr.e_shstrndx := WCHR(0);
+        ehdr.e_phnum := WCHR(6);
+
+        IF amd64 THEN
+            ehdr.e_machine := WCHR(EM_8664);
+            ehdr.e_phoff := 40H;
+            ehdr.e_ehsize := WCHR(40H);
+            ehdr.e_phentsize := WCHR(38H);
+            ehdr.e_shentsize := WCHR(40H)
+        ELSE
+            ehdr.e_machine := WCHR(EM_386);
+            ehdr.e_phoff := 34H;
+            ehdr.e_ehsize := WCHR(34H);
+            ehdr.e_phentsize := WCHR(20H);
+            ehdr.e_shentsize := WCHR(28H)
+        END;
 
-BEGIN
-    dynamic := LISTS.create(NIL);
-    symtab  := LISTS.create(NIL);
-    strtab  := CHL.CreateByteList();
+        SizeOf.header := ORD(ehdr.e_ehsize) + ORD(ehdr.e_phentsize) * ORD(ehdr.e_phnum);
+
+        phdr[interp].p_type := 3;
+        phdr[interp].p_offset := SizeOf.header;
+        phdr[interp].p_vaddr := BaseAdr + phdr[interp].p_offset;
+        phdr[interp].p_paddr := phdr[interp].p_vaddr;
+        phdr[interp].p_filesz := lenInterpreter;
+        phdr[interp].p_memsz := lenInterpreter;
+        phdr[interp].p_flags := PF_R;
+        phdr[interp].p_align := 1;
+
+        phdr[dyn].p_type := 2;
+        phdr[dyn].p_offset := phdr[interp].p_offset + phdr[interp].p_filesz;
+        phdr[dyn].p_vaddr := BaseAdr + phdr[dyn].p_offset;
+        phdr[dyn].p_paddr := phdr[dyn].p_vaddr;
+
+        hashtab := CHL.CreateIntList();
+
+        CHL.PushInt(hashtab, STRINGS.HashStr(""));
+        NewSym(CHL.PushStr(strtab, ""), 0, 0, 0X, 0X, 0X);
+        CHL.PushInt(hashtab, STRINGS.HashStr("dlopen"));
+        NewSym(CHL.PushStr(strtab, "dlopen"), 0, 0, 12X, 0X, 0X);
+        CHL.PushInt(hashtab, STRINGS.HashStr("dlsym"));
+        NewSym(CHL.PushStr(strtab, "dlsym"), 0, 0, 12X, 0X, 0X);
+
+        IF so THEN
+            item := program.exp_list.first;
+            WHILE item # NIL DO
+                ASSERT(CHL.GetStr(program.export, item(BIN.EXPRT).nameoffs, Name));
+                CHL.PushInt(hashtab, STRINGS.HashStr(Name));
+                NewSym(CHL.PushStr(strtab, Name), item(BIN.EXPRT).label, 0, 12X, 0X, 0X);
+                item := item.next
+            END;
+            ASSERT(CHL.GetStr(program.data, program.modname, Name))
+        END;
 
-    IF amd64 THEN
-        BaseAdr := exeBaseAddress64;
-        Interpreter := linuxInterpreter64
-    ELSE
-        BaseAdr := exeBaseAddress32;
-        Interpreter := linuxInterpreter32
-    END;
+        symCount := LISTS.count(symtab);
 
-    IF so THEN
-        BaseAdr := dllBaseAddress
-    END;
+        bucket := CHL.CreateIntList();
+        chain  := CHL.CreateIntList();
 
-    lenInterpreter := LENGTH(Interpreter) + 1;
+        FOR i := 1 TO symCount DO
+            CHL.PushInt(bucket, 0);
+            CHL.PushInt(chain, 0)
+        END;
 
-    SizeOf.code := CHL.Length(program.code);
-    SizeOf.data := CHL.Length(program.data);
-    SizeOf.bss  := program.bss;
+        MakeHash(bucket, chain, symCount);
+
+        NewDyn(DT_NEEDED, CHL.PushStr(strtab, "libdl.so.2"));
+        NewDyn(DT_STRTAB, 0);
+        NewDyn(DT_STRSZ, CHL.Length(strtab));
+        NewDyn(DT_SYMTAB, 0);
+
+        IF amd64 THEN
+            NewDyn(DT_SYMENT, 24);
+            NewDyn(DT_RELA, 0);
+            NewDyn(DT_RELASZ, 48);
+            NewDyn(DT_RELAENT, 24)
+        ELSE
+            NewDyn(DT_SYMENT, 16);
+            NewDyn(DT_REL, 0);
+            NewDyn(DT_RELSZ, 16);
+            NewDyn(DT_RELENT, 8)
+        END;
 
-    ehdr.e_ident[0] := 7FH;
-    ehdr.e_ident[1] := ORD("E");
-    ehdr.e_ident[2] := ORD("L");
-    ehdr.e_ident[3] := ORD("F");
-    IF amd64 THEN
-        ehdr.e_ident[4] := ELFCLASS64
-    ELSE
-        ehdr.e_ident[4] := ELFCLASS32
-    END;
-    ehdr.e_ident[5] := ELFDATA2LSB;
-    ehdr.e_ident[6] := 1;
-    ehdr.e_ident[7] := 3;
-    FOR i := 8 TO EI_NIDENT - 1 DO
-        ehdr.e_ident[i] := 0
-    END;
+        NewDyn(DT_HASH, 0);
 
-    IF so THEN
-        ehdr.e_type := WCHR(ET_DYN)
-    ELSE
-        ehdr.e_type := WCHR(ET_EXEC)
-    END;
+        IF so THEN
+            NewDyn(DT_SONAME, CHL.PushStr(strtab, Name));
+            NewDyn(DT_INIT, 0);
+            NewDyn(DT_FINI, 0)
+        END;
 
-    ehdr.e_version := 1;
-    ehdr.e_shoff := 0;
-    ehdr.e_flags := 0;
-    ehdr.e_shnum := WCHR(0);
-    ehdr.e_shstrndx := WCHR(0);
-    ehdr.e_phnum := WCHR(6);
-
-    IF amd64 THEN
-        ehdr.e_machine := WCHR(EM_8664);
-        ehdr.e_phoff := 40H;
-        ehdr.e_ehsize := WCHR(40H);
-        ehdr.e_phentsize := WCHR(38H);
-        ehdr.e_shentsize := WCHR(40H)
-    ELSE
-        ehdr.e_machine := WCHR(EM_386);
-        ehdr.e_phoff := 34H;
-        ehdr.e_ehsize := WCHR(34H);
-        ehdr.e_phentsize := WCHR(20H);
-        ehdr.e_shentsize := WCHR(28H)
-    END;
+        NewDyn(DT_NULL, 0);
+
+        Offset.symtab := LISTS.count(dynamic) * (8 + 8 * ORD(amd64));
+        Offset.reltab := Offset.symtab + symCount * (16 + 8 * ORD(amd64));
+        Offset.hash   := Offset.reltab + (8 + 16 * ORD(amd64)) * 2;
+        Offset.strtab := Offset.hash + (symCount * 2 + 2) * 4;
+
+        DynAdr := phdr[dyn].p_offset + BaseAdr;
+
+        item := LISTS.getidx(dynamic, 1); item(Elf32_Dyn).d_val := Offset.strtab + DynAdr;
+        item := LISTS.getidx(dynamic, 3); item(Elf32_Dyn).d_val := Offset.symtab + DynAdr;
+        item := LISTS.getidx(dynamic, 5); item(Elf32_Dyn).d_val := Offset.reltab + DynAdr;
+        item := LISTS.getidx(dynamic, 8); item(Elf32_Dyn).d_val := Offset.hash   + DynAdr;
+
+        phdr[dyn].p_filesz := Offset.strtab + CHL.Length(strtab) + 8 + 8 * ORD(amd64);
+        phdr[dyn].p_memsz  := phdr[dyn].p_filesz;
+
+        phdr[dyn].p_flags := PF_R;
+        phdr[dyn].p_align := 1;
+
+        offset := 0;
+
+        phdr[header].p_type := 1;
+        phdr[header].p_offset := offset;
+        phdr[header].p_vaddr := BaseAdr;
+        phdr[header].p_paddr := BaseAdr;
+        phdr[header].p_filesz := SizeOf.header + lenInterpreter + phdr[dyn].p_filesz;
+        phdr[header].p_memsz  := phdr[header].p_filesz;
+        phdr[header].p_flags := PF_R + PF_W;
+        phdr[header].p_align := 1000H;
+
+        INC(offset, phdr[header].p_filesz);
+        VA := BaseAdr + offset + 1000H;
+
+        phdr[text].p_type := 1;
+        phdr[text].p_offset := offset;
+        phdr[text].p_vaddr := VA;
+        phdr[text].p_paddr := VA;
+        phdr[text].p_filesz := SizeOf.code;
+        phdr[text].p_memsz := SizeOf.code;
+        phdr[text].p_flags := PF_X + PF_R;
+        phdr[text].p_align := 1000H;
+
+        ehdr.e_entry := phdr[text].p_vaddr;
+
+        INC(offset, phdr[text].p_filesz);
+        VA := BaseAdr + offset + 2000H;
+        pad := (16 - VA MOD 16) MOD 16;
+
+        phdr[data].p_type := 1;
+        phdr[data].p_offset := offset;
+        phdr[data].p_vaddr := VA;
+        phdr[data].p_paddr := VA;
+        phdr[data].p_filesz := SizeOf.data + pad;
+        phdr[data].p_memsz := SizeOf.data + pad;
+        phdr[data].p_flags := PF_R + PF_W;
+        phdr[data].p_align := 1000H;
+
+        INC(offset, phdr[data].p_filesz);
+        VA := BaseAdr + offset + 3000H;
+
+        phdr[bss].p_type := 1;
+        phdr[bss].p_offset := offset;
+        phdr[bss].p_vaddr := VA;
+        phdr[bss].p_paddr := VA;
+        phdr[bss].p_filesz := 0;
+        phdr[bss].p_memsz := SizeOf.bss + 16;
+        phdr[bss].p_flags := PF_R + PF_W;
+        phdr[bss].p_align := 1000H;
+
+        Address.Code   := ehdr.e_entry;
+        Address.Data   := phdr[data].p_vaddr + pad;
+        Address.Bss    := WR.align(phdr[bss].p_vaddr, 16);
+        Address.Import := 0;
+
+        PE32.fixup(program, Address, amd64);
 
-    SizeOf.header := ORD(ehdr.e_ehsize) + ORD(ehdr.e_phentsize) * ORD(ehdr.e_phnum);
-
-    phdr[interp].p_type := 3;
-    phdr[interp].p_offset := SizeOf.header;
-    phdr[interp].p_vaddr := BaseAdr + phdr[interp].p_offset;
-    phdr[interp].p_paddr := phdr[interp].p_vaddr;
-    phdr[interp].p_filesz := lenInterpreter;
-    phdr[interp].p_memsz := lenInterpreter;
-    phdr[interp].p_flags := PF_R;
-    phdr[interp].p_align := 1;
-
-    phdr[dyn].p_type := 2;
-    phdr[dyn].p_offset := phdr[interp].p_offset + phdr[interp].p_filesz;
-    phdr[dyn].p_vaddr := BaseAdr + phdr[dyn].p_offset;
-    phdr[dyn].p_paddr := phdr[dyn].p_vaddr;
-
-    hashtab := CHL.CreateIntList();
-
-    CHL.PushInt(hashtab, STRINGS.HashStr(""));
-    NewSym(CHL.PushStr(strtab, ""), 0, 0, 0X, 0X, 0X);
-    CHL.PushInt(hashtab, STRINGS.HashStr("dlopen"));
-    NewSym(CHL.PushStr(strtab, "dlopen"), 0, 0, 12X, 0X, 0X);
-    CHL.PushInt(hashtab, STRINGS.HashStr("dlsym"));
-    NewSym(CHL.PushStr(strtab, "dlsym"), 0, 0, 12X, 0X, 0X);
-
-    IF so THEN
-        item := program.exp_list.first;
+        item := symtab.first;
         WHILE item # NIL DO
-            ASSERT(CHL.GetStr(program.export, item(BIN.EXPRT).nameoffs, Name));
-            CHL.PushInt(hashtab, STRINGS.HashStr(Name));
-            NewSym(CHL.PushStr(strtab, Name), item(BIN.EXPRT).label, 0, 12X, 0X, 0X);
+            IF item(Elf32_Sym).value # 0 THEN
+                INC(item(Elf32_Sym).value, ehdr.e_entry)
+            END;
             item := item.next
         END;
-        ASSERT(CHL.GetStr(program.data, program.modname, Name))
-    END;
-
-    symCount := LISTS.count(symtab);
-
-    bucket := CHL.CreateIntList();
-    chain  := CHL.CreateIntList();
 
-    FOR i := 1 TO symCount DO
-        CHL.PushInt(bucket, 0);
-        CHL.PushInt(chain, 0)
-    END;
+        IF so THEN
+            item := LISTS.getidx(dynamic, 10); item(Elf32_Dyn).d_val := ehdr.e_entry;
+            item := LISTS.getidx(dynamic, 11); item(Elf32_Dyn).d_val := BIN.GetLabel(program, fini) + ehdr.e_entry
+        END;
 
-    MakeHash(bucket, chain, symCount);
-
-    NewDyn(DT_NEEDED, CHL.PushStr(strtab, "libdl.so.2"));
-    NewDyn(DT_STRTAB, 0);
-    NewDyn(DT_STRSZ, CHL.Length(strtab));
-    NewDyn(DT_SYMTAB, 0);
-
-    IF amd64 THEN
-        NewDyn(DT_SYMENT, 24);
-        NewDyn(DT_RELA, 0);
-        NewDyn(DT_RELASZ, 48);
-        NewDyn(DT_RELAENT, 24)
-    ELSE
-        NewDyn(DT_SYMENT, 16);
-        NewDyn(DT_REL, 0);
-        NewDyn(DT_RELSZ, 16);
-        NewDyn(DT_RELENT, 8)
-    END;
+        WR.Create(FileName);
 
-    NewDyn(DT_HASH, 0);
+        FOR i := 0 TO EI_NIDENT - 1 DO
+            WR.WriteByte(ehdr.e_ident[i])
+        END;
 
-    IF so THEN
-        NewDyn(DT_SONAME, CHL.PushStr(strtab, Name));
-        NewDyn(DT_INIT, 0);
-        NewDyn(DT_FINI, 0)
-    END;
+        Write16(ehdr.e_type);
+        Write16(ehdr.e_machine);
+
+        WR.Write32LE(ehdr.e_version);
+        IF amd64 THEN
+            WR.Write64LE(ehdr.e_entry);
+            WR.Write64LE(ehdr.e_phoff);
+            WR.Write64LE(ehdr.e_shoff)
+        ELSE
+            WR.Write32LE(ehdr.e_entry);
+            WR.Write32LE(ehdr.e_phoff);
+            WR.Write32LE(ehdr.e_shoff)
+        END;
+        WR.Write32LE(ehdr.e_flags);
+
+        Write16(ehdr.e_ehsize);
+        Write16(ehdr.e_phentsize);
+        Write16(ehdr.e_phnum);
+        Write16(ehdr.e_shentsize);
+        Write16(ehdr.e_shnum);
+        Write16(ehdr.e_shstrndx);
+
+        IF amd64 THEN
+            WritePH64(phdr[interp]);
+            WritePH64(phdr[dyn]);
+            WritePH64(phdr[header]);
+            WritePH64(phdr[text]);
+            WritePH64(phdr[data]);
+            WritePH64(phdr[bss])
+        ELSE
+            WritePH(phdr[interp]);
+            WritePH(phdr[dyn]);
+            WritePH(phdr[header]);
+            WritePH(phdr[text]);
+            WritePH(phdr[data]);
+            WritePH(phdr[bss])
+        END;
 
-    NewDyn(DT_NULL, 0);
-
-    Offset.symtab := LISTS.count(dynamic) * (8 + 8 * ORD(amd64));
-    Offset.reltab := Offset.symtab + symCount * (16 + 8 * ORD(amd64));
-    Offset.hash   := Offset.reltab + (8 + 16 * ORD(amd64)) * 2;
-    Offset.strtab := Offset.hash + (symCount * 2 + 2) * 4;
-
-    DynAdr := phdr[dyn].p_offset + BaseAdr;
-
-    item := LISTS.getidx(dynamic, 1); item(Elf32_Dyn).d_val := Offset.strtab + DynAdr;
-    item := LISTS.getidx(dynamic, 3); item(Elf32_Dyn).d_val := Offset.symtab + DynAdr;
-    item := LISTS.getidx(dynamic, 5); item(Elf32_Dyn).d_val := Offset.reltab + DynAdr;
-    item := LISTS.getidx(dynamic, 8); item(Elf32_Dyn).d_val := Offset.hash   + DynAdr;
-
-    phdr[dyn].p_filesz := Offset.strtab + CHL.Length(strtab) + 8 + 8 * ORD(amd64);
-    phdr[dyn].p_memsz  := phdr[dyn].p_filesz;
-
-    phdr[dyn].p_flags := PF_R;
-    phdr[dyn].p_align := 1;
-
-    offset := 0;
-
-    phdr[header].p_type := 1;
-    phdr[header].p_offset := offset;
-    phdr[header].p_vaddr := BaseAdr;
-    phdr[header].p_paddr := BaseAdr;
-    phdr[header].p_filesz := SizeOf.header + lenInterpreter + phdr[dyn].p_filesz;
-    phdr[header].p_memsz  := phdr[header].p_filesz;
-    phdr[header].p_flags := PF_R + PF_W;
-    phdr[header].p_align := 1000H;
-
-    INC(offset, phdr[header].p_filesz);
-    VA := BaseAdr + offset + 1000H;
-
-    phdr[text].p_type := 1;
-    phdr[text].p_offset := offset;
-    phdr[text].p_vaddr := VA;
-    phdr[text].p_paddr := VA;
-    phdr[text].p_filesz := SizeOf.code;
-    phdr[text].p_memsz := SizeOf.code;
-    phdr[text].p_flags := PF_X + PF_R;
-    phdr[text].p_align := 1000H;
-
-    ehdr.e_entry := phdr[text].p_vaddr;
-
-    INC(offset, phdr[text].p_filesz);
-    VA := BaseAdr + offset + 2000H;
-    pad := (16 - VA MOD 16) MOD 16;
-
-    phdr[data].p_type := 1;
-    phdr[data].p_offset := offset;
-    phdr[data].p_vaddr := VA;
-    phdr[data].p_paddr := VA;
-    phdr[data].p_filesz := SizeOf.data + pad;
-    phdr[data].p_memsz := SizeOf.data + pad;
-    phdr[data].p_flags := PF_R + PF_W;
-    phdr[data].p_align := 1000H;
-
-    INC(offset, phdr[data].p_filesz);
-    VA := BaseAdr + offset + 3000H;
-
-    phdr[bss].p_type := 1;
-    phdr[bss].p_offset := offset;
-    phdr[bss].p_vaddr := VA;
-    phdr[bss].p_paddr := VA;
-    phdr[bss].p_filesz := 0;
-    phdr[bss].p_memsz := SizeOf.bss + 16;
-    phdr[bss].p_flags := PF_R + PF_W;
-    phdr[bss].p_align := 1000H;
-
-    Address.Code   := ehdr.e_entry;
-    Address.Data   := phdr[data].p_vaddr + pad;
-    Address.Bss    := WR.align(phdr[bss].p_vaddr, 16);
-    Address.Import := 0;
-
-    PE32.fixup(program, Address, amd64);
-
-    item := symtab.first;
-    WHILE item # NIL DO
-        IF item(Elf32_Sym).value # 0 THEN
-            INC(item(Elf32_Sym).value, ehdr.e_entry)
+        FOR i := 0 TO lenInterpreter - 1 DO
+            WR.WriteByte(ORD(Interpreter[i]))
         END;
-        item := item.next
-    END;
 
-    IF so THEN
-        item := LISTS.getidx(dynamic, 10); item(Elf32_Dyn).d_val := ehdr.e_entry;
-        item := LISTS.getidx(dynamic, 11); item(Elf32_Dyn).d_val := BIN.GetLabel(program, fini) + ehdr.e_entry
-    END;
+        IF amd64 THEN
+            item := dynamic.first;
+            WHILE item # NIL DO
+                WR.Write64LE(item(Elf32_Dyn).d_tag);
+                WR.Write64LE(item(Elf32_Dyn).d_val);
+                item := item.next
+            END;
 
-    WR.Create(FileName);
+            item := symtab.first;
+            WHILE item # NIL DO
+                WR.Write32LE(item(Elf32_Sym).name);
+                WR.WriteByte(ORD(item(Elf32_Sym).info));
+                WR.WriteByte(ORD(item(Elf32_Sym).other));
+                Write16(item(Elf32_Sym).shndx);
+                WR.Write64LE(item(Elf32_Sym).value);
+                WR.Write64LE(item(Elf32_Sym).size);
+                item := item.next
+            END;
 
-    FOR i := 0 TO EI_NIDENT - 1 DO
-        WR.WriteByte(ehdr.e_ident[i])
-    END;
+            WR.Write64LE(phdr[dyn].p_filesz + DynAdr - 16);
+            WR.Write32LE(1);
+            WR.Write32LE(1);
+            WR.Write64LE(0);
+            WR.Write64LE(phdr[dyn].p_filesz + DynAdr - 8);
+            WR.Write32LE(1);
+            WR.Write32LE(2);
+            WR.Write64LE(0)
+
+        ELSE
+            item := dynamic.first;
+            WHILE item # NIL DO
+                WR.Write32LE(item(Elf32_Dyn).d_tag);
+                WR.Write32LE(item(Elf32_Dyn).d_val);
+                item := item.next
+            END;
 
-    Write16(ehdr.e_type);
-    Write16(ehdr.e_machine);
-
-    WR.Write32LE(ehdr.e_version);
-    IF amd64 THEN
-        WR.Write64LE(ehdr.e_entry);
-        WR.Write64LE(ehdr.e_phoff);
-        WR.Write64LE(ehdr.e_shoff)
-    ELSE
-        WR.Write32LE(ehdr.e_entry);
-        WR.Write32LE(ehdr.e_phoff);
-        WR.Write32LE(ehdr.e_shoff)
-    END;
-    WR.Write32LE(ehdr.e_flags);
-
-    Write16(ehdr.e_ehsize);
-    Write16(ehdr.e_phentsize);
-    Write16(ehdr.e_phnum);
-    Write16(ehdr.e_shentsize);
-    Write16(ehdr.e_shnum);
-    Write16(ehdr.e_shstrndx);
-
-    IF amd64 THEN
-        WritePH64(phdr[interp]);
-        WritePH64(phdr[dyn]);
-        WritePH64(phdr[header]);
-        WritePH64(phdr[text]);
-        WritePH64(phdr[data]);
-        WritePH64(phdr[bss])
-    ELSE
-        WritePH(phdr[interp]);
-        WritePH(phdr[dyn]);
-        WritePH(phdr[header]);
-        WritePH(phdr[text]);
-        WritePH(phdr[data]);
-        WritePH(phdr[bss])
-    END;
+            item := symtab.first;
+            WHILE item # NIL DO
+                WR.Write32LE(item(Elf32_Sym).name);
+                WR.Write32LE(item(Elf32_Sym).value);
+                WR.Write32LE(item(Elf32_Sym).size);
+                WR.WriteByte(ORD(item(Elf32_Sym).info));
+                WR.WriteByte(ORD(item(Elf32_Sym).other));
+                Write16(item(Elf32_Sym).shndx);
+                item := item.next
+            END;
 
-    FOR i := 0 TO lenInterpreter - 1 DO
-        WR.WriteByte(ORD(Interpreter[i]))
-    END;
+            WR.Write32LE(phdr[dyn].p_filesz + DynAdr - 8);
+            WR.Write32LE(00000101H);
+            WR.Write32LE(phdr[dyn].p_filesz + DynAdr - 4);
+            WR.Write32LE(00000201H)
 
-    IF amd64 THEN
-        item := dynamic.first;
-        WHILE item # NIL DO
-            WR.Write64LE(item(Elf32_Dyn).d_tag);
-            WR.Write64LE(item(Elf32_Dyn).d_val);
-            item := item.next
         END;
 
-        item := symtab.first;
-        WHILE item # NIL DO
-            WR.Write32LE(item(Elf32_Sym).name);
-            WR.WriteByte(ORD(item(Elf32_Sym).info));
-            WR.WriteByte(ORD(item(Elf32_Sym).other));
-            Write16(item(Elf32_Sym).shndx);
-            WR.Write64LE(item(Elf32_Sym).value);
-            WR.Write64LE(item(Elf32_Sym).size);
-            item := item.next
-        END;
+        WR.Write32LE(symCount);
+        WR.Write32LE(symCount);
 
-        WR.Write64LE(phdr[dyn].p_filesz + DynAdr - 16);
-        WR.Write32LE(1);
-        WR.Write32LE(1);
-        WR.Write64LE(0);
-        WR.Write64LE(phdr[dyn].p_filesz + DynAdr - 8);
-        WR.Write32LE(1);
-        WR.Write32LE(2);
-        WR.Write64LE(0)
-
-    ELSE
-        item := dynamic.first;
-        WHILE item # NIL DO
-            WR.Write32LE(item(Elf32_Dyn).d_tag);
-            WR.Write32LE(item(Elf32_Dyn).d_val);
-            item := item.next
+        FOR i := 0 TO symCount - 1 DO
+            WR.Write32LE(CHL.GetInt(bucket, i))
         END;
 
-        item := symtab.first;
-        WHILE item # NIL DO
-            WR.Write32LE(item(Elf32_Sym).name);
-            WR.Write32LE(item(Elf32_Sym).value);
-            WR.Write32LE(item(Elf32_Sym).size);
-            WR.WriteByte(ORD(item(Elf32_Sym).info));
-            WR.WriteByte(ORD(item(Elf32_Sym).other));
-            Write16(item(Elf32_Sym).shndx);
-            item := item.next
+        FOR i := 0 TO symCount - 1 DO
+            WR.Write32LE(CHL.GetInt(chain, i))
         END;
 
-        WR.Write32LE(phdr[dyn].p_filesz + DynAdr - 8);
-        WR.Write32LE(00000101H);
-        WR.Write32LE(phdr[dyn].p_filesz + DynAdr - 4);
-        WR.Write32LE(00000201H)
-
-    END;
-
-    WR.Write32LE(symCount);
-    WR.Write32LE(symCount);
+        CHL.WriteToFile(strtab);
 
-    FOR i := 0 TO symCount - 1 DO
-        WR.Write32LE(CHL.GetInt(bucket, i))
-    END;
-
-    FOR i := 0 TO symCount - 1 DO
-        WR.Write32LE(CHL.GetInt(chain, i))
-    END;
-
-    CHL.WriteToFile(strtab);
-
-    IF amd64 THEN
-        WR.Write64LE(0);
-        WR.Write64LE(0)
-    ELSE
-        WR.Write32LE(0);
-        WR.Write32LE(0)
-    END;
+        IF amd64 THEN
+            WR.Write64LE(0);
+            WR.Write64LE(0)
+        ELSE
+            WR.Write32LE(0);
+            WR.Write32LE(0)
+        END;
 
-    CHL.WriteToFile(program.code);
-    WHILE pad > 0 DO
-        WR.WriteByte(0);
-        DEC(pad)
-    END;
-    CHL.WriteToFile(program.data);
-    WR.Close;
-    UTILS.chmod(FileName)
-END write;
+        CHL.WriteToFile(program.code);
+        WHILE pad > 0 DO
+            WR.WriteByte(0);
+            DEC(pad)
+        END;
+        CHL.WriteToFile(program.data);
+        WR.Close;
+        UTILS.chmod(FileName)
+    END write;
 
 
 END ELF.

+ 180 - 187
source/ERRORS.ob07

@@ -1,222 +1,215 @@
-(*
-    BSD 2-Clause License
-
-    Copyright (c) 2018-2022, Anton Krotov
-    All rights reserved.
-*)
-
-MODULE ERRORS;
+MODULE ERRORS;
 
 IMPORT C := CONSOLE, UTILS;
 
 
 PROCEDURE HintMsg* (name: ARRAY OF CHAR; line, col, hint: INTEGER);
-BEGIN
-    IF hint = 0 THEN
-        C.String("  hint ("); C.Int(line); C.String(":"); C.Int(col); C.String(") ");
-        C.String("variable '"); C.String(name); C.StringLn("' never used")
-    END
-END HintMsg;
+    BEGIN
+        IF hint = 0 THEN
+            C.String("  hint ("); C.Int(line); C.String(":"); C.Int(col); C.String(") ");
+            C.String("variable '"); C.String(name); C.StringLn("' never used")
+        END
+    END HintMsg;
 
 
 PROCEDURE WarningMsg* (line, col, warning: INTEGER);
-BEGIN
-    C.String("  warning ("); C.Int(line); C.String(":"); C.Int(col); C.String(") ");
-    CASE warning OF
-    |0: C.StringLn("passing a string value as a fixed array")
-    |1: C.StringLn("endless FOR loop")
-    |2: C.StringLn("identifier too long")
-    END
-END WarningMsg;
+    BEGIN
+        C.String("  warning ("); C.Int(line); C.String(":"); C.Int(col); C.String(") ");
+        CASE warning OF
+        |0: C.StringLn("passing a string value as a fixed array")
+        |1: C.StringLn("endless FOR loop")
+        |2: C.StringLn("identifier too long")
+        END
+    END WarningMsg;
 
 
 PROCEDURE ErrorMsg* (fname: ARRAY OF CHAR; line, col, errno: INTEGER);
-VAR
-    str: ARRAY 80 OF CHAR;
-
-BEGIN
-    C.Ln;
-    C.String("  error  ("); C.Int(errno); C.String(") ("); C.Int(line); C.String(":"); C.Int(col); C.String(") ");
-
-    CASE errno OF
-    |  1: str := "missing 'H' or 'X'"
-    |  2: str := "missing scale"
-    |  3: str := "unclosed string"
-    |  4: str := "illegal character"
-    |  5: str := "string too long"
-
-    |  7: str := "number too long"
-    |  8..12: str := "number too large"
-    | 13: str := "real numbers not supported"
-
-    | 21: str := "'MODULE' expected"
-    | 22: str := "identifier expected"
-    | 23: str := "module name does not match file name"
-    | 24: str := "';' expected"
-    | 25: str := "identifier does not match module name"
-    | 26: str := "'.' expected"
-    | 27: str := "'END' expected"
-    | 28: str := "',', ';' or ':=' expected"
-    | 29: str := "module not found"
-    | 30: str := "multiply defined identifier"
-    | 31: str := "recursive import"
-    | 32: str := "'=' expected"
-    | 33: str := "')' expected"
-    | 34: str := "syntax error in expression"
-    | 35: str := "'}' expected"
-    | 36: str := "incompatible operand"
-    | 37: str := "incompatible operands"
-    | 38: str := "'RETURN' expected"
-    | 39: str := "integer overflow"
-    | 40: str := "floating point overflow"
-    | 41: str := "not enough floating point registers; simplify expression"
-    | 42: str := "out of range 0..255"
-    | 43: str := "expression is not an integer"
-    | 44: str := "out of range 0..MAXSET"
-    | 45: str := "division by zero"
-    | 46: str := "IV out of range"
-    | 47: str := "'OF' or ',' expected"
-    | 48: str := "undeclared identifier"
-    | 49: str := "type expected"
-    | 50: str := "recursive type definition"
-    | 51: str := "illegal value of constant"
-    | 52: str := "not a record type"
-    | 53: str := "':' expected"
-    | 54: str := "need to import SYSTEM"
-    | 55: str := "pointer type not defined"
-    | 56: str := "out of range 0..MAXSET"
-    | 57: str := "'TO' expected"
-    | 58: str := "not a record type"
-    | 59: str := "this expression cannot be a procedure"
-    | 60: str := "identifier does not match procedure name"
-    | 61: str := "illegally marked identifier"
-    | 62: str := "expression should be constant"
-    | 63: str := "not enough RAM"
-    | 64: str := "'(' expected"
-    | 65: str := "',' expected"
-    | 66: str := "incompatible parameter"
-    | 67: str := "'OF' expected"
-    | 68: str := "type expected"
-    | 69: str := "result type of procedure is not a basic type"
-    | 70: str := "import not supported"
-    | 71: str := "']' expected"
-    | 72: str := "expression is not BOOLEAN"
-    | 73: str := "not a record"
-    | 74: str := "undefined record field"
-    | 75: str := "not an array"
-    | 76: str := "expression is not an integer"
-    | 77: str := "not a pointer"
-    | 78: str := "type guard not allowed"
-    | 79: str := "not a type"
-    | 80: str := "not a record type"
-    | 81: str := "not a pointer type"
-    | 82: str := "type guard not allowed"
-    | 83: str := "index out of range"
-    | 84: str := "dimension too large"
-    | 85: str := "procedure must have level 0"
-    | 86: str := "not a procedure"
-    | 87: str := "incompatible expression (RETURN)"
-    | 88: str := "'THEN' expected"
-    | 89: str := "'DO' expected"
-    | 90: str := "'UNTIL' expected"
-    | 91: str := "incompatible assignment"
-    | 92: str := "procedure call of a function"
-    | 93: str := "not a variable"
-    | 94: str := "read only variable"
-    | 95: str := "invalid type of expression (CASE)"
-    | 96: str := "':=' expected"
-    | 97: str := "not INTEGER variable"
-    | 98: str := "illegal value of constant (0)"
-    | 99: str := "incompatible label"
-    |100: str := "multiply defined label"
-    |101: str := "too large parameter of WCHR"
-    |102: str := "label expected"
-    |103: str := "illegal value of constant"
-    |104: str := "type too large"
-    |105: str := "access to intermediate variables not allowed"
-    |106: str := "qualified identifier expected"
-    |107: str := "too large parameter of CHR"
-    |108: str := "a variable or a procedure expected"
-    |109: str := "expression should be constant"
-    |110: str := "out of range 0..65535"
-    |111: str := "record [noalign] cannot have a base type"
-    |112: str := "record [noalign] cannot be a base type"
-    |113: str := "result type of procedure should not be REAL"
-    |114: str := "identifiers 'lib_init' and 'version' are reserved"
-    |115: str := "recursive constant definition"
-    |116: str := "procedure too deep nested"
-    |117: str := "string expected"
-    |118: str := "'$END', '$ELSE' or '$ELSIF' without '$IF'"
-    |119: str := "'$IF', '$ELSIF', '$ELSE' or '$END' expected"
-    |120: str := "too many formal parameters"
-    |121: str := "multiply defined handler"
-    |122: str := "bad divisor"
-    |123: str := "illegal flag"
-    |124: str := "unknown flag"
-    |125: str := "flag not supported"
-    |126: str := "type of formal parameter should not be REAL"
-    END;
-    C.StringLn(str);
-    C.String("  file:  ");  C.StringLn(fname);
-    UTILS.Exit(1)
-END ErrorMsg;
+    VAR
+        str: ARRAY 80 OF CHAR;
+
+    BEGIN
+        C.Ln;
+        C.String("  error  ("); C.Int(errno); C.String(") ("); C.Int(line); C.String(":"); C.Int(col); C.String(") ");
+
+        CASE errno OF
+        |  1: str := "missing 'H' or 'X'"
+        |  2: str := "missing scale"
+        |  3: str := "unclosed string"
+        |  4: str := "illegal character"
+        |  5: str := "string too long"
+
+        |  7: str := "number too long"
+        |  8..12: str := "number too large"
+        | 13: str := "real numbers not supported"
+
+        | 21: str := "'MODULE' expected"
+        | 22: str := "identifier expected"
+        | 23: str := "module name does not match file name"
+        | 24: str := "';' expected"
+        | 25: str := "identifier does not match module name"
+        | 26: str := "'.' expected"
+        | 27: str := "'END' expected"
+        | 28: str := "',', ';' or ':=' expected"
+        | 29: str := "module not found"
+        | 30: str := "multiply defined identifier"
+        | 31: str := "recursive import"
+        | 32: str := "'=' expected"
+        | 33: str := "')' expected"
+        | 34: str := "syntax error in expression"
+        | 35: str := "'}' expected"
+        | 36: str := "incompatible operand"
+        | 37: str := "incompatible operands"
+        | 38: str := "'RETURN' expected"
+        | 39: str := "integer overflow"
+        | 40: str := "floating point overflow"
+        | 41: str := "not enough floating point registers; simplify expression"
+        | 42: str := "out of range 0..255"
+        | 43: str := "expression is not an integer"
+        | 44: str := "out of range 0..MAXSET"
+        | 45: str := "division by zero"
+        | 46: str := "IV out of range"
+        | 47: str := "'OF' or ',' expected"
+        | 48: str := "undeclared identifier"
+        | 49: str := "type expected"
+        | 50: str := "recursive type definition"
+        | 51: str := "illegal value of constant"
+        | 52: str := "not a record type"
+        | 53: str := "':' expected"
+        | 54: str := "need to import SYSTEM"
+        | 55: str := "pointer type not defined"
+        | 56: str := "out of range 0..MAXSET"
+        | 57: str := "'TO' expected"
+        | 58: str := "not a record type"
+        | 59: str := "this expression cannot be a procedure"
+        | 60: str := "identifier does not match procedure name"
+        | 61: str := "illegally marked identifier"
+        | 62: str := "expression should be constant"
+        | 63: str := "not enough RAM"
+        | 64: str := "'(' expected"
+        | 65: str := "',' expected"
+        | 66: str := "incompatible parameter"
+        | 67: str := "'OF' expected"
+        | 68: str := "type expected"
+        | 69: str := "result type of procedure is not a basic type"
+        | 70: str := "import not supported"
+        | 71: str := "']' expected"
+        | 72: str := "expression is not BOOLEAN"
+        | 73: str := "not a record"
+        | 74: str := "undefined record field"
+        | 75: str := "not an array"
+        | 76: str := "expression is not an integer"
+        | 77: str := "not a pointer"
+        | 78: str := "type guard not allowed"
+        | 79: str := "not a type"
+        | 80: str := "not a record type"
+        | 81: str := "not a pointer type"
+        | 82: str := "type guard not allowed"
+        | 83: str := "index out of range"
+        | 84: str := "dimension too large"
+        | 85: str := "procedure must have level 0"
+        | 86: str := "not a procedure"
+        | 87: str := "incompatible expression (RETURN)"
+        | 88: str := "'THEN' expected"
+        | 89: str := "'DO' expected"
+        | 90: str := "'UNTIL' expected"
+        | 91: str := "incompatible assignment"
+        | 92: str := "procedure call of a function"
+        | 93: str := "not a variable"
+        | 94: str := "read only variable"
+        | 95: str := "invalid type of expression (CASE)"
+        | 96: str := "':=' expected"
+        | 97: str := "not INTEGER variable"
+        | 98: str := "illegal value of constant (0)"
+        | 99: str := "incompatible label"
+        |100: str := "multiply defined label"
+        |101: str := "too large parameter of WCHR"
+        |102: str := "label expected"
+        |103: str := "illegal value of constant"
+        |104: str := "type too large"
+        |105: str := "access to intermediate variables not allowed"
+        |106: str := "qualified identifier expected"
+        |107: str := "too large parameter of CHR"
+        |108: str := "a variable or a procedure expected"
+        |109: str := "expression should be constant"
+        |110: str := "out of range 0..65535"
+        |111: str := "record [noalign] cannot have a base type"
+        |112: str := "record [noalign] cannot be a base type"
+        |113: str := "result type of procedure should not be REAL"
+        |114: str := "identifiers 'lib_init' and 'version' are reserved"
+        |115: str := "recursive constant definition"
+        |116: str := "procedure too deep nested"
+        |117: str := "string expected"
+        |118: str := "'$END', '$ELSE' or '$ELSIF' without '$IF'"
+        |119: str := "'$IF', '$ELSIF', '$ELSE' or '$END' expected"
+        |120: str := "too many formal parameters"
+        |121: str := "multiply defined handler"
+        |122: str := "bad divisor"
+        |123: str := "illegal flag"
+        |124: str := "unknown flag"
+        |125: str := "flag not supported"
+        |126: str := "type of formal parameter should not be REAL"
+        END;
+        C.StringLn(str);
+        C.String("  file:  ");  C.StringLn(fname);
+        UTILS.Exit(1)
+    END ErrorMsg;
 
 
 PROCEDURE Error1 (s1: ARRAY OF CHAR);
-BEGIN
-    C.Ln;
-    C.StringLn(s1);
-    UTILS.Exit(1)
-END Error1;
+    BEGIN
+        C.Ln;
+        C.StringLn(s1);
+        UTILS.Exit(1)
+    END Error1;
 
 
 PROCEDURE Error3 (s1, s2, s3: ARRAY OF CHAR);
-BEGIN
-    C.Ln;
-    C.String(s1); C.String(s2); C.StringLn(s3);
-    UTILS.Exit(1)
-END Error3;
+    BEGIN
+        C.Ln;
+        C.String(s1); C.String(s2); C.StringLn(s3);
+        UTILS.Exit(1)
+    END Error3;
 
 
 PROCEDURE Error5 (s1, s2, s3, s4, s5: ARRAY OF CHAR);
-BEGIN
-    C.Ln;
-    C.String(s1); C.String(s2); C.String(s3); C.String(s4); C.StringLn(s5);
-    UTILS.Exit(1)
-END Error5;
+    BEGIN
+        C.Ln;
+        C.String(s1); C.String(s2); C.String(s3); C.String(s4); C.StringLn(s5);
+        UTILS.Exit(1)
+    END Error5;
 
 
 PROCEDURE WrongRTL* (ProcName: ARRAY OF CHAR);
-BEGIN
-    Error5("procedure ", UTILS.RTL_NAME, ".", ProcName, " not found")
-END WrongRTL;
+    BEGIN
+        Error5("procedure ", UTILS.RTL_NAME, ".", ProcName, " not found")
+    END WrongRTL;
 
 
 PROCEDURE BadParam* (param: ARRAY OF CHAR);
-BEGIN
-    Error3("bad parameter: ", param, "")
-END BadParam;
+    BEGIN
+        Error3("bad parameter: ", param, "")
+    END BadParam;
 
 
 PROCEDURE FileNotFound* (Path, Name, Ext: ARRAY OF CHAR);
-BEGIN
-    Error5("file ", Path, Name, Ext, " not found")
-END FileNotFound;
+    BEGIN
+        Error5("file ", Path, Name, Ext, " not found")
+    END FileNotFound;
 
 
 PROCEDURE Error* (n: INTEGER);
-BEGIN
-    CASE n OF
-    |201: Error1("writing file error")
-    |202: Error1("too many relocations")
-    |203: Error1("size of program is too large")
-    |204: Error1("size of variables is too large")
-    |205: Error1("not enough parameters")
-    |206: Error1("bad parameter <target>")
-    |207: Error3('inputfile name extension must be "', UTILS.FILE_EXT, '"')
-    |208: Error1("not enough RAM")
-    END
-END Error;
+    BEGIN
+        CASE n OF
+        |201: Error1("writing file error")
+        |202: Error1("too many relocations")
+        |203: Error1("size of program is too large")
+        |204: Error1("size of variables is too large")
+        |205: Error1("not enough parameters")
+        |206: Error1("bad parameter <target>")
+        |207: Error3('inputfile name extension must be "', UTILS.FILE_EXT, '"')
+        |208: Error1("not enough RAM")
+        END
+    END Error;
 
 
 END ERRORS.

+ 124 - 131
source/FILES.ob07

@@ -1,11 +1,4 @@
-(*
-    BSD 2-Clause License
-
-    Copyright (c) 2018-2022, Anton Krotov
-    All rights reserved.
-*)
-
-MODULE FILES;
+MODULE FILES;
 
 IMPORT UTILS, C := COLLECTIONS;
 
@@ -27,172 +20,172 @@ VAR
 
 
 PROCEDURE copy (src: ARRAY OF BYTE; src_idx: INTEGER; VAR dst: ARRAY OF BYTE; dst_idx: INTEGER; bytes: INTEGER);
-BEGIN
-    WHILE bytes > 0 DO
-        dst[dst_idx] := src[src_idx];
-        INC(dst_idx);
-        INC(src_idx);
-        DEC(bytes)
-    END
-END copy;
+    BEGIN
+        WHILE bytes > 0 DO
+            dst[dst_idx] := src[src_idx];
+            INC(dst_idx);
+            INC(src_idx);
+            DEC(bytes)
+        END
+    END copy;
 
 
 PROCEDURE flush (file: FILE): INTEGER;
-VAR
-    res: INTEGER;
-
-BEGIN
-    IF file # NIL THEN
-        res := UTILS.FileWrite(file.ptr, file.buffer, file.count);
-        IF res < 0 THEN
+    VAR
+        res: INTEGER;
+
+    BEGIN
+        IF file # NIL THEN
+            res := UTILS.FileWrite(file.ptr, file.buffer, file.count);
+            IF res < 0 THEN
+                res := 0
+            END
+        ELSE
             res := 0
         END
-    ELSE
-        res := 0
-    END
 
-    RETURN res
-END flush;
+        RETURN res
+    END flush;
 
 
 PROCEDURE NewFile (): FILE;
-VAR
-    file:  FILE;
-    citem: C.ITEM;
-
-BEGIN
-    citem := C.pop(files);
-    IF citem = NIL THEN
-        NEW(file)
-    ELSE
-        file := citem(FILE)
-    END
+    VAR
+        file:  FILE;
+        citem: C.ITEM;
+
+    BEGIN
+        citem := C.pop(files);
+        IF citem = NIL THEN
+            NEW(file)
+        ELSE
+            file := citem(FILE)
+        END
 
-    RETURN file
-END NewFile;
+        RETURN file
+    END NewFile;
 
 
 PROCEDURE create* (name: ARRAY OF CHAR): FILE;
-VAR
-    file: FILE;
-    ptr:  INTEGER;
-
-BEGIN
-    ptr := UTILS.FileCreate(name);
-
-    IF ptr > 0 THEN
-        file := NewFile();
-        file.ptr := ptr;
-        file.count := 0
-    ELSE
-        file := NIL
-    END
+    VAR
+        file: FILE;
+        ptr:  INTEGER;
+
+    BEGIN
+        ptr := UTILS.FileCreate(name);
+
+        IF ptr > 0 THEN
+            file := NewFile();
+            file.ptr := ptr;
+            file.count := 0
+        ELSE
+            file := NIL
+        END
 
-    RETURN file
-END create;
+        RETURN file
+    END create;
 
 
 PROCEDURE open* (name: ARRAY OF CHAR): FILE;
-VAR
-    file: FILE;
-    ptr:  INTEGER;
-
-BEGIN
-    ptr := UTILS.FileOpen(name);
-
-    IF ptr > 0 THEN
-        file := NewFile();
-        file.ptr := ptr;
-        file.count := -1
-    ELSE
-        file := NIL
-    END
+    VAR
+        file: FILE;
+        ptr:  INTEGER;
+
+    BEGIN
+        ptr := UTILS.FileOpen(name);
+
+        IF ptr > 0 THEN
+            file := NewFile();
+            file.ptr := ptr;
+            file.count := -1
+        ELSE
+            file := NIL
+        END
 
-    RETURN file
-END open;
+        RETURN file
+    END open;
 
 
 PROCEDURE close* (VAR file: FILE);
-VAR
-    n: INTEGER;
+    VAR
+        n: INTEGER;
 
-BEGIN
-    IF file # NIL THEN
+    BEGIN
+        IF file # NIL THEN
 
-        IF file.count > 0 THEN
-            n := flush(file)
-        END;
+            IF file.count > 0 THEN
+                n := flush(file)
+            END;
 
-        file.count := -1;
+            file.count := -1;
 
-        UTILS.FileClose(file.ptr);
-        file.ptr := 0;
+            UTILS.FileClose(file.ptr);
+            file.ptr := 0;
 
-        C.push(files, file);
-        file := NIL
-    END
-END close;
+            C.push(files, file);
+            file := NIL
+        END
+    END close;
 
 
 PROCEDURE read* (file: FILE; VAR chunk: ARRAY OF CHAR; bytes: INTEGER): INTEGER;
-VAR
-    res: INTEGER;
-
-BEGIN
-    IF file # NIL THEN
-        res := UTILS.FileRead(file.ptr, chunk, MAX(MIN(bytes, LEN(chunk)), 0));
-        IF res < 0 THEN
+    VAR
+        res: INTEGER;
+
+    BEGIN
+        IF file # NIL THEN
+            res := UTILS.FileRead(file.ptr, chunk, MAX(MIN(bytes, LEN(chunk)), 0));
+            IF res < 0 THEN
+                res := 0
+            END
+        ELSE
             res := 0
         END
-    ELSE
-        res := 0
-    END
 
-    RETURN res
-END read;
+        RETURN res
+    END read;
 
 
 PROCEDURE write* (file: FILE; chunk: ARRAY OF BYTE; bytes: INTEGER): INTEGER;
-VAR
-    free, n, idx: INTEGER;
-
-BEGIN
-    idx := 0;
-    IF (file # NIL) & (file.count >= 0) THEN
-
-        free := LEN(file.buffer) - file.count;
-        WHILE bytes > 0 DO
-            n := MIN(free, bytes);
-            copy(chunk, idx, file.buffer, file.count, n);
-            DEC(free, n);
-            DEC(bytes, n);
-            INC(idx, n);
-            INC(file.count, n);
-            IF free = 0 THEN
-                IF flush(file) # LEN(file.buffer) THEN
-                    bytes := 0;
-                    DEC(idx, n)
-                ELSE
-                    file.count := 0;
-                    free := LEN(file.buffer)
+    VAR
+        free, n, idx: INTEGER;
+
+    BEGIN
+        idx := 0;
+        IF (file # NIL) & (file.count >= 0) THEN
+
+            free := LEN(file.buffer) - file.count;
+            WHILE bytes > 0 DO
+                n := MIN(free, bytes);
+                copy(chunk, idx, file.buffer, file.count, n);
+                DEC(free, n);
+                DEC(bytes, n);
+                INC(idx, n);
+                INC(file.count, n);
+                IF free = 0 THEN
+                    IF flush(file) # LEN(file.buffer) THEN
+                        bytes := 0;
+                        DEC(idx, n)
+                    ELSE
+                        file.count := 0;
+                        free := LEN(file.buffer)
+                    END
                 END
             END
-        END
 
-    END
+        END
 
-    RETURN idx
-END write;
+        RETURN idx
+    END write;
 
 
 PROCEDURE WriteByte* (file: FILE; byte: BYTE): BOOLEAN;
-VAR
-    arr: ARRAY 1 OF BYTE;
+    VAR
+        arr: ARRAY 1 OF BYTE;
 
-BEGIN
-    arr[0] := byte
-    RETURN write(file, arr, 1) = 1
-END WriteByte;
+    BEGIN
+        arr[0] := byte
+        RETURN write(file, arr, 1) = 1
+    END WriteByte;
 
 
 BEGIN

+ 76 - 83
source/HEX.ob07

@@ -1,11 +1,4 @@
-(*
-    BSD 2-Clause License
-
-    Copyright (c) 2020, Anton Krotov
-    All rights reserved.
-*)
-
-MODULE HEX;
+MODULE HEX;
 
 IMPORT WRITER, CHL := CHUNKLISTS, UTILS;
 
@@ -16,102 +9,102 @@ VAR
 
 
 PROCEDURE Byte (byte: BYTE);
-BEGIN
-    WRITER.WriteByte(UTILS.hexdgt(byte DIV 16));
-    WRITER.WriteByte(UTILS.hexdgt(byte MOD 16));
-    INC(chksum, byte)
-END Byte;
+    BEGIN
+        WRITER.WriteByte(UTILS.hexdgt(byte DIV 16));
+        WRITER.WriteByte(UTILS.hexdgt(byte MOD 16));
+        INC(chksum, byte)
+    END Byte;
 
 
 PROCEDURE Byte4 (a, b, c, d: BYTE);
-BEGIN
-    Byte(a);
-    Byte(b);
-    Byte(c);
-    Byte(d)
-END Byte4;
+    BEGIN
+        Byte(a);
+        Byte(b);
+        Byte(c);
+        Byte(d)
+    END Byte4;
 
 
 PROCEDURE NewLine;
-BEGIN
-    Byte((-chksum) MOD 256);
-    chksum := 0;
-    WRITER.WriteByte(0DH);
-    WRITER.WriteByte(0AH)
-END NewLine;
+    BEGIN
+        Byte((-chksum) MOD 256);
+        chksum := 0;
+        WRITER.WriteByte(0DH);
+        WRITER.WriteByte(0AH)
+    END NewLine;
 
 
 PROCEDURE StartCode;
-BEGIN
-    WRITER.WriteByte(ORD(":"));
-    chksum := 0
-END StartCode;
+    BEGIN
+        WRITER.WriteByte(ORD(":"));
+        chksum := 0
+    END StartCode;
 
 
 PROCEDURE Data* (mem: ARRAY OF BYTE; idx, cnt: INTEGER);
-VAR
-    i, len: INTEGER;
-
-BEGIN
-    WHILE cnt > 0 DO
-        len := MIN(cnt, 16);
-        StartCode;
-        Byte4(len, idx DIV 256, idx MOD 256, 0);
-        FOR i := 1 TO len DO
-            Byte(mem[idx]);
-            INC(idx)
-        END;
-        DEC(cnt, len);
-        NewLine
-    END
-END Data;
+    VAR
+        i, len: INTEGER;
+
+    BEGIN
+        WHILE cnt > 0 DO
+            len := MIN(cnt, 16);
+            StartCode;
+            Byte4(len, idx DIV 256, idx MOD 256, 0);
+            FOR i := 1 TO len DO
+                Byte(mem[idx]);
+                INC(idx)
+            END;
+            DEC(cnt, len);
+            NewLine
+        END
+    END Data;
 
 
 PROCEDURE ExtLA* (LA: INTEGER);
-BEGIN
-    ASSERT((0 <= LA) & (LA <= 0FFFFH));
-    StartCode;
-    Byte4(2, 0, 0, 4);
-    Byte(LA DIV 256);
-    Byte(LA MOD 256);
-    NewLine
-END ExtLA;
+    BEGIN
+        ASSERT((0 <= LA) & (LA <= 0FFFFH));
+        StartCode;
+        Byte4(2, 0, 0, 4);
+        Byte(LA DIV 256);
+        Byte(LA MOD 256);
+        NewLine
+    END ExtLA;
 
 
 PROCEDURE Data2* (mem: CHL.BYTELIST; idx, cnt, LA: INTEGER);
-VAR
-    i, len, offset: INTEGER;
-
-BEGIN
-    ExtLA(LA);
-    offset := 0;
-    WHILE cnt > 0 DO
-        ASSERT(offset <= 65536);
-        IF offset = 65536 THEN
-            INC(LA);
-            ExtLA(LA);
-            offset := 0
-        END;
-        len := MIN(cnt, 16);
-        StartCode;
-        Byte4(len, offset DIV 256, offset MOD 256, 0);
-        FOR i := 1 TO len DO
-            Byte(CHL.GetByte(mem, idx));
-            INC(idx);
-            INC(offset)
-        END;
-        DEC(cnt, len);
-        NewLine
-    END
-END Data2;
+    VAR
+        i, len, offset: INTEGER;
+
+    BEGIN
+        ExtLA(LA);
+        offset := 0;
+        WHILE cnt > 0 DO
+            ASSERT(offset <= 65536);
+            IF offset = 65536 THEN
+                INC(LA);
+                ExtLA(LA);
+                offset := 0
+            END;
+            len := MIN(cnt, 16);
+            StartCode;
+            Byte4(len, offset DIV 256, offset MOD 256, 0);
+            FOR i := 1 TO len DO
+                Byte(CHL.GetByte(mem, idx));
+                INC(idx);
+                INC(offset)
+            END;
+            DEC(cnt, len);
+            NewLine
+        END
+    END Data2;
 
 
 PROCEDURE End*;
-BEGIN
-    StartCode;
-    Byte4(0, 0, 0, 1);
-    NewLine
-END End;
+    BEGIN
+        StartCode;
+        Byte4(0, 0, 0, 1);
+        NewLine
+    END End;
 
 
 END HEX.

+ 699 - 706
source/IL.ob07

@@ -1,11 +1,4 @@
-(*
-    BSD 2-Clause License
-
-    Copyright (c) 2018-2023, Anton Krotov
-    All rights reserved.
-*)
-
-MODULE IL;
+MODULE IL;
 
 IMPORT LISTS, SCAN, STRINGS, CHL := CHUNKLISTS, C := COLLECTIONS, TARGETS, PATHS;
 
@@ -214,146 +207,112 @@ VAR
 
 
 PROCEDURE set_dmin* (value: INTEGER);
-BEGIN
-    codes.dmin := value
-END set_dmin;
+    BEGIN
+        codes.dmin := value
+    END set_dmin;
 
 
 PROCEDURE set_bss* (value: INTEGER);
-BEGIN
-    codes.bss := value
-END set_bss;
+    BEGIN
+        codes.bss := value
+    END set_bss;
 
 
 PROCEDURE set_rtl* (idx, label: INTEGER);
-BEGIN
-    codes.rtl[idx] := label
-END set_rtl;
+    BEGIN
+        codes.rtl[idx] := label
+    END set_rtl;
 
 
 PROCEDURE NewCmd (): COMMAND;
-VAR
-    cmd:   COMMAND;
-    citem: C.ITEM;
+    VAR
+        cmd:   COMMAND;
+        citem: C.ITEM;
 
-BEGIN
-    citem := C.pop(commands);
-    IF citem = NIL THEN
-        NEW(cmd)
-    ELSE
-        cmd := citem(COMMAND)
-    END
+    BEGIN
+        citem := C.pop(commands);
+        IF citem = NIL THEN
+            NEW(cmd)
+        ELSE
+            cmd := citem(COMMAND)
+        END
 
-    RETURN cmd
-END NewCmd;
+        RETURN cmd
+    END NewCmd;
 
 
 PROCEDURE setlast* (cmd: COMMAND);
-BEGIN
-    codes.last := cmd
-END setlast;
+    BEGIN
+        codes.last := cmd
+    END setlast;
 
 
 PROCEDURE getlast* (): COMMAND;
-    RETURN codes.last
-END getlast;
+        RETURN codes.last
+    END getlast;
 
 
 PROCEDURE PutByte (b: BYTE);
-BEGIN
-    CHL.PushByte(codes.data, b)
-END PutByte;
+    BEGIN
+        CHL.PushByte(codes.data, b)
+    END PutByte;
 
 
 PROCEDURE AlignData (n: INTEGER);
-BEGIN
-    WHILE CHL.Length(codes.data) MOD n # 0 DO
-        PutByte(0)
-    END
-END AlignData;
+    BEGIN
+        WHILE CHL.Length(codes.data) MOD n # 0 DO
+            PutByte(0)
+        END
+    END AlignData;
 
 
 PROCEDURE putstr* (s: ARRAY OF CHAR): INTEGER;
-VAR
-    i, n, res: INTEGER;
-BEGIN
-    IF TARGETS.WinLin THEN
-        AlignData(16)
-    END;
-    res := CHL.Length(codes.data);
-    i := 0;
-    n := LENGTH(s);
-    WHILE i < n DO
-        PutByte(ORD(s[i]));
-        INC(i)
-    END;
-
-    PutByte(0)
-
-    RETURN res
-END putstr;
-
-
-PROCEDURE putstr1* (c: INTEGER): INTEGER;
-VAR
-    res: INTEGER;
-
-BEGIN
-    IF codes.charoffs[c] = -1 THEN
+    VAR
+        i, n, res: INTEGER;
+    BEGIN
         IF TARGETS.WinLin THEN
             AlignData(16)
         END;
         res := CHL.Length(codes.data);
-        PutByte(c);
-        PutByte(0);
-        codes.charoffs[c] := res
-    ELSE
-        res := codes.charoffs[c]
-    END
-
-    RETURN res
-END putstr1;
+        i := 0;
+        n := LENGTH(s);
+        WHILE i < n DO
+            PutByte(ORD(s[i]));
+            INC(i)
+        END;
 
+        PutByte(0)
 
-PROCEDURE putstrW* (s: ARRAY OF CHAR): INTEGER;
-VAR
-    i, n, res: INTEGER;
+        RETURN res
+    END putstr;
 
-BEGIN
-    IF TARGETS.WinLin THEN
-        AlignData(16)
-    ELSE
-        AlignData(2)
-    END;
-    res := CHL.Length(codes.data);
 
-    n := STRINGS.Utf8To16(s, codes.wstr);
+PROCEDURE putstr1* (c: INTEGER): INTEGER;
+    VAR
+        res: INTEGER;
 
-    i := 0;
-    WHILE i < n DO
-        IF TARGETS.LittleEndian THEN
-            PutByte(ORD(codes.wstr[i]) MOD 256);
-            PutByte(ORD(codes.wstr[i]) DIV 256)
+    BEGIN
+        IF codes.charoffs[c] = -1 THEN
+            IF TARGETS.WinLin THEN
+                AlignData(16)
+            END;
+            res := CHL.Length(codes.data);
+            PutByte(c);
+            PutByte(0);
+            codes.charoffs[c] := res
         ELSE
-            PutByte(ORD(codes.wstr[i]) DIV 256);
-            PutByte(ORD(codes.wstr[i]) MOD 256)
-        END;
-        INC(i)
-    END;
-
-    PutByte(0);
-    PutByte(0)
+            res := codes.charoffs[c]
+        END
 
-    RETURN res
-END putstrW;
+        RETURN res
+    END putstr1;
 
 
-PROCEDURE putstrW1* (c: INTEGER): INTEGER;
-VAR
-    res: INTEGER;
+PROCEDURE putstrW* (s: ARRAY OF CHAR): INTEGER;
+    VAR
+        i, n, res: INTEGER;
 
-BEGIN
-    IF codes.wcharoffs[c] = -1 THEN
+    BEGIN
         IF TARGETS.WinLin THEN
             AlignData(16)
         ELSE
@@ -361,841 +320,875 @@ BEGIN
         END;
         res := CHL.Length(codes.data);
 
-        IF TARGETS.LittleEndian THEN
-            PutByte(c MOD 256);
-            PutByte(c DIV 256)
-        ELSE
-            PutByte(c DIV 256);
-            PutByte(c MOD 256)
+        n := STRINGS.Utf8To16(s, codes.wstr);
+
+        i := 0;
+        WHILE i < n DO
+            IF TARGETS.LittleEndian THEN
+                PutByte(ORD(codes.wstr[i]) MOD 256);
+                PutByte(ORD(codes.wstr[i]) DIV 256)
+            ELSE
+                PutByte(ORD(codes.wstr[i]) DIV 256);
+                PutByte(ORD(codes.wstr[i]) MOD 256)
+            END;
+            INC(i)
         END;
 
         PutByte(0);
-        PutByte(0);
+        PutByte(0)
+
+        RETURN res
+    END putstrW;
+
+
+PROCEDURE putstrW1* (c: INTEGER): INTEGER;
+    VAR
+        res: INTEGER;
+
+    BEGIN
+        IF codes.wcharoffs[c] = -1 THEN
+            IF TARGETS.WinLin THEN
+                AlignData(16)
+            ELSE
+                AlignData(2)
+            END;
+            res := CHL.Length(codes.data);
+
+            IF TARGETS.LittleEndian THEN
+                PutByte(c MOD 256);
+                PutByte(c DIV 256)
+            ELSE
+                PutByte(c DIV 256);
+                PutByte(c MOD 256)
+            END;
 
-        codes.wcharoffs[c] := res
-    ELSE
-        res := codes.wcharoffs[c]
-    END
+            PutByte(0);
+            PutByte(0);
 
-    RETURN res
-END putstrW1;
+            codes.wcharoffs[c] := res
+        ELSE
+            res := codes.wcharoffs[c]
+        END
+
+        RETURN res
+    END putstrW1;
 
 
 PROCEDURE push (stk: CMDSTACK; cmd: COMMAND);
-BEGIN
-    INC(stk.top);
-    stk.data[stk.top] := cmd
-END push;
+    BEGIN
+        INC(stk.top);
+        stk.data[stk.top] := cmd
+    END push;
 
 
 PROCEDURE pop (stk: CMDSTACK): COMMAND;
-VAR
-    res: COMMAND;
-BEGIN
-    res := stk.data[stk.top];
-    DEC(stk.top)
-    RETURN res
-END pop;
+    VAR
+        res: COMMAND;
+    BEGIN
+        res := stk.data[stk.top];
+        DEC(stk.top)
+        RETURN res
+    END pop;
 
 
 PROCEDURE pushBegEnd* (VAR beg, _end: COMMAND);
-BEGIN
-    push(codes.begcall, beg);
-    push(codes.endcall, _end);
-    beg := codes.last;
-    _end := beg.next(COMMAND)
-END pushBegEnd;
+    BEGIN
+        push(codes.begcall, beg);
+        push(codes.endcall, _end);
+        beg := codes.last;
+        _end := beg.next(COMMAND)
+    END pushBegEnd;
 
 
 PROCEDURE popBegEnd* (VAR beg, _end: COMMAND);
-BEGIN
-    beg := pop(codes.begcall);
-    _end := pop(codes.endcall)
-END popBegEnd;
+    BEGIN
+        beg := pop(codes.begcall);
+        _end := pop(codes.endcall)
+    END popBegEnd;
 
 
 PROCEDURE AddRec* (base: INTEGER);
-BEGIN
-    CHL.PushInt(codes.types, base)
-END AddRec;
+    BEGIN
+        CHL.PushInt(codes.types, base)
+    END AddRec;
 
 
 PROCEDURE insert (cur, nov: COMMAND);
-VAR
-    old_opcode, param2: INTEGER;
-
-
-    PROCEDURE set (cur: COMMAND; opcode, param2: INTEGER);
-    BEGIN
-        cur.opcode := opcode;
-        cur.param1 := cur.param2;
-        cur.param2 := param2
-    END set;
+    VAR
+        old_opcode, param2: INTEGER;
 
 
-BEGIN
-    IF CPU IN {TARGETS.cpuX86, TARGETS.cpuAMD64, TARGETS.cpuMSP430} THEN
+        PROCEDURE set (cur: COMMAND; opcode, param2: INTEGER);
+        BEGIN
+            cur.opcode := opcode;
+            cur.param1 := cur.param2;
+            cur.param2 := param2
+        END set;
 
-        old_opcode := cur.opcode;
-        param2 := nov.param2;
 
-        IF (nov.opcode = opPARAM) & (param2 = 1) THEN
+    BEGIN
+        IF CPU IN {TARGETS.cpuX86, TARGETS.cpuAMD64, TARGETS.cpuMSP430} THEN
+
+            old_opcode := cur.opcode;
+            param2 := nov.param2;
+
+            IF (nov.opcode = opPARAM) & (param2 = 1) THEN
+
+                CASE old_opcode OF
+                |opGLOAD64: cur.opcode := opGLOAD64_PARAM
+                |opLLOAD64: cur.opcode := opLLOAD64_PARAM
+                |opLOAD64:  cur.opcode := opLOAD64_PARAM
+                |opGLOAD32: cur.opcode := opGLOAD32_PARAM
+                |opLLOAD32: cur.opcode := opLLOAD32_PARAM
+                |opLOAD32:  cur.opcode := opLOAD32_PARAM
+                |opSADR:    cur.opcode := opSADR_PARAM
+                |opVADR:    cur.opcode := opVADR_PARAM
+                |opCONST:   cur.opcode := opCONST_PARAM
+                ELSE
+                    old_opcode := -1
+                END
+
+            ELSIF old_opcode = opLADR THEN
+
+                CASE nov.opcode OF
+                |opSAVEC: set(cur, opLADR_SAVEC, param2)
+                |opSAVE:  cur.opcode := opLADR_SAVE
+                |opINC:   cur.opcode := opLADR_INC
+                |opDEC:   cur.opcode := opLADR_DEC
+                |opINCB:  cur.opcode := opLADR_INCB
+                |opDECB:  cur.opcode := opLADR_DECB
+                |opINCL:  cur.opcode := opLADR_INCL
+                |opEXCL:  cur.opcode := opLADR_EXCL
+                |opUNPK:  cur.opcode := opLADR_UNPK
+                |opINCC:  set(cur, opLADR_INCC, param2)
+                |opINCCB: set(cur, opLADR_INCCB, param2)
+                |opDECCB: set(cur, opLADR_DECCB, param2)
+                |opINCLC: set(cur, opLADR_INCLC, param2)
+                |opEXCLC: set(cur, opLADR_EXCLC, param2)
+                ELSE
+                    old_opcode := -1
+                END
+
+            ELSIF (nov.opcode = opSAVEC) & (old_opcode = opGADR) THEN
+                set(cur, opGADR_SAVEC, param2)
+
+            ELSIF (nov.opcode = opMULC) & (old_opcode = opMULC) THEN
+                cur.param2 := cur.param2 * param2
+
+            ELSIF (nov.opcode = opADDC) & (old_opcode = opADDC) THEN
+                INC(cur.param2, param2)
 
-            CASE old_opcode OF
-            |opGLOAD64: cur.opcode := opGLOAD64_PARAM
-            |opLLOAD64: cur.opcode := opLLOAD64_PARAM
-            |opLOAD64:  cur.opcode := opLOAD64_PARAM
-            |opGLOAD32: cur.opcode := opGLOAD32_PARAM
-            |opLLOAD32: cur.opcode := opLLOAD32_PARAM
-            |opLOAD32:  cur.opcode := opLOAD32_PARAM
-            |opSADR:    cur.opcode := opSADR_PARAM
-            |opVADR:    cur.opcode := opVADR_PARAM
-            |opCONST:   cur.opcode := opCONST_PARAM
             ELSE
                 old_opcode := -1
             END
 
-        ELSIF old_opcode = opLADR THEN
-
-            CASE nov.opcode OF
-            |opSAVEC: set(cur, opLADR_SAVEC, param2)
-            |opSAVE:  cur.opcode := opLADR_SAVE
-            |opINC:   cur.opcode := opLADR_INC
-            |opDEC:   cur.opcode := opLADR_DEC
-            |opINCB:  cur.opcode := opLADR_INCB
-            |opDECB:  cur.opcode := opLADR_DECB
-            |opINCL:  cur.opcode := opLADR_INCL
-            |opEXCL:  cur.opcode := opLADR_EXCL
-            |opUNPK:  cur.opcode := opLADR_UNPK
-            |opINCC:  set(cur, opLADR_INCC, param2)
-            |opINCCB: set(cur, opLADR_INCCB, param2)
-            |opDECCB: set(cur, opLADR_DECCB, param2)
-            |opINCLC: set(cur, opLADR_INCLC, param2)
-            |opEXCLC: set(cur, opLADR_EXCLC, param2)
+        ELSIF CPU IN {TARGETS.cpuTHUMB, TARGETS.cpuRVM32I, TARGETS.cpuRVM64I} THEN
+
+            old_opcode := cur.opcode;
+            param2 := nov.param2;
+
+            IF (old_opcode = opLADR) & (nov.opcode = opSAVE) THEN
+                cur.opcode := opLADR_SAVE
+            ELSIF (old_opcode = opLADR) & (nov.opcode = opINCC) THEN
+                set(cur, opLADR_INCC, param2)
+            ELSIF (nov.opcode = opMULC) & (old_opcode = opMULC) THEN
+                cur.param2 := cur.param2 * param2
+            ELSIF (nov.opcode = opADDC) & (old_opcode = opADDC) THEN
+                INC(cur.param2, param2)
             ELSE
                 old_opcode := -1
             END
 
-        ELSIF (nov.opcode = opSAVEC) & (old_opcode = opGADR) THEN
-            set(cur, opGADR_SAVEC, param2)
-
-        ELSIF (nov.opcode = opMULC) & (old_opcode = opMULC) THEN
-            cur.param2 := cur.param2 * param2
-
-        ELSIF (nov.opcode = opADDC) & (old_opcode = opADDC) THEN
-            INC(cur.param2, param2)
-
         ELSE
             old_opcode := -1
-        END
-
-    ELSIF CPU IN {TARGETS.cpuTHUMB, TARGETS.cpuRVM32I, TARGETS.cpuRVM64I} THEN
-
-        old_opcode := cur.opcode;
-        param2 := nov.param2;
+        END;
 
-        IF (old_opcode = opLADR) & (nov.opcode = opSAVE) THEN
-            cur.opcode := opLADR_SAVE
-        ELSIF (old_opcode = opLADR) & (nov.opcode = opINCC) THEN
-            set(cur, opLADR_INCC, param2)
-        ELSIF (nov.opcode = opMULC) & (old_opcode = opMULC) THEN
-            cur.param2 := cur.param2 * param2
-        ELSIF (nov.opcode = opADDC) & (old_opcode = opADDC) THEN
-            INC(cur.param2, param2)
+        IF old_opcode = -1 THEN
+            LISTS.insert(codes.commands, cur, nov);
+            codes.last := nov
         ELSE
-            old_opcode := -1
+            C.push(commands, nov);
+            codes.last := cur
         END
-
-    ELSE
-        old_opcode := -1
-    END;
-
-    IF old_opcode = -1 THEN
-        LISTS.insert(codes.commands, cur, nov);
-        codes.last := nov
-    ELSE
-        C.push(commands, nov);
-        codes.last := cur
-    END
-END insert;
+    END insert;
 
 
 PROCEDURE AddCmd* (opcode: INTEGER; param: INTEGER);
-VAR
-    cmd: COMMAND;
-BEGIN
-    cmd := NewCmd();
-    cmd.opcode := opcode;
-    cmd.param1 := 0;
-    cmd.param2 := param;
-    insert(codes.last, cmd)
-END AddCmd;
+    VAR
+        cmd: COMMAND;
+    BEGIN
+        cmd := NewCmd();
+        cmd.opcode := opcode;
+        cmd.param1 := 0;
+        cmd.param2 := param;
+        insert(codes.last, cmd)
+    END AddCmd;
 
 
 PROCEDURE AddCmd2* (opcode: INTEGER; param1, param2: INTEGER);
-VAR
-    cmd: COMMAND;
-BEGIN
-    cmd := NewCmd();
-    cmd.opcode := opcode;
-    cmd.param1 := param1;
-    cmd.param2 := param2;
-    insert(codes.last, cmd)
-END AddCmd2;
+    VAR
+        cmd: COMMAND;
+    BEGIN
+        cmd := NewCmd();
+        cmd.opcode := opcode;
+        cmd.param1 := param1;
+        cmd.param2 := param2;
+        insert(codes.last, cmd)
+    END AddCmd2;
 
 
 PROCEDURE Const* (val: INTEGER);
-BEGIN
-    AddCmd(opCONST, val)
-END Const;
+    BEGIN
+        AddCmd(opCONST, val)
+    END Const;
 
 
 PROCEDURE StrAdr* (adr: INTEGER);
-BEGIN
-    AddCmd(opSADR, adr)
-END StrAdr;
+    BEGIN
+        AddCmd(opSADR, adr)
+    END StrAdr;
 
 
 PROCEDURE Param1*;
-BEGIN
-    AddCmd(opPARAM, 1)
-END Param1;
+    BEGIN
+        AddCmd(opPARAM, 1)
+    END Param1;
 
 
 PROCEDURE NewLabel* (): INTEGER;
-BEGIN
-    INC(codes.lcount)
-    RETURN codes.lcount - 1
-END NewLabel;
+    BEGIN
+        INC(codes.lcount)
+        RETURN codes.lcount - 1
+    END NewLabel;
 
 
 PROCEDURE SetLabel* (label: INTEGER);
-BEGIN
-    AddCmd2(opLABEL, label, 0)
-END SetLabel;
+    BEGIN
+        AddCmd2(opLABEL, label, 0)
+    END SetLabel;
 
 
 PROCEDURE SetErrLabel* (errno: INTEGER);
-BEGIN
-    codes.errlabels[errno] := NewLabel();
-    SetLabel(codes.errlabels[errno])
-END SetErrLabel;
+    BEGIN
+        codes.errlabels[errno] := NewLabel();
+        SetLabel(codes.errlabels[errno])
+    END SetErrLabel;
 
 
 PROCEDURE AddCmd0* (opcode: INTEGER);
-BEGIN
-    AddCmd(opcode, 0)
-END AddCmd0;
+    BEGIN
+        AddCmd(opcode, 0)
+    END AddCmd0;
 
 
 PROCEDURE delete (cmd: COMMAND);
-BEGIN
-    LISTS.delete(codes.commands, cmd);
-    C.push(commands, cmd)
-END delete;
+    BEGIN
+        LISTS.delete(codes.commands, cmd);
+        C.push(commands, cmd)
+    END delete;
 
 
 PROCEDURE delete2* (first, last: LISTS.ITEM);
-VAR
-    cur, next: LISTS.ITEM;
-
-BEGIN
-    cur := first;
-
-    IF first # last THEN
-        REPEAT
-            next := cur.next;
-            LISTS.delete(codes.commands, cur);
-            C.push(commands, cur);
-            cur := next
-        UNTIL cur = last
-    END;
+    VAR
+        cur, next: LISTS.ITEM;
+
+    BEGIN
+        cur := first;
+
+        IF first # last THEN
+            REPEAT
+                next := cur.next;
+                LISTS.delete(codes.commands, cur);
+                C.push(commands, cur);
+                cur := next
+            UNTIL cur = last
+        END;
 
-    LISTS.delete(codes.commands, cur);
-    C.push(commands, cur)
-END delete2;
+        LISTS.delete(codes.commands, cur);
+        C.push(commands, cur)
+    END delete2;
 
 
 PROCEDURE Jmp* (opcode: INTEGER; label: INTEGER);
-VAR
-    prev: COMMAND;
-    not:  BOOLEAN;
-
-BEGIN
-    prev := codes.last;
-    not := prev.opcode = opNOT;
-    IF not THEN
-        IF opcode = opJNZ THEN
-            opcode := opJZ
-        ELSIF opcode = opJZ THEN
-            opcode := opJNZ
-        ELSE
-            not := FALSE
-        END
-    END;
+    VAR
+        prev: COMMAND;
+        not:  BOOLEAN;
 
-    AddCmd2(opcode, label, label);
+    BEGIN
+        prev := codes.last;
+        not := prev.opcode = opNOT;
+        IF not THEN
+            IF opcode = opJNZ THEN
+                opcode := opJZ
+            ELSIF opcode = opJZ THEN
+                opcode := opJNZ
+            ELSE
+                not := FALSE
+            END
+        END;
+
+        AddCmd2(opcode, label, label);
 
-    IF not THEN
-        delete(prev)
-    END
-END Jmp;
+        IF not THEN
+            delete(prev)
+        END
+    END Jmp;
 
 
 PROCEDURE AndOrOpt* (VAR label: INTEGER);
-VAR
-    cur, prev: COMMAND;
-    i, op, l: INTEGER;
-    jz, not: BOOLEAN;
-
-BEGIN
-    cur := codes.last;
-    not := cur.opcode = opNOT;
-    IF not THEN
-        cur := cur.prev(COMMAND)
-    END;
+    VAR
+        cur, prev: COMMAND;
+        i, op, l: INTEGER;
+        jz, not: BOOLEAN;
 
-    IF cur.opcode = opAND THEN
-        op := opAND
-    ELSIF cur.opcode = opOR THEN
-        op := opOR
-    ELSE
-        op := -1
-    END;
+    BEGIN
+        cur := codes.last;
+        not := cur.opcode = opNOT;
+        IF not THEN
+            cur := cur.prev(COMMAND)
+        END;
 
-    cur := codes.last;
+        IF cur.opcode = opAND THEN
+            op := opAND
+        ELSIF cur.opcode = opOR THEN
+            op := opOR
+        ELSE
+            op := -1
+        END;
 
-    IF op # -1 THEN
-        IF not THEN
-            IF op = opAND THEN
-                op := opOR
-            ELSE (* op = opOR *)
-                op := opAND
+        cur := codes.last;
+
+        IF op # -1 THEN
+            IF not THEN
+                IF op = opAND THEN
+                    op := opOR
+                ELSE (* op = opOR *)
+                    op := opAND
+                END;
+                prev := cur.prev(COMMAND);
+                delete(cur);
+                cur := prev
             END;
-            prev := cur.prev(COMMAND);
-            delete(cur);
-            cur := prev
-        END;
 
-        FOR i := 1 TO 9 DO
-            IF i = 8 THEN
-                l := cur.param1
-            ELSIF i = 9 THEN
-                jz := cur.opcode = opJZ
+            FOR i := 1 TO 9 DO
+                IF i = 8 THEN
+                    l := cur.param1
+                ELSIF i = 9 THEN
+                    jz := cur.opcode = opJZ
+                END;
+                prev := cur.prev(COMMAND);
+                delete(cur);
+                cur := prev
             END;
-            prev := cur.prev(COMMAND);
-            delete(cur);
-            cur := prev
-        END;
 
-        setlast(cur);
+            setlast(cur);
 
-        IF op = opAND THEN
-            label := l;
-            jz := ~jz
-        END;
+            IF op = opAND THEN
+                label := l;
+                jz := ~jz
+            END;
 
-        IF jz THEN
-            Jmp(opJZ, label)
+            IF jz THEN
+                Jmp(opJZ, label)
+            ELSE
+                Jmp(opJNZ, label)
+            END;
+
+            IF op = opOR THEN
+                SetLabel(l)
+            END
         ELSE
-            Jmp(opJNZ, label)
+            Jmp(opJZ, label)
         END;
 
-        IF op = opOR THEN
-            SetLabel(l)
-        END
-    ELSE
-        Jmp(opJZ, label)
-    END;
-
-    setlast(codes.last)
-END AndOrOpt;
+        setlast(codes.last)
+    END AndOrOpt;
 
 
 PROCEDURE OnError* (line, error: INTEGER);
-BEGIN
-    AddCmd2(opONERR, codes.errlabels[error], line)
-END OnError;
+    BEGIN
+        AddCmd2(opONERR, codes.errlabels[error], line)
+    END OnError;
 
 
 PROCEDURE TypeGuard* (op, t: INTEGER; line, error: INTEGER);
-VAR
-    label: INTEGER;
-BEGIN
-    AddCmd(op, t);
-    label := NewLabel();
-    Jmp(opJNZ, label);
-    OnError(line, error);
-    SetLabel(label)
-END TypeGuard;
+    VAR
+        label: INTEGER;
+    BEGIN
+        AddCmd(op, t);
+        label := NewLabel();
+        Jmp(opJNZ, label);
+        OnError(line, error);
+        SetLabel(label)
+    END TypeGuard;
 
 
 PROCEDURE TypeCheck* (t: INTEGER);
-BEGIN
-    AddCmd(opIS, t)
-END TypeCheck;
+    BEGIN
+        AddCmd(opIS, t)
+    END TypeCheck;
 
 
 PROCEDURE TypeCheckRec* (t: INTEGER);
-BEGIN
-    AddCmd(opISREC, t)
-END TypeCheckRec;
+    BEGIN
+        AddCmd(opISREC, t)
+    END TypeCheckRec;
 
 
 PROCEDURE New* (size, typenum: INTEGER);
-BEGIN
-    AddCmd2(opNEW, typenum, size)
-END New;
+    BEGIN
+        AddCmd2(opNEW, typenum, size)
+    END New;
 
 
 PROCEDURE not*;
-VAR
-    prev: COMMAND;
-BEGIN
-    prev := codes.last;
-    IF prev.opcode = opNOT THEN
-        codes.last := prev.prev(COMMAND);
-        delete(prev)
-    ELSE
-        AddCmd0(opNOT)
-    END
-END not;
+    VAR
+        prev: COMMAND;
+    BEGIN
+        prev := codes.last;
+        IF prev.opcode = opNOT THEN
+            codes.last := prev.prev(COMMAND);
+            delete(prev)
+        ELSE
+            AddCmd0(opNOT)
+        END
+    END not;
 
 
 PROCEDURE _ord*;
-BEGIN
-    IF (codes.last.opcode # opAND) & (codes.last.opcode # opOR) THEN
-        AddCmd0(opORD)
-    END
-END _ord;
+    BEGIN
+        IF (codes.last.opcode # opAND) & (codes.last.opcode # opOR) THEN
+            AddCmd0(opORD)
+        END
+    END _ord;
 
 
 PROCEDURE Enter* (label, params: INTEGER): COMMAND;
-VAR
-    cmd: COMMAND;
+    VAR
+        cmd: COMMAND;
 
-BEGIN
-    cmd := NewCmd();
-    cmd.opcode := opENTER;
-    cmd.param1 := label;
-    cmd.param3 := params;
-    insert(codes.last, cmd)
+    BEGIN
+        cmd := NewCmd();
+        cmd.opcode := opENTER;
+        cmd.param1 := label;
+        cmd.param3 := params;
+        insert(codes.last, cmd)
 
-    RETURN codes.last
-END Enter;
+        RETURN codes.last
+    END Enter;
 
 
 PROCEDURE Leave* (result, float: BOOLEAN; locsize, paramsize: INTEGER): COMMAND;
-BEGIN
-    IF result THEN
-        IF float THEN
-            AddCmd2(opLEAVEF, locsize, paramsize)
+    BEGIN
+        IF result THEN
+            IF float THEN
+                AddCmd2(opLEAVEF, locsize, paramsize)
+            ELSE
+                AddCmd2(opLEAVER, locsize, paramsize)
+            END
         ELSE
-            AddCmd2(opLEAVER, locsize, paramsize)
+            AddCmd2(opLEAVE, locsize, paramsize)
         END
-    ELSE
-        AddCmd2(opLEAVE, locsize, paramsize)
-    END
 
-    RETURN codes.last
-END Leave;
+        RETURN codes.last
+    END Leave;
 
 
 PROCEDURE EnterC* (label: INTEGER): COMMAND;
-BEGIN
-    SetLabel(label)
-    RETURN codes.last
-END EnterC;
+    BEGIN
+        SetLabel(label)
+        RETURN codes.last
+    END EnterC;
 
 
 PROCEDURE LeaveC* (): COMMAND;
-BEGIN
-    AddCmd0(opLEAVEC)
-    RETURN codes.last
-END LeaveC;
+    BEGIN
+        AddCmd0(opLEAVEC)
+        RETURN codes.last
+    END LeaveC;
 
 
 PROCEDURE fastcall (VAR callconv: INTEGER);
-BEGIN
-    IF callconv = call_fast1 THEN
-        AddCmd(opFASTCALL, 1);
-        callconv := call_stack
-    ELSIF callconv = call_fast2 THEN
-        AddCmd(opFASTCALL, 2);
-        callconv := call_stack
-    END
-END fastcall;
+    BEGIN
+        IF callconv = call_fast1 THEN
+            AddCmd(opFASTCALL, 1);
+            callconv := call_stack
+        ELSIF callconv = call_fast2 THEN
+            AddCmd(opFASTCALL, 2);
+            callconv := call_stack
+        END
+    END fastcall;
 
 
 PROCEDURE Call* (proc, callconv, fparams: INTEGER);
-BEGIN
-    fastcall(callconv);
-    CASE callconv OF
-    |call_stack: Jmp(opCALL, proc)
-    |call_win64: Jmp(opWIN64CALL, proc)
-    |call_sysv:  Jmp(opSYSVCALL, proc)
-    END;
-    codes.last(COMMAND).param2 := fparams
-END Call;
+    BEGIN
+        fastcall(callconv);
+        CASE callconv OF
+        |call_stack: Jmp(opCALL, proc)
+        |call_win64: Jmp(opWIN64CALL, proc)
+        |call_sysv:  Jmp(opSYSVCALL, proc)
+        END;
+        codes.last(COMMAND).param2 := fparams
+    END Call;
 
 
 PROCEDURE CallImp* (proc: LISTS.ITEM; callconv, fparams: INTEGER);
-BEGIN
-    fastcall(callconv);
-    CASE callconv OF
-    |call_stack: Jmp(opCALLI, proc(IMPORT_PROC).label)
-    |call_win64: Jmp(opWIN64CALLI, proc(IMPORT_PROC).label)
-    |call_sysv:  Jmp(opSYSVCALLI, proc(IMPORT_PROC).label)
-    END;
-    codes.last(COMMAND).param2 := fparams
-END CallImp;
+    BEGIN
+        fastcall(callconv);
+        CASE callconv OF
+        |call_stack: Jmp(opCALLI, proc(IMPORT_PROC).label)
+        |call_win64: Jmp(opWIN64CALLI, proc(IMPORT_PROC).label)
+        |call_sysv:  Jmp(opSYSVCALLI, proc(IMPORT_PROC).label)
+        END;
+        codes.last(COMMAND).param2 := fparams
+    END CallImp;
 
 
 PROCEDURE CallP* (callconv, fparams: INTEGER);
-BEGIN
-    fastcall(callconv);
-    CASE callconv OF
-    |call_stack: AddCmd0(opCALLP)
-    |call_win64: AddCmd(opWIN64CALLP, fparams)
-    |call_sysv:  AddCmd(opSYSVCALLP, fparams)
-    END
-END CallP;
+    BEGIN
+        fastcall(callconv);
+        CASE callconv OF
+        |call_stack: AddCmd0(opCALLP)
+        |call_win64: AddCmd(opWIN64CALLP, fparams)
+        |call_sysv:  AddCmd(opSYSVCALLP, fparams)
+        END
+    END CallP;
 
 
 PROCEDURE AssignProc* (proc: INTEGER);
-BEGIN
-    Jmp(opSAVEP, proc)
-END AssignProc;
+    BEGIN
+        Jmp(opSAVEP, proc)
+    END AssignProc;
 
 
 PROCEDURE AssignImpProc* (proc: LISTS.ITEM);
-BEGIN
-    Jmp(opSAVEIP, proc(IMPORT_PROC).label)
-END AssignImpProc;
+    BEGIN
+        Jmp(opSAVEIP, proc(IMPORT_PROC).label)
+    END AssignImpProc;
 
 
 PROCEDURE PushProc* (proc: INTEGER);
-BEGIN
-    Jmp(opPUSHP, proc)
-END PushProc;
+    BEGIN
+        Jmp(opPUSHP, proc)
+    END PushProc;
 
 
 PROCEDURE PushImpProc* (proc: LISTS.ITEM);
-BEGIN
-    Jmp(opPUSHIP, proc(IMPORT_PROC).label)
-END PushImpProc;
+    BEGIN
+        Jmp(opPUSHIP, proc(IMPORT_PROC).label)
+    END PushImpProc;
 
 
 PROCEDURE ProcCmp* (proc: INTEGER; eq: BOOLEAN);
-BEGIN
-    IF eq THEN
-        Jmp(opEQP, proc)
-    ELSE
-        Jmp(opNEP, proc)
-    END
-END ProcCmp;
+    BEGIN
+        IF eq THEN
+            Jmp(opEQP, proc)
+        ELSE
+            Jmp(opNEP, proc)
+        END
+    END ProcCmp;
 
 
 PROCEDURE ProcImpCmp* (proc: LISTS.ITEM; eq: BOOLEAN);
-BEGIN
-    IF eq THEN
-        Jmp(opEQIP, proc(IMPORT_PROC).label)
-    ELSE
-        Jmp(opNEIP, proc(IMPORT_PROC).label)
-    END
-END ProcImpCmp;
+    BEGIN
+        IF eq THEN
+            Jmp(opEQIP, proc(IMPORT_PROC).label)
+        ELSE
+            Jmp(opNEIP, proc(IMPORT_PROC).label)
+        END
+    END ProcImpCmp;
 
 
 PROCEDURE load* (size: INTEGER);
-VAR
-    last: COMMAND;
-
-BEGIN
-    last := codes.last;
-    CASE size OF
-    |1:
-        IF last.opcode = opLADR THEN
-            last.opcode := opLLOAD8
-        ELSIF last.opcode = opVADR THEN
-            last.opcode := opVLOAD8
-        ELSIF last.opcode = opGADR THEN
-            last.opcode := opGLOAD8
-        ELSE
-            AddCmd0(opLOAD8)
-        END
+    VAR
+        last: COMMAND;
 
-    |2:
-        IF last.opcode = opLADR THEN
-            last.opcode := opLLOAD16
-        ELSIF last.opcode = opVADR THEN
-            last.opcode := opVLOAD16
-        ELSIF last.opcode = opGADR THEN
-            last.opcode := opGLOAD16
-        ELSE
-            AddCmd0(opLOAD16)
-        END
+    BEGIN
+        last := codes.last;
+        CASE size OF
+        |1:
+            IF last.opcode = opLADR THEN
+                last.opcode := opLLOAD8
+            ELSIF last.opcode = opVADR THEN
+                last.opcode := opVLOAD8
+            ELSIF last.opcode = opGADR THEN
+                last.opcode := opGLOAD8
+            ELSE
+                AddCmd0(opLOAD8)
+            END
 
-    |4:
-        IF last.opcode = opLADR THEN
-            last.opcode := opLLOAD32
-        ELSIF last.opcode = opVADR THEN
-            last.opcode := opVLOAD32
-        ELSIF last.opcode = opGADR THEN
-            last.opcode := opGLOAD32
-        ELSE
-            AddCmd0(opLOAD32)
-        END
+        |2:
+            IF last.opcode = opLADR THEN
+                last.opcode := opLLOAD16
+            ELSIF last.opcode = opVADR THEN
+                last.opcode := opVLOAD16
+            ELSIF last.opcode = opGADR THEN
+                last.opcode := opGLOAD16
+            ELSE
+                AddCmd0(opLOAD16)
+            END
 
-    |8:
-        IF last.opcode = opLADR THEN
-            last.opcode := opLLOAD64
-        ELSIF last.opcode = opVADR THEN
-            last.opcode := opVLOAD64
-        ELSIF last.opcode = opGADR THEN
-            last.opcode := opGLOAD64
-        ELSE
-            AddCmd0(opLOAD64)
+        |4:
+            IF last.opcode = opLADR THEN
+                last.opcode := opLLOAD32
+            ELSIF last.opcode = opVADR THEN
+                last.opcode := opVLOAD32
+            ELSIF last.opcode = opGADR THEN
+                last.opcode := opGLOAD32
+            ELSE
+                AddCmd0(opLOAD32)
+            END
+
+        |8:
+            IF last.opcode = opLADR THEN
+                last.opcode := opLLOAD64
+            ELSIF last.opcode = opVADR THEN
+                last.opcode := opVLOAD64
+            ELSIF last.opcode = opGADR THEN
+                last.opcode := opGLOAD64
+            ELSE
+                AddCmd0(opLOAD64)
+            END
         END
-    END
-END load;
+    END load;
 
 
 PROCEDURE SysPut* (size: INTEGER);
-BEGIN
-    CASE size OF
-    |1: AddCmd0(opSAVE8)
-    |2: AddCmd0(opSAVE16)
-    |4: AddCmd0(opSAVE32)
-    |8: AddCmd0(opSAVE64)
-    END
-END SysPut;
+    BEGIN
+        CASE size OF
+        |1: AddCmd0(opSAVE8)
+        |2: AddCmd0(opSAVE16)
+        |4: AddCmd0(opSAVE32)
+        |8: AddCmd0(opSAVE64)
+        END
+    END SysPut;
 
 
 PROCEDURE savef* (inv: BOOLEAN);
-BEGIN
-    IF inv THEN
-        AddCmd0(opSAVEFI)
-    ELSE
-        AddCmd0(opSAVEF)
-    END
-END savef;
+    BEGIN
+        IF inv THEN
+            AddCmd0(opSAVEFI)
+        ELSE
+            AddCmd0(opSAVEF)
+        END
+    END savef;
 
 
 PROCEDURE saves* (offset, length: INTEGER);
-BEGIN
-    AddCmd2(opSAVES, length, offset)
-END saves;
+    BEGIN
+        AddCmd2(opSAVES, length, offset)
+    END saves;
 
 
 PROCEDURE abs* (real: BOOLEAN);
-BEGIN
-    IF real THEN
-        AddCmd0(opFABS)
-    ELSE
-        AddCmd0(opABS)
-    END
-END abs;
+    BEGIN
+        IF real THEN
+            AddCmd0(opFABS)
+        ELSE
+            AddCmd0(opABS)
+        END
+    END abs;
 
 
 PROCEDURE shift_minmax* (op: CHAR);
-BEGIN
-    CASE op OF
-    |"A": AddCmd0(opASR)
-    |"L": AddCmd0(opLSL)
-    |"O": AddCmd0(opROR)
-    |"R": AddCmd0(opLSR)
-    |"m": AddCmd0(opMIN)
-    |"x": AddCmd0(opMAX)
-    END
-END shift_minmax;
+    BEGIN
+        CASE op OF
+        |"A": AddCmd0(opASR)
+        |"L": AddCmd0(opLSL)
+        |"O": AddCmd0(opROR)
+        |"R": AddCmd0(opLSR)
+        |"m": AddCmd0(opMIN)
+        |"x": AddCmd0(opMAX)
+        END
+    END shift_minmax;
 
 
 PROCEDURE shift_minmax1* (op: CHAR; x: INTEGER);
-BEGIN
-    CASE op OF
-    |"A": AddCmd(opASR1, x)
-    |"L": AddCmd(opLSL1, x)
-    |"O": AddCmd(opROR1, x)
-    |"R": AddCmd(opLSR1, x)
-    |"m": AddCmd(opMINC, x)
-    |"x": AddCmd(opMAXC, x)
-    END
-END shift_minmax1;
+    BEGIN
+        CASE op OF
+        |"A": AddCmd(opASR1, x)
+        |"L": AddCmd(opLSL1, x)
+        |"O": AddCmd(opROR1, x)
+        |"R": AddCmd(opLSR1, x)
+        |"m": AddCmd(opMINC, x)
+        |"x": AddCmd(opMAXC, x)
+        END
+    END shift_minmax1;
 
 
 PROCEDURE shift_minmax2* (op: CHAR; x: INTEGER);
-BEGIN
-    CASE op OF
-    |"A": AddCmd(opASR2, x)
-    |"L": AddCmd(opLSL2, x)
-    |"O": AddCmd(opROR2, x)
-    |"R": AddCmd(opLSR2, x)
-    |"m": AddCmd(opMINC, x)
-    |"x": AddCmd(opMAXC, x)
-    END
-END shift_minmax2;
+    BEGIN
+        CASE op OF
+        |"A": AddCmd(opASR2, x)
+        |"L": AddCmd(opLSL2, x)
+        |"O": AddCmd(opROR2, x)
+        |"R": AddCmd(opLSR2, x)
+        |"m": AddCmd(opMINC, x)
+        |"x": AddCmd(opMAXC, x)
+        END
+    END shift_minmax2;
 
 
 PROCEDURE len* (dim: INTEGER);
-BEGIN
-    AddCmd(opLEN, dim)
-END len;
+    BEGIN
+        AddCmd(opLEN, dim)
+    END len;
 
 
 PROCEDURE Float* (r: REAL; line, col: INTEGER);
-VAR
-    cmd: COMMAND;
+    VAR
+        cmd: COMMAND;
 
-BEGIN
-    cmd := NewCmd();
-    cmd.opcode := opCONSTF;
-    cmd.float := r;
-    cmd.param1 := line;
-    cmd.param2 := col;
-    insert(codes.last, cmd)
-END Float;
+    BEGIN
+        cmd := NewCmd();
+        cmd.opcode := opCONSTF;
+        cmd.float := r;
+        cmd.param1 := line;
+        cmd.param2 := col;
+        insert(codes.last, cmd)
+    END Float;
 
 
 PROCEDURE drop*;
-BEGIN
-    AddCmd0(opDROP)
-END drop;
+    BEGIN
+        AddCmd0(opDROP)
+    END drop;
 
 
 PROCEDURE _case* (a, b, L, R: INTEGER);
-VAR
-    cmd: COMMAND;
+    VAR
+        cmd: COMMAND;
 
-BEGIN
-    IF a = b THEN
-        cmd := NewCmd();
-        cmd.opcode := opCASELR;
-        cmd.param1 := a;
-        cmd.param2 := L;
-        cmd.param3 := R;
-        insert(codes.last, cmd)
-    ELSE
-        AddCmd2(opCASEL, a, L);
-        AddCmd2(opCASER, b, R)
-    END
-END _case;
+    BEGIN
+        IF a = b THEN
+            cmd := NewCmd();
+            cmd.opcode := opCASELR;
+            cmd.param1 := a;
+            cmd.param2 := L;
+            cmd.param3 := R;
+            insert(codes.last, cmd)
+        ELSE
+            AddCmd2(opCASEL, a, L);
+            AddCmd2(opCASER, b, R)
+        END
+    END _case;
 
 
 PROCEDURE fname* (name: PATHS.PATH);
-VAR
-    cmd: FNAMECMD;
+    VAR
+        cmd: FNAMECMD;
 
-BEGIN
-    NEW(cmd);
-    cmd.opcode := opFNAME;
-    cmd.fname := name;
-    insert(codes.last, cmd)
-END fname;
+    BEGIN
+        NEW(cmd);
+        cmd.opcode := opFNAME;
+        cmd.fname := name;
+        insert(codes.last, cmd)
+    END fname;
 
 
 PROCEDURE AddExp* (label: INTEGER; name: SCAN.IDSTR);
-VAR
-    exp: EXPORT_PROC;
+    VAR
+        exp: EXPORT_PROC;
 
-BEGIN
-    NEW(exp);
-    exp.label := label;
-    exp.name  := name;
-    LISTS.push(codes.export, exp)
-END AddExp;
+    BEGIN
+        NEW(exp);
+        exp.label := label;
+        exp.name  := name;
+        LISTS.push(codes.export, exp)
+    END AddExp;
 
 
 PROCEDURE AddImp* (dll, proc: SCAN.TEXTSTR): IMPORT_PROC;
-VAR
-    lib: IMPORT_LIB;
-    p:   IMPORT_PROC;
+    VAR
+        lib: IMPORT_LIB;
+        p:   IMPORT_PROC;
 
-BEGIN
-    lib := codes._import.first(IMPORT_LIB);
-    WHILE (lib # NIL) & (lib.name # dll) DO
-        lib := lib.next(IMPORT_LIB)
-    END;
+    BEGIN
+        lib := codes._import.first(IMPORT_LIB);
+        WHILE (lib # NIL) & (lib.name # dll) DO
+            lib := lib.next(IMPORT_LIB)
+        END;
 
-    IF lib = NIL THEN
-        NEW(lib);
-        lib.name := dll;
-        lib.procs := LISTS.create(NIL);
-        LISTS.push(codes._import, lib)
-    END;
+        IF lib = NIL THEN
+            NEW(lib);
+            lib.name := dll;
+            lib.procs := LISTS.create(NIL);
+            LISTS.push(codes._import, lib)
+        END;
 
-    p := lib.procs.first(IMPORT_PROC);
-    WHILE (p # NIL) & (p.name # proc) DO
-        p := p.next(IMPORT_PROC)
-    END;
+        p := lib.procs.first(IMPORT_PROC);
+        WHILE (p # NIL) & (p.name # proc) DO
+            p := p.next(IMPORT_PROC)
+        END;
 
-    IF p = NIL THEN
-        NEW(p);
-        p.name  := proc;
-        p.label := NewLabel();
-        p.lib   := lib;
-        p.count := 1;
-        LISTS.push(lib.procs, p)
-    ELSE
-        INC(p.count)
-    END
+        IF p = NIL THEN
+            NEW(p);
+            p.name  := proc;
+            p.label := NewLabel();
+            p.lib   := lib;
+            p.count := 1;
+            LISTS.push(lib.procs, p)
+        ELSE
+            INC(p.count)
+        END
 
-    RETURN p
-END AddImp;
+        RETURN p
+    END AddImp;
 
 
 PROCEDURE DelImport* (imp: LISTS.ITEM);
-VAR
-    lib: IMPORT_LIB;
-
-BEGIN
-    DEC(imp(IMPORT_PROC).count);
-    IF imp(IMPORT_PROC).count = 0 THEN
-        lib := imp(IMPORT_PROC).lib;
-        LISTS.delete(lib.procs, imp);
-        IF lib.procs.first = NIL THEN
-            LISTS.delete(codes._import, lib)
+    VAR
+        lib: IMPORT_LIB;
+
+    BEGIN
+        DEC(imp(IMPORT_PROC).count);
+        IF imp(IMPORT_PROC).count = 0 THEN
+            lib := imp(IMPORT_PROC).lib;
+            LISTS.delete(lib.procs, imp);
+            IF lib.procs.first = NIL THEN
+                LISTS.delete(codes._import, lib)
+            END
         END
-    END
-END DelImport;
+    END DelImport;
 
 
 PROCEDURE init* (pCPU: INTEGER);
-VAR
-    cmd: COMMAND;
-    i:   INTEGER;
+    VAR
+        cmd: COMMAND;
+        i:   INTEGER;
 
-BEGIN
-    commands := C.create();
+    BEGIN
+        commands := C.create();
 
-    CPU := pCPU;
+        CPU := pCPU;
 
-    NEW(codes.begcall);
-    codes.begcall.top := -1;
-    NEW(codes.endcall);
-    codes.endcall.top := -1;
-    codes.commands := LISTS.create(NIL);
-    codes.export   := LISTS.create(NIL);
-    codes._import  := LISTS.create(NIL);
-    codes.types    := CHL.CreateIntList();
-    codes.data     := CHL.CreateByteList();
+        NEW(codes.begcall);
+        codes.begcall.top := -1;
+        NEW(codes.endcall);
+        codes.endcall.top := -1;
+        codes.commands := LISTS.create(NIL);
+        codes.export   := LISTS.create(NIL);
+        codes._import  := LISTS.create(NIL);
+        codes.types    := CHL.CreateIntList();
+        codes.data     := CHL.CreateByteList();
 
-    NEW(cmd); cmd.opcode := opNOP; LISTS.push(codes.commands, cmd);
-    codes.last := cmd;
-    NEW(cmd); cmd.opcode := opNOP; LISTS.push(codes.commands, cmd);
+        NEW(cmd); cmd.opcode := opNOP; LISTS.push(codes.commands, cmd);
+        codes.last := cmd;
+        NEW(cmd); cmd.opcode := opNOP; LISTS.push(codes.commands, cmd);
 
-    AddRec(0);
+        AddRec(0);
 
-    codes.lcount := 0;
+        codes.lcount := 0;
 
-    FOR i := 0 TO LEN(codes.charoffs) - 1 DO
-        codes.charoffs[i] := -1
-    END;
+        FOR i := 0 TO LEN(codes.charoffs) - 1 DO
+            codes.charoffs[i] := -1
+        END;
 
-    FOR i := 0 TO LEN(codes.wcharoffs) - 1 DO
-        codes.wcharoffs[i] := -1
-    END
+        FOR i := 0 TO LEN(codes.wcharoffs) - 1 DO
+            codes.wcharoffs[i] := -1
+        END
 
-END init;
+    END init;
 
 
 END IL.

+ 141 - 148
source/KOS.ob07

@@ -1,11 +1,4 @@
-(*
-    BSD 2-Clause License
-
-    Copyright (c) 2018-2020, 2023, Anton Krotov
-    All rights reserved.
-*)
-
-MODULE KOS;
+MODULE KOS;
 
 IMPORT BIN, WR := WRITER, LISTS, CHL := CHUNKLISTS;
 
@@ -28,188 +21,188 @@ TYPE
 
 
 PROCEDURE Import* (program: BIN.PROGRAM; idata: INTEGER; VAR ImportTable: CHL.INTLIST; VAR len, libcount, size: INTEGER);
-VAR
-    i:   INTEGER;
-    imp: BIN.IMPRT;
-
-BEGIN
-    libcount  := 0;
-    imp := program.imp_list.first(BIN.IMPRT);
-    WHILE imp # NIL DO
-        IF imp.label = 0 THEN
-            INC(libcount)
+    VAR
+        i:   INTEGER;
+        imp: BIN.IMPRT;
+
+    BEGIN
+        libcount  := 0;
+        imp := program.imp_list.first(BIN.IMPRT);
+        WHILE imp # NIL DO
+            IF imp.label = 0 THEN
+                INC(libcount)
+            END;
+            imp := imp.next(BIN.IMPRT)
         END;
-        imp := imp.next(BIN.IMPRT)
-    END;
 
-    len  := libcount * 2 + 2;
-    size := (LISTS.count(program.imp_list) + len + 1) * SIZE_OF_DWORD;
-
-    ImportTable := CHL.CreateIntList();
-    FOR i := 0 TO size DIV SIZE_OF_DWORD - 1 DO
-        CHL.PushInt(ImportTable, 0)
-    END;
+        len  := libcount * 2 + 2;
+        size := (LISTS.count(program.imp_list) + len + 1) * SIZE_OF_DWORD;
 
-    i := 0;
-    imp := program.imp_list.first(BIN.IMPRT);
-    WHILE imp # NIL DO
-
-        IF imp.label = 0 THEN
-            CHL.SetInt(ImportTable, len, 0);
-            INC(len);
-            CHL.SetInt(ImportTable, i, idata + len * SIZE_OF_DWORD);
-            INC(i);
-            CHL.SetInt(ImportTable, i, imp.nameoffs + size + idata);
-            INC(i)
-        ELSE
-            CHL.SetInt(ImportTable, len, imp.nameoffs + size + idata);
-            imp.label := len * SIZE_OF_DWORD;
-            INC(len)
+        ImportTable := CHL.CreateIntList();
+        FOR i := 0 TO size DIV SIZE_OF_DWORD - 1 DO
+            CHL.PushInt(ImportTable, 0)
         END;
 
-        imp := imp.next(BIN.IMPRT)
-    END;
-    CHL.SetInt(ImportTable, len, 0);
-    CHL.SetInt(ImportTable, i, 0);
-    CHL.SetInt(ImportTable, i + 1, 0);
-    INC(len);
-    INC(size, CHL.Length(program._import))
-END Import;
+        i := 0;
+        imp := program.imp_list.first(BIN.IMPRT);
+        WHILE imp # NIL DO
+
+            IF imp.label = 0 THEN
+                CHL.SetInt(ImportTable, len, 0);
+                INC(len);
+                CHL.SetInt(ImportTable, i, idata + len * SIZE_OF_DWORD);
+                INC(i);
+                CHL.SetInt(ImportTable, i, imp.nameoffs + size + idata);
+                INC(i)
+            ELSE
+                CHL.SetInt(ImportTable, len, imp.nameoffs + size + idata);
+                imp.label := len * SIZE_OF_DWORD;
+                INC(len)
+            END;
+
+            imp := imp.next(BIN.IMPRT)
+        END;
+        CHL.SetInt(ImportTable, len, 0);
+        CHL.SetInt(ImportTable, i, 0);
+        CHL.SetInt(ImportTable, i + 1, 0);
+        INC(len);
+        INC(size, CHL.Length(program._import))
+    END Import;
 
 
 PROCEDURE write* (program: BIN.PROGRAM; FileName: ARRAY OF CHAR; kernel: BOOLEAN);
-CONST
-    PARAM_SIZE    = 2048;
-    FileAlignment = 16;
+    CONST
+        PARAM_SIZE    = 2048;
+        FileAlignment = 16;
 
-VAR
-    header: HEADER;
+    VAR
+        header: HEADER;
 
-    base, text, data, idata, bss, offset: INTEGER;
+        base, text, data, idata, bss, offset: INTEGER;
 
-    reloc:   BIN.RELOC;
-    iproc:   BIN.IMPRT;
-    L:       INTEGER;
-    delta:   INTEGER;
+        reloc:   BIN.RELOC;
+        iproc:   BIN.IMPRT;
+        L:       INTEGER;
+        delta:   INTEGER;
 
-    i: INTEGER;
+        i: INTEGER;
 
-    ImportTable: CHL.INTLIST;
-    ILen, libcount, isize: INTEGER;
+        ImportTable: CHL.INTLIST;
+        ILen, libcount, isize: INTEGER;
 
-    icount, dcount, ccount, glob32_size: INTEGER;
+        icount, dcount, ccount, glob32_size: INTEGER;
 
-    code: CHL.BYTELIST;
+        code: CHL.BYTELIST;
 
-BEGIN
-    base := 0;
+    BEGIN
+        base := 0;
 
-    icount := CHL.Length(program._import);
-    dcount := CHL.Length(program.data);
-    ccount := CHL.Length(program.code);
-
-    text := base;
-    IF ~kernel THEN
-        INC(text, HEADER_SIZE)
-    END;
+        icount := CHL.Length(program._import);
+        dcount := CHL.Length(program.data);
+        ccount := CHL.Length(program.code);
 
-    data  := WR.align(text + ccount, FileAlignment);
-    idata := WR.align(data + dcount, FileAlignment);
+        text := base;
+        IF ~kernel THEN
+            INC(text, HEADER_SIZE)
+        END;
 
-    Import(program, idata, ImportTable, ILen, libcount, isize);
+        data  := WR.align(text + ccount, FileAlignment);
+        idata := WR.align(data + dcount, FileAlignment);
 
-    bss := WR.align(idata + isize, FileAlignment);
+        Import(program, idata, ImportTable, ILen, libcount, isize);
 
-    header.menuet01 := "MENUET01";
-    header.ver      :=  1;
-    header.start    :=  text;
-    header.size     :=  idata + isize - base;
-    header.mem      :=  WR.align(header.size + program.stack + program.bss + PARAM_SIZE * 2 + 4096, FileAlignment);
-    header.sp       :=  base + header.mem - PARAM_SIZE * 2;
-    header.param    :=  header.sp;
-    header.path     :=  header.param + PARAM_SIZE;
+        bss := WR.align(idata + isize, FileAlignment);
 
-    code := program.code;
-    reloc := program.rel_list.first(BIN.RELOC);
-    WHILE reloc # NIL DO
+        header.menuet01 := "MENUET01";
+        header.ver      :=  1;
+        header.start    :=  text;
+        header.size     :=  idata + isize - base;
+        header.mem      :=  WR.align(header.size + program.stack + program.bss + PARAM_SIZE * 2 + 4096, FileAlignment);
+        header.sp       :=  base + header.mem - PARAM_SIZE * 2;
+        header.param    :=  header.sp;
+        header.path     :=  header.param + PARAM_SIZE;
 
-        offset := reloc.offset;
-        L := BIN.get32le(code, offset);
-        delta := 3 - offset - text;
+        code := program.code;
+        reloc := program.rel_list.first(BIN.RELOC);
+        WHILE reloc # NIL DO
 
-        CASE reloc.opcode OF
+            offset := reloc.offset;
+            L := BIN.get32le(code, offset);
+            delta := 3 - offset - text;
 
-        |BIN.RIMP:
-              iproc := BIN.GetIProc(program, L);
-              delta := idata + iproc.label
+            CASE reloc.opcode OF
 
-        |BIN.RBSS:
-              delta := L + bss
+            |BIN.RIMP:
+                iproc := BIN.GetIProc(program, L);
+                delta := idata + iproc.label
 
-        |BIN.RDATA:
-              delta := L + data
+            |BIN.RBSS:
+                delta := L + bss
 
-        |BIN.RCODE:
-              delta := BIN.GetLabel(program, L) + text
+            |BIN.RDATA:
+                delta := L + data
 
-        |BIN.PICDATA:
-              INC(delta, L + data)
+            |BIN.RCODE:
+                delta := BIN.GetLabel(program, L) + text
 
-        |BIN.PICCODE:
-              INC(delta, BIN.GetLabel(program, L) + text)
+            |BIN.PICDATA:
+                INC(delta, L + data)
 
-        |BIN.PICBSS:
-              INC(delta, L + bss)
+            |BIN.PICCODE:
+                INC(delta, BIN.GetLabel(program, L) + text)
 
-        |BIN.PICIMP:
-              iproc := BIN.GetIProc(program, L);
-              INC(delta, idata + iproc.label)
+            |BIN.PICBSS:
+                INC(delta, L + bss)
 
-        |BIN.IMPTAB:
-              INC(delta, idata)
+            |BIN.PICIMP:
+                iproc := BIN.GetIProc(program, L);
+                INC(delta, idata + iproc.label)
 
-        END;
-        BIN.put32le(code, offset, delta);
+            |BIN.IMPTAB:
+                INC(delta, idata)
 
-        reloc := reloc.next(BIN.RELOC)
-    END;
+            END;
+            BIN.put32le(code, offset, delta);
 
-    WR.Create(FileName);
+            reloc := reloc.next(BIN.RELOC)
+        END;
 
-    IF ~kernel THEN
-        FOR i := 0 TO 7 DO
-            WR.WriteByte(ORD(header.menuet01[i]))
+        WR.Create(FileName);
+
+        IF ~kernel THEN
+            FOR i := 0 TO 7 DO
+                WR.WriteByte(ORD(header.menuet01[i]))
+            END;
+            WR.Write32LE(header.ver);
+            WR.Write32LE(header.start);
+            WR.Write32LE(header.size);
+            WR.Write32LE(header.mem);
+            WR.Write32LE(header.sp);
+            WR.Write32LE(header.param);
+            WR.Write32LE(header.path)
         END;
-        WR.Write32LE(header.ver);
-        WR.Write32LE(header.start);
-        WR.Write32LE(header.size);
-        WR.Write32LE(header.mem);
-        WR.Write32LE(header.sp);
-        WR.Write32LE(header.param);
-        WR.Write32LE(header.path)
-    END;
 
-    CHL.WriteToFile(code);
-    WR.Padding(FileAlignment);
+        CHL.WriteToFile(code);
+        WR.Padding(FileAlignment);
 
-    CHL.WriteToFile(program.data);
-    WR.Padding(FileAlignment);
+        CHL.WriteToFile(program.data);
+        WR.Padding(FileAlignment);
 
-    FOR i := 0 TO ILen - 1 DO
-        WR.Write32LE(CHL.GetInt(ImportTable, i))
-    END;
-    CHL.WriteToFile(program._import);
-    WR.Padding(FileAlignment);
-
-    IF kernel THEN
-        glob32_size := program.bss DIV 4 + ORD(program.bss MOD 4 # 0);
-        FOR i := 1 TO glob32_size DO
-            WR.Write32LE(0)
-        END
-    END;
+        FOR i := 0 TO ILen - 1 DO
+            WR.Write32LE(CHL.GetInt(ImportTable, i))
+        END;
+        CHL.WriteToFile(program._import);
+        WR.Padding(FileAlignment);
+
+        IF kernel THEN
+            glob32_size := program.bss DIV 4 + ORD(program.bss MOD 4 # 0);
+            FOR i := 1 TO glob32_size DO
+                WR.Write32LE(0)
+            END
+        END;
 
-    WR.Close
-END write;
+        WR.Close
+    END write;
 
 
 END KOS.

+ 129 - 136
source/LISTS.ob07

@@ -1,11 +1,4 @@
-(*
-    BSD 2-Clause License
-
-    Copyright (c) 2018-2021, Anton Krotov
-    All rights reserved.
-*)
-
-MODULE LISTS;
+MODULE LISTS;
 
 IMPORT C := COLLECTIONS;
 
@@ -26,174 +19,174 @@ TYPE
 
 
 PROCEDURE push* (list: LIST; item: ITEM);
-BEGIN
-    ASSERT(list # NIL);
-    ASSERT(item # NIL);
-
-    IF list.first = NIL THEN
-        list.first := item;
-        item.prev  := NIL
-    ELSE
-        ASSERT(list.last # NIL);
-        item.prev := list.last;
-        list.last.next := item
-    END;
-    list.last := item;
-    item.next := NIL
-END push;
+    BEGIN
+        ASSERT(list # NIL);
+        ASSERT(item # NIL);
+
+        IF list.first = NIL THEN
+            list.first := item;
+            item.prev  := NIL
+        ELSE
+            ASSERT(list.last # NIL);
+            item.prev := list.last;
+            list.last.next := item
+        END;
+        list.last := item;
+        item.next := NIL
+    END push;
 
 
 PROCEDURE pop* (list: LIST): ITEM;
-VAR
-    last: ITEM;
+    VAR
+        last: ITEM;
 
-BEGIN
-    ASSERT(list # NIL);
+    BEGIN
+        ASSERT(list # NIL);
 
-    last := list.last;
+        last := list.last;
 
-    IF last # NIL THEN
-        IF last = list.first THEN
-            list.first := NIL;
-            list.last := NIL
-        ELSE
-            list.last := last.prev;
-            list.last.next := NIL
-        END;
+        IF last # NIL THEN
+            IF last = list.first THEN
+                list.first := NIL;
+                list.last := NIL
+            ELSE
+                list.last := last.prev;
+                list.last.next := NIL
+            END;
 
-        last.next := NIL;
-        last.prev := NIL
-    END
+            last.next := NIL;
+            last.prev := NIL
+        END
 
-    RETURN last
-END pop;
+        RETURN last
+    END pop;
 
 
 PROCEDURE insert* (list: LIST; cur, nov: ITEM);
-VAR
-    next: ITEM;
+    VAR
+        next: ITEM;
 
-BEGIN
-    ASSERT(list # NIL);
-    ASSERT(nov # NIL);
-    ASSERT(cur # NIL);
+    BEGIN
+        ASSERT(list # NIL);
+        ASSERT(nov # NIL);
+        ASSERT(cur # NIL);
 
-    next := cur.next;
+        next := cur.next;
 
-    IF next # NIL THEN
-        next.prev := nov;
-        nov.next := next;
-        cur.next := nov;
-        nov.prev := cur
-    ELSE
-        push(list, nov)
-    END
+        IF next # NIL THEN
+            next.prev := nov;
+            nov.next := next;
+            cur.next := nov;
+            nov.prev := cur
+        ELSE
+            push(list, nov)
+        END
 
-END insert;
+    END insert;
 
 
 PROCEDURE insertL* (list: LIST; cur, nov: ITEM);
-VAR
-    prev: ITEM;
-
-BEGIN
-    ASSERT(list # NIL);
-    ASSERT(nov # NIL);
-    ASSERT(cur # NIL);
-
-    prev := cur.prev;
-
-    IF prev # NIL THEN
-        prev.next := nov;
-        nov.prev := prev
-    ELSE
-        nov.prev := NIL;
-        list.first := nov
-    END;
-    cur.prev := nov;
-    nov.next := cur
-END insertL;
-
+    VAR
+        prev: ITEM;
 
-PROCEDURE delete* (list: LIST; item: ITEM);
-VAR
-    prev, next: ITEM;
+    BEGIN
+        ASSERT(list # NIL);
+        ASSERT(nov # NIL);
+        ASSERT(cur # NIL);
 
-BEGIN
-    ASSERT(list # NIL);
-    ASSERT(item # NIL);
+        prev := cur.prev;
 
-    prev := item.prev;
-    next := item.next;
-
-    IF next # NIL THEN
         IF prev # NIL THEN
-            prev.next := next;
-            next.prev := prev
+            prev.next := nov;
+            nov.prev := prev
         ELSE
-            next.prev := NIL;
-            list.first := next
-        END
-    ELSE
-        IF prev # NIL THEN
-            prev.next := NIL;
-            list.last := prev
+            nov.prev := NIL;
+            list.first := nov
+        END;
+        cur.prev := nov;
+        nov.next := cur
+    END insertL;
+
+
+PROCEDURE delete* (list: LIST; item: ITEM);
+    VAR
+        prev, next: ITEM;
+
+    BEGIN
+        ASSERT(list # NIL);
+        ASSERT(item # NIL);
+
+        prev := item.prev;
+        next := item.next;
+
+        IF next # NIL THEN
+            IF prev # NIL THEN
+                prev.next := next;
+                next.prev := prev
+            ELSE
+                next.prev := NIL;
+                list.first := next
+            END
         ELSE
-            list.first := NIL;
-            list.last := NIL
+            IF prev # NIL THEN
+                prev.next := NIL;
+                list.last := prev
+            ELSE
+                list.first := NIL;
+                list.last := NIL
+            END
         END
-    END
-END delete;
+    END delete;
 
 
 PROCEDURE count* (list: LIST): INTEGER;
-VAR
-    item: ITEM;
-    res:  INTEGER;
-
-BEGIN
-    ASSERT(list # NIL);
-    res := 0;
-
-    item := list.first;
-    WHILE item # NIL DO
-        INC(res);
-        item := item.next
-    END
+    VAR
+        item: ITEM;
+        res:  INTEGER;
+
+    BEGIN
+        ASSERT(list # NIL);
+        res := 0;
+
+        item := list.first;
+        WHILE item # NIL DO
+            INC(res);
+            item := item.next
+        END
 
-    RETURN res
-END count;
+        RETURN res
+    END count;
 
 
 PROCEDURE getidx* (list: LIST; idx: INTEGER): ITEM;
-VAR
-    item: ITEM;
+    VAR
+        item: ITEM;
 
-BEGIN
-    ASSERT(list # NIL);
-    ASSERT(idx >= 0);
+    BEGIN
+        ASSERT(list # NIL);
+        ASSERT(idx >= 0);
 
-    item := list.first;
-    WHILE (item # NIL) & (idx > 0) DO
-        item := item.next;
-        DEC(idx)
-    END
+        item := list.first;
+        WHILE (item # NIL) & (idx > 0) DO
+            item := item.next;
+            DEC(idx)
+        END
 
-    RETURN item
-END getidx;
+        RETURN item
+    END getidx;
 
 
 PROCEDURE create* (list: LIST): LIST;
-BEGIN
-    IF list = NIL THEN
-        NEW(list)
-    END;
+    BEGIN
+        IF list = NIL THEN
+            NEW(list)
+        END;
 
-    list.first := NIL;
-    list.last  := NIL
+        list.first := NIL;
+        list.last  := NIL
 
-    RETURN list
-END create;
+        RETURN list
+    END create;
 
 
 END LISTS.