InOut.mod 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. (*
  2. (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
  3. See the copyright notice in the ACK home directory, in the file "Copyright".
  4. *)
  5. (*$R-*)
  6. IMPLEMENTATION MODULE InOut ;
  7. (*
  8. Module: Wirth's Input/Output module
  9. Author: Ceriel J.H. Jacobs
  10. Version: $Id$
  11. *)
  12. IMPORT Streams;
  13. FROM Conversions IMPORT
  14. ConvertCardinal, ConvertInteger,
  15. ConvertOctal, ConvertHex;
  16. FROM Traps IMPORT Message;
  17. CONST TAB = 11C;
  18. TYPE numbuf = ARRAY[0..255] OF CHAR;
  19. VAR unread: BOOLEAN;
  20. unreadch: CHAR;
  21. CurrIn, CurrOut: Streams.Stream;
  22. result: Streams.StreamResult;
  23. PROCEDURE Read(VAR c : CHAR);
  24. BEGIN
  25. IF unread THEN
  26. unread := FALSE;
  27. c := unreadch;
  28. Done := TRUE;
  29. ELSE
  30. Streams.Read(CurrIn, c, result);
  31. Done := result = Streams.succeeded;
  32. END;
  33. END Read;
  34. PROCEDURE UnRead(ch: CHAR);
  35. BEGIN
  36. unread := TRUE;
  37. unreadch := ch;
  38. END UnRead;
  39. PROCEDURE Write(c: CHAR);
  40. BEGIN
  41. Streams.Write(CurrOut, c, result);
  42. END Write;
  43. PROCEDURE OpenInput(defext: ARRAY OF CHAR);
  44. VAR namebuf : ARRAY [1..128] OF CHAR;
  45. BEGIN
  46. IF CurrIn # Streams.InputStream THEN
  47. Streams.CloseStream(CurrIn, result);
  48. END;
  49. MakeFileName("Name of input file: ", defext, namebuf);
  50. IF NOT Done THEN RETURN; END;
  51. openinput(namebuf);
  52. END OpenInput;
  53. PROCEDURE OpenInputFile(filename: ARRAY OF CHAR);
  54. BEGIN
  55. IF CurrIn # Streams.InputStream THEN
  56. Streams.CloseStream(CurrIn, result);
  57. END;
  58. openinput(filename);
  59. END OpenInputFile;
  60. PROCEDURE openinput(namebuf: ARRAY OF CHAR);
  61. BEGIN
  62. IF (namebuf[0] = '-') AND (namebuf[1] = 0C) THEN
  63. CurrIn := Streams.InputStream;
  64. Done := TRUE;
  65. ELSE
  66. Streams.OpenStream(CurrIn, namebuf, Streams.text,
  67. Streams.reading, result);
  68. Done := result = Streams.succeeded;
  69. END;
  70. END openinput;
  71. PROCEDURE CloseInput;
  72. BEGIN
  73. IF CurrIn # Streams.InputStream THEN
  74. Streams.CloseStream(CurrIn, result);
  75. END;
  76. CurrIn := Streams.InputStream;
  77. END CloseInput;
  78. PROCEDURE OpenOutput(defext: ARRAY OF CHAR);
  79. VAR namebuf : ARRAY [1..128] OF CHAR;
  80. BEGIN
  81. IF CurrOut # Streams.OutputStream THEN
  82. Streams.CloseStream(CurrOut, result);
  83. END;
  84. MakeFileName("Name of output file: ", defext, namebuf);
  85. IF NOT Done THEN RETURN; END;
  86. openoutput(namebuf);
  87. END OpenOutput;
  88. PROCEDURE OpenOutputFile(filename: ARRAY OF CHAR);
  89. BEGIN
  90. IF CurrOut # Streams.OutputStream THEN
  91. Streams.CloseStream(CurrOut, result);
  92. END;
  93. openoutput(filename);
  94. END OpenOutputFile;
  95. PROCEDURE openoutput(namebuf: ARRAY OF CHAR);
  96. BEGIN
  97. IF (namebuf[1] = '-') AND (namebuf[2] = 0C) THEN
  98. CurrOut := Streams.OutputStream;
  99. Done := TRUE;
  100. ELSE
  101. Streams.OpenStream(CurrOut, namebuf, Streams.text,
  102. Streams.writing, result);
  103. Done := result = Streams.succeeded;
  104. END;
  105. END openoutput;
  106. PROCEDURE CloseOutput;
  107. BEGIN
  108. IF CurrOut # Streams.OutputStream THEN
  109. Streams.CloseStream(CurrOut, result);
  110. END;
  111. CurrOut := Streams.OutputStream;
  112. END CloseOutput;
  113. PROCEDURE MakeFileName(prompt, defext : ARRAY OF CHAR;
  114. VAR buf : ARRAY OF CHAR);
  115. VAR i : INTEGER;
  116. j : CARDINAL;
  117. BEGIN
  118. Done := TRUE;
  119. IF Streams.isatty(Streams.InputStream, result) THEN
  120. XWriteString(prompt);
  121. END;
  122. XReadString(buf);
  123. i := 0;
  124. WHILE buf[i] # 0C DO i := i + 1 END;
  125. IF i # 0 THEN
  126. i := i - 1;
  127. IF buf[i] = '.' THEN
  128. FOR j := 0 TO HIGH(defext) DO
  129. i := i + 1;
  130. buf[i] := defext[j];
  131. END;
  132. buf[i+1] := 0C;
  133. END;
  134. RETURN;
  135. END;
  136. Done := FALSE;
  137. END MakeFileName;
  138. PROCEDURE ReadInt(VAR integ : INTEGER);
  139. CONST
  140. SAFELIMITDIV10 = MAX(INTEGER) DIV 10;
  141. SAFELIMITREM10 = MAX(INTEGER) MOD 10;
  142. TYPE
  143. itype = [0..31];
  144. ibuf = ARRAY itype OF CHAR;
  145. VAR
  146. int : INTEGER;
  147. neg : BOOLEAN;
  148. safedigit: [0 .. 9];
  149. chvalue: CARDINAL;
  150. buf : ibuf;
  151. index : itype;
  152. BEGIN
  153. ReadString(buf);
  154. IF NOT Done THEN
  155. RETURN
  156. END;
  157. index := 0;
  158. IF buf[index] = '-' THEN
  159. neg := TRUE;
  160. INC(index);
  161. ELSIF buf[index] = '+' THEN
  162. neg := FALSE;
  163. INC(index);
  164. ELSE
  165. neg := FALSE
  166. END;
  167. safedigit := SAFELIMITREM10;
  168. IF neg THEN safedigit := safedigit + 1 END;
  169. int := 0;
  170. WHILE (buf[index] >= '0') & (buf[index] <= '9') DO
  171. chvalue := ORD(buf[index]) - ORD('0');
  172. IF (int > SAFELIMITDIV10) OR
  173. ( (int = SAFELIMITDIV10) AND
  174. (chvalue > safedigit)) THEN
  175. Message("integer too large");
  176. HALT;
  177. ELSE
  178. int := 10*int + VAL(INTEGER, chvalue);
  179. INC(index)
  180. END;
  181. END;
  182. IF neg THEN
  183. integ := -int
  184. ELSE
  185. integ := int
  186. END;
  187. IF buf[index] > " " THEN
  188. Message("illegal integer");
  189. HALT;
  190. END;
  191. Done := TRUE;
  192. END ReadInt;
  193. PROCEDURE ReadCard(VAR card : CARDINAL);
  194. CONST
  195. SAFELIMITDIV10 = MAX(CARDINAL) DIV 10;
  196. SAFELIMITREM10 = MAX(CARDINAL) MOD 10;
  197. TYPE
  198. itype = [0..31];
  199. ibuf = ARRAY itype OF CHAR;
  200. VAR
  201. int : CARDINAL;
  202. index : itype;
  203. buf : ibuf;
  204. safedigit: [0 .. 9];
  205. chvalue: CARDINAL;
  206. BEGIN
  207. ReadString(buf);
  208. IF NOT Done THEN RETURN; END;
  209. index := 0;
  210. safedigit := SAFELIMITREM10;
  211. int := 0;
  212. WHILE (buf[index] >= '0') & (buf[index] <= '9') DO
  213. chvalue := ORD(buf[index]) - ORD('0');
  214. IF (int > SAFELIMITDIV10) OR
  215. ( (int = SAFELIMITDIV10) AND
  216. (chvalue > safedigit)) THEN
  217. Message("cardinal too large");
  218. HALT;
  219. ELSE
  220. int := 10*int + chvalue;
  221. INC(index);
  222. END;
  223. END;
  224. IF buf[index] > " " THEN
  225. Message("illegal cardinal");
  226. HALT;
  227. END;
  228. card := int;
  229. Done := TRUE;
  230. END ReadCard;
  231. PROCEDURE ReadString(VAR s : ARRAY OF CHAR);
  232. TYPE charset = SET OF CHAR;
  233. VAR i : CARDINAL;
  234. ch : CHAR;
  235. BEGIN
  236. i := 0;
  237. REPEAT
  238. Read(ch);
  239. UNTIL NOT (ch IN charset{' ', TAB, 12C, 15C});
  240. IF NOT Done THEN
  241. RETURN;
  242. END;
  243. UnRead(ch);
  244. REPEAT
  245. Read(ch);
  246. termCH := ch;
  247. IF i <= HIGH(s) THEN
  248. s[i] := ch;
  249. IF (NOT Done) OR (ch <= " ") THEN
  250. s[i] := 0C;
  251. END;
  252. END;
  253. INC(i);
  254. UNTIL (NOT Done) OR (ch <= " ");
  255. IF Done THEN UnRead(ch); END;
  256. END ReadString;
  257. PROCEDURE XReadString(VAR s : ARRAY OF CHAR);
  258. VAR j : CARDINAL;
  259. ch : CHAR;
  260. BEGIN
  261. j := 0;
  262. LOOP
  263. Streams.Read(Streams.InputStream, ch, result);
  264. IF result # Streams.succeeded THEN
  265. EXIT;
  266. END;
  267. IF ch <= " " THEN
  268. s[j] := 0C;
  269. EXIT;
  270. END;
  271. IF j < HIGH(s) THEN
  272. s[j] := ch;
  273. INC(j);
  274. END;
  275. END;
  276. END XReadString;
  277. PROCEDURE XWriteString(s: ARRAY OF CHAR);
  278. VAR i: CARDINAL;
  279. BEGIN
  280. i := 0;
  281. LOOP
  282. IF (i <= HIGH(s)) AND (s[i] # 0C) THEN
  283. Streams.Write(Streams.OutputStream, s[i], result);
  284. INC(i);
  285. ELSE
  286. EXIT;
  287. END;
  288. END;
  289. END XWriteString;
  290. PROCEDURE WriteCard(card, width : CARDINAL);
  291. VAR
  292. buf : numbuf;
  293. BEGIN
  294. ConvertCardinal(card, width, buf);
  295. WriteString(buf);
  296. END WriteCard;
  297. PROCEDURE WriteInt(int : INTEGER; width : CARDINAL);
  298. VAR
  299. buf : numbuf;
  300. BEGIN
  301. ConvertInteger(int, width, buf);
  302. WriteString(buf);
  303. END WriteInt;
  304. PROCEDURE WriteHex(card, width : CARDINAL);
  305. VAR
  306. buf : numbuf;
  307. BEGIN
  308. ConvertHex(card, width, buf);
  309. WriteString(buf);
  310. END WriteHex;
  311. PROCEDURE WriteLn;
  312. BEGIN
  313. Write(EOL)
  314. END WriteLn;
  315. PROCEDURE WriteOct(card, width : CARDINAL);
  316. VAR
  317. buf : numbuf;
  318. BEGIN
  319. ConvertOctal(card, width, buf);
  320. WriteString(buf);
  321. END WriteOct;
  322. PROCEDURE WriteString(str : ARRAY OF CHAR);
  323. VAR
  324. nbytes : CARDINAL;
  325. BEGIN
  326. nbytes := 0;
  327. WHILE (nbytes <= HIGH(str)) AND (str[nbytes] # 0C) DO
  328. Write(str[nbytes]);
  329. INC(nbytes)
  330. END;
  331. END WriteString;
  332. BEGIN (* InOut initialization *)
  333. CurrIn := Streams.InputStream;
  334. CurrOut := Streams.OutputStream;
  335. unread := FALSE;
  336. END InOut.