home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 549a.lha / M2P_v1.0 / mods.lzh / FIO.mod < prev    next >
Text File  |  1991-08-10  |  16KB  |  743 lines

  1. (*======================================================================*)
  2. (*                   Amiga Modula-2 support routines                    *)
  3. (*======================================================================*)
  4.  
  5. IMPLEMENTATION MODULE FIO;
  6.  
  7. (*----------------------------------------------------------------------*
  8.  * Imports *** SOME IMPLEMENTATION DEPENDENT ***                        *
  9.  *----------------------------------------------------------------------*)
  10.  
  11. IMPORT
  12.     SYSTEM;
  13. IMPORT
  14.     FStorage;
  15. IMPORT
  16.     ASCII;
  17. IMPORT
  18.     Strings;
  19.  
  20.  
  21.  
  22.  
  23.  
  24.  
  25.  
  26.  
  27.  
  28.  
  29.  
  30.  
  31.  
  32.  
  33.  
  34.  
  35. (*----------------------------------------------------------------------*
  36.  * Constants for configuring to personal preferences                    *
  37.  *----------------------------------------------------------------------*)
  38.  
  39. CONST
  40.     BufferSize = 4096;
  41.     MaxFileName = 256;
  42.     MaxPrompt = 80;
  43.  
  44. (*----------------------------------------------------------------------*)
  45. (* The IMPLEMENTATION DEPENDENT 'real' file type.                       *)
  46. (*----------------------------------------------------------------------*)
  47.  
  48. TYPE
  49.     RealFileType =
  50.  
  51.  
  52.  (* insert implementation specific type here *)
  53.  
  54.  
  55. (*----------------------------------------------------------------------*)
  56. (* The buffered FILE structure                                          *)
  57. (*----------------------------------------------------------------------*)
  58.  
  59. TYPE
  60.     Access = (Closed,Read,Write);
  61.  
  62.     AccessSet = SET OF Access;
  63.  
  64.     FILE = POINTER TO FHBlock;
  65.     FHBlock = RECORD
  66.         Next: FILE;
  67.         Handle: RealFileType;
  68.         Mode: Access;
  69.         CharsRead: CARDINAL;
  70.         Count: CARDINAL;
  71.         Prompt: ARRAY [0..MaxPrompt] OF CHAR;
  72.         Info: ARRAY [0..BufferSize] OF CHAR;
  73.     END;
  74.  
  75. (*----------------------------------------------------------------------*)
  76.  
  77. TYPE
  78.     Chars = [00C..37C];
  79.     Terms = SET OF Chars;
  80.  
  81. CONST
  82.     Space = ' ';
  83.     Terminators = Terms{ASCII.NUL,ASCII.EOL,ASCII.EOF};
  84.     WhiteSpace = Terms{ASCII.EOL,ASCII.HT};
  85.  
  86. (*----------------------------------------------------------------------*)
  87.  
  88. VAR
  89.     Files: FILE;                    (* the tracking list      *)
  90.  
  91. VAR
  92.     InpBLK: FHBlock;                (* predefined structures  *)
  93.     OutBLK: FHBlock;                (* for INPUT and OUTPUT   *)
  94.  
  95. VAR
  96.     WB: BOOLEAN;                    (* started from workbench?*)
  97.     process:ProcessPtr;
  98.  
  99. (*----------------------------------------------------------------------*)
  100.  
  101.  
  102.  
  103.  
  104.  
  105.  
  106.  
  107.  
  108.  
  109.  
  110.  
  111.  
  112.  
  113. (*----------------------------------------------------------------------*)
  114. (* Adds a file to the file list with the given permissions.  If it      *)
  115. (* could not allocate storage, it closes the file and exits.  Otherwise *)
  116. (* it returns a pointer to the file structure.                          *)
  117. (*----------------------------------------------------------------------*)
  118.  
  119.  
  120.  
  121. PROCEDURE AddFile(VAR F: RealFileType; Permission: Access):FILE;
  122.  
  123. VAR
  124.     file: FILE;
  125.  
  126. BEGIN
  127.     FStorage.ALLOCATE(file,SYSTEM.TSIZE(FHBlock));
  128.     IF file # NIL THEN
  129.         WITH file^ DO
  130.             Mode:=Permission;
  131.                     (* init. file struc *)
  132.             Handle:=F;
  133.             Count:=0;       (* buffer empty *)
  134.             CharsRead:=BufferSize+999;
  135.                     (* forces read  *)
  136.             Prompt[0]:=ASCII.NUL;
  137.             Next:=Files;
  138.         END;
  139.         Files:=file;
  140.     ELSE
  141.         OSClose(F);
  142.     END;
  143.     RETURN file;
  144. END AddFile;
  145.  
  146. (*----------------------------------------------------------------------*)
  147. (* Opens a read-only file.                                              *)
  148. (*----------------------------------------------------------------------*)
  149.  
  150.  
  151.  
  152.  
  153. PROCEDURE Open(FileName: ARRAY OF CHAR):FILE;
  154.  
  155. VAR
  156.     handle: RealFileType;
  157.  
  158. BEGIN
  159.     IF OSOpen(handle,FileName) THEN
  160.         RETURN AddFile(handle,Read);
  161.     ELSE
  162.         RETURN NIL;
  163.     END;
  164. END Open;
  165.  
  166. (*----------------------------------------------------------------------*)
  167. (* Opens a write-only file which writing is to begin after the last     *)
  168. (* position of the file.                                                *)
  169. (*----------------------------------------------------------------------*)
  170.  
  171.  
  172.  
  173. PROCEDURE Append(FileName: ARRAY OF CHAR):FILE;
  174.  
  175. VAR
  176.     handle: RealFileType;
  177.  
  178. BEGIN
  179.     IF OSAppend(handle,FileName) THEN
  180.         RETURN AddFile(handle,Write);
  181.     ELSE
  182.         RETURN NIL;
  183.     END;
  184. END Append;
  185.  
  186. (*----------------------------------------------------------------------*)
  187. (* Creates or overwrites a file.                                        *)
  188. (*----------------------------------------------------------------------*)
  189.  
  190.  
  191.  
  192. PROCEDURE Create(FileName: ARRAY OF CHAR):FILE;
  193.  
  194. VAR
  195.     handle: RealFileType;
  196.  
  197. BEGIN
  198.     IF OSCreate(handle,FileName) THEN
  199.         RETURN AddFile(handle,Write);
  200.     ELSE
  201.         RETURN NIL;
  202.     END;
  203. END Create;
  204.  
  205. (*----------------------------------------------------------------------*
  206.  * Flushes a file's output buffer if it had Write access, OSCloses the  *
  207.  * file, deallocates file header block, and removes file from File list *
  208.  * If the file is not on list, it will do nothing.                      *
  209.  *----------------------------------------------------------------------*)
  210.  
  211.  
  212.  
  213. PROCEDURE Close(VAR F: FILE);
  214.  
  215. VAR
  216.     lead: FILE;
  217.     follow: FILE;
  218.  
  219. BEGIN
  220.     lead:=Files;                    (* get head of tracking list    *)
  221.     follow:=lead;
  222.     WHILE (lead # NIL) AND (lead # F) DO;
  223.         follow:=lead;
  224.         lead:=lead^.Next;       (* postcondition:               *)
  225.     END;
  226.       (*    lead=NIL or lead=F        *)
  227.  
  228.     IF (lead # NIL) AND GoodFILE(F) THEN
  229.                     (* only close it if the FILE    *)
  230.         WITH lead^ DO           (* is on the list and active    *)
  231.             IF lead=Files THEN
  232.                 Files:=Next;
  233.             ELSE
  234.                 follow^.Next:=Next;
  235.             END;
  236.             IF Mode = Write THEN
  237.                 Flush(lead);
  238.             END;
  239.             Mode:=Closed;
  240.             OSClose(Handle);
  241.         END;
  242.         FStorage.DEALLOCATE(lead,SYSTEM.TSIZE(FHBlock));
  243.     END;
  244. END Close;
  245.  
  246. (*----------------------------------------------------------------------*
  247.  * Determines whether a FILE is a valid pointer or not.                 *
  248.  *----------------------------------------------------------------------*)
  249.  
  250.  
  251.  
  252. PROCEDURE GoodFILE(F: FILE):BOOLEAN;
  253.  
  254. BEGIN
  255.  
  256.  
  257.  
  258.  
  259.     RETURN ((F#NIL) AND (F^.Mode IN AccessSet{Read,Write})) ;
  260. END GoodFILE;
  261.  
  262. (*----------------------------------------------------------------------*
  263.  * Set the prompt string for input FILEs.                               *
  264.  *----------------------------------------------------------------------*)
  265.  
  266.  
  267.  
  268. PROCEDURE SetPrompt(F: FILE; prompt: ARRAY OF CHAR);
  269. BEGIN
  270.     IF ((F#NIL) AND (F^.Mode IN AccessSet{Read,Write}))  THEN
  271.         Strings.Assign(prompt,F^.Prompt);
  272.     END END SetPrompt;
  273.  
  274. (************************************************************************)
  275. (* Input Procedures                                                     *)
  276. (************************************************************************)
  277.  
  278. (*----------------------------------------------------------------------*
  279.  * ReadChar reads the next charactor from the input buffer.  ReadChar   *
  280.  * calls ReadInfo to fill the buffer when the contents OF the buffer    *
  281.  * have been depleted.  It returns the next character IN the buffer     *
  282.  * which has not been read.                                             *                                               *
  283.  *----------------------------------------------------------------------*)
  284.  
  285. PROCEDURE ReadChar(Input: FILE):CHAR;
  286.  
  287. BEGIN
  288.  
  289.  
  290.  
  291.     IF ((Input#NIL) AND (Input^.Mode IN AccessSet{Read,Write}))  THEN
  292.         WITH Input^ DO
  293.             IF Mode = Read THEN
  294.                 IF CharsRead >= Count THEN
  295.                     CharsRead:=0;
  296.                     ReadInfo(Input);
  297.                 END;
  298.                 IF CharsRead < Count THEN
  299.                     INC(CharsRead);
  300.                     RETURN Info[CharsRead-1];
  301.                 END;
  302.             ELSE
  303.                 RETURN ASCII.NUL;
  304.             END;
  305.         END;
  306.     ELSE
  307.         RETURN ASCII.NUL;
  308.     END;
  309. END ReadChar;
  310.  
  311. (*----------------------------------------------------------------------*
  312.  * ReadString reads a string into the array given.  It reads characters *
  313.  * into the array until either the array is full, or the EOL charactor  *
  314.  * is reached.  It will not read past the end of line.                  *
  315.  *----------------------------------------------------------------------*)
  316.  
  317. PROCEDURE ReadString(Input: FILE; VAR str:ARRAY OF CHAR);
  318.  
  319. VAR
  320.     index,size : CARDINAL;
  321.     ch : CHAR;
  322.  
  323. BEGIN
  324.     index:=0;
  325.     size:=HIGH(str);
  326.     LOOP
  327.         IF index > size THEN
  328.             IF NextChar(Input) IN Terminators THEN
  329.                 ch:=ReadChar(Input);
  330.             END;
  331.             EXIT;
  332.         END;
  333.         ch := ReadChar(Input);
  334.         IF ch IN Terminators THEN
  335.             str[index] := ASCII.NUL;
  336.             EXIT;
  337.         ELSE
  338.             str[index] := ch;
  339.             INC(index);
  340.         END;
  341.     END;
  342. END ReadString;
  343.  
  344. (*----------------------------------------------------------------------*
  345.  * ReadLn reads all the characters on the current line.  ReadLn calls   *
  346.  * ReadChar and simply discards everything until it sees a EOL char.    *
  347.  *----------------------------------------------------------------------*)
  348.  
  349. PROCEDURE ReadLn(Input: FILE);
  350.  
  351. BEGIN
  352.     WHILE NOT(ReadChar(Input) IN Terminators) DO
  353.     END;
  354. END ReadLn;
  355.  
  356. (*----------------------------------------------------------------------*
  357.  * NextChar returns the next of any pending characters, If there are no *
  358.  * pending characters, it will call ReadInfo to get some.  CAVEAT       *
  359.  * EMPTOR!!!  A poorly controlled NextChar, could cause a user to be    *
  360.  * prompted for input.                                                  *
  361.  *----------------------------------------------------------------------*)
  362.  
  363. PROCEDURE NextChar(Input: FILE):CHAR;
  364.  
  365. BEGIN
  366.     IF ((Input#NIL) AND (Input^.Mode IN AccessSet{Read,Write}))  THEN
  367.         WITH Input^ DO
  368.             IF Mode = Read THEN
  369.                 IF CharsRead >= Count THEN
  370.                     CharsRead:=0;
  371.                     ReadInfo(Input);
  372.                 END;
  373.                 IF CharsRead < Count THEN
  374.                     RETURN Info[CharsRead];
  375.                 END;
  376.             ELSE
  377.                 RETURN ASCII.NUL;
  378.             END;
  379.         END;
  380.     ELSE
  381.         RETURN ASCII.NUL;
  382.     END;
  383. END NextChar;
  384.  
  385. (************************************************************************)
  386. (* Output Procedures                                                    *)
  387. (************************************************************************)
  388.  
  389. (*----------------------------------------------------------------------*
  390.  * WriteChar writes charactors TO the standard output channel.          *
  391.  *----------------------------------------------------------------------*)
  392.  
  393. PROCEDURE WriteChar(Output: FILE; ch:CHAR);
  394.  
  395. BEGIN
  396.  
  397.  
  398.  
  399.     IF ((Output#NIL) AND (Output^.Mode IN AccessSet{Read,Write}))  THEN
  400.         WITH Output^ DO
  401.             IF Mode = Write THEN
  402.                 Info[Count]:=ch;
  403.                 INC(Count);
  404.                 IF (Count > BufferSize) THEN
  405.                     Flush(Output);
  406.                 END;
  407.             END;
  408.         END;
  409.     END;
  410. END WriteChar;
  411.  
  412. (*----------------------------------------------------------------------*
  413.  * WriteLn writes a line feed to the standard output channel.  It       *
  414.  * relies on the error checking performed by WriteChar.                 *
  415.  *----------------------------------------------------------------------*)
  416.  
  417. PROCEDURE WriteLn(Output: FILE);
  418.  
  419. BEGIN
  420.     WriteChar(Output,ASCII.EOL);
  421.     IF Output = OUTPUT THEN
  422.         Flush(Output);
  423.     END;
  424. END WriteLn;
  425.  
  426. (*----------------------------------------------------------------------*
  427.  * WriteString writes strings to the standard output channel.  The      *
  428.  * amount which it writes is determined by whether it finds a string    *
  429.  * terminator (NUL) or the actual length of the string.                 *
  430.  *----------------------------------------------------------------------*)
  431.  
  432.  
  433.  
  434. PROCEDURE WriteString(Output: FILE; str: ARRAY OF CHAR);
  435.  
  436. VAR
  437.     len,I: CARDINAL;
  438.  
  439. BEGIN
  440.     len:=Strings.Length(str);
  441.     I:=0;
  442.     WHILE I < len DO
  443.         WriteChar(Output,str[I]);
  444.         INC(I);
  445.     END;
  446. END WriteString;
  447.  
  448. (*----------------------------------------------------------------------*)
  449. (* Writes an unsigned integer recursively, neat no?                     *)
  450. (*----------------------------------------------------------------------*)
  451.  
  452. PROCEDURE WriteCard(Output: FILE; c:CARDINAL);
  453.  
  454. BEGIN
  455.     IF c>9 THEN
  456.         WriteCard(Output,c DIV 10);
  457.     END;
  458.     WriteChar(Output,CHR(ORD('0')+(c MOD 10)));
  459. END WriteCard;
  460.  
  461. (*----------------------------------------------------------------------*)
  462. (* Termination PROCEDURE -- Closes out all open files                   *)
  463. (*----------------------------------------------------------------------*)
  464.  
  465.  
  466.  
  467. PROCEDURE CloseAllFiles;
  468.  
  469. BEGIN
  470.     WHILE Files # NIL DO
  471.         Close(Files);
  472.     END;
  473.     Flush(OUTPUT);
  474.     IF WB THEN
  475.         OSClose(OUTPUT^.Handle) END;
  476.  
  477.  
  478.  
  479. END CloseAllFiles;
  480.  
  481.  
  482. (************************************************************************)
  483. (* Implementation dependent procedures                                  *)
  484. (************************************************************************)
  485.  
  486.  
  487.  
  488.  
  489.  
  490.  
  491.  
  492.  
  493.  
  494.  
  495.  
  496. (*----------------------------------------------------------------------*)
  497. (* Opens a file for read access.  If unsuccessful, it returns false and *)
  498. (* F is left undefined                                                  *)
  499. (*----------------------------------------------------------------------*)
  500.  
  501.  
  502.  
  503. PROCEDURE OSOpen(VAR F: RealFileType; FileName: ARRAY OF CHAR):BOOLEAN;
  504.  
  505. VAR
  506.  
  507.  
  508.  
  509.  
  510.     BEGIN
  511.  
  512.  
  513.  
  514.  
  515.  
  516.  
  517.  
  518.  
  519.  
  520.  
  521.  (* insert machine dependent stuff here *)
  522.  
  523.  
  524.     RETURN   ;
  525. END OSOpen;
  526.  
  527. (*----------------------------------------------------------------------*)
  528. (* Opens a file for writing and seeks to the end of that file.          *)
  529. (*----------------------------------------------------------------------*)
  530.  
  531. PROCEDURE OSAppend(VAR F: RealFileType; FileName: ARRAY OF CHAR):BOOLEAN;
  532.  
  533. VAR
  534.  
  535.  
  536.  
  537.     VAR stat: LONGINT;
  538.  
  539. BEGIN
  540.  
  541.  
  542.  
  543.  
  544.  
  545.  
  546.  
  547.  
  548.  
  549.  
  550.  (* insert machine dependent stuff here *)
  551.  
  552.  
  553.     IF    THEN
  554.  
  555.  
  556.  
  557.  
  558.  
  559.  (* insert implementation dependent stuff here *)
  560.  
  561.     END;
  562.     RETURN   ;
  563. END OSAppend;
  564.  
  565. (*----------------------------------------------------------------------*)
  566. (* Opens a file for writing.  If unsuccessful, it returns false and     *)
  567. (* F is left undefined                                                  *)
  568. (*----------------------------------------------------------------------*)
  569.  
  570.  
  571.  
  572. PROCEDURE OSCreate(VAR F: RealFileType; FileName: ARRAY OF CHAR):BOOLEAN;
  573.  
  574. VAR
  575.  
  576.  
  577.  
  578.  
  579.     BEGIN
  580.  
  581.  
  582.  
  583.  
  584.  
  585.  
  586.  
  587.  
  588.  
  589.  
  590.  (* insert machine dependent stuff here *)
  591.  
  592.  
  593.     RETURN   ;
  594. END OSCreate;
  595.  
  596. (*----------------------------------------------------------------------*)
  597. (* Closes a FILE                                                        *)
  598. (*----------------------------------------------------------------------*)
  599.  
  600. PROCEDURE OSClose(VAR F: RealFileType);
  601.  
  602. BEGIN
  603.  
  604.  
  605.  
  606.  
  607.  
  608.  
  609.  
  610.  (* insert implementation defined close here *)
  611.  
  612. END OSClose;
  613.  
  614. (*----------------------------------------------------------------------*
  615.  * Flush pending writes out from output buffer.                         *
  616.  *                                                                      *
  617.  * *** IMPLEMENTATION DEPENDENT ***                                     *
  618.  *----------------------------------------------------------------------*)
  619.  
  620. PROCEDURE Flush(Output: FILE);
  621.  
  622. VAR
  623.     len: LONGINT;
  624.  
  625. BEGIN
  626.     WITH Output^ DO
  627.         IF Count <> 0 THEN
  628.  
  629.  
  630.  
  631.  
  632.  
  633.  (* here's where you add stuff for other platforms *)
  634.  
  635.             Count:=0;
  636.         END;
  637.     END;
  638. END Flush;
  639.  
  640. (*----------------------------------------------------------------------*
  641.  * ReadInfo *** IMPLEMENTATION DEPENDENT ***                            *
  642.  *                                                                      *
  643.  * ReadInfo reads info from the standard input, AND stores it in the    *
  644.  * input buffer.  It is local to this module and will require changing  *
  645.  * for different implementations.  This implementation utilizes the     *
  646.  * standard AmigaDOS library read routine to fill the buffer.  When it  *
  647.  * hits EOF, it will tack the EOF charactor onto the end of the buffer. *
  648.  * This way it will be detected by other procedures properly.           *
  649.  *----------------------------------------------------------------------*)
  650.  
  651. PROCEDURE ReadInfo(Input: FILE);
  652.  
  653. BEGIN
  654.     WITH Input^ DO
  655.         IF Input=INPUT THEN
  656.             WriteString(OUTPUT,Prompt);
  657.             Flush(OUTPUT);
  658.         END;
  659.  
  660.  
  661.  
  662.  
  663.  
  664.  (* here's where you add other platforms *)
  665.  
  666.         IF Count = 0 THEN
  667.             Info[0]:=ASCII.EOF;
  668.             INC(Count);
  669.         END;
  670.     END;
  671. END ReadInfo;
  672.  
  673.  
  674. (************************************************************************)
  675. (* Initialization for IO                                                *)
  676. (************************************************************************)
  677.  
  678. BEGIN
  679.  
  680.  
  681.  
  682.  
  683.     Window := 'CON:40/50/600/150/FIO';
  684.  
  685.     Files:=NIL;
  686.  
  687.  
  688.  
  689.  
  690.  
  691.  
  692.  
  693. (* insert compiler dependent stuff here *)
  694.  
  695.  
  696.  
  697.  
  698.     INPUT :=SYSTEM.ADR(InpBLK);
  699.     WITH INPUT^ DO;
  700.         IF WB THEN
  701.  
  702.  
  703.  
  704.  
  705.  
  706.  (* insert machine dependent stuff here *)
  707.  
  708.         ELSE
  709.  (* IMPLEMENTATION DEPENDENT *)
  710.  
  711.  
  712.  
  713.  
  714.  (* for other platforms *)
  715.  
  716.         END;
  717.         Next:=NIL;
  718.         Mode:=Read;
  719.         Count:=0;
  720.         CharsRead:=BufferSize+999;
  721.         Prompt:='> ';
  722.     END;
  723.  
  724.     OUTPUT:=SYSTEM.ADR(OutBLK);
  725.     WITH OUTPUT^ DO;
  726.         IF WB THEN
  727.             Handle:=INPUT^.Handle;
  728.         ELSE
  729.  (* IMPLEMENTATION DEPENDENT *)
  730.  
  731.  
  732.  
  733.  
  734.  (* for other platforms *)
  735.  
  736.         END;
  737.         Next:=NIL;
  738.         Mode:=Write;
  739.         Count:=0;
  740.         CharsRead:=BufferSize+999;
  741.     END;
  742. END FIO.
  743.