
(*********************************************************
*
*		Donated by Ray Penley, June 1980
*
********************************************************)


{*  PROGRAM TITLE:	EDIT A LINEAR FILE
**
**  WRITTEN BY:         W.M. Yarnall
**  DATE WRITTEN:       May 1980
**
**  WRITTEN FOR:	S100 Microsystems
**			May/June 1980
**
**  SUMMARY:
**		See the article in S100....
**
**  MODIFICATION RECORD:
**	25 May 1980	-Modified for Pascal/Z by Raymond E. Penley
**			-All files made local to Procedures.
**			 This insures that each file will be closed.
**
**
**		---NOTE---
**
** The first logical record in Pascal/Z is No. 1, NOT record
** No. 0 as in PASCAL/M or UCSD PASCAL. This can be rectified
** very eaisly by adding a 'bias' to every record number.
**		PASCAL/Z	bias = 1
**		PASCAL/M	bias = 0
**
*}
PROGRAM EDLINEAR;
CONST
  default = 80;	   (* Default length for strings *)
  FID_LENGTH = 14; (* MAXIMUM ALLOWED LENGTH FOR A FILE NAME *)
  bias   =  1;	   (* see comments above *)

TYPE
  FREC = RECORD
	   CASE tag:integer of
	    0:  (NAME :STRING 6; N1, N2 :integer);
	    1:  (HEADER :STRING 64);
	    2:  (RNAME :STRING 6; RINDEX :integer; RHS :real);
	    4:  (CNAME :STRING 6; CINDEX :integer; OBJ :real);
	    6:  (R,S :integer; T :real);
	   99:  () {--end of file--}
	 END;

  FID	    = STRING FID_LENGTH;
  LINEAR    = FILE OF FREC;
  STR0	    = STRING 0;
  STRING80  = STRING default;
  STR255    = STRING 255;

VAR
  OFIL,		(*---File Identifiers <FID>---*)
  NFIL	: FID;
  OBUFFER,	   {buffer for OLD file}
  NBUFFER	   {buffer for NEW file}
	: FREC;
  editing,	   {The state of editing the file}
  valid,	   {An answer must be valid to be accepted}
  valid_build,	   {All aspects of a "build" have been completed}
  XEOF		   {End_Of_File flag for a NON TEXT file}
	: boolean;
  bell,		   {console bell}
  Command	   {Command answer}
	: char;

PROCEDURE KEYIN(VAR X: char); EXTERNAL;
(* Direct keyboard entry of a single char *)

	(*----Required for Pascal/Z functions----*)
FUNCTION  LENGTH( X :STR255) :INTEGER; EXTERNAL;
PROCEDURE SETLENGTH(VAR X :STR0; Y :INTEGER); EXTERNAL;

Function INREC : integer;
{
GLOBAL
	valid_build : boolean }
LABEL	10;
VAR	Alfa : STRING 10;
	j :integer;
	valid : boolean;
begin
  Write(' Enter TAG .......... ');
  REPEAT
    READLN(j);
    valid := false;
    IF j>99 then
      begin
	j := 200;
	{exit} goto 10
      end;
    If  (j=0) or (j=1) or (j=2) or
	(j=4) or (j=6) or (j=99) then
      begin{If valid}
        valid := true;
	NBUFFER.tag := j ;
	WITH NBUFFER DO
	  CASE TAG OF
	  0:    begin
		SETLENGTH(NAME,0);
		write(' Program Name........ ');
		READLN(ALFA);
		If Length(ALFA)>6 then SETLENGTH(ALFA,6);
		APPEND(NAME,ALFA);
		write(' No. ROWS............ ');
		READLN(N1);
		write(' No. Columns......... ');
		READLN(N2)
		end;
	  1:    begin
		write(' Header.............. ');
		READLN(header)
		end;
	  2:    begin
		write(' ROW Name............ ');
		READLN(RNAME);
		write(' ROW No. ............ ');
		READLN(RINDEX);
		write(' RHS ................ ');
		READLN(RHS)
		end;
	  4:    begin
		write(' Column Name ........ ');
		READLN(CNAME);
		write(' Column No. ......... ');
		READLN(CINDEX);
		write(' OBJ ................ ');
		READLN(OBJ)
		end;
	  6:    begin
		write(' ROW NO. ............ ');
		READLN(R);
		write(' Column No. ......... ');
		READLN(S);
		write(' ABAR[R,S] .......... ');
		READLN(T)
		end;
	  99:   valid_build := true
	  End{With/CASE}
      end{If valid}
    Else
      Write('INVALID TAG, Reenter ---> ')
  UNTIL valid{TAG};
10: INREC := j
End{of INREC};

Procedure PRINT( This_one: FREC; Rcd: INTEGER);
begin
  writeln;
  writeln(' REC', Rcd:4, ' TAG:', This_one.tag:5);
  With This_one do
    CASE TAG of
	0:    begin
		writeln(' NAME: ', name);
		writeln(' No ROWS: ', N1);
		writeln(' No COLS: ', N2)
	      end;
	1:    begin
		writeln(' HEADING:');
		writeln(header)
	      end;
	2:    begin
		writeln(' ROW: ', RNAME);
		writeln(' INDEX: ', RINDEX);
		writeln(' RHS: ', RHS)
	      end;
	4:    begin
		writeln(' COL: ', CNAME);
		writeln(' INDEX: ', CINDEX);
		Writeln(' OBJ: ', OBJ)
	      end;
	6:	Writeln(' ABAR[', R:3, ',', S:3, ']: ', T);
	99:	Writeln(' --- End of File ---')
    End{of With/CASE};
  writeln
End{of PRINT};

PROCEDURE GETID( VAR ID: FID; Message: STRING80 );
{-Pascal/Z does not like file names that are
  not space filled to user specified length-}
CONST	SPACE = ' ';
begin
  SETLENGTH(ID,0);
  writeln;
  write(message);
  READLN(ID);
  While Length(ID) < FID_length Do APPEND(ID,SPACE)
end;

Procedure BUILD;
VAR	FX : LINEAR;
	 N : INTEGER;
begin
  GETID(NFIL,' Build what File? ');
  REWRITE(NFIL, FX);	  (*---REWRITE( <FID> , <FCB> )---*)
  valid_build := false;
  N := 0;
  While (N < 100) DO
    begin
	N := INREC;
	If (N<100) then
	   Write(FX, NBUFFER);
	If (N=99) AND valid_build then{finished}
	  N:=200
	Else
	  If (N>99) AND (not valid_build) then
	    begin
	    writeln('You MUST enter a TAG record of 99');
	    N := 0
	    end
    end{while}
End{of build};{ CLOSE(FX) }

Procedure LIST;
LABEL	2 {File not found};
VAR	REC : integer;
	fa  : LINEAR; (*---File descriptor <FCB>---*)
begin
  GETID(OFIL,' List what File? ');
  WRITELN;
  RESET(OFIL, fa);	 (*---RESET( <FID> , <FCB> )---*)
  If EOF(fa) then
    begin
    writeln(bell,'File ',OFIL,'not found');
    {exit}goto 2
    end;
  WRITELN;
  WRITE(' Starting at what record? ');
  READLN(REC);
  writeln;
  READ(fa:REC+BIAS, OBUFFER);
  XEOF := (OBUFFER.TAG=99);
  WHILE NOT XEOF do
    begin
      write( REC:5, ': ' );
      With OBUFFER do begin
	Write(TAG:3,' ');
	CASE TAG of
	  0:	Writeln(Name:8, N1:7, N2:7);
	  1:	Writeln(HEADER);
	  2:	Writeln(RNAME:8, RINDEX:7, RHS:14:8);
	  4:	Writeln(CNAME:8, CINDEX:7, OBJ:14:8);
	  6:	Writeln('ROW', R:3, ' COL', S:3, T:14:8)
	  End{of Case}
	End{With};
      REC := REC + 1;
      READ(fa:REC+BIAS,OBUFFER);
      XEOF := (OBUFFER.TAG=99);
    end{while};
2:	{file not found}
End{of LIST};{ CLOSE(fa) }

Procedure MODIFY;
LABEL	3 {File not found};
VAR	OLDF,		(*---File descriptors <FCB>---*)
	NEWF	: LINEAR;
	REC, j : integer;
	ans : char;
begin
  GETID(OFIL,' Modify what File? ');
  RESET(OFIL, OLDF);	 (*---RESET( <FID> , <FCB> )---*)
  If EOF(OLDF) then
    begin
    writeln(bell,'File ',OFIL,'not found');
    {exit}goto 3
    end;
  GETID(NFIL,' Name of New File? ');
  {--------------------------------------------------------
	WITH PASCAL/Z, THE ACT OF OPENING A NEW FILE
	USING THE SAME <FCB> CLOSES THE PREVIOUS FILE
	BEFORE OPENING THE NEW FILE.
   --------------------------------------------------------}
  REWRITE(NFIL,NEWF);	 (*---REWRITE( <FID> , <FCB> )---*)
  Write(' Starting at which Record? ');
  READLN(J);
  If J>0 then begin
	{Copy previous records from the old file
	 starting at the first record up to but not
	 including the requested record.}
      REC := 0;
      REPEAT
	READ(OLDF:REC+BIAS,OBUFFER); XEOF := (OBUFFER.TAG=99);
	WRITE(NEWF, OBUFFER);
	REC := REC + 1;
      UNTIL XEOF OR (REC = J);
    END;
  REC := J;
  READ(OLDF:REC+BIAS,OBUFFER);
  XEOF := (OBUFFER.TAG=99);
  While not XEOF do
    begin
    PRINT(OBUFFER,REC);
    writeln(' Process this Record?');
    REPEAT
      valid := true;
      write(' K(eep, C(hange, I(nsert, D(elete   >');
      KEYIN(ANS);WRITELN(ANS);
      CASE ans of
	'K','k': begin
		 write(NEWF,OBUFFER);
		 REC := REC + 1
		 end;
	'C','c': begin
		 If INREC<100 then write(NEWF, NBUFFER);
		 REC := REC + 1
		 end;
	'D','d': REC := REC + 1;
	'I','i': If INREC<100 then write(NEWF,NBUFFER);
	ELSE:    begin
		 write(BELL);
		 valid := false
		 end
      End{case};
    UNTIL VALID{ANSWER};
    READ(OLDF:REC+BIAS,OBUFFER);
    XEOF := (OBUFFER.TAG=99);
    End{while not XEOF};
{---Write the End_Of_File record to the New file---}
  Write(NEWF,OBUFFER);
3:	{file not found}
End{of MODIFY};{CLOSE(OLDF);CLOSE(NEWF)}

BEGIN (*---Main Program---*)
  BELL := CHR(7);
  editing := true;

  WHILE editing do
    begin{ EDIT session }
      REPEAT
	valid := true;
	writeln;
	write(' EDIT: L(ist, B(uild, M(odify, Q(uit ');
	KEYIN(Command);WRITELN(Command);
        CASE Command of
	  'L','l':	LIST;
	  'B','b':	BUILD;
	  'M','m':	MODIFY;
	  'Q','q':	editing := false
	  ELSE:    	begin
		 	write(BELL);
		 	valid := false
		 	end
        End{case}
    UNTIL valid{command}
    end{ EDIT session }
End{---of Edit Linear---}.
