FileIO.mod 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795
  1. IMPLEMENTATION MODULE FileIO;
  2. IMPORT Strings,FIO,SysClock, NumberIO, InOut, Storage,FileName;
  3. CONST
  4. MaxFiles = BitSetSize;
  5. NameLength = 256;
  6. TYPE
  7. File = POINTER TO FileRec;
  8. FileRec = RECORD
  9. ref: FIO.File;
  10. self: File;
  11. handle: CARDINAL;
  12. savedCh: CHAR;
  13. textOK, eof, eol, noOutput, noInput, haveCh: BOOLEAN;
  14. name: ARRAY [0 .. NameLength] OF CHAR;
  15. END;
  16. VAR
  17. theTime : SysClock.DateTime;
  18. FromKeyboard, ToScreen: BOOLEAN;
  19. (***********************************************)
  20. PROCEDURE NotRead (f: File): BOOLEAN;
  21. BEGIN
  22. RETURN (f = NIL) OR (f^.self # f) OR (f^.noInput);
  23. END NotRead;
  24. PROCEDURE NotWrite (f: File): BOOLEAN;
  25. BEGIN
  26. RETURN (f = NIL) OR (f^.self # f) OR (f^.noOutput);
  27. END NotWrite;
  28. PROCEDURE NotFile (f: File): BOOLEAN;
  29. BEGIN
  30. RETURN (f = NIL) OR (f^.self # f) OR (File(f) = con) OR (File(f) = err)
  31. OR (File(f) = StdIn) & FromKeyboard
  32. OR (File(f) = StdOut) & ToScreen
  33. END NotFile;
  34. PROCEDURE NextParameter (VAR s: ARRAY OF CHAR);
  35. (* Extracts next parameter from command line.
  36. Returns empty string (s[0] = 0C) if no further parameter can be found. *)
  37. BEGIN
  38. END NextParameter;
  39. PROCEDURE GetEnv (envVar: ARRAY OF CHAR; VAR s: ARRAY OF CHAR);
  40. (* Returns s as the value of environment variable envVar, or empty string
  41. if that variable is not defined. *)
  42. (* The following routines provide a minimal set of file opening routines
  43. and closing routines. *)
  44. BEGIN
  45. END GetEnv;
  46. PROCEDURE Open (VAR f: File; fileName: ARRAY OF CHAR; newFile: BOOLEAN);
  47. (* Opens file f whose full name is specified by fileName.
  48. Opening mode is specified by newFile:
  49. TRUE: the specified file is opened for output only. Any existing
  50. file with the same name is deleted.
  51. FALSE: the specified file is opened for input only.
  52. FileIO.Okay indicates whether the file f has been opened successfully. *)
  53. BEGIN
  54. END Open;
  55. PROCEDURE SearchFile (VAR f: File; envVar, fileName: ARRAY OF CHAR;
  56. newFile: BOOLEAN);
  57. (* As for Open, but tries to open file of given fileName by searching each
  58. directory specified by the environment variable named by envVar. *)
  59. BEGIN
  60. END SearchFile;
  61. PROCEDURE Close (VAR f: File);
  62. (* Closes file f. f becomes NIL.
  63. If possible, Close should be called automatically for all files that
  64. remain open when the application terminates. This will be possible on
  65. implementations that provide some sort of termination or at-exit
  66. facility. *)
  67. BEGIN
  68. END Close;
  69. PROCEDURE CloseAll;
  70. (* Closes all files opened by Open or SearchFile.
  71. On systems that allow this, CloseAll should be automatically installed
  72. as the termination (at-exit) procedure *)
  73. (* The following utility procedure is not used by Coco, but may be useful.
  74. However, some operating systems may not allow for its implementation. *)
  75. BEGIN
  76. END CloseAll;
  77. PROCEDURE Delete (VAR f: File);
  78. (* Deletes file f. f becomes NIL. *)
  79. (* The following routines provide a minimal set of file name manipulation
  80. routines. These are modelled after MS-DOS conventions, where a file
  81. specifier is of a form exemplified by D:\DIR\SUBDIR\PRIMARY.EXT
  82. Other conventions may be introduced; these routines are used by Coco to
  83. derive names for the generated modules from the grammar name and the
  84. directory in which the grammar specification is located. *)
  85. BEGIN
  86. END Delete;
  87. (**********************************************************)
  88. PROCEDURE ExtractDirectory (fullName: ARRAY OF CHAR;
  89. VAR directory: ARRAY OF CHAR);
  90. (* Extracts /home/eric/Projects/ from /home/eric/Projects/essai.txt *)
  91. BEGIN
  92. FileName.GetDir(fullName,directory)
  93. END ExtractDirectory;
  94. PROCEDURE ExtractFileName (fullName: ARRAY OF CHAR;
  95. VAR fileName: ARRAY OF CHAR);
  96. (* Extracts PRIMARY.EXT portion of fullName. *)
  97. VAR
  98. a,b,c : ARRAY[0..256] OF CHAR;
  99. BEGIN
  100. FileName.Get(fullName,a,b,c);
  101. Strings.Concat(b,c,fileName)
  102. END ExtractFileName;
  103. PROCEDURE AppendExtension (oldName, ext: ARRAY OF CHAR;
  104. VAR newName: ARRAY OF CHAR);
  105. (* Constructs newName as complete file name by appending ext to oldName
  106. if it doesn't end with "." Examples: (assume ext = "EXT")
  107. old.any ==> OLD.EXT
  108. old. ==> OLD.
  109. old ==> OLD.EXT
  110. This is not a file renaming facility, merely a string manipulation
  111. routine. *)
  112. VAR
  113. dIr,nAme,eXt : ARRAY[0..256] OF CHAR;
  114. L : CARDINAL;
  115. save : CARDINAL;
  116. extPos, extLen,
  117. namePos, nameLen,
  118. dirPos, dirLen : CARDINAL;
  119. BEGIN
  120. L := LENGTH(oldName);
  121. save := L;
  122. (* separating the dir part from the filename+ext part *)
  123. REPEAT
  124. DEC(save);
  125. IF oldName[save] = "." THEN
  126. extPos := save + 1;
  127. extLen := L - extPos ;
  128. END;
  129. UNTIL oldName[save] = "/";
  130. dirPos := 0;
  131. dirLen := save;
  132. END AppendExtension;
  133. PROCEDURE ChangeExtension (oldName, ext: ARRAY OF CHAR;
  134. VAR newName: ARRAY OF CHAR);
  135. (* Constructs newName as a complete file name by changing extension of
  136. oldName to ext. Examples: (assume ext = "EXT")
  137. old.any ==> OLD.EXT
  138. old. ==> OLD.EXT
  139. old ==> OLD.EXT
  140. This is not a file renaming facility, merely a string manipulation
  141. routine. *)
  142. (* The following routines provide a minimal set of file positioning routines.
  143. Others may be introduced, but at least these should be implemented.
  144. Success of each operation is recorded in FileIO.Okay. *)
  145. BEGIN
  146. END ChangeExtension;
  147. (*********************************************)
  148. PROCEDURE Length (f: File): INT32;
  149. (* Returns length of file f. *)
  150. BEGIN
  151. IF NotFile(f) THEN
  152. Okay := FALSE;
  153. RETURN Long0
  154. ELSE
  155. Okay := TRUE;
  156. FIO.SetPositionFromEnd(f^.ref,0);
  157. RETURN VAL(INT32,FIO.FindPosition(f^.ref))
  158. END;
  159. END Length;
  160. PROCEDURE GetPos (f: File): INT32;
  161. (* Returns the current read/write position in f. *)
  162. BEGIN
  163. IF NotFile(f) THEN
  164. Okay := FALSE;
  165. RETURN Long0
  166. ELSE
  167. Okay := TRUE;
  168. RETURN VAL(INT32,FIO.FindPosition(f^.ref))
  169. END;
  170. END GetPos;
  171. PROCEDURE SetPos (f: File; pos: INT32);
  172. (* Sets the current position for f to pos. *)
  173. (* The following routines provide a minimal set of file rewinding routines.
  174. These two are not currently used by Coco itself.
  175. Success of each operation is recorded in FileIO.Okay *)
  176. BEGIN
  177. IF NotFile(f) THEN
  178. Okay := FALSE
  179. ELSE
  180. Okay := TRUE;
  181. f^.haveCh := FALSE;
  182. FIO.SetPositionFromBeginning(f^.ref,VAL(LONGINT,pos));
  183. END;
  184. END SetPos;
  185. PROCEDURE Reset (f: File);
  186. (* Sets the read/write position to the start of the file *)
  187. BEGIN
  188. IF NotFile(f) THEN
  189. Okay := FALSE
  190. ELSE
  191. FIO.SetPositionFromBeginning(f^.ref,0);
  192. SetPos(f, 0);
  193. IF Okay THEN
  194. f^.haveCh := FALSE;
  195. f^.eof := f^.noInput;
  196. f^.eol := f^.noInput
  197. END
  198. END
  199. END Reset;
  200. PROCEDURE Rewrite (f: File);
  201. (* Truncates the file, leaving open for writing *)
  202. (* The following routines provide a minimal set of input routines.
  203. Others may be introduced, but at least these should be implemented.
  204. Success of each operation is recorded in FileIO.Okay. *)
  205. BEGIN
  206. IF NotFile(f) THEN
  207. Okay := FALSE
  208. ELSE
  209. FIO.Close(f^.ref);
  210. f^.ref := FIO.OpenToWrite(f^.name);
  211. Okay := FIO.IsNoError(f^.ref);
  212. IF ~ Okay THEN
  213. Storage.DEALLOCATE(f, SYSTEM.TSIZE(FileRec)); f := NIL
  214. ELSE
  215. f^.savedCh := 0C; f^.haveCh := FALSE;
  216. f^.eof := TRUE; f^.eol := TRUE;
  217. f^.noInput := TRUE; f^.noOutput := FALSE;
  218. END
  219. END;
  220. END Rewrite;
  221. PROCEDURE EndOfLine (f: File): BOOLEAN;
  222. (* TRUE if f is currently at the end of a line, or at end of file. *)
  223. BEGIN
  224. IF NotRead(f) THEN
  225. Okay := FALSE;
  226. RETURN TRUE
  227. ELSE
  228. Okay := TRUE;
  229. RETURN f^.eol OR f^.eof
  230. END
  231. END EndOfLine;
  232. PROCEDURE EndOfFile (f: File): BOOLEAN;
  233. (* TRUE if f is currently at the end of file. *)
  234. BEGIN
  235. IF NotRead(f)THEN
  236. Okay := FALSE;
  237. RETURN TRUE
  238. ELSE Okay := TRUE;
  239. RETURN f^.eof
  240. END
  241. END EndOfFile;
  242. (****************************************************)
  243. PROCEDURE Read (f: File; VAR ch: CHAR);
  244. (* Reads a character ch from file f.
  245. Maps filing system line mark sequence to FileIO.EOL. *)
  246. BEGIN
  247. END Read;
  248. PROCEDURE ReadAgain (f: File);
  249. (* Prepares to re-read the last character read from f.
  250. There is no buffer, so at most one character can be re-read. *)
  251. BEGIN
  252. END ReadAgain;
  253. PROCEDURE ReadLn (f: File);
  254. (* Reads to start of next line on file f, or to end of file if no next
  255. line. Skips to, and consumes next line mark. *)
  256. BEGIN
  257. END ReadLn;
  258. PROCEDURE ReadString (f: File; VAR str: ARRAY OF CHAR);
  259. (* Reads a string of characters from file f.
  260. Leading blanks are skipped, and str is delimited by line mark.
  261. Line mark is not consumed. *)
  262. BEGIN
  263. END ReadString;
  264. PROCEDURE ReadLine (f: File; VAR str: ARRAY OF CHAR);
  265. (* Reads a string of characters from file f.
  266. Leading blanks are not skipped, and str is terminated by line mark or
  267. control character, which is not consumed. *)
  268. BEGIN
  269. END ReadLine;
  270. PROCEDURE ReadToken (f: File; VAR str: ARRAY OF CHAR);
  271. (* Reads a string of characters from file f.
  272. Leading blanks and line feeds are skipped, and token is terminated by a
  273. character <= ' ', which is not consumed. *)
  274. BEGIN
  275. END ReadToken;
  276. PROCEDURE ReadInt (f: File; VAR i: INTEGER);
  277. (* Reads an integer value from file f. *)
  278. BEGIN
  279. END ReadInt;
  280. PROCEDURE ReadCard (f: File; VAR i: CARDINAL);
  281. (* Reads a cardinal value from file f. *)
  282. BEGIN
  283. END ReadCard;
  284. PROCEDURE ReadBytes (f: File; VAR buf: ARRAY OF SYSTEM.BYTE; VAR len: CARDINAL);
  285. (* Attempts to read len bytes from the current file position into buf.
  286. After the call, len contains the number of bytes actually read. *)
  287. (* The following routines provide a minimal set of output routines.
  288. Others may be introduced, but at least these should be implemented. *)
  289. BEGIN
  290. END ReadBytes;
  291. (*****************************************************)
  292. PROCEDURE Write (f: File; ch: CHAR);
  293. (* Writes a character ch to file f. If ch = FileIO.EOL, writes line mark appropriate to filing system. *)
  294. BEGIN
  295. IF NotWrite(f) THEN
  296. Okay := FALSE;
  297. RETURN
  298. END;
  299. Okay := TRUE;
  300. FIO.WriteChar(f^.ref, ch)
  301. END Write;
  302. PROCEDURE WriteLn (f: File);
  303. (* Skips to the start of the next line on file f.
  304. Writes line mark appropriate to filing system. *)
  305. BEGIN
  306. IF NotWrite(f) THEN
  307. Okay := FALSE;
  308. ELSE
  309. Write(f, EOL)
  310. END
  311. END WriteLn;
  312. PROCEDURE WriteString (f: File; str: ARRAY OF CHAR);
  313. (* Writes entire string str to file f. *)
  314. BEGIN
  315. IF NotWrite(f) THEN
  316. Okay := FALSE;
  317. RETURN
  318. END;
  319. FIO.WriteString(f^.ref, str)
  320. END WriteString;
  321. PROCEDURE WriteText (f: File; text: ARRAY OF CHAR; len: INTEGER);
  322. (* Writes text to file f.
  323. At most len characters are written. Trailing spaces are introduced
  324. if necessary (thus providing left justification). *)
  325. VAR
  326. i, slen: INTEGER;
  327. BEGIN
  328. IF NotWrite(f) THEN
  329. Okay := FALSE;
  330. RETURN
  331. END;
  332. slen := Strings.Length(text);
  333. FOR i := 0 TO len - 1 DO
  334. IF i < slen THEN
  335. Write(f, text[i])
  336. ELSE
  337. Write(f, " ")
  338. END;
  339. END
  340. END WriteText;
  341. PROCEDURE WriteInt (f: File; n: INTEGER; wid: CARDINAL);
  342. (* Writes an INTEGER int into a field of wid characters width.
  343. If the number does not fit into wid characters, wid is expanded.
  344. If wid = 0, exactly one leading space is introduced. *)
  345. VAR
  346. l, d: CARDINAL;
  347. x: INTEGER;
  348. t: ARRAY [1 .. 25] OF CHAR;
  349. sign: CHAR;
  350. BEGIN
  351. IF NotWrite(f) THEN
  352. Okay := FALSE;
  353. RETURN
  354. END;
  355. IF n < 0 THEN
  356. sign := "-";
  357. x := - n;
  358. ELSE
  359. sign := " ";
  360. x := n;
  361. END;
  362. l := 0;
  363. REPEAT
  364. d := x MOD 10;
  365. x := x DIV 10;
  366. INC(l);
  367. t[l] := CHR(ORD("0") + d);
  368. UNTIL x = 0;
  369. IF wid = 0 THEN
  370. Write(f, " ")
  371. END;
  372. WHILE wid > l + 1 DO
  373. Write(f, " ");
  374. DEC(wid);
  375. END;
  376. IF (sign = "-") OR (wid > l) THEN
  377. Write(f, sign);
  378. END;
  379. WHILE l > 0 DO
  380. Write(f, t[l]);
  381. DEC(l);
  382. END;
  383. END WriteInt;
  384. PROCEDURE WriteCard (f: File; n, wid: CARDINAL);
  385. (* Writes a CARDINAL card into a field of wid characters width.
  386. If the number does not fit into wid characters, wid is expanded.
  387. If wid = 0, exactly one leading space is introduced. *)
  388. VAR
  389. l, d: CARDINAL;
  390. t: ARRAY [1 .. 25] OF CHAR;
  391. BEGIN
  392. IF NotWrite(f) THEN
  393. Okay := FALSE;
  394. RETURN
  395. END;
  396. l := 0;
  397. REPEAT
  398. d := n MOD 10;
  399. n := n DIV 10;
  400. INC(l); t[l] := CHR(ORD("0") + d);
  401. UNTIL n = 0;
  402. IF wid = 0 THEN
  403. Write(f, " ")
  404. END;
  405. WHILE wid > l DO
  406. Write(f, " ");
  407. DEC(wid);
  408. END;
  409. WHILE l > 0 DO
  410. Write(f, t[l]);
  411. DEC(l);
  412. END;
  413. END WriteCard;
  414. PROCEDURE WriteBytes (f: File; VAR buf: ARRAY OF SYSTEM.BYTE; len: CARDINAL);
  415. (* Writes len bytes from buf to f at the current file position. *)
  416. (* The following procedures are not currently used by Coco, and may be
  417. safely omitted, or implemented as null procedures. They might be
  418. useful in measuring performance. *)
  419. (*PROCEDURE WriteNBytes (f: File; nBytes: CARDINAL;
  420. src: ADDRESS) : CARDINAL ;*)
  421. VAR
  422. TooMany: BOOLEAN;
  423. number : CARDINAL;
  424. BEGIN
  425. TooMany := (len > 0) & (len - 1 > HIGH(buf));
  426. IF NotWrite(f) OR (File(f) = con) OR (File(f) = err) THEN
  427. Okay := FALSE
  428. ELSE
  429. IF TooMany THEN
  430. len := HIGH(buf) + 1
  431. END;
  432. number := FIO.WriteNBytes(f^.ref, len, SYSTEM.ADR(buf));
  433. Okay := FIO.IsNoError(f^.ref) = TRUE;
  434. Okay := number = len;
  435. END;
  436. IF TooMany THEN
  437. Okay := FALSE
  438. END;
  439. END WriteBytes;
  440. PROCEDURE Write2 (f: File; i: CARDINAL);
  441. BEGIN
  442. Write(f, CHR(i DIV 10 + ORD("0")));
  443. Write(f, CHR(i MOD 10 + ORD("0")));
  444. END Write2;
  445. PROCEDURE WriteDate (f: File);
  446. (* Write current date DD/MM/YYYY to file f. *)
  447. VAR
  448. Year, Month, Day: CARDINAL;
  449. BEGIN
  450. IF NotWrite(f) THEN Okay := FALSE; RETURN END;
  451. SysClock.GetClock(theTime);
  452. WITH theTime DO
  453. Write2(f, day);
  454. Write(f, "/");
  455. Write2(f, month);
  456. Write(f, "/");
  457. WriteCard(f, year, 1)
  458. END;
  459. END WriteDate;
  460. PROCEDURE WriteTime (f: File);
  461. (* Write time HH:MM:SS to file f. *)
  462. (*
  463. PROCEDURE GetClock(VAR userData: DateTime);
  464. (* Assigns local date and time of the day to userData *)
  465. *)
  466. VAR
  467. theTimeString : ARRAY[0..40] OF CHAR;
  468. yearStr, monthStr, dayStr : ARRAY[0..12] OF CHAR;
  469. BEGIN
  470. IF NotWrite(f) THEN
  471. Okay := FALSE;
  472. RETURN
  473. END;
  474. SysClock.GetClock(theTime);
  475. WITH theTime DO
  476. Write2(f, hour);
  477. Write(f, ":");
  478. Write2(f, minute);
  479. Write(f, ":");
  480. Write2(f, second)
  481. END;
  482. END WriteTime;
  483. (***************************************************)
  484. VAR
  485. Hrs0, Mins0, Secs0, Hsecs0: CARDINAL;
  486. Hrs1, Mins1, Secs1, Hsecs1: CARDINAL;
  487. PROCEDURE WriteElapsedTime (f: File);
  488. (* Write elapsed time in seconds since last call of this procedure. *)
  489. VAR
  490. theTimeNow : SysClock.DateTime;
  491. Hrs, Mins, Secs, Hsecs, s, hs: CARDINAL;
  492. BEGIN
  493. IF NotWrite(f) THEN
  494. Okay := FALSE;
  495. RETURN
  496. END;
  497. SysClock.GetClock(theTimeNow);
  498. WITH theTimeNow DO
  499. Hrs := hour;
  500. Mins := minute;
  501. Secs := second;
  502. Hsecs := fractions;
  503. END;
  504. WriteString(f, "Elapsed time: ");
  505. IF Hrs >= Hrs1
  506. THEN s := (Hrs - Hrs1) * 3600 + (Mins - Mins1) * 60 + Secs - Secs1
  507. ELSE s := (Hrs + 24 - Hrs1) * 3600 + (Mins - Mins1) * 60 + Secs - Secs1
  508. END;
  509. IF Hsecs >= Hsecs1
  510. THEN hs := Hsecs - Hsecs1
  511. ELSE hs := (Hsecs + 100) - Hsecs1; DEC(s);
  512. END;
  513. (** Updating**)
  514. WriteCard(f, s, 1);
  515. Write(f, ".");
  516. Write2(f, hs);
  517. WriteString(f, " s");
  518. WriteLn(f);
  519. (** Writing to file**)
  520. Hrs1 := Hrs;
  521. Mins1 := Mins;
  522. Secs1 := Secs;
  523. Hsecs1 := Hsecs;
  524. END WriteElapsedTime;
  525. PROCEDURE WriteExecutionTime (f: File);
  526. (* Write total execution time in seconds thus far to file f. *)
  527. VAR
  528. theTimeNow : SysClock.DateTime;
  529. Hrs, Mins, Secs, Hsecs, s, hs: CARDINAL;
  530. BEGIN
  531. IF NotWrite(f) THEN
  532. Okay := FALSE;
  533. RETURN
  534. END;
  535. SysClock.GetClock(theTimeNow);
  536. WITH theTimeNow DO
  537. Hrs := hour;
  538. Mins := minute;
  539. Secs := second;
  540. Hsecs := fractions;
  541. END;
  542. WriteString(f, "Execution time: ");
  543. IF Hrs >= Hrs0
  544. THEN s := (Hrs - Hrs0) * 3600 + (Mins - Mins0) * 60 + Secs - Secs0
  545. ELSE s := (Hrs + 24 - Hrs0) * 3600 + (Mins - Mins0) * 60 + Secs - Secs0
  546. END;
  547. IF Hsecs >= Hsecs0
  548. THEN hs := Hsecs - Hsecs0
  549. ELSE hs := (Hsecs + 100) - Hsecs0; DEC(s);
  550. END;
  551. WriteCard(f, s, 1);
  552. Write(f, ".");
  553. Write2(f, hs);
  554. WriteString(f, " s");
  555. WriteLn(f);
  556. END WriteExecutionTime;
  557. (***************************************************)
  558. PROCEDURE SLENGTH (stringVal: ARRAY OF CHAR): CARDINAL;
  559. (* Returns number of characters in stringVal, not including nul *)
  560. BEGIN
  561. RETURN LENGTH(stringVal)
  562. END SLENGTH;
  563. PROCEDURE Assign (source: ARRAY OF CHAR; VAR destination: ARRAY OF CHAR);
  564. (* Copies as much of source to destination as possible, truncating if too
  565. long, and nul terminating if shorter.
  566. Be careful - some libraries have the parameters reversed! *)
  567. (*
  568. PROCEDURE Assign (source: ARRAY OF CHAR; VAR destination: ARRAY OF CHAR);
  569. (* Copies source to destination *)
  570. *)
  571. BEGIN
  572. Strings.Assign(source, destination)
  573. END Assign;
  574. PROCEDURE Extract (source: ARRAY OF CHAR;
  575. startIndex, numberToExtract: CARDINAL;
  576. VAR destination: ARRAY OF CHAR);
  577. BEGIN
  578. Strings.Extract(source, startIndex, numberToExtract, destination)
  579. END Extract;
  580. PROCEDURE Concat (stringVal1, stringVal2: ARRAY OF CHAR;
  581. VAR destination: ARRAY OF CHAR);
  582. (* Concatenates stringVal1 and stringVal2 to form destination.
  583. Nul terminated if concatenation is short enough, truncated if it is
  584. too long *)
  585. (*PROCEDURE Concat (source1, source2: ARRAY OF CHAR; VAR destination: ARRAY OF CHAR);
  586. (* Concatenates source2 onto source1 and copies the result into destination. *)
  587. *)
  588. BEGIN
  589. Strings.Concat(stringVal1,stringVal2,destination)
  590. END Concat;
  591. PROCEDURE Compare (stringVal1, stringVal2: ARRAY OF CHAR): INTEGER;
  592. (* Returns -1, 0, 1 depending whether stringVal1 < = > stringVal2.
  593. This is not directly ISO compatible *)
  594. (*
  595. TYPE
  596. CompareResults = (less, equal, greater);
  597. PROCEDURE Compare (stringVal1, stringVal2: ARRAY OF CHAR): CompareResults;
  598. (* Returns less, equal, or greater, according as stringVal1 is lexically less than,
  599. equal to, or greater than stringVal2.
  600. *)
  601. *)
  602. BEGIN
  603. CASE Strings.Compare( stringVal1, stringVal2 ) OF
  604. Strings.less : RETURN -1; |
  605. Strings.equal : RETURN 0; |
  606. Strings.greater : RETURN 1; |
  607. END;
  608. END Compare;
  609. (***************************************************)
  610. (* The following routines are for conversions to and from the INT32 type.
  611. Their names are modelled after the ISO pervasive routines that would
  612. achieve the same end. Where possible, replacing calls to these routines
  613. by the pervasives would improve performance markedly. As used in Coco,
  614. these routines should not give range problems. *)
  615. PROCEDURE ORDL (n: INT32): CARDINAL;
  616. (* Convert long integer n to corresponding (short) cardinal value.
  617. Potentially FileIO.ORDL(n) = VAL(CARDINAL, n) *)
  618. BEGIN
  619. RETURN VAL(CARDINAL, n)
  620. END ORDL;
  621. PROCEDURE INTL (n: INT32): INTEGER;
  622. (* Convert long integer n to corresponding short integer value.
  623. Potentially FileIO.INTL(n) = VAL(INTEGER, n) *)
  624. BEGIN
  625. RETURN VAL(INTEGER, n)
  626. END INTL;
  627. PROCEDURE INT (n: CARDINAL): INT32;
  628. BEGIN
  629. RETURN VAL(INT32, n)
  630. END INT;
  631. PROCEDURE QuitExecution;
  632. BEGIN
  633. HALT;
  634. END QuitExecution;
  635. BEGIN
  636. SysClock.GetClock(theTime);
  637. WITH theTime DO
  638. Hrs0 := hour;
  639. Mins0 := minute;
  640. Secs0 := second;
  641. Hsecs0 := fractions;
  642. Hrs1 := Hrs0; Mins1 := Mins0; Secs1 := Secs0; Hsecs1 := Hsecs0;
  643. END;
  644. END FileIO.