|
@@ -1,18 +1,21 @@
|
|
MODULE Texts;
|
|
MODULE Texts;
|
|
-IMPORT Files, SYSTEM;
|
|
|
|
|
|
+IMPORT Files, IntToStr := Int, Platform, SYSTEM;
|
|
|
|
|
|
CONST
|
|
CONST
|
|
(* Scanner class values *)
|
|
(* Scanner class values *)
|
|
Inval* = 0; Name* = 1; String* = 2; Int* = 3; Real* = 4;
|
|
Inval* = 0; Name* = 1; String* = 2; Int* = 3; Real* = 4;
|
|
LongReal* = 5; Char* = 6;
|
|
LongReal* = 5; Char* = 6;
|
|
|
|
|
|
|
|
+ isWindows = Platform.Windows;
|
|
|
|
+
|
|
TYPE
|
|
TYPE
|
|
LONGINT* = SYSTEM.INT64;
|
|
LONGINT* = SYSTEM.INT64;
|
|
|
|
|
|
Text* = POINTER TO TextDesc;
|
|
Text* = POINTER TO TextDesc;
|
|
TextDesc* = RECORD
|
|
TextDesc* = RECORD
|
|
len*: LONGINT;
|
|
len*: LONGINT;
|
|
- F: Files.File
|
|
|
|
|
|
+ f: Files.File;
|
|
|
|
+ changed: BOOLEAN
|
|
END;
|
|
END;
|
|
|
|
|
|
Reader* = RECORD
|
|
Reader* = RECORD
|
|
@@ -31,18 +34,29 @@ TYPE
|
|
s*: ARRAY 1900 OF CHAR
|
|
s*: ARRAY 1900 OF CHAR
|
|
END;
|
|
END;
|
|
|
|
|
|
|
|
+ Buffer* = POINTER TO BufDesc;
|
|
|
|
+ BufDesc* = RECORD
|
|
|
|
+ len*: LONGINT;
|
|
|
|
+ f: Files.File
|
|
|
|
+ END;
|
|
|
|
+
|
|
|
|
+ Writer* = RECORD
|
|
|
|
+ buf*: Buffer;
|
|
|
|
+ rider: Files.Rider
|
|
|
|
+ END;
|
|
|
|
+
|
|
PROCEDURE Open*(T: Text; fname: ARRAY OF CHAR);
|
|
PROCEDURE Open*(T: Text; fname: ARRAY OF CHAR);
|
|
-BEGIN T.F := Files.Old(fname);
|
|
|
|
- IF T.F = NIL THEN T.F := Files.New(fname) END;
|
|
|
|
- T.len := Files.Length(T.F)
|
|
|
|
|
|
+BEGIN T.f := Files.Old(fname);
|
|
|
|
+ IF T.f = NIL THEN T.f := Files.New(fname) END;
|
|
|
|
+ T.len := Files.Length(T.f); T.changed := FALSE
|
|
END Open;
|
|
END Open;
|
|
|
|
|
|
PROCEDURE Close*(T: Text);
|
|
PROCEDURE Close*(T: Text);
|
|
-BEGIN IF T.F # NIL THEN Files.Register(T.F) END
|
|
|
|
|
|
+BEGIN IF (T.f # NIL) & T.changed THEN Files.Register(T.f) END
|
|
END Close;
|
|
END Close;
|
|
|
|
|
|
PROCEDURE OpenReader*(VAR R: Reader; T: Text; pos: LONGINT);
|
|
PROCEDURE OpenReader*(VAR R: Reader; T: Text; pos: LONGINT);
|
|
-BEGIN Files.Set(R.rider, T.F, pos); R.eot := FALSE
|
|
|
|
|
|
+BEGIN Files.Set(R.rider, T.f, pos); R.eot := FALSE
|
|
END OpenReader;
|
|
END OpenReader;
|
|
|
|
|
|
PROCEDURE Read*(VAR R: Reader; VAR ch: CHAR);
|
|
PROCEDURE Read*(VAR R: Reader; VAR ch: CHAR);
|
|
@@ -62,6 +76,15 @@ PROCEDURE OpenScanner*(VAR S: Scanner; T: Text; pos: LONGINT);
|
|
BEGIN OpenReader(S, T, pos); S.line := 0; S.nextCh := ' '
|
|
BEGIN OpenReader(S, T, pos); S.line := 0; S.nextCh := ' '
|
|
END OpenScanner;
|
|
END OpenScanner;
|
|
|
|
|
|
|
|
+PROCEDURE Ten(n: INTEGER): REAL;
|
|
|
|
+VAR t, p: REAL;
|
|
|
|
+BEGIN t := 1.0; p := 10.0; (* Compute 10^n *)
|
|
|
|
+ WHILE n > 0 DO
|
|
|
|
+ IF ODD(n) THEN t := p * t END;
|
|
|
|
+ p := p * p; n := n DIV 2
|
|
|
|
+ END ;
|
|
|
|
+RETURN t END Ten;
|
|
|
|
+
|
|
PROCEDURE Scan*(VAR S: Scanner);
|
|
PROCEDURE Scan*(VAR S: Scanner);
|
|
VAR i, n: INTEGER;
|
|
VAR i, n: INTEGER;
|
|
quot: CHAR;
|
|
quot: CHAR;
|
|
@@ -104,17 +127,139 @@ BEGIN
|
|
END
|
|
END
|
|
END Scan;
|
|
END Scan;
|
|
|
|
|
|
-END Texts.
|
|
|
|
|
|
+PROCEDURE OpenBuf*(B: Buffer);
|
|
|
|
+BEGIN B.len := 0; B.f := Files.New('')
|
|
|
|
+END OpenBuf;
|
|
|
|
+
|
|
|
|
+PROCEDURE OpenWriter*(VAR W: Writer);
|
|
|
|
+BEGIN NEW(W.buf); OpenBuf(W.buf); Files.Set(W.rider, W.buf.f, 0)
|
|
|
|
+END OpenWriter;
|
|
|
|
+
|
|
|
|
+PROCEDURE Write*(VAR W: Writer; ch: CHAR);
|
|
|
|
+BEGIN Files.WriteChar(W.rider, ch); INC(W.buf.len)
|
|
|
|
+END Write;
|
|
|
|
+
|
|
|
|
+PROCEDURE WriteLn*(VAR W: Writer);
|
|
|
|
+BEGIN IF isWindows THEN Write(W, 0DX); Write(W, 0AX) ELSE Write(W, 0AX) END
|
|
|
|
+END WriteLn;
|
|
|
|
+
|
|
|
|
+PROCEDURE WriteString*(VAR W: Writer; s: ARRAY OF CHAR);
|
|
|
|
+VAR i: INTEGER;
|
|
|
|
+BEGIN i := 0;
|
|
|
|
+ WHILE s[i] # 0X DO Write(W, s[i]); INC(i) END
|
|
|
|
+END WriteString;
|
|
|
|
+
|
|
|
|
+PROCEDURE WriteInt*(VAR W: Writer; x, n: INTEGER);
|
|
|
|
+VAR i: INTEGER;
|
|
|
|
+ s: ARRAY 30 OF CHAR;
|
|
|
|
+BEGIN IntToStr.Str(x, s);
|
|
|
|
+ i := 0; WHILE s[i] # 0X DO INC(i) END;
|
|
|
|
+ DEC(n, i);
|
|
|
|
+ WHILE n > 0 DO Write(W, ' '); DEC(n) END;
|
|
|
|
+ WriteString(W, s)
|
|
|
|
+END WriteInt;
|
|
|
|
+
|
|
|
|
+PROCEDURE WriteHex* (VAR W: Writer; x: LONGINT);
|
|
|
|
+VAR i: INTEGER; y: LONGINT;
|
|
|
|
+ a: ARRAY 10 OF CHAR;
|
|
|
|
+BEGIN i := 0; Write(W, ' ');
|
|
|
|
+ REPEAT y := x MOD 10H;
|
|
|
|
+ IF y < 10 THEN a[i] := CHR(y + 30H) ELSE a[i] := CHR(y + 37H) END;
|
|
|
|
+ x := x DIV 10H; INC(i)
|
|
|
|
+ UNTIL i = 8;
|
|
|
|
+ REPEAT DEC(i); Write(W, a[i]) UNTIL i = 0
|
|
|
|
+END WriteHex;
|
|
|
|
|
|
-(*
|
|
|
|
-VAR T: Texts.Text;
|
|
|
|
- S: Texts.Scanner;
|
|
|
|
|
|
+PROCEDURE WriteReal* (VAR W: Writer; x: REAL; n: INTEGER);
|
|
|
|
+VAR e, i, k, m: INTEGER;
|
|
|
|
+ d: ARRAY 16 OF CHAR;
|
|
|
|
+BEGIN e := ASR(SYSTEM.VAL(INTEGER, x), 23) MOD 100H; (*binary exponent*)
|
|
|
|
+ IF e = 0 THEN
|
|
|
|
+ WriteString(W, '0');
|
|
|
|
+ WHILE n >= 3 DO Write(W, ' '); DEC(n) END
|
|
|
|
+ ELSIF e = 255 THEN WriteString(W, ' NaN ')
|
|
|
|
+ ELSE Write(W, ' ');
|
|
|
|
+ WHILE n >= 15 DO DEC(n); Write(W, ' ') END;
|
|
|
|
+ (* 2 < n < 9 digits to be written*)
|
|
|
|
+ IF x < 0.0 THEN Write(W, '-'); x := -x ELSE Write(W, ' ') END;
|
|
|
|
+ e := (e - 127) * 77 DIV 256 - 6; (*decimal exponent*)
|
|
|
|
+ IF e >= 0 THEN x := x / Ten(e) ELSE x := Ten(-e) * x END;
|
|
|
|
+ m := FLOOR(x + 0.5);
|
|
|
|
+ IF m >= 10000000 THEN INC(e); m := m DIV 10 END;
|
|
|
|
+ i := 0; k := 13-n;
|
|
|
|
+ REPEAT
|
|
|
|
+ IF i = k THEN INC(m, 5) END; (*rounding*)
|
|
|
|
+ d[i] := CHR(m MOD 10 + 30H); m := m DIV 10; INC(i)
|
|
|
|
+ UNTIL m = 0;
|
|
|
|
+ DEC(i); Write(W, d[i]); Write(W, '.');
|
|
|
|
+ IF i < n-7 THEN n := 0 ELSE n := 14 - n END;
|
|
|
|
+ WHILE i > n DO DEC(i); Write(W, d[i]) END;
|
|
|
|
+ Write(W, 'E'); INC(e, 6);
|
|
|
|
+ IF e < 0 THEN Write(W, '-'); e := -e ELSE Write(W, '+') END;
|
|
|
|
+ Write(W, CHR(e DIV 10 + 30H)); Write(W, CHR(e MOD 10 + 30H))
|
|
|
|
+ END
|
|
|
|
+END WriteReal;
|
|
|
|
+
|
|
|
|
+PROCEDURE WriteRealFix* (VAR W: Writer; x: REAL; n, k: INTEGER);
|
|
|
|
+VAR i, m: INTEGER; neg: BOOLEAN;
|
|
|
|
+ d: ARRAY 12 OF CHAR;
|
|
|
|
+BEGIN
|
|
|
|
+ IF x = 0.0 THEN WriteString(W, '0')
|
|
|
|
+ ELSE
|
|
|
|
+ IF x < 0.0 THEN x := -x; neg := TRUE ELSE neg := FALSE END;
|
|
|
|
+ IF k > 7 THEN k := 7 END;
|
|
|
|
+ x := Ten(k) * x; m := FLOOR(x + 0.5);
|
|
|
|
+ i := 0;
|
|
|
|
+ REPEAT d[i] := CHR(m MOD 10 + 30H); m := m DIV 10; INC(i) UNTIL m = 0;
|
|
|
|
+ Write(W, ' ');
|
|
|
|
+ WHILE n > i + 3 DO Write(W, ' '); DEC(n) END;
|
|
|
|
+ IF neg THEN Write(W, '-'); DEC(n) ELSE Write(W, ' ') END;
|
|
|
|
+ WHILE i > k DO DEC(i); Write(W, d[i]) END;
|
|
|
|
+ Write(W, '.');
|
|
|
|
+ WHILE k > i DO DEC(k); Write(W, '0') END;
|
|
|
|
+ WHILE i > 0 DO DEC(i); Write(W, d[i]) END
|
|
|
|
+ END
|
|
|
|
+END WriteRealFix;
|
|
|
|
+
|
|
|
|
+PROCEDURE Save*(T: Text; beg, end: LONGINT; B: Buffer);
|
|
|
|
+VAR R, W: Files.Rider;
|
|
|
|
+ ch: CHAR;
|
|
BEGIN
|
|
BEGIN
|
|
- NEW(T);
|
|
|
|
- Texts.Open(T, s);
|
|
|
|
- Texts.OpenScanner(S, T, 0);
|
|
|
|
- S.eot: BOOLEAN
|
|
|
|
- Texts.Scan(S);
|
|
|
|
- S.class = Texts.Int
|
|
|
|
- S.i: INTEGER
|
|
|
|
-*)
|
|
|
|
|
|
+ IF end > T.len THEN end := T.len END;
|
|
|
|
+ Files.Set(R, T.f, beg); Files.Set(W, B.f, B.len);
|
|
|
|
+ DEC(end, beg);
|
|
|
|
+ WHILE end > 0 DO Files.ReadChar(R, ch); Files.WriteChar(W, ch) END;
|
|
|
|
+ INC(B.len, end - beg)
|
|
|
|
+END Save;
|
|
|
|
+
|
|
|
|
+PROCEDURE Copy*(SB, DB: Buffer);
|
|
|
|
+VAR R, W: Files.Rider;
|
|
|
|
+ ch: CHAR;
|
|
|
|
+BEGIN Files.Set(R, SB.f, 0); Files.Set(W, DB.f, DB.len);
|
|
|
|
+ Files.ReadChar(R, ch);
|
|
|
|
+ WHILE ~R.eof DO Files.WriteChar(W, ch); Files.ReadChar(R, ch) END;
|
|
|
|
+ INC(DB.len, SB.len)
|
|
|
|
+END Copy;
|
|
|
|
+
|
|
|
|
+PROCEDURE Insert*(T: Text; pos: LONGINT; B: Buffer);
|
|
|
|
+VAR R, W: Files.Rider;
|
|
|
|
+ ch: CHAR;
|
|
|
|
+ n, q: LONGINT;
|
|
|
|
+BEGIN n := T.len - pos;
|
|
|
|
+ IF n > 0 THEN q := B.len - n;
|
|
|
|
+ IF q > 0 THEN Files.Set(W, T.f, T.len);
|
|
|
|
+ WHILE q # 0 DO Files.WriteChar(W, ' '); DEC(q) END
|
|
|
|
+ END;
|
|
|
|
+ Files.Set(R, T.f, pos); Files.Set(W, T.f, pos + B.len);
|
|
|
|
+ WHILE n > 0 DO Files.ReadChar(R, ch); Files.WriteChar(W, ch) END
|
|
|
|
+ END;
|
|
|
|
+ n := B.len; Files.Set(R, B.f, 0); Files.Set(W, T.f, pos);
|
|
|
|
+ WHILE n # 0 DO Files.ReadChar(R, ch); Files.WriteChar(W, ch) END;
|
|
|
|
+ INC(T.len, B.len); T.changed := TRUE
|
|
|
|
+END Insert;
|
|
|
|
+
|
|
|
|
+PROCEDURE Append*(T: Text; B: Buffer);
|
|
|
|
+BEGIN Insert(T, T.len, B)
|
|
|
|
+END Append;
|
|
|
|
+
|
|
|
|
+END Texts.
|