TEXTDRV.ob07 4.1 KB

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