home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pmos2002.zip / SRC / files.mod < prev    next >
Text File  |  1997-05-08  |  13KB  |  369 lines

  1. IMPLEMENTATION MODULE Files;
  2.  
  3.         (****************************************************************)
  4.         (*                                                              *)
  5.         (*                      File operations.                        *)
  6.         (*                                                              *)
  7.         (*  Programmer:         P. Moylan                               *)
  8.         (*  Last edited:        8 May 1997                              *)
  9.         (*  Status:             Apparently working                      *)
  10.         (*                                                              *)
  11.         (*     Limitation: In this version we assume that the size      *)
  12.         (*     of a file can fit in a CARDINAL.  I'll think about the   *)
  13.         (*     issue of very large files at some later stage.           *)
  14.         (*                                                              *)
  15.         (****************************************************************)
  16.  
  17. FROM SYSTEM IMPORT
  18.     (* type *)  CARD8;
  19.  
  20. FROM Windows IMPORT                     (* for testing *)
  21.     (* type *)  Window, Colour, FrameType, DividerType,
  22.     (* proc *)  OpenWindow, WriteString, WriteLn;
  23.  
  24. FROM NumericIO IMPORT                   (* for testing *)
  25.     (* proc *)  WriteHexLongword;
  26.  
  27. FROM SYSTEM IMPORT
  28.     (* type *)  BYTE, ADDRESS,
  29.     (* proc *)  ADR;
  30.  
  31. FROM Trace IMPORT
  32.     (* proc *)  InTrace, OutTrace;
  33.  
  34. FROM IOErrorCodes IMPORT
  35.     (* type *)  ErrorCode;
  36.  
  37. IMPORT RndFile;
  38. FROM RndFile IMPORT read, write, raw, OpenResults;
  39.  
  40. IMPORT IOChan;
  41.  
  42. IMPORT IOConsts;
  43. FROM IOConsts IMPORT ReadResults;
  44.  
  45. (************************************************************************)
  46.  
  47. CONST testing = FALSE;
  48.  
  49. VAR debug: Window;
  50.  
  51. (************************************************************************)
  52. (*                  TRANSLATING THE LIBRARY ERROR CODES                 *)
  53. (************************************************************************)
  54.  
  55. PROCEDURE TranslateOpenResults (code: RndFile.OpenResults): ErrorCode;
  56.  
  57.     (* Returns the status of the last I/O operation.  We do a "best     *)
  58.     (* guess" approximation to the error code.                          *)
  59.  
  60.     BEGIN
  61.         CASE code OF
  62.           opened:    RETURN OK;
  63.          |
  64.           wrongNameFormat: RETURN InvalidFileNameString;
  65.          |
  66.           wrongFlags: RETURN UndiagnosedFailure;
  67.          |
  68.           tooManyOpen: RETURN UndiagnosedFailure;
  69.          |
  70.           outOfChans: RETURN UndiagnosedFailure;
  71.          |
  72.           wrongPermissions: RETURN UndiagnosedFailure;
  73.          |
  74.           noRoomOnDevice: RETURN DeviceFull;
  75.          |
  76.           noSuchFile: RETURN NameNotFound;
  77.          |
  78.           fileExists: RETURN DuplicateFileName;
  79.          |
  80.           wrongFileType: RETURN UndiagnosedFailure;
  81.          |
  82.           noTextOperations: RETURN UndiagnosedFailure;
  83.          |
  84.           noRawOperations: RETURN UndiagnosedFailure;
  85.          |
  86.           noMixedOperations: RETURN UndiagnosedFailure;
  87.          |
  88.           alreadyOpen: RETURN UndiagnosedFailure;
  89.          |
  90.           otherProblem: RETURN UndiagnosedFailure;
  91.          |
  92.         ELSE
  93.                 RETURN UndiagnosedFailure;
  94.         END (*CASE*);
  95.     END TranslateOpenResults;
  96.  
  97. (************************************************************************)
  98. (*                           OPENING A FILE                             *)
  99. (************************************************************************)
  100.  
  101. PROCEDURE OpenFile (VAR (*OUT*) f: File;  name: ARRAY OF CHAR;
  102.                                         newfile: BOOLEAN): ErrorCode;
  103.  
  104.     (* Opens the file named by the given character string, and returns  *)
  105.     (* f as the identification to be used when specifying this file in  *)
  106.     (* future.  If newfile is TRUE, a new file is created.  If newfile  *)
  107.     (* is FALSE, the file must already exist.                           *)
  108.  
  109.     VAR result: RndFile.OpenResults;
  110.  
  111.     BEGIN
  112.         IF newfile THEN
  113.             RndFile.OpenClean (f, name, read+write+raw, result);
  114.         ELSE
  115.             RndFile.OpenOld (f, name, read+write+raw, result);
  116.         END (*IF*);
  117.         RETURN TranslateOpenResults (result);
  118.     END OpenFile;
  119.  
  120. (************************************************************************)
  121. (*                           CLOSING A FILE                             *)
  122. (************************************************************************)
  123.  
  124. PROCEDURE CloseFile (VAR (*INOUT*) f: File);
  125.  
  126.     (* Closes file f. *)
  127.  
  128.     BEGIN
  129.         RndFile.Close(f);
  130.     EXCEPT
  131.         (* Do nothing if file not open. *)
  132.     END CloseFile;
  133.  
  134. (************************************************************************)
  135. (*                        FILE POSITION CALCULATIONS                    *)
  136. (************************************************************************)
  137.  
  138. PROCEDURE FilePosDifference (p2, p1: RndFile.FilePos): INTEGER;
  139.  
  140.     (* Returns p2-p1, saturating the result if needed. *)
  141.  
  142.     (* There's probably a better way to do this, but for now I'm playing it     *)
  143.     (* safe and avoiding special tricks.                                        *)
  144.  
  145.     TYPE Position = RECORD
  146.                         CASE :BOOLEAN OF
  147.                             FALSE:  FP: RndFile.FilePos;
  148.                           | TRUE:   high: INTEGER;  low: CARDINAL;
  149.                         END (*CASE*);
  150.                     END (*RECORD*);
  151.  
  152.     VAR pos1, pos2, result: Position;
  153.  
  154.     BEGIN
  155.         InTrace ("FilePosDifference");
  156.         pos1.FP := p1;  pos2.FP := p2;
  157.  
  158.         (* Negate p1. *)
  159.  
  160.         IF pos1.low = 0 THEN
  161.             pos1.high := -pos1.high;
  162.         ELSE
  163.             pos1.low := MAX(CARDINAL)-pos1.low+1;
  164.             pos1.high := -pos1.high - 1;
  165.         END (*IF*);
  166.  
  167.         (* Add in p2. *)
  168.  
  169.         IF pos1.low  > MAX(CARDINAL) - pos2.low THEN
  170.             result.low := pos1.low - (MAX(CARDINAL) - pos2.low) - 1;
  171.             result.high := pos1.high + pos2.high + 1;
  172.         ELSE
  173.             result.low := pos1.low + pos2.low;
  174.             result.high := pos1.high + pos2.high;
  175.         END (*IF*);
  176.  
  177.         OutTrace ("FilePosDifference");
  178.  
  179.         (* Truncate the result to INTEGER. *)
  180.  
  181.         IF result.high < -1 THEN RETURN -MAX(INTEGER)
  182.         ELSIF result.high = -1 THEN
  183.             IF result.low > MAX(INTEGER) THEN RETURN -VAL(INTEGER,MAX(CARDINAL)-result.low+1)
  184.             ELSE RETURN -MAX(INTEGER)
  185.             END (*IF*);
  186.         ELSIF (result.high > 0) OR (result.low > MAX(INTEGER)) THEN RETURN MAX(INTEGER)
  187.         ELSE RETURN result.low;
  188.         END (*IF*);
  189.  
  190.     END FilePosDifference;
  191.  
  192. (************************************************************************)
  193. (*                          END-OF-FILE TEST                            *)
  194. (************************************************************************)
  195.  
  196. PROCEDURE EOF (f: File): BOOLEAN;
  197.  
  198.     (* Returns TRUE iff we are currently at the end of file f.          *)
  199.  
  200.     BEGIN
  201.         RETURN FilePosDifference (RndFile.CurrentPos(f), RndFile.EndPos(f)) >= 0;
  202.     END EOF;
  203.  
  204. (************************************************************************)
  205. (*                              WRITING                                 *)
  206. (************************************************************************)
  207.  
  208. PROCEDURE WriteByte (f: File;  value: BYTE): ErrorCode;
  209.  
  210.     (* Writes one byte to the file.  The returned value is an error     *)
  211.     (* code (OK if no error).                                           *)
  212.  
  213.     BEGIN
  214.         InTrace ("WriteByte");
  215.         IOChan.RawWrite (f, ADR(value), 1);
  216.         OutTrace ("WriteByte");
  217.         RETURN OK;
  218.     EXCEPT
  219.         OutTrace ("WriteByte");
  220.         RETURN UndiagnosedFailure;
  221.     END WriteByte;
  222.  
  223. (************************************************************************)
  224.  
  225. PROCEDURE WriteRecord (f: File;  buffaddr: ADDRESS;
  226.                                         count: CARDINAL): ErrorCode;
  227.  
  228.     (* Writes count bytes from memory location buffaddr.        *)
  229.  
  230.     BEGIN
  231.         InTrace ("WriteRecord");
  232.         IOChan.RawWrite (f, buffaddr, count);
  233.         OutTrace ("WriteRecord");
  234.         RETURN OK;
  235.     EXCEPT
  236.         OutTrace ("WriteRecord");
  237.         RETURN UndiagnosedFailure;
  238.     END WriteRecord;
  239.  
  240. (************************************************************************)
  241. (*                              READING                                 *)
  242. (************************************************************************)
  243.  
  244. PROCEDURE ReadByte (f: File): CARD8;
  245.  
  246.     (* Returns the next byte from the file.     *)
  247.  
  248.     VAR datum: CARD8;  locsRead: CARDINAL;
  249.  
  250.     BEGIN
  251.         IOChan.RawRead (f, ADR(datum), 1, locsRead);
  252.         RETURN datum;
  253.     END ReadByte;
  254.  
  255. (************************************************************************)
  256.  
  257. PROCEDURE ReadRecord (f: File;  buffaddr: ADDRESS;  desired: CARDINAL;
  258.                                 VAR (*OUT*) actual: CARDINAL): ErrorCode;
  259.  
  260.     (* Reads up to "desired" bytes from file f to memory location       *)
  261.     (* "buffaddr".  On return, "actual" gives the number of bytes read. *)
  262.  
  263.     VAR status: IOConsts.ReadResults;
  264.  
  265.     BEGIN
  266.         IOChan.RawRead (f, buffaddr, desired, actual);
  267.         status := IOChan.ReadResult (f);
  268.         IF status = allRight THEN RETURN OK
  269.         ELSIF status = endOfInput THEN RETURN IllegalBlockNumber
  270.         ELSE RETURN UndiagnosedFailure;
  271.         END (*IF*);
  272.     END ReadRecord;
  273.  
  274. (************************************************************************)
  275. (*                              RANDOM ACCESS                           *)
  276. (************************************************************************)
  277.  
  278. PROCEDURE WritePosition (w: Window;  position: RndFile.FilePos);
  279.  
  280.     VAR arg: RECORD
  281.                  CASE :BOOLEAN OF
  282.                    | FALSE:   Pos: RndFile.FilePos;
  283.                    | TRUE:    high, low: CARDINAL;
  284.                  END (*CASE*);
  285.              END (*RECORD*);
  286.  
  287.     BEGIN
  288.         arg.Pos := position;
  289.         WriteHexLongword (w, arg.high);  WriteHexLongword(w,arg.low);
  290.     END WritePosition;
  291.  
  292. (************************************************************************)
  293.  
  294. PROCEDURE SetPosition (f: File;  position: CARDINAL): ErrorCode;
  295.  
  296.     (* Ensures that the next read or write on this file will be at      *)
  297.     (* byte number position in the file.  (The first byte in the file   *)
  298.     (* is byte number 0.)  If a position greater than the file size     *)
  299.     (* is specified, the length of the file will increase.              *)
  300.  
  301.     VAR target: RndFile.FilePos;
  302.  
  303.     BEGIN
  304.         InTrace ("SetPosition");
  305.         target := RndFile.NewPos (f, position, 1, RndFile.StartPos(f));
  306.         IF FilePosDifference (target, RndFile.EndPos(f)) > 0 THEN
  307.  
  308.             (* Case where padding needed. *)
  309.  
  310.             InTrace ("SetPosition padding");
  311.             IF testing THEN
  312.                 WriteString (debug, "Target position is ");
  313.                 WriteHexLongword (debug, position);  WriteString (debug, " => ");
  314.                 WritePosition (debug, target);  WriteLn (debug);
  315.                 WriteString (debug, "Start = ");
  316.                 WritePosition (debug, RndFile.StartPos(f));
  317.                 WriteString (debug, "  Current = ");
  318.                 WritePosition (debug, RndFile.CurrentPos(f));
  319.                 WriteString (debug, "  End = ");
  320.                 WritePosition (debug, RndFile.EndPos(f));
  321.             END (*IF*);
  322.             RndFile.SetPos (f, RndFile.EndPos(f));
  323.             LOOP
  324.                 IF WriteByte (f, CHR(0)) <> OK THEN EXIT(*LOOP*) END (*IF*);
  325.                 IF FilePosDifference (target, RndFile.EndPos(f)) = 0 THEN EXIT (*LOOP*) END(*IF*);
  326.             END (*LOOP*);
  327.             OutTrace ("SetPosition padding");
  328.  
  329.         ELSE
  330.  
  331.             RndFile.SetPos (f, target);
  332.  
  333.         END (*IF*);
  334.  
  335.         OutTrace ("SetPosition");
  336.         RETURN OK;
  337.  
  338.     END SetPosition;
  339.  
  340. (************************************************************************)
  341.  
  342. PROCEDURE SavePosition (f: File): CARDINAL;
  343.  
  344.     (* Returns the current byte number in file f.       *)
  345.  
  346.     BEGIN
  347.         RETURN FilePosDifference (RndFile.CurrentPos(f), RndFile.StartPos(f));
  348.     END SavePosition;
  349.  
  350. (************************************************************************)
  351.  
  352. PROCEDURE FileSize (f: File): CARDINAL;
  353.  
  354.     (* Returns the length of the file in bytes. *)
  355.  
  356.     BEGIN
  357.         RETURN FilePosDifference (RndFile.EndPos(f), RndFile.StartPos(f));
  358.     END FileSize;
  359.  
  360. (************************************************************************)
  361.  
  362. BEGIN
  363.     IF testing THEN
  364.         OpenWindow (debug, white, black, 11, 16, 0, 79,
  365.                                         simpleframe, nodivider);
  366.     END (*IF*);
  367. END Files.
  368.  
  369.