FileIO-2.mod 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571
  1. IMPLEMENTATION MODULE FileIO;
  2. IMPORT FIO, Strings, SYSTEM, Environment, FileSystem, ProgramArgs;
  3. FROM Storage IMPORT ALLOCATE, DEALLOCATE;
  4. CONST
  5. MaxFiles = BitSetSize;
  6. NameLength = 256;
  7. BufSize = 2048; (*1024 + FIO.BufferOverhead;*)
  8. (*EOF = 0C; (* FileIO.Read returns EOF when eof is reached. *)
  9. EOL = 36C; (* FileIO.Read maps line marks onto EOL
  10. FileIO.Write maps EOL onto cr, lf, or cr/lf
  11. as appropriate for filing system. *)
  12. ESC = 33C; (* Standard ASCII escape. *)
  13. CR = 15C; (* Standard ASCII carriage return. *)
  14. LF = 12C; (* Standard ASCII line feed. *)
  15. BS = 10C; (* Standard ASCII backspace. *)
  16. DEL = 177C; (* Standard ASCII DEL (rub-out). *)*)
  17. TYPE
  18. Buftype = ARRAY [1 .. BufSize] OF CHAR;
  19. File = POINTER TO FileRec;
  20. FileRec = RECORD
  21. ref: FIO.File;
  22. self: File;
  23. handle: CARDINAL;
  24. savedCh: CHAR;
  25. textOK, eof, eol, noOutput, noInput, haveCh: BOOLEAN;
  26. name: ARRAY [0 .. NameLength] OF CHAR;
  27. buffer: Buftype;
  28. END;
  29. VAR
  30. Handles: BITSET;
  31. Opened: ARRAY [0 .. MaxFiles-1] OF File;
  32. FromKeyboard, ToScreen: BOOLEAN;
  33. Param: CARDINAL;
  34. Continue: PROC;
  35. PROCEDURE ErrWrite (ch: CHAR);
  36. BEGIN
  37. FIO.WriteChar(err^.ref, ch)
  38. END ErrWrite;
  39. PROCEDURE ConWrite (ch: CHAR);
  40. BEGIN
  41. ErrWrite(ch);
  42. END ConWrite;
  43. (*PROCEDURE ConRead (VAR ch: CHAR);
  44. VAR
  45. R: SYSTEM.Registers;
  46. BEGIN
  47. R.AX := 0; Lib.Intr(R, 16H); ch := CHR(R.AL);
  48. IF ch = CR THEN ch := EOL END;
  49. END ConRead;*)
  50. PROCEDURE NotRead (f: File): BOOLEAN;
  51. BEGIN
  52. RETURN (f = NIL) OR (f^.self # f) OR (f^.noInput);
  53. END NotRead;
  54. PROCEDURE NotWrite (f: File): BOOLEAN;
  55. BEGIN
  56. RETURN (f = NIL) OR (f^.self # f) OR (f^.noOutput);
  57. END NotWrite;
  58. PROCEDURE NotFile (f: File): BOOLEAN;
  59. BEGIN
  60. RETURN (f = NIL) OR (f^.self # f) OR (File(f) = con) OR (File(f) = err)
  61. OR (File(f) = StdIn) & FromKeyboard
  62. OR (File(f) = StdOut) & ToScreen
  63. END NotFile;
  64. (*PROCEDURE CheckRedirection;
  65. VAR
  66. R: SYSTEM.Registers;
  67. BEGIN
  68. FromKeyboard := FALSE; ToScreen := FALSE;
  69. R.AX := 4400H; R.BX := 0; Lib.Dos(R);
  70. IF ~ (0 IN R.Flags) THEN
  71. IF {7, 0} <= BITSET(R.DX) THEN FromKeyboard := TRUE END;
  72. END;
  73. R.AX := 4400H; R.BX := 1; Lib.Dos(R);
  74. IF ~ (0 IN R.Flags) THEN
  75. IF {7, 1} <= BITSET(R.DX) THEN ToScreen := TRUE END;
  76. END;
  77. END CheckRedirection;*)
  78. PROCEDURE ASCIIZ (VAR s1, s2: ARRAY OF CHAR);
  79. (* Convert s2 to a nul terminated string in s1 *)
  80. VAR
  81. i: CARDINAL;
  82. BEGIN
  83. i := 0;
  84. WHILE (i <= HIGH(s2)) & (s2[i] # 0C) DO
  85. s1[i] := s2[i]; INC(i)
  86. END;
  87. s1[i] := 0C
  88. END ASCIIZ;
  89. PROCEDURE NextParameter (VAR s: ARRAY OF CHAR);
  90. BEGIN
  91. END NextParameter;
  92. PROCEDURE GetEnv (envVar: ARRAY OF CHAR; VAR s: ARRAY OF CHAR);
  93. (*
  94. GetEnvironment - gets the environment variable Env and places
  95. a copy of its value into string, dest.
  96. It returns TRUE if the string Env was found in
  97. the processes environment.
  98. PROCEDURE GetEnvironment (Env: ARRAY OF CHAR;
  99. VAR dest: ARRAY OF CHAR) : BOOLEAN ;
  100. *)
  101. VAR
  102. result : BOOLEAN;
  103. BEGIN
  104. result := Environment.GetEnvironment(envVar, s);
  105. END GetEnv;
  106. PROCEDURE OpenRead (fileName: ARRAY OF CHAR) : FIO.File;
  107. BEGIN
  108. RETURN FIO.OpenToRead(fileName);
  109. END OpenRead;
  110. PROCEDURE Open (VAR f: File; fileName: ARRAY OF CHAR; newFile: BOOLEAN);
  111. BEGIN
  112. ExtractFileName(fileName, name);
  113. FOR i := 0 TO NameLength - 1 DO
  114. name[i] := CAP(name[i])
  115. END;
  116. IF (name[0] = 0C) OR (Compare(name, "CON") = 0) THEN
  117. (* con already opened, but reset it *)
  118. Okay := TRUE;
  119. f := con;
  120. f^.savedCh := 0C;
  121. f^.haveCh := FALSE;
  122. f^.eof := FALSE;
  123. f^.eol := FALSE;
  124. f^.name := "CON";
  125. RETURN
  126. ELSIF Compare(name, "ERR") = 0 THEN
  127. Okay := TRUE;
  128. f := err;
  129. RETURN
  130. ELSE
  131. ALLOCATE(f, SYSTEM.TSIZE(FileRec));
  132. NoWrite := FALSE;
  133. IF newFile THEN
  134. f^.ref := FIO.OpenToWrite(fileName)
  135. ELSE
  136. f^.ref := FIO.OpenToRead(fileName);
  137. IF FIO.IsNoError(f^.ref) THEN
  138. f^.ref := OpenToRead(fileName);
  139. NoWrite := TRUE;
  140. END;
  141. END;
  142. Okay := FIO.IsNoError(f^.ref);
  143. IF ~ Okay
  144. THEN
  145. DEALLOCATE(f, SYSTEM.TSIZE(FileRec)); f := NIL
  146. ELSE
  147. (* textOK below may have to be altered according to implementation *)
  148. f^.savedCh := 0C; f^.haveCh := FALSE; f^.textOK := TRUE;
  149. f^.eof := newFile; f^.eol := newFile; f^.self := f;
  150. f^.noInput := newFile; f^.noOutput := ~ newFile OR NoWrite;
  151. ASCIIZ(f^.name, fileName);
  152. i := 0 (* find next available filehandle *);
  153. WHILE (i IN Handles) & (i < MaxFiles) DO
  154. INC(i)
  155. END;
  156. IF i < MaxFiles THEN
  157. f^.handle := i; INCL(Handles, i); Opened[i] := f
  158. ELSE
  159. WriteString(err, "Too many files");
  160. Okay := FALSE
  161. END;
  162. IF Okay THEN
  163. FIO.AssignBuffer(f^.ref, f^.buffer)
  164. END;
  165. END
  166. END
  167. END Open;
  168. PROCEDURE Close (VAR f: File);
  169. BEGIN
  170. FIO.Close(f)
  171. END Close;
  172. PROCEDURE Delete (VAR f: File);
  173. BEGIN
  174. Fio.Delete(f);
  175. END Delete;
  176. PROCEDURE SearchFile (VAR f: File; envVar, fileName: ARRAY OF CHAR;
  177. newFile: BOOLEAN);
  178. (*
  179. Lookup - looks for a file, filename. If the file is found
  180. then, f, is opened. If it is not found and, newFile,
  181. is TRUE then a new file is created and attached to, f.
  182. If, newFile, is FALSE and no file was found then f.res
  183. is set to notdone.
  184. PROCEDURE Lookup (VAR f: File; filename: ARRAY OF CHAR; newFile: BOOLEAN) ;
  185. *)
  186. BEGIN
  187. FileSystem.Lookup(f,filename,newFile);
  188. END SearchFile;
  189. PROCEDURE ExtractDirectory (fullName: ARRAY OF CHAR;
  190. VAR directory: ARRAY OF CHAR);
  191. BEGIN
  192. END ExtractDirectory;
  193. PROCEDURE ExtractFileName (fullName: ARRAY OF CHAR;
  194. VAR fileName: ARRAY OF CHAR);
  195. BEGIN
  196. END ExtractFileName;
  197. PROCEDURE AppendExtension (oldName, ext: ARRAY OF CHAR;
  198. VAR newName: ARRAY OF CHAR);
  199. BEGIN
  200. END AppendExtension;
  201. PROCEDURE ChangeExtension (oldName, ext: ARRAY OF CHAR;
  202. VAR newName: ARRAY OF CHAR);
  203. BEGIN
  204. END ChangeExtension;
  205. PROCEDURE Length (f: File): INT32;
  206. BEGIN
  207. END Length;
  208. PROCEDURE GetPos (f: File): INT32;
  209. BEGIN
  210. END GetPos;
  211. PROCEDURE SetPos (f: File; pos: INT32);
  212. BEGIN
  213. END SetPos;
  214. PROCEDURE Reset (f: File);
  215. BEGIN
  216. END Reset;
  217. PROCEDURE Rewrite (f: File);
  218. BEGIN
  219. END Rewrite;
  220. PROCEDURE EndOfLine (f: File): BOOLEAN;
  221. BEGIN
  222. END EndOfLine;
  223. PROCEDURE EndOfFile (f: File): BOOLEAN;
  224. BEGIN
  225. END EndOfFile;
  226. PROCEDURE Read (f: File; VAR ch: CHAR);
  227. BEGIN
  228. END Read;
  229. PROCEDURE ReadAgain (f: File);
  230. BEGIN
  231. END ReadAgain;
  232. PROCEDURE ReadLn (f: File);
  233. BEGIN
  234. END ReadLn;
  235. PROCEDURE ReadString (f: File; VAR str: ARRAY OF CHAR);
  236. BEGIN
  237. END ReadString;
  238. PROCEDURE ReadLine (f: File; VAR str: ARRAY OF CHAR);
  239. BEGIN
  240. END ReadLine;
  241. PROCEDURE ReadToken (f: File; VAR str: ARRAY OF CHAR);
  242. BEGIN
  243. END ReadToken;
  244. PROCEDURE ReadInt (f: File; VAR i: INTEGER);
  245. BEGIN
  246. END ReadInt;
  247. PROCEDURE ReadCard (f: File; VAR i: CARDINAL);
  248. BEGIN
  249. END ReadCard;
  250. PROCEDURE ReadBytes (f: File; VAR buf: ARRAY OF SYSTEM.BYTE; VAR len: CARDINAL);
  251. BEGIN
  252. END ReadBytes;
  253. PROCEDURE Write (f: File; ch: CHAR);
  254. BEGIN
  255. END Write;
  256. PROCEDURE WriteLn (f: File);
  257. BEGIN
  258. END WriteLn;
  259. PROCEDURE WriteString (f: File; str: ARRAY OF CHAR);
  260. BEGIN
  261. END WriteString;
  262. PROCEDURE WriteText (f: File; text: ARRAY OF CHAR; len: INTEGER);
  263. BEGIN
  264. END WriteText;
  265. PROCEDURE WriteInt (f: File; n: INTEGER; wid: CARDINAL);
  266. BEGIN
  267. END WriteInt;
  268. PROCEDURE WriteCard (f: File; n, wid: CARDINAL);
  269. BEGIN
  270. END WriteCard;
  271. PROCEDURE WriteBytes (f: File; VAR buf: ARRAY OF SYSTEM.BYTE; len: CARDINAL);
  272. BEGIN
  273. END WriteBytes;
  274. PROCEDURE GetDate (VAR Year, Month, Day: CARDINAL);
  275. BEGIN
  276. END GetDate;
  277. PROCEDURE GetTime (VAR Hrs, Mins, Secs, Hsecs: CARDINAL);
  278. BEGIN
  279. END GetTime;
  280. PROCEDURE Write2 (f: File; i: CARDINAL);
  281. BEGIN
  282. Write(f, CHR(i DIV 10 + ORD("0")));
  283. Write(f, CHR(i MOD 10 + ORD("0")));
  284. END Write2;
  285. PROCEDURE WriteDate (f: File);
  286. VAR
  287. Year, Month, Day: CARDINAL;
  288. BEGIN
  289. IF NotWrite(f) THEN Okay := FALSE; RETURN END;
  290. GetDate(Year, Month, Day);
  291. Write2(f, Day); Write(f, "/"); Write2(f, Month); Write(f, "/");
  292. WriteCard(f, Year, 1)
  293. END WriteDate;
  294. PROCEDURE WriteTime (f: File);
  295. VAR
  296. Hrs, Mins, Secs, Hsecs: CARDINAL;
  297. BEGIN
  298. IF NotWrite(f) THEN Okay := FALSE; RETURN END;
  299. GetTime(Hrs, Mins, Secs, Hsecs);
  300. Write2(f, Hrs); Write(f, ":"); Write2(f, Mins); Write(f, ":");
  301. Write2(f, Secs)
  302. END WriteTime;
  303. VAR
  304. Hrs0, Mins0, Secs0, Hsecs0: CARDINAL;
  305. Hrs1, Mins1, Secs1, Hsecs1: CARDINAL;
  306. PROCEDURE WriteElapsedTime (f: File);
  307. VAR
  308. Hrs, Mins, Secs, Hsecs, s, hs: CARDINAL;
  309. BEGIN
  310. IF NotWrite(f) THEN Okay := FALSE; RETURN END;
  311. GetTime(Hrs, Mins, Secs, Hsecs);
  312. WriteString(f, "Elapsed time: ");
  313. IF Hrs >= Hrs1
  314. THEN s := (Hrs - Hrs1) * 3600 + (Mins - Mins1) * 60 + Secs - Secs1
  315. ELSE s := (Hrs + 24 - Hrs1) * 3600 + (Mins - Mins1) * 60 + Secs - Secs1
  316. END;
  317. IF Hsecs >= Hsecs1
  318. THEN hs := Hsecs - Hsecs1
  319. ELSE hs := (Hsecs + 100) - Hsecs1; DEC(s);
  320. END;
  321. WriteCard(f, s, 1); Write(f, ".");
  322. Write2(f, hs); WriteString(f, " s"); WriteLn(f);
  323. Hrs1 := Hrs; Mins1 := Mins; Secs1 := Secs; Hsecs1 := Hsecs;
  324. END WriteElapsedTime;
  325. PROCEDURE WriteExecutionTime (f: File);
  326. VAR
  327. Hrs, Mins, Secs, Hsecs, s, hs: CARDINAL;
  328. BEGIN
  329. IF NotWrite(f) THEN Okay := FALSE; RETURN END;
  330. GetTime(Hrs, Mins, Secs, Hsecs);
  331. WriteString(f, "Execution time: ");
  332. IF Hrs >= Hrs0
  333. THEN s := (Hrs - Hrs0) * 3600 + (Mins - Mins0) * 60 + Secs - Secs0
  334. ELSE s := (Hrs + 24 - Hrs0) * 3600 + (Mins - Mins0) * 60 + Secs - Secs0
  335. END;
  336. IF Hsecs >= Hsecs0
  337. THEN hs := Hsecs - Hsecs0
  338. ELSE hs := (Hsecs + 100) - Hsecs0; DEC(s);
  339. END;
  340. WriteCard(f, s, 1); Write(f, "."); Write2(f, hs);
  341. WriteString(f, " s"); WriteLn(f);
  342. END WriteExecutionTime;
  343. (* The code for the next four procedures below may be commented out if your
  344. compiler supports ISO PROCEDURE constant declarations and these declarations
  345. are made in the DEFINITION MODULE *)
  346. PROCEDURE SLENGTH (stringVal: ARRAY OF CHAR): CARDINAL;
  347. BEGIN
  348. RETURN Str.Length(stringVal)
  349. END SLENGTH;
  350. PROCEDURE Assign (source: ARRAY OF CHAR; VAR destination: ARRAY OF CHAR);
  351. BEGIN
  352. (* Be careful - some libraries have the parameters reversed! *)
  353. Str.Copy(destination, source)
  354. END Assign;
  355. PROCEDURE Extract (source: ARRAY OF CHAR; startIndex: CARDINAL;
  356. numberToExtract: CARDINAL; VAR destination: ARRAY OF CHAR);
  357. BEGIN
  358. Str.Slice(destination, source, startIndex, numberToExtract)
  359. END Extract;
  360. PROCEDURE Concat (source1, source2: ARRAY OF CHAR; VAR destination: ARRAY OF CHAR);
  361. BEGIN
  362. Str.Concat(destination, source1, source2);
  363. END Concat;
  364. (* The code for the four procedures above may be commented out if your
  365. compiler supports ISO PROCEDURE constant declarations and these declarations
  366. are made in the DEFINITION MODULE *)
  367. PROCEDURE Compare (stringVal1, stringVal2: ARRAY OF CHAR): INTEGER;
  368. BEGIN
  369. RETURN Str.Compare(stringVal1, stringVal2)
  370. END Compare;
  371. PROCEDURE ORDL (n: INT32): CARDINAL;
  372. BEGIN RETURN VAL(CARDINAL, n) END ORDL;
  373. PROCEDURE INTL (n: INT32): INTEGER;
  374. BEGIN RETURN VAL(INTEGER, n) END INTL;
  375. PROCEDURE INT (n: CARDINAL): INT32;
  376. BEGIN RETURN VAL(INT32, n) END INT;
  377. PROCEDURE CloseAll;
  378. VAR
  379. handle: CARDINAL;
  380. BEGIN
  381. FOR handle := 0 TO MaxFiles - 1 DO
  382. IF handle IN Handles THEN Close(Opened[handle]) END
  383. END;
  384. IF ~ ToScreen THEN FIO.Close(StdOut^.ref) END;
  385. Continue;
  386. END CloseAll;
  387. PROCEDURE QuitExecution;
  388. BEGIN
  389. HALT
  390. END QuitExecution;
  391. BEGIN
  392. (*CheckRedirection; (* Not apparently available on many systems *)*)
  393. GetTime(Hrs0, Mins0, Secs0, Hsecs0);
  394. Hrs1 := Hrs0;
  395. Mins1 := Mins0;
  396. Secs1 := Secs0;
  397. Hsecs1 := Hsecs0;
  398. Handles := BITSET{};
  399. Okay := FALSE;
  400. EOFChar := 32C;
  401. Param := 0;
  402. (*FIO.Separators := Str.CHARSET{CHR(0) .. " "}; *)
  403. FIO.IOcheck := FALSE;
  404. ALLOCATE(con, SYSTEM.TSIZE(FileRec)-SYSTEM.TSIZE(Buftype));
  405. con^.ref := FIO.StdOut;
  406. con^.savedCh := 0C;
  407. con^.haveCh := FALSE;
  408. con^.self := con;
  409. con^.noOutput := FALSE;
  410. con^.noInput := FALSE;
  411. con^.textOK := TRUE;
  412. con^.eof := FALSE;
  413. con^.eol := FALSE;
  414. IF FromKeyboard
  415. THEN ALLOCATE(StdIn, SYSTEM.TSIZE(FileRec)-SYSTEM.TSIZE(Buftype));
  416. ELSE ALLOCATE(StdIn, SYSTEM.TSIZE(FileRec));
  417. FIO.AssignBuffer(FIO.StdIn, StdIn^.buffer)
  418. END;
  419. StdIn^.ref := FIO.StdIn;
  420. StdIn^.savedCh := 0C; StdIn^.haveCh := FALSE; StdIn^.self := StdIn;
  421. StdIn^.noOutput := TRUE; StdIn^.noInput := FALSE; StdIn^.textOK := TRUE;
  422. StdIn^.eof := FALSE; StdIn^.eol := FALSE;
  423. IF ToScreen
  424. THEN ALLOCATE(StdOut, SYSTEM.TSIZE(FileRec)-SYSTEM.TSIZE(Buftype));
  425. ELSE ALLOCATE(StdOut, SYSTEM.TSIZE(FileRec));
  426. FIO.AssignBuffer(FIO.StdOut, StdOut^.buffer)
  427. END;
  428. StdOut^.ref := FIO.StdOut;
  429. StdOut^.savedCh := 0C; StdOut^.haveCh := FALSE; StdOut^.self := StdOut;
  430. StdOut^.noOutput := FALSE; StdOut^.noInput := TRUE; StdOut^.textOK := TRUE;
  431. StdOut^.eof := TRUE; StdOut^.eol := TRUE;
  432. ALLOCATE(err, SYSTEM.TSIZE(FileRec)-SYSTEM.TSIZE(Buftype));
  433. err^.ref := FIO.StdErr;
  434. err^.savedCh := 0C; err^.haveCh := FALSE; err^.self := err;
  435. err^.noOutput := FALSE; err^.noInput := TRUE; err^.textOK := TRUE;
  436. err^.eof := TRUE; err^.eol := TRUE;
  437. Lib.Terminate(CloseAll, Continue);
  438. END FileIO.