Rev 8859 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
7983 | leency | 1 | (* |
7597 | akron1 | 2 | BSD 2-Clause License |
3 | |||
9177 | akron1 | 4 | Copyright (c) 2018-2021, Anton Krotov |
7597 | akron1 | 5 | All rights reserved. |
6 | *) |
||
7 | |||
8 | MODULE TEXTDRV; |
||
9 | |||
10 | IMPORT FILES, C := COLLECTIONS; |
||
11 | |||
12 | |||
13 | CONST |
||
14 | |||
9177 | akron1 | 15 | CR = 0DX; LF = 0AX; HT = 9X; |
7597 | akron1 | 16 | |
17 | CHUNK = 1024 * 256; |
||
18 | |||
9177 | akron1 | 19 | defTabSize* = 4; |
7597 | akron1 | 20 | |
9177 | akron1 | 21 | |
7597 | akron1 | 22 | TYPE |
23 | |||
24 | TEXT* = POINTER TO RECORD (C.ITEM) |
||
25 | |||
7696 | akron1 | 26 | chunk: ARRAY CHUNK OF CHAR; |
7597 | akron1 | 27 | pos, size: INTEGER; |
28 | file: FILES.FILE; |
||
29 | utf8: BOOLEAN; |
||
30 | CR: BOOLEAN; |
||
31 | |||
32 | line*, col*: INTEGER; |
||
8097 | maxcodehac | 33 | ifc*: INTEGER; |
34 | elsec*: INTEGER; |
||
7597 | akron1 | 35 | eof*: BOOLEAN; |
36 | eol*: BOOLEAN; |
||
8097 | maxcodehac | 37 | skip*: BOOLEAN; |
38 | peak*: CHAR; |
||
39 | _skip*, |
||
40 | _elsif*, |
||
41 | _else*: ARRAY 100 OF BOOLEAN; |
||
42 | fname*: ARRAY 2048 OF CHAR |
||
7597 | akron1 | 43 | |
44 | END; |
||
45 | |||
46 | |||
47 | VAR |
||
48 | |||
49 | texts: C.COLLECTION; |
||
9177 | akron1 | 50 | TabSize: INTEGER; |
7597 | akron1 | 51 | |
52 | |||
53 | PROCEDURE load (text: TEXT); |
||
54 | BEGIN |
||
55 | IF ~text.eof THEN |
||
56 | text.size := FILES.read(text.file, text.chunk, LEN(text.chunk)); |
||
57 | text.pos := 0; |
||
58 | IF text.size = 0 THEN |
||
59 | text.eof := TRUE; |
||
7696 | akron1 | 60 | text.chunk[0] := 0X |
7693 | akron1 | 61 | END; |
7696 | akron1 | 62 | text.peak := text.chunk[0] |
7597 | akron1 | 63 | END |
64 | END load; |
||
65 | |||
66 | |||
7693 | akron1 | 67 | PROCEDURE next* (text: TEXT); |
7597 | akron1 | 68 | VAR |
69 | c: CHAR; |
||
7693 | akron1 | 70 | |
7597 | akron1 | 71 | BEGIN |
72 | IF text.pos < text.size - 1 THEN |
||
7693 | akron1 | 73 | INC(text.pos); |
7696 | akron1 | 74 | text.peak := text.chunk[text.pos] |
7597 | akron1 | 75 | ELSE |
76 | load(text) |
||
77 | END; |
||
78 | |||
79 | IF ~text.eof THEN |
||
80 | |||
7693 | akron1 | 81 | c := text.peak; |
7597 | akron1 | 82 | |
83 | IF c = CR THEN |
||
84 | INC(text.line); |
||
7693 | akron1 | 85 | text.col := 0; |
86 | text.eol := TRUE; |
||
87 | text.CR := TRUE |
||
7597 | akron1 | 88 | ELSIF c = LF THEN |
89 | IF ~text.CR THEN |
||
90 | INC(text.line); |
||
7693 | akron1 | 91 | text.col := 0; |
92 | text.eol := TRUE |
||
7597 | akron1 | 93 | ELSE |
7693 | akron1 | 94 | text.eol := FALSE |
7597 | akron1 | 95 | END; |
96 | text.CR := FALSE |
||
9177 | akron1 | 97 | ELSIF c = HT THEN |
98 | text.col := text.col + TabSize - text.col MOD TabSize; |
||
99 | text.eol := FALSE; |
||
100 | text.CR := FALSE |
||
7597 | akron1 | 101 | ELSE |
102 | IF text.utf8 THEN |
||
7696 | akron1 | 103 | IF ORD(c) DIV 64 # 2 THEN |
7597 | akron1 | 104 | INC(text.col) |
105 | END |
||
106 | ELSE |
||
107 | INC(text.col) |
||
108 | END; |
||
9177 | akron1 | 109 | text.eol := FALSE; |
110 | text.CR := FALSE |
||
7597 | akron1 | 111 | END |
112 | |||
113 | END |
||
114 | |||
115 | END next; |
||
116 | |||
117 | |||
118 | PROCEDURE init (text: TEXT); |
||
119 | BEGIN |
||
120 | IF (text.pos = 0) & (text.size >= 3) THEN |
||
7696 | akron1 | 121 | IF (text.chunk[0] = 0EFX) & |
122 | (text.chunk[1] = 0BBX) & |
||
123 | (text.chunk[2] = 0BFX) THEN |
||
7597 | akron1 | 124 | text.pos := 3; |
125 | text.utf8 := TRUE |
||
126 | END |
||
127 | END; |
||
128 | |||
129 | IF text.size = 0 THEN |
||
7696 | akron1 | 130 | text.chunk[0] := 0X; |
7597 | akron1 | 131 | text.size := 1; |
132 | text.eof := FALSE |
||
133 | END; |
||
134 | |||
135 | text.line := 1; |
||
7693 | akron1 | 136 | text.col := 1; |
7597 | akron1 | 137 | |
7696 | akron1 | 138 | text.peak := text.chunk[text.pos] |
7597 | akron1 | 139 | END init; |
140 | |||
141 | |||
7693 | akron1 | 142 | PROCEDURE close* (VAR text: TEXT); |
7597 | akron1 | 143 | BEGIN |
7693 | akron1 | 144 | IF text # NIL THEN |
145 | IF text.file # NIL THEN |
||
146 | FILES.close(text.file) |
||
147 | END; |
||
7597 | akron1 | 148 | |
7693 | akron1 | 149 | C.push(texts, text); |
150 | text := NIL |
||
7597 | akron1 | 151 | END |
7693 | akron1 | 152 | END close; |
7597 | akron1 | 153 | |
154 | |||
7693 | akron1 | 155 | PROCEDURE open* (name: ARRAY OF CHAR): TEXT; |
7597 | akron1 | 156 | VAR |
7693 | akron1 | 157 | text: TEXT; |
7597 | akron1 | 158 | citem: C.ITEM; |
159 | |||
160 | BEGIN |
||
161 | citem := C.pop(texts); |
||
162 | IF citem = NIL THEN |
||
163 | NEW(text) |
||
164 | ELSE |
||
165 | text := citem(TEXT) |
||
7693 | akron1 | 166 | END; |
7597 | akron1 | 167 | |
168 | IF text # NIL THEN |
||
7696 | akron1 | 169 | text.chunk[0] := 0X; |
7693 | akron1 | 170 | text.pos := 0; |
171 | text.size := 0; |
||
172 | text.utf8 := FALSE; |
||
173 | text.CR := FALSE; |
||
174 | text.line := 1; |
||
175 | text.col := 1; |
||
176 | text.eof := FALSE; |
||
177 | text.eol := FALSE; |
||
8097 | maxcodehac | 178 | text.skip := FALSE; |
179 | text.ifc := 0; |
||
180 | text.elsec := 0; |
||
181 | text._skip[0] := FALSE; |
||
7693 | akron1 | 182 | text.peak := 0X; |
183 | text.file := FILES.open(name); |
||
8097 | maxcodehac | 184 | COPY(name, text.fname); |
7597 | akron1 | 185 | IF text.file # NIL THEN |
7693 | akron1 | 186 | load(text); |
187 | init(text) |
||
188 | ELSE |
||
189 | close(text) |
||
190 | END |
||
7597 | akron1 | 191 | END |
192 | |||
7693 | akron1 | 193 | RETURN text |
194 | END open; |
||
7597 | akron1 | 195 | |
7693 | akron1 | 196 | |
9177 | akron1 | 197 | PROCEDURE setTabSize* (n: INTEGER); |
7597 | akron1 | 198 | BEGIN |
9177 | akron1 | 199 | IF (0 < n) & (n <= 64) THEN |
200 | TabSize := n |
||
201 | ELSE |
||
202 | TabSize := defTabSize |
||
203 | END |
||
204 | END setTabSize; |
||
205 | |||
206 | |||
207 | BEGIN |
||
208 | TabSize := defTabSize; |
||
7597 | akron1 | 209 | texts := C.create() |
7983 | leency | 210 | END TEXTDRV.=>>> |