MODULE C5P2;  (* Chapter 5  Problem 2 *)

  (* From the book "Modula-2  A Seafarer's Manual and Shipyard Guide" *)
  (* Page 161   adapted "Amiga M2Modula-2"   11 Mar 1988 *)

(* terminal input/ouput *)
FROM InOut IMPORT ReadCard,		(* read cardinal value *)
                  ReadString,		(* read string *)
                  WriteLn,		(* write cr/line feed *)
                  WriteString;		(* write string *)
                  
(* file input & output tools *)
FROM FileSystem IMPORT File,		(* file definition *)
                       Response,	(* includes 'done' *)
                       Lookup,		(* look up file on disk *)
                       SetPos,		(* set position *)
                       Close,		(* close *)
                       ReadChar,	(* read character *)
                       WriteChar;	(* write character *)
FROM ASCII IMPORT eol;
                                              
CONST
  LenCrDataIn = 35;	(* length of data per crew member in IN file,
                           includes line feed *)
  LenCrDataOut = 55;	(* length of data per crew member in OUT file,
                           includes line feed *)
  LenCrNum = 8;		(* length of crew mem number in file *)
  
VAR
  FL1,
  FL2 : File;				(* contains file definition &
                                           status info *)
  CrewNum : [1..100];			(* crew mem. number *)
  JobDes : ARRAY [0..25] OF CHAR;	(* job description *)
  Name : ARRAY [0..19] OF CHAR;		(* crew mem. name *)
  CharNum : ARRAY [0..7] OF CHAR;	(* crew mem. number as character *)
  i : CARDINAL;				(* loop counter *)
    
(* Initialize file *)
PROCEDURE InitFL (VAR FL : File;		(* file defin. *)
                  FLName : ARRAY OF CHAR);	(* file name *)
                  
  BEGIN
    Lookup (FL,				(* look up file on disk *)
            FLName,
            2048,			(* buffersize *)
            FALSE);
  END InitFL;


(* Read description from file for specified crew member *)
PROCEDURE ReadDes (VAR FL : File;		(* file defin. *)
                   CrNum : CARDINAL;		(* crew mem num *)
                   VAR Num : ARRAY OF CHAR;	(* crew mem num as char *)
                   VAR Des : ARRAY OF CHAR);	(* job des. *)

  VAR
    i : CARDINAL;			(* array index *)
    ch : CHAR;				(* holds character *)
    
  BEGIN					(* set file position *)
    SetPos (FL,				(* file *)
            (CrNum-1)*LenCrDataIn);	(* character position *)
    IF (FL.res = done) THEN		(* skip if error *)
      i := 0;
      REPEAT				(* read crewmem number as char *)
        ReadChar (FL,
                  ch);
        Num[i] := ch;
        INC (i);
      UNTIL ((i > CARDINAL (HIGH (Num))) OR (FL.res # done));
      i := 0;
      REPEAT				(* read description *)
        ReadChar (FL,			(* char by char *)
                  ch);
        Des[i] := ch;			(* abort if error *)
        INC (i);
      UNTIL ((i > CARDINAL (HIGH (Des))) OR (FL.res # done));
    END;   (* IF *)
  END ReadDes;
  

(* Update name on file for specified crew member *)
PROCEDURE UpdtFL (VAR FL : File;		(* file defin. *)
                  CrNum : CARDINAL;		(* crew mem num *)
                  Num : ARRAY OF CHAR;		(* crew mem num as char *)
                  CrName : ARRAY OF CHAR;	(* crew mem name *)
                  Des : ARRAY OF CHAR);		(* job des. *)

  VAR
    i : CARDINAL;			(* array index *)
    ch : CHAR;				(* holds character *)
    
  BEGIN
    SetPos (FL,				(* file *)
            ((CrNum-1)*LenCrDataOut));	(* character position *)
    IF (FL.res = done) THEN		(* skip if error *)
      i := 0;
      REPEAT				(* write description *)
        ch := Num[i];			(* char by char *)
        WriteChar (FL,
                   ch);
        INC (i);
      UNTIL ((i > CARDINAL (HIGH (Num))) OR (FL.res # done));
      i := 0;
      REPEAT				(* write description *)
        ch := CrName[i];		(* char by char *)
        WriteChar (FL,
                   ch);
        INC (i);
      UNTIL ((i > CARDINAL (HIGH (CrName))) OR (FL.res # done));
      i := 0;
      REPEAT				(* write description *)
        ch := Des[i];			(* char by char *)
        WriteChar (FL,
                   ch);
        INC (i);
      UNTIL ((i > CARDINAL (HIGH (Des))) OR (FL.res # done));
      WriteChar (FL, eol); 
    END;   (* IF *)
  END UpdtFL;
  

BEGIN   (* main body *)
  WriteLn;
  WriteString ("Start file update");
  
  InitFL (FL1,					    (* initialize first file *)
          "CREW1.TXT");				    (* drive/path/file name *)
  InitFL (FL2,					    (* initialize second file *)
          "CREW3.TXT");                             (* drive/path/file name *)
  IF ((FL1.res = done) AND (FL2.res = done)) THEN   (* error? *)
    i := 0;					    (* no *)
    LOOP
      INC (i);
      IF (i > 100) THEN
        EXIT;
      END;
      WriteLn;
      CrewNum := i;
      
      ReadDes (FL1,CrewNum,CharNum,JobDes);	(* read des. from file *)
      IF (FL1.res # done) THEN			(* error? *)
        EXIT;					(* yes *)
      END;   (* IF *)
      
      WriteLn; WriteLn;
      WriteString ("old job description of Crewmember");
      WriteLn;
      WriteString (CharNum);
      WriteString (": ");
      WriteString (JobDes);
      
      WriteLn;
      WriteString ("enter Crewmember name: ");
      ReadString (Name);
      
      UpdtFL (FL2,CrewNum,CharNum,Name,JobDes);	(* update name on file 2 *)
      IF (FL2.res # done) THEN			(* error? *)
        EXIT;					(* yes *)
      END;   (* IF *)
      
    END;   (* LOOP *)
    
  END;   (* IF done *)
  
  IF (FL1.res = done) THEN		(* error on file? *)
    Close (FL1);			(* no - close it *)
  END;
  
  IF (FL2.res = done) THEN		(* error on file? *)
    Close (FL2);			(* no - close it *)
  END;
  
  IF ((FL1.res # done) OR (FL2.res # done)) THEN
    WriteLn;				(* error encountered *)
    WriteString ("error encountered while accessing file");
  END;
  
  WriteLn;
  WriteString ("End file update");
  WriteLn;
  
END C5P2.
